*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*
* lustre/utils/lfs.c
*
static int lfs_getdirstripe(int argc, char **argv);
static int lfs_setdirstripe(int argc, char **argv);
static int lfs_rmentry(int argc, char **argv);
+static int lfs_unlink_foreign(int argc, char **argv);
static int lfs_osts(int argc, char **argv);
static int lfs_mdts(int argc, char **argv);
static int lfs_df(int argc, char **argv);
struct llapi_stripe_param *param,
struct llapi_layout *layout);
+struct pool_to_id_cbdata {
+ const char *pool;
+ __u32 id;
+};
+static int find_comp_id_by_pool(struct llapi_layout *layout, void *cbdata);
+static int find_mirror_id_by_pool(struct llapi_layout *layout, void *cbdata);
+
enum setstripe_origin {
SO_SETSTRIPE,
SO_MIGRATE,
" [--stripe-size|-S <stripe_size>]\n" \
" [--extension-size|--ext-size|-z]\n" \
" [--layout|-L <pattern>]\n" \
- " [--mirror_count|-N[mirror_count]]\n" \
+ " [--mirror-count|-N[mirror_count]]\n" \
" [--ost|-o <ost_indices>]\n" \
" [--pool|-p <pool_name>]\n" \
" [--yaml|-y <yaml_template_file>]\n" \
" [--copy=<lustre_src>]\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" \
+ "\tstripe_count: Number of OSTs to stripe on (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" \
- "\t respectively)\n" \
- "\textension_size:\n" \
+ "\tstripe_size: Number of bytes on each OST (0=fs default)\n" \
+ "\t Optional K, M, or G suffix (for KB, MB, GB\n" \
+ "\t respectively). Must be a multiple of 64KiB.\n" \
+ "\textension_size:\n" \
"\t Number of bytes the previous component is extended\n" \
- "\t each time. Can be specified with K, M, G (for KB,\n" \
- "\t MB, GB respectively)\n" \
- "\tpool_name: Name of OST pool to use (default none)\n" \
- "\tlayout: stripe pattern type: raid0, mdt (default raid0)\n"\
+ "\t each time. Optional K, M, or G suffix (for KB,\n" \
+ "\t MB, GB respectively)\n" \
+ "\tpool_name: Name of OST pool to use (default none)\n" \
+ "\tlayout: stripe pattern type: raid0, mdt (default raid0)\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 then the OSTs\n" \
- "\t must be the members of the pool.\n" \
- "\tcomp_end: Extent end of component, start after previous end.\n"\
- "\t Can be specified with K, M or G (for KB, MB, GB\n" \
- "\t respectively, -1 for EOF). Must be a multiple of\n"\
- "\t stripe_size.\n" \
- "\tyaml_template_file:\n" \
- "\t YAML layout template file, can't be used with -c,\n" \
- "\t -i, -S, -p, -o, or -E arguments.\n" \
- "\tlustre_src: Lustre file/dir whose layout info is used to set\n" \
- "\t another lustre file or directory, can't used with\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 then the OSTs\n" \
+ "\t must be the members of the pool.\n" \
+ "\tcomp_end: Extent end of component, start after previous end.\n" \
+ "\t Optional K, M, or G suffix (for KiB, MiB, GiB), or\n" \
+ "\t -1 or 'eof' for max file size). Must be a multiple\n" \
+ "\t of stripe_size and a multiple of 64KiB.\n" \
+ "\tyaml_template_file:\n" \
+ "\t YAML layout template file, can't be used with -c,\n" \
+ "\t -i, -S, -p, -o, or -E arguments.\n" \
+ "\tlustre_src: Lustre file/dir whose layout info is used to set\n" \
+ "\t another lustre file or directory, can't used with\n" \
"\t -c, -i, -S, -p, -o, or -E arguments.\n"
#define MIRROR_CREATE_HELP \
"setdirstripe|mkdir --foreign[=<foreign_type>] -x|-xattr <string> " \
"[--mode|-o mode] [--flags <hex>] <dir>\n" \
"\tmode: the mode of the directory\n" \
- "\tforeign_type: none or daos\n"
+ "\tforeign_type: none or symlink\n"
/**
* command_t mirror_cmdlist - lfs mirror commands.
"\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"
+ " or\n"
+ "To set or clear flags on a specific component\n"
+ "(note that this command can only be applied to mirrored files:\n"
+ "usage: setstripe --comp-set {-I comp_id|--comp-flags=comp_flags}\n"
+ " <filename>\n"
+ " or\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"
" [--component-start[=[+-]comp_start]]\n"
" [--component-end[=[+-]comp_end]|-E[[+-]comp_end]]\n"
" [[!] --mirror-index=[+-]<index> |\n"
- " [!] --mirror-id=[+-]<id>]\n"
+ " [!] --mirror-id=[+-]<id>] [--mirror-count|-N]\n"
" <directory|filename> ..."},
{"setdirstripe", lfs_setdirstripe, 0,
"Create striped directory on specified MDT, same as mkdir.\n"
"will become inaccessable after this command. This can only be done\n"
"by the administrator\n"
"usage: rm_entry <dir>\n"},
+ {"unlink_foreign", lfs_unlink_foreign, 0,
+ "To remove the foreign file/dir.\n"
+ "Note: This is for files/dirs prevented to be removed using\n"
+ "unlink/rmdir, but works also for regular ones\n"
+ "usage: unlink_foreign <foreign_dir/file> [<foreign_dir/file> ...]\n"},
{"pool_list", lfs_poollist, 0,
"List pools or pool OSTs\n"
"usage: pool_list <fsname>[.<pool>] | <pathname>\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"
" [[!] --mirror-count|-N [+-]<n>]\n"
" [[!] --mirror-state <[^]state>]\n"
" [[!] --mdt-count|-T [+-]<stripes>]\n"
- " [[!] --mdt-hash|-H <hashtype>\n"
+ " [[!] --mdt-hash|-H <[^][blm],[^]fnv_1a_64,all_char,crush,...>\n"
" [[!] --mdt-index|-m <uuid|index,...>]\n"
"\t !: used before an option indicates 'NOT' requested attribute\n"
"\t -: used before a value indicates less than requested value\n"
"\t +: used before a value indicates more than requested value\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"},
+ "\t ^: used before a flag indicates to exclude it\n"},
{"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"
" clear the project inherit flag and ID on the file or directory\n"
},
#endif
- {"flushctx", lfs_flushctx, 0, "Flush security context for current user.\n"
- "usage: flushctx [-k] [mountpoint...]"},
+ {"flushctx", lfs_flushctx, 0,
+ "Flush security context for current user.\n"
+ "usage: flushctx [-k] [-r] [mountpoint...]"},
{"changelog", lfs_changelog, 0,
"Show the metadata changes on an MDT."
"\nusage: changelog <mdtname> [startrec [endrec]]"},
{"fid2path", lfs_fid2path, 0,
"Resolve the full path(s) for given FID(s). For a specific hardlink "
"specify link number <linkno>.\n"
- "usage: fid2path [-c] [--link|-l <linkno>] <fsname|root> <fid> ..."},
+ "usage: fid2path [--print-fid|-f] [--print-link|-c] [--link|-l <linkno>] "
+ "<fsname|root> <fid>..."},
{"path2fid", lfs_path2fid, 0, "Display the fid(s) for a given path(s).\n"
"usage: path2fid [--parents] <path> ..."},
{"rmfid", lfs_rmfid, 0, "Remove file(s) by FID(s)\n"
MIGRATION_VERBOSE = 0x0008,
};
-static int lfs_component_create(char *fname, int open_flags, mode_t open_mode,
- struct llapi_layout *layout);
-
static int
migrate_open_files(const char *name, __u64 migration_flags,
const struct llapi_stripe_param *param,
}
/* create, open a volatile file, use caching (ie no directio) */
- if (layout)
- fdv = lfs_component_create(volatile_file, open_flags,
- open_mode, layout);
- else
+ if (layout) {
+ /* Returns -1 and sets errno on error: */
+ fdv = llapi_layout_file_open(volatile_file, open_flags,
+ open_mode, layout);
+ if (fdv < 0)
+ fdv = -errno;
+ } else {
+ /* Does the right thing on error: */
fdv = llapi_file_open_param(volatile_file, open_flags,
open_mode, param);
+ }
} while (fdv < 0 && (rc = fdv) == -EEXIST);
if (rc < 0) {
static int migrate_copy_data(int fd_src, int fd_dst, int (*check_file)(int))
{
struct llapi_layout *layout;
- size_t buf_size = 4 * 1024 * 1024;
- void *buf = NULL;
- ssize_t rsize = -1;
- ssize_t wsize = 0;
- size_t rpos = 0;
- size_t wpos = 0;
- off_t bufoff = 0;
- int rc;
+ size_t buf_size = 4 * 1024 * 1024;
+ void *buf = NULL;
+ off_t pos = 0;
+ off_t data_end = 0;
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ bool sparse;
+ int rc;
layout = llapi_layout_get_by_fd(fd_src, 0);
if (layout) {
}
/* Use a page-aligned buffer for direct I/O */
- rc = posix_memalign(&buf, getpagesize(), buf_size);
+ rc = posix_memalign(&buf, page_size, buf_size);
if (rc != 0)
return -rc;
+ sparse = llapi_file_is_sparse(fd_src);
+ if (sparse) {
+ rc = ftruncate(fd_dst, pos);
+ if (rc < 0) {
+ rc = -errno;
+ return rc;
+ }
+ }
+
while (1) {
- /*
- * read new data only if we have written all
- * previously read data
- */
- if (wpos == rpos) {
- if (check_file) {
- rc = check_file(fd_src);
+ off_t data_off;
+ size_t to_read, to_write;
+ ssize_t rsize;
+
+ if (sparse && pos >= data_end) {
+ size_t data_size;
+
+ data_off = llapi_data_seek(fd_src, pos, &data_size);
+ if (data_off < 0) {
+ /* Non-fatal, switch to full copy */
+ sparse = false;
+ continue;
+ }
+ /* hole at the end of file, truncate up to it */
+ if (!data_size) {
+ rc = ftruncate(fd_dst, data_off);
if (rc < 0)
- break;
+ goto out;
}
+ pos = data_off & ~(page_size - 1);
+ data_end = data_off + data_size;
+ to_read = ((data_end - pos - 1) | (page_size - 1)) + 1;
+ to_read = MIN(to_read, buf_size);
+ } else {
+ to_read = buf_size;
+ }
- rsize = read(fd_src, buf, buf_size);
- if (rsize < 0) {
- rc = -errno;
- break;
- }
- rpos += rsize;
- bufoff = 0;
+ if (check_file) {
+ rc = check_file(fd_src);
+ if (rc < 0)
+ goto out;
}
- /* eof ? */
- if (rsize == 0)
- break;
- wsize = write(fd_dst, buf + bufoff, rpos - wpos);
- if (wsize < 0) {
+ rsize = pread(fd_src, buf, to_read, pos);
+ if (rsize < 0) {
rc = -errno;
+ goto out;
+ }
+ /* EOF */
+ if (rsize == 0)
break;
+
+ to_write = rsize;
+ while (to_write > 0) {
+ ssize_t written;
+
+ written = pwrite(fd_dst, buf, to_write, pos);
+ if (written < 0) {
+ rc = -errno;
+ goto out;
+ }
+ pos += written;
+ to_write -= written;
}
- wpos += wsize;
- bufoff += wsize;
+ if (rc || rsize < to_read)
+ break;
}
- if (rc == 0) {
- rc = fsync(fd_dst);
- if (rc < 0)
- rc = -errno;
- }
+ rc = fsync(fd_dst);
+ if (rc < 0)
+ rc = -errno;
+out:
+ /* Try to avoid page cache pollution after migration. */
+ (void)posix_fadvise(fd_src, 0, 0, POSIX_FADV_DONTNEED);
+ (void)posix_fadvise(fd_dst, 0, 0, POSIX_FADV_DONTNEED);
free(buf);
return rc;
return 0;
}
-static int lfs_component_set(char *fname, int comp_id,
+static
+int lfs_layout_compid_by_pool(char *fname, const char *pool, int *comp_id)
+{
+ struct pool_to_id_cbdata data = { .pool = pool };
+ struct llapi_layout *layout = NULL;
+ int rc;
+
+ layout = llapi_layout_get_by_path(fname, 0);
+ if (!layout) {
+ fprintf(stderr,
+ "error %s: file '%s' couldn't get layout: rc=%d\n",
+ progname, fname, errno);
+ rc = -errno;
+ goto free_layout;
+ }
+ rc = llapi_layout_sanity(layout, false, true);
+ if (rc < 0) {
+ llapi_layout_sanity_perror(errno);
+ goto free_layout;
+ }
+ rc = llapi_layout_comp_iterate(layout, find_comp_id_by_pool, &data);
+ if (rc < 0)
+ goto free_layout;
+
+ *comp_id = data.id;
+ rc = 0;
+
+free_layout:
+ if (layout)
+ llapi_layout_free(layout);
+ return rc;
+}
+
+static int lfs_component_set(char *fname, int comp_id, const char *pool,
__u32 flags, __u32 neg_flags)
{
__u32 ids[2];
size_t count = 0;
int rc;
+ if (!comp_id) {
+ if (pool == NULL) {
+ fprintf(stderr,
+ "error %s: neither component id nor pool is specified\n",
+ progname);
+ return -EINVAL;
+ }
+ rc = lfs_layout_compid_by_pool(fname, pool, &comp_id);
+ if (rc)
+ return rc;
+ }
+
if (flags) {
ids[count] = comp_id;
flags_array[count] = flags;
static int comp_str2flags(char *string, __u32 *flags, __u32 *neg_flags)
{
char *name;
-
- if (!string)
- return -EINVAL;
+ char *dup_string = NULL;
+ int rc = 0;
*flags = 0;
*neg_flags = 0;
- for (name = strtok(string, ","); name; name = strtok(NULL, ",")) {
+
+ if (!string || !string[0])
+ return -EINVAL;
+
+ dup_string = strdup(string);
+ if (!dup_string) {
+ llapi_printf(LLAPI_MSG_ERROR,
+ "%s: insufficient memory\n",
+ progname);
+ return -ENOMEM;
+ }
+
+ for (name = strtok(dup_string, ","); name; name = strtok(NULL, ",")) {
bool found = false;
int i;
llapi_printf(LLAPI_MSG_ERROR,
"%s: component flag '%s' not supported\n",
progname, name);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_free;
}
}
if (!*flags && !*neg_flags)
- return -EINVAL;
+ rc = -EINVAL;
/* don't allow to set and exclude the same flag */
if (*flags & *neg_flags)
+ rc = -EINVAL;
+
+out_free:
+ free(dup_string);
+ return rc;
+}
+
+static int mdthash_input(char *string, __u32 *inflags,
+ __u32 *exflags, __u32 *type)
+{
+ char *name;
+ struct mhf_list {
+ char *name;
+ __u32 flag;
+ } mhflist[] = {
+ {"migrating", LMV_HASH_FLAG_MIGRATION},
+ {"badtype", LMV_HASH_FLAG_BAD_TYPE},
+ {"lostlmv", LMV_HASH_FLAG_LOST_LMV},
+ };
+
+ if (string == NULL)
return -EINVAL;
+ *inflags = 0;
+ *exflags = 0;
+ *type = 0;
+ for (name = strtok(string, ","); name; name = strtok(NULL, ",")) {
+ bool found = false;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mhflist); i++) {
+ if (strcmp(name, mhflist[i].name) == 0 ||
+ name[0] == mhflist[i].name[0]) {
+ *inflags |= mhflist[i].flag;
+ found = true;
+ } else if (name[0] == '^' &&
+ (strcmp(name + 1, mhflist[i].name) == 0 ||
+ name[1] == mhflist[i].name[0])) {
+ *exflags |= mhflist[i].flag;
+ found = true;
+ }
+ }
+ if (!found) {
+ i = check_hashtype(name);
+ if (i > 0) {
+ *type |= 1 << i;
+ continue;
+ }
+ llapi_printf(LLAPI_MSG_ERROR,
+ "%s: invalid mdt_hash value '%s'\n",
+ progname, name);
+ return -EINVAL;
+ }
+ }
+
+ /* don't allow to include and exclude the same flag */
+ if (*inflags & *exflags) {
+ llapi_printf(LLAPI_MSG_ERROR,
+ "%s: include and exclude same flag '%s'\n",
+ progname, string);
+ return -EINVAL;
+ }
+
return 0;
}
}
static int mirror_extend_layout(char *name, struct llapi_layout *m_layout,
- bool inherit)
+ bool inherit, uint32_t flags)
{
struct llapi_layout *f_layout = NULL;
struct ll_ioc_lease *data = NULL;
goto out;
}
}
- rc = migrate_open_files(name, 0, NULL, m_layout, &fd, &fdv);
+ llapi_layout_comp_flags_set(m_layout, flags);
+ rc = migrate_open_files(name, MIGRATION_NONDIRECT, NULL, m_layout, &fd,
+ &fdv);
if (rc < 0)
goto out;
while (mirror_count > 0) {
rc = mirror_extend_layout(fname,
mirror_list->m_layout,
- mirror_list->m_inherit);
+ mirror_list->m_inherit,
+ mirror_list->m_flags);
if (rc)
break;
return LLAPI_LAYOUT_ITER_CONT;
}
-struct pool_to_id_cbdata {
- const char *pool;
- __u32 id;
-};
+static int find_mirror_id_by_pool(struct llapi_layout *layout, void *cbdata)
+{
+ char buf[LOV_MAXPOOLNAME + 1];
+ struct pool_to_id_cbdata *d = (void *)cbdata;
+ uint32_t id;
+ int rc;
+
+ rc = llapi_layout_pool_name_get(layout, buf, sizeof(buf));
+ if (rc < 0)
+ return rc;
+ if (strcmp(d->pool, buf))
+ return LLAPI_LAYOUT_ITER_CONT;
+
+ rc = llapi_layout_mirror_id_get(layout, &id);
+ if (rc < 0)
+ return rc;
+ d->id = id;
+
+ return LLAPI_LAYOUT_ITER_STOP;
+}
static int find_comp_id_by_pool(struct llapi_layout *layout, void *cbdata)
{
if (strcmp(d->pool, buf))
return LLAPI_LAYOUT_ITER_CONT;
- rc = llapi_layout_mirror_id_get(layout, &id);
+ rc = llapi_layout_comp_id_get(layout, &id);
if (rc < 0)
return rc;
d->id = id;
__u32 mirror_id;
int mdt_index;
int fd, fdv;
+ bool purge = true; /* delete mirror by setting fdv=fd */
int rc;
+ if (victim_file && (strcmp(fname, victim_file) == 0)) {
+ fprintf(stderr,
+ "error %s: the source file '%s' and -f file are the same\n",
+ progname, fname);
+ return -EINVAL;
+ }
+
/* check fname contains mirror with mirror_id/comp_id */
layout = llapi_layout_get_by_path(fname, 0);
if (!layout) {
if (mflags & MF_COMP_POOL) {
struct pool_to_id_cbdata data = { .pool = pool };
- rc = llapi_layout_comp_iterate(layout, find_comp_id_by_pool,
+ rc = llapi_layout_comp_iterate(layout, find_mirror_id_by_pool,
&data);
mirror_id = data.id;
} else if (mflags & MF_COMP_ID) {
goto close_fd;
}
+again:
if (!victim_file) {
/* use a temp file to store the splitted layout */
if (mflags & MF_DESTROY) {
goto close_fd;
}
- fdv = llapi_create_volatile_idx(parent, mdt_index,
- O_LOV_DELAY_CREATE);
+ if (purge) {
+ /* don't use volatile file for mirror destroy */
+ fdv = fd;
+ } else {
+ /**
+ * try the old way to delete mirror using
+ * volatile file.
+ */
+ fdv = llapi_create_volatile_idx(parent,
+ mdt_index, O_LOV_DELAY_CREATE);
+ }
} else {
snprintf(victim, sizeof(victim), "%s.mirror~%u",
fname, mirror_id);
data->lil_ids[1] = mirror_id;
rc = llapi_lease_set(fd, data);
if (rc <= 0) {
+ if (rc == -EINVAL && purge) {
+ /* could be old MDS which prohibit fd==fdv */
+ purge = false;
+ goto again;
+
+ }
if (rc == 0) /* lost lease lock */
rc = -EBUSY;
fprintf(stderr,
free(data);
close_victim:
- close(fdv);
+ if (!purge)
+ close(fdv);
close_fd:
close(fd);
free_layout:
end_of_loop = *ptr == '\0';
*ptr = '\0';
+ errno = 0;
start_index = strtol(arg, &endptr, 0);
if (endptr == arg) /* no data at all */
break;
- if (*endptr != '-' && *endptr != '\0') /* has invalid data */
+ if (errno != 0 || start_index < -1 ||
+ (*endptr != '-' && *endptr != '\0'))
break;
end_index = start_index;
if (*endptr == '-') {
+ errno = 0;
end_index = strtol(endptr + 1, &endptr, 0);
- if (*endptr != '\0')
+ if (errno != 0 || *endptr != '\0' || end_index < -1)
break;
if (end_index < start_index)
break;
case LFS_COMP_NO_VERIFY_OPT:
mirror_flags |= MF_NO_VERIFY;
break;
- case LFS_MIRROR_ID_OPT:
- mirror_id = strtoul(optarg, &end, 0);
- if (*end != '\0' || mirror_id == 0) {
+ case LFS_MIRROR_ID_OPT: {
+ unsigned long int id;
+
+ errno = 0;
+ id = strtoul(optarg, &end, 0);
+ if (errno != 0 || *end != '\0' || id == 0 ||
+ id > UINT16_MAX) {
fprintf(stderr,
"%s %s: invalid mirror ID '%s'\n",
progname, argv[0], optarg);
goto usage_error;
}
+
+ mirror_id = (__u16)id;
break;
+ }
case LFS_LAYOUT_FLAGS_OPT: {
uint32_t neg_flags;
/* check for numeric flags (foreign and mirror cases) */
if (setstripe_mode && !mirror_mode && !last_mirror) {
+ errno = 0;
flags = strtoul(optarg, &end, 16);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' ||
+ flags >= UINT32_MAX) {
fprintf(stderr,
- "%s %s: bad flags '%s'\n",
+ "%s %s: invalid hex flags '%s'\n",
progname, argv[0], optarg);
return CMD_HELP;
}
+ if (!foreign_mode) {
+ fprintf(stderr,
+ "%s %s: hex flags must be specified with --foreign option\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
break;
}
optarg);
return CMD_HELP;
}
+ } else if (type >= UINT32_MAX) {
+ fprintf(stderr,
+ "%s %s: invalid foreign type '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
}
}
foreign_mode = true;
lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
/* fall through */
case 'c':
+ errno = 0;
lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0'||
+ lsa.lsa_stripe_count < -1 ||
+ lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) {
fprintf(stderr,
"%s %s: invalid stripe count '%s'\n",
progname, argv[0], optarg);
lsa.lsa_comp_end = LUSTRE_EOF;
} else {
result = llapi_parse_size(optarg,
- &lsa.lsa_comp_end,
- &size_units, 0);
- if (result) {
+ &lsa.lsa_comp_end,
+ &size_units, 0);
+ /* assume units of KB if too small */
+ if (lsa.lsa_comp_end < 4096)
+ lsa.lsa_comp_end *= 1024;
+ if (result ||
+ lsa.lsa_comp_end & (LOV_MIN_STRIPE_SIZE - 1)) {
fprintf(stderr,
"%s %s: invalid component end '%s'\n",
progname, argv[0], optarg);
}
break;
case 'i':
+ errno = 0;
lsa.lsa_stripe_off = strtol(optarg, &end, 0);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' ||
+ lsa.lsa_stripe_off < -1 ||
+ lsa.lsa_stripe_off > LOV_V1_INSANE_STRIPE_COUNT) {
fprintf(stderr,
"%s %s: invalid stripe offset '%s'\n",
progname, argv[0], optarg);
}
mirror_count = 1;
if (optarg) {
+ errno = 0;
mirror_count = strtoul(optarg, &end, 0);
- if (*end != '\0' || mirror_count == 0) {
+ if (errno != 0 || *end != '\0' ||
+ mirror_count == 0 ||
+ mirror_count > LUSTRE_MIRROR_COUNT_MAX) {
fprintf(stderr,
"error: %s: bad mirror count: %s\n",
progname, optarg);
case 'S':
result = llapi_parse_size(optarg, &lsa.lsa_stripe_size,
&size_units, 0);
- if (result) {
+ /* assume units of KB if too small to be valid */
+ if (lsa.lsa_stripe_size < 4096)
+ lsa.lsa_stripe_size *= 1024;
+ if (result ||
+ lsa.lsa_stripe_size & (LOV_MIN_STRIPE_SIZE - 1)) {
fprintf(stderr,
"%s %s: invalid stripe size '%s'\n",
progname, argv[0], optarg);
}
}
- if (comp_set && !comp_id) {
+ if (comp_set && !comp_id && !lsa.lsa_pool_name) {
fprintf(stderr,
"%s %s: --component-set doesn't have component-id set\n",
progname, argv[0]);
layout = llapi_layout_get_by_path(template ?: fname, 0);
if (!layout) {
fprintf(stderr,
- "%s: can't create composite layout from file %s.\n",
- progname, template ?: fname);
+ "%s: can't create composite layout from file %s: %s\n",
+ progname, template ?: fname,
+ strerror(errno));
+ result = -errno;
goto error;
}
}
layout);
} else if (comp_set != 0) {
result = lfs_component_set(fname, comp_id,
+ lsa.lsa_pool_name,
lsa.lsa_comp_flags,
lsa.lsa_comp_neg_flags);
} else if (comp_del != 0) {
comp_id = mirror_id;
else
mirror_flags |= MF_COMP_ID;
+ if (has_m_file && !strcmp(fname, mirror_list->m_file)) {
+ fprintf(stderr,
+ "%s: the file specified by -f cannot be same as the source file '%s'\n",
+ progname, fname);
+ goto usage_error;
+ }
result = mirror_split(fname, comp_id, lsa.lsa_pool_name,
mirror_flags,
has_m_file ? mirror_list->m_file :
return llapi_poollist(argv[1]);
}
+#define FP_DEFAULT_TIME_MARGIN (24 * 60 * 60)
static time_t set_time(struct find_param *param, time_t *time, time_t *set,
char *str)
{
long long t = 0;
- int res = 0;
+ int sign = 0;
char *endptr = "AD";
char *timebuf;
if (str[0] == '+')
- res = 1;
+ sign = 1;
else if (str[0] == '-')
- res = -1;
+ sign = -1;
- if (res)
+ if (sign)
str++;
for (timebuf = str; *endptr && *(endptr + 1); timebuf = endptr + 1) {
unit *= 52; /* 52 weeks + 1 day below */
case 'w': /* fallthrough */
unit *= 7;
+ if (param->fp_time_margin == FP_DEFAULT_TIME_MARGIN)
+ param->fp_time_margin *= (1 + unit / 52);
+ unit += (*endptr == 'y'); /* +1 day for 365 days/year */
case '\0': /* days are default unit if none used */
case 'd': /* fallthrough */
- unit = (unit + (*endptr == 'y')) * 24;
+ unit *= 24;
case 'h': /* fallthrough */
unit *= 60;
case 'm': /* fallthrough */
t += val * unit;
}
if (*time < t) {
- if (res != 0)
+ if (sign != 0)
str--;
fprintf(stderr, "%s find: bad time '%s': too large\n",
progname, str);
*set = *time - t;
- return res;
+ return sign;
+}
+
+static int str2quotaid(__u32 *id, const char *arg)
+{
+ unsigned long int projid_tmp = 0;
+ char *endptr = NULL;
+
+ projid_tmp = strtoul(arg, &endptr, 10);
+ if (*endptr != '\0')
+ return -EINVAL;
+ if (projid_tmp >= UINT32_MAX)
+ return -ERANGE;
+
+ *id = projid_tmp;
+ return 0;
}
static int name2uid(unsigned int *id, const char *name)
struct find_param param = {
.fp_max_depth = -1,
.fp_quiet = 1,
- .fp_time_margin = 24 * 60 * 60,
+ .fp_time_margin = FP_DEFAULT_TIME_MARGIN,
};
struct option long_opts[] = {
{ .val = 'A', .name = "atime", .has_arg = required_argument },
.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 = LFS_NEWERXY_OPT,
.name = "newer", .has_arg = required_argument},
{ .val = LFS_NEWERXY_OPT,
optarg++;
}
+ errno = 0;
param.fp_comp_count = strtoul(optarg, &endptr, 0);
- if (*endptr != '\0') {
+ if (errno != 0 || *endptr != '\0' ||
+ param.fp_comp_count > UINT32_MAX) {
fprintf(stderr,
"error: bad component count '%s'\n",
optarg);
optarg++;
}
+ errno = 0;
param.fp_stripe_count = strtoul(optarg, &endptr, 0);
- if (*endptr != '\0') {
+ if (errno != 0 || *endptr != '\0' ||
+ param.fp_stripe_count > LOV_MAX_STRIPE_COUNT) {
fprintf(stderr,
"error: bad stripe_count '%s'\n",
optarg);
param.fp_exclude_stripe_count = !!neg_opt;
break;
case 'D':
+ errno = 0;
param.fp_max_depth = strtol(optarg, 0, 0);
+ if (errno != 0 || param.fp_max_depth < 0) {
+ fprintf(stderr,
+ "error: bad maxdepth '%s'\n",
+ optarg);
+ ret = -1;
+ goto err;
+ }
break;
case 'E':
if (optarg[0] == '+') {
rc = llapi_parse_size(optarg,
¶m.fp_comp_end,
¶m.fp_comp_end_units, 0);
+ /* assume units of KB if too small */
+ if (param.fp_comp_end < 4096)
+ param.fp_comp_end *= 1024;
}
if (rc) {
fprintf(stderr,
optarg);
return CMD_HELP;
}
+ } else if (type >= UINT32_MAX) {
+ fprintf(stderr,
+ "%s %s: invalid foreign type '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
}
}
param.fp_foreign_type = type;
case 'G':
rc = name2gid(¶m.fp_gid, optarg);
if (rc) {
- param.fp_gid = strtoul(optarg, &endptr, 10);
- if (*endptr != '\0') {
+ if (str2quotaid(¶m.fp_gid, optarg)) {
fprintf(stderr,
"Group/GID: %s cannot be found.\n",
optarg);
param.fp_check_gid = 1;
break;
case 'H':
- param.fp_hash_type = check_hashtype(optarg);
- if (param.fp_hash_type == 0) {
- fprintf(stderr, "error: bad hash_type '%s'\n",
- optarg);
+ rc = mdthash_input(optarg, ¶m.fp_hash_inflags,
+ ¶m.fp_hash_exflags,
+ ¶m.fp_hash_type);
+ if (rc) {
ret = -1;
goto err;
}
- param.fp_check_hash_type = 1;
+ if (param.fp_hash_inflags || param.fp_hash_exflags)
+ param.fp_check_hash_flag = 1;
param.fp_exclude_hash_type = !!neg_opt;
break;
case 'l':
case 'U':
rc = name2uid(¶m.fp_uid, optarg);
if (rc) {
- param.fp_uid = strtoul(optarg, &endptr, 10);
- if (*endptr != '\0') {
+ if (str2quotaid(¶m.fp_uid, optarg)) {
fprintf(stderr,
"User/UID: %s cannot be found.\n",
optarg);
optarg++;
}
+ errno = 0;
param.fp_mirror_count = strtoul(optarg, &endptr, 0);
- if (*endptr != '\0') {
+ if (errno != 0 || *endptr != '\0' ||
+ param.fp_mirror_count > LUSTRE_MIRROR_COUNT_MAX) {
fprintf(stderr,
"error: bad mirror count '%s'\n",
optarg);
case LFS_PROJID_OPT:
rc = name2projid(¶m.fp_projid, optarg);
if (rc) {
- param.fp_projid = strtoul(optarg, &endptr, 10);
- if (*endptr != '\0') {
+ if (str2quotaid(¶m.fp_projid, optarg)) {
fprintf(stderr,
- "Invalid project ID: %s",
+ "Invalid project ID: %s\n",
optarg);
ret = -1;
goto err;
ret = llapi_parse_size(optarg, ¶m.fp_stripe_size,
¶m.fp_stripe_size_units, 0);
+ /* assume units of KB if too small to be valid */
+ if (param.fp_stripe_size < 4096)
+ param.fp_stripe_size *= 1024;
if (ret) {
fprintf(stderr, "error: bad stripe_size '%s'\n",
optarg);
optarg++;
}
+ errno = 0;
param.fp_mdt_count = strtoul(optarg, &endptr, 0);
- if (*endptr != '\0') {
+ if (errno != 0 || *endptr != '\0' ||
+ param.fp_mdt_count >= UINT32_MAX) {
fprintf(stderr, "error: bad mdt_count '%s'\n",
optarg);
ret = -1;
param->fp_max_depth = 0;
}
break;
- case LFS_MIRROR_INDEX_OPT:
+ case LFS_MIRROR_INDEX_OPT: {
+ unsigned long int mirror_index;
+
if (optarg[0] == '+') {
param->fp_mirror_index_sign = -1;
optarg++;
optarg++;
}
- param->fp_mirror_index = strtoul(optarg, &end, 0);
- if (*end != '\0' || (param->fp_mirror_index == 0 &&
+ errno = 0;
+ mirror_index = strtoul(optarg, &end, 0);
+ if (errno != 0 || *end != '\0' ||
+ mirror_index > UINT16_MAX || (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;
}
+
+ param->fp_mirror_index = (__u16)mirror_index;
+
if (param->fp_mirror_id != 0) {
fprintf(stderr,
"%s %s: can't specify both mirror index and mirror ID\n",
param->fp_check_mirror_index = 1;
param->fp_exclude_mirror_index = !!neg_opt;
break;
- case LFS_MIRROR_ID_OPT:
+ }
+ case LFS_MIRROR_ID_OPT: {
+ unsigned long int mirror_id;
+
if (optarg[0] == '+') {
param->fp_mirror_id_sign = -1;
optarg++;
optarg++;
}
- param->fp_mirror_id = strtoul(optarg, &end, 0);
- if (*end != '\0' || (param->fp_mirror_id == 0 &&
+ errno = 0;
+ mirror_id = strtoul(optarg, &end, 0);
+ if (errno != 0 || *end != '\0' ||
+ mirror_id > UINT16_MAX || (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;
}
+
+ param->fp_mirror_id = (__u16)mirror_id;
+
if (param->fp_mirror_index != 0) {
fprintf(stderr,
"%s %s: can't specify both mirror index and mirror ID\n",
param->fp_check_mirror_id = 1;
param->fp_exclude_mirror_id = !!neg_opt;
break;
+ }
case 'd':
param->fp_max_depth = 0;
break;
rc = llapi_parse_size(tmp,
¶m->fp_comp_end,
¶m->fp_comp_end_units, 0);
+ /* assume units of KB if too small */
+ if (param->fp_comp_end < 4096)
+ param->fp_comp_end *= 1024;
}
if (rc != 0) {
fprintf(stderr,
MNTDF_LAZY = 0x0004,
MNTDF_VERBOSE = 0x0008,
MNTDF_SHOW = 0x0010,
+ MNTDF_DECIMAL = 0x0020,
};
-#define COOK(value) \
+#define COOK(value, base) \
({ \
int radix = 0; \
- while (value > 1024) { \
- value /= 1024; \
+ while (value > base) { \
+ value /= base; \
radix++; \
} \
radix; \
{
long long avail, used, total;
int ratio = 0;
- char *suffix = "KMGTPEZY";
+ char *suffix = flags & MNTDF_DECIMAL ? "kMGTPEZY" : "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)];
ratio = obd_statfs_ratio(stat, flags & MNTDF_INODES);
if (flags & MNTDF_COOKED) {
- int i;
+ int base = flags & MNTDF_DECIMAL ? 1000 : 1024;
double cook_val;
+ int i;
cook_val = (double)total;
- i = COOK(cook_val);
+ i = COOK(cook_val, base);
if (i > 0)
snprintf(tbuf, sizeof(tbuf), HDF, cook_val,
suffix[i - 1]);
snprintf(tbuf, sizeof(tbuf), CDF, total);
cook_val = (double)used;
- i = COOK(cook_val);
+ i = COOK(cook_val, base);
if (i > 0)
snprintf(ubuf, sizeof(ubuf), HDF, cook_val,
suffix[i - 1]);
snprintf(ubuf, sizeof(ubuf), CDF, used);
cook_val = (double)avail;
- i = COOK(cook_val);
+ i = COOK(cook_val, base);
if (i > 0)
snprintf(abuf, sizeof(abuf), HDF, cook_val,
suffix[i - 1]);
continue;
/*
- * the llapi_obd_statfs() call may have returned with
+ * the llapi_obd_fstatfs() 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
mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
mode_t previous_mode = 0;
char *xattr = NULL;
- __u32 type = LU_FOREIGN_TYPE_DAOS, flags = 0;
+ __u32 type = LU_FOREIGN_TYPE_SYMLINK, flags = 0;
struct option long_opts[] = {
{ .val = 'c', .name = "count", .has_arg = required_argument },
{ .val = 'c', .name = "mdt-count", .has_arg = required_argument },
break;
case 'c':
case 'T':
+ errno = 0;
lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' ||
+ lsa.lsa_stripe_count < -1 ||
+ lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) {
fprintf(stderr,
"%s %s: invalid stripe count '%s'\n",
progname, argv[0], optarg);
optarg);
return CMD_HELP;
}
+ } else if (type >= UINT32_MAX) {
+ fprintf(stderr,
+ "%s %s: invalid foreign type '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
}
}
foreign_mode = true;
break;
case LFS_LAYOUT_FLAGS_OPT:
+ errno = 0;
flags = strtoul(optarg, &end, 16);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' ||
+ flags >= UINT32_MAX) {
fprintf(stderr,
- "%s %s: bad flags '%s'\n",
+ "%s %s: invalid hex flags '%s'\n",
progname, argv[0], optarg);
return CMD_HELP;
}
+ if (!foreign_mode) {
+ fprintf(stderr,
+ "%s %s: hex flags must be specified with --foreign option\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
break;
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
case 't':
if (!delete && lsa.lsa_stripe_off == 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]);
- return CMD_HELP;
+ /* if no parameters set, create directory on least-used MDTs */
+ lsa.lsa_stripe_off = -1;
+ lsa.lsa_stripe_count = 1;
}
if (delete &&
return result;
}
+static int lfs_unlink_foreign(int argc, char **argv)
+{
+ char *name;
+ int index;
+ int result = 0;
+
+ if (argc <= 1) {
+ fprintf(stderr, "error: %s: missing pathname\n",
+ argv[0]);
+ return CMD_HELP;
+ }
+
+ index = 1;
+ name = argv[index];
+ while (name != NULL) {
+ result = llapi_unlink_foreign(name);
+ if (result) {
+ fprintf(stderr,
+ "error: %s: unlink foreign entry '%s' failed\n",
+ argv[0], name);
+ break;
+ }
+ name = argv[++index];
+ }
+ return result;
+}
+
static int lfs_mv(int argc, char **argv)
{
struct lmv_user_md lmu = { LMV_USER_MAGIC };
"warning: '-M' deprecated, use '--mdt-index' or '-m' instead\n");
#endif
case 'm':
+ errno = 0;
lmu.lum_stripe_offset = strtoul(optarg, &end, 0);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' ||
+ lmu.lum_stripe_offset >= UINT32_MAX) {
fprintf(stderr, "%s mv: bad MDT index '%s'\n",
progname, optarg);
return CMD_HELP;
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 = 'h', .name = "human-readable", .has_arg = no_argument },
+ { .val = 'H', .name = "si", .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) {
+ while ((c = getopt_long(argc, argv, "hHilp:v", long_opts, NULL)) != -1) {
switch (c) {
case 'h':
- flags |= MNTDF_COOKED;
+ flags = (flags & ~MNTDF_DECIMAL) | MNTDF_COOKED;
+ break;
+ case 'H':
+ flags |= MNTDF_COOKED | MNTDF_DECIMAL;
break;
case 'i':
flags |= MNTDF_INODES;
{ .val = 'p', .name = "projid", .has_arg = no_argument },
{ .val = 't', .name = "times", .has_arg = no_argument },
{ .val = 'u', .name = "user", .has_arg = no_argument },
- { .val = 'o', .name = "pool", .has_arg = required_argument },
+ { .val = LFS_POOL_OPT,
+ .name = "pool", .has_arg = required_argument },
{ .name = NULL } };
int qtype;
qctl->qc_cmd = LUSTRE_Q_SETINFO;
qctl->qc_type = ALLQUOTA;
- while ((c = getopt_long(argc, argv, "b:gi:ptuo:",
+ while ((c = getopt_long(argc, argv, "b:gi:ptu",
long_opts, NULL)) != -1) {
switch (c) {
case 'u':
break;
case 't': /* Yes, of course! */
break;
- case 'o':
+ case LFS_POOL_OPT:
if (lfs_verify_poolarg(optarg))
return -1;
fprintf(stdout,
{ .val = 'P', .name = "default-prj", .has_arg = no_argument },
{ .val = 'u', .name = "user", .has_arg = required_argument },
{ .val = 'U', .name = "default-usr", .has_arg = no_argument },
- { .val = 'o', .name = "pool", .has_arg = required_argument },
+ { .val = LFS_POOL_OPT,
+ .name = "pool", .has_arg = required_argument },
{ .name = NULL } };
unsigned int limit_mask = 0;
- char *endptr;
bool use_default = false;
int qtype, qctl_len;
* isn't reinitialized from command line
*/
- while ((c = getopt_long(argc, argv, "b:B:dg:Gi:I:p:Pu:Uo:",
+ while ((c = getopt_long(argc, argv, "b:B:dg:Gi:I:p:Pu:U",
long_opts, NULL)) != -1) {
switch (c) {
case 'U':
rc = name2projid(&qctl->qc_id, optarg);
quota_type:
if (rc) {
- qctl->qc_id = strtoul(optarg, &endptr, 10);
- if (*endptr != '\0') {
+ if (str2quotaid(&qctl->qc_id, optarg)) {
fprintf(stderr,
"%s setquota: invalid id '%s'\n",
progname, optarg);
(unsigned long long)dqb->dqb_ihardlimit,
progname);
break;
- case 'o':
+ case LFS_POOL_OPT:
if (lfs_verify_poolarg(optarg)) {
rc = -1;
goto out;
}
}
+static int tgt_name2index(const char *tgtname, unsigned int *idx)
+{
+ char *dash, *endp;
+
+ /* format is "lustre-OST0001" */
+ dash = memchr(tgtname, '-', LUSTRE_MAXFSNAME + 1);
+ if (!dash) {
+ fprintf(stderr, "wrong tgtname format '%s'\n", tgtname);
+ return -EINVAL;
+ }
+ dash += 4;
+
+ *idx = strtoul(dash, &endp, 16);
+ if (*idx > 0xffff) {
+ fprintf(stderr, "wrong index %s\n", tgtname);
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
static int print_obd_quota(char *mnt, struct if_quotactl *qctl, int is_mdt,
bool h, __u64 *total)
{
- int rc = 0, rc1 = 0, count = 0;
+ int rc = 0, rc1 = 0, count = 0, i = 0;
+ char **list = NULL, *buffer = NULL;
__u32 valid = qctl->qc_valid;
- /*
- * TODO: for commands LUSTRE_Q_"S\|G"ETQUOTAPOOL we need
- * to go only through OSTs that belong to requested pool.
- */
+ if (qctl->qc_cmd == LUSTRE_Q_GETQUOTAPOOL && is_mdt)
+ return 0;
+
+ /* Is it correct for the case OST0000, OST0002, OST0003 -
+ * we will ask OST0001 that is absent and won't ask OST0003? */
rc = llapi_get_obd_count(mnt, &count, is_mdt);
if (rc) {
fprintf(stderr, "can not get %s count: %s\n",
return rc;
}
- for (qctl->qc_idx = 0; qctl->qc_idx < count; qctl->qc_idx++) {
+ if (qctl->qc_cmd == LUSTRE_Q_GETQUOTAPOOL) {
+ char fname[PATH_MAX];
+ char fsname[LUSTRE_MAXFSNAME + 1];
+ int bufsize = sizeof(struct obd_uuid) * count;
+
+ rc = llapi_search_fsname(mnt, fsname);
+ if (rc) {
+ fprintf(stderr, "cannot get fsname for mountpoint %s\n",
+ mnt);
+ goto out;
+ }
+ buffer = malloc(bufsize + sizeof(*list) * count);
+ if (!buffer)
+ return -ENOMEM;
+ list = (char **)(buffer + bufsize);
+ snprintf(fname, PATH_MAX, "%s.%s", fsname, qctl->qc_poolname);
+ count = llapi_get_poolmembers(fname, list, count,
+ buffer, bufsize);
+ if (count <= 0)
+ goto out;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (qctl->qc_cmd == LUSTRE_Q_GETQUOTAPOOL) {
+ unsigned int index;
+
+ if (tgt_name2index(list[i], &index))
+ continue;
+ qctl->qc_idx = index;
+ } else {
+ qctl->qc_idx = i;
+ }
+
qctl->qc_valid = is_mdt ? QC_MDTIDX : QC_OSTIDX;
rc = llapi_quotactl(mnt, qctl);
if (rc) {
qctl->qc_dqblk.dqb_bhardlimit;
}
out:
+ if (buffer)
+ free(buffer);
qctl->qc_valid = valid;
return rc ? : rc1;
}
phc.recursive = true;
break;
case 'p':
- phc.projid = strtoul(optarg, NULL, 0);
+ if (str2quotaid(&phc.projid, optarg)) {
+ fprintf(stderr,
+ "Invalid project ID: %s\n",
+ optarg);
+ return CMD_HELP;
+ }
+
phc.assign_projid = true;
break;
struct if_quotactl *qctl;
char *obd_uuid;
int rc = 0, rc1 = 0, verbose = 0, quiet = 0;
- char *endptr;
__u32 valid = QC_GENERAL, idx = 0;
bool human_readable = false;
bool show_default = false;
int qtype;
struct option long_opts[] = {
- { .val = 1, .name = "pool", .has_arg = required_argument },
+ { .val = LFS_POOL_OPT, .name = "pool", .has_arg = required_argument },
{ .name = NULL } };
qctl = calloc(1, sizeof(*qctl) + LOV_MAXPOOLNAME + 1);
case 'h':
human_readable = true;
break;
- case 1:
+ case LFS_POOL_OPT:
if (lfs_verify_poolarg(optarg)) {
rc = -1;
goto out;
}
if (rc) {
- qctl->qc_id = strtoul(name, &endptr, 10);
- if (*endptr != '\0') {
+ if (str2quotaid(&qctl->qc_id, name)) {
fprintf(stderr, "%s quota: invalid id '%s'\n",
progname, name);
rc = CMD_HELP;
static int lfs_flushctx(int argc, char **argv)
{
- int kdestroy = 0, c;
+ int kdestroy = 0, reap = 0, c;
char mntdir[PATH_MAX] = {'\0'};
int index = 0;
int rc = 0;
- while ((c = getopt(argc, argv, "k")) != -1) {
+ while ((c = getopt(argc, argv, "kr")) != -1) {
switch (c) {
case 'k':
kdestroy = 1;
break;
+ case 'r':
+ reap = 1;
+ break;
default:
fprintf(stderr,
"error: %s: option '-%c' unrecognized\n",
rc = -1;
}
}
+
+ if (reap) {
+ rc = system("keyctl reap > /dev/null");
+ if (rc != 0) {
+ rc = WEXITSTATUS(rc);
+ fprintf(stderr, "error reaping keyring: %d\n", rc);
+ }
+ }
+
return rc;
}
}
mdd = argv[optind++];
- if (argc > optind)
+ if (argc > optind) {
+ errno = 0;
startrec = strtoll(argv[optind++], NULL, 10);
- if (argc > optind)
+ if (errno != 0 || startrec < 0) {
+ fprintf(stderr,
+ "%s changelog: bad startrec\n",
+ progname);
+ return CMD_HELP;
+ }
+ }
+
+ if (argc > optind) {
+ errno = 0;
endrec = strtoll(argv[optind++], NULL, 10);
+ if (errno != 0 || endrec < 0) {
+ fprintf(stderr,
+ "%s changelog: bad endrec\n",
+ progname);
+ return CMD_HELP;
+ }
+ }
rc = llapi_changelog_start(&changelog_priv,
CHANGELOG_FLAG_BLOCK |
}
}
+ if (!fid_is_zero(&rec->cr_pfid))
+ printf(" p="DFID, PFID(&rec->cr_pfid));
if (rec->cr_namelen)
- printf(" p="DFID" %.*s", PFID(&rec->cr_pfid),
- rec->cr_namelen, changelog_rec_name(rec));
+ printf(" %.*s", rec->cr_namelen,
+ changelog_rec_name(rec));
if (rec->cr_flags & CLF_RENAME) {
struct changelog_ext_rename *rnm =
if (argc != 4)
return CMD_HELP;
+ errno = 0;
endrec = strtoll(argv[3], NULL, 10);
+ if (errno != 0 || endrec < 0) {
+ fprintf(stderr,
+ "%s: bad endrec '%s'\n",
+ argv[0], argv[3]);
+ return CMD_HELP;
+ }
rc = llapi_changelog_clear(argv[1], argv[2], endrec);
return rc;
}
+static void rstripc(char *str, int c)
+{
+ char *end = str + strlen(str);
+
+ for (; str < end && end[-1] == c; --end)
+ end[-1] = '\0';
+}
+
static int lfs_fid2path(int argc, char **argv)
{
struct option long_opts[] = {
{ .val = 'c', .name = "cur", .has_arg = no_argument },
+ { .val = 'c', .name = "current", .has_arg = no_argument },
+ { .val = 'c', .name = "print-link", .has_arg = no_argument },
+ { .val = 'f', .name = "print-fid", .has_arg = no_argument },
{ .val = 'l', .name = "link", .has_arg = required_argument },
- { .val = 'r', .name = "rec", .has_arg = required_argument },
{ .name = NULL } };
- char short_opts[] = "cl:r:";
- char *device, *fid, *path;
+ char short_opts[] = "cfl:pr:";
+ bool print_link = false;
+ bool print_fid = false;
+ bool print_mnt_dir;
+ char mnt_dir[PATH_MAX] = "";
+ int mnt_fd = -1;
+ char *path_or_fsname;
long long recno = -1;
int linkno = -1;
- int lnktmp;
- int printcur = 0;
- int rc = 0;
char *endptr = NULL;
+ int rc = 0;
+ int c;
+ int i;
- while ((rc = getopt_long(argc, argv, short_opts,
- long_opts, NULL)) != -1) {
- switch (rc) {
+ while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (c) {
case 'c':
- printcur++;
+ print_link = true;
+ break;
+ case 'f':
+ print_fid = true;
break;
case 'l':
+ errno = 0;
linkno = strtol(optarg, &endptr, 10);
- if (*endptr != '\0') {
+ if (errno != 0 || *endptr != '\0' || linkno < 0) {
fprintf(stderr,
"%s fid2path: invalid linkno '%s'\n",
progname, optarg);
}
break;
case 'r':
+ /* recno is something to do with changelogs
+ * that was never implemented. We just pass it
+ * through for the MDT to ignore.
+ */
+ errno = 0;
recno = strtoll(optarg, &endptr, 10);
- if (*endptr != '\0') {
+ if (errno != 0 || *endptr != '\0' || recno < 0) {
fprintf(stderr,
"%s fid2path: invalid recno '%s'\n",
progname, optarg);
}
}
- if (argc < 3) {
+ if (argc - optind < 2) {
fprintf(stderr,
- "%s fid2path: <fsname|rootpath> and <fid>... must be specified\n",
+ "Usage: %s fid2path FSNAME|ROOT FID...\n",
progname);
return CMD_HELP;
}
- device = argv[optind++];
- path = calloc(1, PATH_MAX);
- if (!path) {
- rc = -errno;
+ path_or_fsname = argv[optind];
+
+ if (*path_or_fsname == '/') {
+ print_mnt_dir = true;
+ rc = llapi_search_mounts(path_or_fsname, 0, mnt_dir, NULL);
+ } else {
+ print_mnt_dir = false;
+ rc = llapi_search_rootpath(mnt_dir, path_or_fsname);
+ }
+
+ if (rc < 0) {
fprintf(stderr,
- "%s fid2path: cannot allocate memory for path: %s\n",
- progname, strerror(-rc));
- return rc;
+ "%s fid2path: cannot resolve mount point for '%s': %s\n",
+ progname, path_or_fsname, strerror(-rc));
+ goto out;
}
- rc = 0;
- while (optind < argc) {
- fid = argv[optind++];
+ mnt_fd = open(mnt_dir, O_RDONLY | O_DIRECTORY);
+ if (mnt_fd < 0) {
+ fprintf(stderr,
+ "%s fid2path: cannot open mount point for '%s': %s\n",
+ progname, path_or_fsname, strerror(-rc));
+ goto out;
+ }
+
+ /* Strip trailing slashes from mnt_dir. */
+ rstripc(mnt_dir + 1, '/');
+
+ for (i = optind + 1; i < argc; i++) {
+ const char *fid_str = argv[i];
+ struct lu_fid fid;
+ int rc2;
+
+ rc2 = llapi_fid_parse(fid_str, &fid, NULL);
+ if (rc2 < 0) {
+ fprintf(stderr,
+ "%s fid2path: invalid FID '%s'\n",
+ progname, fid_str);
+ if (rc == 0)
+ rc = rc2;
+
+ continue;
+ }
- lnktmp = (linkno >= 0) ? linkno : 0;
+ int linktmp = (linkno >= 0) ? linkno : 0;
while (1) {
- int oldtmp = lnktmp;
+ int oldtmp = linktmp;
long long rectmp = recno;
- int rc2;
+ char path_buf[PATH_MAX];
- rc2 = llapi_fid2path(device, fid, path, PATH_MAX,
- &rectmp, &lnktmp);
+ rc2 = llapi_fid2path_at(mnt_fd, &fid,
+ path_buf, sizeof(path_buf), &rectmp, &linktmp);
if (rc2 < 0) {
fprintf(stderr,
- "%s fid2path: cannot find '%s': %s\n",
- progname, fid, strerror(errno = -rc2));
+ "%s fid2path: cannot find %s %s: %s\n",
+ progname, path_or_fsname, fid_str,
+ strerror(-rc2));
if (rc == 0)
rc = rc2;
break;
}
- if (printcur)
- fprintf(stdout, "%lld ", rectmp);
- if (device[0] == '/') {
- fprintf(stdout, "%s", device);
- if (device[strlen(device) - 1] != '/')
- fprintf(stdout, "/");
- } else if (path[0] == '\0') {
- fprintf(stdout, "/");
- }
- fprintf(stdout, "%s\n", path);
+ if (print_fid)
+ printf("%s ", fid_str);
+
+ if (print_link)
+ printf("%d ", linktmp);
+
+ /* You may think this looks wrong or weird (and it is!)
+ * but we are actually trying to preserve the old quirky
+ * behaviors (enforced by our old quirky tests!) that
+ * make lfs so much fun to work on:
+ *
+ * lustre 0x200000007:0x1:0x0 => "/"
+ * /mnt/lustre 0x200000007:0x1:0x0 => "/mnt/lustre//"
+ *
+ * Note that llapi_fid2path() returns "" for the root
+ * FID. */
+
+ printf("%s%s%s\n",
+ print_mnt_dir ? mnt_dir : "",
+ (print_mnt_dir || *path_buf == '\0') ? "/" : "",
+ path_buf);
if (linkno >= 0)
/* specified linkno */
break;
- if (oldtmp == lnktmp)
+
+ if (oldtmp == linktmp)
/* no more links */
break;
}
}
+out:
+ if (!(mnt_fd < 0))
+ close(mnt_fd);
- free(path);
return rc;
}
static int lfs_rmfid_and_show_errors(const char *device, struct fid_array *fa)
{
- int rc, rc2 = 0, k;
+ int rc, rc2, k;
rc = llapi_rmfid(device, fa);
- if (rc) {
- fprintf(stderr, "rmfid(): rc = %d\n", rc);
+ if (rc < 0) {
+ fprintf(stderr, "%s rmfid: cannot remove FIDs: %s\n",
+ progname, strerror(-rc));
return rc;
}
for (k = 0; k < fa->fa_nr; k++) {
- rc = (__s32)fa->fa_fids[k].f_ver;
- if (!IS_ERR_VALUE(rc))
- continue;
- if (!rc2 && rc)
- rc2 = rc;
- if (!rc)
+ rc2 = (__s32)fa->fa_fids[k].f_ver;
+ if (!IS_ERR_VALUE(rc2))
continue;
+
+ if (rc == 0)
+ rc = rc2;
+
fa->fa_fids[k].f_ver = 0;
- fprintf(stderr, "rmfid("DFID"): rc = %d\n",
- PFID(&fa->fa_fids[k]), rc);
+ fprintf(stderr, "%s rmfid: cannot remove "DFID": %s\n",
+ progname, PFID(&fa->fa_fids[k]), strerror(-rc2));
}
- return rc2;
+ return rc;
}
static int lfs_rmfid(int argc, char **argv)
mask |= HS_EXISTS;
break;
case 'i':
+ errno = 0;
archive_id = strtol(optarg, &end, 10);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' || archive_id < 0) {
fprintf(stderr, "invalid archive_id: '%s'\n",
end);
return CMD_HELP;
char *end;
switch (c) {
- case 'N':
- mirror_id = strtoul(optarg, &end, 0);
- if (*end != '\0' || mirror_id == 0) {
+ case 'N': {
+ unsigned long int id;
+
+ errno = 0;
+ id = strtoul(optarg, &end, 0);
+ if (errno != 0 || *end != '\0' || id == 0 ||
+ id > UINT16_MAX) {
fprintf(stderr,
"%s %s: invalid mirror ID '%s'\n",
progname, argv[0], optarg);
return rc;
}
+
+ mirror_id = (__u16)id;
break;
+ }
case 'o':
outfile = optarg;
break;
char *end;
switch (c) {
- case 'N':
- mirror_id = strtoul(optarg, &end, 0);
- if (*end != '\0' || mirror_id == 0) {
+ case 'N': {
+ unsigned long int id;
+
+ errno = 0;
+ id = strtoul(optarg, &end, 0);
+ if (errno != 0 || *end != '\0' || id == 0 ||
+ id > UINT16_MAX) {
fprintf(stderr,
"%s %s: invalid mirror ID '%s'\n",
progname, argv[0], optarg);
return rc;
}
+
+ mirror_id = (__u16)id;
break;
+ }
case 'i':
inputfile = optarg;
break;
char *end;
switch (c) {
- case 'i':
- read_mirror_id = strtoul(optarg, &end, 0);
- if (*end != '\0' || read_mirror_id == 0) {
+ case 'i': {
+ unsigned long int id;
+
+ errno = 0;
+ id = strtoul(optarg, &end, 0);
+ if (errno != 0 || *end != '\0' || id == 0 ||
+ id > UINT16_MAX) {
fprintf(stderr,
"%s %s: invalid read mirror ID '%s'\n",
progname, argv[0], optarg);
return rc;
}
+
+ read_mirror_id = (__u16)id;
break;
+ }
case 'o':
if (!strcmp(optarg, "-1")) {
/* specify all other mirrors */
long_opts, NULL)) != -1) {
switch (c) {
case 'i':
+ errno = 0;
archive_id = strtoul(optarg, &end, 0);
- if (*end != '\0' || archive_id == 0) {
+ if (errno != 0 || *end != '\0' ||
+ archive_id == 0 || archive_id > UINT32_MAX) {
fprintf(stderr,
"error: %s: bad archive ID '%s'\n",
argv[0], optarg);
long_opts, NULL)) != -1) {
switch (c) {
case 'i':
+ errno = 0;
archive_id = strtoul(optarg, &end, 0);
- if (*end != '\0') {
+ if (errno != 0 || *end != '\0' ||
+ archive_id > UINT32_MAX) {
fprintf(stderr,
"error: %s: bad archive ID '%s'\n",
argv[0], optarg);