diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-06-05 13:07:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-06-05 13:07:25 -0400 |
commit | 78b36558b7061430fe16ce49f83f1bc3a0b7d4b8 (patch) | |
tree | 6f6a8ee8658187b41aba19a9656c6caadee24f2b | |
parent | 6c5de280b6683d194ee60cf22dee56eef0b09619 (diff) | |
parent | 84a8dce2710cc425089a2b92acc354d4fbb5788d (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: Fix remaining racy updates of EXT4_I(inode)->i_flags
ext4: Make sure the MOVE_EXT ioctl can't overwrite append-only files
-rw-r--r-- | fs/ext4/inode.c | 40 | ||||
-rw-r--r-- | fs/ext4/move_extent.c | 3 |
2 files changed, 26 insertions, 17 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 19df61c321fd..42272d67955a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4942,20 +4942,26 @@ void ext4_set_inode_flags(struct inode *inode) | |||
4942 | /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ | 4942 | /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ |
4943 | void ext4_get_inode_flags(struct ext4_inode_info *ei) | 4943 | void ext4_get_inode_flags(struct ext4_inode_info *ei) |
4944 | { | 4944 | { |
4945 | unsigned int flags = ei->vfs_inode.i_flags; | 4945 | unsigned int vfs_fl; |
4946 | 4946 | unsigned long old_fl, new_fl; | |
4947 | ei->i_flags &= ~(EXT4_SYNC_FL|EXT4_APPEND_FL| | 4947 | |
4948 | EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|EXT4_DIRSYNC_FL); | 4948 | do { |
4949 | if (flags & S_SYNC) | 4949 | vfs_fl = ei->vfs_inode.i_flags; |
4950 | ei->i_flags |= EXT4_SYNC_FL; | 4950 | old_fl = ei->i_flags; |
4951 | if (flags & S_APPEND) | 4951 | new_fl = old_fl & ~(EXT4_SYNC_FL|EXT4_APPEND_FL| |
4952 | ei->i_flags |= EXT4_APPEND_FL; | 4952 | EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL| |
4953 | if (flags & S_IMMUTABLE) | 4953 | EXT4_DIRSYNC_FL); |
4954 | ei->i_flags |= EXT4_IMMUTABLE_FL; | 4954 | if (vfs_fl & S_SYNC) |
4955 | if (flags & S_NOATIME) | 4955 | new_fl |= EXT4_SYNC_FL; |
4956 | ei->i_flags |= EXT4_NOATIME_FL; | 4956 | if (vfs_fl & S_APPEND) |
4957 | if (flags & S_DIRSYNC) | 4957 | new_fl |= EXT4_APPEND_FL; |
4958 | ei->i_flags |= EXT4_DIRSYNC_FL; | 4958 | if (vfs_fl & S_IMMUTABLE) |
4959 | new_fl |= EXT4_IMMUTABLE_FL; | ||
4960 | if (vfs_fl & S_NOATIME) | ||
4961 | new_fl |= EXT4_NOATIME_FL; | ||
4962 | if (vfs_fl & S_DIRSYNC) | ||
4963 | new_fl |= EXT4_DIRSYNC_FL; | ||
4964 | } while (cmpxchg(&ei->i_flags, old_fl, new_fl) != old_fl); | ||
4959 | } | 4965 | } |
4960 | 4966 | ||
4961 | static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | 4967 | static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, |
@@ -5191,7 +5197,7 @@ static int ext4_inode_blocks_set(handle_t *handle, | |||
5191 | */ | 5197 | */ |
5192 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); | 5198 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); |
5193 | raw_inode->i_blocks_high = 0; | 5199 | raw_inode->i_blocks_high = 0; |
5194 | ei->i_flags &= ~EXT4_HUGE_FILE_FL; | 5200 | ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); |
5195 | return 0; | 5201 | return 0; |
5196 | } | 5202 | } |
5197 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) | 5203 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) |
@@ -5204,9 +5210,9 @@ static int ext4_inode_blocks_set(handle_t *handle, | |||
5204 | */ | 5210 | */ |
5205 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); | 5211 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); |
5206 | raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); | 5212 | raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); |
5207 | ei->i_flags &= ~EXT4_HUGE_FILE_FL; | 5213 | ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); |
5208 | } else { | 5214 | } else { |
5209 | ei->i_flags |= EXT4_HUGE_FILE_FL; | 5215 | ext4_set_inode_flag(inode, EXT4_INODE_HUGE_FILE); |
5210 | /* i_block is stored in file system block size */ | 5216 | /* i_block is stored in file system block size */ |
5211 | i_blocks = i_blocks >> (inode->i_blkbits - 9); | 5217 | i_blocks = i_blocks >> (inode->i_blkbits - 9); |
5212 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); | 5218 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 3a6c92ac131c..52abfa12762a 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -960,6 +960,9 @@ mext_check_arguments(struct inode *orig_inode, | |||
960 | return -EINVAL; | 960 | return -EINVAL; |
961 | } | 961 | } |
962 | 962 | ||
963 | if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode)) | ||
964 | return -EPERM; | ||
965 | |||
963 | /* Ext4 move extent does not support swapfile */ | 966 | /* Ext4 move extent does not support swapfile */ |
964 | if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { | 967 | if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { |
965 | ext4_debug("ext4 move extent: The argument files should " | 968 | ext4_debug("ext4 move extent: The argument files should " |