]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blobdiff - misc/tune2fs.c
tune2fs: prevent enabling encryption flag on encoding-aware fs
[thirdparty/e2fsprogs.git] / misc / tune2fs.c
index ecba2ea5112dd8cce7bf398685035199f1dd982b..fbdf78a8f849d130a1e1625eca86b52e87620668 100644 (file)
@@ -137,9 +137,8 @@ static void usage(void)
                  "[-g group]\n"
                  "\t[-i interval[d|m|w]] [-j] [-J journal_options] [-l]\n"
                  "\t[-m reserved_blocks_percent] [-o [^]mount_options[,...]]\n"
-                 "\t[-p mmp_update_interval] [-r reserved_blocks_count] "
-                 "[-u user]\n"
-                 "\t[-C mount_count] [-L volume_label] [-M last_mounted_dir]\n"
+                 "\t[-r reserved_blocks_count] [-u user] [-C mount_count]\n"
+                 "\t[-L volume_label] [-M last_mounted_dir]\n"
                  "\t[-O [^]feature[,...]] [-Q quota_options]\n"
                  "\t[-E extended-option[,...]] [-T last_check_time] "
                  "[-U UUID]\n\t[-I new_inode_size] [-z undo_file] device\n"),
@@ -171,7 +170,8 @@ static __u32 ok_features[3] = {
                EXT4_FEATURE_RO_COMPAT_QUOTA |
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM |
                EXT4_FEATURE_RO_COMPAT_READONLY |
-               EXT4_FEATURE_RO_COMPAT_PROJECT
+               EXT4_FEATURE_RO_COMPAT_PROJECT |
+               EXT4_FEATURE_RO_COMPAT_VERITY
 };
 
 static __u32 clear_ok_features[3] = {
@@ -292,6 +292,12 @@ static int remove_journal_device(ext2_filsys fs)
        jsb = (journal_superblock_t *) buf;
        /* Find the filesystem UUID */
        nr_users = ntohl(jsb->s_nr_users);
+       if (nr_users > JFS_USERS_MAX) {
+               fprintf(stderr, _("Journal superblock is corrupted, nr_users\n"
+                                "is too high (%d).\n"), nr_users);
+               commit_remove_journal = 1;
+               goto no_valid_journal;
+       }
 
        if (!journal_user(fs->super->s_uuid, jsb->s_users, nr_users)) {
                fputs(_("Filesystem's UUID not found on journal device.\n"),
@@ -467,9 +473,6 @@ static void request_fsck_afterwards(ext2_filsys fs)
 
 static void convert_64bit(ext2_filsys fs, int direction)
 {
-       if (!direction)
-               return;
-
        /*
         * Is resize2fs going to demand a fsck run? Might as well tell the
         * user now.
@@ -494,64 +497,6 @@ static void convert_64bit(ext2_filsys fs, int direction)
                fprintf(stderr, _("' to disable 64-bit mode.\n"));
 }
 
-/* Rewrite extents */
-static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino,
-                                struct ext2_inode *inode)
-{
-       ext2_extent_handle_t    handle;
-       struct ext2fs_extent    extent;
-       errcode_t               errcode;
-       struct ext2_extent_info info;
-
-       if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
-           !ext2fs_has_feature_metadata_csum(fs->super))
-               return 0;
-
-       errcode = ext2fs_extent_open(fs, ino, &handle);
-       if (errcode)
-               return errcode;
-
-       errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
-       if (errcode)
-               goto out;
-
-       do {
-               errcode = ext2fs_extent_get_info(handle, &info);
-               if (errcode)
-                       break;
-
-               /*
-                * If this is the first extent in an extent block that we
-                * haven't visited, rewrite the extent to force the ETB
-                * checksum to be rewritten.
-                */
-               if (info.curr_entry == 1 && info.curr_level != 0 &&
-                   !(extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)) {
-                       errcode = ext2fs_extent_replace(handle, 0, &extent);
-                       if (errcode)
-                               break;
-               }
-
-               /* Skip to the end of a block of leaf nodes */
-               if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
-                       errcode = ext2fs_extent_get(handle,
-                                                   EXT2_EXTENT_LAST_SIB,
-                                                   &extent);
-                       if (errcode)
-                               break;
-               }
-
-               errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent);
-       } while (errcode == 0);
-
-out:
-       /* Ok if we run off the end */
-       if (errcode == EXT2_ET_EXTENT_NO_NEXT)
-               errcode = 0;
-       ext2fs_extent_free(handle);
-       return errcode;
-}
-
 /*
  * Rewrite directory blocks with checksums
  */
@@ -757,7 +702,8 @@ static void update_ea_inode_hash(struct rewrite_context *ctx, ext2_ino_t ino,
        if (retval)
                fatal_err(retval, "close ea_inode");
 
-       hash = ext2fs_crc32c_le(ctx->fs->csum_seed, ctx->ea_buf, inode->i_size);
+       hash = ext2fs_crc32c_le(ctx->fs->csum_seed,
+                               (unsigned char *) ctx->ea_buf, inode->i_size);
        ext2fs_set_ea_inode_hash(inode, hash);
 }
 
@@ -806,7 +752,7 @@ static void update_inline_xattr_hashes(struct rewrite_context *ctx,
 }
 
 static void update_block_xattr_hashes(struct rewrite_context *ctx,
-                                     void *block_buf)
+                                     char *block_buf)
 {
        struct ext2_ext_attr_header *header;
        struct ext2_ext_attr_entry *start, *end;
@@ -845,7 +791,7 @@ static void rewrite_one_inode(struct rewrite_context *ctx, ext2_ino_t ino,
        if (retval)
                fatal_err(retval, "while writing inode");
 
-       retval = rewrite_extents(ctx->fs, ino, inode);
+       retval = ext2fs_fix_extents_checksums(ctx->fs, ino, inode);
        if (retval)
                fatal_err(retval, "while rewriting extents");
 
@@ -1455,6 +1401,12 @@ mmp_error:
        }
 
        if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
+               if (ext2fs_has_feature_fname_encoding(sb)) {
+                       fputs(_("Cannot enable encrypt feature on filesystems "
+                               "with the encoding feature enabled.\n"),
+                             stderr);
+                       return 1;
+               }
                fs->super->s_encrypt_algos[0] =
                        EXT4_ENCRYPTION_MODE_AES_256_XTS;
                fs->super->s_encrypt_algos[1] =
@@ -1480,16 +1432,18 @@ mmp_error:
 
                uuid_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
                                        sizeof(fs->super->s_uuid));
-               if (fs->super->s_checksum_seed != uuid_seed &&
-                   (mount_flags & EXT2_MF_MOUNTED)) {
-                       fputs(_("UUID has changed since enabling "
-                               "metadata_csum.  Filesystem must be unmounted "
-                               "\nto safely rewrite all metadata to "
-                               "match the new UUID.\n"), stderr);
-                       return 1;
+               if (fs->super->s_checksum_seed != uuid_seed) {
+                       if (mount_flags & (EXT2_MF_BUSY|EXT2_MF_MOUNTED)) {
+                               fputs(_("UUID has changed since enabling "
+               "metadata_csum.  Filesystem must be unmounted "
+               "\nto safely rewrite all metadata to match the new UUID.\n"),
+                                     stderr);
+                               return 1;
+                       }
+                       check_fsck_needed(fs, _("Recalculating checksums "
+                                               "could take some time."));
+                       rewrite_checksums = 1;
                }
-
-               rewrite_checksums = 1;
        }
 
        if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
@@ -2119,6 +2073,10 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
                               intv);
                        fs->super->s_mmp_update_interval = intv;
                        ext2fs_mark_super_dirty(fs);
+               } else if (!strcmp(token, "force_fsck")) {
+                       fs->super->s_state |= EXT2_ERROR_FS;
+                       printf(_("Setting filesystem error flag to force fsck.\n"));
+                       ext2fs_mark_super_dirty(fs);
                } else if (!strcmp(token, "test_fs")) {
                        fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
                        printf("Setting test filesystem flag\n");
@@ -2198,8 +2156,10 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
                        "\tclear_mmp\n"
                        "\thash_alg=<hash algorithm>\n"
                        "\tmount_opts=<extended default mount options>\n"
+                       "\tmmp_update_interval=<mmp update interval in seconds>\n"
                        "\tstride=<RAID per-disk chunk size in blocks>\n"
                        "\tstripe_width=<RAID stride*data disks in blocks>\n"
+                       "\tforce_fsck\n"
                        "\ttest_fs\n"
                        "\t^test_fs\n"));
                free(buf);
@@ -2849,6 +2809,11 @@ fs_update_journal_user(struct ext2_super_block *sb, __u8 old_uuid[UUID_SIZE])
        jsb = (journal_superblock_t *) buf;
        /* Find the filesystem UUID */
        nr_users = ntohl(jsb->s_nr_users);
+       if (nr_users > JFS_USERS_MAX) {
+               fprintf(stderr, _("Journal superblock is corrupted, nr_users\n"
+                                "is too high (%d).\n"), nr_users);
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
+       }
 
        j_uuid = journal_user(old_uuid, jsb->s_users, nr_users);
        if (j_uuid == NULL) {
@@ -3023,6 +2988,37 @@ retry_open:
                rc = 1;
                goto closefs;
        }
+
+#ifdef NO_RECOVERY
+       /* Warn if file system needs recovery and it is opened for writing. */
+       if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & EXT2_MF_MOUNTED) &&
+           (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+           (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER)) {
+               fprintf(stderr,
+_("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
+  "\te2fsck -E journal_only %s\n\n"
+  "then rerun this command.  Otherwise, any changes made may be overwritten\n"
+  "by journal recovery.\n"), device_name);
+       }
+#else
+       /* Recover the journal if possible. */
+       if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & (EXT2_MF_BUSY | EXT2_MF_MOUNTED)) &&
+           ext2fs_has_feature_journal_needs_recovery(fs->super)) {
+               errcode_t err;
+
+               printf(_("Recovering journal.\n"));
+               err = ext2fs_run_ext3_journal(&fs);
+               if (err) {
+                       com_err("tune2fs", err, "while recovering journal.\n");
+                       printf(_("Please run e2fsck -fy %s.\n"), argv[1]);
+                       if (fs)
+                               ext2fs_close_free(&fs);
+                       exit(1);
+               }
+               sb = fs->super;
+       }
+#endif
+
        /* Normally we only need to write out the superblock */
        fs->flags |= EXT2_FLAG_SUPER_ONLY;
 
@@ -3178,6 +3174,15 @@ retry_open:
                char buf[SUPERBLOCK_SIZE] __attribute__ ((aligned(8)));
                __u8 old_uuid[UUID_SIZE];
 
+               if (!ext2fs_has_feature_csum_seed(fs->super) &&
+                   (ext2fs_has_feature_metadata_csum(fs->super) ||
+                    ext2fs_has_feature_ea_inode(fs->super))) {
+                       check_fsck_needed(fs,
+                               _("Setting the UUID on this "
+                                 "filesystem could take some time."));
+                       rewrite_checksums = 1;
+               }
+
                if (ext2fs_has_group_desc_csum(fs)) {
                        /*
                         * Changing the UUID on a metadata_csum FS requires
@@ -3198,10 +3203,6 @@ retry_open:
                                try_confirm_csum_seed_support();
                                exit(1);
                        }
-                       if (!ext2fs_has_feature_csum_seed(fs->super))
-                               check_fsck_needed(fs,
-                                       _("Setting UUID on a checksummed "
-                                         "filesystem could take some time."));
 
                        /*
                         * Determine if the block group checksums are
@@ -3259,10 +3260,6 @@ retry_open:
                }
 
                ext2fs_mark_super_dirty(fs);
-               if (!ext2fs_has_feature_csum_seed(fs->super) &&
-                   (ext2fs_has_feature_metadata_csum(fs->super) ||
-                    ext2fs_has_feature_ea_inode(fs->super)))
-                       rewrite_checksums = 1;
        }
 
        if (I_flag) {
@@ -3327,35 +3324,6 @@ retry_open:
                free(ext_mount_opts);
        }
 
-#ifdef NO_RECOVERY
-       /* Warn if file system needs recovery and it is opened for writing. */
-       if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & EXT2_MF_MOUNTED) &&
-           (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
-           (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER)) {
-               fprintf(stderr,
-_("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
-  "\te2fsck -E journal_only %s\n\n"
-  "then rerun this command.  Otherwise, any changes made may be overwritten\n"
-  "by journal recovery.\n"), device_name);
-       }
-#else
-       /* Recover the journal if possible. */
-       if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & EXT2_MF_MOUNTED) &&
-           ext2fs_has_feature_journal_needs_recovery(fs->super)) {
-               errcode_t err;
-
-               printf(_("Recovering journal.\n"));
-               err = ext2fs_run_ext3_journal(&fs);
-               if (err) {
-                       com_err("tune2fs", err, "while recovering journal.\n");
-                       printf(_("Please run e2fsck -fy %s.\n"), argv[1]);
-                       goto closefs;
-               }
-               ext2fs_clear_feature_journal_needs_recovery(fs->super);
-               ext2fs_mark_super_dirty(fs);
-       }
-#endif
-
        free(device_name);
        remove_error_table(&et_ext2_error_table);
 
@@ -3367,6 +3335,7 @@ closefs:
 #endif
        }
 
-       convert_64bit(fs, feature_64bit);
+       if (feature_64bit)
+               convert_64bit(fs, feature_64bit);
        return (ext2fs_close_free(&fs) ? 1 : 0);
 }