Whamcloud - gitweb
tune2fs: Add support for orphan_file feature
authorJan Kara <jack@suse.cz>
Wed, 25 Aug 2021 22:11:33 +0000 (00:11 +0200)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 1 Oct 2021 01:59:09 +0000 (21:59 -0400)
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/tune2fs.8.in
misc/tune2fs.c

index 979f6c5..1e026e5 100644 (file)
@@ -257,6 +257,11 @@ program.
 This superblock setting is only honored in 2.6.35+ kernels;
 and not at all by the ext2 and ext3 file system drivers.
 .TP
+.BI orphan_file_size= size
+Set size of the file for tracking unlinked but still open inodes and inodes
+with truncate in progress. Larger file allows for better scalability, reserving
+a few blocks per cpu is ideal.
+.TP
 .B force_fsck
 Set a flag in the file system superblock indicating that errors have been found.
 This will force fsck to run at the next mount.
index 7f023ad..71a8e99 100644 (file)
@@ -106,6 +106,7 @@ int enabling_casefold;
 int journal_size, journal_fc_size, journal_flags;
 char *journal_device;
 static blk64_t journal_location = ~0LL;
+static e2_blkcnt_t orphan_file_blocks;
 
 static struct list_head blk_move_list;
 
@@ -152,7 +153,8 @@ static __u32 ok_features[3] = {
        EXT3_FEATURE_COMPAT_HAS_JOURNAL |
                EXT2_FEATURE_COMPAT_DIR_INDEX |
                EXT4_FEATURE_COMPAT_FAST_COMMIT |
-               EXT4_FEATURE_COMPAT_STABLE_INODES,
+               EXT4_FEATURE_COMPAT_STABLE_INODES |
+               EXT4_FEATURE_COMPAT_ORPHAN_FILE,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE |
                EXT3_FEATURE_INCOMPAT_EXTENTS |
@@ -183,7 +185,8 @@ static __u32 clear_ok_features[3] = {
        EXT3_FEATURE_COMPAT_HAS_JOURNAL |
                EXT2_FEATURE_COMPAT_RESIZE_INODE |
                EXT2_FEATURE_COMPAT_DIR_INDEX |
-               EXT4_FEATURE_COMPAT_FAST_COMMIT,
+               EXT4_FEATURE_COMPAT_FAST_COMMIT |
+               EXT4_FEATURE_COMPAT_ORPHAN_FILE,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE |
                EXT4_FEATURE_INCOMPAT_FLEX_BG |
@@ -1145,6 +1148,56 @@ static int update_feature_set(ext2_filsys fs, char *features)
                }
        }
 
+       if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_ORPHAN_FILE)) {
+               ext2_ino_t ino;
+
+               if (mount_flags & EXT2_MF_MOUNTED) {
+                       fputs(_("The orphan_file feature may only be cleared "
+                               "when the filesystem is unmounted.\n"), stderr);
+                       return 1;
+               }
+               if (ext2fs_has_feature_orphan_present(sb) && f_flag < 2) {
+                       fputs(_("The orphan_present feature is set. Please "
+                               "run e2fsck before clearing orphan_file "
+                               "feature.\n"),
+                             stderr);
+                       return 1;
+               }
+               err = ext2fs_read_bitmaps(fs);
+               if (err) {
+                       com_err(program_name, err, "%s",
+                               _("while loading bitmaps"));
+                       return 1;
+               }
+               err = ext2fs_truncate_orphan_file(fs);
+               if (err) {
+                       com_err(program_name, err,
+                               _("\n\twhile trying to delete orphan file\n"));
+                       return 1;
+               }
+               ino = sb->s_orphan_file_inum;
+               sb->s_orphan_file_inum = 0;
+               ext2fs_inode_alloc_stats2(fs, ino, -1, 0);
+               ext2fs_clear_feature_orphan_file(sb);
+               ext2fs_clear_feature_orphan_present(sb);
+               ext2fs_mark_super_dirty(fs);
+       }
+
+       if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_ORPHAN_FILE)) {
+               if (!ext2fs_has_feature_journal(sb)) {
+                       fputs(_("orphan_file feature can be set only for "
+                               "filesystems with journal.\n"), stderr);
+                       return 1;
+               }
+               /*
+                * If adding an orphan file, let the create orphan file
+                * code below handle setting the flag and creating it.
+                * We supply a default size if necessary.
+                */
+               orphan_file_blocks = ext2fs_default_orphan_file_blocks(fs);
+               ext2fs_set_feature_orphan_file(sb);
+       }
+
        if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
                EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
                if (ext2fs_has_feature_meta_bg(sb)) {
@@ -2269,6 +2322,21 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
                                continue;
                        }
                        encoding_flags = arg;
+               } else if (!strcmp(token, "orphan_file_size")) {
+                       if (!arg) {
+                               r_usage++;
+                               continue;
+                       }
+                       orphan_file_blocks = parse_num_blocks2(arg,
+                                                fs->super->s_log_block_size);
+
+                       if (orphan_file_blocks < 1) {
+                               fprintf(stderr,
+                                       _("Invalid size of orphan file %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
                } else
                        r_usage++;
        }
@@ -3254,6 +3322,24 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
                if (rc)
                        goto closefs;
        }
+       if (orphan_file_blocks) {
+               errcode_t err;
+
+               err = ext2fs_read_bitmaps(fs);
+               if (err) {
+                       com_err(program_name, err, "%s",
+                               _("while loading bitmaps"));
+                       rc = 1;
+                       goto closefs;
+               }
+               err = ext2fs_create_orphan_file(fs, orphan_file_blocks);
+               if (err) {
+                       com_err(program_name, err, "%s",
+                               _("while creating orphan file"));
+                       rc = 1;
+                       goto closefs;
+               }
+       }
 
        if (Q_flag) {
                if (mount_flags & EXT2_MF_MOUNTED) {