--- linux-3.7/fs/xfs/xfs_dinode.h 2012-10-04 13:27:44.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_dinode.h 2012-12-11 15:56:32.000000000 +0000 @@ -51,7 +51,9 @@ typedef struct xfs_dinode { __be32 di_nlink; /* number of links to file */ __be16 di_projid_lo; /* lower part of owner's project id */ __be16 di_projid_hi; /* higher part owner's project id */ - __u8 di_pad[6]; /* unused, zeroed space */ + __u8 di_pad[2]; /* unused, zeroed space */ + __be16 di_tag; /* context tagging */ + __be16 di_vflags; /* vserver specific flags */ __be16 di_flushiter; /* incremented on flush */ xfs_timestamp_t di_atime; /* time last accessed */ xfs_timestamp_t di_mtime; /* time last modified */ @@ -184,6 +186,8 @@ static inline void xfs_dinode_put_rdev(s #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ #define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */ #define XFS_DIFLAG_FILESTREAM_BIT 14 /* use filestream allocator */ +#define XFS_DIFLAG_IXUNLINK_BIT 15 /* Immutable inver on unlink */ + #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) @@ -199,6 +203,7 @@ static inline void xfs_dinode_put_rdev(s #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) #define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT) #define XFS_DIFLAG_FILESTREAM (1 << XFS_DIFLAG_FILESTREAM_BIT) +#define XFS_DIFLAG_IXUNLINK (1 << XFS_DIFLAG_IXUNLINK_BIT) #ifdef CONFIG_XFS_RT #define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) @@ -211,6 +216,10 @@ static inline void xfs_dinode_put_rdev(s XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ - XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM) + XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM | \ + XFS_DIFLAG_IXUNLINK) + +#define XFS_DIVFLAG_BARRIER 0x01 +#define XFS_DIVFLAG_COW 0x02 #endif /* __XFS_DINODE_H__ */ --- linux-3.7/fs/xfs/xfs_fs.h 2011-10-24 16:45:31.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_fs.h 2012-12-11 15:56:32.000000000 +0000 @@ -67,6 +67,9 @@ struct fsxattr { #define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ #define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define XFS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ +#define XFS_XFLAG_IXUNLINK 0x00008000 /* immutable invert on unlink */ +#define XFS_XFLAG_BARRIER 0x10000000 /* chroot() barrier */ +#define XFS_XFLAG_COW 0x20000000 /* copy on write mark */ #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* @@ -302,7 +305,8 @@ typedef struct xfs_bstat { #define bs_projid bs_projid_lo /* (previously just bs_projid) */ __u16 bs_forkoff; /* inode fork offset in bytes */ __u16 bs_projid_hi; /* higher part of project id */ - unsigned char bs_pad[10]; /* pad space, unused */ + unsigned char bs_pad[8]; /* pad space, unused */ + __u16 bs_tag; /* context tagging */ __u32 bs_dmevmask; /* DMIG event mask */ __u16 bs_dmstate; /* DMIG state info */ __u16 bs_aextents; /* attribute number of extents */ --- linux-3.7/fs/xfs/xfs_ialloc.c 2012-12-11 15:47:37.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_ialloc.c 2012-12-11 15:56:32.000000000 +0000 @@ -37,7 +37,6 @@ #include "xfs_error.h" #include "xfs_bmap.h" - /* * Allocation group level functions. */ --- linux-3.7/fs/xfs/xfs_inode.c 2012-12-11 15:47:37.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_inode.c 2012-12-11 22:20:23.000000000 +0000 @@ -16,6 +16,7 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include +#include #include "xfs.h" #include "xfs_fs.h" @@ -563,15 +564,25 @@ xfs_iformat_btree( STATIC void xfs_dinode_from_disk( xfs_icdinode_t *to, - xfs_dinode_t *from) + xfs_dinode_t *from, + int tagged) { + uint32_t uid, gid, tag; + to->di_magic = be16_to_cpu(from->di_magic); to->di_mode = be16_to_cpu(from->di_mode); to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink = be16_to_cpu(from->di_onlink); - to->di_uid = be32_to_cpu(from->di_uid); - to->di_gid = be32_to_cpu(from->di_gid); + + uid = be32_to_cpu(from->di_uid); + gid = be32_to_cpu(from->di_gid); + tag = be16_to_cpu(from->di_tag); + + to->di_uid = INOTAG_UID(tagged, uid, gid); + to->di_gid = INOTAG_GID(tagged, uid, gid); + to->di_tag = INOTAG_TAG(tagged, uid, gid, tag); + to->di_nlink = be32_to_cpu(from->di_nlink); to->di_projid_lo = be16_to_cpu(from->di_projid_lo); to->di_projid_hi = be16_to_cpu(from->di_projid_hi); @@ -593,21 +604,26 @@ xfs_dinode_from_disk( to->di_dmevmask = be32_to_cpu(from->di_dmevmask); to->di_dmstate = be16_to_cpu(from->di_dmstate); to->di_flags = be16_to_cpu(from->di_flags); + to->di_vflags = be16_to_cpu(from->di_vflags); to->di_gen = be32_to_cpu(from->di_gen); } void xfs_dinode_to_disk( xfs_dinode_t *to, - xfs_icdinode_t *from) + xfs_icdinode_t *from, + int tagged) { to->di_magic = cpu_to_be16(from->di_magic); to->di_mode = cpu_to_be16(from->di_mode); to->di_version = from ->di_version; to->di_format = from->di_format; to->di_onlink = cpu_to_be16(from->di_onlink); - to->di_uid = cpu_to_be32(from->di_uid); - to->di_gid = cpu_to_be32(from->di_gid); + + to->di_uid = cpu_to_be32(TAGINO_UID(tagged, from->di_uid, from->di_tag)); + to->di_gid = cpu_to_be32(TAGINO_GID(tagged, from->di_gid, from->di_tag)); + to->di_tag = cpu_to_be16(TAGINO_TAG(tagged, from->di_tag)); + to->di_nlink = cpu_to_be32(from->di_nlink); to->di_projid_lo = cpu_to_be16(from->di_projid_lo); to->di_projid_hi = cpu_to_be16(from->di_projid_hi); @@ -629,12 +645,14 @@ xfs_dinode_to_disk( to->di_dmevmask = cpu_to_be32(from->di_dmevmask); to->di_dmstate = cpu_to_be16(from->di_dmstate); to->di_flags = cpu_to_be16(from->di_flags); + to->di_vflags = cpu_to_be16(from->di_vflags); to->di_gen = cpu_to_be32(from->di_gen); } STATIC uint _xfs_dic2xflags( - __uint16_t di_flags) + __uint16_t di_flags, + __uint16_t di_vflags) { uint flags = 0; @@ -645,6 +663,8 @@ _xfs_dic2xflags( flags |= XFS_XFLAG_PREALLOC; if (di_flags & XFS_DIFLAG_IMMUTABLE) flags |= XFS_XFLAG_IMMUTABLE; + if (di_flags & XFS_DIFLAG_IXUNLINK) + flags |= XFS_XFLAG_IXUNLINK; if (di_flags & XFS_DIFLAG_APPEND) flags |= XFS_XFLAG_APPEND; if (di_flags & XFS_DIFLAG_SYNC) @@ -669,6 +689,10 @@ _xfs_dic2xflags( flags |= XFS_XFLAG_FILESTREAM; } + if (di_vflags & XFS_DIVFLAG_BARRIER) + flags |= FS_BARRIER_FL; + if (di_vflags & XFS_DIVFLAG_COW) + flags |= FS_COW_FL; return flags; } @@ -678,7 +702,7 @@ xfs_ip2xflags( { xfs_icdinode_t *dic = &ip->i_d; - return _xfs_dic2xflags(dic->di_flags) | + return _xfs_dic2xflags(dic->di_flags, dic->di_vflags) | (XFS_IFORK_Q(ip) ? XFS_XFLAG_HASATTR : 0); } @@ -686,7 +710,8 @@ uint xfs_dic2xflags( xfs_dinode_t *dip) { - return _xfs_dic2xflags(be16_to_cpu(dip->di_flags)) | + return _xfs_dic2xflags(be16_to_cpu(dip->di_flags), + be16_to_cpu(dip->di_vflags)) | (XFS_DFORK_Q(dip) ? XFS_XFLAG_HASATTR : 0); } @@ -740,7 +765,8 @@ xfs_iread( * Otherwise, just get the truly permanent information. */ if (dip->di_mode) { - xfs_dinode_from_disk(&ip->i_d, dip); + xfs_dinode_from_disk(&ip->i_d, dip, + mp->m_flags & XFS_MOUNT_TAGGED); error = xfs_iformat(ip, dip); if (error) { #ifdef DEBUG @@ -927,6 +953,7 @@ xfs_ialloc( ASSERT(ip->i_d.di_nlink == nlink); ip->i_d.di_uid = current_fsuid(); ip->i_d.di_gid = current_fsgid(); + ip->i_d.di_tag = current_fstag(&ip->i_vnode); xfs_set_projid(ip, prid); memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); @@ -986,6 +1013,7 @@ xfs_ialloc( ip->i_d.di_dmevmask = 0; ip->i_d.di_dmstate = 0; ip->i_d.di_flags = 0; + ip->i_d.di_vflags = 0; flags = XFS_ILOG_CORE; switch (mode & S_IFMT) { case S_IFIFO: @@ -1668,6 +1696,7 @@ xfs_ifree( } ip->i_d.di_mode = 0; /* mark incore inode as free */ ip->i_d.di_flags = 0; + ip->i_d.di_vflags = 0; ip->i_d.di_dmevmask = 0; ip->i_d.di_forkoff = 0; /* mark the attr fork not in use */ ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; @@ -1834,7 +1863,6 @@ xfs_iroot_realloc( return; } - /* * This is called when the amount of space needed for if_data * is increased or decreased. The change in size is indicated by @@ -2522,7 +2550,8 @@ xfs_iflush_int( * because if the inode is dirty at all the core must * be. */ - xfs_dinode_to_disk(dip, &ip->i_d); + xfs_dinode_to_disk(dip, &ip->i_d, + mp->m_flags & XFS_MOUNT_TAGGED); /* Wrap, we never let the log put out DI_MAX_FLUSH */ if (ip->i_d.di_flushiter == DI_MAX_FLUSH) --- linux-3.7/fs/xfs/xfs_inode.h 2012-10-04 13:27:44.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_inode.h 2012-12-11 15:56:32.000000000 +0000 @@ -134,7 +134,9 @@ typedef struct xfs_icdinode { __uint32_t di_nlink; /* number of links to file */ __uint16_t di_projid_lo; /* lower part of owner's project id */ __uint16_t di_projid_hi; /* higher part of owner's project id */ - __uint8_t di_pad[6]; /* unused, zeroed space */ + __uint8_t di_pad[2]; /* unused, zeroed space */ + __uint16_t di_tag; /* context tagging */ + __uint16_t di_vflags; /* vserver specific flags */ __uint16_t di_flushiter; /* incremented on flush */ xfs_ictimestamp_t di_atime; /* time last accessed */ xfs_ictimestamp_t di_mtime; /* time last modified */ @@ -561,7 +563,7 @@ int xfs_imap_to_bp(struct xfs_mount *, int xfs_iread(struct xfs_mount *, struct xfs_trans *, struct xfs_inode *, uint); void xfs_dinode_to_disk(struct xfs_dinode *, - struct xfs_icdinode *); + struct xfs_icdinode *, int); void xfs_idestroy_fork(struct xfs_inode *, int); void xfs_idata_realloc(struct xfs_inode *, int, int); void xfs_iroot_realloc(struct xfs_inode *, int, int); --- linux-3.7/fs/xfs/xfs_ioctl.c 2012-12-11 15:47:37.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_ioctl.c 2012-12-11 15:56:32.000000000 +0000 @@ -26,7 +26,7 @@ #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_ioctl.h" +// #include "xfs_ioctl.h" #include "xfs_rtalloc.h" #include "xfs_itable.h" #include "xfs_error.h" @@ -762,6 +762,10 @@ xfs_merge_ioc_xflags( xflags |= XFS_XFLAG_IMMUTABLE; else xflags &= ~XFS_XFLAG_IMMUTABLE; + if (flags & FS_IXUNLINK_FL) + xflags |= XFS_XFLAG_IXUNLINK; + else + xflags &= ~XFS_XFLAG_IXUNLINK; if (flags & FS_APPEND_FL) xflags |= XFS_XFLAG_APPEND; else @@ -790,6 +794,8 @@ xfs_di2lxflags( if (di_flags & XFS_DIFLAG_IMMUTABLE) flags |= FS_IMMUTABLE_FL; + if (di_flags & XFS_DIFLAG_IXUNLINK) + flags |= FS_IXUNLINK_FL; if (di_flags & XFS_DIFLAG_APPEND) flags |= FS_APPEND_FL; if (di_flags & XFS_DIFLAG_SYNC) @@ -850,6 +856,8 @@ xfs_set_diflags( di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC); if (xflags & XFS_XFLAG_IMMUTABLE) di_flags |= XFS_DIFLAG_IMMUTABLE; + if (xflags & XFS_XFLAG_IXUNLINK) + di_flags |= XFS_DIFLAG_IXUNLINK; if (xflags & XFS_XFLAG_APPEND) di_flags |= XFS_DIFLAG_APPEND; if (xflags & XFS_XFLAG_SYNC) @@ -892,6 +900,10 @@ xfs_diflags_to_linux( inode->i_flags |= S_IMMUTABLE; else inode->i_flags &= ~S_IMMUTABLE; + if (xflags & XFS_XFLAG_IXUNLINK) + inode->i_flags |= S_IXUNLINK; + else + inode->i_flags &= ~S_IXUNLINK; if (xflags & XFS_XFLAG_APPEND) inode->i_flags |= S_APPEND; else @@ -1396,10 +1408,18 @@ xfs_file_ioctl( case XFS_IOC_FSGETXATTRA: return xfs_ioc_fsgetxattr(ip, 1, arg); case XFS_IOC_FSSETXATTR: + if (IS_BARRIER(inode)) { + vxwprintk_task(1, "messing with the barrier."); + return -XFS_ERROR(EACCES); + } return xfs_ioc_fssetxattr(ip, filp, arg); case XFS_IOC_GETXFLAGS: return xfs_ioc_getxflags(ip, arg); case XFS_IOC_SETXFLAGS: + if (IS_BARRIER(inode)) { + vxwprintk_task(1, "messing with the barrier."); + return -XFS_ERROR(EACCES); + } return xfs_ioc_setxflags(ip, filp, arg); case XFS_IOC_FSSETDM: { --- linux-3.7/fs/xfs/xfs_ioctl.h 2011-10-24 16:45:31.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_ioctl.h 2012-12-11 15:56:32.000000000 +0000 @@ -70,6 +70,12 @@ xfs_handle_to_dentry( void __user *uhandle, u32 hlen); +extern int +xfs_sync_flags( + struct inode *inode, + int flags, + int vflags); + extern long xfs_file_ioctl( struct file *filp, --- linux-3.7/fs/xfs/xfs_iops.c 2012-10-04 13:27:44.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_iops.c 2012-12-11 15:56:32.000000000 +0000 @@ -28,6 +28,7 @@ #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_ioctl.h" #include "xfs_bmap.h" #include "xfs_rtalloc.h" #include "xfs_error.h" @@ -46,6 +47,7 @@ #include #include #include +#include static int xfs_initxattrs( @@ -421,6 +423,7 @@ xfs_vn_getattr( stat->nlink = ip->i_d.di_nlink; stat->uid = ip->i_d.di_uid; stat->gid = ip->i_d.di_gid; + stat->tag = ip->i_d.di_tag; stat->ino = ip->i_ino; stat->atime = inode->i_atime; stat->mtime = inode->i_mtime; @@ -1033,6 +1036,7 @@ static const struct inode_operations xfs .listxattr = xfs_vn_listxattr, .fiemap = xfs_vn_fiemap, .update_time = xfs_vn_update_time, + .sync_flags = xfs_sync_flags, }; static const struct inode_operations xfs_dir_inode_operations = { @@ -1059,6 +1063,7 @@ static const struct inode_operations xfs .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, .update_time = xfs_vn_update_time, + .sync_flags = xfs_sync_flags, }; static const struct inode_operations xfs_dir_ci_inode_operations = { @@ -1110,6 +1115,10 @@ xfs_diflags_to_iflags( inode->i_flags |= S_IMMUTABLE; else inode->i_flags &= ~S_IMMUTABLE; + if (ip->i_d.di_flags & XFS_DIFLAG_IXUNLINK) + inode->i_flags |= S_IXUNLINK; + else + inode->i_flags &= ~S_IXUNLINK; if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) inode->i_flags |= S_APPEND; else @@ -1122,6 +1131,15 @@ xfs_diflags_to_iflags( inode->i_flags |= S_NOATIME; else inode->i_flags &= ~S_NOATIME; + + if (ip->i_d.di_vflags & XFS_DIVFLAG_BARRIER) + inode->i_vflags |= V_BARRIER; + else + inode->i_vflags &= ~V_BARRIER; + if (ip->i_d.di_vflags & XFS_DIVFLAG_COW) + inode->i_vflags |= V_COW; + else + inode->i_vflags &= ~V_COW; } /* @@ -1153,6 +1171,7 @@ xfs_setup_inode( set_nlink(inode, ip->i_d.di_nlink); inode->i_uid = ip->i_d.di_uid; inode->i_gid = ip->i_d.di_gid; + inode->i_tag = ip->i_d.di_tag; switch (inode->i_mode & S_IFMT) { case S_IFBLK: --- linux-3.7/fs/xfs/xfs_itable.c 2012-10-04 13:27:44.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_itable.c 2012-12-11 15:56:32.000000000 +0000 @@ -96,6 +96,7 @@ xfs_bulkstat_one_int( buf->bs_mode = dic->di_mode; buf->bs_uid = dic->di_uid; buf->bs_gid = dic->di_gid; + buf->bs_tag = dic->di_tag; buf->bs_size = dic->di_size; buf->bs_atime.tv_sec = dic->di_atime.t_sec; buf->bs_atime.tv_nsec = dic->di_atime.t_nsec; --- linux-3.7/fs/xfs/xfs_linux.h 2011-10-24 16:45:31.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_linux.h 2012-12-11 15:56:32.000000000 +0000 @@ -121,6 +121,7 @@ #define current_cpu() (raw_smp_processor_id()) #define current_pid() (current->pid) +#define current_fstag(vp) (dx_current_fstag((vp)->i_sb)) #define current_test_flags(f) (current->flags & (f)) #define current_set_flags_nested(sp, f) \ (*(sp) = current->flags, current->flags |= (f)) --- linux-3.7/fs/xfs/xfs_log_recover.c 2012-12-11 15:47:37.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_log_recover.c 2012-12-11 15:56:32.000000000 +0000 @@ -2359,7 +2359,8 @@ xlog_recover_inode_pass2( } /* The core is in in-core format */ - xfs_dinode_to_disk(dip, item->ri_buf[1].i_addr); + xfs_dinode_to_disk(dip, item->ri_buf[1].i_addr, + mp->m_flags & XFS_MOUNT_TAGGED); /* the rest is in on-disk format */ if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { --- linux-3.7/fs/xfs/xfs_mount.h 2012-12-11 15:47:37.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_mount.h 2012-12-11 15:56:32.000000000 +0000 @@ -246,6 +246,7 @@ typedef struct xfs_mount { allocator */ #define XFS_MOUNT_NOATTR2 (1ULL << 25) /* disable use of attr2 format */ +#define XFS_MOUNT_TAGGED (1ULL << 31) /* context tagging */ /* * Default minimum read and write sizes. --- linux-3.7/fs/xfs/xfs_super.c 2012-12-11 15:47:37.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_super.c 2012-12-11 17:36:47.000000000 +0000 @@ -114,6 +114,9 @@ mempool_t *xfs_ioend_pool; #define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed logging disabled */ #define MNTOPT_DISCARD "discard" /* Discard unused blocks */ #define MNTOPT_NODISCARD "nodiscard" /* Do not discard unused blocks */ +#define MNTOPT_TAGXID "tagxid" /* context tagging for inodes */ +#define MNTOPT_TAGGED "tag" /* context tagging for inodes */ +#define MNTOPT_NOTAGTAG "notag" /* do not use context tagging */ /* * Table driven mount option parser. @@ -126,6 +129,8 @@ enum { Opt_nobarrier, Opt_inode64, Opt_inode32, + Opt_tag, + Opt_notag, Opt_err }; @@ -134,6 +139,9 @@ static const match_table_t tokens = { {Opt_nobarrier, "nobarrier"}, {Opt_inode64, "inode64"}, {Opt_inode32, "inode32"}, + {Opt_tag, "tagxid"}, + {Opt_tag, "tag"}, + {Opt_notag, "notag"}, {Opt_err, NULL} }; @@ -383,6 +391,19 @@ xfs_parseargs( } else if (!strcmp(this_char, "irixsgid")) { xfs_warn(mp, "irixsgid is now a sysctl(2) variable, option is deprecated."); +#ifndef CONFIG_TAGGING_NONE + } else if (!strcmp(this_char, MNTOPT_TAGGED)) { + mp->m_flags |= XFS_MOUNT_TAGGED; + } else if (!strcmp(this_char, MNTOPT_NOTAGTAG)) { + mp->m_flags &= ~XFS_MOUNT_TAGGED; + } else if (!strcmp(this_char, MNTOPT_TAGXID)) { + mp->m_flags |= XFS_MOUNT_TAGGED; +#endif +#ifdef CONFIG_PROPAGATE + } else if (!strcmp(this_char, MNTOPT_TAGGED)) { + /* use value */ + mp->m_flags |= XFS_MOUNT_TAGGED; +#endif } else { xfs_warn(mp, "unknown mount option [%s].", this_char); return EINVAL; @@ -1149,6 +1170,16 @@ xfs_fs_remount( case Opt_inode32: mp->m_maxagi = xfs_set_inode32(mp); break; + case Opt_tag: + if (!(sb->s_flags & MS_TAGGED)) { + printk(KERN_INFO + "XFS: %s: tagging not permitted on remount.\n", + sb->s_id); + return -EINVAL; + } + break; + case Opt_notag: + break; default: /* * Logically we would return an error here to prevent @@ -1368,6 +1399,9 @@ xfs_fs_fill_super( if (error) goto out_free_sb; + if (mp->m_flags & XFS_MOUNT_TAGGED) + sb->s_flags |= MS_TAGGED; + /* * we must configure the block size in the superblock before we run the * full mount process as the mount process can lookup and cache inodes. --- linux-3.7/fs/xfs/xfs_vnodeops.c 2012-10-04 13:27:44.000000000 +0000 +++ linux-3.7-vs2.3.5.1/fs/xfs/xfs_vnodeops.c 2012-12-11 15:56:32.000000000 +0000 @@ -103,6 +103,77 @@ xfs_readlink_bmap( return error; } + +STATIC void +xfs_get_inode_flags( + xfs_inode_t *ip) +{ + struct inode *inode = VFS_I(ip); + unsigned int flags = inode->i_flags; + unsigned int vflags = inode->i_vflags; + + if (flags & S_IMMUTABLE) + ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE; + else + ip->i_d.di_flags &= ~XFS_DIFLAG_IMMUTABLE; + if (flags & S_IXUNLINK) + ip->i_d.di_flags |= XFS_DIFLAG_IXUNLINK; + else + ip->i_d.di_flags &= ~XFS_DIFLAG_IXUNLINK; + + if (vflags & V_BARRIER) + ip->i_d.di_vflags |= XFS_DIVFLAG_BARRIER; + else + ip->i_d.di_vflags &= ~XFS_DIVFLAG_BARRIER; + if (vflags & V_COW) + ip->i_d.di_vflags |= XFS_DIVFLAG_COW; + else + ip->i_d.di_vflags &= ~XFS_DIVFLAG_COW; +} + +int +xfs_sync_flags( + struct inode *inode, + int flags, + int vflags) +{ + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + unsigned int lock_flags = 0; + int code; + + tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); + code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); + if (code) + goto error_out; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + inode->i_flags = flags; + inode->i_vflags = vflags; + xfs_get_inode_flags(ip); + + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + + XFS_STATS_INC(xs_ig_attrchg); + + if (mp->m_flags & XFS_MOUNT_WSYNC) + xfs_trans_set_sync(tp); + code = xfs_trans_commit(tp, 0); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return code; + +error_out: + xfs_trans_cancel(tp, 0); + if (lock_flags) + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return code; +} + + int xfs_readlink( xfs_inode_t *ip,