Whamcloud - gitweb
tune2fs: fix casefold+encrypt error message
[tools/e2fsprogs.git] / misc / mke2fs.c
index 57b5bbf..9957642 100644 (file)
@@ -93,8 +93,10 @@ static uid_t root_uid;
 static gid_t   root_gid;
 int    journal_size;
 int    journal_flags;
+int    journal_fc_size;
 static int     lazy_itable_init;
 static int     packed_meta_blocks;
+int            no_copy_xattrs;
 static char    *bad_blocks_filename = NULL;
 static __u32   fs_stride;
 /* Initialize usr/grp quotas by default */
@@ -343,7 +345,7 @@ _("Warning: the backup superblock/group descriptors at block %u contain\n"
                exit(1);
        }
        while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
-               ext2fs_mark_block_bitmap2(fs->block_map, EXT2FS_B2C(fs, blk));
+               ext2fs_mark_block_bitmap2(fs->block_map, blk);
        ext2fs_badblocks_list_iterate_end(bb_iter);
 }
 
@@ -359,9 +361,15 @@ static void write_reserved_inodes(ext2_filsys fs)
                exit(1);
        }
 
-       for (ino = 1; ino < EXT2_FIRST_INO(fs->super); ino++)
-               ext2fs_write_inode_full(fs, ino, inode,
-                                       EXT2_INODE_SIZE(fs->super));
+       for (ino = 1; ino < EXT2_FIRST_INO(fs->super); ino++) {
+               retval = ext2fs_write_inode_full(fs, ino, inode,
+                                                EXT2_INODE_SIZE(fs->super));
+               if (retval) {
+                       com_err("ext2fs_write_inode_full", retval,
+                               _("while writing reserved inodes"));
+                       exit(1);
+               }
+       }
 
        ext2fs_free_mem(&inode);
 }
@@ -597,9 +605,16 @@ static void create_journal_dev(ext2_filsys fs)
        char                    *buf;
        blk64_t                 blk, err_blk;
        int                     c, count, err_count;
+       struct ext2fs_journal_params    jparams;
+
+       retval = ext2fs_get_journal_params(&jparams, fs);
+       if (retval) {
+               com_err("create_journal_dev", retval, "%s",
+                       _("while splitting the journal size"));
+               exit(1);
+       }
 
-       retval = ext2fs_create_journal_superblock(fs,
-                                 ext2fs_blocks_count(fs->super), 0, &buf);
+       retval = ext2fs_create_journal_superblock2(fs, &jparams, 0, &buf);
        if (retval) {
                com_err("create_journal_dev", retval, "%s",
                        _("while initializing journal superblock"));
@@ -648,7 +663,6 @@ write_superblock:
 static void show_stats(ext2_filsys fs)
 {
        struct ext2_super_block *s = fs->super;
-       char                    buf[80];
         char                    *os;
        blk64_t                 group_block;
        dgrp_t                  i;
@@ -666,9 +680,8 @@ static void show_stats(ext2_filsys fs)
                fprintf(stderr, _("warning: %llu blocks unused.\n\n"),
                       ext2fs_blocks_count(&fs_param) - ext2fs_blocks_count(s));
 
-       memset(buf, 0, sizeof(buf));
-       strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name));
-       printf(_("Filesystem label=%s\n"), buf);
+       printf(_("Filesystem label=%.*s\n"), EXT2_LEN_STR(s->s_volume_name));
+
        os = e2p_os2string(fs->super->s_creator_os);
        if (os)
                printf(_("OS type: %s\n"), os);
@@ -783,6 +796,8 @@ static void parse_extended_opts(struct ext2_super_block *param,
        int     len;
        int     r_usage = 0;
        int     ret;
+       int     encoding = -1;
+       char    *encoding_flags = NULL;
 
        len = strlen(opts);
        buf = malloc(len+1);
@@ -874,6 +889,9 @@ static void parse_extended_opts(struct ext2_super_block *param,
                                r_usage++;
                                continue;
                        }
+               } else if (strcmp(token, "no_copy_xattrs") == 0) {
+                       no_copy_xattrs = 1;
+                       continue;
                } else if (strcmp(token, "num_backup_sb") == 0) {
                        if (!arg) {
                                r_usage++;
@@ -1046,6 +1064,26 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        }
                } else if (!strcmp(token, "android_sparse")) {
                        android_sparse_file = 1;
+               } else if (!strcmp(token, "encoding")) {
+                       if (!arg) {
+                               r_usage++;
+                               continue;
+                       }
+
+                       encoding = e2p_str2encoding(arg);
+                       if (encoding < 0) {
+                               fprintf(stderr, _("Invalid encoding: %s"), arg);
+                               r_usage++;
+                               continue;
+                       }
+                       param->s_encoding = encoding;
+                       ext2fs_set_feature_casefold(param);
+               } else if (!strcmp(token, "encoding_flags")) {
+                       if (!arg) {
+                               r_usage++;
+                               continue;
+                       }
+                       encoding_flags = arg;
                } else {
                        r_usage++;
                        badopt = token;
@@ -1070,6 +1108,8 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        "\ttest_fs\n"
                        "\tdiscard\n"
                        "\tnodiscard\n"
+                       "\tencoding=<encoding>\n"
+                       "\tencoding_flags=<flags>\n"
                        "\tquotatype=<quota type(s) to be enabled>\n\n"),
                        badopt ? badopt : "");
                free(buf);
@@ -1081,6 +1121,25 @@ static void parse_extended_opts(struct ext2_super_block *param,
                                  "multiple of stride %u.\n\n"),
                        param->s_raid_stripe_width, param->s_raid_stride);
 
+       if (ext2fs_has_feature_casefold(param)) {
+               param->s_encoding_flags =
+                       e2p_get_encoding_flags(param->s_encoding);
+
+               if (encoding_flags &&
+                   e2p_str2encoding_flags(param->s_encoding, encoding_flags,
+                                          &param->s_encoding_flags)) {
+                       fprintf(stderr, _("error: Invalid encoding flag: %s\n"),
+                               encoding_flags);
+                       free(buf);
+                       exit(1);
+               }
+       } else if (encoding_flags) {
+               fprintf(stderr, _("error: An encoding must be explicitly "
+                                 "specified when passing encoding-flags\n"));
+               free(buf);
+               exit(1);
+       }
+
        free(buf);
 }
 
@@ -1090,7 +1149,9 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_COMPAT_RESIZE_INODE |
                EXT2_FEATURE_COMPAT_DIR_INDEX |
                EXT2_FEATURE_COMPAT_EXT_ATTR |
-               EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
+               EXT4_FEATURE_COMPAT_SPARSE_SUPER2 |
+               EXT4_FEATURE_COMPAT_FAST_COMMIT |
+               EXT4_FEATURE_COMPAT_STABLE_INODES,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE|
                EXT3_FEATURE_INCOMPAT_EXTENTS|
@@ -1102,6 +1163,7 @@ static __u32 ok_features[3] = {
                EXT4_FEATURE_INCOMPAT_64BIT|
                EXT4_FEATURE_INCOMPAT_INLINE_DATA|
                EXT4_FEATURE_INCOMPAT_ENCRYPT |
+               EXT4_FEATURE_INCOMPAT_CASEFOLD |
                EXT4_FEATURE_INCOMPAT_CSUM_SEED |
                EXT4_FEATURE_INCOMPAT_LARGEDIR,
        /* R/O compat */
@@ -1114,7 +1176,8 @@ static __u32 ok_features[3] = {
                EXT4_FEATURE_RO_COMPAT_BIGALLOC|
                EXT4_FEATURE_RO_COMPAT_QUOTA|
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|
-               EXT4_FEATURE_RO_COMPAT_PROJECT
+               EXT4_FEATURE_RO_COMPAT_PROJECT|
+               EXT4_FEATURE_RO_COMPAT_VERITY
 };
 
 
@@ -1413,23 +1476,30 @@ int get_bool_from_profile(char **types, const char *opt, int def_val)
 extern const char *mke2fs_default_profile;
 static const char *default_files[] = { "<default>", 0 };
 
+struct device_param {
+       unsigned long min_io;           /* prefered minimum IO size */
+       unsigned long opt_io;           /* optimal IO size */
+       unsigned long alignment_offset; /* alignment offset wrt physical block size */
+       unsigned int dax:1;             /* supports dax? */
+};
+
 #ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
 /*
  * Sets the geometry of a device (stripe/stride), and returns the
  * device's alignment offset, if any, or a negative error.
  */
 static int get_device_geometry(const char *file,
-                              struct ext2_super_block *param,
-                              unsigned int psector_size)
+                              unsigned int blocksize,
+                              unsigned int psector_size,
+                              struct device_param *dev_param)
 {
        int rc = -1;
-       unsigned int blocksize;
        blkid_probe pr;
        blkid_topology tp;
-       unsigned long min_io;
-       unsigned long opt_io;
        struct stat statbuf;
 
+       memset(dev_param, 0, sizeof(*dev_param));
+
        /* Nothing to do for a regular file */
        if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode))
                return 0;
@@ -1442,23 +1512,20 @@ static int get_device_geometry(const char *file,
        if (!tp)
                goto out;
 
-       min_io = blkid_topology_get_minimum_io_size(tp);
-       opt_io = blkid_topology_get_optimal_io_size(tp);
-       blocksize = EXT2_BLOCK_SIZE(param);
-       if ((min_io == 0) && (psector_size > blocksize))
-               min_io = psector_size;
-       if ((opt_io == 0) && min_io)
-               opt_io = min_io;
-       if ((opt_io == 0) && (psector_size > blocksize))
-               opt_io = psector_size;
-
-       /* setting stripe/stride to blocksize is pointless */
-       if (min_io > blocksize)
-               param->s_raid_stride = min_io / blocksize;
-       if (opt_io > blocksize)
-               param->s_raid_stripe_width = opt_io / blocksize;
-
-       rc = blkid_topology_get_alignment_offset(tp);
+       dev_param->min_io = blkid_topology_get_minimum_io_size(tp);
+       dev_param->opt_io = blkid_topology_get_optimal_io_size(tp);
+       if ((dev_param->min_io == 0) && (psector_size > blocksize))
+               dev_param->min_io = psector_size;
+       if ((dev_param->opt_io == 0) && dev_param->min_io > 0)
+               dev_param->opt_io = dev_param->min_io;
+       if ((dev_param->opt_io == 0) && (psector_size > blocksize))
+               dev_param->opt_io = psector_size;
+
+       dev_param->alignment_offset = blkid_topology_get_alignment_offset(tp);
+#ifdef HAVE_BLKID_TOPOLOGY_GET_DAX
+       dev_param->dax = blkid_topology_get_dax(tp);
+#endif
+       rc = 0;
 out:
        blkid_free_probe(pr);
        return rc;
@@ -1507,6 +1574,7 @@ static void PRS(int argc, char *argv[])
        int             use_bsize;
        char            *newpath;
        int             pathlen = sizeof(PATH_SET) + 1;
+       struct device_param dev_param;
 
        if (oldpath)
                pathlen += strlen(oldpath);
@@ -1693,6 +1761,8 @@ profile_error:
                case 'j':
                        if (!journal_size)
                                journal_size = -1;
+                       if (!journal_fc_size)
+                               journal_fc_size = -1;
                        break;
                case 'J':
                        parse_journal_opts(optarg);
@@ -2015,6 +2085,7 @@ profile_error:
                ext2fs_clear_feature_huge_file(&fs_param);
                ext2fs_clear_feature_metadata_csum(&fs_param);
                ext2fs_clear_feature_ea_inode(&fs_param);
+               ext2fs_clear_feature_casefold(&fs_param);
        }
        edit_feature(fs_features ? fs_features : tmp,
                     &fs_param.s_feature_compat);
@@ -2127,9 +2198,11 @@ profile_error:
        }
        /*
         * Guard against group descriptor count overflowing... Mostly to avoid
-        * strange results for absurdly large devices.
+        * strange results for absurdly large devices.  This is in log2:
+        * (blocksize) * (bits per byte) * (maximum number of block groups)
         */
-       if (fs_blocks_count > ((1ULL << (fs_param.s_log_block_size + 3 + 32)) - 1)) {
+       if (fs_blocks_count >
+           (1ULL << (EXT2_BLOCK_SIZE_BITS(&fs_param) + 3 + 32)) - 1) {
                fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s "
                                  "too big to create\n\t"
                                  "a filesystem using a blocksize of %d.\n"),
@@ -2249,17 +2322,35 @@ profile_error:
        }
 
 #ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
-       retval = get_device_geometry(device_name, &fs_param,
-                                    (unsigned int) psector_size);
+       retval = get_device_geometry(device_name, blocksize,
+                                    psector_size, &dev_param);
        if (retval < 0) {
                fprintf(stderr,
                        _("warning: Unable to get device geometry for %s\n"),
                        device_name);
-       } else if (retval) {
-               printf(_("%s alignment is offset by %lu bytes.\n"),
-                      device_name, retval);
-               printf(_("This may result in very poor performance, "
-                         "(re)-partitioning suggested.\n"));
+       } else {
+               /* setting stripe/stride to blocksize is pointless */
+               if (dev_param.min_io > blocksize)
+                       fs_param.s_raid_stride = dev_param.min_io / blocksize;
+               if (dev_param.opt_io > blocksize) {
+                       fs_param.s_raid_stripe_width =
+                                               dev_param.opt_io / blocksize;
+               }
+
+               if (dev_param.alignment_offset) {
+                       printf(_("%s alignment is offset by %lu bytes.\n"),
+                              device_name, dev_param.alignment_offset);
+                       printf(_("This may result in very poor performance, "
+                                 "(re)-partitioning suggested.\n"));
+               }
+
+               if (dev_param.dax && blocksize != sys_page_size) {
+                       fprintf(stderr,
+                               _("%s is capable of DAX but current block size "
+                                 "%u is different from system page size %u so "
+                                 "filesystem will not support DAX.\n"),
+                               device_name, blocksize, sys_page_size);
+               }
        }
 #endif
 
@@ -2330,6 +2421,33 @@ profile_error:
        if (packed_meta_blocks)
                journal_location = 0;
 
+       if (ext2fs_has_feature_casefold(&fs_param)) {
+               char *ef, *en = get_string_from_profile(fs_types,
+                                                       "encoding", "utf8");
+               int encoding = e2p_str2encoding(en);
+
+               if (encoding < 0) {
+                       com_err(program_name, 0,
+                               _("Unknown filename encoding from profile: %s"),
+                               en);
+                       exit(1);
+               }
+               free(en);
+               fs_param.s_encoding = encoding;
+               ef = get_string_from_profile(fs_types, "encoding_flags", NULL);
+               if (ef) {
+                       if (e2p_str2encoding_flags(encoding, ef,
+                                       &fs_param.s_encoding_flags) < 0) {
+                               com_err(program_name, 0,
+                       _("Unknown encoding flags from profile: %s"), ef);
+                               exit(1);
+                       }
+                       free(ef);
+               } else
+                       fs_param.s_encoding_flags =
+                               e2p_get_encoding_flags(encoding);
+       }
+
        /* Get options from profile */
        for (cpp = fs_types; *cpp; cpp++) {
                tmp = NULL;
@@ -2374,6 +2492,15 @@ profile_error:
                }
        }
 
+       if (ext2fs_has_feature_casefold(&fs_param) &&
+           ext2fs_has_feature_encrypt(&fs_param)) {
+               com_err(program_name, 0, "%s",
+                       _("The encrypt and casefold features are not "
+                         "compatible.\nThey can not be both enabled "
+                         "simultaneously.\n"));
+                     exit (1);
+       }
+
        /* Don't allow user to set both metadata_csum and uninit_bg bits. */
        if (ext2fs_has_feature_metadata_csum(&fs_param) &&
            ext2fs_has_feature_gdt_csum(&fs_param))
@@ -2818,7 +2945,9 @@ int main (int argc, char *argv[])
        errcode_t       retval = 0;
        ext2_filsys     fs;
        badblocks_list  bb_list = 0;
-       unsigned int    journal_blocks = 0;
+       badblocks_iterate       bb_iter;
+       blk_t           blk;
+       struct ext2fs_journal_params    jparams = {0};
        unsigned int    i, checkinterval;
        int             max_mnt_count;
        int             val, hash_alg;
@@ -2828,6 +2957,7 @@ int main (int argc, char *argv[])
        char            opt_string[40];
        char            *hash_alg_str;
        int             itable_zeroed = 0;
+       blk64_t         overhead;
 
 #ifdef ENABLE_NLS
        setlocale(LC_MESSAGES, "");
@@ -2927,7 +3057,7 @@ int main (int argc, char *argv[])
        /* Calculate journal blocks */
        if (!journal_device && ((journal_size) ||
            ext2fs_has_feature_journal(&fs_param)))
-               journal_blocks = figure_journal_size(journal_size, fs);
+               figure_journal_size(&jparams, journal_size, journal_fc_size, fs);
 
        sprintf(opt_string, "tdb_data_size=%d", fs->blocksize <= 4096 ?
                32768 : fs->blocksize * 8);
@@ -3059,7 +3189,7 @@ int main (int argc, char *argv[])
        if (volume_label) {
                memset(fs->super->s_volume_name, 0,
                       sizeof(fs->super->s_volume_name));
-               strncpy(fs->super->s_volume_name, volume_label,
+               strncpy((char *) fs->super->s_volume_name, volume_label,
                        sizeof(fs->super->s_volume_name));
        }
 
@@ -3069,7 +3199,7 @@ int main (int argc, char *argv[])
        if (mount_dir) {
                memset(fs->super->s_last_mounted, 0,
                       sizeof(fs->super->s_last_mounted));
-               strncpy(fs->super->s_last_mounted, mount_dir,
+               strncpy((char *) fs->super->s_last_mounted, mount_dir,
                        sizeof(fs->super->s_last_mounted));
        }
 
@@ -3119,6 +3249,23 @@ int main (int argc, char *argv[])
        if (!quiet)
                printf("%s", _("done                            \n"));
 
+       /*
+        * Unmark bad blocks to calculate overhead, because metadata
+        * blocks and bad blocks can land on the same allocation cluster.
+        */
+       if (bb_list) {
+               retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+                                                            &bb_iter);
+               if (retval) {
+                       com_err("ext2fs_badblocks_list_iterate_begin", retval,
+                               "%s", _("while unmarking bad blocks"));
+                       exit(1);
+               }
+               while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
+                       ext2fs_unmark_block_bitmap2(fs->block_map, blk);
+               ext2fs_badblocks_list_iterate_end(bb_iter);
+       }
+
        retval = ext2fs_convert_subcluster_bitmap(fs, &fs->block_map);
        if (retval) {
                com_err(program_name, retval, "%s",
@@ -3126,6 +3273,28 @@ int main (int argc, char *argv[])
                exit(1);
        }
 
+       retval = ext2fs_count_used_clusters(fs, fs->super->s_first_data_block,
+                                       ext2fs_blocks_count(fs->super) - 1,
+                                       &overhead);
+       if (retval) {
+               com_err(program_name, retval, "%s",
+                       _("while calculating overhead"));
+               exit(1);
+       }
+
+       if (bb_list) {
+               retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+                                                            &bb_iter);
+               if (retval) {
+                       com_err("ext2fs_badblocks_list_iterate_begin", retval,
+                               "%s", _("while marking bad blocks as used"));
+                       exit(1);
+               }
+               while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
+                       ext2fs_mark_block_bitmap2(fs->block_map, blk);
+               ext2fs_badblocks_list_iterate_end(bb_iter);
+       }
+
        if (super_only) {
                check_plausibility(device_name, CHECK_FS_EXIST, NULL);
                printf(_("%s may be further corrupted by superblock rewrite\n"),
@@ -3223,22 +3392,23 @@ int main (int argc, char *argv[])
                free(journal_device);
        } else if ((journal_size) ||
                   ext2fs_has_feature_journal(&fs_param)) {
+               overhead += EXT2FS_NUM_B2C(fs, jparams.num_journal_blocks + jparams.num_fc_blocks);
                if (super_only) {
                        printf("%s", _("Skipping journal creation in super-only mode\n"));
                        fs->super->s_journal_inum = EXT2_JOURNAL_INO;
                        goto no_journal;
                }
 
-               if (!journal_blocks) {
+               if (!jparams.num_journal_blocks) {
                        ext2fs_clear_feature_journal(fs->super);
                        goto no_journal;
                }
                if (!quiet) {
                        printf(_("Creating journal (%u blocks): "),
-                              journal_blocks);
+                              jparams.num_journal_blocks + jparams.num_fc_blocks);
                        fflush(stdout);
                }
-               retval = ext2fs_add_journal_inode2(fs, journal_blocks,
+               retval = ext2fs_add_journal_inode3(fs, &jparams,
                                                   journal_location,
                                                   journal_flags);
                if (retval) {
@@ -3265,6 +3435,10 @@ no_journal:
                               fs->super->s_mmp_update_interval);
        }
 
+       overhead += fs->super->s_first_data_block;
+       if (!super_only)
+               fs->super->s_overhead_clusters = overhead;
+
        if (ext2fs_has_feature_bigalloc(&fs_param))
                fix_cluster_bg_counts(fs);
        if (ext2fs_has_feature_quota(&fs_param))