Index: linux-2.6.14/fs/ext2/file.c =================================================================== --- linux-2.6.14.orig/fs/ext2/file.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/ext2/file.c 2005-11-02 10:22:15.000000000 -0600 @@ -80,4 +80,5 @@ #endif .setattr = ext2_setattr, .permission = ext2_permission, + .sync_flags = ext2_sync_inode_flags, }; Index: linux-2.6.14/fs/ext2/inode.c =================================================================== --- linux-2.6.14.orig/fs/ext2/inode.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/ext2/inode.c 2005-11-02 11:55:09.000000000 -0600 @@ -1073,6 +1073,38 @@ inode->i_flags |= S_DIRSYNC; } +int ext2_sync_inode_flags(struct inode *inode) +{ + unsigned int oldflags, newflags; + + oldflags = EXT2_I(inode)->i_flags; + newflags = oldflags & + ~(EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL | EXT2_BARRIER_FL | + EXT2_SYNC_FL | EXT2_APPEND_FL | EXT2_NOATIME_FL | + EXT2_DIRSYNC_FL); + if (inode->i_flags & S_IMMUTABLE) + newflags |= EXT2_IMMUTABLE_FL; + if (inode->i_flags & S_IUNLINK) + newflags |= EXT2_IUNLINK_FL; + if (inode->i_flags & S_BARRIER) + newflags |= EXT2_BARRIER_FL; + if (inode->i_flags & S_SYNC) + newflags |= EXT2_SYNC_FL; + if (inode->i_flags & S_APPEND) + newflags |= EXT2_APPEND_FL; + if (inode->i_flags & S_NOATIME) + newflags |= EXT2_NOATIME_FL; + if (inode->i_flags & S_DIRSYNC) + newflags |= EXT2_DIRSYNC_FL; + + if (oldflags ^ newflags) { + EXT2_I(inode)->i_flags = newflags; + inode->i_ctime = CURRENT_TIME; + } + + return 0; +} + void ext2_read_inode (struct inode * inode) { struct ext2_inode_info *ei = EXT2_I(inode); @@ -1315,26 +1347,6 @@ return sync_inode(inode, &wbc); } -static void ext2_setattr_flags(struct inode *inode) -{ - unsigned int oldflags, newflags; - - oldflags = EXT2_I(inode)->i_flags; - newflags = oldflags & - ~(EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL | EXT2_BARRIER_FL); - if (IS_IMMUTABLE(inode)) - newflags |= EXT2_IMMUTABLE_FL; - if (IS_IUNLINK(inode)) - newflags |= EXT2_IUNLINK_FL; - if (IS_BARRIER(inode)) - newflags |= EXT2_BARRIER_FL; - - if (oldflags ^ newflags) { - EXT2_I(inode)->i_flags = newflags; - inode->i_ctime = CURRENT_TIME; - } -} - int ext2_setattr(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; @@ -1351,8 +1363,6 @@ return error; } - if (iattr->ia_valid & ATTR_ATTR_FLAG) - ext2_setattr_flags(inode); error = inode_setattr(inode, iattr); if (!error && (iattr->ia_valid & ATTR_MODE)) error = ext2_acl_chmod(inode); Index: linux-2.6.14/fs/ext2/namei.c =================================================================== --- linux-2.6.14.orig/fs/ext2/namei.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/ext2/namei.c 2005-11-02 10:23:50.000000000 -0600 @@ -412,6 +412,7 @@ #endif .setattr = ext2_setattr, .permission = ext2_permission, + .sync_flags = ext2_sync_inode_flags, }; struct inode_operations ext2_special_inode_operations = { @@ -423,4 +424,5 @@ #endif .setattr = ext2_setattr, .permission = ext2_permission, + .sync_flags = ext2_sync_inode_flags, }; Index: linux-2.6.14/fs/ext2/symlink.c =================================================================== --- linux-2.6.14.orig/fs/ext2/symlink.c 2005-10-27 19:02:08.000000000 -0500 +++ linux-2.6.14/fs/ext2/symlink.c 2005-11-02 10:24:07.000000000 -0600 @@ -38,6 +38,7 @@ .listxattr = ext2_listxattr, .removexattr = generic_removexattr, #endif + .sync_flags = ext2_sync_inode_flags, }; struct inode_operations ext2_fast_symlink_inode_operations = { @@ -49,4 +50,5 @@ .listxattr = ext2_listxattr, .removexattr = generic_removexattr, #endif + .sync_flags = ext2_sync_inode_flags, }; Index: linux-2.6.14/include/linux/fs.h =================================================================== --- linux-2.6.14.orig/include/linux/fs.h 2005-11-02 10:21:24.000000000 -0600 +++ linux-2.6.14/include/linux/fs.h 2005-11-02 13:00:49.000000000 -0600 @@ -1015,6 +1015,7 @@ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); + int (*sync_flags) (struct inode *); }; struct seq_file; Index: linux-2.6.14/kernel/vserver/inode.c =================================================================== --- linux-2.6.14.orig/kernel/vserver/inode.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/kernel/vserver/inode.c 2005-11-02 13:01:32.000000000 -0600 @@ -161,7 +161,6 @@ } if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) { - attr.ia_valid |= ATTR_ATTR_FLAG; if (*mask & IATTR_IMMUTABLE) { if (*flags & IATTR_IMMUTABLE) in->i_flags |= S_IMMUTABLE; @@ -180,6 +179,11 @@ else in->i_flags &= ~S_BARRIER; } + if (in->i_op && in->i_op->sync_flags) { + error = in->i_op->sync_flags(in); + if (error) + goto out; + } } if (attr.ia_valid) { @@ -192,8 +196,9 @@ } } +out: up(&in->i_sem); - return 0; + return error; } int vc_set_iattr(uint32_t id, void __user *data) Index: linux-2.6.14/fs/ext3/file.c =================================================================== --- linux-2.6.14.orig/fs/ext3/file.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/ext3/file.c 2005-11-02 10:38:36.000000000 -0600 @@ -132,5 +132,6 @@ .removexattr = generic_removexattr, #endif .permission = ext3_permission, + .sync_flags = ext3_sync_inode_flags, }; Index: linux-2.6.14/fs/ext3/namei.c =================================================================== --- linux-2.6.14.orig/fs/ext3/namei.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/ext3/namei.c 2005-11-02 10:39:10.000000000 -0600 @@ -2375,6 +2375,7 @@ .removexattr = generic_removexattr, #endif .permission = ext3_permission, + .sync_flags = ext3_sync_inode_flags, }; struct inode_operations ext3_special_inode_operations = { @@ -2386,4 +2387,5 @@ .removexattr = generic_removexattr, #endif .permission = ext3_permission, + .sync_flags = ext3_sync_inode_flags, }; Index: linux-2.6.14/fs/ext3/symlink.c =================================================================== --- linux-2.6.14.orig/fs/ext3/symlink.c 2005-10-27 19:02:08.000000000 -0500 +++ linux-2.6.14/fs/ext3/symlink.c 2005-11-02 10:38:54.000000000 -0600 @@ -40,6 +40,7 @@ .listxattr = ext3_listxattr, .removexattr = generic_removexattr, #endif + .sync_flags = ext3_sync_inode_flags, }; struct inode_operations ext3_fast_symlink_inode_operations = { @@ -51,4 +52,5 @@ .listxattr = ext3_listxattr, .removexattr = generic_removexattr, #endif + .sync_flags = ext3_sync_inode_flags, }; Index: linux-2.6.14/fs/ext3/inode.c =================================================================== --- linux-2.6.14.orig/fs/ext3/inode.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/ext3/inode.c 2005-11-02 11:54:51.000000000 -0600 @@ -2756,20 +2756,31 @@ return ext3_force_commit(inode->i_sb); } -static int ext3_setattr_flags(struct inode *inode) +int ext3_sync_inode_flags(struct inode *inode) { unsigned int oldflags, newflags; int err = 0; oldflags = EXT3_I(inode)->i_flags; newflags = oldflags & - ~(EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL | EXT3_BARRIER_FL); - if (IS_IMMUTABLE(inode)) + ~(EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL | EXT3_BARRIER_FL | + EXT3_SYNC_FL | EXT3_APPEND_FL | EXT3_NOATIME_FL | + EXT3_DIRSYNC_FL); + + if (inode->i_flags & S_IMMUTABLE) newflags |= EXT3_IMMUTABLE_FL; - if (IS_IUNLINK(inode)) + if (inode->i_flags & S_IUNLINK) newflags |= EXT3_IUNLINK_FL; - if (IS_BARRIER(inode)) + if (inode->i_flags & S_BARRIER) newflags |= EXT3_BARRIER_FL; + if (inode->i_flags & S_SYNC) + newflags |= EXT3_SYNC_FL; + if (inode->i_flags & S_APPEND) + newflags |= EXT3_APPEND_FL; + if (inode->i_flags & S_NOATIME) + newflags |= EXT3_NOATIME_FL; + if (inode->i_flags & S_DIRSYNC) + newflags |= EXT3_DIRSYNC_FL; if (oldflags ^ newflags) { handle_t *handle; @@ -2869,12 +2880,6 @@ ext3_journal_stop(handle); } - if (ia_valid & ATTR_ATTR_FLAG) { - rc = ext3_setattr_flags(inode); - if (!error) - error = rc; - } - rc = inode_setattr(inode, attr); /* If inode_setattr's call to ext3_truncate failed to get a Index: linux-2.6.14/fs/reiserfs/file.c =================================================================== --- linux-2.6.14.orig/fs/reiserfs/file.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/reiserfs/file.c 2005-11-02 10:47:19.000000000 -0600 @@ -1568,4 +1568,5 @@ .listxattr = reiserfs_listxattr, .removexattr = reiserfs_removexattr, .permission = reiserfs_permission, + .sync_flags = reiserfs_sync_inode_flags, }; Index: linux-2.6.14/fs/reiserfs/inode.c =================================================================== --- linux-2.6.14.orig/fs/reiserfs/inode.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/reiserfs/inode.c 2005-11-02 12:59:58.000000000 -0600 @@ -2921,24 +2921,30 @@ reiserfs_get_blocks_direct_io, NULL); } -static void reiserfs_setattr_flags(struct inode *inode) +/* + * Serge: Hmm, this approach will set these flags in the inode if the + * superblock has them set. I think that's the wrong thing to do... + */ +int reiserfs_sync_inode_flags(struct inode *inode) { unsigned int oldflags, newflags; + reiserfs_write_lock(inode->i_sb); oldflags = REISERFS_I(inode)->i_flags; newflags = oldflags & ~(REISERFS_IMMUTABLE_FL | - REISERFS_IUNLINK_FL | REISERFS_BARRIER_FL); - if (IS_IMMUTABLE(inode)) - newflags |= REISERFS_IMMUTABLE_FL; - if (IS_IUNLINK(inode)) - newflags |= REISERFS_IUNLINK_FL; - if (IS_BARRIER(inode)) - newflags |= REISERFS_BARRIER_FL; + REISERFS_IUNLINK_FL | REISERFS_BARRIER_FL | + REISERFS_SYNC_FL | REISERFS_NOATIME_FL | + REISERFS_NOTAIL_FL); + i_attrs_to_sd_attrs(inode, (__u16 *)&newflags); if (oldflags ^ newflags) { REISERFS_I(inode)->i_flags = newflags; inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); } + reiserfs_write_unlock(inode->i_sb); + + return 0; } int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) @@ -2986,9 +2992,6 @@ error = inode_change_ok(inode, attr); - if (!error && attr->ia_valid & ATTR_ATTR_FLAG) - reiserfs_setattr_flags(inode); - if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid) || Index: linux-2.6.14/fs/reiserfs/namei.c =================================================================== --- linux-2.6.14.orig/fs/reiserfs/namei.c 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/fs/reiserfs/namei.c 2005-11-02 10:47:43.000000000 -0600 @@ -1553,6 +1553,7 @@ .listxattr = reiserfs_listxattr, .removexattr = reiserfs_removexattr, .permission = reiserfs_permission, + .sync_flags = reiserfs_sync_inode_flags, }; /* @@ -1569,6 +1570,7 @@ .listxattr = reiserfs_listxattr, .removexattr = reiserfs_removexattr, .permission = reiserfs_permission, + .sync_flags = reiserfs_sync_inode_flags, }; @@ -1582,5 +1584,6 @@ .listxattr = reiserfs_listxattr, .removexattr = reiserfs_removexattr, .permission = reiserfs_permission, + .sync_flags = reiserfs_sync_inode_flags, }; Index: linux-2.6.14/fs/xfs/linux-2.6/xfs_iops.c =================================================================== --- linux-2.6.14.orig/fs/xfs/linux-2.6/xfs_iops.c 2005-10-31 11:09:53.000000000 -0600 +++ linux-2.6.14/fs/xfs/linux-2.6/xfs_iops.c 2005-11-02 13:41:45.000000000 -0600 @@ -472,25 +472,38 @@ return 0; } -STATIC void -linvfs_setattr_flags( - struct inode *inode, - vattr_t *vap) +STATIC int +linvfs_sync_ino_flags(struct inode *inode) { unsigned int oldflags, newflags; + vattr_t vattr; + int flags = 0; + int error; + vnode_t *vp = LINVFS_GET_VP(inode); + + memset(&vattr, 0, sizeof(vattr_t)); - oldflags = vap->va_xflags; + vattr.va_mask = XFS_AT_XFLAGS; + VOP_GETATTR(vp, &vattr, 0, NULL, error); + if (error) + return error; + oldflags = vattr.va_xflags; newflags = oldflags & ~(XFS_XFLAG_IMMUTABLE | XFS_XFLAG_IUNLINK | XFS_XFLAG_BARRIER); - if (IS_IMMUTABLE(inode)) + if (inode->i_flags & S_IMMUTABLE) newflags |= XFS_XFLAG_IMMUTABLE; - if (IS_IUNLINK(inode)) + if (inode->i_flags & S_IUNLINK) newflags |= XFS_XFLAG_IUNLINK; - if (IS_BARRIER(inode)) + if (inode->i_flags & S_BARRIER) newflags |= XFS_XFLAG_BARRIER; - if (oldflags ^ newflags) - vap->va_xflags = newflags; + if (oldflags ^ newflags) { + vattr.va_xflags = newflags; + vattr.va_mask |= XFS_AT_XFLAGS; + VOP_SETATTR(vp, &vattr, flags, NULL, error); + } + vn_revalidate(vp); + return error; } STATIC int @@ -552,11 +565,6 @@ flags |= ATTR_NONBLOCK; #endif - if (ia_valid & ATTR_ATTR_FLAG) { - vattr.va_mask |= XFS_AT_XFLAGS; - linvfs_setattr_flags(inode, &vattr); - } - VOP_SETATTR(vp, &vattr, flags, NULL, error); if (error) return -error; @@ -684,6 +692,7 @@ .getxattr = linvfs_getxattr, .listxattr = linvfs_listxattr, .removexattr = linvfs_removexattr, + .sync_flags = linvfs_sync_ino_flags, }; struct inode_operations linvfs_dir_inode_operations = { @@ -703,6 +712,7 @@ .getxattr = linvfs_getxattr, .listxattr = linvfs_listxattr, .removexattr = linvfs_removexattr, + .sync_flags = linvfs_sync_ino_flags, }; struct inode_operations linvfs_symlink_inode_operations = { @@ -716,4 +726,5 @@ .getxattr = linvfs_getxattr, .listxattr = linvfs_listxattr, .removexattr = linvfs_removexattr, + .sync_flags = linvfs_sync_ino_flags, }; Index: linux-2.6.14/fs/ext2/ext2.h =================================================================== --- linux-2.6.14.orig/fs/ext2/ext2.h 2005-10-27 19:02:08.000000000 -0500 +++ linux-2.6.14/fs/ext2/ext2.h 2005-11-02 11:40:04.000000000 -0600 @@ -162,6 +162,7 @@ extern struct address_space_operations ext2_aops; extern struct address_space_operations ext2_aops_xip; extern struct address_space_operations ext2_nobh_aops; +extern int ext2_sync_inode_flags(struct inode *inode); /* namei.c */ extern struct inode_operations ext2_dir_inode_operations; Index: linux-2.6.14/include/linux/ext3_fs.h =================================================================== --- linux-2.6.14.orig/include/linux/ext3_fs.h 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/include/linux/ext3_fs.h 2005-11-02 11:42:39.000000000 -0600 @@ -787,6 +787,7 @@ extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); +extern int ext3_sync_inode_flags(struct inode *inode); extern void ext3_read_inode (struct inode *); extern int ext3_write_inode (struct inode *, int); Index: linux-2.6.14/include/linux/reiserfs_fs.h =================================================================== --- linux-2.6.14.orig/include/linux/reiserfs_fs.h 2005-10-31 11:05:45.000000000 -0600 +++ linux-2.6.14/include/linux/reiserfs_fs.h 2005-11-02 12:05:38.000000000 -0600 @@ -1916,6 +1916,7 @@ void sd_attrs_to_i_attrs(__u16 sd_attrs, struct inode *inode); void i_attrs_to_sd_attrs(struct inode *inode, __u16 * sd_attrs); int reiserfs_setattr(struct dentry *dentry, struct iattr *attr); +int reiserfs_sync_inode_flags(struct inode *inode); /* namei.c */ void set_de_name_and_namelen(struct reiserfs_dir_entry *de);