diff options
author | Jan Kara <jack@suse.cz> | 2007-05-08 00:30:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 11:15:12 -0700 |
commit | 28be5abb400e5e082f5225105fdc69337ec0c0b4 (patch) | |
tree | e4bb3e527aac316004be68e28a25b2919e30afd4 /fs | |
parent | 9926e4c74300c4b31dee007298c6475d33369df0 (diff) |
ext3: copy i_flags to inode flags on write
A patch that stores inode flags such as S_IMMUTABLE, S_APPEND, etc. from
i_flags to EXT3_I(inode)->i_flags when inode is written to disk. The same
thing is done on GETFLAGS ioctl.
Quota code changes these flags on quota files (to make it harder for
sysadmin to screw himself) and these changes were not correctly propagated
into the filesystem (especially, lsattr did not show them and users were
wondering...).
Propagate flags such as S_APPEND, S_IMMUTABLE, etc. from i_flags into
ext3-specific i_flags. Hence, when someone sets these flags via a
different interface than ioctl, they are stored correctly.
Signed-off-by: Jan Kara <jack@suse.cz>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext3/inode.c | 20 | ||||
-rw-r--r-- | fs/ext3/ioctl.c | 1 |
2 files changed, 21 insertions, 0 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index f9bcddbd2ef..e1bb0317198 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2580,6 +2580,25 @@ void ext3_set_inode_flags(struct inode *inode) inode->i_flags |= S_DIRSYNC; } +/* Propagate flags from i_flags to EXT3_I(inode)->i_flags */ +void ext3_get_inode_flags(struct ext3_inode_info *ei) +{ + unsigned int flags = ei->vfs_inode.i_flags; + + ei->i_flags &= ~(EXT3_SYNC_FL|EXT3_APPEND_FL| + EXT3_IMMUTABLE_FL|EXT3_NOATIME_FL|EXT3_DIRSYNC_FL); + if (flags & S_SYNC) + ei->i_flags |= EXT3_SYNC_FL; + if (flags & S_APPEND) + ei->i_flags |= EXT3_APPEND_FL; + if (flags & S_IMMUTABLE) + ei->i_flags |= EXT3_IMMUTABLE_FL; + if (flags & S_NOATIME) + ei->i_flags |= EXT3_NOATIME_FL; + if (flags & S_DIRSYNC) + ei->i_flags |= EXT3_DIRSYNC_FL; +} + void ext3_read_inode(struct inode * inode) { struct ext3_iloc iloc; @@ -2735,6 +2754,7 @@ static int ext3_do_update_inode(handle_t *handle, if (ei->i_state & EXT3_STATE_NEW) memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size); + ext3_get_inode_flags(ei); raw_inode->i_mode = cpu_to_le16(inode->i_mode); if(!(test_opt(inode->i_sb, NO_UID32))) { raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 9b8090d94e6..965006dba6b 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -28,6 +28,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, switch (cmd) { case EXT3_IOC_GETFLAGS: + ext3_get_inode_flags(ei); flags = ei->i_flags & EXT3_FL_USER_VISIBLE; return put_user(flags, (int __user *) arg); case EXT3_IOC_SETFLAGS: { |