" [--stripe-size|-S <stripe_size>]\n"\
" [--pool|-p <pool_name>]\n"\
" [--block|-b] "_tgt"\n"\
+ " [--ost-list|-o <ost_indices>]\n"\
"\tstripe_size: Number of bytes on each OST (0 filesystem default)\n"\
"\t Can be specified with k, m or g (in KB, MB and GB\n"\
"\t respectively)\n"\
"\tstart_ost_idx: OST index of first stripe (-1 default)\n"\
"\tstripe_count: Number of OSTs to stripe over (0 default, -1 all)\n"\
"\tpool_name: Name of OST pool to use (default none)\n"\
- "\tblock: Block file access during data migration"
+ "\tblock: Block file access during data migration\n"\
+ "\tost_indices: List of OST indices, can be repeated multiple times\n"\
+ "\t Indices be specified in a format of:\n"\
+ "\t -o <ost_1>,<ost_i>-<ost_j>,<ost_n>\n"\
+ "\t Or:\n"\
+ "\t -o <ost_1> -o <ost_i>-<ost_j> -o <ost_n>\n"\
+ "\t If --pool is set with --ost-list, then the OSTs\n"\
+ "\t must be the members of the pool."
/* all avaialable commands */
command_t cmdlist[] = {
goto out;
}
+retry:
rc = read(fd, gid, sz);
if (rc < sz) {
rc = -errno;
goto out;
}
+ /* gids must be non-zero */
+ if (*gid == 0)
+ goto retry;
+
out:
if (fd >= 0)
close(fd);
#define MIGRATION_BLOCKS 1
-static int lfs_migrate(char *name, unsigned long long stripe_size,
- int stripe_offset, int stripe_count,
- int stripe_pattern, char *pool_name,
- __u64 migration_flags)
+static int lfs_migrate(char *name, __u64 migration_flags,
+ struct llapi_stripe_param *param)
{
int fd, fdv;
char volatile_file[PATH_MAX +
/* create, open a volatile file, use caching (ie no directio) */
/* exclusive create is not needed because volatile files cannot
* conflict on name by construction */
- fdv = llapi_file_open_pool(volatile_file, O_CREAT | O_WRONLY,
- 0644, stripe_size, stripe_offset,
- stripe_count, stripe_pattern, pool_name);
+ fdv = llapi_file_open_param(volatile_file, O_CREAT | O_WRONLY, 0644,
+ param);
if (fdv < 0) {
rc = fdv;
fprintf(stderr, "cannot create volatile file in %s (%s)\n",
return rc;
}
+/**
+ * Parse a string containing an OST index list into an array of integers.
+ *
+ * The input string contains a comma delimited list of individual
+ * indices and ranges, for example "1,2-4,7". Add the indices into the
+ * \a osts array and remove duplicates.
+ *
+ * \param[out] osts array to store indices in
+ * \param[in] size size of \a osts array
+ * \param[in] offset starting index in \a osts
+ * \param[in] arg string containing OST index list
+ *
+ * \retval positive number of indices in \a osts
+ * \retval -EINVAL unable to parse \a arg
+ */
+static int parse_targets(__u32 *osts, int size, int offset, char *arg)
+{
+ int rc;
+ int nr = offset;
+ int slots = size - offset;
+ char *ptr = NULL;
+ bool end_of_loop;
+
+ if (arg == NULL)
+ return -EINVAL;
+
+ end_of_loop = false;
+ while (!end_of_loop) {
+ int start_index;
+ int end_index;
+ int i;
+ char *endptr = NULL;
+
+ rc = -EINVAL;
+
+ ptr = strchrnul(arg, ',');
+
+ end_of_loop = *ptr == '\0';
+ *ptr = '\0';
+
+ start_index = strtol(arg, &endptr, 0);
+ if (endptr == arg) /* no data at all */
+ break;
+ if (*endptr != '-' && *endptr != '\0') /* has invalid data */
+ break;
+ if (start_index < 0)
+ break;
+
+ end_index = start_index;
+ if (*endptr == '-') {
+ end_index = strtol(endptr + 1, &endptr, 0);
+ if (*endptr != '\0')
+ break;
+ if (end_index < start_index)
+ break;
+ }
+
+ for (i = start_index; i <= end_index && slots > 0; i++) {
+ int j;
+
+ /* remove duplicate */
+ for (j = 0; j < offset; j++) {
+ if (osts[j] == i)
+ break;
+ }
+ if (j == offset) { /* no duplicate */
+ osts[nr++] = i;
+ --slots;
+ }
+ }
+ if (slots == 0 && i < end_index)
+ break;
+
+ *ptr = ',';
+ arg = ++ptr;
+ offset = nr;
+ rc = 0;
+ }
+ if (!end_of_loop && ptr != NULL)
+ *ptr = ',';
+
+ return rc < 0 ? rc : nr;
+}
+
/* functions */
static int lfs_setstripe(int argc, char **argv)
{
- char *fname;
- int result;
- unsigned long long st_size;
- int st_offset, st_count;
- char *end;
- int c;
- int delete = 0;
- char *stripe_size_arg = NULL;
- char *stripe_off_arg = NULL;
- char *stripe_count_arg = NULL;
- char *pool_name_arg = NULL;
- unsigned long long size_units = 1;
- int migrate_mode = 0;
- __u64 migration_flags = 0;
+ struct llapi_stripe_param *param;
+ char *fname;
+ int result;
+ unsigned long long st_size;
+ int st_offset, st_count;
+ char *end;
+ int c;
+ int delete = 0;
+ char *stripe_size_arg = NULL;
+ char *stripe_off_arg = NULL;
+ char *stripe_count_arg = NULL;
+ char *pool_name_arg = NULL;
+ unsigned long long size_units = 1;
+ bool migrate_mode = false;
+ __u64 migration_flags = 0;
+ __u32 osts[LOV_MAX_STRIPE_COUNT] = { 0 };
+ int nr_osts = 0;
struct option long_opts[] = {
/* valid only in migrate mode */
#endif
{"stripe-index", required_argument, 0, 'i'},
{"stripe_index", required_argument, 0, 'i'},
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 53, 0)
- /* This formerly implied "stripe-index", but was confusing
- * with "file offset" (which will eventually be needed for
- * with different layouts by offset), so deprecate it. */
- {"offset", required_argument, 0, 'o'},
-#endif
+ {"ost-list", required_argument, 0, 'o'},
+ {"ost_list", required_argument, 0, 'o'},
{"pool", required_argument, 0, 'p'},
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 53, 0)
/* This formerly implied "--stripe-size", but was confusing
{0, 0, 0, 0}
};
- st_size = 0;
- st_offset = -1;
- st_count = 0;
+ st_size = 0;
+ st_offset = -1;
+ st_count = 0;
if (strcmp(argv[0], "migrate") == 0)
- migrate_mode = 1;
+ migrate_mode = true;
optind = 0;
while ((c = getopt_long(argc, argv, "c:di:o:p:s:S:",
/* Long options. */
break;
case 'b':
- if (migrate_mode == 0) {
+ if (!migrate_mode) {
fprintf(stderr, "--block is valid only for"
" migrate mode");
return CMD_HELP;
/* delete the default striping pattern */
delete = 1;
break;
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 53, 0)
case 'o':
- fprintf(stderr, "warning: '--offset|-o' deprecated, "
- "use '--stripe-index|-i' instead\n");
-#endif
+ nr_osts = parse_targets(osts, ARRAY_SIZE(osts), nr_osts,
+ optarg);
+ if (nr_osts < 0) {
+ fprintf(stderr,
+ "error: %s: bad OST indices '%s'\n",
+ argv[0], optarg);
+ return CMD_HELP;
+ }
+
+ if (st_offset == -1) /* first in the command line */
+ st_offset = osts[0];
+ break;
case 'i':
#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 53, 0)
if (strcmp(argv[optind - 1], "--index") == 0)
}
}
+ /* initialize stripe parameters */
+ param = calloc(1, offsetof(typeof(*param), lsp_osts[nr_osts]));
+ if (param == NULL) {
+ fprintf(stderr, "error: %s: run out of memory\n", argv[0]);
+ return CMD_HELP;
+ }
+
+ param->lsp_stripe_size = st_size;
+ param->lsp_stripe_offset = st_offset;
+ param->lsp_stripe_count = st_count;
+ param->lsp_stripe_pattern = 0;
+ param->lsp_pool = pool_name_arg;
+ param->lsp_is_specific = false;
+ if (nr_osts > 0) {
+ if (st_count > 0 && nr_osts != st_count) {
+ fprintf(stderr, "error: %s: stripe count '%d' doesn't "
+ "match the number of OSTs: %d\n",
+ argv[0], st_count, nr_osts);
+ return CMD_HELP;
+ }
+
+ param->lsp_is_specific = true;
+ param->lsp_stripe_count = nr_osts;
+ memcpy(param->lsp_osts, osts, sizeof(*osts) * nr_osts);
+ }
+
do {
- if (migrate_mode)
- result = lfs_migrate(fname, st_size, st_offset,
- st_count, 0, pool_name_arg,
- migration_flags);
- else
- result = llapi_file_create_pool(fname, st_size,
- st_offset, st_count,
- 0, pool_name_arg);
+ if (!migrate_mode) {
+ result = llapi_file_open_param(fname,
+ O_CREAT | O_WRONLY,
+ 0644, param);
+ if (result >= 0) {
+ close(result);
+ result = 0;
+ }
+ } else {
+ result = lfs_migrate(fname, migration_flags, param);
+ }
if (result) {
fprintf(stderr,
"error: %s: %s stripe file '%s' failed\n",
fname = argv[++optind];
} while (fname != NULL);
+ free(param);
return result;
}
if (rc == -ENODEV)
break;
+ if (rc == -EAGAIN)
+ continue;
+
if (poolname && tp->st_op == LL_STATFS_LOV &&
llapi_search_ost(fsname, poolname,
obd_uuid2str(&uuid_buf)) != 1)
printf(" s="DFID" sp="DFID" %.*s",
PFID(&rnm->cr_sfid),
PFID(&rnm->cr_spfid),
- changelog_rec_snamelen(rec),
+ (int)changelog_rec_snamelen(rec),
changelog_rec_sname(rec));
}
printf("\n");