*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
#include <lustre_ver.h>
#include <lustre_param.h>
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
+#endif /* !ARRAY_SIZE */
+
/* all functions */
static int lfs_setstripe(int argc, char **argv);
static int lfs_find(int argc, char **argv);
static int lfs_hsm_cancel(int argc, char **argv);
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);
/* Setstripe and migrate share mostly the same parameters */
#define SSM_CMD_COMMON(cmd) \
" [--stripe-index|-i <start_ost_idx>]\n" \
" [--stripe-size|-S <stripe_size>]\n" \
" [--pool|-p <pool_name>]\n" \
- " [--ost-list|-o <ost_indices>]\n"
+ " [--ost|-o <ost_indices>]\n"
#define SSM_HELP_COMMON \
"\tstripe_size: Number of bytes on each OST (0 filesystem default)\n" \
"\t -o <ost_1>,<ost_i>-<ost_j>,<ost_n>\n" \
"\t Or:\n" \
"\t -o <ost_1> -o <ost_i>-<ost_j> -o <ost_n>\n" \
- "\t If --pool is set with --ost-list, then the OSTs\n" \
+ "\t If --pool is set with --ost, then the OSTs\n" \
"\t must be the members of the pool."
#define SETSTRIPE_USAGE \
"\tblock: Block file access during data migration (default)\n" \
"\tnon-block: Abort migrations if concurrent access is detected\n" \
+#define SETDIRSTRIPE_USAGE \
+ " [--mdt-count|-c stripe_count>\n" \
+ " [--mdt-index|-i mdt_index]\n" \
+ " [--mdt-hash|-t mdt_hash]\n" \
+ " [--default_stripe|-D] [--mode|-m mode] <dir>\n" \
+ "\tstripe_count: stripe count of the striped directory\n" \
+ "\tmdt_index: MDT index of first stripe\n" \
+ "\tmdt_hash: hash type of the striped directory. mdt types:\n" \
+ " fnv_1a_64 FNV-1a hash algorithm (default)\n" \
+ " all_char sum of characters % MDT_COUNT (not recommended)\n" \
+ "\tdefault_stripe: set default dirstripe of the directory\n" \
+ "\tmode: the mode of the directory\n"
+
static const char *progname;
static bool file_lease_supported = true;
{"getstripe", lfs_getstripe, 0,
"To list the striping info for a given file or files in a\n"
"directory or recursively for all files in a directory tree.\n"
- "usage: getstripe [--ost|-O <uuid>] [--quiet | -q] [--verbose | -v]\n"
+ "usage: getstripe [--ost|-O <uuid>] [--quiet|-q] [--verbose|-v]\n"
" [--stripe-count|-c] [--stripe-index|-i]\n"
" [--pool|-p] [--stripe-size|-S] [--directory|-d]\n"
- " [--mdt-index|-M] [--recursive|-r] [--raw|-R]\n"
- " [--layout|-L]\n"
+ " [--mdt|-m] [--recursive|-r] [--raw|-R]\n"
+ " [--layout|-L] [--fid|-F] [--generation|-g]\n"
" <directory|filename> ..."},
{"setdirstripe", lfs_setdirstripe, 0,
"To create a striped directory on a specified MDT. This can only\n"
"be done on MDT0 with the right of administrator.\n"
- "usage: setdirstripe <--count|-c stripe_count>\n"
- " [--index|-i mdt_index] [--hash-type|-t hash_type]\n"
- " [--default_stripe|-D ] [--mode|-m mode] <dir>\n"
- "\tstripe_count: stripe count of the striped directory\n"
- "\tmdt_index: MDT index of first stripe\n"
- "\thash_type: hash type of the striped directory. Hash types:\n"
- " fnv_1a_64 FNV-1a hash algorithm (default)\n"
- " all_char sum of characters % MDT_COUNT (not recommended)\n"
- "\tdefault_stripe: set default dirstripe of the directory\n"
- "\tmode: the mode of the directory\n"},
+ "usage: setdirstripe [OPTION] <directory>\n"
+ SETDIRSTRIPE_USAGE},
{"getdirstripe", lfs_getdirstripe, 0,
"To list the striping info for a given directory\n"
"or recursively for all directories in a directory tree.\n"
{"mkdir", lfs_setdirstripe, 0,
"To create a striped directory on a specified MDT. This can only\n"
"be done on MDT0 with the right of administrator.\n"
- "usage: mkdir <--count|-c stripe_count>\n"
- " [--index|-i mdt_index] [--hash-type|-t hash_type]\n"
- " [--default_stripe|-D ] [--mode|-m mode] <dir>\n"
- "\tstripe_count: stripe count of the striped directory\n"
- "\tmdt_index: MDT index of first stripe\n"
- "\thash_type: hash type of the striped directory. Hash types:\n"
- " fnv_1a_64 FNV-1a hash algorithm (default)\n"
- " all_char sum of characters % MDT_COUNT (not recommended)\n"
- "\tdefault_stripe: set default dirstripe of the directory\n"
- "\tmode: the mode of the directory\n"},
+ "usage: mkdir [OPTION] <directory>\n"
+ SETDIRSTRIPE_USAGE},
{"rm_entry", lfs_rmentry, 0,
"To remove the name entry of the remote directory. Note: This\n"
"command will only delete the name entry, i.e. the remote directory\n"
"migrate a directory between MDTs.\n"
"usage: migrate --mdt-index <mdt_idx> [--verbose|-v] "
"<directory>\n"
- "\tmdt_idx: index of the destination MDT\n"},
- {"migrate", lfs_setstripe, 0,
+ "\tmdt_idx: index of the destination MDT\n"
+ "\n"
"migrate file objects from one OST "
"layout\nto another (may be not safe with concurent writes).\n"
- "usage: migrate "
+ "usage: migrate "
"[--stripe-count|-c] <stripe_count>\n"
- "[--stripe-index|-i] <start_ost_index>\n"
- "[--stripe-size|-S] <stripe_size>\n"
- "[--pool|-p] <pool_name>\n"
- "[--ost-list|-o] <ost_indices>\n"
- "[--block|-b]\n"
- "[--non-block|-n]\n"
- "<file|directory>\n"
+ " [--stripe-index|-i] <start_ost_index>\n"
+ " [--stripe-size|-S] <stripe_size>\n"
+ " [--pool|-p] <pool_name>\n"
+ " [--ost-list|-o] <ost_indices>\n"
+ " [--block|-b]\n"
+ " [--non-block|-n]\n"
+ " <file|directory>\n"
"\tstripe_count: number of OSTs to stripe a file over\n"
"\tstripe_ost_index: index of the first OST to stripe a file over\n"
"\tstripe_size: number of bytes to store before moving to the next OST\n"
"use \"migrate\" instead.\n"
"usage: mv <directory|filename> [--mdt-index|-M] <mdt_index> "
"[--verbose|-v]\n"},
+ {"ladvise", lfs_ladvise, 0,
+ "Provide servers with advice about access patterns for a file.\n"
+ "usage: ladvise [--advice|-a ADVICE] [--start|-s START[kMGT]]\n"
+ " [--background|-b]\n"
+ " {[--end|-e END[kMGT]] | [--length|-l LENGTH[kMGT]]}\n"
+ " <file> ..."},
{"help", Parser_help, 0, "help"},
{"exit", Parser_quit, 0, "quit"},
{"quit", Parser_quit, 0, "quit"},
#endif
{"stripe-index", required_argument, 0, 'i'},
{"stripe_index", required_argument, 0, 'i'},
+ {"mdt", required_argument, 0, 'm'},
{"mdt-index", required_argument, 0, 'm'},
{"mdt_index", required_argument, 0, 'm'},
/* --non-block is only valid in migrate mode */
{"non-block", no_argument, 0, 'n'},
+ {"ost", required_argument, 0, 'o'},
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
{"ost-list", required_argument, 0, 'o'},
{"ost_list", required_argument, 0, 'o'},
+#endif
{"pool", required_argument, 0, 'p'},
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 53, 0)
/* This formerly implied "--stripe-size", but was confusing
/* Save the first error encountered. */
if (result2 == 0)
result2 = result;
- fprintf(stderr,
- "error: %s: %s file '%s' failed\n",
+ fprintf(stderr, "error: %s: %s file '%s' failed: %s\n",
argv[0], migrate_mode ? "migrate" : "create",
- fname);
+ fname,
+ pool_name_arg != NULL && result == EINVAL ?
+ "OST not in pool?" : strerror(errno));
continue;
}
}
{"stripe_index", required_argument, 0, 'i'},
{"layout", required_argument, 0, 'L'},
{"mdt", required_argument, 0, 'm'},
+ {"mdt-index", required_argument, 0, 'm'},
+ {"mdt_index", required_argument, 0, 'm'},
{"mtime", required_argument, 0, 'M'},
{"name", required_argument, 0, 'n'},
/* reserve {"or", no_argument, , 0, 'o'}, to match find(1) */
{"stripe_count", no_argument, 0, 'c'},
{"directory", no_argument, 0, 'd'},
{"default", no_argument, 0, 'D'},
+ {"fid", no_argument, 0, 'F'},
{"generation", no_argument, 0, 'g'},
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 53, 0)
/* This formerly implied "stripe-index", but was explicitly
{"stripe-index", no_argument, 0, 'i'},
{"stripe_index", no_argument, 0, 'i'},
{"layout", no_argument, 0, 'L'},
+ {"mdt", no_argument, 0, 'm'},
+ {"mdt-index", no_argument, 0, 'm'},
+ {"mdt_index", no_argument, 0, 'm'},
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
{"mdt-index", no_argument, 0, 'M'},
{"mdt_index", no_argument, 0, 'M'},
+#endif
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 53, 0)
/* This formerly implied "stripe-index", but was confusing
* with "file offset" (which will eventually be needed for
};
int c, rc;
- param->fp_max_depth = 1;
- while ((c = getopt_long(argc, argv, "cdDghiLMoO:pqrRsSv",
+ while ((c = getopt_long(argc, argv, "cdDFghiLmMoO:pqrRsSv",
long_opts, NULL)) != -1) {
switch (c) {
case 'O':
case 'D':
param->fp_get_default_lmv = 1;
break;
+ case 'F':
+ if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+ param->fp_verbose |= VERBOSE_DFID;
+ param->fp_max_depth = 0;
+ }
+ break;
case 'r':
param->fp_recursive = 1;
break;
case 'v':
- param->fp_verbose = VERBOSE_ALL | VERBOSE_DETAIL;
+ param->fp_verbose = VERBOSE_DEFAULT | VERBOSE_DETAIL;
break;
case 'c':
#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 53, 0)
param->fp_max_depth = 0;
}
break;
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
case 'M':
+#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 11, 53, 0)
+ fprintf(stderr, "warning: '-M' deprecated"
+ ", use '-m' instead\n");
+#endif
+#endif
+ case 'm':
if (!(param->fp_verbose & VERBOSE_DETAIL))
param->fp_max_depth = 0;
param->fp_verbose |= VERBOSE_MDTINDEX;
param->fp_max_depth = -1;
if (!param->fp_verbose)
- param->fp_verbose = VERBOSE_ALL;
+ param->fp_verbose = VERBOSE_DEFAULT;
if (param->fp_quiet)
param->fp_verbose = VERBOSE_OBJID;
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);
}
bool delete = false;
struct option long_opts[] = {
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
{"count", required_argument, 0, 'c'},
+#endif
+ {"mdt-count", required_argument, 0, 'c'},
{"delete", no_argument, 0, 'd'},
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
{"index", required_argument, 0, 'i'},
+#endif
+ {"mdt-index", required_argument, 0, 'i'},
{"mode", required_argument, 0, 'm'},
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
{"hash-type", required_argument, 0, 't'},
+#endif
+ {"mdt-hash", required_argument, 0, 't'},
{"default_stripe", no_argument, 0, 'D'},
{0, 0, 0, 0}
};
/* Long options. */
break;
case 'c':
+#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 11, 53, 0)
+ if (strcmp(argv[optind - 1], "--count") == 0)
+ fprintf(stderr, "warning: '--count' deprecated"
+ ", use '--mdt-count' instead\n");
+#endif
stripe_count_opt = optarg;
break;
case 'd':
default_stripe = true;
break;
case 'i':
+#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 11, 53, 0)
+ if (strcmp(argv[optind - 1], "--index") == 0)
+ fprintf(stderr, "warning: '--index' deprecated"
+ ", use '--mdt-index' instead\n");
+#endif
stripe_offset_opt = optarg;
break;
case 'm':
mode_opt = optarg;
break;
case 't':
+#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 11, 53, 0)
+ if (strcmp(argv[optind - 1], "--hash-type") == 0)
+ fprintf(stderr, "warning: '--hash-type' "
+ "deprecated, use '--mdt-hash' "
+ "instead\n");
+#endif
stripe_hash_opt = optarg;
break;
default:
mnt = argv[optind];
rc1 = llapi_quotactl(mnt, &qctl);
- if (rc1 < 0) {
- switch (rc1) {
- case -ESRCH:
- fprintf(stderr, "%s quotas are not enabled.\n",
- qctl.qc_type == USRQUOTA ? "user" : "group");
- goto out;
- case -EPERM:
- fprintf(stderr, "Permission denied.\n");
- case -ENOENT:
- /* We already got a "No such file..." message. */
- goto out;
- default:
- fprintf(stderr, "Unexpected quotactl error: %s\n",
- strerror(-rc1));
- }
- }
+ if (rc1 < 0) {
+ switch (rc1) {
+ case -ESRCH:
+ fprintf(stderr, "%s quotas are not enabled.\n",
+ qctl.qc_type == USRQUOTA ? "user" : "group");
+ goto out;
+ case -EPERM:
+ fprintf(stderr, "Permission denied.\n");
+ case -ENODEV:
+ case -ENOENT:
+ /* We already got error message. */
+ goto out;
+ default:
+ fprintf(stderr, "Unexpected quotactl error: %s\n",
+ strerror(-rc1));
+ }
+ }
if (qctl.qc_cmd == LUSTRE_Q_GETQUOTA && !quiet)
print_quota_title(name, &qctl, human_readable);
static int lfs_lsetfacl(int argc, char **argv)
{
- argv[0]++;
- return(llapi_lsetfacl(argc, argv));
+ fprintf(stderr, "local client sets facl for remote client.\n"
+ "obsolete, does not support it anymore.\n");
+ return 0;
}
static int lfs_lgetfacl(int argc, char **argv)
{
- argv[0]++;
- return(llapi_lgetfacl(argc, argv));
+ fprintf(stderr, "local client gets facl for remote client.\n"
+ "obsolete, does not support it anymore.\n");
+ return 0;
}
static int lfs_rsetfacl(int argc, char **argv)
{
- argv[0]++;
- return(llapi_rsetfacl(argc, argv));
+ fprintf(stderr, "remote client sets facl for remote client.\n"
+ "obsolete, does not support it anymore.\n");
+ return 0;
}
static int lfs_rgetfacl(int argc, char **argv)
{
- argv[0]++;
- return(llapi_rgetfacl(argc, argv));
+ fprintf(stderr, "remote client gets facl for remote client.\n"
+ "obsolete, does not support it anymore.\n");
+ return 0;
}
static int lfs_cp(int argc, char **argv)
{
- return(llapi_cp(argc, argv));
+ fprintf(stderr, "remote client copy file(s).\n"
+ "obsolete, does not support it anymore.\n");
+ return 0;
}
static int lfs_ls(int argc, char **argv)
{
- return(llapi_ls(argc, argv));
+ fprintf(stderr, "remote client lists directory contents.\n"
+ "obsolete, does not support it anymore.\n");
+ return 0;
}
static int lfs_changelog(int argc, char **argv)
SWAP_LAYOUTS_KEEP_ATIME);
}
+static const char *const ladvise_names[] = LU_LADVISE_NAMES;
+
+static enum lu_ladvise_type lfs_get_ladvice(const char *string)
+{
+ enum lu_ladvise_type advice;
+
+ for (advice = 0;
+ advice < ARRAY_SIZE(ladvise_names); advice++) {
+ if (ladvise_names[advice] == NULL)
+ continue;
+ if (strcmp(string, ladvise_names[advice]) == 0)
+ return advice;
+ }
+
+ return LU_LADVISE_INVALID;
+}
+
+static int lfs_ladvise(int argc, char **argv)
+{
+ struct option long_opts[] = {
+ {"advice", required_argument, 0, 'a'},
+ {"background", no_argument, 0, 'b'},
+ {"end", required_argument, 0, 'e'},
+ {"start", required_argument, 0, 's'},
+ {"length", required_argument, 0, 'l'},
+ {0, 0, 0, 0}
+ };
+ char short_opts[] = "a:be:l:s:";
+ int c;
+ int rc = 0;
+ const char *path;
+ int fd;
+ struct llapi_lu_ladvise advice;
+ enum lu_ladvise_type advice_type = LU_LADVISE_INVALID;
+ unsigned long long start = 0;
+ unsigned long long end = LUSTRE_EOF;
+ unsigned long long length = 0;
+ unsigned long long size_units;
+ unsigned long long flags = 0;
+
+ optind = 0;
+ while ((c = getopt_long(argc, argv, short_opts,
+ long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'a':
+ advice_type = lfs_get_ladvice(optarg);
+ if (advice_type == LU_LADVISE_INVALID) {
+ fprintf(stderr, "%s: invalid advice type "
+ "'%s'\n", argv[0], optarg);
+ fprintf(stderr, "Valid types:");
+
+ for (advice_type = 0;
+ advice_type < ARRAY_SIZE(ladvise_names);
+ advice_type++) {
+ if (ladvise_names[advice_type] == NULL)
+ continue;
+ fprintf(stderr, " %s",
+ ladvise_names[advice_type]);
+ }
+ fprintf(stderr, "\n");
+
+ return CMD_HELP;
+ }
+ break;
+ case 'b':
+ flags |= LF_ASYNC;
+ break;
+ case 'e':
+ size_units = 1;
+ rc = llapi_parse_size(optarg, &end,
+ &size_units, 0);
+ if (rc) {
+ fprintf(stderr, "%s: bad end offset '%s'\n",
+ argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 's':
+ size_units = 1;
+ rc = llapi_parse_size(optarg, &start,
+ &size_units, 0);
+ if (rc) {
+ fprintf(stderr, "%s: bad start offset "
+ "'%s'\n", argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
+ case 'l':
+ size_units = 1;
+ rc = llapi_parse_size(optarg, &length,
+ &size_units, 0);
+ if (rc) {
+ fprintf(stderr, "%s: bad length '%s'\n",
+ argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
+ case '?':
+ return CMD_HELP;
+ default:
+ fprintf(stderr, "%s: option '%s' unrecognized\n",
+ argv[0], argv[optind - 1]);
+ return CMD_HELP;
+ }
+ }
+
+ if (advice_type == LU_LADVISE_INVALID) {
+ fprintf(stderr, "%s: please give an advice type\n", argv[0]);
+ fprintf(stderr, "Valid types:");
+ for (advice_type = 0; advice_type < ARRAY_SIZE(ladvise_names);
+ advice_type++) {
+ if (ladvise_names[advice_type] == NULL)
+ continue;
+ fprintf(stderr, " %s", ladvise_names[advice_type]);
+ }
+ fprintf(stderr, "\n");
+ return CMD_HELP;
+ }
+
+ if (argc <= optind) {
+ fprintf(stderr, "%s: please give one or more file names\n",
+ argv[0]);
+ return CMD_HELP;
+ }
+
+ if (end != LUSTRE_EOF && length != 0 && end != start + length) {
+ fprintf(stderr, "%s: conflicting arguments of -l and -e\n",
+ argv[0]);
+ return CMD_HELP;
+ }
+
+ if (end == LUSTRE_EOF && length != 0)
+ end = start + length;
+
+ if (end <= start) {
+ fprintf(stderr, "%s: range [%llu, %llu] is invalid\n",
+ argv[0], start, end);
+ return CMD_HELP;
+ }
+
+ while (optind < argc) {
+ int rc2;
+
+ path = argv[optind++];
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: cannot open file '%s': %s\n",
+ argv[0], path, strerror(errno));
+ rc2 = -errno;
+ goto next;
+ }
+
+ advice.lla_start = start;
+ advice.lla_end = end;
+ advice.lla_advice = advice_type;
+ advice.lla_value1 = 0;
+ advice.lla_value2 = 0;
+ advice.lla_value3 = 0;
+ advice.lla_value4 = 0;
+ rc2 = llapi_ladvise(fd, flags, 1, &advice);
+ close(fd);
+ if (rc2 < 0) {
+ fprintf(stderr, "%s: cannot give advice '%s' to file "
+ "'%s': %s\n", argv[0],
+ ladvise_names[advice_type],
+ path, strerror(errno));
+ }
+next:
+ if (rc == 0 && rc2 < 0)
+ rc = rc2;
+ }
+ return rc;
+}
+
int main(int argc, char **argv)
{
int rc;