#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/xattr.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
#include <ctype.h>
#include <zlib.h>
#include <libgen.h>
+#include <asm/byteorder.h>
#include "lfs_project.h"
#include <libcfs/util/string.h>
static int lfs_swap_layouts(int argc, char **argv);
static int lfs_mv(int argc, char **argv);
static int lfs_ladvise(int argc, char **argv);
+static int lfs_getsom(int argc, char **argv);
static int lfs_mirror(int argc, char **argv);
static int lfs_mirror_list_commands(int argc, char **argv);
static int lfs_list_commands(int argc, char **argv);
" [--component-count]\n"
" [--component-start[=[+-]comp_start]]\n"
" [--component-end[=[+-]comp_end]|-E[[+-]comp_end]]\n"
+ " [[!] --mirror-index=[+-]<index> |\n"
+ " [!] --mirror-id=[+-]<id>]\n"
" <directory|filename> ..."},
{"setdirstripe", lfs_setdirstripe, 0,
"To create a striped directory on a specified MDT. This can only\n"
"lfs mirror split - split a mirror from an existing mirrored file\n"
"lfs mirror resync - resynchronize out-of-sync mirrored file(s)\n"
"lfs mirror verify - verify mirrored file(s)\n"},
+ {"getsom", lfs_getsom, 0, "To list the SOM info for a given file.\n"
+ "usage: getsom [-s] [-b] [-f] <path>\n"
+ "\t-s: Only show the size value of the SOM data for a given file\n"
+ "\t-b: Only show the blocks value of the SOM data for a given file\n"
+ "\t-f: Only show the flags value of the SOM data for a given file\n"},
{"help", Parser_help, 0, "help"},
{"exit", Parser_quit, 0, "quit"},
{"quit", Parser_quit, 0, "quit"},
LFS_MIRROR_ID_OPT,
LFS_MIRROR_STATE_OPT,
LFS_LAYOUT_COPY,
+ LFS_MIRROR_INDEX_OPT,
};
/* functions */
.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 = '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::LmMoO:pqrRsSvy",
- long_opts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv,
+ "-cdDE::FghiI::LmMoO: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_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;
}
}
- if (optind >= argc)
+ 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_verbose = VERBOSE_OBJID;
do {
- rc = llapi_getstripe(argv[optind], param);
- } while (++optind < argc && !rc);
+ rc = llapi_getstripe(argv[pathstart], param);
+ } while (++pathstart < pathend && !rc);
if (rc)
fprintf(stderr, "error: %s failed for %s.\n",
struct llapi_layout *layout;
struct stat stbuf;
uint32_t flr_state;
+ uint64_t start;
+ uint64_t end;
int comp_size = 0;
int idx;
int fd;
goto free_layout;
}
- idx = 0;
- while (idx < comp_size) {
- ssize_t result;
- uint64_t end;
- __u16 mirror_id;
- int i;
-
- rc = llapi_lease_check(fd);
- if (rc != LL_LEASE_WRLCK) {
- fprintf(stderr, "%s: '%s' lost lease lock.\n",
- progname, fname);
- goto free_layout;
- }
-
- mirror_id = comp_array[idx].lrc_mirror_id;
- end = comp_array[idx].lrc_end;
-
- /* try to combine adjacent component */
- for (i = idx + 1; i < comp_size; i++) {
- if (mirror_id != comp_array[i].lrc_mirror_id ||
- end != comp_array[i].lrc_start)
- break;
- end = comp_array[i].lrc_end;
- }
-
- result = llapi_mirror_resync_one(fd, layout, mirror_id,
- comp_array[idx].lrc_start,
- end);
- if (result < 0) {
- fprintf(stderr, "%s: '%s' llapi_mirror_resync_one: "
- "%ld.\n", progname, fname, result);
- rc = result;
- goto unlock;
- } else if (result > 0) {
- int j;
-
- /* mark synced components */
- for (j = idx; j < i; j++)
- comp_array[j].lrc_synced = true;
- }
+ /* get the read range [start, end) */
+ start = comp_array[0].lrc_start;
+ end = comp_array[0].lrc_end;
+ for (idx = 1; idx < comp_size; idx++) {
+ if (comp_array[idx].lrc_start < start)
+ start = comp_array[idx].lrc_start;
+ if (end < comp_array[idx].lrc_end)
+ end = comp_array[idx].lrc_end;
+ }
- idx = i;
+ rc = llapi_lease_check(fd);
+ if (rc != LL_LEASE_WRLCK) {
+ fprintf(stderr, "%s: '%s' lost lease lock.\n",
+ progname, fname);
+ goto free_layout;
}
-unlock:
+ rc = llapi_mirror_resync_many(fd, layout, comp_array, comp_size,
+ start, end);
+ if (rc < 0)
+ fprintf(stderr, "%s: '%s' llapi_mirror_resync_many: %d.\n",
+ progname, fname, rc);
+
/* prepare ioc for lease put */
ioc->lil_mode = LL_LEASE_UNLCK;
ioc->lil_flags = LL_LEASE_RESYNC_DONE;
return rc < 0 ? -rc : rc;
}
+static void lustre_som_swab(struct lustre_som_attrs *attrs)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ __swab16s(&attrs->lsa_valid);
+ __swab64s(&attrs->lsa_size);
+ __swab64s(&attrs->lsa_blocks);
+#endif
+}
+
+enum lfs_som_type {
+ LFS_SOM_SIZE = 0x1,
+ LFS_SOM_BLOCKS = 0x2,
+ LFS_SOM_FLAGS = 0x4,
+ LFS_SOM_ATTR_ALL = LFS_SOM_SIZE | LFS_SOM_BLOCKS |
+ LFS_SOM_FLAGS,
+};
+
+static int lfs_getsom(int argc, char **argv)
+{
+ const char *path;
+ struct lustre_som_attrs *attrs;
+ char buf[sizeof(*attrs) + 64];
+ enum lfs_som_type type = LFS_SOM_ATTR_ALL;
+ int rc = 0, c;
+
+ while ((c = getopt(argc, argv, "sbf")) != -1) {
+ switch (c) {
+ case 's':
+ type = LFS_SOM_SIZE;
+ break;
+ case 'b':
+ type = LFS_SOM_BLOCKS;
+ break;
+ case 'f':
+ type = LFS_SOM_FLAGS;
+ break;
+ default:
+ fprintf(stderr, "%s: invalid option '%c'\n",
+ progname, optopt);
+ return CMD_HELP;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ fprintf(stderr, "%s: %s\n",
+ progname, argc == 0 ? "miss file target" :
+ "input more than 2 files");
+ return CMD_HELP;
+ }
+
+ path = argv[0];
+ attrs = (void *)buf;
+ rc = lgetxattr(path, "trusted.som", attrs, sizeof(buf));
+ if (rc < 0) {
+ fprintf(stderr, "%s failed to get som xattr: %s\n", argv[0],
+ strerror(-rc));
+ return rc;
+ }
+
+ lustre_som_swab(attrs);
+
+ switch (type) {
+ case LFS_SOM_ATTR_ALL:
+ printf("file: %s size: %llu blocks: %llu flags: %x\n",
+ path, attrs->lsa_size, attrs->lsa_blocks,
+ attrs->lsa_valid);
+ break;
+ case LFS_SOM_SIZE:
+ printf("%llu\n", attrs->lsa_size);
+ break;
+ case LFS_SOM_BLOCKS:
+ printf("%llu\n", attrs->lsa_blocks);
+ break;
+ case LFS_SOM_FLAGS:
+ printf("%x\n", attrs->lsa_valid);
+ break;
+ default:
+ fprintf(stderr, "%s: unknown option\n", progname);
+ return CMD_HELP;
+ }
+
+ return rc;
+}
+
/**
* lfs_mirror_list_commands() - List lfs mirror commands.
* @argc: The count of command line arguments.