Whamcloud - gitweb
LU-16446 utils: specify total count for mirror extend 67/55867/11
authorFrederick Dilger <fdilger@whamcloud.com>
Wed, 24 Jul 2024 21:59:36 +0000 (15:59 -0600)
committerOleg Drokin <green@whamcloud.com>
Mon, 2 Dec 2024 05:46:43 +0000 (05:46 +0000)
The 'lfs mirror extend -N' can now be used to specify the total
number of mirrors to create on a file by using '=' infront of the
COUNT:
    'lfs mirror extend -N=TOTAL_COUNT'
or
    'lfs mirror extend --mirror-count==TOTAL_COUNT'

This is a no-op if the specified number of mirrors already exists on
that file.

Signed-off-by: Frederick Dilger <fdilger@whamcloud.com>
Change-Id: I76fc416b4dc2c37edf99926bae9a8d42167a49ab
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55867
Reviewed-by: Alexandre Ioffe <aioffe@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/doc/lfs-mirror-extend.1
lustre/include/lustre/lustreapi.h
lustre/tests/sanity-flr.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index fe1943c..572f5d8 100644 (file)
@@ -19,12 +19,21 @@ The file \fIFILENAME\fR can already be a mirrored file, or just a regular
 non-mirrored file. If it's a non-mirrored file, then the command will convert it
 to a mirrored file.
 .br
-The \fB\-\-mirror\-count\fR|\fB\-N\fR option is optional and indicates how many
+The
+.BR --mirror-count | -N
+option is optional and indicates how many
 mirrors that have the same layout will be added. It can be repeated multiple
 times to separate mirrors that have different layouts. The \fIMIRROR_COUNT\fR
-argument is optional and defaults to 1 if it's not specified; if specified, it
-must follow the option without a space. If \fB\-\-mirror\-count\fR|\fB\-N\fR is
-not specified, the default value of 1 will be used.
+can be specified with a preceding '=' to indicate the number of total mirrors
+desired for the layout, such as
+\fB\-\-mirror\-count\fR==\fITOTAL_MIRROR_COUNT\fR or
+\fB\-N\fR=\fITOTAL_MIRROR_COUNT\fR. This will create mirrors until the total
+number of mirrors in the layout match \fITOTAL_MIRROR_COUNT\fR, this also means
+that if there are already at least \fITOTAL_MIRROR_COUNT\fR mirrors in the
+layout then no new mirrors will be created. The \fIMIRROR_COUNT\fR argument is
+optional and defaults to 1 if it's not specified; if specified, it must follow
+the option without a space. If \fB\-\-mirror\-count\fR|\fB\-N\fR is not
+specified, the default value of 1 will be used.
 .br
 The \fISETSTRIPE_OPTIONS\fR specify the specific layout for the mirror. It can
 be a plain layout with specific striping pattern or a composite layout like
index 9791584..2a799d4 100644 (file)
@@ -176,6 +176,7 @@ int llapi_file_get_stripe(const char *path, struct lov_user_md *lum);
 int llapi_file_lookup(int dirfd, const char *name);
 void llapi_set_command_name(const char *cmd);
 void llapi_clear_command_name(void);
+int llapi_get_lmm_from_path(const char *path, struct lov_user_md_v1 **lmmbuf);
 
 enum llapi_layout_verbose  {
        VERBOSE_STRIPE_COUNT    =      0x1,
index e2e22ec..69778e5 100644 (file)
@@ -312,8 +312,6 @@ test_0a() {
        # create parent directory
        mkdir $td || error "mkdir $td failed"
 
-       $mirror_cmd $tf &> /dev/null && error "miss -N option"
-
        $mirror_cmd -N $tf || error "create mirrored file $tf failed"
        verify_mirror_count $tf 1
        id=$($LFS getstripe -I $tf)
index 786062d..bbb4284 100755 (executable)
@@ -193,24 +193,6 @@ static inline int lfs_mirror_create(int argc, char **argv)
 
 static inline int lfs_mirror_extend(int argc, char **argv)
 {
-       int i;
-
-       for (i = 0; i < argc; i++)
-               if (strstr(argv[i], "-N") ||
-                   strstr(argv[i], "--mirror-count"))
-                       break;
-
-       /* add -N if not specified */
-       if (i == argc) {
-               char *tmp[argc + 1];
-
-               tmp[0] = argv[0]; /* extend */
-               tmp[1] = "-N";
-               memcpy(tmp + 2, argv + 1, (argc - 1) * sizeof(*argv));
-
-               return lfs_setstripe_internal(argc + 1, tmp, SO_MIRROR_EXTEND);
-       }
-
        return lfs_setstripe_internal(argc, argv, SO_MIRROR_EXTEND);
 }
 
@@ -283,11 +265,10 @@ command_t mirror_cmdlist[] = {
        },
        { .pc_name = "extend", .pc_func = lfs_mirror_extend,
          .pc_help = "Extend a mirrored file.\n"
-               "Usage: lfs mirror extend "
-               "--mirror-count|-N[MIRROR_COUNT] [--no-verify]|\n"
-               "\t\t[--stats|--stats-interval=STATS_INTERVAL]|\n"
+"Usage: lfs mirror extend [--mirror-count|-N[MIRROR_COUNT]]\n"
+               "\t\t[--no-verify] [--stats|--stats-interval=STATS_INTERVAL]\n"
                "\t\t[--bandwidth-limit|--W BANDWIDTH]\n"
-               "\t\t[[-f VICTIM_FILE] |\n"
+               "\t\t[-f VICTIM_FILE]\n"
                "\t\t" SSM_SETSTRIPE_OPT "]"
                " FILENAME ...\n" },
        { .pc_name = "split", .pc_func = lfs_mirror_split,
@@ -3647,7 +3628,7 @@ enum {
        LFS_STATS_INTERVAL_OPT,
        LFS_LINKS_OPT,
        LFS_ATTRS_OPT,
-       LFS_XATTRS_MATCH_OPT
+       LFS_XATTRS_MATCH_OPT,
 };
 
 #ifndef LCME_USER_MIRROR_FLAGS
@@ -3659,39 +3640,40 @@ enum {
 static int lfs_setstripe_internal(int argc, char **argv,
                                  enum setstripe_origin opc)
 {
-       struct lfs_setstripe_args        lsa = { 0 };
-       struct llapi_stripe_param       *param = NULL;
-       struct find_param                migrate_mdt_param = {
+       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 = 0;
-       int                              result2 = 0;
-       char                            *end;
-       int                              c;
-       int                              delete = 0;
-       unsigned long long               size_units = 1;
-       bool                             migrate_mode = false;
-       bool                             migrate_mdt_mode = false;
-       bool                             setstripe_mode = false;
-       bool                             migration_block = false;
-       __u64                            migration_flags = 0;
-       __u32                            tgts[LOV_MAX_STRIPE_COUNT] = { 0 };
-       int                              comp_del = 0, comp_set = 0;
-       int                              comp_add = 0;
-       __u32                            comp_id = 0;
-       struct llapi_layout             *layout = NULL;
-       struct llapi_layout             **lpp = &layout;
-       bool                             mirror_mode = false;
-       bool                             has_m_file = false;
-       __u32                            mirror_count = 0;
-       enum mirror_flags                mirror_flags = 0;
-       struct mirror_args              *mirror_list = NULL;
-       struct mirror_args              *new_mirror = NULL;
-       struct mirror_args              *last_mirror = NULL;
-       __u16                            mirror_id = 0;
-       char                             cmd[PATH_MAX];
+       char *fname;
+       int result = 0;
+       int result2 = 0;
+       char *end;
+       int c;
+       int delete = 0;
+       unsigned long long size_units = 1;
+       bool migrate_mode = false;
+       bool migrate_mdt_mode = false;
+       bool setstripe_mode = false;
+       bool migration_block = false;
+       __u64 migration_flags = 0;
+       __u32 tgts[LOV_MAX_STRIPE_COUNT] = { 0 };
+       int comp_del = 0, comp_set = 0;
+       int comp_add = 0;
+       __u32 comp_id = 0;
+       struct llapi_layout *layout = NULL;
+       struct llapi_layout **lpp = &layout;
+       bool mirror_mode = false;
+       bool mirror_total_mode = false;
+       bool has_m_file = false;
+       __u32 mirror_count = 0;
+       enum mirror_flags mirror_flags = 0;
+       struct mirror_args *mirror_list = NULL;
+       struct mirror_args *new_mirror = NULL;
+       struct mirror_args *last_mirror = NULL;
+       __u16 mirror_id = 0;
+       char cmd[PATH_MAX];
        bool from_yaml = false;
        bool from_copy = false;
        char *template = NULL;
@@ -4189,12 +4171,18 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        migration_flags |= LLAPI_MIGRATION_NONBLOCK;
                        break;
                case 'N':
+create_mirror:
                        if (opc == SO_SETSTRIPE) {
                                opc = SO_MIRROR_CREATE;
                                mirror_mode = true;
                        }
+                       mirror_total_mode = false;
                        mirror_count = 1;
                        if (optarg) {
+                               if (optarg[0] == '=') {
+                                       mirror_total_mode = true;
+                                       optarg++; /* skip '=' */
+                               }
                                errno = 0;
                                mirror_count = strtoul(optarg, &end, 0);
                                if (errno != 0 || *end != '\0' ||
@@ -4208,6 +4196,32 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                }
                        }
 
+                       if (mirror_total_mode) {
+                               char *path = argv[argc-1];
+                               struct lov_comp_md_v1 *comp_v1;
+
+                               result = llapi_get_lmm_from_path(path, (struct lov_user_md_v1 **)&comp_v1);
+                               if (result) {
+                                       fprintf(stderr,
+                                               "error: %s: cannot get layout from %s: %s\n",
+                                               progname, path, strerror(-result));
+                                       goto error;
+                               }
+
+                               if (comp_v1->lcm_mirror_count >= mirror_count)
+                                       mirror_count = 0;
+                               else
+                                       mirror_count -= comp_v1->lcm_mirror_count;
+
+                               if (!mirror_count) {
+                                       fprintf(stderr,
+                                               "warning: the file '%s' already has %d mirrors. No new mirrors will be created\n",
+                                               path,
+                                               comp_v1->lcm_mirror_count);
+                                       break;
+                               }
+                       }
+
                        new_mirror = lfs_mirror_alloc();
                        new_mirror->m_count = mirror_count;
 
@@ -4382,15 +4396,9 @@ static int lfs_setstripe_internal(int argc, char **argv,
                return CMD_HELP;
        }
 
-       if (mirror_mode && mirror_count == 0) {
-               fprintf(stderr,
-                       "error: %s: --mirror-count|-N option is required\n",
-                       progname);
-               result = -EINVAL;
-               goto error;
-       }
-
-       if (mirror_mode) {
+       if (mirror_mode && (!mirror_total_mode || mirror_count)) {
+               if (mirror_count == 0)
+                       goto create_mirror;
                if (!setstripe_args_specified(&lsa))
                        last_mirror->m_inherit = true;
                if (lsa.lsa_comp_end == 0)
index d0b5eb4..acc252e 100644 (file)
@@ -1950,6 +1950,39 @@ retry_getfileinfo:
        return ret;
 }
 
+/**
+ * Get the mirror layout info from a file.
+ *
+ * \param path [in]            a string containing the file path
+ * \param lmmbuf [out]         pointer to an lov_user_md_v1 buffer
+ *                             that will be set with the mirror layout info
+ *                             from the file specified by \a path.
+ *
+ * \retval 0                   success
+ * \retval -errno              on error
+ */
+int llapi_get_lmm_from_path(const char *path, struct lov_user_md_v1 **lmmbuf)
+{
+       size_t lmmlen;
+       int p = -1;
+       int rc = 0;
+
+       lmmlen = get_mds_md_size(path);
+       if (lmmlen < 0)
+               return -EINVAL;
+
+       p = open_parent(path);
+
+       *lmmbuf = calloc(1, lmmlen);
+       if (*lmmbuf == NULL)
+               return -errno;
+
+       rc = get_lmd_info_fd(path, p, 0, *lmmbuf, lmmlen, GET_LMD_STRIPE);
+       if (p != -1)
+               close(p);
+       return rc;
+}
+
 static int llapi_semantic_traverse(char *path, int size, int parent,
                                   semantic_func_t sem_init,
                                   semantic_func_t sem_fini, void *data,