summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authoryangerkun2019-02-11 06:35:06 +0100
committerGreg Kroah-Hartman2019-03-23 20:10:02 +0100
commita0d876c77705c1dd2df2d89e040bf570755cd676 (patch)
treed650133ed166ba1e5d49d2c82f526dac59ea87b1 /fs/ext4
parentext4: update quota information while swapping boot loader inode (diff)
downloadkernel-qcow2-linux-a0d876c77705c1dd2df2d89e040bf570755cd676.tar.gz
kernel-qcow2-linux-a0d876c77705c1dd2df2d89e040bf570755cd676.tar.xz
kernel-qcow2-linux-a0d876c77705c1dd2df2d89e040bf570755cd676.zip
ext4: add mask of ext4 flags to swap
commit abdc644e8cbac2e9b19763680e5a7cf9bab2bee7 upstream. The reason is that while swapping two inode, we swap the flags too. Some flags such as EXT4_JOURNAL_DATA_FL can really confuse the things since we're not resetting the address operations structure. The simplest way to keep things sane is to restrict the flags that can be swapped. Signed-off-by: yangerkun <yangerkun@huawei.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/ioctl.c6
2 files changed, 8 insertions, 1 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 032cf9b92665..2ddf7833350d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -435,6 +435,9 @@ struct flex_groups {
/* Flags that are appropriate for non-directories/regular files. */
#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL)
+/* The only flags that should be swapped */
+#define EXT4_FL_SHOULD_SWAP (EXT4_HUGE_FILE_FL | EXT4_EXTENTS_FL)
+
/* Mask out flags that are inappropriate for the given type of inode. */
static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
{
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index eff68358fae7..2e76fb55d94a 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -63,6 +63,7 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
loff_t isize;
struct ext4_inode_info *ei1;
struct ext4_inode_info *ei2;
+ unsigned long tmp;
ei1 = EXT4_I(inode1);
ei2 = EXT4_I(inode2);
@@ -72,7 +73,10 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
swap(inode1->i_mtime, inode2->i_mtime);
memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
- swap(ei1->i_flags, ei2->i_flags);
+ tmp = ei1->i_flags & EXT4_FL_SHOULD_SWAP;
+ ei1->i_flags = (ei2->i_flags & EXT4_FL_SHOULD_SWAP) |
+ (ei1->i_flags & ~EXT4_FL_SHOULD_SWAP);
+ ei2->i_flags = tmp | (ei2->i_flags & ~EXT4_FL_SHOULD_SWAP);
swap(ei1->i_disksize, ei2->i_disksize);
ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);