Whamcloud - gitweb
LU-9324 lfs: add setstripe --yaml=template parameter 60/26860/34
authorBobi Jam <bobijam.xu@intel.com>
Tue, 25 Apr 2017 01:18:44 +0000 (09:18 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 3 Mar 2018 04:28:09 +0000 (04:28 +0000)
Add a "lfs setstripe --yaml=<yaml_template> <lustre_file_or_dir>"
usage to set stripe using stripe info from a YAML template file.

The YAML template file can be get from
$ lfs getstripe --yaml <lustre_file_or_dir>
and user can manually edit it to tweak stripe options.

This patch fixes two cyaml issues:
1. a YAML_BLOCK_ENTRY_TOKEN can follow a YAML_VALUE_TOKEN.
2. free_node() has memory leak, it needs to free
   cYAML::cy_valuestring and cYAML::cy_string if possible.

Test-Parameters: testlist=sanity-pfl,sanity-flr
Signed-off-by: Bobi Jam <bobijam.xu@intel.com>
Change-Id: I78149bb011fbc03387cbe3d057eb030550dd75ae
Reviewed-on: https://review.whamcloud.com/26860
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Emoly Liu <emoly.liu@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lnet/utils/lnetconfig/cyaml.c
lustre/doc/lfs-getstripe.1
lustre/doc/lfs-setstripe.1
lustre/doc/lfs.1
lustre/include/lustre/lustreapi.h
lustre/tests/sanity-flr.sh
lustre/tests/sanity-pfl.sh
lustre/utils/Makefile.am
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/liblustreapi_layout.c

index 0293be5..7c0ae4e 100644 (file)
@@ -590,7 +590,8 @@ static enum cYAML_handler_error yaml_entry_token(yaml_token_t *token,
        struct cYAML *obj;
 
        if (tree->state != TREE_STATE_SEQ_START &&
-           tree->state != TREE_STATE_BLK_STARTED)
+           tree->state != TREE_STATE_BLK_STARTED &&
+           tree->state != TREE_STATE_VALUE)
                return CYAML_ERROR_UNEXPECTED_STATE;
 
        if (tree->state == TREE_STATE_SEQ_START) {
@@ -678,6 +679,10 @@ static bool clean_usr_data(struct cYAML *node, void *usr_data, void **out)
 
 static bool free_node(struct cYAML *node, void *user_data, void **out)
 {
+       if (node->cy_type == CYAML_TYPE_STRING)
+               free(node->cy_valuestring);
+       if (node->cy_string)
+               free(node->cy_string);
        if (node)
                free(node);
 
index 46d3e6b..22d8ea8 100644 (file)
@@ -213,6 +213,9 @@ List information of components in a file with extent end less than 64MiB.
 .TP
 .B $ lfs getstripe -I3 --component-start /mnt/lustre/file1
 Print only the component start for the component with ID of 3
+.TP
+.B $ lfs getstripe --yaml /mnt/lustre/file1
+Lists the information of the components of a file in YAML format.
 .SH AUTHOR
 The lfs command is part of the Lustre filesystem.
 .SH SEE ALSO
index 98abce4..12b904b 100644 (file)
@@ -19,6 +19,8 @@ lfs setstripe \- set striping pattern of a file or directory default
 .br
 .B lfs setstripe -d \fR<\fIdirectory\fR>
 .br
+.B lfs setstripe --yaml=<yaml_template_file> <filename>
+.br
 .SH DESCRIPTION
 .TP
 .B lfs setstripe \fR[\fISTRIPE_OPTIONS\fR] <\fIdirectory\fR|\fIfilename\fR>
@@ -111,6 +113,13 @@ Delete the default layout on the specified directory.  It is not necessary
 to delete the default layout on a directory before replacing it.  This is
 only needed if the directory should revert from a directory-specific layout
 to using the global filesystem default layout stored on the root directory.
+.TP
+.B lfs setstripe --yaml=<yaml_template_file> <filename>
+.br
+Create a file with layout information specified by a YAML format template
+file, the template file can be obtained using the
+.B lfs getstripe --yaml <anotherfile>
+command.
 .SH STRIPE_OPTIONS
 The various stripe related options are listed and explained below:
 .TP
@@ -260,6 +269,11 @@ component with ID 1.
 .B $ lfs setstripe -E 1M -L mdt -E -1 /mnt/lustre/file1
 This created file with Data-on-MDT layout. The first 1M is placed on MDT and \
 rest of file is placed on OST with default striping.
+.TP
+.B $ lfs setstripe --yaml=/tmp/layout_yaml /mnt/lustre/file2
+This creates a file with layout specified by a layout template which can be \
+obtained with \fBlfs getstripe --yaml\fR command.
+
 .SH SEE ALSO
 .BR lfs (1),
 .BR lfs-migrate (1),
index 2c72790..29cd139 100644 (file)
@@ -126,6 +126,8 @@ lfs \- client utility for Lustre-specific file layout and other attributes
 .B lfs setstripe --component-del {--component-id|-I id |
      \fB--component-flags <flags>} <filename>
 .br
+.B lfs setstripe --yaml=<yaml_template_file> <filename>
+.br
 .B lfs --version
 .br
 .B lfs --list-commands
index 617ffcd..c6a15f3 100644 (file)
@@ -873,6 +873,10 @@ int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id);
  */
 int llapi_layout_comp_add(struct llapi_layout *layout);
 /**
+ * Adds a first component of a mirror to the existing composite layout.
+ */
+int llapi_layout_add_first_comp(struct llapi_layout *layout);
+/**
  * Deletes the current layout component from the composite layout.
  */
 int llapi_layout_comp_del(struct llapi_layout *layout);
index 3d87ba5..bdcb3bf 100644 (file)
@@ -1763,6 +1763,31 @@ test_44() {
 }
 run_test 44 "lfs mirror split check"
 
+test_45() {
+       [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs" && return
+
+       local file=$DIR/$tdir/$tfile
+       local dir=$DIR/$tdir/$dir
+       local temp=$DIR/$tdir/template
+       rm -rf $DIR/$tdir
+       test_mkdir $DIR/$tdir
+
+       $LFS setstripe -N -E1m -c2 -o0,1 -E2m -Eeof -N -E4m -Eeof \
+               -N -E3m -Eeof -N -E8m -Eeof $file || error "Create $file failed"
+
+       echo "getstripe --yaml $file"
+       $LFS getstripe --yaml $file > $temp || error "getstripe $file failed"
+       echo "setstripe --yaml=$temp $file.2"
+       $LFS setstripe --yaml=$temp $file.2 || error "setstripe $file.2 failed"
+
+       echo "compare layout"
+       local layout1=$(get_layout_param $file)
+       local layout2=$(get_layout_param $file.2)
+       [ "$layout1" == "$layout2" ] ||
+               error "FLR file $file/$file.2 layouts are not equal"
+}
+run_test 45 "Verify setstripe/getstripe with YAML with FLR file"
+
 ctrl_file=$(mktemp /tmp/CTRL.XXXXXX)
 lock_file=$(mktemp /var/lock/FLR.XXXXXX)
 
index 3f9083b..ca63b90 100644 (file)
@@ -636,6 +636,74 @@ test_15() {
 }
 run_test 15 "Verify component options for lfs find"
 
+verify_16() {
+       local src=$1
+       local dst=$2
+       local temp=$3
+       local msg_prefix=$4
+
+       echo "getstripe --yaml $src"
+       $LFS getstripe --yaml $src > $temp || error "getstripe $src failed"
+       echo "setstripe --yaml=$temp $dst"
+       $LFS setstripe --yaml=$temp $dst|| error "setstripe $dst failed"
+
+       echo "compare"
+       local layout1=$(get_layout_param $src)
+       local layout2=$(get_layout_param $dst)
+       # compare their layout info
+       [ "$layout1" == "$layout2" ] ||
+               error "$msg_prefix $src/$dst layouts are not equal"
+}
+
+test_16() {
+       [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs" && return
+
+       local file=$DIR/$tdir/$tfile
+       local dir=$DIR/$tdir/dir
+       local temp=$DIR/$tdir/template
+       rm -rf $DIR/$tdir
+       test_mkdir $DIR/$tdir
+
+       #####################################################################
+       #                           1. PFL file
+       # set stripe for source file
+       $LFS setstripe -E1m -c2 -o0,1 -E2m -c2 -E3m -o1,0 -E4m -c1 -E-1 $file ||
+               error "Create $file failed"
+
+       echo "1. PFL file"
+       verify_16 $file $file.copy $temp "1. PFL file"
+
+       #####################################################################
+       #                           2. plain file
+       # set stripe for source file
+       rm -f $file
+       $LFS setstripe -c2 -o0,1 -i1 $file || error "Create $file failed"
+
+       rm -f $file.copy
+       echo "2. plain file"
+       verify_16 $file $file.copy $temp "2. plain file"
+
+       #####################################################################
+       #                           3. PFL dir
+       # set stripe for source dir
+       test_mkdir $dir
+       $LFS setstripe -E1m -c2 -E2m -c1 -E-1 $dir ||
+               error "setstripe $dir failed"
+
+       test_mkdir $dir.copy
+       echo "3. PFL dir"
+       verify_16 $dir $dir.copy $temp.dir "3. PFL dir"
+
+       #####################################################################
+       #                           4. plain dir
+       # set stripe for source dir
+       $LFS setstripe -c2 -i-1 $dir || error "setstripe $dir failed"
+
+       echo "4. plain dir"
+       verify_16 $dir $dir.copy $temp.dir "4. plain dir"
+}
+run_test 16 "Verify setstripe/getstripe with YAML config file"
+
 test_17() {
        [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs" && return
        local file=$DIR/$tdir/$tfile
index 43ca575..2f1a301 100644 (file)
@@ -2,7 +2,6 @@
 
 AM_CFLAGS  := -fPIC -D_GNU_SOURCE \
              -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DLUSTRE_UTILS=1
-AM_LDFLAGS := -L$(top_builddir)/lnet/utils
 
 if TESTS
 EXTRA_PROGRAMS = wirecheck
@@ -61,6 +60,7 @@ lctl_DEPENDENCIES := liblustreapi.la
 
 lfs_SOURCES = lfs.c lfs_project.c lfs_project.h
 lfs_LDADD := liblustreapi.la -lz
+lfs_LDADD += $(top_builddir)/lnet/utils/lnetconfig/liblnetconfig.la
 lfs_DEPENDENCIES := liblustreapi.la
 
 lustre_rsync_SOURCES = lustre_rsync.c lustre_rsync.h callvpe.c callvpe.h
index 1020567..fbddb03 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/lustre/lustre_ver.h>
 #include <linux/lustre/lustre_param.h>
 #include <linux/lnet/nidstr.h>
+#include <cyaml.h>
 
 #ifndef ARRAY_SIZE
 # define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
@@ -160,7 +161,8 @@ static inline int lfs_mirror_split(int argc, char **argv)
        "                 [--stripe-size|-S <stripe_size>]\n"           \
        "                 [--layout|-L <pattern>]\n"            \
        "                 [--pool|-p <pool_name>]\n"                    \
-       "                 [--ost|-o <ost_indices>]\n"
+       "                 [--ost|-o <ost_indices>]\n"                   \
+       "                 [--yaml|-y <yaml_template_file>]\n"
 
 #define SSM_HELP_COMMON \
        "\tstripe_count: Number of OSTs to stripe over (0=fs default, -1 all)\n" \
@@ -180,7 +182,10 @@ static inline int lfs_mirror_split(int argc, char **argv)
        "\tcomp_end:     Extent end of component, start after previous end.\n"\
        "\t              Can be specified with K, M or G (for KB, MB, GB\n" \
        "\t              respectively, -1 for EOF). Must be a multiple of\n"\
-       "\t              stripe_size.\n"
+       "\t              stripe_size.\n"                                      \
+       "\tyaml_template_file:\n"                                             \
+       "\t              YAML layout template file, can't be used with -c,\n" \
+       "\t              -i, -S, -p, -o, or -E arguments.\n"
 
 #define MIRROR_CREATE_HELP                                                    \
        "\tmirror_count: Number of mirrors to be created with the upcoming\n"  \
@@ -1915,13 +1920,18 @@ struct lfs_setstripe_args {
        __u32                    lsa_comp_flags;
        __u32                    lsa_comp_neg_flags;
        unsigned long long       lsa_pattern;
+       unsigned int             lsa_mirror_count;
        int                      lsa_nr_tgts;
+       bool                     lsa_first_comp;
        __u32                   *lsa_tgts;
        char                    *lsa_pool_name;
 };
 
 static inline void setstripe_args_init(struct lfs_setstripe_args *lsa)
 {
+       unsigned int mirror_count = lsa->lsa_mirror_count;
+       bool first_comp = lsa->lsa_first_comp;
+
        memset(lsa, 0, sizeof(*lsa));
 
        lsa->lsa_stripe_size = LLAPI_LAYOUT_DEFAULT;
@@ -1929,6 +1939,9 @@ static inline void setstripe_args_init(struct lfs_setstripe_args *lsa)
        lsa->lsa_stripe_off = LLAPI_LAYOUT_DEFAULT;
        lsa->lsa_pattern = LLAPI_LAYOUT_RAID0;
        lsa->lsa_pool_name = NULL;
+
+       lsa->lsa_mirror_count = mirror_count;
+       lsa->lsa_first_comp = first_comp;
 }
 
 /**
@@ -1978,7 +1991,8 @@ static inline bool setstripe_args_specified(struct lfs_setstripe_args *lsa)
  * Return: 0 on success or an error code on failure.
  */
 static int comp_args_to_layout(struct llapi_layout **composite,
-                              struct lfs_setstripe_args *lsa)
+                              struct lfs_setstripe_args *lsa,
+                              bool set_extent)
 {
        struct llapi_layout *layout = *composite;
        uint64_t prev_end = 0;
@@ -2004,19 +2018,30 @@ static int comp_args_to_layout(struct llapi_layout **composite,
                        return rc;
                }
 
-               rc = llapi_layout_comp_add(layout);
+               if (lsa->lsa_first_comp)
+                       prev_end = 0;
+
+               if (lsa->lsa_first_comp)
+                       rc = llapi_layout_add_first_comp(layout);
+               else
+                       rc = llapi_layout_comp_add(layout);
                if (rc) {
                        fprintf(stderr, "Add component failed. %s\n",
                                strerror(errno));
                        return rc;
                }
        }
+       /* reset lsa_first_comp */
+       lsa->lsa_first_comp = false;
 
-       rc = llapi_layout_comp_extent_set(layout, prev_end, lsa->lsa_comp_end);
-       if (rc) {
-               fprintf(stderr, "Set extent [%lu, %llu) failed. %s\n",
-                       prev_end, lsa->lsa_comp_end, strerror(errno));
-               return rc;
+       if (set_extent) {
+               rc = llapi_layout_comp_extent_set(layout, prev_end,
+                                                 lsa->lsa_comp_end);
+               if (rc) {
+                       fprintf(stderr, "Set extent [%lu, %llu) failed. %s\n",
+                               prev_end, lsa->lsa_comp_end, strerror(errno));
+                       return rc;
+               }
        }
 
        /* Data-on-MDT component setting */
@@ -2106,7 +2131,7 @@ static int comp_args_to_layout(struct llapi_layout **composite,
                    lsa->lsa_stripe_count != LLAPI_LAYOUT_DEFAULT &&
                    lsa->lsa_stripe_count != LLAPI_LAYOUT_WIDE &&
                    lsa->lsa_nr_tgts != lsa->lsa_stripe_count) {
-                       fprintf(stderr, "stripe_count(%lld) != nr_osts(%d)\n",
+                       fprintf(stderr, "stripe_count(%lld) != nr_tgts(%d)\n",
                                lsa->lsa_stripe_count, lsa->lsa_nr_tgts);
                        return -EINVAL;
                }
@@ -2116,7 +2141,8 @@ static int comp_args_to_layout(struct llapi_layout **composite,
                        if (rc)
                                break;
                }
-       } else if (lsa->lsa_stripe_off != LLAPI_LAYOUT_DEFAULT) {
+       } else if (lsa->lsa_stripe_off != LLAPI_LAYOUT_DEFAULT &&
+                  lsa->lsa_stripe_off != -1) {
                rc = llapi_layout_ost_index_set(layout, 0, lsa->lsa_stripe_off);
        }
        if (rc) {
@@ -2128,6 +2154,140 @@ static int comp_args_to_layout(struct llapi_layout **composite,
        return 0;
 }
 
+static int build_component(struct llapi_layout **layout,
+                          struct lfs_setstripe_args *lsa, bool set_extent)
+{
+       int rc;
+
+       rc = comp_args_to_layout(layout, lsa, set_extent);
+       if (rc)
+               return rc;
+
+       if (lsa->lsa_mirror_count > 0) {
+               rc = llapi_layout_mirror_count_set(*layout,
+                                                  lsa->lsa_mirror_count);
+               if (rc)
+                       return rc;
+
+               rc = llapi_layout_flags_set(*layout, LCM_FL_RDONLY);
+               if (rc)
+                       return rc;
+               lsa->lsa_mirror_count = 0;
+       }
+
+       return rc;
+}
+
+static int build_layout_from_yaml_node(struct cYAML *node,
+                                      struct llapi_layout **layout,
+                                      struct lfs_setstripe_args *lsa,
+                                      __u32 *osts)
+{
+       char *string;
+       int rc = 0;
+
+       while (node) {
+               string = node->cy_string;
+               /* skip leading lmm_ if present, to simplify parsing */
+               if (string != NULL && strncmp(string, "lmm_", 4) == 0)
+                       string += 4;
+
+               if (node->cy_type == CYAML_TYPE_STRING) {
+                       if (!strcmp(string, "lcme_extent.e_end")) {
+                               if (!strcmp(node->cy_valuestring, "EOF") ||
+                                   !strcmp(node->cy_valuestring, "eof"))
+                                       lsa->lsa_comp_end = LUSTRE_EOF;
+                       } else if (!strcmp(string, "pool")) {
+                               lsa->lsa_pool_name = node->cy_valuestring;
+                       } else if (!strcmp(string, "pattern")) {
+                               if (!strcmp(node->cy_valuestring, "mdt"))
+                                       lsa->lsa_pattern = LLAPI_LAYOUT_MDT;
+                       }
+               } else if (node->cy_type == CYAML_TYPE_NUMBER) {
+                       if (!strcmp(string, "lcm_mirror_count")) {
+                               lsa->lsa_mirror_count = node->cy_valueint;
+                       } else if (!strcmp(string, "lcme_extent.e_start")) {
+                               if (node->cy_valueint != 0 || *layout != NULL) {
+                                       rc = build_component(layout, lsa, true);
+                                       if (rc)
+                                               return rc;
+                               }
+
+                               if (node->cy_valueint == 0)
+                                       lsa->lsa_first_comp = true;
+
+                               /* initialize lsa */
+                               setstripe_args_init(lsa);
+                               lsa->lsa_tgts = osts;
+                       } else if (!strcmp(string, "lcme_extent.e_end")) {
+                               if (node->cy_valueint == -1)
+                                       lsa->lsa_comp_end = LUSTRE_EOF;
+                               else
+                                       lsa->lsa_comp_end = node->cy_valueint;
+                       } else if (!strcmp(string, "stripe_count")) {
+                               lsa->lsa_stripe_count = node->cy_valueint;
+                       } else if (!strcmp(string, "stripe_size")) {
+                               lsa->lsa_stripe_size = node->cy_valueint;
+                       } else if (!strcmp(string, "stripe_offset")) {
+                               lsa->lsa_stripe_off = node->cy_valueint;
+                       } else if (!strcmp(string, "l_ost_idx")) {
+                               osts[lsa->lsa_nr_tgts] = node->cy_valueint;
+                               lsa->lsa_nr_tgts++;
+                       }
+               } else if (node->cy_type == CYAML_TYPE_OBJECT) {
+                       /* go deep to sub blocks */
+                       rc = build_layout_from_yaml_node(node->cy_child, layout,
+                                                        lsa, osts);
+                       if (rc)
+                               return rc;
+               }
+               node = node->cy_next;
+       }
+
+       return rc;
+}
+
+static int lfs_comp_create_from_yaml(char *template,
+                                    struct llapi_layout **layout,
+                                    struct lfs_setstripe_args *lsa,
+                                    __u32 *osts)
+{
+       struct cYAML *tree = NULL, *err_rc = NULL;
+       int rc = 0;
+
+       tree = cYAML_build_tree(template, NULL, 0, &err_rc, false);
+       if (!tree) {
+               fprintf(stderr, "%s: cannot parse YAML file %s\n",
+                       progname, template);
+               cYAML_build_error(-EINVAL, -1, "yaml", "from comp yaml",
+                                 "can't parse", &err_rc);
+               cYAML_print_tree2file(stderr, err_rc);
+               cYAML_free_tree(err_rc);
+               rc = -EINVAL;
+               goto err;
+       }
+
+       /* initialize lsa for plain file */
+       setstripe_args_init(lsa);
+       lsa->lsa_tgts = osts;
+
+       rc = build_layout_from_yaml_node(tree, layout, lsa, osts);
+       if (rc) {
+               fprintf(stderr, "%s: cannot build layout from YAML file %s.\n",
+                       progname, template);
+               goto err;
+       } else {
+               rc = build_component(layout, lsa, *layout != NULL);
+       }
+       /* clean clean lsa */
+       setstripe_args_init(lsa);
+
+err:
+       if (tree)
+               cYAML_free_tree(tree);
+       return rc;
+}
+
 /* In 'lfs setstripe --component-add' mode, we need to fetch the extent
  * end of the last component in the existing file, and adjust the
  * first extent start of the components to be added accordingly. */
@@ -2305,14 +2465,14 @@ enum {
 static int lfs_setstripe_internal(int argc, char **argv,
                                  enum setstripe_origin opc)
 {
-       struct lfs_setstripe_args        lsa;
+       struct lfs_setstripe_args        lsa = { 0 };
        struct llapi_stripe_param       *param = NULL;
        struct find_param                migrate_mdt_param = {
                .fp_max_depth = -1,
                .fp_mdt_index = -1,
        };
        char                            *fname;
-       int                              result;
+       int                              result = 0;
        int                              result2 = 0;
        char                            *end;
        int                              c;
@@ -2337,6 +2497,8 @@ static int lfs_setstripe_internal(int argc, char **argv,
        struct mirror_args              *last_mirror = NULL;
        __u16                            mirror_id = 0;
        char                             cmd[PATH_MAX];
+       bool from_yaml = false;
+       char *template = NULL;
 
        struct option long_opts[] = {
 /* find        { .val = 'A',   .name = "atime",        .has_arg = required_argument }*/
@@ -2410,7 +2572,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
 /* find        { .val = 'U',   .name = "user",         .has_arg = required_argument }*/
        /* --verbose is only valid in migrate mode */
        { .val = 'v',   .name = "verbose",      .has_arg = no_argument},
-/* getstripe { .val = 'y', .name = "yaml",     .has_arg = no_argument }, */
+       { .val = 'y',   .name = "yaml",         .has_arg = required_argument },
        { .name = NULL } };
 
        setstripe_args_init(&lsa);
@@ -2420,7 +2582,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
 
        snprintf(cmd, sizeof(cmd), "%s %s", progname, argv[0]);
        progname = cmd;
-       while ((c = getopt_long(argc, argv, "bc:dDE:f:i:I:m:N::no:p:L:s:S:v",
+       while ((c = getopt_long(argc, argv, "bc:dDE:f:i:I:m:N::no:p:L:s:S:vy:",
                                long_opts, NULL)) >= 0) {
                switch (c) {
                case 0:
@@ -2541,7 +2703,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        break;
                case 'E':
                        if (lsa.lsa_comp_end != 0) {
-                               result = comp_args_to_layout(lpp, &lsa);
+                               result = comp_args_to_layout(lpp, &lsa, true);
                                if (result) {
                                        fprintf(stderr,
                                                "%s %s: invalid layout\n",
@@ -2681,7 +2843,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                if (lsa.lsa_comp_end == 0)
                                        lsa.lsa_comp_end = LUSTRE_EOF;
 
-                               result = comp_args_to_layout(lpp, &lsa);
+                               result = comp_args_to_layout(lpp, &lsa, true);
                                if (result) {
                                        lfs_mirror_free(new_mirror);
                                        goto error;
@@ -2744,6 +2906,10 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        }
                        migrate_mdt_param.fp_verbose = VERBOSE_DETAIL;
                        break;
+               case 'y':
+                       from_yaml = true;
+                       template = optarg;
+                       break;
                default:
                        fprintf(stderr, "%s %s: unrecognized option '%s'\n",
                                progname, argv[0], argv[optind - 1]);
@@ -2773,7 +2939,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
        }
 
        if (lsa.lsa_comp_end != 0) {
-               result = comp_args_to_layout(lpp, &lsa);
+               result = comp_args_to_layout(lpp, &lsa, true);
                if (result)
                        goto error;
        }
@@ -2867,6 +3033,13 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        goto error;
        }
 
+       if (from_yaml && (setstripe_args_specified(&lsa) || layout != NULL)) {
+               fprintf(stderr, "error: %s: can't specify --yaml with "
+                       "-c, -S, -i, -o, -p or -E options.\n",
+                       argv[0]);
+               goto error;
+       }
+
        if (mdt_idx_arg != NULL && optind > 3) {
                fprintf(stderr,
                        "%s %s: option -m cannot be used with other options\n",
@@ -2943,6 +3116,18 @@ static int lfs_setstripe_internal(int argc, char **argv,
                }
        }
 
+       if (from_yaml) {
+               /* generate a layout from a YAML template */
+               result = lfs_comp_create_from_yaml(template, &layout,
+                                                  &lsa, osts);
+               if (result) {
+                       fprintf(stderr, "error: %s: can't create composite "
+                               "layout from template file %s\n",
+                               argv[0], template);
+                       goto error;
+               }
+       }
+
        for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) {
                if (mdt_idx_arg != NULL) {
                        result = llapi_migrate_mdt(fname, &migrate_mdt_param);
@@ -4404,7 +4589,7 @@ static int lfs_setdirstripe(int argc, char **argv)
 {
        char                    *dname;
        int                     result;
-       struct lfs_setstripe_args        lsa;
+       struct lfs_setstripe_args        lsa = { 0 };
        struct llapi_stripe_param       *param = NULL;
        __u32                   mdts[LMV_MAX_STRIPE_COUNT] = { 0 };
        char                    *end;
@@ -4434,6 +4619,7 @@ static int lfs_setdirstripe(int argc, char **argv)
        { .val = 't',   .name = "hash-type",    .has_arg = required_argument },
 #endif
        { .val = 'T',   .name = "mdt-count",    .has_arg = required_argument },
+/* setstripe { .val = 'y', .name = "yaml",     .has_arg = no_argument }, */
        { .name = NULL } };
 
        setstripe_args_init(&lsa);
index b3dd226..2c23a1a 100644 (file)
@@ -2580,7 +2580,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path,
                                     layout2name(lum->lmm_pattern));
                else
                        llapi_printf(LLAPI_MSG_NORMAL, "%x", lum->lmm_pattern);
-               separator = is_dir ? " " : "\n";
+               separator = (!yaml && is_dir) ? " " : "\n";
        }
 
        if ((verbose & VERBOSE_GENERATION) && !is_dir) {
@@ -2589,7 +2589,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path,
                        llapi_printf(LLAPI_MSG_NORMAL, "%s%slayout_gen:    ",
                                     space, prefix);
                llapi_printf(LLAPI_MSG_NORMAL, "%u",
-                            (int)lum->lmm_layout_gen);
+                            skip_objs ? 0 : (int)lum->lmm_layout_gen);
                separator = "\n";
        }
 
index 4b0adbd..d179a09 100644 (file)
@@ -1687,7 +1687,7 @@ int llapi_layout_comp_extent_set(struct llapi_layout *layout,
        if (comp->llc_list.prev != &layout->llot_comp_list) {
                prev = list_entry(comp->llc_list.prev, typeof(*prev),
                                  llc_list);
-               if (start != prev->llc_extent.e_end) {
+               if (start != 0 && start != prev->llc_extent.e_end) {
                        errno = EINVAL;
                        return -1;
                }
@@ -1696,7 +1696,8 @@ int llapi_layout_comp_extent_set(struct llapi_layout *layout,
        if (comp->llc_list.next != &layout->llot_comp_list) {
                next = list_entry(comp->llc_list.next, typeof(*next),
                                  llc_list);
-               if (end != next->llc_extent.e_start) {
+               if (next->llc_extent.e_start != 0 &&
+                   end != next->llc_extent.e_start) {
                        errno = EINVAL;
                        return -1;
                }
@@ -1875,6 +1876,37 @@ int llapi_layout_comp_add(struct llapi_layout *layout)
 
        return 0;
 }
+/**
+ * Adds a first component of a mirror to \a layout.
+ * The \a layout will change it's current component pointer to
+ * the newly added component, and it'll be turned into a composite
+ * layout if it was not before the adding.
+ *
+ * \param[in] layout           existing composite or plain layout
+ *
+ * \retval     0 on success
+ * \retval     <0 if error occurs
+ */
+int llapi_layout_add_first_comp(struct llapi_layout *layout)
+{
+       struct llapi_layout_comp *comp, *new;
+
+       comp = __llapi_layout_cur_comp(layout);
+       if (comp == NULL)
+               return -1;
+
+       new = __llapi_comp_alloc(0);
+       if (new == NULL)
+               return -1;
+
+       new->llc_extent.e_start = 0;
+
+       list_add_tail(&new->llc_list, &layout->llot_comp_list);
+       layout->llot_cur_comp = new;
+       layout->llot_is_composite = true;
+
+       return 0;
+}
 
 /**
  * Deletes current component from the composite layout. The component