#define SSM_CMD_COMMON(cmd) \
"usage: "cmd" [--component-end|-E <comp_end>]\n" \
" [--stripe-count|-c <stripe_count>]\n" \
+ " [--overstripe-count|-C <stripe_count>]\n" \
" [--stripe-index|-i <start_ost_idx>]\n" \
" [--stripe-size|-S <stripe_size>]\n" \
" [--layout|-L <pattern>]\n" \
#define SSM_HELP_COMMON \
"\tstripe_count: Number of OSTs to stripe over (0=fs default, -1 all)\n" \
+ "\t Using -C instead of -c allows overstriping, which\n" \
+ "\t will place more than one stripe per OST if\n" \
+ "\t stripe_count is greater than the number of OSTs\n" \
"\tstart_ost_idx: OST index of first stripe (-1=default round robin)\n"\
"\tstripe_size: Number of bytes on each OST (0=fs default)\n" \
"\t Can be specified with K, M or G (for KB, MB, GB\n" \
"\tmdt_hash: hash type of the striped directory. mdt types:\n" \
" fnv_1a_64 FNV-1a hash algorithm (default)\n" \
" all_char sum of characters % MDT_COUNT (not recommended)\n" \
+ " space create subdirectories with balanced space usage\n" \
"\tdefault_stripe: set default dirstripe of the directory\n" \
- "\tmode: the file access permission of the directory (octal)\n"
+ "\tmode: the file access permission of the directory (octal)\n" \
+ "To create dir with a foreign (free format) layout :\n" \
+ "setdirstripe|mkdir --foreign[=<foreign_type>] -x|-xattr <string> " \
+ "[--mode|-m mode] [--flags <hex>] <dir>\n" \
+ "\tmode: the mode of the directory\n" \
+ "\tforeign_type: none or daos\n"
/**
* command_t mirror_cmdlist - lfs mirror commands.
"To create a file with specified striping/composite layout, or\n"
"create/replace the default layout on an existing directory:\n"
SSM_CMD_COMMON("setstripe")
+ " [--mode <mode>]\n"
" <directory|filename>\n"
" or\n"
"To add component(s) to an existing composite file:\n"
"\tcomp_id: Unique component ID to delete\n"
"\tcomp_flags: 'init' indicating all instantiated components\n"
"\t '^init' indicating all uninstantiated components\n"
- "\t-I and -F cannot be specified at the same time\n"},
+ "\t-I and -F cannot be specified at the same time\n"
+ "To create a file with a foreign (free format) layout:\n"
+ "usage: setstripe --foreign[=<foreign_type>]\n"
+ " --xattr|-x <layout_string> [--flags <hex>]\n"
+ " [--mode <mode>] <filename>\n"},
{"getstripe", lfs_getstripe, 0,
"To list the layout pattern for a given file or files in a\n"
"directory or recursively for all files in a directory tree.\n"
"usage: getdirstripe [--mdt-count|-c] [--mdt-index|-m|-i]\n"
" [--mdt-hash|-H] [--obd|-O <uuid>]\n"
" [--recursive|-r] [--yaml|-y]\n"
- " [--default|-D] <dir> ..."},
+ " [--verbose|-v] [--default|-D] <dir> ..."},
{"mkdir", lfs_setdirstripe, 0,
"To create a striped directory on a specified MDT. This can only\n"
"be done on MDT0 with the right of administrator.\n"
" [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
" [[!] --uid|-u|--user|-U <uid>|<uname>] [[!] --pool <pool>]\n"
" [[!] --projid <projid>]\n"
+ " [[!] --foreign[=<foreign_type>]]\n"
" [[!] --layout|-L released,raid0,mdt]\n"
+ " [[!] --foreign[=<foreign_type>]]\n"
" [[!] --component-count [+-]<comp_cnt>]\n"
" [[!] --component-start [+-]N[kMGTPE]]\n"
" [[!] --component-end|-E [+-]N[kMGTPE]]\n"
"\thashtype: hash type of the striped directory.\n"
"\t fnv_1a_64 FNV-1a hash algorithm\n"
"\t all_char sum of characters % MDT_COUNT\n"},
- {"check", lfs_check, 0,
+ {"check", lfs_check, 0,
"Display the status of MGTs, MDTs or OSTs (as specified in the command)\n"
"or all the servers (MGTs, MDTs and OSTs).\n"
"usage: check <mgts|osts|mdts|all>"},
- {"osts", lfs_osts, 0, "list OSTs connected to client "
- "[for specified path only]\n" "usage: osts [path]"},
- {"mdts", lfs_mdts, 0, "list MDTs connected to client "
- "[for specified path only]\n" "usage: mdts [path]"},
- {"df", lfs_df, 0,
- "report filesystem disk space usage or inodes usage"
- "of each MDS and all OSDs or a batch belonging to a specific pool .\n"
- "Usage: df [-i] [-h] [--lazy|-l] [--pool|-p <fsname>[.<pool>] [path]"},
- {"getname", lfs_getname, 0, "list instances and specified mount points "
- "[for specified path only]\n"
- "Usage: getname [-h]|[path ...] "},
+ {"osts", lfs_osts, 0, "list OSTs connected to client "
+ "[for specified path only]\n" "usage: osts [path]"},
+ {"mdts", lfs_mdts, 0, "list MDTs connected to client "
+ "[for specified path only]\n" "usage: mdts [path]"},
+ {"df", lfs_df, 0,
+ "report filesystem disk space usage or inodes usage "
+ "of each MDS and all OSDs or a batch belonging to a specific pool.\n"
+ "Usage: df [-i] [-h] [--lazy|-l] [--pool|-p <fsname>[.<pool>] [path]"},
+ {"getname", lfs_getname, 0,
+ "list instances and specified mount points [for specified path only]\n"
+ "Usage: getname [--help|-h] [--instance|-i] [--fsname|-n] [path ...]"},
#ifdef HAVE_SYS_QUOTA_H
- {"setquota", lfs_setquota, 0, "Set filesystem quotas.\n"
+ {"setquota", lfs_setquota, 0, "Set filesystem quotas.\n"
"usage: setquota <-u|-g|-p> <uname>|<uid>|<gname>|<gid>|<projid>\n"
- " -b <block-softlimit> -B <block-hardlimit>\n"
- " -i <inode-softlimit> -I <inode-hardlimit> <filesystem>\n"
+ " -b <block-softlimit> -B <block-hardlimit>\n"
+ " -i <inode-softlimit> -I <inode-hardlimit> <filesystem>\n"
" setquota <-u|--user|-g|--group|-p|--projid> <uname>|<uid>|<gname>|<gid>|<projid>\n"
" [--block-softlimit <block-softlimit>]\n"
" [--block-hardlimit <block-hardlimit>]\n"
"layout\nto another (may be not safe with concurent writes).\n"
"usage: migrate "
"[--stripe-count|-c] <stripe_count>\n"
+ "[--overstripe-count|-C] <stripe_count>\n"
" [--stripe-index|-i] <start_ost_index>\n"
" [--stripe-size|-S] <stripe_size>\n"
" [--pool|-p] <pool_name>\n"
" [--non-direct|-D]\n"
" <file|directory>\n"
"\tstripe_count: number of OSTs to stripe a file over\n"
+ "\t Using -C instead of -c allows overstriping, which\n"
+ "\t will place more than one stripe per OST if\n"
+ "\t stripe_count is greater than the number of OSTs\n"
"\tstripe_ost_index: index of the first OST to stripe a file over\n"
"\tstripe_size: number of bytes to store before moving to the next OST\n"
"\tpool_name: name of the predefined pool of OSTs\n"
return 0;
}
+static uint32_t check_foreign_type_name(const char *foreign_type_name)
+{
+ uint32_t i;
+
+ for (i = 0; i < LU_FOREIGN_TYPE_UNKNOWN; i++) {
+ if (lu_foreign_types[i].lft_name == NULL)
+ break;
+ if (strcmp(foreign_type_name,
+ lu_foreign_types[i].lft_name) == 0)
+ return lu_foreign_types[i].lft_type;
+ }
+
+ return LU_FOREIGN_TYPE_UNKNOWN;
+}
static const char *error_loc = "syserror";
* indices and ranges, for example "1,2-4,7". Add the indices into the
* \a tgts array and remove duplicates.
*
- * \param[out] tgts array to store indices in
- * \param[in] size size of \a tgts array
- * \param[in] offset starting index in \a tgts
- * \param[in] arg string containing OST index list
+ * \param[out] tgts array to store indices in
+ * \param[in] size size of \a tgts array
+ * \param[in] offset starting index in \a tgts
+ * \param[in] arg string containing OST index list
+ * \param[in/out] overstriping index list may contain duplicates
*
* \retval positive number of indices in \a tgts
* \retval -EINVAL unable to parse \a arg
*/
-static int parse_targets(__u32 *tgts, int size, int offset, char *arg)
+static int parse_targets(__u32 *tgts, int size, int offset, char *arg,
+ unsigned long long *pattern)
{
int rc;
int nr = offset;
int slots = size - offset;
char *ptr = NULL;
+ bool overstriped = false;
bool end_of_loop;
if (arg == NULL)
end_of_loop = false;
while (!end_of_loop) {
- int start_index;
- int end_index;
+ int start_index = 0;
+ int end_index = 0;
int i;
char *endptr = NULL;
/* remove duplicate */
for (j = 0; j < offset; j++) {
- if (tgts[j] == i)
- break;
+ if (tgts[j] == i && pattern &&
+ *pattern == LLAPI_LAYOUT_OVERSTRIPING)
+ overstriped = true;
+ else if (tgts[j] == i)
+ return -EINVAL;
}
- if (j == offset) { /* no duplicate */
+
+ j = offset;
+
+ if (j == offset) { /* check complete */
tgts[nr++] = i;
--slots;
}
}
+
if (slots == 0 && i < end_index)
break;
if (!end_of_loop && ptr != NULL)
*ptr = ',';
+ if (!overstriped && pattern)
+ *pattern = LLAPI_LAYOUT_DEFAULT;
+
return rc < 0 ? rc : nr;
}
}
/* Data-on-MDT component has always single stripe up to end */
lsa->lsa_stripe_size = lsa->lsa_comp_end;
+ } else if (lsa->lsa_pattern == LLAPI_LAYOUT_OVERSTRIPING) {
+ rc = llapi_layout_pattern_set(layout, lsa->lsa_pattern);
+ if (rc) {
+ fprintf(stderr, "Set stripe pattern %#llx failed. %s\n",
+ lsa->lsa_pattern, strerror(errno));
+ return rc;
+ }
}
rc = llapi_layout_stripe_size_set(layout, lsa->lsa_stripe_size);
} else if (!strcmp(string, "pattern")) {
if (!strcmp(node->cy_valuestring, "mdt"))
lsa->lsa_pattern = LLAPI_LAYOUT_MDT;
+ if (!strcmp(node->cy_valuestring,
+ "raid0,overstriped"))
+ lsa->lsa_pattern =
+ LLAPI_LAYOUT_OVERSTRIPING;
} else if (!strcmp(string, "lcme_flags")) {
rc = comp_str2flags(node->cy_valuestring,
&lsa->lsa_comp_flags,
LFS_COMP_ADD_OPT,
LFS_COMP_NO_VERIFY_OPT,
LFS_PROJID_OPT,
- LFS_MIRROR_FLAGS_OPT,
+ LFS_LAYOUT_FLAGS_OPT, /* used for mirror and foreign flags */
LFS_MIRROR_ID_OPT,
LFS_MIRROR_STATE_OPT,
LFS_LAYOUT_COPY,
LFS_MIRROR_INDEX_OPT,
+ LFS_LAYOUT_FOREIGN_OPT,
+ LFS_MODE_OPT,
};
/* functions */
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 };
bool from_yaml = false;
bool from_copy = false;
char *template = NULL;
+ bool foreign_mode = false;
+ char *xattr = NULL;
+ uint32_t type = LU_FOREIGN_TYPE_NONE, flags = 0;
+ char *mode_opt = NULL;
+ mode_t previous_umask = 0;
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
struct option long_opts[] = {
/* find { .val = '0', .name = "null", .has_arg = no_argument }, */
.has_arg = no_argument},
{ .val = LFS_COMP_NO_VERIFY_OPT,
.name = "no-verify", .has_arg = no_argument},
- { .val = LFS_MIRROR_FLAGS_OPT,
+ { .val = LFS_LAYOUT_FLAGS_OPT,
.name = "flags", .has_arg = required_argument},
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
{ .val = LFS_MIRROR_ID_OPT,
.name = "mirror-id", .has_arg = required_argument},
+ { .val = LFS_MODE_OPT,
+ .name = "mode", .has_arg = required_argument},
{ .val = LFS_LAYOUT_COPY,
.name = "copy", .has_arg = required_argument},
{ .val = 'c', .name = "stripe-count", .has_arg = required_argument},
{ .val = 'c', .name = "stripe_count", .has_arg = required_argument},
{ .val = 'c', .name = "mdt-count", .has_arg = required_argument},
-/* find { .val = 'C', .name = "ctime", .has_arg = required_argument }*/
+ { .val = 'C', .name = "overstripe-count",
+ .has_arg = required_argument},
{ .val = 'd', .name = "delete", .has_arg = no_argument},
{ .val = 'd', .name = "destroy", .has_arg = no_argument},
/* --non-direct is only valid in migrate mode */
/* find { .val = 'U', .name = "user", .has_arg = required_argument }*/
/* --verbose is only valid in migrate mode */
{ .val = 'v', .name = "verbose", .has_arg = no_argument},
+ { .val = 'x', .name = "xattr", .has_arg = required_argument },
{ .val = 'y', .name = "yaml", .has_arg = required_argument },
{ .name = NULL } };
migrate_mode = (opc == SO_MIGRATE);
mirror_mode = (opc == SO_MIRROR_CREATE || opc == SO_MIRROR_EXTEND);
+ setstripe_mode = (opc == SO_SETSTRIPE);
snprintf(cmd, sizeof(cmd), "%s %s", progname, argv[0]);
progname = cmd;
while ((c = getopt_long(argc, argv,
- "bc:dDE:f:H:i:I:m:N::no:p:L:s:S:vy:", long_opts,
- NULL)) >= 0) {
+ "bc:C:dDE:f:H:i:I:m:N::no:p:L:s:S:vx:y:",
+ long_opts, NULL)) >= 0) {
switch (c) {
case 0:
/* Long options. */
goto usage_error;
}
break;
- case LFS_MIRROR_FLAGS_OPT: {
- __u32 flags;
+ case LFS_LAYOUT_FLAGS_OPT: {
+ uint32_t neg_flags;
+
+ /* check for numeric flags (foreign and mirror cases) */
+ if (setstripe_mode && !mirror_mode && !last_mirror) {
+ flags = strtoul(optarg, &end, 16);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s %s: bad flags '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
+ }
if (!mirror_mode || !last_mirror) {
fprintf(stderr, "error: %s: --flags must be specified with --mirror-count|-N option\n",
}
result = comp_str2flags(optarg, &last_mirror->m_flags,
- &flags);
+ &neg_flags);
if (result != 0)
goto usage_error;
- if (flags) {
+ if (neg_flags) {
fprintf(stderr, "%s: inverted flags are not supported\n",
progname);
result = -EINVAL;
}
break;
}
+ case LFS_LAYOUT_FOREIGN_OPT:
+ if (optarg != NULL) {
+ /* check pure numeric */
+ type = strtoul(optarg, &end, 0);
+ if (*end) {
+ /* check name */
+ type = check_foreign_type_name(optarg);
+ if (type == LU_FOREIGN_TYPE_UNKNOWN) {
+ fprintf(stderr,
+ "%s %s: unrecognized foreign type '%s'\n",
+ progname, argv[0],
+ optarg);
+ return CMD_HELP;
+ }
+ }
+ }
+ foreign_mode = true;
+ break;
+ case LFS_MODE_OPT:
+ mode_opt = optarg;
+ if (mode_opt != NULL) {
+ mode = strtoul(mode_opt, &end, 8);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s %s: bad mode '%s'\n",
+ progname, argv[0], mode_opt);
+ return CMD_HELP;
+ }
+ previous_umask = umask(0);
+ }
+ break;
case LFS_LAYOUT_COPY:
from_copy = true;
template = optarg;
}
migration_block = true;
break;
+ case 'C':
+ lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
+ /* fall through */
case 'c':
lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
if (*end != '\0') {
migrate_mdt_mode = true;
lsa.lsa_nr_tgts = parse_targets(tgts,
sizeof(tgts) / sizeof(__u32),
- lsa.lsa_nr_tgts, optarg);
+ lsa.lsa_nr_tgts, optarg, NULL);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
"%s %s: invalid MDT target(s) '%s'\n",
fprintf(stderr, "warning: '--ost-list' is "
"deprecated, use '--ost' instead\n");
#endif
+ /* -o allows overstriping, and must note it because
+ * parse_targets is shared with MDT striping, which
+ * does not allow duplicates
+ */
+ lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
lsa.lsa_nr_tgts = parse_targets(tgts,
sizeof(tgts) / sizeof(__u32),
- lsa.lsa_nr_tgts, optarg);
+ lsa.lsa_nr_tgts, optarg,
+ &lsa.lsa_pattern);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
"%s %s: invalid OST target(s) '%s'\n",
migrate_mdt_param.fp_verbose = VERBOSE_DETAIL;
migration_flags = MIGRATION_VERBOSE;
break;
+ case 'x':
+ xattr = optarg;
+ break;
case 'y':
from_yaml = true;
template = optarg;
goto usage_error;
}
+ if (xattr && !foreign_mode) {
+ /* only print a warning as this is harmless and will be ignored
+ */
+ fprintf(stderr,
+ "%s %s: xattr has been specified for non-foreign layout\n",
+ progname, argv[0]);
+ } else if (foreign_mode && !xattr) {
+ fprintf(stderr,
+ "%s %s: xattr must be provided in foreign mode\n",
+ progname, argv[0]);
+ goto usage_error;
+ }
+
+ if (foreign_mode && (!setstripe_mode || comp_add | comp_del ||
+ comp_set || comp_id || delete || from_copy ||
+ setstripe_args_specified(&lsa) || lsa.lsa_nr_tgts ||
+ lsa.lsa_tgts)) {
+ fprintf(stderr,
+ "%s %s: only --xattr/--flags/--mode options are valid with --foreign\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
if (mirror_mode && mirror_count == 0) {
fprintf(stderr,
"error: %s: --mirror-count|-N option is required\n",
lmu->lum_hash_type = LMV_HASH_TYPE_FNV_1A_64;
if (lsa.lsa_pool_name)
strncpy(lmu->lum_pool_name, lsa.lsa_pool_name,
- sizeof(lmu->lum_pool_name));
+ sizeof(lmu->lum_pool_name) - 1);
if (lsa.lsa_nr_tgts > 1) {
int i;
param->lsp_stripe_offset = -1;
else
param->lsp_stripe_offset = lsa.lsa_stripe_off;
+ param->lsp_stripe_pattern =
+ llapi_pattern_to_lov(lsa.lsa_pattern);
+ if (param->lsp_stripe_pattern == EINVAL) {
+ fprintf(stderr, "error: %s: invalid stripe pattern\n",
+ argv[0]);
+ free(param);
+ goto usage_error;
+ }
param->lsp_pool = lsa.lsa_pool_name;
param->lsp_is_specific = false;
if (lsa.lsa_nr_tgts > 0) {
NULL);
} else if (layout != NULL) {
result = lfs_component_create(fname, O_CREAT | O_WRONLY,
- 0666, layout);
+ mode, layout);
+ if (result >= 0) {
+ close(result);
+ result = 0;
+ }
+ } else if (foreign_mode) {
+ result = llapi_file_create_foreign(fname, mode, type,
+ flags, xattr);
if (result >= 0) {
close(result);
result = 0;
} else {
result = llapi_file_open_param(fname,
O_CREAT | O_WRONLY,
- 0666, param);
+ mode, param);
if (result >= 0) {
close(result);
result = 0;
}
}
+ if (mode_opt != NULL)
+ umask(previous_umask);
+
free(param);
free(migrate_mdt_param.fp_lmv_md);
llapi_layout_free(layout);
progname, timebuf, strerror(EINVAL));
return LONG_MAX;
}
- if (*endptr && unit < 24 * 60 * 60)
+
+ if (param->fp_time_margin == 0 ||
+ (*endptr && unit < param->fp_time_margin))
param->fp_time_margin = unit;
t += val * unit;
}
*set = *time - t;
+
return res;
}
*layout |= LOV_PATTERN_RAID0;
else if (strcmp(layout_name, "mdt") == 0)
*layout |= LOV_PATTERN_MDT;
+ else if (strcmp(layout_name, "overstriping") == 0)
+ *layout |= LOV_PATTERN_OVERSTRIPING;
else
return -1;
}
.has_arg = required_argument },
{ .val = LFS_MIRROR_STATE_OPT,
.name = "mirror-state", .has_arg = required_argument },
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
{ .val = 'c', .name = "stripe-count", .has_arg = required_argument },
{ .val = 'c', .name = "stripe_count", .has_arg = required_argument },
{ .val = 'C', .name = "ctime", .has_arg = required_argument },
{ .val = 'E', .name = "component-end",
.has_arg = required_argument },
/* find { .val = 'F', .name = "fid", .has_arg = no_argument }, */
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
{ .val = 'g', .name = "gid", .has_arg = required_argument },
{ .val = 'G', .name = "group", .has_arg = required_argument },
{ .val = 'H', .name = "mdt-hash", .has_arg = required_argument },
param.fp_check_comp_end = 1;
param.fp_exclude_comp_end = !!neg_opt;
break;
+ case LFS_LAYOUT_FOREIGN_OPT: {
+ /* all types by default */
+ uint32_t type = LU_FOREIGN_TYPE_UNKNOWN;
+
+ if (optarg != NULL) {
+ /* check pure numeric */
+ type = strtoul(optarg, &endptr, 0);
+ if (*endptr) {
+ /* check name */
+ type = check_foreign_type_name(optarg);
+ if (type == LU_FOREIGN_TYPE_UNKNOWN) {
+ fprintf(stderr,
+ "%s %s: unknown foreign type '%s'\n",
+ progname, argv[0],
+ optarg);
+ return CMD_HELP;
+ }
+ }
+ }
+ param.fp_foreign_type = type;
+ param.fp_check_foreign = 1;
+ param.fp_exclude_foreign = !!neg_opt;
+ break;
+ }
case 'g':
case 'G':
rc = name2gid(¶m.fp_gid, optarg);
{ .val = 'O', .name = "obd", .has_arg = required_argument },
{ .val = 'r', .name = "recursive", .has_arg = no_argument },
{ .val = 'T', .name = "mdt-count", .has_arg = no_argument },
+ { .val = 'v', .name = "verbose", .has_arg = no_argument },
{ .val = 'y', .name = "yaml", .has_arg = no_argument },
{ .name = NULL } };
int c, rc;
param.fp_get_lmv = 1;
while ((c = getopt_long(argc, argv,
- "cDHimO:rtTy", long_opts, NULL)) != -1)
+ "cDHimO:rtTvy", long_opts, NULL)) != -1)
{
switch (c) {
case 'c':
case 'r':
param.fp_recursive = 1;
break;
+ case 'v':
+ param.fp_verbose |= VERBOSE_DETAIL;
+ break;
case 'y':
param.fp_yaml = 1;
break;
default:
+ fprintf(stderr, "%s %s: unrecognized option '%s'\n",
+ progname, argv[0], argv[optind - 1]);
return CMD_HELP;
}
}
return (ratio - (int)ratio) > 0 ? (int)(ratio + 1) : (int)ratio;
}
+/* This is only used to reflect various problem states for lfs df, so we only
+ * translate the flags reflecting those states.
+ */
+static char obd_statfs_state_names[] = {
+ [OS_STATE_DEGRADED] = 'D',
+ [OS_STATE_READONLY] = 'R',
+ [OS_STATE_NOPRECREATE] = 'N',
+ [OS_STATE_ENOSPC] = 'S',
+ [OS_STATE_ENOINO] = 'I',
+};
+
+static char obd_statfs_state2char(int s)
+{
+ /* Not an error state, do not print here */
+ if (s == OS_STATE_NONROT)
+ return '\0';
+ /* Unknown name */
+ if (s > ARRAY_SIZE(obd_statfs_state_names)/sizeof(char) ||
+ obd_statfs_state_names[s] == 0)
+ return '?';
+
+ return obd_statfs_state_names[s];
+}
+
static int showdf(char *mntdir, struct obd_statfs *stat,
char *uuid, enum mntdf_flags flags,
char *type, int index, int rc)
printf("[%s:%d]", type, index);
if (stat->os_state) {
- /*
- * Each character represents the matching
- * OS_STATE_* bit.
- */
- const char state_names[] = "DRSI";
- __u32 state;
- __u32 i;
+ uint32_t state;
+ uint32_t i;
printf(" ");
- for (i = 0, state = stat->os_state;
- state && i < sizeof(state_names); i++) {
- if (!(state & (1 << i)))
+ for (i = 0, state = stat->os_state; state != 0; i++) {
+ uint32_t mask = 1 << i;
+ if (!(state & mask))
continue;
- printf("%c", state_names[i]);
- state ^= 1 << i;
+ printf("%c", obd_statfs_state2char(mask));
+ state &= ~mask;
}
}
{ .st_op = LL_STATFS_LOV, .st_name = "OST" },
{ .st_name = NULL } };
struct ll_stat_type *tp;
+ __u64 ost_files = 0;
__u64 ost_ffree = 0;
__u32 index;
__u32 type;
sum.os_ffree += stat_buf.os_ffree;
sum.os_files += stat_buf.os_files;
} else /* if (tp->st_op == LL_STATFS_LOV) */ {
+ ost_files += stat_buf.os_files;
ost_ffree += stat_buf.os_ffree;
}
sum.os_blocks += stat_buf.os_blocks *
close(fd);
- /* If we don't have as many objects free on the OST as inodes
- * on the MDS, we reduce the total number of inodes to
- * compensate, so that the "inodes in use" number is correct.
- * Matches ll_statfs_internal() so the results are consistent. */
- if (ost_ffree < sum.os_ffree) {
+ /* If we have _some_ OSTs, but don't have as many free objects on the
+ * OST as inodes on the MDTs, reduce the reported number of inodes
+ * to compensate, so that the "inodes in use" number is correct.
+ * This should be kept in sync with ll_statfs_internal().
+ */
+ if (ost_files && ost_ffree < sum.os_ffree) {
sum.os_files = (sum.os_files - sum.os_ffree) + ost_ffree;
sum.os_ffree = ost_ffree;
}
/* functions */
static int lfs_setdirstripe(int argc, char **argv)
{
- char *dname;
- int result;
- struct lfs_setstripe_args lsa = { 0 };
- struct llapi_stripe_param *param = NULL;
- __u32 mdts[LMV_MAX_STRIPE_COUNT] = { 0 };
- char *end;
- int c;
- char *mode_opt = NULL;
- bool default_stripe = false;
- mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
- mode_t previous_mode = 0;
- bool delete = false;
- struct ll_statfs_buf *lsb = NULL;
- char mntdir[PATH_MAX] = "";
- bool auto_distributed = false;
-
+ char *dname;
+ struct lfs_setstripe_args lsa = { 0 };
+ struct llapi_stripe_param *param = NULL;
+ __u32 mdts[LMV_MAX_STRIPE_COUNT] = { 0 };
+ char *end;
+ int c;
+ char *mode_opt = NULL;
+ bool default_stripe = false;
+ bool delete = false;
+ bool auto_distributed = false;
+ bool foreign_mode = false;
+ mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
+ mode_t previous_mode = 0;
+ struct ll_statfs_buf *lsb = NULL;
+ char mntdir[PATH_MAX] = "";
+ char *xattr = NULL;
+ __u32 type = LU_FOREIGN_TYPE_DAOS, flags = 0;
struct option long_opts[] = {
{ .val = 'c', .name = "count", .has_arg = required_argument },
{ .val = 'c', .name = "mdt-count", .has_arg = required_argument },
{ .val = 'd', .name = "delete", .has_arg = no_argument },
{ .val = 'D', .name = "default", .has_arg = no_argument },
{ .val = 'D', .name = "default_stripe", .has_arg = no_argument },
+ { .val = LFS_LAYOUT_FLAGS_OPT,
+ .name = "flags", .has_arg = required_argument },
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
{ .val = 'H', .name = "mdt-hash", .has_arg = required_argument },
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 17, 53, 0)
{ .val = 'i', .name = "mdt-index", .has_arg = required_argument },
#endif
{ .val = 'T', .name = "mdt-count", .has_arg = required_argument },
/* setstripe { .val = 'y', .name = "yaml", .has_arg = no_argument }, */
+ { .val = 'x', .name = "xattr", .has_arg = required_argument },
{ .name = NULL } };
+ int result = 0;
setstripe_args_init(&lsa);
- while ((c = getopt_long(argc, argv, "c:dDi:H:m:o:t:T:", long_opts,
- NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "c:dDi:H:m:o:t:T:x:",
+ long_opts, NULL)) >= 0) {
switch (c) {
case 0:
/* Long options. */
case 'D':
default_stripe = true;
break;
+ case LFS_LAYOUT_FOREIGN_OPT:
+ if (optarg != NULL) {
+ /* check pure numeric */
+ type = strtoul(optarg, &end, 0);
+ if (*end) {
+ /* check name */
+ type = check_foreign_type_name(optarg);
+ if (type == LU_FOREIGN_TYPE_UNKNOWN) {
+ fprintf(stderr,
+ "%s %s: unknown foreign type '%s'\n",
+ progname, argv[0],
+ optarg);
+ return CMD_HELP;
+ }
+ }
+ }
+ foreign_mode = true;
+ break;
+ case LFS_LAYOUT_FLAGS_OPT:
+ flags = strtoul(optarg, &end, 16);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s %s: bad flags '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
case 't':
fprintf(stderr, "warning: '--hash-type' and '-t' "
"%s %s: warning: '--index' deprecated, use '--mdt-index' instead\n",
progname, argv[0]);
#endif
+ lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
lsa.lsa_nr_tgts = parse_targets(mdts,
sizeof(mdts) / sizeof(__u32),
- lsa.lsa_nr_tgts, optarg);
+ lsa.lsa_nr_tgts, optarg, NULL);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
"%s %s: invalid MDT target(s) '%s'\n",
progname, argv[0], optarg);
return CMD_HELP;
}
+ lsa.lsa_pattern = 0;
lsa.lsa_tgts = mdts;
if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
case 'o':
mode_opt = optarg;
break;
+ case 'x':
+ xattr = optarg;
+ break;
default:
fprintf(stderr, "%s %s: unrecognized option '%s'\n",
progname, argv[0], argv[optind - 1]);
return CMD_HELP;
}
+ if (xattr && !foreign_mode) {
+ /* only print a warning as this is armless and will be
+ * ignored
+ */
+ fprintf(stderr,
+ "%s %s: xattr has been specified for non-foreign layout\n",
+ progname, argv[0]);
+ } else if (foreign_mode && !xattr) {
+ fprintf(stderr,
+ "%s %s: xattr must be provided in foreign mode\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ if (foreign_mode && (delete || default_stripe || lsa.lsa_nr_tgts ||
+ lsa.lsa_tgts || setstripe_args_specified(&lsa))) {
+ fprintf(stderr,
+ "%s %s: only --xattr/--flags/--mode options are valid with --foreign\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
if (!delete && lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT &&
- lsa.lsa_stripe_count == LLAPI_LAYOUT_DEFAULT) {
+ lsa.lsa_stripe_count == LLAPI_LAYOUT_DEFAULT && !foreign_mode) {
fprintf(stderr,
"%s %s: stripe offset and count must be specified\n",
progname, argv[0]);
previous_mode = umask(0);
}
+ /* foreign LMV/dir case */
+ if (foreign_mode) {
+ if (argc > optind + 1) {
+ fprintf(stderr,
+ "%s %s: cannot specify multiple foreign dirs\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ dname = argv[optind];
+ result = llapi_dir_create_foreign(dname, mode, type, flags,
+ xattr);
+ if (result != 0)
+ fprintf(stderr,
+ "%s mkdir: can't create foreign dir '%s': %s\n",
+ progname, dname, strerror(-result));
+ return result;
+ }
+
/*
* initialize stripe parameters, in case param is converted to specific,
* i.e, 'lfs mkdir -i -1 -c N', always allocate space for lsp_tgts.
memcpy(param->lsp_tgts, mdts, sizeof(*mdts) * lsa.lsa_nr_tgts);
}
+ if (!default_stripe && lsa.lsa_pattern == LMV_HASH_TYPE_SPACE) {
+ fprintf(stderr, "%s %s: can only specify -H space with -D\n",
+ progname, argv[0]);
+ free(param);
+ return CMD_HELP;
+ }
+
dname = argv[optind];
do {
if (default_stripe) {
result = llapi_dir_set_default_lmv(dname, param);
- } else {
- /* if current \a dname isn't under the same \a mntdir
- * as the last one, and the last one was
- * auto-distributed, restore \a param.
- */
- if (mntdir[0] != '\0' &&
- strncmp(dname, mntdir, strlen(mntdir)) &&
- auto_distributed) {
- param->lsp_is_specific = false;
- param->lsp_stripe_offset = -1;
- auto_distributed = false;
- }
-
- if (!param->lsp_is_specific &&
- param->lsp_stripe_offset == -1) {
- char path[PATH_MAX] = "";
+ if (result)
+ fprintf(stderr,
+ "%s setdirstripe: cannot set default stripe on dir '%s': %s\n",
+ progname, dname, strerror(-result));
+ continue;
+ }
- if (!lsb) {
- lsb = malloc(sizeof(*lsb));
- if (!lsb) {
- result = -ENOMEM;
- break;
- }
- }
- lsb->sb_count = 0;
+ /*
+ * if current \a dname isn't under the same \a mntdir as the
+ * last one, and the last one was auto-distributed, restore
+ * \a param.
+ */
+ if (mntdir[0] != '\0' &&
+ strncmp(dname, mntdir, strlen(mntdir)) &&
+ auto_distributed) {
+ param->lsp_is_specific = false;
+ param->lsp_stripe_offset = -1;
+ auto_distributed = false;
+ }
- /* use mntdir for dirname() temporarily */
- strncpy(mntdir, dname, sizeof(mntdir));
- if (!realpath(dirname(mntdir), path)) {
- result = -errno;
- fprintf(stderr,
- "error: invalid path '%s': %s\n",
- argv[optind], strerror(errno));
- break;
- }
- mntdir[0] = '\0';
+ /*
+ * TODO: when MDT can allocate object with QoS (LU-9435), below
+ * code should be removed, instead we should let LMV to allocate
+ * the starting MDT object, and then let LOD allocate other MDT
+ * objects.
+ */
+ if (!param->lsp_is_specific && param->lsp_stripe_offset == -1) {
+ char path[PATH_MAX] = "";
- result = llapi_search_mounts(path, 0, mntdir,
- NULL);
- if (result < 0 || mntdir[0] == '\0') {
- fprintf(stderr,
- "No suitable Lustre mount found\n");
+ if (!lsb) {
+ lsb = malloc(sizeof(*lsb));
+ if (!lsb) {
+ result = -ENOMEM;
break;
}
+ }
+ lsb->sb_count = 0;
- result = mntdf(mntdir, NULL, NULL, 0,
- LL_STATFS_LMV, lsb);
- if (result < 0)
- break;
+ /* use mntdir for dirname() temporarily */
+ strncpy(mntdir, dname, sizeof(mntdir));
+ if (!realpath(dirname(mntdir), path)) {
+ result = -errno;
+ fprintf(stderr,
+ "error: invalid path '%s': %s\n",
+ argv[optind], strerror(errno));
+ break;
+ }
+ mntdir[0] = '\0';
- if (param->lsp_stripe_count > lsb->sb_count) {
- fprintf(stderr,
- "error: stripe count %d is too big\n",
- param->lsp_stripe_count);
- result = -ERANGE;
- break;
- }
+ result = llapi_search_mounts(path, 0, mntdir, NULL);
+ if (result < 0 || mntdir[0] == '\0') {
+ fprintf(stderr,
+ "No suitable Lustre mount found\n");
+ break;
+ }
- qsort(lsb->sb_buf, lsb->sb_count,
- sizeof(struct ll_statfs_data),
- ll_statfs_data_comp);
+ result = mntdf(mntdir, NULL, NULL, 0, LL_STATFS_LMV,
+ lsb);
+ if (result < 0)
+ break;
- auto_distributed = true;
+ if (param->lsp_stripe_count > lsb->sb_count) {
+ fprintf(stderr,
+ "error: stripe count %d is too big\n",
+ param->lsp_stripe_count);
+ result = -ERANGE;
+ break;
}
- if (auto_distributed) {
- int r;
- int nr = MAX(param->lsp_stripe_count,
- lsb->sb_count / 2);
+ qsort(lsb->sb_buf, lsb->sb_count,
+ sizeof(struct ll_statfs_data),
+ ll_statfs_data_comp);
+
+ auto_distributed = true;
+ }
- /* don't use server whose usage is above 90% */
- while (nr != param->lsp_stripe_count &&
- obd_statfs_ratio(&lsb->sb_buf[nr].sd_st,
- false) > 90)
- nr = MAX(param->lsp_stripe_count,
- nr / 2);
+ if (auto_distributed) {
+ int r;
+ int nr = MAX(param->lsp_stripe_count,
+ lsb->sb_count / 2);
- /* get \a r between [0, nr) */
- r = rand() % nr;
+ /* don't use server whose usage is above 90% */
+ while (nr != param->lsp_stripe_count &&
+ obd_statfs_ratio(&lsb->sb_buf[nr].sd_st, false) >
+ 90)
+ nr = MAX(param->lsp_stripe_count, nr / 2);
- param->lsp_stripe_offset =
- lsb->sb_buf[r].sd_index;
- if (param->lsp_stripe_count > 1) {
- int i = 0;
+ /* get \a r between [0, nr) */
+ r = rand() % nr;
- param->lsp_is_specific = true;
- for (; i < param->lsp_stripe_count; i++)
- param->lsp_tgts[(i + r) % nr] =
- lsb->sb_buf[i].sd_index;
- }
- }
+ param->lsp_stripe_offset = lsb->sb_buf[r].sd_index;
+ if (param->lsp_stripe_count > 1) {
+ int i = 0;
- result = llapi_dir_create(dname, mode, param);
+ param->lsp_is_specific = true;
+ for (; i < param->lsp_stripe_count; i++)
+ param->lsp_tgts[(i + r) % nr] =
+ lsb->sb_buf[i].sd_index;
+ }
}
- if (result) {
+ result = llapi_dir_create(dname, mode, param);
+ if (result)
fprintf(stderr,
- "%s setdirstripe: cannot create stripe dir '%s': %s\n",
+ "%s setdirstripe: cannot create dir '%s': %s\n",
progname, dname, strerror(-result));
- break;
- }
- dname = argv[++optind];
- } while (dname != NULL);
+ } while (!result && (dname = argv[++optind]));
if (mode_opt != NULL)
umask(previous_mode);
return rc;
}
+static int print_instance(const char *mntdir, char *fsname, size_t fsnamelen,
+ bool opt_instance, bool opt_fsname, bool opt_mntdir)
+{
+ char *buf = fsname;
+
+ /* llapi_search_mounts() fills "fsname", but that is not called if
+ * explicit paths are specified on the command-line
+ */
+ if (opt_instance || (opt_fsname && fsname[0] == '\0')) {
+ int rc = llapi_getname(mntdir, fsname, fsnamelen);
+
+ if (rc < 0) {
+ fprintf(stderr, "cannot get instance for '%s': %s\n",
+ mntdir, strerror(-rc));
+ return rc;
+ }
+ buf = fsname;
+ if (!opt_instance) {
+ /* print only the fsname name */
+ buf = strchr(fsname, '-');
+ if (buf)
+ *buf = '\0';
+ buf = fsname;
+ } else if (!opt_fsname) {
+ /* print only the instance name */
+ buf = strchr(fsname, '-');
+ if (buf)
+ buf++;
+ else
+ buf = fsname;
+ }
+ } else if (opt_fsname) {
+ /* print only the fsname */
+ buf = fsname;
+ }
+
+ printf("%s %s\n", buf, opt_mntdir ? mntdir : "");
+
+ return 0;
+}
+
static int lfs_getname(int argc, char **argv)
{
- char mntdir[PATH_MAX] = "", path[PATH_MAX] = "", fsname[PATH_MAX] = "";
- int rc = 0, index = 0, c;
- char buf[sizeof(struct obd_uuid)];
+ struct option long_opts[] = {
+ { .val = 'h', .name = "help", .has_arg = no_argument },
+ { .val = 'i', .name = "instance", .has_arg = no_argument },
+ { .val = 'n', .name = "fsname", .has_arg = no_argument },
+ { .name = NULL} };
+ bool opt_instance = false, opt_fsname = false;
+ char fsname[PATH_MAX] = "";
+ int rc = 0, rc2, c;
- while ((c = getopt(argc, argv, "h")) != -1)
- return CMD_HELP;
+ while ((c = getopt_long(argc, argv, "hin", long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'i':
+ opt_instance = true;
+ break;
+ case 'n':
+ opt_fsname = true;
+ break;
+ case 'h':
+ default:
+ return CMD_HELP;
+ }
+ }
- if (optind == argc) { /* no paths specified, get all paths. */
- while (!llapi_search_mounts(path, index++, mntdir, fsname)) {
- rc = llapi_getname(mntdir, buf, sizeof(buf));
- if (rc < 0) {
- fprintf(stderr,
- "cannot get name for `%s': %s\n",
- mntdir, strerror(-rc));
- break;
- }
+ /* If neither option is given, print both instance and fsname */
+ if (!opt_instance && !opt_fsname)
+ opt_instance = opt_fsname = true;
- printf("%s %s\n", buf, mntdir);
+ if (optind == argc) { /* no paths specified, get all paths. */
+ char mntdir[PATH_MAX] = "", path[PATH_MAX] = "";
+ int index = 0;
- path[0] = fsname[0] = mntdir[0] = 0;
- }
- } else { /* paths specified, only attempt to search these. */
- for (; optind < argc; optind++) {
- rc = llapi_getname(argv[optind], buf, sizeof(buf));
- if (rc < 0) {
- fprintf(stderr,
- "cannot get name for `%s': %s\n",
- argv[optind], strerror(-rc));
- break;
- }
+ while (!llapi_search_mounts(path, index++, mntdir, fsname)) {
+ rc2 = print_instance(mntdir, fsname, sizeof(fsname),
+ opt_instance, opt_fsname, true);
+ if (!rc)
+ rc = rc2;
+ path[0] = fsname[0] = mntdir[0] = '\0';
+ }
+ } else { /* paths specified, only attempt to search these. */
+ bool opt_mntdir;
- printf("%s %s\n", buf, argv[optind]);
- }
- }
- return rc;
+ /* if only one path is given, print only requested info */
+ opt_mntdir = argc - optind > 1 || (opt_instance == opt_fsname);
+
+ for (; optind < argc; optind++) {
+ rc2 = print_instance(argv[optind], fsname,
+ sizeof(fsname), opt_instance,
+ opt_fsname, opt_mntdir);
+ if (!rc)
+ rc = rc2;
+ fsname[0] = '\0';
+ }
+ }
+
+ return rc;
}
static int lfs_check(int argc, char **argv)
return rc;
}
-
static const char *const heat_names[] = LU_HEAT_NAMES;
static int lfs_heat_get(int argc, char **argv)
{
- struct lu_heat *heat;
- int rc = 0, rc2;
- char *path;
- int fd;
- int i;
+ struct lu_heat *heat;
+ int rc = 0, rc2;
+ char *path;
+ int fd;
+ int i;
if (argc <= 1)
return CMD_HELP;
static int lfs_heat_set(int argc, char **argv)
{
- struct option long_opts[] = {
- {"clear", no_argument, 0, 'c'},
- {"off", no_argument, 0, 'o'},
- {"on", no_argument, 0, 'O'},
- {0, 0, 0, 0}
- };
- char short_opts[] = "coO";
- int rc = 0, rc2;
- char *path;
- int fd;
- __u64 flags = 0;
- int c;
+ struct option long_opts[] = {
+ { .val = 'c', .name = "clear", .has_arg = no_argument },
+ { .val = 'o', .name = "off", .has_arg = no_argument },
+ { .val = 'O', .name = "on", .has_arg = no_argument },
+ { .name = NULL } };
+ enum lu_heat_flag flags = 0;
+ int rc = 0, rc2;
+ char *path;
+ int fd;
+ int c;
if (argc <= 1)
return CMD_HELP;
optind = 0;
- while ((c = getopt_long(argc, argv, short_opts,
- long_opts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "coO", long_opts, NULL)) != -1) {
switch (c) {
case 'c':
flags |= LU_HEAT_FLAG_CLEAR;