+ fprintf(stderr,
+ "Invalid project ID: %s",
+ optarg);
+ ret = -1;
+ goto err;
+ }
+ }
+ param.fp_exclude_projid = !!neg_opt;
+ param.fp_check_projid = 1;
+ break;
+ case 's':
+ if (optarg[0] == '+') {
+ param.fp_size_sign = -1;
+ optarg++;
+ } else if (optarg[0] == '-') {
+ param.fp_size_sign = 1;
+ optarg++;
+ }
+
+ ret = llapi_parse_size(optarg, ¶m.fp_size,
+ ¶m.fp_size_units, 0);
+ if (ret) {
+ fprintf(stderr, "error: bad file size '%s'\n",
+ optarg);
+ goto err;
+ }
+ param.fp_check_size = 1;
+ param.fp_exclude_size = !!neg_opt;
+ break;
+ case 'S':
+ if (optarg[0] == '+') {
+ param.fp_stripe_size_sign = -1;
+ optarg++;
+ } else if (optarg[0] == '-') {
+ param.fp_stripe_size_sign = 1;
+ optarg++;
+ }
+
+ ret = llapi_parse_size(optarg, ¶m.fp_stripe_size,
+ ¶m.fp_stripe_size_units, 0);
+ if (ret) {
+ fprintf(stderr, "error: bad stripe_size '%s'\n",
+ optarg);
+ goto err;
+ }
+ param.fp_check_stripe_size = 1;
+ param.fp_exclude_stripe_size = !!neg_opt;
+ break;
+ case 't':
+ param.fp_exclude_type = !!neg_opt;
+ switch (optarg[0]) {
+ case 'b':
+ param.fp_type = S_IFBLK;
+ break;
+ case 'c':
+ param.fp_type = S_IFCHR;
+ break;
+ case 'd':
+ param.fp_type = S_IFDIR;
+ break;
+ case 'f':
+ param.fp_type = S_IFREG;
+ break;
+ case 'l':
+ param.fp_type = S_IFLNK;
+ break;
+ case 'p':
+ param.fp_type = S_IFIFO;
+ break;
+ case 's':
+ param.fp_type = S_IFSOCK;
+ break;
+ default:
+ fprintf(stderr, "error: %s: bad type '%s'\n",
+ argv[0], optarg);
+ ret = CMD_HELP;
+ goto err;
+ };
+ break;
+ case 'T':
+ if (optarg[0] == '+') {
+ param.fp_mdt_count_sign = -1;
+ optarg++;
+ } else if (optarg[0] == '-') {
+ param.fp_mdt_count_sign = 1;
+ optarg++;
+ }
+
+ param.fp_mdt_count = strtoul(optarg, &endptr, 0);
+ if (*endptr != '\0') {
+ fprintf(stderr, "error: bad mdt_count '%s'\n",
+ optarg);
+ ret = -1;
+ goto err;
+ }
+ param.fp_check_mdt_count = 1;
+ param.fp_exclude_mdt_count = !!neg_opt;
+ break;
+ default:
+ ret = CMD_HELP;
+ goto err;
+ };
+ }
+
+ if (pathstart == -1) {
+ fprintf(stderr, "error: %s: no filename|pathname\n",
+ argv[0]);
+ ret = CMD_HELP;
+ goto err;
+ } else if (pathend == -1) {
+ /* no options */
+ pathend = argc;
+ }
+
+ do {
+ rc = llapi_find(argv[pathstart], ¶m);
+ if (rc != 0 && ret == 0)
+ ret = rc;
+ } while (++pathstart < pathend);
+
+ if (ret)
+ fprintf(stderr, "error: %s failed for %s.\n",
+ argv[0], argv[optind - 1]);
+err:
+ if (param.fp_obd_uuid && param.fp_num_alloc_obds)
+ free(param.fp_obd_uuid);
+
+ if (param.fp_mdt_uuid && param.fp_num_alloc_mdts)
+ free(param.fp_mdt_uuid);
+
+ return ret;
+}
+
+static int lfs_getstripe_internal(int argc, char **argv,
+ struct find_param *param)
+{
+ struct option long_opts[] = {
+/* find { .val = 'A', .name = "atime", .has_arg = required_argument }*/
+/* find { .val = 'b', .name = "blocks", .has_arg = required_argument }*/
+ { .val = LFS_COMP_COUNT_OPT,
+ .name = "comp-count", .has_arg = no_argument },
+ { .val = LFS_COMP_COUNT_OPT,
+ .name = "component-count", .has_arg = no_argument },
+ { .val = LFS_COMP_FLAGS_OPT,
+ .name = "comp-flags", .has_arg = optional_argument },
+ { .val = LFS_COMP_FLAGS_OPT,
+ .name = "component-flags", .has_arg = optional_argument },
+ { .val = LFS_COMP_START_OPT,
+ .name = "comp-start", .has_arg = optional_argument },
+ { .val = LFS_COMP_START_OPT,
+ .name = "component-start", .has_arg = optional_argument },
+ { .val = LFS_MIRROR_INDEX_OPT,
+ .name = "mirror-index", .has_arg = required_argument },
+ { .val = LFS_MIRROR_ID_OPT,
+ .name = "mirror-id", .has_arg = required_argument },
+ { .val = 'c', .name = "stripe-count", .has_arg = no_argument },
+ { .val = 'c', .name = "stripe_count", .has_arg = no_argument },
+/* find { .val = 'C', .name = "ctime", .has_arg = required_argument }*/
+ { .val = 'd', .name = "directory", .has_arg = no_argument },
+ { .val = 'D', .name = "default", .has_arg = no_argument },
+ { .val = 'E', .name = "comp-end", .has_arg = optional_argument },
+ { .val = 'E', .name = "component-end", .has_arg = optional_argument },
+ { .val = 'F', .name = "fid", .has_arg = no_argument },
+ { .val = 'g', .name = "generation", .has_arg = no_argument },
+/* find { .val = 'G', .name = "group", .has_arg = required_argument }*/
+/* dirstripe { .val = 'H', .name = "mdt-hash", .has_arg = required_argument }*/
+ { .val = 'i', .name = "stripe-index", .has_arg = no_argument },
+ { .val = 'i', .name = "stripe_index", .has_arg = no_argument },
+ { .val = 'I', .name = "comp-id", .has_arg = optional_argument },
+ { .val = 'I', .name = "component-id", .has_arg = optional_argument },
+ { .val = 'L', .name = "layout", .has_arg = no_argument },
+ { .val = 'm', .name = "mdt", .has_arg = no_argument },
+ { .val = 'm', .name = "mdt-index", .has_arg = no_argument },
+ { .val = 'm', .name = "mdt_index", .has_arg = no_argument },
+/* find { .val = 'M', .name = "mtime", .has_arg = required_argument }*/
+/* find { .val = 'n', .name = "name", .has_arg = required_argument }*/
+ { .val = 'N', .name = "mirror-count", .has_arg = no_argument },
+ { .val = 'O', .name = "obd", .has_arg = required_argument },
+ { .val = 'O', .name = "ost", .has_arg = required_argument },
+ { .val = 'p', .name = "pool", .has_arg = no_argument },
+/* find { .val = 'P', .name = "print", .has_arg = no_argument }, */
+ { .val = 'q', .name = "quiet", .has_arg = no_argument },
+ { .val = 'r', .name = "recursive", .has_arg = no_argument },
+ { .val = 'R', .name = "raw", .has_arg = no_argument },
+ { .val = 'S', .name = "stripe-size", .has_arg = no_argument },
+ { .val = 'S', .name = "stripe_size", .has_arg = no_argument },
+/* find { .val = 't', .name = "type", .has_arg = required_argument }*/
+/* dirstripe { .val = 'T', .name = "mdt-count", .has_arg = required_argument }*/
+/* find { .val = 'u', .name = "uid", .has_arg = required_argument }*/
+/* find { .val = 'U', .name = "user", .has_arg = required_argument }*/
+ { .val = 'v', .name = "verbose", .has_arg = no_argument },
+ { .val = 'y', .name = "yaml", .has_arg = no_argument },
+ { .name = NULL } };
+ int c, rc;
+ int neg_opt = 0;
+ int pathstart = -1, pathend = -1;
+ int isoption;
+ char *end, *tmp;
+
+ while ((c = getopt_long(argc, argv,
+ "-cdDE::FghiI::LmMNoO:pqrRsSvy",
+ long_opts, NULL)) != -1) {
+ if (neg_opt)
+ --neg_opt;
+
+ /* '!' is part of option */
+ isoption = (c != 1) || (strcmp(optarg, "!") == 0);
+ if (!isoption && pathend != -1) {
+ fprintf(stderr,
+ "error: %s: filename|dirname must either precede options or follow options\n",
+ argv[0]);
+ return CMD_HELP;
+ }
+ if (!isoption && pathstart == -1)
+ pathstart = optind - 1;
+ if (isoption && pathstart != -1 && pathend == -1)
+ pathend = optind - 2;
+
+ switch (c) {
+ case 1:
+ /* unknown: opt is "!" */
+ if (strcmp(optarg, "!") == 0)
+ neg_opt = 2;
+ break;
+ case 'c':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_COUNT;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case LFS_COMP_COUNT_OPT:
+ param->fp_verbose |= VERBOSE_COMP_COUNT;
+ param->fp_max_depth = 0;
+ break;
+ case LFS_COMP_FLAGS_OPT:
+ if (optarg != NULL) {
+ rc = comp_str2flags(optarg,
+ ¶m->fp_comp_flags,
+ ¶m->fp_comp_neg_flags);
+ if (rc != 0) {
+ fprintf(stderr, "error: %s bad "
+ "component flags '%s'.\n",
+ argv[0], optarg);
+ return CMD_HELP;
+ }
+ param->fp_check_comp_flags = 1;
+ } else {
+ param->fp_verbose |= VERBOSE_COMP_FLAGS;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case LFS_COMP_START_OPT:
+ if (optarg != NULL) {
+ tmp = optarg;
+ if (tmp[0] == '+') {
+ param->fp_comp_start_sign = -1;
+ tmp++;
+ } else if (tmp[0] == '-') {
+ param->fp_comp_start_sign = 1;
+ tmp++;
+ }
+ rc = llapi_parse_size(tmp,
+ ¶m->fp_comp_start,
+ ¶m->fp_comp_start_units, 0);
+ if (rc != 0) {
+ fprintf(stderr, "error: %s bad "
+ "component start '%s'.\n",
+ argv[0], tmp);
+ return CMD_HELP;
+ } else {
+ param->fp_check_comp_start = 1;
+ }
+ } else {
+ param->fp_verbose |= VERBOSE_COMP_START;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case LFS_MIRROR_INDEX_OPT:
+ if (optarg[0] == '+') {
+ param->fp_mirror_index_sign = -1;
+ optarg++;
+ } else if (optarg[0] == '-') {
+ param->fp_mirror_index_sign = 1;
+ optarg++;
+ }
+
+ param->fp_mirror_index = strtoul(optarg, &end, 0);
+ if (*end != '\0' || (param->fp_mirror_index == 0 &&
+ param->fp_mirror_index_sign == 0 && neg_opt == 0)) {
+ fprintf(stderr,
+ "%s %s: invalid mirror index '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ if (param->fp_mirror_id != 0) {
+ fprintf(stderr,
+ "%s %s: can't specify both mirror index and mirror ID\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+ param->fp_check_mirror_index = 1;
+ param->fp_exclude_mirror_index = !!neg_opt;
+ break;
+ case LFS_MIRROR_ID_OPT:
+ if (optarg[0] == '+') {
+ param->fp_mirror_id_sign = -1;
+ optarg++;
+ } else if (optarg[0] == '-') {
+ param->fp_mirror_id_sign = 1;
+ optarg++;
+ }
+
+ param->fp_mirror_id = strtoul(optarg, &end, 0);
+ if (*end != '\0' || (param->fp_mirror_id == 0 &&
+ param->fp_mirror_id_sign == 0 && neg_opt == 0)) {
+ fprintf(stderr,
+ "%s %s: invalid mirror ID '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ if (param->fp_mirror_index != 0) {
+ fprintf(stderr,
+ "%s %s: can't specify both mirror index and mirror ID\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+ param->fp_check_mirror_id = 1;
+ param->fp_exclude_mirror_id = !!neg_opt;
+ break;
+ case 'd':
+ param->fp_max_depth = 0;
+ break;
+ case 'D':
+ param->fp_get_default_lmv = 1;
+ break;
+ case 'E':
+ if (optarg != NULL) {
+ tmp = optarg;
+ if (tmp[0] == '+') {
+ param->fp_comp_end_sign = -1;
+ tmp++;
+ } else if (tmp[0] == '-') {
+ param->fp_comp_end_sign = 1;
+ tmp++;
+ }
+
+ if (arg_is_eof(tmp)) {
+ param->fp_comp_end = LUSTRE_EOF;
+ param->fp_comp_end_units = 1;
+ rc = 0;
+ } else {
+ rc = llapi_parse_size(tmp,
+ ¶m->fp_comp_end,
+ ¶m->fp_comp_end_units, 0);
+ }
+ if (rc != 0) {
+ fprintf(stderr, "error: %s bad "
+ "component end '%s'.\n",
+ argv[0], tmp);
+ return CMD_HELP;
+ }
+ param->fp_check_comp_end = 1;
+ } else {
+ param->fp_verbose |= VERBOSE_COMP_END;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'F':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_DFID;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'g':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_GENERATION;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'i':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_STRIPE_OFFSET;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'I':
+ if (optarg != NULL) {
+ param->fp_comp_id = strtoul(optarg, &end, 0);
+ if (*end != '\0' || param->fp_comp_id == 0 ||
+ param->fp_comp_id > LCME_ID_MAX) {
+ fprintf(stderr, "error: %s bad "
+ "component id '%s'\n",
+ argv[0], optarg);
+ return CMD_HELP;
+ } else {
+ param->fp_check_comp_id = 1;
+ }
+ } else {
+ param->fp_max_depth = 0;
+ param->fp_verbose |= VERBOSE_COMP_ID;
+ }
+ break;
+ case 'L':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_PATTERN;
+ param->fp_max_depth = 0;
+ }
+ break;
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ case 'M':
+ fprintf(stderr, "warning: '-M' deprecated"
+ ", use '--mdt-index' or '-m' instead\n");
+#endif
+ case 'm':
+ if (!(param->fp_verbose & VERBOSE_DETAIL))
+ param->fp_max_depth = 0;
+ param->fp_verbose |= VERBOSE_MDTINDEX;
+ break;
+ case 'N':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_MIRROR_COUNT;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'O':
+ if (param->fp_obd_uuid) {
+ fprintf(stderr,
+ "error: %s: only one obduuid allowed",
+ argv[0]);
+ return CMD_HELP;
+ }
+ param->fp_obd_uuid = (struct obd_uuid *)optarg;
+ break;
+ case 'p':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_POOL;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'q':
+ param->fp_quiet++;
+ break;
+ case 'r':
+ param->fp_recursive = 1;
+ break;
+ case 'R':
+ param->fp_raw = 1;
+ break;
+ case 'S':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_STRIPE_SIZE;
+ param->fp_max_depth = 0;
+ }
+ break;
+ case 'v':
+ param->fp_verbose = VERBOSE_DEFAULT | VERBOSE_DETAIL;
+ break;
+ case 'y':
+ param->fp_yaml = 1;
+ break;
+ default:
+ return CMD_HELP;
+ }
+ }
+
+ if (pathstart == -1) {
+ fprintf(stderr, "error: %s: no filename|pathname\n",
+ argv[0]);
+ return CMD_HELP;
+ } else if (pathend == -1) {
+ /* no options */
+ pathend = argc;
+ }
+
+ if (pathend > argc)
+ return CMD_HELP;
+
+ if (param->fp_recursive)
+ param->fp_max_depth = -1;
+ else if (param->fp_verbose & VERBOSE_DETAIL)
+ param->fp_max_depth = 1;
+
+ if (!param->fp_verbose)
+ param->fp_verbose = VERBOSE_DEFAULT;
+ if (param->fp_quiet)
+ param->fp_verbose = VERBOSE_OBJID;
+
+ do {
+ rc = llapi_getstripe(argv[pathstart], param);
+ } while (++pathstart < pathend && !rc);
+
+ if (rc)
+ fprintf(stderr, "error: %s failed for %s.\n",
+ argv[0], argv[optind - 1]);
+ return rc;
+}
+
+static int lfs_tgts(int argc, char **argv)
+{
+ char mntdir[PATH_MAX] = {'\0'}, path[PATH_MAX] = {'\0'};
+ struct find_param param;
+ int index = 0, rc=0;
+
+ if (argc > 2)
+ return CMD_HELP;
+
+ if (argc == 2 && !realpath(argv[1], path)) {
+ rc = -errno;
+ fprintf(stderr, "error: invalid path '%s': %s\n",
+ argv[1], strerror(-rc));
+ return rc;
+ }
+
+ while (!llapi_search_mounts(path, index++, mntdir, NULL)) {
+ /* Check if we have a mount point */
+ if (mntdir[0] == '\0')
+ continue;
+
+ memset(¶m, 0, sizeof(param));
+ if (!strcmp(argv[0], "mdts"))
+ param.fp_get_lmv = 1;
+
+ rc = llapi_ostlist(mntdir, ¶m);
+ if (rc) {
+ fprintf(stderr, "error: %s: failed on %s\n",
+ argv[0], mntdir);
+ }
+ if (path[0] != '\0')
+ break;
+ memset(mntdir, 0, PATH_MAX);
+ }
+
+ return rc;
+}
+
+static int lfs_getstripe(int argc, char **argv)
+{
+ struct find_param param = { 0 };
+
+ param.fp_max_depth = 1;
+ return lfs_getstripe_internal(argc, argv, ¶m);
+}
+
+/* functions */
+static int lfs_getdirstripe(int argc, char **argv)
+{
+ struct find_param param = { 0 };
+ struct option long_opts[] = {
+ { .val = 'c', .name = "mdt-count", .has_arg = no_argument },
+ { .val = 'D', .name = "default", .has_arg = no_argument },
+ { .val = 'H', .name = "mdt-hash", .has_arg = no_argument },
+ { .val = 'i', .name = "mdt-index", .has_arg = no_argument },
+ { .val = 'm', .name = "mdt-index", .has_arg = no_argument },
+ { .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 = '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)
+ {
+ switch (c) {
+ case 'c':
+ case 'T':
+ param.fp_verbose |= VERBOSE_COUNT;
+ break;
+ case 'D':
+ param.fp_get_default_lmv = 1;
+ break;
+ case 'i':
+ case 'm':
+ param.fp_verbose |= VERBOSE_STRIPE_OFFSET;
+ break;
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ case 't':
+ fprintf(stderr, "warning: '-t' deprecated, "
+ "use '--mdt-hash' or '-H' instead\n");
+#endif
+ case 'H':
+ param.fp_verbose |= VERBOSE_HASH_TYPE;
+ break;
+ case 'O':
+ if (param.fp_obd_uuid) {
+ fprintf(stderr,
+ "error: %s: only one obduuid allowed",
+ argv[0]);
+ return CMD_HELP;
+ }
+ param.fp_obd_uuid = (struct obd_uuid *)optarg;
+ break;
+ case 'r':
+ param.fp_recursive = 1;
+ break;
+ case 'y':
+ param.fp_yaml = 1;
+ break;
+ default:
+ return CMD_HELP;
+ }
+ }
+
+ if (optind >= argc)
+ return CMD_HELP;
+
+ if (param.fp_recursive)
+ param.fp_max_depth = -1;
+
+ if (!param.fp_verbose)
+ param.fp_verbose = VERBOSE_DEFAULT;
+
+ do {
+ rc = llapi_getstripe(argv[optind], ¶m);
+ } while (++optind < argc && !rc);
+
+ if (rc)
+ fprintf(stderr, "error: %s failed for %s.\n",
+ argv[0], argv[optind - 1]);
+ return rc;
+}
+
+enum mntdf_flags {
+ MNTDF_INODES = 0x0001,
+ MNTDF_COOKED = 0x0002,
+ MNTDF_LAZY = 0x0004,
+ MNTDF_VERBOSE = 0x0008,
+ MNTDF_SHOW = 0x0010,
+};
+
+#define COOK(value) \
+({ \
+ int radix = 0; \
+ while (value > 1024) { \
+ value /= 1024; \
+ radix++; \
+ } \
+ radix; \
+})
+#define UUF "%-20s"
+#define CSF "%11s"
+#define CDF "%11llu"
+#define HDF "%8.1f%c"
+#define RSF "%4s"
+#define RDF "%3d%%"
+
+static inline int obd_statfs_ratio(const struct obd_statfs *st)
+{
+ double avail, used, ratio = 0;
+
+ avail = st->os_bavail;
+ used = st->os_blocks - st->os_bfree;
+ if (avail + used > 0)
+ ratio = used / (used + avail) * 100 + 0.5;
+
+ return (int)ratio;
+}
+
+static int showdf(char *mntdir, struct obd_statfs *stat,
+ char *uuid, enum mntdf_flags flags,
+ char *type, int index, int rc)
+{
+ long long avail, used, total;
+ int ratio = 0;
+ char *suffix = "KMGTPEZY";
+ /* Note if we have >2^64 bytes/fs these buffers will need to be grown */
+ char tbuf[3 * sizeof(__u64)];
+ char ubuf[3 * sizeof(__u64)];
+ char abuf[3 * sizeof(__u64)];
+ char rbuf[3 * sizeof(__u64)];
+
+ if (!uuid || !stat)
+ return -EINVAL;
+
+ switch (rc) {
+ case 0:
+ if (flags & MNTDF_INODES) {
+ avail = stat->os_ffree;
+ used = stat->os_files - stat->os_ffree;
+ total = stat->os_files;
+ } else {
+ int shift = flags & MNTDF_COOKED ? 0 : 10;
+
+ avail = (stat->os_bavail * stat->os_bsize) >> shift;
+ used = ((stat->os_blocks - stat->os_bfree) *
+ stat->os_bsize) >> shift;
+ total = (stat->os_blocks * stat->os_bsize) >> shift;
+ }
+
+ ratio = obd_statfs_ratio(stat);
+
+ if (flags & MNTDF_COOKED) {
+ int i;
+ double cook_val;
+
+ cook_val = (double)total;
+ i = COOK(cook_val);
+ if (i > 0)
+ snprintf(tbuf, sizeof(tbuf), HDF, cook_val,
+ suffix[i - 1]);
+ else
+ snprintf(tbuf, sizeof(tbuf), CDF, total);
+
+ cook_val = (double)used;
+ i = COOK(cook_val);
+ if (i > 0)
+ snprintf(ubuf, sizeof(ubuf), HDF, cook_val,
+ suffix[i - 1]);
+ else
+ snprintf(ubuf, sizeof(ubuf), CDF, used);
+
+ cook_val = (double)avail;
+ i = COOK(cook_val);
+ if (i > 0)
+ snprintf(abuf, sizeof(abuf), HDF, cook_val,
+ suffix[i - 1]);
+ else
+ snprintf(abuf, sizeof(abuf), CDF, avail);
+ } else {
+ snprintf(tbuf, sizeof(tbuf), CDF, total);
+ snprintf(ubuf, sizeof(tbuf), CDF, used);
+ snprintf(abuf, sizeof(tbuf), CDF, avail);
+ }
+
+ sprintf(rbuf, RDF, ratio);
+ printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s",
+ uuid, tbuf, ubuf, abuf, rbuf, mntdir);
+ if (type)
+ 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;
+
+ printf(" ");
+ for (i = 0, state = stat->os_state;
+ state && i < sizeof(state_names); i++) {
+ if (!(state & (1 << i)))
+ continue;
+ printf("%c", state_names[i]);
+ state ^= 1 << i;
+ }
+ }
+
+ printf("\n");
+ break;
+ case -ENODATA:
+ printf(UUF": inactive device\n", uuid);
+ break;
+ default:
+ printf(UUF": %s\n", uuid, strerror(-rc));
+ break;
+ }
+
+ return 0;
+}
+
+struct ll_stat_type {
+ int st_op;
+ char *st_name;
+};
+
+#define LL_STATFS_MAX LOV_MAX_STRIPE_COUNT
+
+struct ll_statfs_data {
+ int sd_index;
+ struct obd_statfs sd_st;
+};
+
+struct ll_statfs_buf {
+ int sb_count;
+ struct ll_statfs_data sb_buf[LL_STATFS_MAX];
+};
+
+static int mntdf(char *mntdir, char *fsname, char *pool, enum mntdf_flags flags,
+ int ops, struct ll_statfs_buf *lsb)
+{
+ struct obd_statfs stat_buf, sum = { .os_bsize = 1 };
+ struct obd_uuid uuid_buf;
+ char *poolname = NULL;
+ struct ll_stat_type types[] = {
+ { .st_op = LL_STATFS_LMV, .st_name = "MDT" },
+ { .st_op = LL_STATFS_LOV, .st_name = "OST" },
+ { .st_name = NULL } };
+ struct ll_stat_type *tp;
+ __u64 ost_ffree = 0;
+ __u32 index;
+ __u32 type;
+ int fd;
+ int rc = 0;
+ int rc2;
+
+ if (pool) {
+ poolname = strchr(pool, '.');
+ if (poolname != NULL) {
+ if (strncmp(fsname, pool, strlen(fsname))) {
+ fprintf(stderr, "filesystem name incorrect\n");
+ return -ENODEV;
+ }
+ poolname++;
+ } else
+ poolname = pool;
+ }
+
+ fd = open(mntdir, O_RDONLY);
+ if (fd < 0) {
+ rc = -errno;
+ fprintf(stderr, "%s: cannot open '%s': %s\n", progname, mntdir,
+ strerror(errno));
+ return rc;
+ }
+
+ if (flags & MNTDF_SHOW) {
+ if (flags & MNTDF_INODES)
+ printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s\n",
+ "UUID", "Inodes", "IUsed", "IFree",
+ "IUse%", "Mounted on");
+ else
+ printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s\n",
+ "UUID",
+ flags & MNTDF_COOKED ? "bytes" : "1K-blocks",
+ "Used", "Available", "Use%", "Mounted on");
+ }
+
+ for (tp = types; tp->st_name != NULL; tp++) {
+ bool have_ost = false;
+
+ if (!(tp->st_op & ops))
+ continue;
+
+ for (index = 0; ; index++) {
+ memset(&stat_buf, 0, sizeof(struct obd_statfs));
+ memset(&uuid_buf, 0, sizeof(struct obd_uuid));
+ type = flags & MNTDF_LAZY ?
+ tp->st_op | LL_STATFS_NODELAY : tp->st_op;
+ rc2 = llapi_obd_fstatfs(fd, type, index,
+ &stat_buf, &uuid_buf);
+ if (rc2 == -ENODEV)
+ break;
+ if (rc2 == -EAGAIN)
+ continue;
+ if (rc2 == -ENODATA) { /* Inactive device, OK. */
+ if (!(flags & MNTDF_VERBOSE))
+ continue;
+ } else if (rc2 < 0 && rc == 0) {
+ rc = rc2;
+ }
+
+ /* If we have OSTs then don't report MDT block counts.
+ * For MDT-only filesystems the expectation is that all
+ * layouts have a DoM component. For filesystems with
+ * OSTs, files are not necessarily going to store data
+ * on MDTs, and MDT space is limited to a fraction of
+ * OST space, so don't include it in the summary.
+ */
+ if (tp->st_op == LL_STATFS_LOV && !have_ost) {
+ have_ost = true;
+ sum.os_blocks = 0;
+ sum.os_bfree = 0;
+ sum.os_bavail = 0;
+ }
+
+ if (poolname && tp->st_op == LL_STATFS_LOV &&
+ llapi_search_ost(fsname, poolname,
+ obd_uuid2str(&uuid_buf)) != 1)
+ continue;
+
+ /* the llapi_obd_statfs() call may have returned with
+ * an error, but if it filled in uuid_buf we will at
+ * lease use that to print out a message for that OBD.
+ * If we didn't get anything in the uuid_buf, then fill
+ * it in so that we can print an error message. */
+ if (uuid_buf.uuid[0] == '\0')
+ snprintf(uuid_buf.uuid, sizeof(uuid_buf.uuid),
+ "%s%04x", tp->st_name, index);
+ if (!rc && lsb) {
+ lsb->sb_buf[lsb->sb_count].sd_index = index;
+ lsb->sb_buf[lsb->sb_count].sd_st = stat_buf;
+ lsb->sb_count++;
+ }
+ if (flags & MNTDF_SHOW)
+ showdf(mntdir, &stat_buf,
+ obd_uuid2str(&uuid_buf), flags,
+ tp->st_name, index, rc2);
+
+ if (rc2)
+ continue;
+
+ if (tp->st_op == LL_STATFS_LMV) {
+ sum.os_ffree += stat_buf.os_ffree;
+ sum.os_files += stat_buf.os_files;
+ } else /* if (tp->st_op == LL_STATFS_LOV) */ {
+ ost_ffree += stat_buf.os_ffree;
+ }
+ sum.os_blocks += stat_buf.os_blocks *
+ stat_buf.os_bsize;
+ sum.os_bfree += stat_buf.os_bfree *
+ stat_buf.os_bsize;
+ sum.os_bavail += stat_buf.os_bavail *
+ stat_buf.os_bsize;
+ }
+ }
+
+ 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) {
+ sum.os_files = (sum.os_files - sum.os_ffree) + ost_ffree;
+ sum.os_ffree = ost_ffree;
+ }
+ if (flags & MNTDF_SHOW) {
+ printf("\n");
+ showdf(mntdir, &sum, "filesystem_summary:", flags, NULL, 0, 0);
+ printf("\n");
+ }
+
+ return rc;
+}
+
+static int ll_statfs_data_comp(const void *sd1, const void *sd2)
+{
+ const struct obd_statfs *st1 = &((const struct ll_statfs_data *)sd1)->
+ sd_st;
+ const struct obd_statfs *st2 = &((const struct ll_statfs_data *)sd2)->
+ sd_st;
+ int r1 = obd_statfs_ratio(st1);
+ int r2 = obd_statfs_ratio(st2);
+ int64_t result = r1 - r2;
+
+ /* if both space usage are above 90, compare free inodes */
+ if (r1 > 90 && r2 > 90)
+ result = st2->os_ffree - st1->os_ffree;
+
+ if (result < 0)
+ return -1;
+ else if (result == 0)
+ return 0;
+ else
+ return 1;
+}
+
+/* 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;
+
+ 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 = 'H', .name = "mdt-hash", .has_arg = required_argument },
+ { .val = 'i', .name = "mdt-index", .has_arg = required_argument },
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ { .val = 'i', .name = "index", .has_arg = required_argument },
+#endif
+ { .val = 'o', .name = "mode", .has_arg = required_argument },
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ { .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);
+
+ while ((c = getopt_long(argc, argv, "c:dDi:H:m:o:t:T:", long_opts,
+ NULL)) >= 0) {
+ switch (c) {
+ case 0:
+ /* Long options. */
+ break;
+ case 'c':
+ case 'T':
+ lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s %s: invalid stripe count '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 'd':
+ delete = true;
+ default_stripe = true;
+ break;
+ case 'D':
+ default_stripe = true;
+ break;
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ case 't':
+ fprintf(stderr, "warning: '--hash-type' and '-t' "
+ "deprecated, use '--mdt-hash' or '-H' instead\n");
+#endif
+ case 'H':
+ lsa.lsa_pattern = check_hashtype(optarg);
+ if (lsa.lsa_pattern == 0) {
+ fprintf(stderr,
+ "%s %s: bad stripe hash type '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 'i':
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ if (strcmp(argv[optind - 1], "--index") == 0)
+ fprintf(stderr,
+ "%s %s: warning: '--index' deprecated, use '--mdt-index' instead\n",
+ progname, argv[0]);
+#endif
+ lsa.lsa_nr_tgts = parse_targets(mdts,
+ sizeof(mdts) / sizeof(__u32),
+ lsa.lsa_nr_tgts, optarg);
+ 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_tgts = mdts;
+ if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
+ lsa.lsa_stripe_off = mdts[0];
+ break;
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 16, 53, 0)
+ case 'm':
+ fprintf(stderr, "warning: '-m' is deprecated, "
+ "use '--mode' or '-o' instead\n");
+#endif
+ case 'o':
+ mode_opt = optarg;
+ break;
+ default:
+ fprintf(stderr, "%s %s: unrecognized option '%s'\n",
+ progname, argv[0], argv[optind - 1]);
+ return CMD_HELP;
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, "%s %s: DIR must be specified\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ if (!delete && lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT &&
+ lsa.lsa_stripe_count == LLAPI_LAYOUT_DEFAULT) {
+ fprintf(stderr,
+ "%s %s: stripe offset and count must be specified\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ if (delete &&
+ (lsa.lsa_stripe_off != LLAPI_LAYOUT_DEFAULT ||
+ lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT)) {
+ fprintf(stderr,
+ "%s %s: cannot specify -d with -c or -i options\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ 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_mode = umask(0);
+ }
+
+ /*
+ * initialize stripe parameters, in case param is converted to specific,
+ * i.e, 'lfs mkdir -i -1 -c N', always allocate space for lsp_tgts.
+ */
+ param = calloc(1, offsetof(typeof(*param),
+ lsp_tgts[lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT ?
+ lsa.lsa_stripe_count : lsa.lsa_nr_tgts]));
+ if (param == NULL) {
+ fprintf(stderr,
+ "%s %s: cannot allocate memory for parameters: %s\n",
+ progname, argv[0], strerror(ENOMEM));
+ return CMD_HELP;
+ }
+
+ if (lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT)
+ param->lsp_stripe_count = lsa.lsa_stripe_count;
+ if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
+ param->lsp_stripe_offset = -1;
+ else
+ param->lsp_stripe_offset = lsa.lsa_stripe_off;
+ if (lsa.lsa_pattern != LLAPI_LAYOUT_RAID0)
+ param->lsp_stripe_pattern = lsa.lsa_pattern;
+ else
+ param->lsp_stripe_pattern = LMV_HASH_TYPE_FNV_1A_64;
+ param->lsp_pool = lsa.lsa_pool_name;
+ param->lsp_is_specific = false;
+ if (lsa.lsa_nr_tgts > 1) {
+ if (lsa.lsa_stripe_count > 0 &&
+ lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT &&
+ lsa.lsa_stripe_count != lsa.lsa_nr_tgts) {
+ fprintf(stderr, "error: %s: stripe count %lld doesn't "
+ "match the number of MDTs: %d\n",
+ argv[0], lsa.lsa_stripe_count, lsa.lsa_nr_tgts);
+ free(param);
+ return CMD_HELP;
+ }
+
+ param->lsp_is_specific = true;
+ param->lsp_stripe_count = lsa.lsa_nr_tgts;
+ memcpy(param->lsp_tgts, mdts, sizeof(*mdts) * lsa.lsa_nr_tgts);
+ }
+
+ 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 (!lsb) {
+ lsb = malloc(sizeof(*lsb));
+ if (!lsb) {
+ result = -ENOMEM;
+ break;
+ }
+ }
+ lsb->sb_count = 0;
+
+ /* 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';
+
+ result = llapi_search_mounts(path, 0, mntdir,
+ NULL);
+ if (result < 0 || mntdir[0] == '\0') {
+ fprintf(stderr,
+ "No suitable Lustre mount found\n");
+ break;
+ }
+
+ result = mntdf(mntdir, NULL, NULL, 0,
+ LL_STATFS_LMV, lsb);
+ if (result < 0)
+ break;
+
+ 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;
+ }
+
+ qsort(lsb->sb_buf, lsb->sb_count,
+ sizeof(struct ll_statfs_data),
+ ll_statfs_data_comp);
+
+ auto_distributed = true;
+ }
+
+ if (auto_distributed) {
+ int r;
+ int nr = MAX(param->lsp_stripe_count,
+ lsb->sb_count / 2);
+
+ /* don't use server whose usage is above 90% */
+ while (nr != param->lsp_stripe_count &&
+ obd_statfs_ratio(&lsb->sb_buf[nr].sd_st)
+ > 90)
+ nr = MAX(param->lsp_stripe_count,
+ nr / 2);
+
+ /* get \a r between [0, nr) */
+ r = rand() % nr;
+
+ param->lsp_stripe_offset =
+ lsb->sb_buf[r].sd_index;
+ if (param->lsp_stripe_count > 1) {
+ int i = 0;
+
+ param->lsp_is_specific = true;
+ for (; i < param->lsp_stripe_count; i++)
+ param->lsp_tgts[(i + r) % nr] =
+ lsb->sb_buf[i].sd_index;
+ }
+ }
+
+ result = llapi_dir_create(dname, mode, param);
+ }
+
+ if (result) {
+ fprintf(stderr,
+ "%s setdirstripe: cannot create stripe dir '%s': %s\n",
+ progname, dname, strerror(-result));
+ break;
+ }
+ dname = argv[++optind];
+ } while (dname != NULL);
+
+ if (mode_opt != NULL)
+ umask(previous_mode);
+
+ free(lsb);
+ free(param);
+ return result;
+}
+
+/* functions */
+static int lfs_rmentry(int argc, char **argv)
+{
+ char *dname;
+ int index;
+ int result = 0;
+
+ if (argc <= 1) {
+ fprintf(stderr, "error: %s: missing dirname\n",
+ argv[0]);
+ return CMD_HELP;
+ }
+
+ index = 1;
+ dname = argv[index];
+ while (dname != NULL) {
+ result = llapi_direntry_remove(dname);
+ if (result) {
+ fprintf(stderr, "error: %s: remove dir entry '%s' "
+ "failed\n", argv[0], dname);
+ break;
+ }
+ dname = argv[++index];
+ }
+ return result;
+}
+
+static int lfs_mv(int argc, char **argv)
+{
+ struct lmv_user_md lmu = { LMV_USER_MAGIC };
+ struct find_param param = {
+ .fp_max_depth = -1,
+ .fp_mdt_index = -1,
+ };
+ char *end;
+ int c;
+ int rc = 0;
+ struct option long_opts[] = {
+ { .val = 'm', .name = "mdt-index", .has_arg = required_argument },
+ { .val = 'v', .name = "verbose", .has_arg = no_argument },
+ { .name = NULL } };
+
+ while ((c = getopt_long(argc, argv, "m:M:v", long_opts, NULL)) != -1) {
+ switch (c) {
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
+ case 'M':
+ fprintf(stderr, "warning: '-M' deprecated"
+ ", use '--mdt-index' or '-m' instead\n");
+#endif
+ case 'm':
+ lmu.lum_stripe_offset = strtoul(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "%s mv: bad MDT index '%s'\n",
+ progname, optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 'v':
+ param.fp_verbose = VERBOSE_DETAIL;
+ break;
+ default:
+ fprintf(stderr, "%s mv: unrecognized option '%s'\n",
+ progname, argv[optind - 1]);
+ return CMD_HELP;
+ }
+ }
+
+ if (lmu.lum_stripe_offset == -1) {
+ fprintf(stderr, "%s mv: MDT index must be specified\n",
+ progname);
+ return CMD_HELP;
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "%s mv: DIR must be specified\n", progname);
+ return CMD_HELP;
+ }
+
+
+ /* initialize migrate mdt parameters */
+ param.fp_lmv_md = &lmu;
+ param.fp_migrate = 1;
+ rc = llapi_migrate_mdt(argv[optind], ¶m);
+ if (rc != 0)
+ fprintf(stderr, "%s mv: cannot migrate '%s' to MDT%04x: %s\n",
+ progname, argv[optind], param.fp_mdt_index,
+ strerror(-rc));
+ return rc;
+}
+
+static int lfs_osts(int argc, char **argv)
+{
+ return lfs_tgts(argc, argv);
+}
+
+static int lfs_mdts(int argc, char **argv)
+{
+ return lfs_tgts(argc, argv);
+}
+
+static int lfs_df(int argc, char **argv)
+{
+ char mntdir[PATH_MAX] = {'\0'}, path[PATH_MAX] = {'\0'};
+ enum mntdf_flags flags = MNTDF_SHOW;
+ int ops = LL_STATFS_LMV | LL_STATFS_LOV;
+ int c, rc = 0, index = 0;
+ char fsname[PATH_MAX] = "", *pool_name = NULL;
+ struct option long_opts[] = {
+ { .val = 'h', .name = "human-readable",
+ .has_arg = no_argument },
+ { .val = 'i', .name = "inodes", .has_arg = no_argument },
+ { .val = 'l', .name = "lazy", .has_arg = no_argument },
+ { .val = 'p', .name = "pool", .has_arg = required_argument },
+ { .val = 'v', .name = "verbose", .has_arg = no_argument },
+ { .name = NULL} };
+
+ while ((c = getopt_long(argc, argv, "hilp:v", long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'h':
+ flags |= MNTDF_COOKED;
+ break;
+ case 'i':
+ flags |= MNTDF_INODES;
+ break;
+ case 'l':
+ flags |= MNTDF_LAZY;
+ break;
+ case 'p':
+ pool_name = optarg;
+ break;
+ case 'v':
+ flags |= MNTDF_VERBOSE;
+ break;
+ default:
+ return CMD_HELP;
+ }
+ }
+ if (optind < argc && !realpath(argv[optind], path)) {
+ rc = -errno;
+ fprintf(stderr, "error: invalid path '%s': %s\n",
+ argv[optind], strerror(-rc));
+ return rc;
+ }
+
+ while (!llapi_search_mounts(path, index++, mntdir, fsname)) {
+ /* Check if we have a mount point */
+ if (mntdir[0] == '\0')
+ continue;
+
+ rc = mntdf(mntdir, fsname, pool_name, flags, ops, NULL);
+ if (rc || path[0] != '\0')
+ break;
+ fsname[0] = '\0'; /* avoid matching in next loop */
+ mntdir[0] = '\0'; /* avoid matching in next loop */
+ }
+
+ return rc;
+}
+
+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)];
+
+ while ((c = getopt(argc, argv, "h")) != -1)
+ 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;