f2fs: fix to remove F2FS_COMPR_FL and tag F2FS_NOCOMP_FL at the same time
authorChao Liu <liuchao@coolpad.com>
Mon, 25 Jul 2022 10:16:33 +0000 (18:16 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:24:13 +0000 (14:24 +0200)
[ Upstream commit 8ee236dcaa690d09ca612622e8bc8d09c302021d ]

If the inode has the compress flag, it will fail to use
'chattr -c +m' to remove its compress flag and tag no compress flag.
However, the same command will be successful when executed again,
as shown below:

  $ touch foo.txt
  $ chattr +c foo.txt
  $ chattr -c +m foo.txt
  chattr: Invalid argument while setting flags on foo.txt
  $ chattr -c +m foo.txt
  $ f2fs_io getflags foo.txt
  get a flag on foo.txt ret=0, flags=nocompression,inline_data

Fix this by removing some checks in f2fs_setflags_common()
that do not affect the original logic. I go through all the
possible scenarios, and the results are as follows. Bold is
the only thing that has changed.

+---------------+-----------+-----------+----------+
|               |            file flags            |
+ command       +-----------+-----------+----------+
|               | no flag   | compr     | nocompr  |
+---------------+-----------+-----------+----------+
| chattr +c     | compr     | compr     | -EINVAL  |
| chattr -c     | no flag   | no flag   | nocompr  |
| chattr +m     | nocompr   | -EINVAL   | nocompr  |
| chattr -m     | no flag   | compr     | no flag  |
| chattr +c +m  | -EINVAL   | -EINVAL   | -EINVAL  |
| chattr +c -m  | compr     | compr     | compr    |
| chattr -c +m  | nocompr   | *nocompr* | nocompr  |
| chattr -c -m  | no flag   | no flag   | no flag  |
+---------------+-----------+-----------+----------+

Link: https://lore.kernel.org/linux-f2fs-devel/20220621064833.1079383-1-chaoliu719@gmail.com/
Fixes: 4c8ff7095bef ("f2fs: support data compression")
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Chao Liu <liuchao@coolpad.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/f2fs/file.c

index bfcafc20eadab8bb0f3b8ae659c17610b8939bd1..eacc80ac160fbde7ba149b9308be9ebb8633aa34 100644 (file)
@@ -1869,10 +1869,7 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
                if (masked_flags & F2FS_COMPR_FL) {
                        if (!f2fs_disable_compressed_file(inode))
                                return -EINVAL;
-               }
-               if (iflags & F2FS_NOCOMP_FL)
-                       return -EINVAL;
-               if (iflags & F2FS_COMPR_FL) {
+               } else {
                        if (!f2fs_may_compress(inode))
                                return -EINVAL;
                        if (S_ISREG(inode->i_mode) && inode->i_size)
@@ -1881,10 +1878,6 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
                        set_compress_context(inode);
                }
        }
-       if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) {
-               if (masked_flags & F2FS_COMPR_FL)
-                       return -EINVAL;
-       }
 
        fi->i_flags = iflags | (fi->i_flags & ~mask);
        f2fs_bug_on(F2FS_I_SB(inode), (fi->i_flags & F2FS_COMPR_FL) &&