Whamcloud - gitweb
LU-471 fix mkfs.lustre to avoid creating duplicate options
authorBobi Jam <bobijam@whamcloud.com>
Wed, 27 Jul 2011 01:32:15 +0000 (09:32 +0800)
committerJohann Lombardi <johann@whamcloud.com>
Fri, 29 Jul 2011 13:58:49 +0000 (09:58 -0400)
Also make user specified options overwrite default internal default
options.

Change-Id: I27d55e7490566e07c310e52ba7319fefcd0528d9
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Reviewed-on: http://review.whamcloud.com/1103
Tested-by: Hudson
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/tests/conf-sanity.sh
lustre/utils/mkfs_lustre.c

index f2e34b4..51c9b0d 100644 (file)
@@ -2370,6 +2370,31 @@ test_59() {
 }
 run_test 59 "writeconf mount option"
 
+test_60() { # LU-471
+       add mds $MDS_MKFS_OPTS --mkfsoptions='\" -E stride=64 \"' --reformat $MDSDEV
+
+       dump=$(do_facet mds dumpe2fs -h $MDSDEV)
+       rc=${PIPESTATUS[0]}
+       [ $rc -eq 0 ] || error "dumpe2fs $MDSDEV failed"
+
+       # MDT default has uninit_bg feature
+       echo $dump | grep uninit_bg > /dev/null || error "uninit_bg is not set"
+       # we set stride extended options
+       echo $dump | grep stride > /dev/null || error "stride is not set"
+
+       add mds $MDS_MKFS_OPTS --mkfsoptions='\" -E stride=64 -O ^uninit_bg\"' --reformat $MDSDEV
+       dump=$(do_facet mds dumpe2fs -h $MDSDEV)
+       rc=${PIPESTATUS[0]}
+       [ $rc -eq 0 ] || error "dumpe2fs $MDSDEV failed"
+
+       # we disabled dir_index feature
+       echo $dump | grep uninit_bg > /dev/null && error "uninit_bg is set"
+       # we set stride extended options
+       echo $dump | grep stride > /dev/null || error "stride is not set"
+       reformat
+}
+run_test 60 "check mkfs.lustre --mkfsoptions -E -O options setting"
+
 if ! combined_mgs_mds ; then
        stop mgs
 fi
index c1c8d52..9486849 100644 (file)
@@ -477,30 +477,67 @@ static int is_e2fsprogs_feature_supp(const char *feature)
         return ret;
 }
 
-static void enable_default_ext4_features(struct mkfs_opts *mop)
+/**
+ * append_unique: append @key or @key=@val pair to @buf only if @key does not
+ *                exists
+ *      @buf: buffer to hold @key or @key=@val
+ *      @prefix: prefix string before @key
+ *      @key: key string
+ *      @val: value string if it's a @key=@val pair
+ */
+static void append_unique(char *buf, char *prefix, char *key, char *val,
+                          size_t maxbuflen)
 {
-        if (IS_OST(&mop->mo_ldd))
-                strscat(mop->mo_mkfsopts, " -O extents,uninit_bg",
-                        sizeof(mop->mo_mkfsopts));
-        else if (IS_MDT(&mop->mo_ldd))
-                strscat(mop->mo_mkfsopts, " -O uninit_bg",
-                        sizeof(mop->mo_mkfsopts));
-        else
-                strscat(mop->mo_mkfsopts, " -O uninit_bg",
-                        sizeof(mop->mo_mkfsopts));
+        char *anchor, *end;
+        int  len;
+
+        if (key == NULL)
+                return;
+
+        anchor = end = strstr(buf, key);
+        /* try to find exact match string in @buf */
+        while (end && *end != '\0' && *end != ',' && *end != ' ' && *end != '=')
+                ++end;
+        len = end - anchor;
+        if (anchor == NULL || strlen(key) != len ||
+            strncmp(anchor, key, len) != 0) {
+                if (prefix != NULL)
+                        strscat(buf, prefix, maxbuflen);
+
+                strscat(buf, key, maxbuflen);
+                if (val != NULL) {
+                        strscat(buf, "=", maxbuflen);
+                        strscat(buf, val, maxbuflen);
+                }
+        }
+}
+
+static void enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
+                                         size_t maxbuflen, int user_spec)
+{
+        if (IS_OST(&mop->mo_ldd)) {
+                append_unique(anchor, user_spec ? "," : " -O ",
+                              "extents", NULL, maxbuflen);
+                append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen);
+        } else if (IS_MDT(&mop->mo_ldd)) {
+                append_unique(anchor, user_spec ? "," : " -O ",
+                              "uninit_bg", NULL, maxbuflen);
+        } else {
+                append_unique(anchor, user_spec ? "," : " -O ",
+                              "uninit_bg", NULL, maxbuflen);
+        }
 
         /* Multiple mount protection enabled only if failover node specified */
         if (failover) {
                 if (is_e2fsprogs_feature_supp("-O mmp") == 0)
-                        strscat(mop->mo_mkfsopts, ",mmp",
-                                sizeof(mop->mo_mkfsopts));
+                        append_unique(anchor, ",", "mmp", NULL, maxbuflen);
                 else
                         disp_old_e2fsprogs_msg("mmp", 1);
         }
 
         /* Allow more than 65000 subdirectories */
         if (is_e2fsprogs_feature_supp("-O dir_nlink") == 0)
-                strscat(mop->mo_mkfsopts,",dir_nlink",sizeof(mop->mo_mkfsopts));
+                append_unique(anchor, ",", "dir_nlink", NULL, maxbuflen);
 
 #ifdef HAVE_EXT4_LDISKFS
         /* The following options are only valid for ext4-based ldiskfs.
@@ -510,12 +547,12 @@ static void enable_default_ext4_features(struct mkfs_opts *mop)
 
         /* Allow files larger than 2TB.  Also needs LU-16, but not harmful. */
         if (is_e2fsprogs_feature_supp("-O huge_file") == 0)
-                strscat(mop->mo_mkfsopts,",huge_file",sizeof(mop->mo_mkfsopts));
+                append_unique(anchor, ",", "huge_file", NULL, maxbuflen);
 
         /* Enable large block addresses if the LUN is over 2^32 blocks */
         if (mop->mo_device_sz / (L_BLOCK_SIZE >> 10) >= 0x100002000ULL &&
             is_e2fsprogs_feature_supp("-O 64bit") == 0)
-                strscat(mop->mo_mkfsopts,",64bit",sizeof(mop->mo_mkfsopts));
+                append_unique(anchor, ",", "64bit", NULL, maxbuflen);
 
         /* Cluster inode/block bitmaps and inode table for more efficient IO.
          * Align the flex groups on a 1MB boundary for better performance.
@@ -523,27 +560,67 @@ static void enable_default_ext4_features(struct mkfs_opts *mop)
         if (is_e2fsprogs_feature_supp("-O flex_bg") == 0) {
                 char tmp_buf[64];
 
-                strscat(mop->mo_mkfsopts, ",flex_bg", sizeof(mop->mo_mkfsopts));
+                append_unique(anchor, ",", "flex_bg", NULL, maxbuflen);
 
                 if (IS_OST(&mop->mo_ldd)) {
                         snprintf(tmp_buf, sizeof(tmp_buf), " -G %u",
                                  (1 << 20) / L_BLOCK_SIZE);
-                        strscat(mop->mo_mkfsopts, tmp_buf,
-                                sizeof(mop->mo_mkfsopts));
+                        strscat(anchor, tmp_buf, maxbuflen);
                 }
         }
 
 #endif
 }
 
+/**
+ * moveopts_to_end: find the option string, move remaining strings to
+ *                  where option string starts, and append the option
+ *                  string at the end
+ *      @start: where the option string starts before the move
+ *      RETURN: where the option string starts after the move
+ */
+static char *moveopts_to_end(char *start)
+{
+        char save[512];
+        char *end, *idx;
+
+        /* skip whitespace before options */
+        end = start + 2;
+        while (*end == ' ')
+                ++end;
+
+        /* find end of option characters */
+        while (*end != ' ' && *end != '\0')
+                ++end;
+
+        /* save options */
+        strncpy(save, start, end - start);
+        save[end - start] = '\0';
+
+        /* move remaining options up front */
+        if (*end)
+                memmove(start, end, strlen(end));
+        *(start + strlen(end)) = '\0';
+
+        /* append the specified options */
+        if (*(start + strlen(start) - 1) != ' ')
+                strcat(start, " ");
+        idx = start + strlen(start);
+        strcat(start, save);
+
+        return idx;
+}
+
 /* Build fs according to type */
 int make_lustre_backfs(struct mkfs_opts *mop)
 {
         __u64 device_sz = mop->mo_device_sz, block_count = 0;
         char mkfs_cmd[PATH_MAX];
         char buf[64];
+        char *start;
         char *dev;
-        int ret = 0;
+        int ret = 0, ext_opts = 0;
+        size_t maxbuflen;
 
         if (!(mop->mo_flags & MO_IS_LOOP)) {
                 mop->mo_device_sz = get_device_size(mop->mo_device);
@@ -675,8 +752,43 @@ int make_lustre_backfs(struct mkfs_opts *mop)
                                 sizeof(mop->mo_mkfsopts));
                 }
 
-                if (strstr(mop->mo_mkfsopts, "-O") == NULL)
-                        enable_default_ext4_features(mop);
+                /* start handle -O mkfs options */
+                if ((start = strstr(mop->mo_mkfsopts, "-O")) != NULL) {
+                        if (strstr(start + 2, "-O") != NULL) {
+                                fprintf(stderr,
+                                        "%s: don't specify multiple -O options\n",
+                                        progname);
+                                return EINVAL;
+                        }
+                        start = moveopts_to_end(start);
+                        maxbuflen = sizeof(mop->mo_mkfsopts) -
+                                    (start - mop->mo_mkfsopts) - strlen(start);
+                        enable_default_ext4_features(mop, start, maxbuflen, 1);
+                } else {
+                        start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts),
+                        maxbuflen = sizeof(mop->mo_mkfsopts) -
+                                    strlen(mop->mo_mkfsopts);
+                        enable_default_ext4_features(mop, start, maxbuflen, 0);
+                }
+                /* end handle -O mkfs options */
+
+                /* start handle -E mkfs options */
+                if ((start = strstr(mop->mo_mkfsopts, "-E")) != NULL) {
+                        if (strstr(start + 2, "-E") != NULL) {
+                                fprintf(stderr,
+                                        "%s: don't specify multiple -E options\n",
+                                        progname);
+                                return EINVAL;
+                        }
+                        start = moveopts_to_end(start);
+                        maxbuflen = sizeof(mop->mo_mkfsopts) -
+                                    (start - mop->mo_mkfsopts) - strlen(start);
+                        ext_opts = 1;
+                } else {
+                        start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts);
+                        maxbuflen = sizeof(mop->mo_mkfsopts) -
+                                    strlen(mop->mo_mkfsopts);
+                }
 
                 /* In order to align the filesystem metadata on 1MB boundaries,
                  * give a resize value that will reserve a power-of-two group
@@ -690,17 +802,17 @@ int make_lustre_backfs(struct mkfs_opts *mop)
                         unsigned resize_blks;
 
                         resize_blks = (1ULL<<32) - desc_per_block*group_blocks;
-                        snprintf(buf, sizeof(buf)," -E resize=%u,",resize_blks);
-                } else {
-                        strncpy(buf, " -E ", sizeof(buf));
+                        snprintf(buf, sizeof(buf), "%u", resize_blks);
+                        append_unique(start, ext_opts ? "," : " -E ",
+                                      "resize", buf, maxbuflen);
+                        ext_opts = 1;
                 }
 
                 /* Avoid zeroing out the full journal - speeds up mkfs */
                 if (is_e2fsprogs_feature_supp("-E lazy_journal_init") == 0)
-                        strscat(buf, "lazy_journal_init,", sizeof(buf));
-
-                if (strlen(buf) > strlen(" -E "))
-                        strscat(mop->mo_mkfsopts, buf,sizeof(mop->mo_mkfsopts));
+                        append_unique(start, ext_opts ? "," : " -E ",
+                                      "lazy_journal_init", NULL, maxbuflen);
+                /* end handle -E mkfs options */
 
                 /* Allow reformat of full devices (as opposed to
                    partitions.)  We already checked for mounted dev. */