static int lfs_pcc(int argc, char **argv);
static int lfs_pcc_list_commands(int argc, char **argv);
static int lfs_migrate_to_dom(int fd, int fdv, char *name,
- __u64 migration_flags,
- struct llapi_stripe_param *param,
- struct llapi_layout *layout);
+ __u64 migration_flags);
struct pool_to_id_cbdata {
const char *pool;
/* Setstripe and migrate share mostly the same parameters */
#define SSM_CMD_COMMON(cmd) \
"usage: "cmd" [--component-end|-E COMP_END]\n" \
- " [--stripe-count|-c STRIPE_COUNT]\n" \
- " [--overstripe-count|-C STRIPE_COUNT]\n" \
- " [--stripe-index|-i START_OST_IDX]\n" \
- " [--stripe-size|-S STRIPE_SIZE]\n" \
- " [--extension-size|--ext-size|-z]\n" \
+ " [--copy=LUSTRE_SRC]\n" \
+ " [--extension-size|--ext-size|-z SIZE]\n" \
" [--help|-h] [--layout|-L PATTERN]\n" \
- " [--mirror_count|-N[MIRROR_COUNT]]\n" \
+ " [--layout|-L PATTERN]\n" \
+ " [--mirror-count|-N[MIRROR_COUNT]]\n" \
" [--ost|-o OST_INDICES]\n" \
+ " [--overstripe-count|-C STRIPE_COUNT]\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 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 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. 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 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 \
- "\tMIRROR_COUNT: Number of mirrors to be created with the upcoming\n" \
- "\t setstripe layout options\n" \
- "\t It defaults to 1 if not specified; if specified,\n" \
- "\t it must follow the option without a space.\n" \
- "\t The option can also be repeated multiple times to\n" \
- "\t separate mirrors that have different layouts.\n" \
- "\tSETSTRIPE_OPTIONS: Mirror layout as with 'setstripe'\n" \
- "\t It can be a plain layout or a composite layout.\n" \
- "\t If not specified, the stripe options inherited\n" \
- "\t from the previous component will be used.\n" \
- "\tFLAGS: set flags to the component of the current mirror.\n" \
- "\t Only \"prefer\" flag is supported so far.\n"
-
-#define MIRROR_EXTEND_HELP \
- MIRROR_CREATE_HELP \
- "\tVICTIM_FILE: The layout of victim_file will be split and used\n" \
- "\t as a mirror added to the mirrored file.\n" \
- "\tno-verify: This option indicates not to verify the mirror(s)\n" \
- "\t from victim file(s) in case the victim file(s)\n" \
- "\t contains the same data as the original mirrored\n" \
- "\t file.\n"
-
-#define MIRROR_EXTEND_USAGE \
- " {--mirror-count|-N[mirror_count]}\n" \
- " [SETSTRIPE_OPTIONS|-f|--file VICTIM_FILE]\n" \
+ " [--stripe-count|-c STRIPE_COUNT]\n" \
+ " [--stripe-index|-i START_OST_IDX]\n" \
+ " [--stripe-size|-S STRIPE_SIZE]\n" \
+ " [--yaml|-y YAML_TEMPLATE_FILE]\n"
+
+#define MIRROR_EXTEND_USAGE \
+ " {--mirror-count|-N[MIRROR_COUNT]}\n" \
+ " [SETSTRIPE_OPTIONS|-f|--file VICTIM_FILE]\n" \
" [--no-verify]\n"
#define SETSTRIPE_USAGE \
SSM_CMD_COMMON("setstripe") \
MIRROR_EXTEND_USAGE \
- " <directory|filename>\n" \
- SSM_HELP_COMMON \
- MIRROR_EXTEND_HELP
+ " DIRECTORY|FILENAME\n"
#define MIGRATE_USAGE \
SSM_CMD_COMMON("migrate ") \
" [--block|-b] [--non-block|-n]\n" \
" [--non-direct|-D] [--verbose|-v]\n" \
- " <filename>\n" \
- SSM_HELP_COMMON \
- "\n" \
- "\tblock: Block file access during data migration (default)\n" \
- "\tnon-block: Abort migrations if concurrent access is detected\n" \
- "\tnon-direct: Do not use direct I/O to copy file contents\n" \
- "\tverbose: Print each filename as it is migrated\n" \
+ " FILENAME\n"
#define SETDIRSTRIPE_USAGE \
" [--mdt-count|-c stripe_count>\n" \
" [--default|-D] [--mode|-o mode]\n" \
" [--max-inherit|-X max_inherit]\n" \
" [--max-inherit-rr max_inherit_rr] <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" \
- " crush CRUSH hash algorithm (default)\n" \
- " fnv_1a_64 FNV-1a hash algorithm\n" \
- " all_char sum of characters % MDT_COUNT (not recommended)\n" \
- "\tdefault_stripe: set default dirstripe of the directory\n" \
- "\tmode: the file access permission of the directory (octal)\n" \
"To create dir with a foreign (free format) layout :\n" \
"setdirstripe|mkdir --foreign[=FOREIGN_TYPE] -x|-xattr STRING " \
- "[--mode|-o MODE] [--flags HEX] <dir>\n" \
- "\tmode: the file access permissions of the directory\n" \
- "\tforeign_type: none, daos, symlink, or numeric value\n"
+ " [--mode|-o MODE] [--flags HEX] DIRECTORY\n"
/**
* command_t mirror_cmdlist - lfs mirror commands.
command_t mirror_cmdlist[] = {
{ .pc_name = "create", .pc_func = lfs_mirror_create,
.pc_help = "Create a mirrored file.\n"
- "usage: lfs mirror create {--mirror-count|-N[MIRROR_COUNT]}\n"
- "\t\t[SETSTRIPE_OPTIONS] <filename|directory> ...\n"
- MIRROR_CREATE_HELP },
+ "usage: lfs mirror create --mirror-count|-N[MIRROR_COUNT]\n"
+ " [SETSTRIPE_OPTIONS] ... FILENAME|DIRECTORY ...\n" },
{ .pc_name = "delete", .pc_func = lfs_mirror_delete,
.pc_help = "Delete a mirror from a file.\n"
- "usage: lfs mirror delete {--mirror-id MIRROR_ID|-p POOL|\n"
- "\t --component-id|--comp-id|-I COMP_ID} <mirror_file>\n"
+ "usage: lfs mirror delete {--mirror-id <mirror_id> |\n"
+ "\t --component-id|--comp-id|-I COMP_ID |\n"
+ "\t -p <pool>} MIRRORED_FILE ...\n"
},
{ .pc_name = "extend", .pc_func = lfs_mirror_extend,
.pc_help = "Extend a mirrored file.\n"
- "usage: lfs mirror extend {--mirror-count|-N[MIRROR_COUNT]}\n"
- "\t\t[--no-verify] [SETSTRIPE_OPTIONS|-f VICTIM_FILE] ... <filename> ...\n"
- MIRROR_EXTEND_HELP },
+ "usage: lfs mirror extend "
+ "{--mirror-count|-N[MIRROR_COUNT]} [--no-verify] "
+ "[SETSTRIPE_OPTIONS|-f VICTIM_FILE] ... FILENAME ...\n" },
{ .pc_name = "split", .pc_func = lfs_mirror_split,
.pc_help = "Split a mirrored file.\n"
- "usage: lfs mirror split [--destroy|-d] [-f NEW_FILE] [--help|-h]\n"
- "\t\t{--mirror-id MIRROR_ID|--component-id|-I COMP_ID|-p POOL}\n"
- "\t\t<mirrored file> ...\n"
- "\tMIRROR_ID: The numerical unique identifier for a mirror.\n"
- "\t It can be fetched by the 'lfs getstripe' command.\n"
- "\tCOMP_ID: Unique component ID within a mirror.\n"
- "\tPOOL: Components using specified pool.\n"
- "\tNEW_FILE: This option indicates the layout of the split\n"
- "\t mirror will be stored into. If not specified,\n"
- "\t a new file named <mirrored_file>.mirror~MIRROR_ID\n"
- "\t will be used.\n" },
+ "usage: lfs mirror split {--mirror-id MIRROR_ID |\n"
+ "\t --component-id|-I COMP_ID|-p POOL} [--destroy|-d]\n"
+ "\t [-f NEW_FILE] MIRRORED_FILE ...\n" },
{ .pc_name = "read", .pc_func = lfs_mirror_read,
.pc_help = "Read the content of a specified mirror of a file.\n"
"usage: lfs mirror read {--mirror-id|-N MIRROR_ID}\n"
" or\n"
"To add component(s) to an existing composite file:\n"
SSM_CMD_COMMON("setstripe --component-add")
- SSM_HELP_COMMON
"To totally delete the default striping from an existing directory:\n"
"usage: setstripe [--delete|-d] <directory>\n"
" or\n"
{"find", lfs_find, 0,
"find files matching given attributes recursively in directory tree.\n"
"usage: find <directory|filename> ...\n"
- " [[!] --atime|-A [+-]N[smhdwy]] [[!] --ctime|-C [+-]N[smhdwy]]\n"
- " [[!] --mtime|-M [+-]N[smhdwy]]\n"
- " [[!] --btime|--Btime|-B [+-]N[smhdwy]] [--help|-h]\n"
- " [[!] --newer[XY] <reference>] [[!] --blocks|-b N]\n"
- " [--maxdepth|-D N] [[!] --mdt-index|--mdt|-m <uuid|index,...>]\n"
- " [[!] --name|-n <pattern>] [[!] --ost|-O <uuid|index,...>]\n"
- " [[!] --perm [/-]mode] [[!] --pool <pool>] [--print|-P]\n"
- " [--print0|-0] [[!] --projid <projid>]\n"
- " [[!] --size|-s [+-]N[bkMGTPE]]\n"
- " [[!] --stripe-count|-c [+-]<stripes>]\n"
- " [[!] --stripe-index|-i <index,...>]\n"
- " [[!] --stripe-size|-S [+-]N[kMGT]] [[!] --type|-t <filetype>]\n"
- " [[!] --extension-size|--ext-size|-z [+-]N[kMGT]]\n"
- " [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
- " [[!] --uid|-u|--user|-U <uid>|<uname>]\n"
- " [[!] --layout|-L released,raid0,mdt]\n"
- " [[!] --foreign[=<foreign_type>]]\n"
- " [[!] --component-count [+-]<comp_cnt>]\n"
+ " [[!] --atime|-A [+-]N[smhdwy]] [[!] --btime|-B [+-]N[smhdwy]]\n"
+ " [[!] --ctime|-C [+-]N[smhdwy]] [[!] --mtime|-M [+-]N[smhdwy]]\n"
+ " [[!] --blocks|-b N] [[!] --component-count [+-]<comp_cnt>]\n"
" [[!] --component-start [+-]N[kMGTPE]]\n"
" [[!] --component-end|-E [+-]N[kMGTPE]]\n"
" [[!] --component-flags {init,stale,prefer,offline,nosync,extension}]\n"
+ " [[!] --extension-size|--ext-size|-z [+-]N[kMGT]]\n"
+ " [[!] --foreign[=<foreign_type>]]\n"
+ " [[!] --gid|-g|--group|-G <gid>|<gname>] [--help|-h]\n"
+ " [[!] --layout|-L released,raid0,mdt] [--lazy]\n"
+ " [--maxdepth|-D N] [[!] --mdt-count|-T [+-]<stripes>]\n"
+ " [[!] --mdt-hash|-H <[^][blm],[^]fnv_1a_64,all_char,crush,...>\n"
+ " [[!] --mdt-index|--mdt|-m <uuid|index,...>]\n"
" [[!] --mirror-count|-N [+-]<n>]\n"
" [[!] --mirror-state <[^]state>]\n"
- " [[!] --mdt-count|-T [+-]<stripes>]\n"
- " [[!] --mdt-hash|-H <[^][blm],[^]fnv_1a_64,all_char,crush,...>\n"
- " [[!] --mdt-index|-m <uuid|index,...>]\n"
+ " [[!] --name|-n <pattern>] [[!] --newer[XY] <reference>]\n"
+ " [[!] --ost|-O <uuid|index,...>] [[!] --perm [/-]mode]\n"
+ " [[!] --pool <pool>] [--print|-P] [--print0|-0] [--printf <format>]\n"
+ " [[!] --projid <projid>] [[!] --size|-s [+-]N[bkMGTPE]]\n"
+ " [[!] --stripe-count|-c [+-]<stripes>]\n"
+ " [[!] --stripe-index|-i <index,...>]\n"
+ " [[!] --stripe-size|-S [+-]N[kMGT]] [[!] --type|-t <filetype>]\n"
+ " [[!] --uid|-u|--user|-U <uid>|<uname>]\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"
"Usage: getname [--help|-h] [--instance|-i] [--fsname|-n] [path ...]"},
#ifdef HAVE_SYS_QUOTA_H
{"setquota", lfs_setquota, 0, "Set filesystem quotas.\n"
- "usage: setquota {-u|-g|-p} UNAME|UID|GNAME|GID|PROJID\n"
- " -b BLOCK_SOFTLIMIT -B BLOCK_HARDLIMIT\n"
- " -i INODE_SOFTLIMIT -I INODE_HARDLIMIT <filesystem>\n"
- " setquota {-u|--user USER|UID|-g|--group GROUP|GID|-p|--projid PROJID}\n"
- " [--block-softlimit BLOCK_SOFTLIMIT]\n"
- " [--block-hardlimit BLOCK_HARDLIMIT]\n"
- " [--inode-softlimit INODE_SOFTLIMIT]\n"
- " [--inode-hardlimit INODE_HARDLIMIT] <filesystem>\n"
- " setquota [-t] {-h|--help|-u|--user|-g|--group|-p|--projid}\n"
- " [--block-grace 'notify'|BLOCK_GRACE]\n"
- " [--inode-grace 'notify'|INODE_GRACE] <filesystem>\n"
- " setquota {-U|-G|-P}\n"
- " -b BLOCK_SOFTLIMIT -B BLOCK_HARDLIMIT\n"
- " -i INODE_SOFTLIMIT -I INODE_HARDLIMIT <filesystem>\n"
- " setquota {-U|--default-usr|-G|--default-grp|-P|--default-prj}\n"
- " [--block-softlimit BLOCK_SOFTLIMIT]\n"
- " [--block-hardlimit BLOCK_HARDLIMIT]\n"
- " [--inode-softlimit INODE_SOFTLIMIT]\n"
- " [--inode-hardlimit INODE_HARDLIMIT] <filesystem>\n"
- " setquota {-u|-g|-p} UNAME|UID|GNAME|GID|PROJID\n"
- " {-d|--default}\n"
- " -b can be used instead of --block-softlimit/--block-grace\n"
- " -B can be used instead of --block-hardlimit\n"
- " -i can be used instead of --inode-softlimit/--inode-grace\n"
- " -I can be used instead of --inode-hardlimit\n"
- " -d can be used instead of --default\n\n"
- "Note: The total quota space will be split into many qunits and\n"
- " balanced over all server targets, the minimal qunit size is\n"
- " 1M bytes for block space and 1K inodes for inode space.\n\n"
- " The maximum quota grace time is 2^48 - 1 seconds.\n\n"
- " Quota space rebalancing process will stop when this mininum\n"
- " value is reached. As a result, quota exceeded can be returned\n"
- " while many targets still have 1MB or 1K inodes of spare\n"
- " quota space.\n\n"
- " When setting the grace time, 'notify' can be used as grace to\n"
- " be notified after the quota is over soft limit but prevents\n"
- " the soft limit from becoming the hard limit."},
+ "usage: setquota [-t][-D] {-u|-U|-g|-G|-p|-P} {-b|-B|-i|-I LIMIT} [--pool POOL] FILESYSTEM\n"
+ " setquota {-u|-g|-p} --delete FILESYSTEM\n"},
{"quota", lfs_quota, 0, "Display disk usage and limits.\n"
"usage: quota [-q] [-v] [-h] [-o OBD_UUID|-i MDT_IDX|-I OST_IDX]\n"
- " [{-u|-g|-p} UNAME|UID|GNAME|GID|PROJID] <filesystem>\n"
- " quota [-o OBD_UUID|-i MDT_IDX|-I OST_IDX] -t {-u|-g|-p} <filesystem>\n"
- " quota [-q] [-v] [h] {-U|-G|-P} <filesystem>"},
+ " [{-u|-g|-p} UNAME|UID|GNAME|GID|PROJID]\n"
+ " [--pool <OST pool name>] <filesystem>\n"
+ " quota -t <-u|-g|-p> [--pool <OST pool name>] <filesystem>\n"
+ " quota [-q] [-v] [h] {-U|-G|-P} [--pool <OST pool name>] <filesystem>"},
{"project", lfs_project, 0,
"Change or list project attribute for specified file or directory.\n"
"usage: project [-d|-r] <file|directory...>\n"
" set project ID and/or inherit flag for specified file(s) or directories\n"
" project -c [-d|-r [-p id] [-0]] <file|directory...>\n"
" check project ID and flags on file(s) or directories, print outliers\n"
- " project -C [-r] [-k] <file|directory...>\n"
+ " project -C [-d|-r] [-k] <file|directory...>\n"
" clear the project inherit flag and ID on the file or directory\n"
},
#endif
{"swap_layouts", lfs_swap_layouts, 0, "Swap layouts between 2 files.\n"
"usage: swap_layouts <path1> <path2>"},
{"migrate", lfs_setstripe_migrate, 0,
- "migrate a directory between MDTs.\n"
- "usage: migrate [--mdt-count|-c STRIPE_COUNT]\n"
+ "migrate directories and their inodes between MDTs.\n"
+ "usage: migrate [--mdt-count|-c STRIPE_COUNT] [--directory|-d]\n"
" [--mdt-hash|-H HASH_TYPE]\n"
" [--mdt-index|-m START_MDT_INDEX] [--verbose|-v]\n"
- " <directory>\n"
- "\tmdt: MDTs to stripe over, if only one MDT is specified\n"
- " it's the MDT index of first stripe\n"
- "\tmdt_count: number of MDTs to stripe a directory over\n"
- "\tmdt_hash: hash type of the striped directory. mdt types:\n"
- " all_char (type 1)sum of characters % MDT_COUNT\n"
- " fnv_1a_64 (type 2)FNV-1a hash algorithm (default)\n"
- " crush (type 3)CRUSH hash algorithm\n"
+ " DIRECTORY\n"
"\n"
- "migrate file objects from one OST "
- "layout\nto another (may be not safe with concurent writes).\n"
- "usage: migrate [--stripe-count|-c STRIPE_COUNT]\n"
- " [--overstripe-count|-C STRIPE_COUNT]\n"
- " [--stripe-index|-i START_OST_INDEX]\n"
- " [--stripe-size|-S STRIPE_SIZE]\n"
- " [--pool|-p <pool_name>] [--ost|-o OST_INDICES]\n"
- " [--block|-b] [--non-block|-n] [--non-direct|-D]\n"
- " <file|directory>\n"
- "\tstripe_count: number of OSTs to stripe a file over\n"
- "\t Using -C instead of -c allows overstriping, which\n"
- "\t will place more than one stripe per OST if\n"
- "\t stripe_count is greater than the number of OSTs\n"
- "\tstripe_ost_index: index of the first OST to stripe a file over\n"
- "\tstripe_size: number of bytes to store before moving to the next OST\n"
- "\tpool_name: name of the predefined pool of OSTs\n"
- "\tost_indices: OSTs to stripe over, in order\n"
- "\tblock: Block file access during data migration (default)\n"
- "\tnon-block: Abort migrations if concurrent access is detected\n"
- "\tnon-direct: do not use direct I/O to copy file contents.\n"},
+ "migrate file objects from one OST layout to another\n"
+ "(may be not safe with concurent writes).\n"
+ MIGRATE_USAGE },
{"mv", lfs_mv, 0,
"To move directories between MDTs. This command is deprecated, "
"use \"migrate\" instead.\n"
int i;
/* numeric hash type */
- if (hashtype && strlen(hashtype) == 1 &&
- (type_num > 0 && type_num < LMV_HASH_TYPE_MAX))
+ if (hashtype && lmv_is_known_hash_type(type_num))
return type_num;
/* string hash type */
- for (i = LMV_HASH_TYPE_ALL_CHARS; i < LMV_HASH_TYPE_MAX; i++)
+ for (i = LMV_HASH_TYPE_ALL_CHARS; i < ARRAY_SIZE(mdt_hash_name); i++)
if (strcmp(hashtype, mdt_hash_name[i]) == 0)
return i;
static const char *error_loc = "syserror";
-enum {
- MIGRATION_NONBLOCK = 0x0001,
- MIGRATION_MIRROR = 0x0002,
- MIGRATION_NONDIRECT = 0x0004,
- MIGRATION_VERBOSE = 0x0008,
-};
-
static int
migrate_open_files(const char *name, __u64 migration_flags,
const struct llapi_stripe_param *param,
*ptr = '\0';
}
- /* open file, direct io */
/* even if the file is only read, WR mode is nedeed to allow
* layout swap on fd
*/
- rflags = O_RDWR | O_NOATIME;
- if (!(migration_flags & MIGRATION_NONDIRECT))
+ /* Allow migrating even without the key on encrypted files */
+ rflags = O_RDWR | O_NOATIME | O_FILE_ENC;
+ if (!(migration_flags & LLAPI_MIGRATION_NONDIRECT))
rflags |= O_DIRECT;
+source_open:
fd = open(name, rflags);
if (fd < 0) {
+ /* If encrypted file without the key,
+ * retry mirror extend in O_DIRECT.
+ */
+ if (errno == ENOKEY && !(rflags & O_DIRECT) &&
+ migration_flags & LLAPI_MIGRATION_MIRROR) {
+ rflags |= O_DIRECT;
+ goto source_open;
+ }
rc = -errno;
error_loc = "cannot open source file";
return rc;
}
do {
- int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW;
+ int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW |
+ /* Allow migrating without the key on encrypted files */
+ O_FILE_ENC;
mode_t open_mode = S_IRUSR | S_IWUSR;
+ if (rflags & O_DIRECT)
+ open_flags |= O_DIRECT;
random_value = random();
rc = snprintf(volatile_file, sizeof(volatile_file),
"%s/%s:%.4X:%.4X:fd=%.2d", parent,
rc = -errno;
goto free_layout;
}
- rc = llapi_layout_sanity(layout, fname, false, true);
+ rc = llapi_layout_sanity(layout, false, true);
if (rc < 0) {
llapi_layout_sanity_perror(errno);
goto free_layout;
{
int rc = 0;
- if (flags && neg_flags)
+ if (flags && neg_flags) {
+ fprintf(stderr,
+ "%s: cannot specify both positive and negative flags\n",
+ progname);
return -EINVAL;
+ }
if (!flags && neg_flags)
flags = neg_flags | LCME_FL_NEG;
- if ((flags && comp_id) || (!flags && !comp_id))
+ if (flags && comp_id) {
+ fprintf(stderr,
+ "%s: cannot specify component ID and flags at the same time\n",
+ progname);
return -EINVAL;
+ }
+
+ if (!flags && !comp_id) {
+ fprintf(stderr,
+ "%s: neither flags nor component ID is specified\n",
+ progname);
+ return -EINVAL;
+ }
if (flags) {
if (flags & ~LCME_KNOWN_FLAGS) {
* if new layout used bigger DOM size, then mirroring is used
*/
if (dom_new > dom_cur) {
- rc = lfs_migrate_to_dom(fd, fdv, name, migration_flags, param,
- layout);
+ rc = lfs_migrate_to_dom(fd, fdv, name, migration_flags);
if (rc)
error_loc = "cannot migrate to DOM layout";
goto out_closed;
}
- if (!(migration_flags & MIGRATION_NONBLOCK)) {
+ if (!(migration_flags & LLAPI_MIGRATION_NONBLOCK)) {
/*
* Blocking mode (forced if servers do not support file lease).
* It is also the default mode, since we cannot distinguish
if (rc < 0)
fprintf(stderr, "error: %s: %s: %s: %s\n",
progname, name, error_loc, strerror(-rc));
- else if (migration_flags & MIGRATION_VERBOSE)
+ else if (migration_flags & LLAPI_MIGRATION_VERBOSE)
printf("%s\n", name);
return rc;
__u32 flag;
} mhflist[] = {
{"migrating", LMV_HASH_FLAG_MIGRATION},
+ {"bad_type", LMV_HASH_FLAG_BAD_TYPE},
{"badtype", LMV_HASH_FLAG_BAD_TYPE},
+ {"lost_lmv", LMV_HASH_FLAG_LOST_LMV},
{"lostlmv", LMV_HASH_FLAG_LOST_LMV},
};
return -ENODATA;
}
- rc = llapi_layout_sanity(layout, fname, false, true);
+ rc = llapi_layout_sanity(layout, false, true);
llapi_layout_free(layout);
}
}
- rc = llapi_layout_sanity(list->m_layout, fname, false, true);
+ rc = llapi_layout_sanity(list->m_layout, false, true);
if (rc) {
llapi_layout_sanity_perror(rc);
return rc;
if (inherit) {
f_layout = llapi_layout_get_by_path(name, 0);
if (!f_layout) {
+ rc = -EINVAL;
fprintf(stderr, "%s: cannot get layout\n", progname);
goto out;
}
goto out;
}
}
+
llapi_layout_comp_flags_set(m_layout, flags);
- rc = migrate_open_files(name, MIGRATION_NONDIRECT, NULL, m_layout, &fd,
- &fdv);
+ rc = migrate_open_files(name,
+ LLAPI_MIGRATION_NONDIRECT | LLAPI_MIGRATION_MIRROR,
+ NULL, m_layout, &fd, &fdv);
if (rc < 0)
goto out;
static int mirror_extend(char *fname, struct mirror_args *mirror_list,
enum mirror_flags mirror_flags)
{
- int rc;
-
- rc = mirror_create_sanity_check(fname, mirror_list, true);
- if (rc)
- return rc;
+ int rc = 0;
while (mirror_list) {
if (mirror_list->m_file) {
return -EINVAL;
}
- rc = llapi_layout_sanity(layout, fname, false, true);
+ rc = llapi_layout_sanity(layout, false, true);
if (rc) {
llapi_layout_sanity_perror(rc);
goto free_layout;
}
}
- fd = open(fname, O_RDWR);
+ if (!victim_file && mflags & MF_DESTROY)
+ /* Allow mirror split even without the key on encrypted files,
+ * and in this case of a 'split -d', open file with O_DIRECT
+ * (no IOs will be done).
+ */
+ fd = open(fname, O_RDWR | O_DIRECT | O_FILE_ENC);
+ else
+ fd = open(fname, O_RDWR);
+
if (fd < 0) {
fprintf(stderr,
"error %s: open file '%s' failed: %s\n",
open_flags = O_RDWR |
(O_LOV_DELAY_CREATE & ~O_ACCMODE) |
- O_CREAT | O_EXCL | O_NOFOLLOW;
+ O_CREAT | O_EXCL | O_NOFOLLOW |
+ /* O_DIRECT for mirror split -d */
+ O_DIRECT |
+ /* Allow split without the key */
+ O_FILE_ENC;
fdv = open(file_path, open_flags,
S_IRUSR | S_IWUSR);
if (fdv < 0)
data->lil_ids[1] = mirror_id;
rc = llapi_lease_set(fd, data);
if (rc <= 0) {
- if (rc == -EINVAL && purge) {
+ if ((rc == -EINVAL || rc == -EBUSY) && purge) {
/* could be old MDS which prohibit fd==fdv */
purge = false;
goto again;
__u16 *mirror_ids, int ids_nr);
static int lfs_migrate_to_dom(int fd, int fdv, char *name,
- __u64 migration_flags,
- struct llapi_stripe_param *param,
- struct llapi_layout *layout)
+ __u64 migration_flags)
{
struct ll_ioc_lease *data = NULL;
int rc;
goto out_close;
}
+ rc = migrate_nonblock(fd, fdv);
+ if (rc < 0)
+ goto out_release;
+
/* Atomically put lease, merge layouts, resync and close. */
- data = calloc(1, offsetof(typeof(*data), lil_ids[1024]));
+ data = calloc(1, offsetof(typeof(*data), lil_ids[1]));
if (!data) {
error_loc = "memory allocation";
- goto out_close;
+ goto out_release;
}
data->lil_mode = LL_LEASE_UNLCK;
data->lil_flags = LL_LEASE_LAYOUT_MERGE;
error_loc = "cannot delete old layout";
goto out;
+out_release:
+ llapi_lease_release(fd);
out_close:
close(fd);
close(fdv);
if (rc < 0)
fprintf(stderr, "error: %s: %s: %s: %s\n",
progname, name, error_loc, strerror(-rc));
- else if (migration_flags & MIGRATION_VERBOSE)
+ else if (migration_flags & LLAPI_MIGRATION_VERBOSE)
printf("%s\n", name);
if (data)
free(data);
errno = EINVAL;
return -1;
}
- if (lsa->lsa_stripe_size != LLAPI_LAYOUT_DEFAULT) {
+ if (lsa->lsa_stripe_size != LLAPI_LAYOUT_DEFAULT &&
+ lsa->lsa_stripe_size != lsa->lsa_comp_end - prev_end) {
fprintf(stderr,
"Option 'stripe-size' can't be specified with Data-on-MDT component: %llu\n",
lsa->lsa_stripe_size);
return 0;
}
+#ifndef LCME_TEMPLATE_FLAGS
+#define LCME_TEMPLATE_FLAGS (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
+ LCME_FL_EXTENSION)
+#endif
+
static int build_layout_from_yaml_node(struct cYAML *node,
struct llapi_layout **layout,
struct lfs_setstripe_args *lsa,
}
enum {
+ LFS_SETQUOTA_DELETE = 1,
LFS_POOL_OPT = 3,
LFS_COMP_COUNT_OPT,
LFS_COMP_START_OPT,
LFS_NEWERXY_OPT,
LFS_INHERIT_RR_OPT,
LFS_FIND_PERM,
+ LFS_PRINTF_OPT,
};
+#ifndef LCME_USER_MIRROR_FLAGS
+/* The mirror flags can be set by users at creation time. */
+#define LCME_USER_MIRROR_FLAGS (LCME_FL_PREF_RW)
+#endif
+
/* functions */
static int lfs_setstripe_internal(int argc, char **argv,
enum setstripe_origin opc)
.has_arg = required_argument},
{ .val = 'd', .name = "delete", .has_arg = no_argument},
{ .val = 'd', .name = "destroy", .has_arg = no_argument},
+ /* used with "lfs migrate -m" */
+ { .val = 'd', .name = "directory", .has_arg = no_argument},
/* --non-direct is only valid in migrate mode */
{ .val = 'D', .name = "non-direct", .has_arg = no_argument },
{ .val = 'E', .name = "comp-end", .has_arg = required_argument},
{ .val = 'p', .name = "pool", .has_arg = required_argument },
/* find { .val = 'P', .name = "print", .has_arg = no_argument }, */
/* getstripe { .val = 'q', .name = "quiet", .has_arg = no_argument }, */
-/* getstripe { .val = 'r', .name = "recursive", .has_arg = no_argument }, */
/* getstripe { .val = 'R', .name = "raw", .has_arg = no_argument }, */
{ .val = 'S', .name = "stripe-size", .has_arg = required_argument },
{ .val = 'S', .name = "stripe_size", .has_arg = required_argument },
goto usage_error;
}
lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
- /* fall through */
+ fallthrough;
case 'c':
errno = 0;
lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
- if (errno != 0 || *end != '\0'||
+ if (errno != 0 || *end != '\0'|| optarg == end ||
lsa.lsa_stripe_count < -1 ||
lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) {
fprintf(stderr,
lsa.lsa_stripe_count = LLAPI_LAYOUT_WIDE;
break;
case 'd':
- /* delete the default striping pattern */
- delete = 1;
- if (opc == SO_MIRROR_SPLIT) {
- if (has_m_file) {
- fprintf(stderr,
- "%s %s: -d cannot used with -f\n",
- progname, argv[0]);
- goto usage_error;
+ if (migrate_mode) {
+ migrate_mdt_param.fp_max_depth = 1;
+ } else {
+ /* delete the default striping pattern */
+ delete = 1;
+ if (opc == SO_MIRROR_SPLIT) {
+ if (has_m_file) {
+ fprintf(stderr,
+ "%s %s: -d cannot used with -f\n",
+ progname, argv[0]);
+ goto usage_error;
+ }
+ mirror_flags |= MF_DESTROY;
}
- mirror_flags |= MF_DESTROY;
}
break;
case 'D':
progname, argv[0]);
goto usage_error;
}
- migration_flags |= MIGRATION_NONDIRECT;
+ migration_flags |= LLAPI_MIGRATION_NONDIRECT;
break;
case 'E':
if (lsa.lsa_comp_end != 0) {
case 'i':
errno = 0;
lsa.lsa_stripe_off = strtol(optarg, &end, 0);
- if (errno != 0 || *end != '\0' ||
+ if (errno != 0 || *end != '\0' || optarg == end ||
lsa.lsa_stripe_off < -1 ||
lsa.lsa_stripe_off > LOV_V1_INSANE_STRIPE_COUNT) {
fprintf(stderr,
goto error;
}
lsa.lsa_pattern = LLAPI_LAYOUT_MDT;
+ lsa.lsa_stripe_size = LLAPI_LAYOUT_DEFAULT;
} else if (strcmp(argv[optind - 1], "raid0") != 0) {
result = -EINVAL;
fprintf(stderr,
progname, argv[0]);
goto usage_error;
}
- migration_flags |= MIGRATION_NONBLOCK;
+ migration_flags |= LLAPI_MIGRATION_NONBLOCK;
break;
case 'N':
if (opc == SO_SETSTRIPE) {
goto usage_error;
}
migrate_mdt_param.fp_verbose = VERBOSE_DETAIL;
- migration_flags = MIGRATION_VERBOSE;
+ migration_flags = LLAPI_MIGRATION_VERBOSE;
break;
case 'x':
xattr = optarg;
}
/* lfs migrate $filename should keep the file's layout by default */
- if (migrate_mode && !setstripe_args_specified(&lsa) && !layout &&
- !from_yaml)
+ if (migrate_mode && !layout && !from_yaml &&
+ !setstripe_args_specified(&lsa) && !lsa.lsa_pool_name)
from_copy = true;
if (xattr && !foreign_mode) {
goto error;
}
- if ((migration_flags & MIGRATION_NONBLOCK) && migration_block) {
+ if ((migration_flags & LLAPI_MIGRATION_NONBLOCK) && migration_block) {
fprintf(stderr,
"%s %s: options --non-block and --block are mutually exclusive\n",
progname, argv[0]);
switch (*endptr) {
case 'y':
unit *= 52; /* 52 weeks + 1 day below */
- case 'w': /* fallthrough */
+ fallthrough;
+ case 'w':
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 */
+ fallthrough;
case '\0': /* days are default unit if none used */
- case 'd': /* fallthrough */
+ fallthrough;
+ case 'd':
unit *= 24;
- case 'h': /* fallthrough */
+ fallthrough;
+ case 'h':
unit *= 60;
- case 'm': /* fallthrough */
+ fallthrough;
+ case 'm':
unit *= 60;
- case 's': /* fallthrough */
+ fallthrough;
+ case 's':
break;
/* don't need to multiply by 1 for seconds */
default:
projid_tmp = strtoul(arg, &endptr, 10);
if (*endptr != '\0')
return -EINVAL;
+ /* UINT32_MAX is not allowed - see projid_valid()/INVALID_PROJID */
if (projid_tmp >= UINT32_MAX)
return -ERANGE;
/* find { .val = 'o' .name = "or", .has_arg = no_argument }, like find(1) */
{ .val = 'O', .name = "obd", .has_arg = required_argument },
{ .val = 'O', .name = "ost", .has_arg = required_argument },
+ { .val = LFS_FIND_PERM,
+ .name = "perm", .has_arg = required_argument },
/* no short option for pool yet, can be 'p' after 2.18 */
{ .val = LFS_POOL_OPT,
.name = "pool", .has_arg = required_argument },
{ .val = '0', .name = "print0", .has_arg = no_argument },
{ .val = 'P', .name = "print", .has_arg = no_argument },
+ { .val = LFS_PRINTF_OPT,
+ .name = "printf", .has_arg = required_argument },
{ .val = LFS_PROJID_OPT,
.name = "projid", .has_arg = required_argument },
/* getstripe { .val = 'q', .name = "quiet", .has_arg = no_argument }, */
{ .val = 'S', .name = "stripe-size", .has_arg = required_argument },
{ .val = 'S', .name = "stripe_size", .has_arg = required_argument },
{ .val = 't', .name = "type", .has_arg = required_argument },
- { .val = LFS_FIND_PERM,
- .name = "perm", .has_arg = required_argument },
{ .val = 'T', .name = "mdt-count", .has_arg = required_argument },
{ .val = 'u', .name = "uid", .has_arg = required_argument },
{ .val = 'U', .name = "user", .has_arg = required_argument },
+/* getstripe { .val = 'v', .name = "verbose", .has_arg = no_argument }, */
{ .val = 'z', .name = "extension-size",
.has_arg = required_argument },
{ .val = 'z', .name = "ext-size", .has_arg = required_argument },
-/* getstripe { .val = 'v', .name = "verbose", .has_arg = no_argument }, */
-/* getstripe { .val = 'y', .name = "yaml", .has_arg = no_argument }, */
{ .name = NULL } };
int optidx = 0;
int pathstart = -1;
/* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
while ((c = getopt_long_only(argc, argv,
- "-0A:b:B:c:C:D:E:g:G:hH:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:vz:",
+ "-0A:b:B:c:C:D:E:g:G:hH:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:z:",
long_opts, &optidx)) >= 0) {
xtime = NULL;
xsign = NULL;
xsign = ¶m.fp_asign;
param.fp_exclude_atime = !!neg_opt;
/* no break, this falls through to 'B' for btime */
+ fallthrough;
case 'B':
if (c == 'B') {
xtime = ¶m.fp_btime;
param.fp_exclude_btime = !!neg_opt;
}
/* no break, this falls through to 'C' for ctime */
+ fallthrough;
case 'C':
if (c == 'C') {
xtime = ¶m.fp_ctime;
param.fp_exclude_ctime = !!neg_opt;
}
/* no break, this falls through to 'M' for mtime */
+ fallthrough;
case 'M':
if (c == 'M') {
xtime = ¶m.fp_mtime;
break;
case 'P': /* we always print, this option is a no-op */
break;
+ case LFS_PRINTF_OPT:
+ param.fp_format_printf_str = optarg;
+ break;
case LFS_PROJID_OPT:
rc = name2projid(¶m.fp_projid, optarg);
if (rc) {
goto err;
}
}
+ if (!param.fp_verbose)
+ param.fp_verbose = VERBOSE_DEFAULT;
if (pathstart == -1) {
fprintf(stderr, "error: %s: no filename|pathname\n",
case 't':
fprintf(stderr,
"warning: '-t' deprecated, use '--mdt-hash' or '-H' instead\n");
- /* fallthrough */
+ fallthrough;
#endif
case 'H':
param.fp_verbose |= VERBOSE_HASH_TYPE;
break;
- case 'i': /* fallthrough */
+ case 'i':
+ fallthrough;
case 'm':
param.fp_verbose |= VERBOSE_STRIPE_OFFSET;
break;
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
if (!(tp->st_op & ops))
continue;
- for (index = 0; ; index++) {
+ for (index = 0; index < LOV_ALL_STRIPES &&
+ (!lsb || lsb->sb_count < LL_STATFS_MAX); 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);
+ &stat_buf, &uuid_buf);
if (rc2 == -ENODEV)
break;
if (rc2 == -EAGAIN)
case 't':
fprintf(stderr,
"warning: '--hash-type' and '-t' deprecated, use '--mdt-hash' or '-H' instead\n");
- /* fallthrough */
+ fallthrough;
#endif
case 'H':
lsa.lsa_pattern = check_hashtype(optarg);
if (lsa.lsa_pattern == 0) {
fprintf(stderr,
- "%s %s: bad stripe hash type '%s'\n",
+ "%s %s: bad directory hash type '%s'\n",
progname, argv[0], optarg);
return CMD_HELP;
}
xattr = optarg;
break;
case 'X':
- if (!default_stripe) {
- fprintf(stderr,
- "%s %s: '--max-inherit' must be specified with '-D'\n",
- progname, argv[0]);
- return CMD_HELP;
- }
errno = 0;
max_inherit = strtol(optarg, &end, 10);
if (errno != 0 || *end != '\0' || max_inherit < -2) {
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
previous_mode = umask(0);
}
+ /* check max-inherit and warn user in some cases */
+ if (default_stripe &&
+ (lsa.lsa_stripe_count < 0 || lsa.lsa_stripe_count > 1)) {
+ if (max_inherit == LMV_INHERIT_UNLIMITED)
+ fprintf(stderr,
+ "%s %s: unrecommended max-inherit=-1 when default stripe-count=%lld\n",
+ progname, argv[0], lsa.lsa_stripe_count);
+ else if (max_inherit > LMV_INHERIT_DEFAULT_STRIPED + 2 &&
+ max_inherit != LMV_INHERIT_NONE)
+ fprintf(stderr,
+ "%s %s: unrecommended max-inherit=%d when default stripe-count=%lld\n",
+ progname, argv[0], max_inherit,
+ lsa.lsa_stripe_count);
+ }
+
if (max_inherit_rr != LAYOUT_INHERIT_UNSET &&
lsa.lsa_stripe_off != LLAPI_LAYOUT_DEFAULT &&
lsa.lsa_stripe_off != LMV_OFFSET_DEFAULT) {
param->lsp_stripe_pattern = LMV_HASH_TYPE_UNKNOWN;
param->lsp_pool = lsa.lsa_pool_name;
param->lsp_is_specific = false;
+ if (max_inherit == LAYOUT_INHERIT_UNSET) {
+ if (lsa.lsa_stripe_count == 0 || lsa.lsa_stripe_count == 1)
+ max_inherit = LMV_INHERIT_DEFAULT_PLAIN;
+ else
+ max_inherit = LMV_INHERIT_DEFAULT_STRIPED;
+ }
+ param->lsp_max_inherit = max_inherit;
if (default_stripe) {
- if (max_inherit == LAYOUT_INHERIT_UNSET)
- max_inherit = LMV_INHERIT_DEFAULT;
+
if (max_inherit_rr == LAYOUT_INHERIT_UNSET)
max_inherit_rr = LMV_INHERIT_RR_DEFAULT;
- param->lsp_max_inherit = max_inherit;
param->lsp_max_inherit_rr = max_inherit_rr;
}
if (strcmp(argv[0], "mkdir") == 0)
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;
+ int c, rc = 0, rc1 = 0, index = 0, arg_idx = 0;
char fsname[PATH_MAX] = "", *pool_name = NULL;
struct option long_opts[] = {
{ .val = 'h', .name = "human-readable", .has_arg = no_argument },
return CMD_HELP;
}
}
- if (optind < argc && !realpath(argv[optind], path)) {
- rc = -errno;
- fprintf(stderr, "%s: invalid path '%s': %s\n",
- progname, argv[optind], strerror(-rc));
+
+ /* Handle case where path is not specified */
+ if (optind == argc) {
+ 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 */
+ path[0] = '\0'; /* clean for next loop */
+ }
return rc;
}
- while (!llapi_search_mounts(path, index++, mntdir, fsname)) {
- /* Check if we have a mount point */
- if (mntdir[0] == '\0')
+ /* Loop through all the remaining arguments. These are Lustre FS
+ * paths.
+ */
+ for (arg_idx = optind; arg_idx <= argc - 1; arg_idx++) {
+ bool valid = false;
+
+ fsname[0] = '\0'; /* start clean */
+ mntdir[0] = '\0'; /* start clean */
+ path[0] = '\0'; /* start clean */
+
+ /* path does not exists at all */
+ if (!realpath(argv[arg_idx], path)) {
+ rc = -errno;
+ fprintf(stderr, "error: invalid path '%s': %s\n",
+ argv[arg_idx], strerror(-rc));
+ /* save first seen error */
+ if (!rc1)
+ rc1 = rc;
+
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 */
+ /* path exists but may not be a Lustre filesystem */
+ 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') {
+ valid = true;
+
+ /* save first seen error */
+ if (!rc1)
+ rc1 = rc;
+ break;
+ }
+ }
+
+ if (!valid) {
+ llapi_printf(LLAPI_MSG_ERROR,
+ "%s:%s Not a Lustre filesystem\n",
+ argv[0], argv[arg_idx]);
+ /* save first seen error */
+ if (!rc1)
+ rc1 = -EOPNOTSUPP;
+ }
}
- return rc;
+ return rc1;
}
static int print_instance(const char *mntdir, char *buf, size_t buflen,
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
return 0;
}
+/* special grace time, only notify the user when its quota is over soft limit
+ * but doesn't block new writes until the hard limit is reached.
+ */
+#define NOTIFY_GRACE "notify"
+#define NOTIFY_GRACE_TIME LQUOTA_GRACE_MASK
+
+#ifndef toqb
+static inline __u64 lustre_stoqb(size_t space)
+{
+ return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
+}
+#else
+#define lustre_stoqb toqb
+#endif
+
int lfs_setquota_times(int argc, char **argv, struct if_quotactl *qctl)
{
int c, rc;
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
{ .val = 'B', .name = "block-hardlimit",
.has_arg = required_argument },
{ .val = 'd', .name = "default", .has_arg = no_argument },
+ { .val = LFS_SETQUOTA_DELETE,
+ .name = "delete", .has_arg = no_argument },
{ .val = 'g', .name = "group", .has_arg = required_argument },
{ .val = 'G', .name = "default-grp", .has_arg = no_argument },
{ .val = 'h', .name = "help", .has_arg = no_argument },
* so it can be used as a marker that qc_type
* isn't reinitialized from command line
*/
-
- while ((c = getopt_long(argc, argv, "b:B:dg:Ghi:I:p:Pu:U",
+ while ((c = getopt_long(argc, argv, "b:B:dDg:Ghi:I:p:Pu:U",
long_opts, NULL)) != -1) {
switch (c) {
case 'U':
}
qctl->qc_type = qtype;
break;
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
case 'd':
- qctl->qc_cmd = LUSTRE_Q_SETDEFAULT;
+#if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2, 15, 53, 0)
+ fprintf(stderr, "'-d' deprecatd, use '-D' or '--default'\n");
+#endif
+ /* falltrrough */
+#endif
+ case 'D':
use_default = true;
+ qctl->qc_cmd = LUSTRE_Q_SETDEFAULT;
+ break;
+ case LFS_SETQUOTA_DELETE:
+ qctl->qc_cmd = LUSTRE_Q_DELETEQID;
break;
case 'b':
ARG2ULL(dqb->dqb_bsoftlimit, optarg, 1024);
fprintf(stderr,
"%s setquota: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
rc = CMD_HELP;
goto out;
goto out;
}
- if (!use_default && limit_mask == 0) {
+ if (!use_default && qctl->qc_cmd != LUSTRE_Q_DELETEQID &&
+ limit_mask == 0) {
fprintf(stderr,
"%s setquota: at least one limit must be specified\n",
progname);
goto out;
}
- if (use_default && limit_mask != 0) {
+ if ((use_default || qctl->qc_cmd == LUSTRE_Q_DELETEQID) &&
+ limit_mask != 0) {
fprintf(stderr,
- "%s setquota: limits should not be specified when using default quota\n",
+ "%s setquota: limits should not be specified when using default quota or deleting quota ID\n",
progname);
rc = CMD_HELP;
goto out;
goto out;
}
+ if (qctl->qc_cmd == LUSTRE_Q_DELETEQID && qctl->qc_id == 0) {
+ fprintf(stderr,
+ "%s setquota: can not delete root user/group/project\n",
+ progname);
+ rc = CMD_HELP;
+ goto out;
+ }
+
if (optind != argc - 1) {
fprintf(stderr,
"%s setquota: filesystem not specified or unexpected argument '%s'\n",
} else if ((!(limit_mask & BHLIMIT) ^ !(limit_mask & BSLIMIT)) ||
(!(limit_mask & IHLIMIT) ^ !(limit_mask & ISLIMIT))) {
/* sigh, we can't just set blimits/ilimits */
- struct if_quotactl tmp_qctl = {.qc_cmd = LUSTRE_Q_GETQUOTA,
- .qc_type = qctl->qc_type,
- .qc_id = qctl->qc_id};
+ struct if_quotactl *tmp_qctl;
- rc = llapi_quotactl(mnt, &tmp_qctl);
- if (rc < 0)
+ tmp_qctl = calloc(1, sizeof(*qctl) + LOV_MAXPOOLNAME + 1);
+ if (!tmp_qctl)
goto out;
+ if (qctl->qc_cmd == LUSTRE_Q_SETQUOTAPOOL) {
+ tmp_qctl->qc_cmd = LUSTRE_Q_GETQUOTAPOOL;
+ strncpy(tmp_qctl->qc_poolname, qctl->qc_poolname,
+ LOV_MAXPOOLNAME);
+ } else {
+ tmp_qctl->qc_cmd = LUSTRE_Q_GETQUOTA;
+ }
+ tmp_qctl->qc_type = qctl->qc_type;
+ tmp_qctl->qc_id = qctl->qc_id;
+
+ rc = llapi_quotactl(mnt, tmp_qctl);
+ if (rc < 0) {
+ free(tmp_qctl);
+ goto out;
+ }
+
if (!(limit_mask & BHLIMIT))
- dqb->dqb_bhardlimit = tmp_qctl.qc_dqblk.dqb_bhardlimit;
+ dqb->dqb_bhardlimit = tmp_qctl->qc_dqblk.dqb_bhardlimit;
if (!(limit_mask & BSLIMIT))
- dqb->dqb_bsoftlimit = tmp_qctl.qc_dqblk.dqb_bsoftlimit;
+ dqb->dqb_bsoftlimit = tmp_qctl->qc_dqblk.dqb_bsoftlimit;
if (!(limit_mask & IHLIMIT))
- dqb->dqb_ihardlimit = tmp_qctl.qc_dqblk.dqb_ihardlimit;
+ dqb->dqb_ihardlimit = tmp_qctl->qc_dqblk.dqb_ihardlimit;
if (!(limit_mask & ISLIMIT))
- dqb->dqb_isoftlimit = tmp_qctl.qc_dqblk.dqb_isoftlimit;
+ dqb->dqb_isoftlimit = tmp_qctl->qc_dqblk.dqb_isoftlimit;
/* Keep grace times if we have got no softlimit arguments */
if ((limit_mask & BHLIMIT) && !(limit_mask & BSLIMIT)) {
dqb->dqb_valid |= QIF_BTIME;
- dqb->dqb_btime = tmp_qctl.qc_dqblk.dqb_btime;
+ dqb->dqb_btime = tmp_qctl->qc_dqblk.dqb_btime;
}
if ((limit_mask & IHLIMIT) && !(limit_mask & ISLIMIT)) {
dqb->dqb_valid |= QIF_ITIME;
- dqb->dqb_itime = tmp_qctl.qc_dqblk.dqb_itime;
+ dqb->dqb_itime = tmp_qctl->qc_dqblk.dqb_itime;
}
+ free(tmp_qctl);
}
dqb->dqb_valid |= (limit_mask & (BHLIMIT | BSLIMIT)) ? QIF_BLIMITS : 0;
if (rc) {
if (*obd_type)
fprintf(stderr,
- "%s setquota: cannot quotactl '%s' '%s': %s",
+ "%s setquota: cannot quotactl '%s' '%s': %s\n",
progname, obd_type,
obd_uuid2str(&qctl->obd_uuid), strerror(-rc));
+ else
+ fprintf(stderr,
+ "%s setquota: quotactl failed: %s\n",
+ progname, strerror(-rc));
}
out:
+ if (rc)
+ fprintf(stderr, "setquota failed: %s\n", strerror(-rc));
+
free(qctl);
return rc;
}
}
}
+#ifdef HAVE_NATIVE_CLIENT
+/* In the current Lustre implementation, the grace time is either the time
+ * or the timestamp to be used after some quota ID exceeds the soft limt,
+ * 48 bits should be enough, its high 16 bits can be used as quota flags.
+ */
+#define LQUOTA_GRACE_BITS 48
+#define LQUOTA_GRACE_MASK ((1ULL << LQUOTA_GRACE_BITS) - 1)
+#define LQUOTA_GRACE_MAX LQUOTA_GRACE_MASK
+#define LQUOTA_GRACE(t) (t & LQUOTA_GRACE_MASK)
+#define LQUOTA_FLAG(t) (t >> LQUOTA_GRACE_BITS)
+#define LQUOTA_GRACE_FLAG(t, f) ((__u64)t | (__u64)f << LQUOTA_GRACE_BITS)
+#endif
+
#define STRBUF_LEN 24
static void print_quota(char *mnt, struct if_quotactl *qctl, int type,
int rc, bool h, bool show_default)
goto out;
}
+ /* no target for this index yet */
+ if (rc == -ENODEV) {
+ rc = 0;
+ continue;
+ }
+
+ /* inactive target */
+ if (rc == -ENODATA) {
+ char name[UUID_MAX+8];
+
+ snprintf(name, sizeof(name), "%s[inact]",
+ obd_uuid2str(&qctl->obd_uuid));
+ memset(&qctl->qc_dqinfo, 0,
+ sizeof(qctl->qc_dqinfo));
+ memset(&qctl->qc_dqblk, 0,
+ sizeof(qctl->qc_dqblk));
+ print_quota(name, qctl, qctl->qc_valid, 0, h,
+ false);
+ rc = 0;
+ continue;
+ }
+
if (!rc1)
rc1 = rc;
fprintf(stderr, "quotactl %s%d failed.\n",
fprintf(stderr,
"%s data_version: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
goto error;
}
- fd = open(fname, O_DIRECT | O_RDWR);
+ /* Allow mirror resync even without the key on encrypted files */
+ fd = open(fname, O_DIRECT | O_RDWR | O_FILE_ENC);
if (fd < 0) {
fprintf(stderr, "%s: cannot open '%s': %s.\n",
progname, fname, strerror(errno));
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
rc = CMD_HELP;
goto error;
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
return cid.cid_count;
}
+#ifndef MIRROR_ID_NEG
+#define MIRROR_ID_NEG 0x8000
+#endif
+
static inline int lfs_mirror_copy(int argc, char **argv)
{
int rc = CMD_HELP;
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
* Return: void.
*/
static inline
-void print_checksums(struct verify_chunk *chunk, unsigned long *crc)
+void print_checksums(struct verify_chunk *chunk, unsigned long *crc,
+ unsigned long long pos, unsigned long long len)
{
int i;
fprintf(stdout,
- "CRC-32 checksum value for chunk "DEXT":\n",
- PEXT(&chunk->chunk));
+ "CRC-32 checksum value for chunk "DEXT":\n", pos, pos + len);
for (i = 0; i < chunk->mirror_count; i++)
fprintf(stdout, "Mirror %u:\t%#lx\n",
chunk->mirror_id[i], crc[i]);
goto error;
}
- chunks[idx].mirror_id[i] = mirror_id;
- i++;
if (i >= ARRAY_SIZE(chunks[idx].mirror_id)) {
fprintf(stderr,
"%s: mirror_id array is too small.\n",
rc = -EINVAL;
goto error;
}
+ chunks[idx].mirror_id[i] = mirror_id;
+ i++;
next:
rc = llapi_layout_comp_use(layout,
}
if (verbose)
- print_checksums(chunk, crc_array);
+ print_checksums(chunk, crc_array, pos, buflen);
/* compare CRC-32 checksum values */
for (i = 1; i < chunk->mirror_count; i++) {
goto error;
}
- fd = open(fname, O_DIRECT | O_RDONLY);
+ /* Allow mirror verify even without the key on encrypted files */
+ fd = open(fname, O_DIRECT | O_RDONLY | O_FILE_ENC);
if (fd < 0) {
fprintf(stderr, "%s: cannot open '%s': %s.\n",
progname, fname, strerror(errno));
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
rc = CMD_HELP;
goto error;
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}
default:
fprintf(stderr, "%s: unrecognized option '%s'\n",
progname, argv[optind - 1]);
- /* fallthrough */
+ fallthrough;
case 'h':
return CMD_HELP;
}