Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+25 -16
+22 -16
fs/ext4/inode.c
··· 4942 4942 /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ 4943 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 + unsigned long old_fl, new_fl; 4946 4947 4947 - ei->i_flags &= ~(EXT4_SYNC_FL|EXT4_APPEND_FL| 4948 - EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|EXT4_DIRSYNC_FL); 4949 - if (flags & S_SYNC) 4950 - ei->i_flags |= EXT4_SYNC_FL; 4951 - if (flags & S_APPEND) 4952 - ei->i_flags |= EXT4_APPEND_FL; 4953 - if (flags & S_IMMUTABLE) 4954 - ei->i_flags |= EXT4_IMMUTABLE_FL; 4955 - if (flags & S_NOATIME) 4956 - ei->i_flags |= EXT4_NOATIME_FL; 4957 - if (flags & S_DIRSYNC) 4958 - ei->i_flags |= EXT4_DIRSYNC_FL; 4948 + do { 4949 + vfs_fl = ei->vfs_inode.i_flags; 4950 + old_fl = ei->i_flags; 4951 + new_fl = old_fl & ~(EXT4_SYNC_FL|EXT4_APPEND_FL| 4952 + EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL| 4953 + EXT4_DIRSYNC_FL); 4954 + if (vfs_fl & S_SYNC) 4955 + new_fl |= EXT4_SYNC_FL; 4956 + if (vfs_fl & S_APPEND) 4957 + new_fl |= EXT4_APPEND_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 4967 static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, ··· 5197 5191 */ 5198 5192 raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); 5199 5193 raw_inode->i_blocks_high = 0; 5200 - ei->i_flags &= ~EXT4_HUGE_FILE_FL; 5194 + ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); 5201 5195 return 0; 5202 5196 } 5203 5197 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) ··· 5210 5204 */ 5211 5205 raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); 5212 5206 raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); 5213 - ei->i_flags &= ~EXT4_HUGE_FILE_FL; 5207 + ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); 5214 5208 } else { 5215 - ei->i_flags |= EXT4_HUGE_FILE_FL; 5209 + ext4_set_inode_flag(inode, EXT4_INODE_HUGE_FILE); 5216 5210 /* i_block is stored in file system block size */ 5217 5211 i_blocks = i_blocks >> (inode->i_blkbits - 9); 5218 5212 raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
+3
fs/ext4/move_extent.c
··· 960 960 return -EINVAL; 961 961 } 962 962 963 + if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode)) 964 + return -EPERM; 965 + 963 966 /* Ext4 move extent does not support swapfile */ 964 967 if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { 965 968 ext4_debug("ext4 move extent: The argument files should "