[Ocfs2-tools-devel] [patch 09/11] Modify mkfs.ocfs2 for sparse
files.take 2
tao.ma at oracle.com
tao.ma at oracle.com
Wed Aug 22 17:08:13 PDT 2007
This has included the new mkfs update.
===================================================================
--- quilt.ocfs2-tools.orig/mkfs.ocfs2/mkfs.c 2007-08-21 06:38:06.000000000 -0400
+++ quilt.ocfs2-tools/mkfs.ocfs2/mkfs.c 2007-08-22 05:51:42.000000000 -0400
@@ -116,6 +116,80 @@ static struct fs_type_translation ocfs2_
enum {
BACKUP_SUPER_OPTION = CHAR_MAX + 1,
+ FEATURE_LEVEL,
+ FEATURES_OPTION,
+};
+
+struct fs_feature_flags {
+ const char *ff_str;
+ /* this flag is the feature's own flag. */
+ fs_options ff_own_flags;
+ /*
+ * this flag includes the feature's own flag and
+ * all the other features' flag it depends on.
+ */
+ fs_options ff_flags;
+};
+
+static struct fs_feature_flags ocfs2_supported_features[] = {
+ {
+ "local",
+ {0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
+ {0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
+ },
+ {
+ "sparse",
+ {0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
+ {0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
+ },
+ {
+ "backup-super",
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
+ },
+ {
+ "unwritten",
+ {0, 0, OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
+ {0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
+ OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
+ },
+ {
+ NULL,
+ {0, 0, 0},
+ {0, 0, 0}
+ },
+};
+
+enum feature_level_indexes {
+ FEATURE_LEVEL_DEFAULT = 0,
+ FEATURE_LEVEL_MAX_COMPAT,
+ FEATURE_LEVEL_MAX_FEATURES,
+};
+
+struct feature_level_translation {
+ const char *fl_str;
+ enum feature_level_indexes fl_type;
+};
+
+static struct feature_level_translation ocfs2_feature_levels_table[] = {
+ {"default", FEATURE_LEVEL_DEFAULT},
+ {"max-compat", FEATURE_LEVEL_MAX_COMPAT},
+ {"max-features", FEATURE_LEVEL_MAX_FEATURES},
+ {NULL, FEATURE_LEVEL_DEFAULT},
+};
+
+static fs_options feature_level_defaults[] = {
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB,
+ OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
+ 0}, /* FEATURE_LEVEL_DEFAULT */
+
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB,
+ 0,
+ 0}, /* FEATURE_LEVEL_MAX_COMPAT */
+
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB,
+ OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
+ OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* FEATURE_LEVEL_MAX_FEATURES */
};
static uint64_t align_bytes_to_clusters_ceil(State *s,
@@ -505,6 +579,159 @@ parse_fs_type_opts(char *progname, const
}
}
+/* Get the feature level according to the value set by "--fs-feature-level". */
+static void parse_feature_level_opts(char *progname, const char *typestr,
+ enum feature_level_indexes *index)
+{
+ int i;
+
+ for(i = 0; ocfs2_feature_levels_table[i].fl_str; i++) {
+ if (strcmp(typestr,
+ ocfs2_feature_levels_table[i].fl_str) == 0) {
+ *index = ocfs2_feature_levels_table[i].fl_type;
+ break;
+ }
+ }
+
+ if (!ocfs2_feature_levels_table[i].fl_str) {
+ com_err(progname, 0,
+ "unrecognized fs-feature-level:%s", typestr);
+ exit(1);
+ }
+}
+
+static void inline merge_features(fs_options *features,
+ fs_options new_features)
+{
+ features->compat |= new_features.compat;
+ features->incompat |= new_features.incompat;
+ features->ro_compat |= new_features.ro_compat;
+}
+
+/*
+ * Parse the feature string set by the user in "--fs-features".
+ * for all the features the user want to set, they are added into
+ * the "feature_flags". For those the user want to clear(with "no"
+ * in the beginning), they are stored in the "reverse_flags".
+ */
+static void parse_feature_opts(char *progname, const char *opts,
+ fs_options *feature_flags,
+ fs_options *reverse_flags)
+{
+ char *options, *token, *next, *p, *arg;
+ int i, reverse = 0;
+
+ memset(feature_flags, 0, sizeof(fs_options));
+ memset(reverse_flags, 0, sizeof(fs_options));
+
+ options = strdup(opts);
+ for (token = options; token && *token; token = next) {
+ reverse = 0;
+ p = strchr(token, ',');
+ next = NULL;
+
+ if (p) {
+ *p = '\0';
+ next = p + 1;
+ }
+
+ arg = strstr(token, "no");
+ if (arg && arg == token) {
+ reverse = 1;
+ token += 2;
+ }
+
+ for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
+ if (strcmp(token,
+ ocfs2_supported_features[i].ff_str) == 0) {
+ if (!reverse)
+ merge_features(feature_flags,
+ ocfs2_supported_features[i].ff_flags);
+ else
+ merge_features(reverse_flags,
+ ocfs2_supported_features[i].ff_own_flags);
+ break;
+ }
+ }
+ if (!ocfs2_supported_features[i].ff_str) {
+ com_err(progname, 0,
+ "unrecognized fs-feature-string:%s", token);
+ exit(1);
+ }
+ }
+
+ free(options);
+}
+
+static int check_feature_flags(fs_options *fs_flags,
+ fs_options *fs_r_flags)
+{
+ int ret = 1;
+
+ if (fs_r_flags->compat &&
+ fs_flags->compat & fs_r_flags->compat)
+ ret = 0;
+ else if (fs_r_flags->incompat &&
+ fs_flags->incompat & fs_r_flags->incompat)
+ ret = 0;
+ else if (fs_r_flags->ro_compat &&
+ fs_flags->ro_compat & fs_r_flags->ro_compat)
+ ret = 0;
+
+ return ret;
+}
+
+/*
+ * Check and Merge all the diffent features set by the user.
+ *
+ * level_set: all the features a user set by choose a feature level.
+ * feature_set: all the features a user set by "--fs-features".
+ * reverse_set: all the features a user want to clear by "--fs-features".
+ */
+static int merge_feature_flags_with_level(State *s,
+ fs_options *level_set,
+ fs_options *feature_set,
+ fs_options *reverse_set)
+{
+ int i;
+
+ /*
+ * "Check whether the user asked for a flag to be set and cleared,
+ * which is illegal. The feature_set and reverse_set are both set
+ * by "--fs-features", so they shouldn't collide with each other.
+ */
+ if (!check_feature_flags(feature_set, reverse_set))
+ return 0;
+
+ /* Now combine all the features the user has set. */
+ s->feature_flags = *level_set;
+ merge_features(&s->feature_flags, *feature_set);
+
+ /*
+ * We have to remove all the features in the reverse set
+ * and other features which depend on them.
+ */
+ for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
+ if ((reverse_set->compat &
+ ocfs2_supported_features[i].ff_flags.compat) ||
+ (reverse_set->incompat &
+ ocfs2_supported_features[i].ff_flags.incompat) ||
+ (reverse_set->ro_compat &
+ ocfs2_supported_features[i].ff_flags.ro_compat)) {
+ s->feature_flags.compat &=
+ ~ocfs2_supported_features[i].ff_own_flags.compat;
+
+ s->feature_flags.incompat &=
+ ~ocfs2_supported_features[i].ff_own_flags.incompat;
+
+ s->feature_flags.ro_compat &=
+ ~ocfs2_supported_features[i].ff_own_flags.ro_compat;
+ }
+ }
+
+ return 1;
+}
+
static State *
get_state(int argc, char **argv)
{
@@ -523,8 +750,10 @@ get_state(int argc, char **argv)
uint64_t val;
uint64_t journal_size_in_bytes = 0;
enum ocfs2_fs_types fs_type = FS_DEFAULT;
- int mount = 0;
- int no_backup_super = 0;
+ int mount = -1;
+ int no_backup_super = -1;
+ enum feature_level_indexes index = FEATURE_LEVEL_DEFAULT;
+ fs_options feature_flags ={0,0,0}, reverse_flags = {0,0,0};
static struct option long_options[] = {
{ "block-size", 1, 0, 'b' },
@@ -539,6 +768,8 @@ get_state(int argc, char **argv)
{ "force", 0, 0, 'F'},
{ "mount", 1, 0, 'M'},
{ "no-backup-super", 0, 0, BACKUP_SUPER_OPTION },
+ { "fs-feature-level=", 1, 0, FEATURE_LEVEL },
+ { "fs-features=", 1, 0, FEATURES_OPTION },
{ 0, 0, 0, 0}
};
@@ -673,6 +904,17 @@ get_state(int argc, char **argv)
no_backup_super = 1;
break;
+ case FEATURE_LEVEL:
+ parse_feature_level_opts(progname, optarg,
+ &index);
+ break;
+
+ case FEATURES_OPTION:
+ parse_feature_opts(progname, optarg,
+ &feature_flags,
+ &reverse_flags);
+ break;
+
default:
usage(progname);
break;
@@ -735,9 +977,32 @@ get_state(int argc, char **argv)
s->fs_type = fs_type;
- s->mount = mount;
+ if(!merge_feature_flags_with_level(s, &feature_level_defaults[index],
+ &feature_flags, &reverse_flags)) {
+ com_err(s->progname, 0,
+ "Incompatible feature flags"
+ " were specified\n");
+ exit(1);
+ }
+
+ if (s->feature_flags.incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT)
+ s->mount = MOUNT_LOCAL;
+ else
+ s->mount = MOUNT_CLUSTER;
+ if (s->feature_flags.compat & OCFS2_FEATURE_COMPAT_BACKUP_SB)
+ s->no_backup_super = 0;
+ else
+ s->no_backup_super = 1;
+
+
+ /* Here if the user set these flags explicitly, we will use them and
+ * discard the setting in the features set.
+ */
+ if (mount != -1)
+ s->mount = mount;
- s->no_backup_super = no_backup_super;
+ if (no_backup_super != -1)
+ s->no_backup_super = no_backup_super;
return s;
}
@@ -851,6 +1116,8 @@ usage(const char *progname)
fprintf(stderr, "usage: %s [-b block-size] [-C cluster-size] "
"[-J journal-options]\n\t\t[-L volume-label] [-M mount-type] "
"[-N number-of-node-slots]\n\t\t[-T filesystem-type] [-HFqvV] "
+ "\n\t\t[--fs-feature-level=[default|max-compat|max-features]] "
+ "\n\t\t[--fs-features=[[no]sparse,...]]"
"[--no-backup-super] device [blocks-count]\n", progname);
exit(0);
}
@@ -1716,7 +1983,6 @@ format_superblock(State *s, SystemFileDi
SystemFileDiskRecord *root_rec, SystemFileDiskRecord *sys_rec)
{
struct ocfs2_dinode *di;
- uint32_t incompat;
uint64_t super_off = rec->fe_off;
di = do_malloc(s, s->blocksize);
@@ -1750,14 +2016,27 @@ format_superblock(State *s, SystemFileDi
di->id2.i_super.s_max_slots = s->initial_slots;
di->id2.i_super.s_first_cluster_group = s->first_cluster_group_blkno;
- incompat = 0;
- if (s->hb_dev)
- incompat |= OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV;
+ if (s->hb_dev) {
+ s->feature_flags.incompat =
+ OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV;
+ s->feature_flags.compat = 0;
+ s->feature_flags.ro_compat = 0;
+ }
if (s->mount == MOUNT_LOCAL)
- incompat |= OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT;
+ s->feature_flags.incompat |=
+ OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT;
+ /*
+ * we clear the "backup_sb" here since it should be written by
+ * format_backup_super, not by us. And we have already set the
+ * "s->no_backup_super" according to the features in get_state,
+ * so it is safe to clear the flag here.
+ */
+ s->feature_flags.compat &= !OCFS2_FEATURE_COMPAT_BACKUP_SB;
- di->id2.i_super.s_feature_incompat = incompat;
+ di->id2.i_super.s_feature_incompat = s->feature_flags.incompat;
+ di->id2.i_super.s_feature_compat = s->feature_flags.compat;
+ di->id2.i_super.s_feature_ro_compat = s->feature_flags.ro_compat;
strcpy(di->id2.i_super.s_label, s->vol_label);
memcpy(di->id2.i_super.s_uuid, s->uuid, 16);
@@ -1899,7 +2178,7 @@ format_file(State *s, SystemFileDiskReco
if (rec->extent_len) {
di->id2.i_list.l_next_free_rec = 1;
di->id2.i_list.l_recs[0].e_cpos = 0;
- di->id2.i_list.l_recs[0].e_clusters = clusters;
+ ocfs2_set_rec_clusters(0, &di->id2.i_list.l_recs[0], clusters);
di->id2.i_list.l_recs[0].e_blkno =
rec->extent_off >> s->blocksize_bits;
}
===================================================================
--- quilt.ocfs2-tools.orig/mkfs.ocfs2/mkfs.h 2007-08-16 00:27:42.000000000 -0400
+++ quilt.ocfs2-tools/mkfs.ocfs2/mkfs.h 2007-08-22 05:51:42.000000000 -0400
@@ -192,6 +192,14 @@ struct _DirData {
SystemFileDiskRecord *record;
};
+typedef struct _fs_options fs_options;
+
+struct _fs_options {
+ uint32_t compat;
+ uint32_t incompat;
+ uint32_t ro_compat;
+};
+
typedef struct _State State;
struct _State {
@@ -241,6 +249,8 @@ struct _State {
uint32_t first_cluster_group;
uint64_t first_cluster_group_blkno;
+ fs_options feature_flags;
+
enum ocfs2_fs_types fs_type;
};
--
More information about the Ocfs2-tools-devel
mailing list