f2fs: compress: fix to avoid redundant compress extension
authorChao Yu <chao@kernel.org>
Mon, 28 Aug 2023 14:04:17 +0000 (22:04 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:52:09 +0000 (11:52 +0100)
[ Upstream commit 7e1b150fece033703a824df1bbc03df091ea53cc ]

With below script, redundant compress extension will be parsed and added
by parse_options(), because parse_options() doesn't check whether the
extension is existed or not, fix it.

1. mount -t f2fs -o compress_extension=so /dev/vdb /mnt/f2fs
2. mount -t f2fs -o remount,compress_extension=so /mnt/f2fs
3. mount|grep f2fs

/dev/vdb on /mnt/f2fs type f2fs (...,compress_extension=so,compress_extension=so,...)

Fixes: 4c8ff7095bef ("f2fs: support data compression")
Fixes: 151b1982be5d ("f2fs: compress: add nocompress extensions support")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/f2fs/super.c

index 2046f63..1ba85ef 100644 (file)
@@ -548,6 +548,29 @@ static int f2fs_set_test_dummy_encryption(struct super_block *sb,
 }
 
 #ifdef CONFIG_F2FS_FS_COMPRESSION
+static bool is_compress_extension_exist(struct f2fs_sb_info *sbi,
+                                       const char *new_ext, bool is_ext)
+{
+       unsigned char (*ext)[F2FS_EXTENSION_LEN];
+       int ext_cnt;
+       int i;
+
+       if (is_ext) {
+               ext = F2FS_OPTION(sbi).extensions;
+               ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt;
+       } else {
+               ext = F2FS_OPTION(sbi).noextensions;
+               ext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt;
+       }
+
+       for (i = 0; i < ext_cnt; i++) {
+               if (!strcasecmp(new_ext, ext[i]))
+                       return true;
+       }
+
+       return false;
+}
+
 /*
  * 1. The same extension name cannot not appear in both compress and non-compress extension
  * at the same time.
@@ -1145,6 +1168,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
                                return -EINVAL;
                        }
 
+                       if (is_compress_extension_exist(sbi, name, true)) {
+                               kfree(name);
+                               break;
+                       }
+
                        strcpy(ext[ext_cnt], name);
                        F2FS_OPTION(sbi).compress_ext_cnt++;
                        kfree(name);
@@ -1169,6 +1197,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
                                return -EINVAL;
                        }
 
+                       if (is_compress_extension_exist(sbi, name, false)) {
+                               kfree(name);
+                               break;
+                       }
+
                        strcpy(noext[noext_cnt], name);
                        F2FS_OPTION(sbi).nocompress_ext_cnt++;
                        kfree(name);