]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
tune2fs: allow disabling casefold feature
authorSlava Bacherikov <slava@bacher09.org>
Fri, 8 Jul 2022 12:26:58 +0000 (15:26 +0300)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 13 Aug 2022 02:38:35 +0000 (22:38 -0400)
Casefold can be safely disabled if there are no directories with +F
attribute ( EXT4_CASEFOLD_FL ). This checks all inodes for that flag and in
case there isn't any, it disables casefold FS feature. When FS has
directories with +F attributes, user could convert these directories,
probably by mounting FS and executing some script or by doing it
manually. Afterwards, it would be possible to disable casefold FS flag
via tune2fs.

Link: https://lore.kernel.org/r/20220708122658.17907-1-slava@bacher09.org
Signed-off-by: Slava Bacherikov <slava@bacher09.org>
Reviewed-by: Gabriel Krisman Bertazi <krisman@collabora.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/tune2fs.8.in
misc/tune2fs.c

index 628dcdc03383fe5c3949d221e2d1f1bd0707cc64..dcf108c1f026cf3fc375fcced02c2ecfa1e22337 100644 (file)
@@ -593,8 +593,10 @@ Enable the file system to be larger than 2^32 blocks.
 .TP
 .B casefold
 Enable support for file system level casefolding.
-.B Tune2fs
-currently only supports setting this file system feature.
+The option can be cleared only if filesystem has no
+directories with
+.B F
+attribute.
 .TP
 .B dir_index
 Use hashed b-trees to speed up lookups for large directories.
index 50bba9903e07c59a9ed4121e5fd29ffd4d046f52..eca77a5a372b61bdcd77723a29ed2f6a4fc1ce0d 100644 (file)
@@ -205,7 +205,8 @@ static __u32 clear_ok_features[3] = {
                EXT4_FEATURE_INCOMPAT_FLEX_BG |
                EXT4_FEATURE_INCOMPAT_MMP |
                EXT4_FEATURE_INCOMPAT_64BIT |
-               EXT4_FEATURE_INCOMPAT_CSUM_SEED,
+               EXT4_FEATURE_INCOMPAT_CSUM_SEED |
+               EXT4_FEATURE_INCOMPAT_CASEFOLD,
        /* R/O compat */
        EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
                EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -1021,6 +1022,41 @@ out:
        return retval;
 }
 
+static int has_casefold_inode(ext2_filsys fs)
+{
+       int length = EXT2_INODE_SIZE(fs->super);
+       struct ext2_inode *inode = NULL;
+       ext2_inode_scan scan;
+       errcode_t       retval;
+       ext2_ino_t      ino;
+       int found_casefold = 0;
+
+       retval = ext2fs_get_mem(length, &inode);
+       if (retval)
+               fatal_err(retval, "while allocating memory");
+
+       retval = ext2fs_open_inode_scan(fs, 0, &scan);
+       if (retval)
+               fatal_err(retval, "while opening inode scan");
+
+       do {
+               retval = ext2fs_get_next_inode_full(scan, &ino, inode, length);
+               if (retval)
+                       fatal_err(retval, "while getting next inode");
+               if (!ino)
+                       break;
+
+               if(inode->i_flags & EXT4_CASEFOLD_FL) {
+                       found_casefold = 1;
+                       break;
+               }
+       } while(1);
+
+       ext2fs_free_mem(&inode);
+       ext2fs_close_inode_scan(scan);
+       return found_casefold;
+}
+
 static errcode_t disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
 {
        struct ext2_group_desc *gd;
@@ -1555,6 +1591,22 @@ mmp_error:
                enabling_casefold = 1;
        }
 
+       if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CASEFOLD)) {
+               if (mount_flags & EXT2_MF_MOUNTED) {
+                       fputs(_("The casefold feature may only be disabled when "
+                               "the filesystem is unmounted.\n"), stderr);
+                       return 1;
+               }
+               if (has_casefold_inode(fs)) {
+                       fputs(_("The casefold feature can't be cleared when "
+                                       "there are inodes with +F flag.\n"), stderr);
+                       return 1;
+               }
+               fs->super->s_encoding = 0;
+               fs->super->s_encoding_flags = 0;
+               enabling_casefold = 0;
+       }
+
        if (FEATURE_ON(E2P_FEATURE_INCOMPAT,
                EXT4_FEATURE_INCOMPAT_CSUM_SEED)) {
                if (!ext2fs_has_feature_metadata_csum(sb)) {