Whamcloud - gitweb
a957a2a0ce0168acf4dc751e7b8d2cc5554dc0a9
[fs/lustre-release.git] / lustre / utils / lfs.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  *
32  * lustre/utils/lfs.c
33  *
34  * Author: Peter J. Braam <braam@clusterfs.com>
35  * Author: Phil Schwan <phil@clusterfs.com>
36  * Author: Robert Read <rread@clusterfs.com>
37  */
38
39 /* for O_DIRECTORY */
40 #ifndef _GNU_SOURCE
41 #define _GNU_SOURCE
42 #endif
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <inttypes.h>
47 #include <getopt.h>
48 #include <string.h>
49 #include <mntent.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <err.h>
53 #include <pwd.h>
54 #include <grp.h>
55 #include <sys/ioctl.h>
56 #include <sys/quota.h>
57 #include <sys/time.h>
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <sys/param.h>
61 #include <fcntl.h>
62 #include <dirent.h>
63 #include <time.h>
64 #include <ctype.h>
65 #include <zlib.h>
66 #include "lfs_project.h"
67
68 #include <libcfs/util/string.h>
69 #include <libcfs/util/ioctl.h>
70 #include <libcfs/util/parser.h>
71 #include <lustre/lustreapi.h>
72 #include <linux/lustre/lustre_ver.h>
73 #include <linux/lustre/lustre_param.h>
74
75 #ifndef ARRAY_SIZE
76 # define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
77 #endif /* !ARRAY_SIZE */
78
79 /* all functions */
80 static int lfs_find(int argc, char **argv);
81 static int lfs_getstripe(int argc, char **argv);
82 static int lfs_getdirstripe(int argc, char **argv);
83 static int lfs_setdirstripe(int argc, char **argv);
84 static int lfs_rmentry(int argc, char **argv);
85 static int lfs_osts(int argc, char **argv);
86 static int lfs_mdts(int argc, char **argv);
87 static int lfs_df(int argc, char **argv);
88 static int lfs_getname(int argc, char **argv);
89 static int lfs_check(int argc, char **argv);
90 #ifdef HAVE_SYS_QUOTA_H
91 static int lfs_setquota(int argc, char **argv);
92 static int lfs_quota(int argc, char **argv);
93 static int lfs_project(int argc, char **argv);
94 #endif
95 static int lfs_flushctx(int argc, char **argv);
96 static int lfs_cp(int argc, char **argv);
97 static int lfs_ls(int argc, char **argv);
98 static int lfs_poollist(int argc, char **argv);
99 static int lfs_changelog(int argc, char **argv);
100 static int lfs_changelog_clear(int argc, char **argv);
101 static int lfs_fid2path(int argc, char **argv);
102 static int lfs_path2fid(int argc, char **argv);
103 static int lfs_data_version(int argc, char **argv);
104 static int lfs_hsm_state(int argc, char **argv);
105 static int lfs_hsm_set(int argc, char **argv);
106 static int lfs_hsm_clear(int argc, char **argv);
107 static int lfs_hsm_action(int argc, char **argv);
108 static int lfs_hsm_archive(int argc, char **argv);
109 static int lfs_hsm_restore(int argc, char **argv);
110 static int lfs_hsm_release(int argc, char **argv);
111 static int lfs_hsm_remove(int argc, char **argv);
112 static int lfs_hsm_cancel(int argc, char **argv);
113 static int lfs_swap_layouts(int argc, char **argv);
114 static int lfs_mv(int argc, char **argv);
115 static int lfs_ladvise(int argc, char **argv);
116 static int lfs_mirror(int argc, char **argv);
117 static int lfs_mirror_list_commands(int argc, char **argv);
118 static int lfs_list_commands(int argc, char **argv);
119 static inline int lfs_mirror_resync(int argc, char **argv);
120 static inline int lfs_mirror_verify(int argc, char **argv);
121
122 enum setstripe_origin {
123         SO_SETSTRIPE,
124         SO_MIGRATE,
125         SO_MIRROR_CREATE,
126         SO_MIRROR_EXTEND
127 };
128 static int lfs_setstripe0(int argc, char **argv, enum setstripe_origin opc);
129
130 static inline int lfs_setstripe(int argc, char **argv)
131 {
132         return lfs_setstripe0(argc, argv, SO_SETSTRIPE);
133 }
134 static inline int lfs_setstripe_migrate(int argc, char **argv)
135 {
136         return lfs_setstripe0(argc, argv, SO_MIGRATE);
137 }
138 static inline int lfs_mirror_create(int argc, char **argv)
139 {
140         return lfs_setstripe0(argc, argv, SO_MIRROR_CREATE);
141 }
142 static inline int lfs_mirror_extend(int argc, char **argv)
143 {
144         return lfs_setstripe0(argc, argv, SO_MIRROR_EXTEND);
145 }
146
147 /* Setstripe and migrate share mostly the same parameters */
148 #define SSM_CMD_COMMON(cmd) \
149         "usage: "cmd" [--component-end|-E <comp_end>]\n"                \
150         "                 [--stripe-count|-c <stripe_count>]\n"         \
151         "                 [--stripe-index|-i <start_ost_idx>]\n"        \
152         "                 [--stripe-size|-S <stripe_size>]\n"           \
153         "                 [--layout|-L <pattern>]\n"            \
154         "                 [--pool|-p <pool_name>]\n"                    \
155         "                 [--ost|-o <ost_indices>]\n"
156
157 #define SSM_HELP_COMMON \
158         "\tstripe_count: Number of OSTs to stripe over (0=fs default, -1 all)\n" \
159         "\tstart_ost_idx: OST index of first stripe (-1=default round robin)\n"\
160         "\tstripe_size:  Number of bytes on each OST (0=fs default)\n" \
161         "\t              Can be specified with K, M or G (for KB, MB, GB\n" \
162         "\t              respectively)\n"                               \
163         "\tpool_name:    Name of OST pool to use (default none)\n"      \
164         "\tlayout:       stripe pattern type: raid0, mdt (default raid0)\n"\
165         "\tost_indices:  List of OST indices, can be repeated multiple times\n"\
166         "\t              Indices be specified in a format of:\n"        \
167         "\t                -o <ost_1>,<ost_i>-<ost_j>,<ost_n>\n"        \
168         "\t              Or:\n"                                         \
169         "\t                -o <ost_1> -o <ost_i>-<ost_j> -o <ost_n>\n"  \
170         "\t              If --pool is set with --ost, then the OSTs\n"  \
171         "\t              must be the members of the pool.\n"            \
172         "\tcomp_end:     Extent end of component, start after previous end.\n"\
173         "\t              Can be specified with K, M or G (for KB, MB, GB\n" \
174         "\t              respectively, -1 for EOF). Must be a multiple of\n"\
175         "\t              stripe_size.\n"
176
177 #define MIRROR_CREATE_HELP                                                     \
178         "\tmirror_count: Number of mirrors to be created with the upcoming\n"  \
179         "\t              setstripe layout options\n"                           \
180         "\t              It defaults to 1 if not specified; if specified,\n"   \
181         "\t              it must follow the option without a space.\n"         \
182         "\t              The option can also be repeated multiple times to\n"  \
183         "\t              separate mirrors that have different layouts.\n"      \
184         "\tsetstripe options: Mirror layout\n"                                 \
185         "\t              It can be a plain layout or a composite layout.\n"    \
186         "\t              If not specified, the stripe options inherited\n"     \
187         "\t              from the previous component will be used.\n"          \
188         "\tparent:       Use default stripe options from parent directory\n"   \
189         "\tflags:        set flags to the component of the current mirror.\n"  \
190         "\t              Only \"prefer\" flag is supported so far.\n"
191
192 #define MIRROR_EXTEND_HELP                                                     \
193         MIRROR_CREATE_HELP                                                     \
194         "\tvictim_file:  The layout of victim_file will be split and used\n"   \
195         "\t              as a mirror added to the mirrored file.\n"            \
196         "\tno-verify:    This option indicates not to verify the mirror(s)\n"  \
197         "\t              from victim file(s) in case the victim file(s)\n"     \
198         "\t              contains the same data as the original mirrored\n"    \
199         "\t              file.\n"
200
201 #define MIRROR_EXTEND_USAGE                                                    \
202         "                 <--mirror-count|-N[mirror_count]>\n"                 \
203         "                 [setstripe options|--parent|-f <victim_file>]\n"     \
204         "                 [--no-verify]\n"
205
206 #define SETSTRIPE_USAGE                                                 \
207         SSM_CMD_COMMON("setstripe")                                     \
208         MIRROR_EXTEND_USAGE                                             \
209         "                 <directory|filename>\n"                       \
210         SSM_HELP_COMMON                                                 \
211         MIRROR_EXTEND_HELP
212
213 #define MIGRATE_USAGE                                                   \
214         SSM_CMD_COMMON("migrate  ")                                     \
215         "                 [--block|-b]\n"                               \
216         "                 [--non-block|-n]\n"                           \
217         "                 <filename>\n"                                 \
218         SSM_HELP_COMMON                                                 \
219         "\n"                                                            \
220         "\tblock:        Block file access during data migration (default)\n" \
221         "\tnon-block:    Abort migrations if concurrent access is detected\n" \
222
223 #define SETDIRSTRIPE_USAGE                                      \
224         "               [--mdt-count|-c stripe_count>\n"        \
225         "               [--mdt-index|-i mdt_index]\n"           \
226         "               [--mdt-hash|-H mdt_hash]\n"             \
227         "               [--default|-D] [--mode|-m mode] <dir>\n"        \
228         "\tstripe_count: stripe count of the striped directory\n"       \
229         "\tmdt_index: MDT index of first stripe\n"                      \
230         "\tmdt_hash:  hash type of the striped directory. mdt types:\n" \
231         "       fnv_1a_64 FNV-1a hash algorithm (default)\n"            \
232         "       all_char  sum of characters % MDT_COUNT (not recommended)\n" \
233         "\tdefault_stripe: set default dirstripe of the directory\n"    \
234         "\tmode: the mode of the directory\n"
235
236 /**
237  * command_t mirror_cmdlist - lfs mirror commands.
238  */
239 command_t mirror_cmdlist[] = {
240         { .pc_name = "create", .pc_func = lfs_mirror_create,
241           .pc_help = "Create a mirrored file.\n"
242                 "usage: lfs mirror create "
243                 "<--mirror-count|-N[mirror_count]> "
244                 "[setstripe options|--parent] ... <filename|directory>\n"
245           MIRROR_CREATE_HELP },
246         { .pc_name = "extend", .pc_func = lfs_mirror_extend,
247           .pc_help = "Extend a mirrored file.\n"
248                 "usage: lfs mirror extend "
249                 "<--mirror-count|-N[mirror_count]> [--no-verify] "
250                 "[setstripe options|--parent|-f <victim_file>] ... <filename>\n"
251           MIRROR_EXTEND_HELP },
252         { .pc_name = "resync", .pc_func = lfs_mirror_resync,
253           .pc_help = "Resynchronizes out-of-sync mirrored file(s).\n"
254                 "usage: lfs mirror resync [--only <mirror_id[,...]>] "
255                 "<mirrored file> [<mirrored file2>...]\n"},
256         { .pc_name = "verify", .pc_func = lfs_mirror_verify,
257           .pc_help = "Verify mirrored file(s).\n"
258                 "usage: lfs mirror verify "
259                 "[--only <mirror_id,mirror_id2[,...]>] "
260                 "[--verbose|-v] <mirrored_file> [<mirrored_file2> ...]\n"},
261         { .pc_name = "--list-commands", .pc_func = lfs_mirror_list_commands,
262           .pc_help = "list commands supported by lfs mirror"},
263         { .pc_name = "help", .pc_func = Parser_help, .pc_help = "help" },
264         { .pc_name = "exit", .pc_func = Parser_quit, .pc_help = "quit" },
265         { .pc_name = "quit", .pc_func = Parser_quit, .pc_help = "quit" },
266         { .pc_help = NULL }
267 };
268
269 /* all available commands */
270 command_t cmdlist[] = {
271         {"setstripe", lfs_setstripe, 0,
272          "To create a file with specified striping/composite layout, or\n"
273          "create/replace the default layout on an existing directory:\n"
274          SSM_CMD_COMMON("setstripe")
275          "                 <directory|filename>\n"
276          " or\n"
277          "To add component(s) to an existing composite file:\n"
278          SSM_CMD_COMMON("setstripe --component-add")
279          SSM_HELP_COMMON
280          "To totally delete the default striping from an existing directory:\n"
281          "usage: setstripe -d <directory>\n"
282          " or\n"
283          "To delete the last component(s) from an existing composite file\n"
284          "(note that this will also delete any data in those components):\n"
285          "usage: setstripe --component-del [--component-id|-I <comp_id>]\n"
286          "                               [--component-flags|-F <comp_flags>]\n"
287          "                               <filename>\n"
288          "\tcomp_id:     Unique component ID to delete\n"
289          "\tcomp_flags:  'init' indicating all instantiated components\n"
290          "\t             '^init' indicating all uninstantiated components\n"
291          "\t-I and -F cannot be specified at the same time\n"},
292         {"getstripe", lfs_getstripe, 0,
293          "To list the striping info for a given file or files in a\n"
294          "directory or recursively for all files in a directory tree.\n"
295          "usage: getstripe [--ost|-O <uuid>] [--quiet|-q] [--verbose|-v]\n"
296          "                 [--stripe-count|-c] [--stripe-index|-i]\n"
297          "                 [--pool|-p] [--stripe-size|-S] [--directory|-d]\n"
298          "                 [--mdt|-m] [--recursive|-r] [--raw|-R] [--yaml|-y]\n"
299          "                 [--layout|-L] [--fid|-F] [--generation|-g]\n"
300          "                 [--component-id[=comp_id]|-I[comp_id]]\n"
301          "                 [--component-flags[=comp_flags]]\n"
302          "                 [--component-count]\n"
303          "                 [--component-start[=[+-]comp_start]]\n"
304          "                 [--component-end[=[+-]comp_end]|-E[[+-]comp_end]]\n"
305          "                 <directory|filename> ..."},
306         {"setdirstripe", lfs_setdirstripe, 0,
307          "To create a striped directory on a specified MDT. This can only\n"
308          "be done on MDT0 with the right of administrator.\n"
309          "usage: setdirstripe [OPTION] <directory>\n"
310          SETDIRSTRIPE_USAGE},
311         {"getdirstripe", lfs_getdirstripe, 0,
312          "To list the striping info for a given directory\n"
313          "or recursively for all directories in a directory tree.\n"
314          "usage: getdirstripe [--obd|-O <uuid>] [--mdt-count|-c]\n"
315          "                    [--mdt-index|-i] [--mdt-hash|-t]\n"
316          "                    [--recursive|-r] [--yaml|-y]\n"
317          "                    [--default|-D] <dir> ..."},
318         {"mkdir", lfs_setdirstripe, 0,
319          "To create a striped directory on a specified MDT. This can only\n"
320          "be done on MDT0 with the right of administrator.\n"
321          "usage: mkdir [OPTION] <directory>\n"
322          SETDIRSTRIPE_USAGE},
323         {"rm_entry", lfs_rmentry, 0,
324          "To remove the name entry of the remote directory. Note: This\n"
325          "command will only delete the name entry, i.e. the remote directory\n"
326          "will become inaccessable after this command. This can only be done\n"
327          "by the administrator\n"
328          "usage: rm_entry <dir>\n"},
329         {"pool_list", lfs_poollist, 0,
330          "List pools or pool OSTs\n"
331          "usage: pool_list <fsname>[.<pool>] | <pathname>\n"},
332         {"find", lfs_find, 0,
333          "find files matching given attributes recursively in directory tree.\n"
334          "usage: find <directory|filename> ...\n"
335          "     [[!] --atime|-A [+-]N] [[!] --ctime|-C [+-]N]\n"
336          "     [[!] --mtime|-M [+-]N] [[!] --mdt|-m <uuid|index,...>]\n"
337          "     [--maxdepth|-D N] [[!] --name|-n <pattern>]\n"
338          "     [[!] --ost|-O <uuid|index,...>] [--print|-p] [--print0|-P]\n"
339          "     [[!] --size|-s [+-]N[bkMGTPE]]\n"
340          "     [[!] --stripe-count|-c [+-]<stripes>]\n"
341          "     [[!] --stripe-index|-i <index,...>]\n"
342          "     [[!] --stripe-size|-S [+-]N[kMGT]] [[!] --type|-t <filetype>]\n"
343          "     [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
344          "     [[!] --uid|-u|--user|-U <uid>|<uname>] [[!] --pool <pool>]\n"
345          "     [[!] --projid <projid>]\n"
346          "     [[!] --layout|-L released,raid0,mdt]\n"
347          "     [[!] --component-count [+-]<comp_cnt>]\n"
348          "     [[!] --component-start [+-]N[kMGTPE]]\n"
349          "     [[!] --component-end|-E [+-]N[kMGTPE]]\n"
350          "     [[!] --component-flags <comp_flags>]\n"
351          "     [[!] --mdt-count|-T [+-]<stripes>]\n"
352          "     [[!] --mdt-hash|-H <hashtype>\n"
353          "\t !: used before an option indicates 'NOT' requested attribute\n"
354          "\t -: used before a value indicates less than requested value\n"
355          "\t +: used before a value indicates more than requested value\n"
356          "\tmdt-hash:   hash type of the striped directory.\n"
357          "\t            fnv_1a_64 FNV-1a hash algorithm\n"
358          "\t            all_char  sum of characters % MDT_COUNT\n"},
359         {"check", lfs_check, 0,
360          "Display the status of MDS or OSTs (as specified in the command)\n"
361          "or all the servers (MDS and OSTs).\n"
362          "usage: check <osts|mds|servers>"},
363         {"osts", lfs_osts, 0, "list OSTs connected to client "
364          "[for specified path only]\n" "usage: osts [path]"},
365         {"mdts", lfs_mdts, 0, "list MDTs connected to client "
366          "[for specified path only]\n" "usage: mdts [path]"},
367         {"df", lfs_df, 0,
368          "report filesystem disk space usage or inodes usage"
369          "of each MDS and all OSDs or a batch belonging to a specific pool .\n"
370          "Usage: df [-i] [-h] [--lazy|-l] [--pool|-p <fsname>[.<pool>] [path]"},
371         {"getname", lfs_getname, 0, "list instances and specified mount points "
372          "[for specified path only]\n"
373          "Usage: getname [-h]|[path ...] "},
374 #ifdef HAVE_SYS_QUOTA_H
375         {"setquota", lfs_setquota, 0, "Set filesystem quotas.\n"
376          "usage: setquota <-u|-g|-p> <uname>|<uid>|<gname>|<gid>|<projid>\n"
377          "                -b <block-softlimit> -B <block-hardlimit>\n"
378          "                -i <inode-softlimit> -I <inode-hardlimit> <filesystem>\n"
379          "       setquota <-u|--user|-g|--group|-p|--projid> <uname>|<uid>|<gname>|<gid>|<projid>\n"
380          "                [--block-softlimit <block-softlimit>]\n"
381          "                [--block-hardlimit <block-hardlimit>]\n"
382          "                [--inode-softlimit <inode-softlimit>]\n"
383          "                [--inode-hardlimit <inode-hardlimit>] <filesystem>\n"
384          "       setquota [-t] <-u|--user|-g|--group|-p|--projid>\n"
385          "                [--block-grace <block-grace>]\n"
386          "                [--inode-grace <inode-grace>] <filesystem>\n"
387          "       -b can be used instead of --block-softlimit/--block-grace\n"
388          "       -B can be used instead of --block-hardlimit\n"
389          "       -i can be used instead of --inode-softlimit/--inode-grace\n"
390          "       -I can be used instead of --inode-hardlimit\n\n"
391          "Note: The total quota space will be split into many qunits and\n"
392          "      balanced over all server targets, the minimal qunit size is\n"
393          "      1M bytes for block space and 1K inodes for inode space.\n\n"
394          "      Quota space rebalancing process will stop when this mininum\n"
395          "      value is reached. As a result, quota exceeded can be returned\n"
396          "      while many targets still have 1MB or 1K inodes of spare\n"
397          "      quota space."},
398         {"quota", lfs_quota, 0, "Display disk usage and limits.\n"
399          "usage: quota [-q] [-v] [-h] [-o <obd_uuid>|-i <mdt_idx>|-I "
400                        "<ost_idx>]\n"
401          "             [<-u|-g|-p> <uname>|<uid>|<gname>|<gid>|<projid>] <filesystem>\n"
402          "       quota [-o <obd_uuid>|-i <mdt_idx>|-I <ost_idx>] -t <-u|-g|-p> <filesystem>"},
403         {"project", lfs_project, 0,
404          "Change or list project attribute for specified file or directory.\n"
405          "usage: project [-d|-r] <file|directory...>\n"
406          "         list project ID and flags on file(s) or directories\n"
407          "       project [-p id] [-s] [-r] <file|directory...>\n"
408          "         set project ID and/or inherit flag for specified file(s) or directories\n"
409          "       project -c [-d|-r [-p id] [-0]] <file|directory...>\n"
410          "         check project ID and flags on file(s) or directories, print outliers\n"
411          "       project -C [-r] [-k] <file|directory...>\n"
412          "         clear the project inherit flag and ID on the file or directory\n"
413         },
414 #endif
415         {"flushctx", lfs_flushctx, 0, "Flush security context for current user.\n"
416          "usage: flushctx [-k] [mountpoint...]"},
417         {"cp", lfs_cp, 0,
418          "Remote user copy files and directories.\n"
419          "usage: cp [OPTION]... [-T] SOURCE DEST\n\tcp [OPTION]... SOURCE... DIRECTORY\n\tcp [OPTION]... -t DIRECTORY SOURCE..."},
420         {"ls", lfs_ls, 0,
421          "Remote user list directory contents.\n"
422          "usage: ls [OPTION]... [FILE]..."},
423         {"changelog", lfs_changelog, 0,
424          "Show the metadata changes on an MDT."
425          "\nusage: changelog <mdtname> [startrec [endrec]]"},
426         {"changelog_clear", lfs_changelog_clear, 0,
427          "Indicate that old changelog records up to <endrec> are no longer of "
428          "interest to consumer <id>, allowing the system to free up space.\n"
429          "An <endrec> of 0 means all records.\n"
430          "usage: changelog_clear <mdtname> <id> <endrec>"},
431         {"fid2path", lfs_fid2path, 0,
432          "Resolve the full path(s) for given FID(s). For a specific hardlink "
433          "specify link number <linkno>.\n"
434         /* "For a historical link name, specify changelog record <recno>.\n" */
435          "usage: fid2path [--link <linkno>] <fsname|rootpath> <fid> ..."
436                 /* [ --rec <recno> ] */ },
437         {"path2fid", lfs_path2fid, 0, "Display the fid(s) for a given path(s).\n"
438          "usage: path2fid [--parents] <path> ..."},
439         {"data_version", lfs_data_version, 0, "Display file data version for "
440          "a given path.\n" "usage: data_version -[n|r|w] <path>"},
441         {"hsm_state", lfs_hsm_state, 0, "Display the HSM information (states, "
442          "undergoing actions) for given files.\n usage: hsm_state <file> ..."},
443         {"hsm_set", lfs_hsm_set, 0, "Set HSM user flag on specified files.\n"
444          "usage: hsm_set [--norelease] [--noarchive] [--dirty] [--exists] "
445          "[--archived] [--lost] [--archive-id NUM] <file> ..."},
446         {"hsm_clear", lfs_hsm_clear, 0, "Clear HSM user flag on specified "
447          "files.\n"
448          "usage: hsm_clear [--norelease] [--noarchive] [--dirty] [--exists] "
449          "[--archived] [--lost] <file> ..."},
450         {"hsm_action", lfs_hsm_action, 0, "Display current HSM request for "
451          "given files.\n" "usage: hsm_action <file> ..."},
452         {"hsm_archive", lfs_hsm_archive, 0,
453          "Archive file to external storage.\n"
454          "usage: hsm_archive [--filelist FILELIST] [--data DATA] [--archive NUM] "
455          "<file> ..."},
456         {"hsm_restore", lfs_hsm_restore, 0,
457          "Restore file from external storage.\n"
458          "usage: hsm_restore [--filelist FILELIST] [--data DATA] <file> ..."},
459         {"hsm_release", lfs_hsm_release, 0,
460          "Release files from Lustre.\n"
461          "usage: hsm_release [--filelist FILELIST] [--data DATA] <file> ..."},
462         {"hsm_remove", lfs_hsm_remove, 0,
463          "Remove file copy from external storage.\n"
464          "usage: hsm_remove [--filelist FILELIST] [--data DATA] "
465          "[--archive NUM]\n"
466          "                  (FILE [FILE ...] | "
467          "--mntpath MOUNTPATH FID [FID ...])\n"
468          "\n"
469          "Note: To remove an archived copy of a file already deleted from a "
470          "Lustre FS, the\n"
471          "--mntpath option and a list of FIDs must be specified"
472         },
473         {"hsm_cancel", lfs_hsm_cancel, 0,
474          "Cancel requests related to specified files.\n"
475          "usage: hsm_cancel [--filelist FILELIST] [--data DATA] <file> ..."},
476         {"swap_layouts", lfs_swap_layouts, 0, "Swap layouts between 2 files.\n"
477          "usage: swap_layouts <path1> <path2>"},
478         {"migrate", lfs_setstripe_migrate, 0,
479          "migrate a directory between MDTs.\n"
480          "usage: migrate --mdt-index <mdt_idx> [--verbose|-v] "
481          "<directory>\n"
482          "\tmdt_idx:      index of the destination MDT\n"
483          "\n"
484          "migrate file objects from one OST "
485          "layout\nto another (may be not safe with concurent writes).\n"
486          "usage: migrate  "
487          "[--stripe-count|-c] <stripe_count>\n"
488          "              [--stripe-index|-i] <start_ost_index>\n"
489          "              [--stripe-size|-S] <stripe_size>\n"
490          "              [--pool|-p] <pool_name>\n"
491          "              [--ost-list|-o] <ost_indices>\n"
492          "              [--block|-b]\n"
493          "              [--non-block|-n]\n"
494          "              <file|directory>\n"
495          "\tstripe_count:     number of OSTs to stripe a file over\n"
496          "\tstripe_ost_index: index of the first OST to stripe a file over\n"
497          "\tstripe_size:      number of bytes to store before moving to the next OST\n"
498          "\tpool_name:        name of the predefined pool of OSTs\n"
499          "\tost_indices:      OSTs to stripe over, in order\n"
500          "\tblock:            wait for the operation to return before continuing\n"
501          "\tnon-block:        do not wait for the operation to return.\n"},
502         {"mv", lfs_mv, 0,
503          "To move directories between MDTs. This command is deprecated, "
504          "use \"migrate\" instead.\n"
505          "usage: mv <directory|filename> [--mdt-index|-M] <mdt_index> "
506          "[--verbose|-v]\n"},
507         {"ladvise", lfs_ladvise, 0,
508          "Provide servers with advice about access patterns for a file.\n"
509          "usage: ladvise [--advice|-a ADVICE] [--start|-s START[kMGT]]\n"
510          "               [--background|-b] [--unset|-u]\n\n"
511          "               {[--end|-e END[kMGT]] | [--length|-l LENGTH[kMGT]]}\n"
512          "               {[--mode|-m [READ,WRITE]}\n"
513          "               <file> ...\n"},
514         {"mirror", lfs_mirror, mirror_cmdlist,
515          "lfs commands used to manage files with mirrored components:\n"
516          "lfs mirror create - create a mirrored file or directory\n"
517          "lfs mirror extend - add mirror(s) to an existing file\n"
518          "lfs mirror split  - split a mirror from an existing mirrored file\n"
519          "lfs mirror resync - resynchronize out-of-sync mirrored file(s)\n"
520          "lfs mirror verify - verify mirrored file(s)\n"},
521         {"help", Parser_help, 0, "help"},
522         {"exit", Parser_quit, 0, "quit"},
523         {"quit", Parser_quit, 0, "quit"},
524         {"--version", Parser_version, 0,
525          "output build version of the utility and exit"},
526         {"--list-commands", lfs_list_commands, 0,
527          "list commands supported by the utility and exit"},
528         { 0, 0, 0, NULL }
529 };
530
531
532 static int check_hashtype(const char *hashtype)
533 {
534         int i;
535
536         for (i = LMV_HASH_TYPE_ALL_CHARS; i < LMV_HASH_TYPE_MAX; i++)
537                 if (strcmp(hashtype, mdt_hash_name[i]) == 0)
538                         return i;
539
540         return 0;
541 }
542
543
544 static const char *error_loc = "syserror";
545
546 enum {
547         MIGRATION_NONBLOCK      = 1 << 0,
548         MIGRATION_MIRROR        = 1 << 1,
549 };
550
551 static int lfs_component_create(char *fname, int open_flags, mode_t open_mode,
552                                 struct llapi_layout *layout);
553
554 static int
555 migrate_open_files(const char *name, const struct llapi_stripe_param *param,
556                    struct llapi_layout *layout, int *fd_src, int *fd_tgt)
557 {
558         int                      fd = -1;
559         int                      fdv = -1;
560         int                      mdt_index;
561         int                      random_value;
562         char                     parent[PATH_MAX];
563         char                     volatile_file[PATH_MAX];
564         char                    *ptr;
565         int                      rc;
566         struct stat              st;
567         struct stat              stv;
568
569         if (param == NULL && layout == NULL) {
570                 error_loc = "layout information";
571                 return -EINVAL;
572         }
573
574         /* search for file directory pathname */
575         if (strlen(name) > sizeof(parent) - 1) {
576                 error_loc = "source file name";
577                 return -ERANGE;
578         }
579
580         strncpy(parent, name, sizeof(parent));
581         ptr = strrchr(parent, '/');
582         if (ptr == NULL) {
583                 if (getcwd(parent, sizeof(parent)) == NULL) {
584                         error_loc = "getcwd";
585                         return -errno;
586                 }
587         } else {
588                 if (ptr == parent) /* leading '/' */
589                         ptr = parent + 1;
590                 *ptr = '\0';
591         }
592
593         /* open file, direct io */
594         /* even if the file is only read, WR mode is nedeed to allow
595          * layout swap on fd */
596         fd = open(name, O_RDWR | O_DIRECT);
597         if (fd < 0) {
598                 rc = -errno;
599                 error_loc = "cannot open source file";
600                 return rc;
601         }
602
603         rc = llapi_file_fget_mdtidx(fd, &mdt_index);
604         if (rc < 0) {
605                 error_loc = "cannot get MDT index";
606                 goto out;
607         }
608
609         do {
610                 int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW;
611                 mode_t open_mode = S_IRUSR | S_IWUSR;
612
613                 random_value = random();
614                 rc = snprintf(volatile_file, sizeof(volatile_file),
615                               "%s/%s:%.4X:%.4X", parent, LUSTRE_VOLATILE_HDR,
616                               mdt_index, random_value);
617                 if (rc >= sizeof(volatile_file)) {
618                         rc = -ENAMETOOLONG;
619                         break;
620                 }
621
622                 /* create, open a volatile file, use caching (ie no directio) */
623                 if (param != NULL)
624                         fdv = llapi_file_open_param(volatile_file, open_flags,
625                                                     open_mode, param);
626                 else
627                         fdv = lfs_component_create(volatile_file, open_flags,
628                                                    open_mode, layout);
629         } while (fdv < 0 && (rc = fdv) == -EEXIST);
630
631         if (rc < 0) {
632                 error_loc = "cannot create volatile file";
633                 goto out;
634         }
635
636         /* In case the MDT does not support creation of volatile files
637          * we should try to unlink it. */
638         (void)unlink(volatile_file);
639
640         /* Not-owner (root?) special case.
641          * Need to set owner/group of volatile file like original.
642          * This will allow to pass related check during layout_swap.
643          */
644         rc = fstat(fd, &st);
645         if (rc != 0) {
646                 rc = -errno;
647                 error_loc = "cannot stat source file";
648                 goto out;
649         }
650
651         rc = fstat(fdv, &stv);
652         if (rc != 0) {
653                 rc = -errno;
654                 error_loc = "cannot stat volatile";
655                 goto out;
656         }
657
658         if (st.st_uid != stv.st_uid || st.st_gid != stv.st_gid) {
659                 rc = fchown(fdv, st.st_uid, st.st_gid);
660                 if (rc != 0) {
661                         rc = -errno;
662                         error_loc = "cannot change ownwership of volatile";
663                         goto out;
664                 }
665         }
666
667 out:
668         if (rc < 0) {
669                 if (fd > 0)
670                         close(fd);
671                 if (fdv > 0)
672                         close(fdv);
673         } else {
674                 *fd_src = fd;
675                 *fd_tgt = fdv;
676                 error_loc = NULL;
677         }
678         return rc;
679 }
680
681 static int migrate_copy_data(int fd_src, int fd_dst, int (*check_file)(int))
682 {
683         struct llapi_layout *layout;
684         size_t   buf_size = 4 * 1024 * 1024;
685         void    *buf = NULL;
686         ssize_t  rsize = -1;
687         ssize_t  wsize = 0;
688         size_t   rpos = 0;
689         size_t   wpos = 0;
690         off_t    bufoff = 0;
691         int      rc;
692
693         layout = llapi_layout_get_by_fd(fd_src, 0);
694         if (layout != NULL) {
695                 uint64_t stripe_size;
696
697                 rc = llapi_layout_stripe_size_get(layout, &stripe_size);
698                 if (rc == 0)
699                         buf_size = stripe_size;
700
701                 llapi_layout_free(layout);
702         }
703
704         /* Use a page-aligned buffer for direct I/O */
705         rc = posix_memalign(&buf, getpagesize(), buf_size);
706         if (rc != 0)
707                 return -rc;
708
709         while (1) {
710                 /* read new data only if we have written all
711                  * previously read data */
712                 if (wpos == rpos) {
713                         if (check_file) {
714                                 rc = check_file(fd_src);
715                                 if (rc < 0)
716                                         break;
717                         }
718
719                         rsize = read(fd_src, buf, buf_size);
720                         if (rsize < 0) {
721                                 rc = -errno;
722                                 break;
723                         }
724                         rpos += rsize;
725                         bufoff = 0;
726                 }
727                 /* eof ? */
728                 if (rsize == 0)
729                         break;
730
731                 wsize = write(fd_dst, buf + bufoff, rpos - wpos);
732                 if (wsize < 0) {
733                         rc = -errno;
734                         break;
735                 }
736                 wpos += wsize;
737                 bufoff += wsize;
738         }
739
740         if (rc == 0) {
741                 rc = fsync(fd_dst);
742                 if (rc < 0)
743                         rc = -errno;
744         }
745
746         free(buf);
747         return rc;
748 }
749
750 static int migrate_copy_timestamps(int fd, int fdv)
751 {
752         struct stat st;
753
754         if (fstat(fd, &st) == 0) {
755                 struct timeval tv[2] = {
756                         {.tv_sec = st.st_atime},
757                         {.tv_sec = st.st_mtime}
758                 };
759
760                 return futimes(fdv, tv);
761         }
762
763         return -errno;
764 }
765
766 static int migrate_block(int fd, int fdv)
767 {
768         __u64   dv1;
769         int     gid;
770         int     rc;
771         int     rc2;
772
773         rc = llapi_get_data_version(fd, &dv1, LL_DV_RD_FLUSH);
774         if (rc < 0) {
775                 error_loc = "cannot get dataversion";
776                 return rc;
777         }
778
779         do
780                 gid = random();
781         while (gid == 0);
782
783         /* The grouplock blocks all concurrent accesses to the file.
784          * It has to be taken after llapi_get_data_version as it would
785          * block it too. */
786         rc = llapi_group_lock(fd, gid);
787         if (rc < 0) {
788                 error_loc = "cannot get group lock";
789                 return rc;
790         }
791
792         rc = migrate_copy_data(fd, fdv, NULL);
793         if (rc < 0) {
794                 error_loc = "data copy failed";
795                 goto out_unlock;
796         }
797
798         /* Make sure we keep original atime/mtime values */
799         rc = migrate_copy_timestamps(fd, fdv);
800         if (rc < 0) {
801                 error_loc = "timestamp copy failed";
802                 goto out_unlock;
803         }
804
805         /* swap layouts
806          * for a migration we need to check data version on file did
807          * not change.
808          *
809          * Pass in gid=0 since we already own grouplock. */
810         rc = llapi_fswap_layouts_grouplock(fd, fdv, dv1, 0, 0,
811                                            SWAP_LAYOUTS_CHECK_DV1);
812         if (rc == -EAGAIN) {
813                 error_loc = "file changed";
814                 goto out_unlock;
815         } else if (rc < 0) {
816                 error_loc = "cannot swap layout";
817                 goto out_unlock;
818         }
819
820 out_unlock:
821         rc2 = llapi_group_unlock(fd, gid);
822         if (rc2 < 0 && rc == 0) {
823                 error_loc = "unlock group lock";
824                 rc = rc2;
825         }
826
827         return rc;
828 }
829
830 /**
831  * Internal helper for migrate_copy_data(). Check lease and report error if
832  * need be.
833  *
834  * \param[in]  fd           File descriptor on which to check the lease.
835  *
836  * \retval 0       Migration can keep on going.
837  * \retval -errno  Error occurred, abort migration.
838  */
839 static int check_lease(int fd)
840 {
841         int rc;
842
843         rc = llapi_lease_check(fd);
844         if (rc > 0)
845                 return 0; /* llapi_check_lease returns > 0 on success. */
846
847         return -EBUSY;
848 }
849
850 static int migrate_nonblock(int fd, int fdv)
851 {
852         __u64   dv1;
853         __u64   dv2;
854         int     rc;
855
856         rc = llapi_get_data_version(fd, &dv1, LL_DV_RD_FLUSH);
857         if (rc < 0) {
858                 error_loc = "cannot get data version";
859                 return rc;
860         }
861
862         rc = migrate_copy_data(fd, fdv, check_lease);
863         if (rc < 0) {
864                 error_loc = "data copy failed";
865                 return rc;
866         }
867
868         rc = llapi_get_data_version(fd, &dv2, LL_DV_RD_FLUSH);
869         if (rc != 0) {
870                 error_loc = "cannot get data version";
871                 return rc;
872         }
873
874         if (dv1 != dv2) {
875                 rc = -EAGAIN;
876                 error_loc = "source file changed";
877                 return rc;
878         }
879
880         /* Make sure we keep original atime/mtime values */
881         rc = migrate_copy_timestamps(fd, fdv);
882         if (rc < 0) {
883                 error_loc = "timestamp copy failed";
884                 return rc;
885         }
886
887         return 0;
888 }
889
890 static int lfs_component_set(char *fname, int comp_id,
891                              __u32 flags, __u32 neg_flags)
892 {
893         __u32 ids[2];
894         __u32 flags_array[2];
895         size_t count = 0;
896         int rc;
897
898         if (flags) {
899                 ids[count] = comp_id;
900                 flags_array[count] = flags;
901                 ++count;
902         }
903
904         if (neg_flags) {
905                 ids[count] = comp_id;
906                 flags_array[count] = neg_flags | LCME_FL_NEG;
907                 ++count;
908         }
909
910         rc = llapi_layout_file_comp_set(fname, ids, flags_array, count);
911         if (rc)
912                 fprintf(stderr,
913                         "%s: cannot change the flags of component '%#x' of file '%s': %x / ^(%x)\n",
914                         progname, comp_id, fname, flags, neg_flags);
915
916         return rc;
917 }
918
919 static int lfs_component_del(char *fname, __u32 comp_id,
920                              __u32 flags, __u32 neg_flags)
921 {
922         int     rc = 0;
923
924         if (flags && neg_flags)
925                 return -EINVAL;
926
927         if (!flags && neg_flags)
928                 flags = neg_flags | LCME_FL_NEG;
929
930         if ((flags && comp_id) || (!flags && !comp_id))
931                 return -EINVAL;
932
933         /* LCME_FL_INIT is the only supported flag in PFL */
934         if (flags) {
935                 if (flags & ~LCME_KNOWN_FLAGS) {
936                         fprintf(stderr,
937                                 "%s setstripe: unknown flags %#x\n",
938                                 progname, flags);
939                         return -EINVAL;
940                 }
941         } else if (comp_id > LCME_ID_MAX) {
942                 fprintf(stderr, "%s setstripe: invalid component id %u\n",
943                         progname, comp_id);
944                 return -EINVAL;
945         }
946
947         rc = llapi_layout_file_comp_del(fname, comp_id, flags);
948         if (rc)
949                 fprintf(stderr,
950                         "%s setstripe: cannot delete component %#x from '%s': %s\n",
951                         progname, comp_id, fname, strerror(errno));
952         return rc;
953 }
954
955 static int lfs_component_add(char *fname, struct llapi_layout *layout)
956 {
957         int     rc;
958
959         if (layout == NULL)
960                 return -EINVAL;
961
962         rc = llapi_layout_file_comp_add(fname, layout);
963         if (rc)
964                 fprintf(stderr, "Add layout component(s) to %s failed. %s\n",
965                         fname, strerror(errno));
966         return rc;
967 }
968
969 static int lfs_component_create(char *fname, int open_flags, mode_t open_mode,
970                                 struct llapi_layout *layout)
971 {
972         struct stat     st;
973         int     fd;
974
975         if (layout == NULL)
976                 return -EINVAL;
977
978         fd = lstat(fname, &st);
979         if (fd == 0 && S_ISDIR(st.st_mode))
980                 open_flags = O_DIRECTORY | O_RDONLY;
981
982         fd = llapi_layout_file_open(fname, open_flags, open_mode, layout);
983         if (fd < 0)
984                 fprintf(stderr, "%s: cannot %s '%s': %s\n", progname,
985                         S_ISDIR(st.st_mode) ?
986                                 "set default composite layout for" :
987                                 "create composite file",
988                         fname, strerror(errno));
989         return fd;
990 }
991
992 static int lfs_migrate(char *name, __u64 migration_flags,
993                        struct llapi_stripe_param *param,
994                        struct llapi_layout *layout)
995 {
996         int fd = -1;
997         int fdv = -1;
998         int rc;
999
1000         rc = migrate_open_files(name, param, layout, &fd, &fdv);
1001         if (rc < 0)
1002                 goto out;
1003
1004         if (!(migration_flags & MIGRATION_NONBLOCK)) {
1005                 /* Blocking mode (forced if servers do not support file lease).
1006                  * It is also the default mode, since we cannot distinguish
1007                  * between a broken lease and a server that does not support
1008                  * atomic swap/close (LU-6785) */
1009                 rc = migrate_block(fd, fdv);
1010                 goto out;
1011         }
1012
1013         rc = llapi_lease_acquire(fd, LL_LEASE_RDLCK);
1014         if (rc < 0) {
1015                 error_loc = "cannot get lease";
1016                 goto out;
1017         }
1018
1019         rc = migrate_nonblock(fd, fdv);
1020         if (rc < 0) {
1021                 llapi_lease_release(fd);
1022                 goto out;
1023         }
1024
1025         /* Atomically put lease, swap layouts and close.
1026          * for a migration we need to check data version on file did
1027          * not change. */
1028         rc = llapi_fswap_layouts(fd, fdv, 0, 0, SWAP_LAYOUTS_CLOSE);
1029         if (rc < 0) {
1030                 error_loc = "cannot swap layout";
1031                 goto out;
1032         }
1033
1034 out:
1035         if (fd >= 0)
1036                 close(fd);
1037
1038         if (fdv >= 0)
1039                 close(fdv);
1040
1041         if (rc < 0)
1042                 fprintf(stderr, "error: %s: %s: %s: %s\n",
1043                         progname, name, error_loc, strerror(-rc));
1044         return rc;
1045 }
1046
1047 static int comp_str2flags(char *string, __u32 *flags, __u32 *neg_flags)
1048 {
1049         char *name;
1050
1051         if (string == NULL)
1052                 return -EINVAL;
1053
1054         *flags = 0;
1055         *neg_flags = 0;
1056         for (name = strtok(string, ","); name; name = strtok(NULL, ",")) {
1057                 bool found = false;
1058                 int i;
1059
1060                 for (i = 0; i < ARRAY_SIZE(comp_flags_table); i++) {
1061                         __u32 comp_flag = comp_flags_table[i].cfn_flag;
1062                         const char *comp_name = comp_flags_table[i].cfn_name;
1063
1064                         if (strcmp(name, comp_name) == 0) {
1065                                 *flags |= comp_flag;
1066                                 found = true;
1067                         } else if (strncmp(name, "^", 1) == 0 &&
1068                                    strcmp(name + 1, comp_name) == 0) {
1069                                 *neg_flags |= comp_flag;
1070                                 found = true;
1071                         }
1072                 }
1073                 if (!found) {
1074                         llapi_printf(LLAPI_MSG_ERROR,
1075                                      "%s: component flag '%s' not supported\n",
1076                                      progname, name);
1077                         return -EINVAL;
1078                 }
1079         }
1080
1081         if (!*flags && !*neg_flags)
1082                 return -EINVAL;
1083
1084         /* don't allow to set and exclude the same flag */
1085         if (*flags & *neg_flags)
1086                 return -EINVAL;
1087
1088         return 0;
1089 }
1090
1091 /**
1092  * struct mirror_args - Command-line arguments for mirror(s).
1093  * @m_count:  Number of mirrors to be created with this layout.
1094  * @m_flags:  Mirror level flags, only 'prefer' is supported.
1095  * @m_layout: Mirror layout.
1096  * @m_file:   A victim file. Its layout will be split and used as a mirror.
1097  * @m_next:   Point to the next node of the list.
1098  *
1099  * Command-line arguments for mirror(s) will be parsed and stored in
1100  * a linked list that consists of this structure.
1101  */
1102 struct mirror_args {
1103         __u32                   m_count;
1104         __u32                   m_flags;
1105         struct llapi_layout     *m_layout;
1106         const char              *m_file;
1107         struct mirror_args      *m_next;
1108 };
1109
1110 static int mirror_sanity_check_flags(struct llapi_layout *layout, void *unused)
1111 {
1112         uint32_t flags;
1113         int rc;
1114
1115         rc = llapi_layout_comp_flags_get(layout, &flags);
1116         if (rc)
1117                 return -errno;
1118
1119         if (flags & LCME_FL_NEG) {
1120                 fprintf(stderr, "error: %s: negative flags are not supported\n",
1121                         progname);
1122                 return -EINVAL;
1123         }
1124
1125         if (flags & LCME_FL_STALE) {
1126                 fprintf(stderr, "error: %s: setting '%s' is not supported\n",
1127                         progname, comp_flags_table[LCME_FL_STALE].cfn_name);
1128                 return -EINVAL;
1129         }
1130
1131         return LLAPI_LAYOUT_ITER_CONT;
1132 }
1133
1134 static inline int mirror_sanity_check_one(struct llapi_layout *layout)
1135 {
1136         uint64_t start, end;
1137         uint64_t pattern;
1138         int rc;
1139
1140         /* LU-10112: do not support dom+flr in phase 1 */
1141         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1142         if (rc)
1143                 return -errno;
1144
1145         rc = llapi_layout_pattern_get(layout, &pattern);
1146         if (rc)
1147                 return -errno;
1148
1149         if (pattern == LOV_PATTERN_MDT || pattern == LLAPI_LAYOUT_MDT) {
1150                 fprintf(stderr, "error: %s: doesn't support dom+flr for now\n",
1151                         progname);
1152                 return -ENOTSUP;
1153         }
1154
1155         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_LAST);
1156         if (rc)
1157                 return -errno;
1158
1159         rc = llapi_layout_comp_extent_get(layout, &start, &end);
1160         if (rc)
1161                 return -errno;
1162
1163         if (end != LUSTRE_EOF) {
1164                 fprintf(stderr, "error: %s: mirror layout doesn't reach eof\n",
1165                         progname);
1166                 return -EINVAL;
1167         }
1168
1169         rc = llapi_layout_comp_iterate(layout, mirror_sanity_check_flags, NULL);
1170         return rc;
1171 }
1172
1173 /**
1174  * enum mirror_flags - Flags for extending a mirrored file.
1175  * @NO_VERIFY: Indicates not to verify the mirror(s) from victim file(s)
1176  *             in case the victim file(s) contains the same data as the
1177  *             original mirrored file.
1178  *
1179  * Flags for extending a mirrored file.
1180  */
1181 enum mirror_flags {
1182         NO_VERIFY       = 0x1,
1183 };
1184
1185 /**
1186  * mirror_create_sanity_check() - Check mirror list.
1187  * @list:  A linked list that stores the mirror arguments.
1188  *
1189  * This function does a sanity check on @list for creating
1190  * a mirrored file.
1191  *
1192  * Return: 0 on success or a negative error code on failure.
1193  */
1194 static int mirror_create_sanity_check(const char *fname,
1195                                       struct mirror_args *list)
1196 {
1197         int rc = 0;
1198         bool has_m_file = false;
1199         bool has_m_layout = false;
1200
1201         if (list == NULL)
1202                 return -EINVAL;
1203
1204         if (fname) {
1205                 struct llapi_layout *layout;
1206
1207                 layout = llapi_layout_get_by_path(fname, 0);
1208                 if (!layout) {
1209                         fprintf(stderr,
1210                                 "error: %s: file '%s' couldn't get layout\n",
1211                                 progname, fname);
1212                         return -ENODATA;
1213                 }
1214
1215                 rc = mirror_sanity_check_one(layout);
1216                 llapi_layout_free(layout);
1217
1218                 if (rc)
1219                         return rc;
1220         }
1221
1222         while (list != NULL) {
1223                 if (list->m_file != NULL) {
1224                         has_m_file = true;
1225                         llapi_layout_free(list->m_layout);
1226
1227                         list->m_layout =
1228                                 llapi_layout_get_by_path(list->m_file, 0);
1229                         if (list->m_layout == NULL) {
1230                                 fprintf(stderr,
1231                                         "error: %s: file '%s' has no layout\n",
1232                                         progname, list->m_file);
1233                                 return -ENODATA;
1234                         }
1235                 } else {
1236                         has_m_layout = true;
1237                         if (list->m_layout == NULL) {
1238                                 fprintf(stderr, "error: %s: no mirror layout\n",
1239                                         progname);
1240                                 return -EINVAL;
1241                         }
1242                 }
1243
1244                 rc = mirror_sanity_check_one(list->m_layout);
1245                 if (rc)
1246                         return rc;
1247
1248                 list = list->m_next;
1249         }
1250
1251         if (has_m_file && has_m_layout) {
1252                 fprintf(stderr, "error: %s: -f <victim_file> option should not "
1253                         "be specified with setstripe options or "
1254                         "--parent option\n", progname);
1255                 return -EINVAL;
1256         }
1257
1258         return 0;
1259 }
1260
1261 static int mirror_set_flags(struct llapi_layout *layout, void *cbdata)
1262 {
1263         __u32 mirror_flags = *(__u32 *)cbdata;
1264         uint32_t flags;
1265         int rc;
1266
1267         rc = llapi_layout_comp_flags_get(layout, &flags);
1268         if (rc < 0)
1269                 return rc;
1270
1271         if (!flags) {
1272                 rc = llapi_layout_comp_flags_set(layout, mirror_flags);
1273                 if (rc)
1274                         return rc;
1275         }
1276
1277         return LLAPI_LAYOUT_ITER_CONT;
1278 }
1279
1280 /**
1281  * mirror_create() - Create a mirrored file.
1282  * @fname:        The file to be created.
1283  * @mirror_list:  A linked list that stores the mirror arguments.
1284  *
1285  * This function creates a mirrored file @fname with the mirror(s)
1286  * from @mirror_list.
1287  *
1288  * Return: 0 on success or a negative error code on failure.
1289  */
1290 static int mirror_create(char *fname, struct mirror_args *mirror_list)
1291 {
1292         struct llapi_layout *layout = NULL;
1293         struct mirror_args *cur_mirror = NULL;
1294         uint16_t mirror_count = 0;
1295         int i = 0;
1296         int rc = 0;
1297
1298         rc = mirror_create_sanity_check(NULL, mirror_list);
1299         if (rc)
1300                 return rc;
1301
1302         cur_mirror = mirror_list;
1303         while (cur_mirror != NULL) {
1304                 rc = llapi_layout_comp_iterate(cur_mirror->m_layout,
1305                                                mirror_set_flags,
1306                                                &cur_mirror->m_flags);
1307                 if (rc) {
1308                         rc = -errno;
1309                         fprintf(stderr, "%s: failed to set mirror flags\n",
1310                                 progname);
1311                         goto error;
1312                 }
1313
1314                 for (i = 0; i < cur_mirror->m_count; i++) {
1315                         rc = llapi_layout_merge(&layout, cur_mirror->m_layout);
1316                         if (rc) {
1317                                 rc = -errno;
1318                                 fprintf(stderr, "error: %s: "
1319                                         "merge layout failed: %s\n",
1320                                         progname, strerror(errno));
1321                                 goto error;
1322                         }
1323                 }
1324                 mirror_count += cur_mirror->m_count;
1325                 cur_mirror = cur_mirror->m_next;
1326         }
1327
1328         if (layout == NULL) {
1329                 fprintf(stderr, "error: %s: layout is NULL\n", progname);
1330                 return -EINVAL;
1331         }
1332
1333         rc = llapi_layout_mirror_count_set(layout, mirror_count);
1334         if (rc) {
1335                 rc = -errno;
1336                 fprintf(stderr, "error: %s: set mirror count failed: %s\n",
1337                         progname, strerror(errno));
1338                 goto error;
1339         }
1340
1341         rc = lfs_component_create(fname, O_CREAT | O_WRONLY, 0644,
1342                                   layout);
1343         if (rc >= 0) {
1344                 close(rc);
1345                 rc = 0;
1346         }
1347
1348 error:
1349         llapi_layout_free(layout);
1350         return rc;
1351 }
1352
1353 /**
1354  * Compare files and check lease on @fd.
1355  *
1356  * \retval bytes number of bytes are the same
1357  */
1358 static ssize_t mirror_file_compare(int fd, int fdv)
1359 {
1360         const size_t buflen = 4 * 1024 * 1024; /* 4M */
1361         void *buf;
1362         ssize_t bytes_done = 0;
1363         ssize_t bytes_read = 0;
1364
1365         buf = malloc(buflen * 2);
1366         if (!buf)
1367                 return -ENOMEM;
1368
1369         while (1) {
1370                 if (!llapi_lease_check(fd)) {
1371                         bytes_done = -EBUSY;
1372                         break;
1373                 }
1374
1375                 bytes_read = read(fd, buf, buflen);
1376                 if (bytes_read <= 0)
1377                         break;
1378
1379                 if (bytes_read != read(fdv, buf + buflen, buflen))
1380                         break;
1381
1382                 /* XXX: should compute the checksum on each buffer and then
1383                  * compare checksum to avoid cache collision */
1384                 if (memcmp(buf, buf + buflen, bytes_read))
1385                         break;
1386
1387                 bytes_done += bytes_read;
1388         }
1389
1390         free(buf);
1391
1392         return bytes_done;
1393 }
1394
1395 static int mirror_extend_file(const char *fname, const char *victim_file,
1396                               enum mirror_flags mirror_flags)
1397 {
1398         int fd = -1;
1399         int fdv = -1;
1400         struct stat stbuf;
1401         struct stat stbuf_v;
1402         struct ll_ioc_lease *data = NULL;
1403         int rc;
1404
1405         fd = open(fname, O_RDWR);
1406         if (fd < 0) {
1407                 error_loc = "open source file";
1408                 rc = -errno;
1409                 goto out;
1410         }
1411
1412         fdv = open(victim_file, O_RDWR);
1413         if (fdv < 0) {
1414                 error_loc = "open target file";
1415                 rc = -errno;
1416                 goto out;
1417         }
1418
1419         if (fstat(fd, &stbuf) || fstat(fdv, &stbuf_v)) {
1420                 error_loc = "stat source or target file";
1421                 rc = -errno;
1422                 goto out;
1423         }
1424
1425         if (stbuf.st_dev != stbuf_v.st_dev) {
1426                 error_loc = "stat source and target file";
1427                 rc = -EXDEV;
1428                 goto out;
1429         }
1430
1431         /* mirrors should be of the same size */
1432         if (stbuf.st_size != stbuf_v.st_size) {
1433                 error_loc = "file sizes don't match";
1434                 rc = -EINVAL;
1435                 goto out;
1436         }
1437
1438         rc = llapi_lease_acquire(fd, LL_LEASE_RDLCK);
1439         if (rc < 0) {
1440                 error_loc = "cannot get lease";
1441                 goto out;
1442         }
1443
1444         if (!(mirror_flags & NO_VERIFY)) {
1445                 ssize_t ret;
1446                 /* mirrors should have the same contents */
1447                 ret = mirror_file_compare(fd, fdv);
1448                 if (ret != stbuf.st_size) {
1449                         error_loc = "file busy or contents don't match";
1450                         rc = ret < 0 ? ret : -EINVAL;
1451                         goto out;
1452                 }
1453         }
1454
1455         /* Get rid of caching pages from clients */
1456         rc = llapi_file_flush(fd);
1457         if (rc < 0) {
1458                 error_loc = "cannot get data version";
1459                 goto out;
1460         }
1461
1462         rc = llapi_file_flush(fdv);
1463         if (rc < 0) {
1464                 error_loc = "cannot get data version";
1465                 goto out;
1466
1467         }
1468
1469         /* Make sure we keep original atime/mtime values */
1470         rc = migrate_copy_timestamps(fd, fdv);
1471         if (rc < 0) {
1472                 error_loc = "cannot copy timestamp";
1473                 goto out;
1474         }
1475
1476         /* Atomically put lease, merge layouts and close. */
1477         data = calloc(1, offsetof(typeof(*data), lil_ids[1]));
1478         if (!data) {
1479                 error_loc = "memory allocation";
1480                 goto out;
1481         }
1482         data->lil_mode = LL_LEASE_UNLCK;
1483         data->lil_flags = LL_LEASE_LAYOUT_MERGE;
1484         data->lil_count = 1;
1485         data->lil_ids[0] = fdv;
1486         rc = llapi_lease_set(fd, data);
1487         if (rc < 0) {
1488                 error_loc = "cannot merge layout";
1489                 goto out;
1490         } else if (rc == 0) {
1491                 rc = -EBUSY;
1492                 error_loc = "lost lease lock";
1493                 goto out;
1494         }
1495         rc = 0;
1496
1497 out:
1498         if (data)
1499                 free(data);
1500         if (fd >= 0)
1501                 close(fd);
1502         if (fdv >= 0)
1503                 close(fdv);
1504         if (!rc)
1505                 (void) unlink(victim_file);
1506         if (rc < 0)
1507                 fprintf(stderr, "error: %s: %s: %s: %s\n",
1508                         progname, fname, error_loc, strerror(-rc));
1509         return rc;
1510 }
1511
1512 static int mirror_extend_layout(char *name, struct llapi_layout *layout)
1513 {
1514         struct ll_ioc_lease *data = NULL;
1515         int fd = -1;
1516         int fdv = -1;
1517         int rc;
1518
1519         rc = migrate_open_files(name, NULL, layout, &fd, &fdv);
1520         if (rc < 0)
1521                 goto out;
1522
1523         rc = llapi_lease_acquire(fd, LL_LEASE_RDLCK);
1524         if (rc < 0) {
1525                 error_loc = "cannot get lease";
1526                 goto out;
1527         }
1528
1529         rc = migrate_nonblock(fd, fdv);
1530         if (rc < 0) {
1531                 llapi_lease_release(fd);
1532                 goto out;
1533         }
1534
1535         /* Atomically put lease, merge layouts and close. */
1536         data = calloc(1, offsetof(typeof(*data), lil_ids[1]));
1537         if (!data) {
1538                 error_loc = "memory allocation";
1539                 goto out;
1540         }
1541         data->lil_mode = LL_LEASE_UNLCK;
1542         data->lil_flags = LL_LEASE_LAYOUT_MERGE;
1543         data->lil_count = 1;
1544         data->lil_ids[0] = fdv;
1545         rc = llapi_lease_set(fd, data);
1546         if (rc < 0) {
1547                 error_loc = "cannot merge layout";
1548                 goto out;
1549         } else if (rc == 0) {
1550                 rc = -EBUSY;
1551                 error_loc = "lost lease lock";
1552                 goto out;
1553         }
1554         rc = 0;
1555
1556 out:
1557         if (data)
1558                 free(data);
1559         if (fd >= 0)
1560                 close(fd);
1561         if (fdv >= 0)
1562                 close(fdv);
1563         if (rc < 0)
1564                 fprintf(stderr, "error: %s: %s: %s: %s\n",
1565                         progname, name, error_loc, strerror(-rc));
1566         return rc;
1567 }
1568
1569 static int mirror_extend(char *fname, struct mirror_args *mirror_list,
1570                          enum mirror_flags mirror_flags)
1571 {
1572         int rc;
1573
1574         rc = mirror_create_sanity_check(fname, mirror_list);
1575         if (rc)
1576                 return rc;
1577
1578         while (mirror_list) {
1579                 if (mirror_list->m_file != NULL) {
1580                         rc = mirror_extend_file(fname, mirror_list->m_file,
1581                                                 mirror_flags);
1582                 } else {
1583                         __u32 mirror_count = mirror_list->m_count;
1584
1585                         while (mirror_count > 0) {
1586                                 rc = mirror_extend_layout(fname,
1587                                                         mirror_list->m_layout);
1588                                 if (rc)
1589                                         break;
1590
1591                                 --mirror_count;
1592                         }
1593                 }
1594                 if (rc)
1595                         break;
1596
1597                 mirror_list = mirror_list->m_next;
1598         }
1599
1600         return rc;
1601 }
1602
1603 /**
1604  * Parse a string containing an target index list into an array of integers.
1605  *
1606  * The input string contains a comma delimited list of individual
1607  * indices and ranges, for example "1,2-4,7". Add the indices into the
1608  * \a tgts array and remove duplicates.
1609  *
1610  * \param[out] tgts    array to store indices in
1611  * \param[in] size     size of \a tgts array
1612  * \param[in] offset   starting index in \a tgts
1613  * \param[in] arg      string containing OST index list
1614  *
1615  * \retval positive    number of indices in \a tgts
1616  * \retval -EINVAL     unable to parse \a arg
1617  */
1618 static int parse_targets(__u32 *tgts, int size, int offset, char *arg)
1619 {
1620         int rc;
1621         int nr = offset;
1622         int slots = size - offset;
1623         char *ptr = NULL;
1624         bool end_of_loop;
1625
1626         if (arg == NULL)
1627                 return -EINVAL;
1628
1629         end_of_loop = false;
1630         while (!end_of_loop) {
1631                 int start_index;
1632                 int end_index;
1633                 int i;
1634                 char *endptr = NULL;
1635
1636                 rc = -EINVAL;
1637
1638                 ptr = strchrnul(arg, ',');
1639
1640                 end_of_loop = *ptr == '\0';
1641                 *ptr = '\0';
1642
1643                 start_index = strtol(arg, &endptr, 0);
1644                 if (endptr == arg) /* no data at all */
1645                         break;
1646                 if (*endptr != '-' && *endptr != '\0') /* has invalid data */
1647                         break;
1648
1649                 end_index = start_index;
1650                 if (*endptr == '-') {
1651                         end_index = strtol(endptr + 1, &endptr, 0);
1652                         if (*endptr != '\0')
1653                                 break;
1654                         if (end_index < start_index)
1655                                 break;
1656                 }
1657
1658                 for (i = start_index; i <= end_index && slots > 0; i++) {
1659                         int j;
1660
1661                         /* remove duplicate */
1662                         for (j = 0; j < offset; j++) {
1663                                 if (tgts[j] == i)
1664                                         break;
1665                         }
1666                         if (j == offset) { /* no duplicate */
1667                                 tgts[nr++] = i;
1668                                 --slots;
1669                         }
1670                 }
1671                 if (slots == 0 && i < end_index)
1672                         break;
1673
1674                 *ptr = ',';
1675                 arg = ++ptr;
1676                 offset = nr;
1677                 rc = 0;
1678         }
1679         if (!end_of_loop && ptr != NULL)
1680                 *ptr = ',';
1681
1682         return rc < 0 ? rc : nr;
1683 }
1684
1685 struct lfs_setstripe_args {
1686         unsigned long long       lsa_comp_end;
1687         unsigned long long       lsa_stripe_size;
1688         long long                lsa_stripe_count;
1689         long long                lsa_stripe_off;
1690         __u32                    lsa_comp_flags;
1691         __u32                    lsa_comp_neg_flags;
1692         unsigned long long       lsa_pattern;
1693         int                      lsa_nr_tgts;
1694         __u32                   *lsa_tgts;
1695         char                    *lsa_pool_name;
1696 };
1697
1698 static inline void setstripe_args_init(struct lfs_setstripe_args *lsa)
1699 {
1700         memset(lsa, 0, sizeof(*lsa));
1701
1702         lsa->lsa_stripe_size = LLAPI_LAYOUT_DEFAULT;
1703         lsa->lsa_stripe_count = LLAPI_LAYOUT_DEFAULT;
1704         lsa->lsa_stripe_off = LLAPI_LAYOUT_DEFAULT;
1705         lsa->lsa_pattern = LLAPI_LAYOUT_RAID0;
1706         lsa->lsa_pool_name = NULL;
1707 }
1708
1709 /**
1710  * setstripe_args_init_inherit() - Initialize and inherit stripe options.
1711  * @lsa: Stripe options to be initialized and inherited.
1712  *
1713  * This function initializes stripe options in @lsa and inherit
1714  * stripe_size, stripe_count and OST pool_name options.
1715  *
1716  * Return: void.
1717  */
1718 static inline void setstripe_args_init_inherit(struct lfs_setstripe_args *lsa)
1719 {
1720         unsigned long long stripe_size;
1721         long long stripe_count;
1722         char *pool_name = NULL;
1723
1724         stripe_size = lsa->lsa_stripe_size;
1725         stripe_count = lsa->lsa_stripe_count;
1726         pool_name = lsa->lsa_pool_name;
1727
1728         setstripe_args_init(lsa);
1729
1730         lsa->lsa_stripe_size = stripe_size;
1731         lsa->lsa_stripe_count = stripe_count;
1732         lsa->lsa_pool_name = pool_name;
1733 }
1734
1735 static inline bool setstripe_args_specified(struct lfs_setstripe_args *lsa)
1736 {
1737         return (lsa->lsa_stripe_size != LLAPI_LAYOUT_DEFAULT ||
1738                 lsa->lsa_stripe_count != LLAPI_LAYOUT_DEFAULT ||
1739                 lsa->lsa_stripe_off != LLAPI_LAYOUT_DEFAULT ||
1740                 lsa->lsa_pattern != LLAPI_LAYOUT_RAID0 ||
1741                 lsa->lsa_pool_name != NULL ||
1742                 lsa->lsa_comp_end != 0);
1743 }
1744
1745 /**
1746  * comp_args_to_layout() - Create or extend a composite layout.
1747  * @composite:       Pointer to the composite layout.
1748  * @lsa:             Stripe options for the new component.
1749  *
1750  * This function creates or extends a composite layout by adding a new
1751  * component with stripe options from @lsa.
1752  *
1753  * Return: 0 on success or an error code on failure.
1754  */
1755 static int comp_args_to_layout(struct llapi_layout **composite,
1756                                struct lfs_setstripe_args *lsa)
1757 {
1758         struct llapi_layout *layout = *composite;
1759         uint64_t prev_end = 0;
1760         int i = 0, rc;
1761
1762         if (layout == NULL) {
1763                 layout = llapi_layout_alloc();
1764                 if (layout == NULL) {
1765                         fprintf(stderr, "Alloc llapi_layout failed. %s\n",
1766                                 strerror(errno));
1767                         return -ENOMEM;
1768                 }
1769                 *composite = layout;
1770         } else {
1771                 uint64_t start;
1772
1773                 /* Get current component extent, current component
1774                  * must be the tail component. */
1775                 rc = llapi_layout_comp_extent_get(layout, &start, &prev_end);
1776                 if (rc) {
1777                         fprintf(stderr, "Get comp extent failed. %s\n",
1778                                 strerror(errno));
1779                         return rc;
1780                 }
1781
1782                 rc = llapi_layout_comp_add(layout);
1783                 if (rc) {
1784                         fprintf(stderr, "Add component failed. %s\n",
1785                                 strerror(errno));
1786                         return rc;
1787                 }
1788         }
1789
1790         rc = llapi_layout_comp_extent_set(layout, prev_end, lsa->lsa_comp_end);
1791         if (rc) {
1792                 fprintf(stderr, "Set extent [%lu, %llu) failed. %s\n",
1793                         prev_end, lsa->lsa_comp_end, strerror(errno));
1794                 return rc;
1795         }
1796
1797         /* Data-on-MDT component setting */
1798         if (lsa->lsa_pattern == LLAPI_LAYOUT_MDT) {
1799                 /* In case of Data-on-MDT patterns the only extra option
1800                  * applicable is stripe size option. */
1801                 if (lsa->lsa_stripe_count != LLAPI_LAYOUT_DEFAULT) {
1802                         fprintf(stderr, "Option 'stripe-count' can't be "
1803                                 "specified with Data-on-MDT component: %lld\n",
1804                                 lsa->lsa_stripe_count);
1805                         return -EINVAL;
1806                 }
1807                 if (lsa->lsa_stripe_size != LLAPI_LAYOUT_DEFAULT) {
1808                         fprintf(stderr, "Option 'stripe-size' can't be "
1809                                 "specified with Data-on-MDT component: %llu\n",
1810                                 lsa->lsa_stripe_size);
1811                         return -EINVAL;
1812                 }
1813                 if (lsa->lsa_nr_tgts != 0) {
1814                         fprintf(stderr, "Option 'ost-list' can't be specified "
1815                                 "with Data-on-MDT component: '%i'\n",
1816                                 lsa->lsa_nr_tgts);
1817                         return -EINVAL;
1818                 }
1819                 if (lsa->lsa_stripe_off != LLAPI_LAYOUT_DEFAULT) {
1820                         fprintf(stderr, "Option 'stripe-offset' can't be "
1821                                 "specified with Data-on-MDT component: %lld\n",
1822                                 lsa->lsa_stripe_off);
1823                         return -EINVAL;
1824                 }
1825                 if (lsa->lsa_pool_name != 0) {
1826                         fprintf(stderr, "Option 'pool' can't be specified "
1827                                 "with Data-on-MDT component: '%s'\n",
1828                                 lsa->lsa_pool_name);
1829                         return -EINVAL;
1830                 }
1831
1832                 rc = llapi_layout_pattern_set(layout, lsa->lsa_pattern);
1833                 if (rc) {
1834                         fprintf(stderr, "Set stripe pattern %#llx failed. %s\n",
1835                                 lsa->lsa_pattern, strerror(errno));
1836                         return rc;
1837                 }
1838                 /* Data-on-MDT component has always single stripe up to end */
1839                 lsa->lsa_stripe_size = lsa->lsa_comp_end;
1840         }
1841
1842         rc = llapi_layout_stripe_size_set(layout, lsa->lsa_stripe_size);
1843         if (rc) {
1844                 fprintf(stderr, "Set stripe size %llu failed: %s\n",
1845                         lsa->lsa_stripe_size, strerror(errno));
1846                 return rc;
1847         }
1848
1849         rc = llapi_layout_stripe_count_set(layout, lsa->lsa_stripe_count);
1850         if (rc) {
1851                 fprintf(stderr, "Set stripe count %lld failed: %s\n",
1852                         lsa->lsa_stripe_count, strerror(errno));
1853                 return rc;
1854         }
1855
1856         rc = llapi_layout_comp_flags_set(layout, lsa->lsa_comp_flags);
1857         if (rc) {
1858                 fprintf(stderr, "Set flags 0x%x failed: %s\n",
1859                         lsa->lsa_comp_flags, strerror(errno));
1860                 return rc;
1861         }
1862
1863         if (lsa->lsa_pool_name != NULL) {
1864                 rc = llapi_layout_pool_name_set(layout, lsa->lsa_pool_name);
1865                 if (rc) {
1866                         fprintf(stderr, "Set pool name: %s failed. %s\n",
1867                                 lsa->lsa_pool_name, strerror(errno));
1868                         return rc;
1869                 }
1870         } else {
1871                 rc = llapi_layout_pool_name_set(layout, "");
1872                 if (rc) {
1873                         fprintf(stderr, "Clear pool name failed: %s\n",
1874                                 strerror(errno));
1875                         return rc;
1876                 }
1877         }
1878
1879         if (lsa->lsa_nr_tgts > 0) {
1880                 if (lsa->lsa_stripe_count > 0 &&
1881                     lsa->lsa_stripe_count != LLAPI_LAYOUT_DEFAULT &&
1882                     lsa->lsa_stripe_count != LLAPI_LAYOUT_WIDE &&
1883                     lsa->lsa_nr_tgts != lsa->lsa_stripe_count) {
1884                         fprintf(stderr, "stripe_count(%lld) != nr_osts(%d)\n",
1885                                 lsa->lsa_stripe_count, lsa->lsa_nr_tgts);
1886                         return -EINVAL;
1887                 }
1888                 for (i = 0; i < lsa->lsa_nr_tgts; i++) {
1889                         rc = llapi_layout_ost_index_set(layout, i,
1890                                                         lsa->lsa_tgts[i]);
1891                         if (rc)
1892                                 break;
1893                 }
1894         } else if (lsa->lsa_stripe_off != LLAPI_LAYOUT_DEFAULT) {
1895                 rc = llapi_layout_ost_index_set(layout, 0, lsa->lsa_stripe_off);
1896         }
1897         if (rc) {
1898                 fprintf(stderr, "Set ost index %d failed. %s\n",
1899                         i, strerror(errno));
1900                 return rc;
1901         }
1902
1903         return 0;
1904 }
1905
1906 /* In 'lfs setstripe --component-add' mode, we need to fetch the extent
1907  * end of the last component in the existing file, and adjust the
1908  * first extent start of the components to be added accordingly. */
1909 static int adjust_first_extent(char *fname, struct llapi_layout *layout)
1910 {
1911         struct llapi_layout *head;
1912         uint64_t start, end, stripe_size, prev_end = 0;
1913         int rc;
1914
1915         if (layout == NULL) {
1916                 fprintf(stderr,
1917                         "%s setstripe: layout must be specified\n",
1918                         progname);
1919                 return -EINVAL;
1920         }
1921
1922         errno = 0;
1923         head = llapi_layout_get_by_path(fname, 0);
1924         if (head == NULL) {
1925                 fprintf(stderr,
1926                         "%s setstripe: cannot read layout from '%s': %s\n",
1927                         progname, fname, strerror(errno));
1928                 return -EINVAL;
1929         } else if (errno == ENODATA) {
1930                 /* file without LOVEA, this component-add will be turned
1931                  * into a component-create. */
1932                 llapi_layout_free(head);
1933                 return -ENODATA;
1934         } else if (!llapi_layout_is_composite(head)) {
1935                 fprintf(stderr, "%s setstripe: '%s' not a composite file\n",
1936                         progname, fname);
1937                 llapi_layout_free(head);
1938                 return -EINVAL;
1939         }
1940
1941         rc = llapi_layout_comp_extent_get(head, &start, &prev_end);
1942         if (rc) {
1943                 fprintf(stderr, "%s setstripe: cannot get prev extent: %s\n",
1944                         progname, strerror(errno));
1945                 llapi_layout_free(head);
1946                 return rc;
1947         }
1948
1949         llapi_layout_free(head);
1950
1951         /* Make sure we use the first component of the layout to be added. */
1952         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1953         if (rc < 0) {
1954                 fprintf(stderr,
1955                         "%s setstripe: cannot move component cursor: %s\n",
1956                         progname, strerror(errno));
1957                 return rc;
1958         }
1959
1960         rc = llapi_layout_comp_extent_get(layout, &start, &end);
1961         if (rc) {
1962                 fprintf(stderr, "%s setstripe: cannot get extent: %s\n",
1963                         progname, strerror(errno));
1964                 return rc;
1965         }
1966
1967         if (start > prev_end || end <= prev_end) {
1968                 fprintf(stderr,
1969                         "%s setstripe: first extent [%lu, %lu) not adjacent with extent end %lu\n",
1970                         progname, start, end, prev_end);
1971                 return -EINVAL;
1972         }
1973
1974         rc = llapi_layout_stripe_size_get(layout, &stripe_size);
1975         if (rc) {
1976                 fprintf(stderr, "%s setstripe: cannot get stripe size: %s\n",
1977                         progname, strerror(errno));
1978                 return rc;
1979         }
1980
1981         if (stripe_size != LLAPI_LAYOUT_DEFAULT &&
1982             (prev_end & (stripe_size - 1))) {
1983                 fprintf(stderr,
1984                         "%s setstripe: stripe size %lu not aligned with %lu\n",
1985                         progname, stripe_size, prev_end);
1986                 return -EINVAL;
1987         }
1988
1989         rc = llapi_layout_comp_extent_set(layout, prev_end, end);
1990         if (rc) {
1991                 fprintf(stderr,
1992                         "%s setstripe: cannot set component extent [%lu, %lu): %s\n",
1993                         progname, prev_end, end, strerror(errno));
1994                 return rc;
1995         }
1996
1997         return 0;
1998 }
1999
2000 static inline bool arg_is_eof(char *arg)
2001 {
2002         return !strncmp(arg, "-1", strlen("-1")) ||
2003                !strncmp(arg, "EOF", strlen("EOF")) ||
2004                !strncmp(arg, "eof", strlen("eof"));
2005 }
2006
2007 /**
2008  * lfs_mirror_alloc() - Allocate a mirror argument structure.
2009  *
2010  * Return: Valid mirror_args pointer on success and
2011  *         NULL if memory allocation fails.
2012  */
2013 static struct mirror_args *lfs_mirror_alloc(void)
2014 {
2015         struct mirror_args *mirror = NULL;
2016
2017         while (1) {
2018                 mirror = calloc(1, sizeof(*mirror));
2019                 if (mirror != NULL)
2020                         break;
2021
2022                 sleep(1);
2023         }
2024
2025         return mirror;
2026 }
2027
2028 /**
2029  * lfs_mirror_free() - Free memory allocated for a mirror argument
2030  *                     structure.
2031  * @mirror: Previously allocated mirror argument structure by
2032  *          lfs_mirror_alloc().
2033  *
2034  * Free memory allocated for @mirror.
2035  *
2036  * Return: void.
2037  */
2038 static void lfs_mirror_free(struct mirror_args *mirror)
2039 {
2040         if (mirror->m_layout != NULL)
2041                 llapi_layout_free(mirror->m_layout);
2042         free(mirror);
2043 }
2044
2045 /**
2046  * lfs_mirror_list_free() - Free memory allocated for a mirror list.
2047  * @mirror_list: Previously allocated mirror list.
2048  *
2049  * Free memory allocated for @mirror_list.
2050  *
2051  * Return: void.
2052  */
2053 static void lfs_mirror_list_free(struct mirror_args *mirror_list)
2054 {
2055         struct mirror_args *next_mirror = NULL;
2056
2057         while (mirror_list != NULL) {
2058                 next_mirror = mirror_list->m_next;
2059                 lfs_mirror_free(mirror_list);
2060                 mirror_list = next_mirror;
2061         }
2062 }
2063
2064 enum {
2065         LFS_POOL_OPT = 3,
2066         LFS_COMP_COUNT_OPT,
2067         LFS_COMP_START_OPT,
2068         LFS_COMP_FLAGS_OPT,
2069         LFS_COMP_DEL_OPT,
2070         LFS_COMP_SET_OPT,
2071         LFS_COMP_ADD_OPT,
2072         LFS_COMP_USE_PARENT_OPT,
2073         LFS_COMP_NO_VERIFY_OPT,
2074         LFS_PROJID_OPT,
2075         LFS_MIRROR_FLAGS_OPT,
2076 };
2077
2078 /* functions */
2079 static int lfs_setstripe0(int argc, char **argv, enum setstripe_origin opc)
2080 {
2081         struct lfs_setstripe_args        lsa;
2082         struct llapi_stripe_param       *param = NULL;
2083         struct find_param                migrate_mdt_param = {
2084                 .fp_max_depth = -1,
2085                 .fp_mdt_index = -1,
2086         };
2087         char                            *fname;
2088         int                              result;
2089         int                              result2 = 0;
2090         char                            *end;
2091         int                              c;
2092         int                              delete = 0;
2093         char                            *mdt_idx_arg = NULL;
2094         unsigned long long               size_units = 1;
2095         bool                             migrate_mode = false;
2096         bool                             migration_block = false;
2097         __u64                            migration_flags = 0;
2098         __u32                            osts[LOV_MAX_STRIPE_COUNT] = { 0 };
2099         int                              comp_del = 0, comp_set = 0;
2100         int                              comp_add = 0;
2101         __u32                            comp_id = 0;
2102         struct llapi_layout             *layout = NULL;
2103         struct llapi_layout             **lpp = &layout;
2104         bool                             mirror_mode = false;
2105         bool                             has_m_file = false;
2106         __u32                            mirror_count = 0;
2107         enum mirror_flags                mirror_flags = 0;
2108         struct mirror_args              *mirror_list = NULL;
2109         struct mirror_args              *new_mirror = NULL;
2110         struct mirror_args              *last_mirror = NULL;
2111         char                             cmd[PATH_MAX];
2112
2113         struct option long_opts[] = {
2114                 /* --block is only valid in migrate mode */
2115         { .val = 'b',   .name = "block",        .has_arg = no_argument},
2116         { .val = LFS_COMP_ADD_OPT,
2117                         .name = "comp-add",     .has_arg = no_argument},
2118         { .val = LFS_COMP_ADD_OPT,
2119                         .name = "component-add",
2120                                                 .has_arg = no_argument},
2121         { .val = LFS_COMP_DEL_OPT,
2122                         .name = "comp-del",     .has_arg = no_argument},
2123         { .val = LFS_COMP_DEL_OPT,
2124                         .name = "component-del",
2125                                                 .has_arg = no_argument},
2126         { .val = LFS_COMP_FLAGS_OPT,
2127                         .name = "comp-flags",   .has_arg = required_argument},
2128         { .val = LFS_COMP_FLAGS_OPT,
2129                         .name = "component-flags",
2130                                                 .has_arg = required_argument},
2131         { .val = LFS_COMP_SET_OPT,
2132                         .name = "comp-set",     .has_arg = no_argument},
2133         { .val = LFS_COMP_SET_OPT,
2134                         .name = "component-set",
2135                                                 .has_arg = no_argument},
2136         { .val = LFS_COMP_USE_PARENT_OPT,
2137                         .name = "parent",       .has_arg = no_argument},
2138         { .val = LFS_COMP_NO_VERIFY_OPT,
2139                         .name = "no-verify",    .has_arg = no_argument},
2140         { .val = LFS_MIRROR_FLAGS_OPT,
2141                         .name = "flags",        .has_arg = required_argument},
2142         { .val = 'c',   .name = "stripe-count", .has_arg = required_argument},
2143         { .val = 'c',   .name = "stripe_count", .has_arg = required_argument},
2144         { .val = 'd',   .name = "delete",       .has_arg = no_argument},
2145         { .val = 'E',   .name = "comp-end",     .has_arg = required_argument},
2146         { .val = 'E',   .name = "component-end",
2147                                                 .has_arg = required_argument},
2148         { .val = 'f',   .name = "file",         .has_arg = required_argument },
2149         /* dirstripe {"mdt-hash",     required_argument, 0, 'H'}, */
2150         { .val = 'i',   .name = "stripe-index", .has_arg = required_argument},
2151         { .val = 'i',   .name = "stripe_index", .has_arg = required_argument},
2152         { .val = 'I',   .name = "comp-id",      .has_arg = required_argument},
2153         { .val = 'I',   .name = "component-id", .has_arg = required_argument},
2154         { .val = 'L',   .name = "layout",       .has_arg = required_argument },
2155         { .val = 'm',   .name = "mdt",          .has_arg = required_argument},
2156         { .val = 'm',   .name = "mdt-index",    .has_arg = required_argument},
2157         { .val = 'm',   .name = "mdt_index",    .has_arg = required_argument},
2158         { .val = 'N',   .name = "mirror-count", .has_arg = optional_argument},
2159         /* --non-block is only valid in migrate mode */
2160         { .val = 'n',   .name = "non-block",    .has_arg = no_argument},
2161         { .val = 'o',   .name = "ost",          .has_arg = required_argument},
2162 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
2163         { .val = 'o',   .name = "ost-list",     .has_arg = required_argument },
2164         { .val = 'o',   .name = "ost_list",     .has_arg = required_argument },
2165 #endif
2166         { .val = 'p',   .name = "pool",         .has_arg = required_argument },
2167         { .val = 'S',   .name = "stripe-size",  .has_arg = required_argument },
2168         { .val = 'S',   .name = "stripe_size",  .has_arg = required_argument },
2169         /* dirstripe {"mdt-count",    required_argument, 0, 'T'}, */
2170         /* --verbose is only valid in migrate mode */
2171         { .val = 'v',   .name = "verbose",      .has_arg = no_argument },
2172         { .name = NULL } };
2173
2174         setstripe_args_init(&lsa);
2175
2176         migrate_mode = (opc == SO_MIGRATE);
2177         mirror_mode = (opc == SO_MIRROR_CREATE || opc == SO_MIRROR_EXTEND);
2178
2179         snprintf(cmd, sizeof(cmd), "%s %s", progname, argv[0]);
2180         progname = cmd;
2181         while ((c = getopt_long(argc, argv, "bc:dE:f:i:I:m:N::no:p:L:s:S:v",
2182                                 long_opts, NULL)) >= 0) {
2183                 switch (c) {
2184                 case 0:
2185                         /* Long options. */
2186                         break;
2187                 case LFS_COMP_ADD_OPT:
2188                         comp_add = 1;
2189                         break;
2190                 case LFS_COMP_DEL_OPT:
2191                         comp_del = 1;
2192                         break;
2193                 case LFS_COMP_FLAGS_OPT:
2194                         result = comp_str2flags(optarg, &lsa.lsa_comp_flags,
2195                                                 &lsa.lsa_comp_neg_flags);
2196                         if (result != 0)
2197                                 goto usage_error;
2198                         if (mirror_mode && lsa.lsa_comp_neg_flags) {
2199                                 fprintf(stderr, "%s: inverted flags are not supported\n",
2200                                         progname);
2201                                 goto usage_error;
2202                         }
2203                         if (lsa.lsa_comp_neg_flags & LCME_FL_STALE) {
2204                                 fprintf(stderr,
2205                                         "%s: cannot clear 'stale' flags from component. Please use lfs-mirror-resync(1) instead\n",
2206                                         progname);
2207                                 result = -EINVAL;
2208                                 goto error;
2209                         }
2210
2211                         break;
2212                 case LFS_COMP_SET_OPT:
2213                         comp_set = 1;
2214                         break;
2215                 case LFS_COMP_USE_PARENT_OPT:
2216                         if (!mirror_mode) {
2217                                 fprintf(stderr, "error: %s: --parent must be "
2218                                         "specified with --mirror-count|-N "
2219                                         "option\n", progname);
2220                                 goto usage_error;
2221                         }
2222                         setstripe_args_init(&lsa);
2223                         break;
2224                 case LFS_COMP_NO_VERIFY_OPT:
2225                         mirror_flags |= NO_VERIFY;
2226                         break;
2227                 case LFS_MIRROR_FLAGS_OPT: {
2228                         __u32 flags;
2229
2230                         if (!mirror_mode || !last_mirror) {
2231                                 fprintf(stderr, "error: %s: --flags must be specified with --mirror-count|-N option\n",
2232                                         progname);
2233                                 goto usage_error;
2234                         }
2235
2236                         result = comp_str2flags(optarg, &last_mirror->m_flags,
2237                                                 &flags);
2238                         if (result != 0)
2239                                 goto usage_error;
2240
2241                         if (flags) {
2242                                 fprintf(stderr, "%s: inverted flags are not supported\n",
2243                                         progname);
2244                                 result = -EINVAL;
2245                                 goto usage_error;
2246                         }
2247                         if (last_mirror->m_flags & ~LCME_USER_FLAGS) {
2248                                 fprintf(stderr,
2249                                         "%s: unsupported mirror flags: %s\n",
2250                                         progname, optarg);
2251                                 result = -EINVAL;
2252                                 goto error;
2253                         }
2254                         break;
2255                 }
2256                 case 'b':
2257                         if (!migrate_mode) {
2258                                 fprintf(stderr,
2259                                         "%s %s: -b|--block valid only for migrate command\n",
2260                                         progname, argv[0]);
2261                                 goto usage_error;
2262                         }
2263                         migration_block = true;
2264                         break;
2265                 case 'c':
2266                         lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
2267                         if (*end != '\0') {
2268                                 fprintf(stderr,
2269                                         "%s %s: invalid stripe count '%s'\n",
2270                                         progname, argv[0], optarg);
2271                                 goto usage_error;
2272                         }
2273
2274                         if (lsa.lsa_stripe_count == -1)
2275                                 lsa.lsa_stripe_count = LLAPI_LAYOUT_WIDE;
2276                         break;
2277                 case 'd':
2278                         /* delete the default striping pattern */
2279                         delete = 1;
2280                         break;
2281                 case 'E':
2282                         if (lsa.lsa_comp_end != 0) {
2283                                 result = comp_args_to_layout(lpp, &lsa);
2284                                 if (result) {
2285                                         fprintf(stderr,
2286                                                 "%s %s: invalid layout\n",
2287                                                 progname, argv[0]);
2288                                         goto usage_error;
2289                                 }
2290
2291                                 setstripe_args_init_inherit(&lsa);
2292                         }
2293
2294                         if (arg_is_eof(optarg)) {
2295                                 lsa.lsa_comp_end = LUSTRE_EOF;
2296                         } else {
2297                                 result = llapi_parse_size(optarg,
2298                                                         &lsa.lsa_comp_end,
2299                                                         &size_units, 0);
2300                                 if (result) {
2301                                         fprintf(stderr,
2302                                                 "%s %s: invalid component end '%s'\n",
2303                                                 progname, argv[0], optarg);
2304                                         goto usage_error;
2305                                 }
2306                         }
2307                         break;
2308                 case 'i':
2309                         lsa.lsa_stripe_off = strtol(optarg, &end, 0);
2310                         if (*end != '\0') {
2311                                 fprintf(stderr,
2312                                         "%s %s: invalid stripe offset '%s'\n",
2313                                         progname, argv[0], optarg);
2314                                 goto usage_error;
2315                         }
2316                         if (lsa.lsa_stripe_off == -1)
2317                                 lsa.lsa_stripe_off = LLAPI_LAYOUT_DEFAULT;
2318                         break;
2319                 case 'I':
2320                         comp_id = strtoul(optarg, &end, 0);
2321                         if (*end != '\0' || comp_id == 0 ||
2322                             comp_id > LCME_ID_MAX) {
2323                                 fprintf(stderr,
2324                                         "%s %s: invalid component ID '%s'\n",
2325                                         progname, argv[0], optarg);
2326                                 goto usage_error;
2327                         }
2328                         break;
2329                 case 'f':
2330                         if (opc != SO_MIRROR_EXTEND) {
2331                                 fprintf(stderr,
2332                                         "error: %s: invalid option: %s\n",
2333                                         progname, argv[optopt + 1]);
2334                                 goto usage_error;
2335                         }
2336                         if (last_mirror == NULL) {
2337                                 fprintf(stderr, "error: %s: '-N' must exist "
2338                                         "in front of '%s'\n",
2339                                         progname, argv[optopt + 1]);
2340                                 goto usage_error;
2341                         }
2342
2343                         last_mirror->m_file = optarg;
2344                         last_mirror->m_count = 1;
2345                         has_m_file = true;
2346                         break;
2347                 case 'L':
2348                         if (strcmp(argv[optind - 1], "mdt") == 0) {
2349                                 /* Can be only the first component */
2350                                 if (layout != NULL) {
2351                                         result = -EINVAL;
2352                                         fprintf(stderr, "error: 'mdt' layout "
2353                                                 "can be only the first one\n");
2354                                         goto error;
2355                                 }
2356                                 if (lsa.lsa_comp_end > (1ULL << 30)) { /* 1Gb */
2357                                         result = -EFBIG;
2358                                         fprintf(stderr, "error: 'mdt' layout "
2359                                                 "size is too big\n");
2360                                         goto error;
2361                                 }
2362                                 lsa.lsa_pattern = LLAPI_LAYOUT_MDT;
2363                         } else if (strcmp(argv[optind - 1], "raid0") != 0) {
2364                                 result = -EINVAL;
2365                                 fprintf(stderr, "error: layout '%s' is "
2366                                         "unknown, supported layouts are: "
2367                                         "'mdt', 'raid0'\n", argv[optind]);
2368                                 goto error;
2369                         }
2370                         break;
2371                 case 'm':
2372                         if (!migrate_mode) {
2373                                 fprintf(stderr,
2374                                         "%s %s: -m|--mdt-index valid only for migrate command\n",
2375                                         progname, argv[0]);
2376                                 goto usage_error;
2377                         }
2378                         mdt_idx_arg = optarg;
2379                         break;
2380                 case 'n':
2381                         if (!migrate_mode) {
2382                                 fprintf(stderr,
2383                                         "%s %s: -n|--non-block valid only for migrate command\n",
2384                                         progname, argv[0]);
2385                                 goto usage_error;
2386                         }
2387                         migration_flags |= MIGRATION_NONBLOCK;
2388                         break;
2389                 case 'N':
2390                         if (opc == SO_SETSTRIPE) {
2391                                 opc = SO_MIRROR_CREATE;
2392                                 mirror_mode = true;
2393                         }
2394                         mirror_count = 1;
2395                         if (optarg != NULL) {
2396                                 mirror_count = strtoul(optarg, &end, 0);
2397                                 if (*end != '\0' || mirror_count == 0) {
2398                                         fprintf(stderr,
2399                                                 "error: %s: bad mirror count: %s\n",
2400                                                 progname, optarg);
2401                                         result = -EINVAL;
2402                                         goto error;
2403                                 }
2404                         }
2405
2406                         new_mirror = lfs_mirror_alloc();
2407                         new_mirror->m_count = mirror_count;
2408
2409                         if (mirror_list == NULL)
2410                                 mirror_list = new_mirror;
2411
2412                         if (last_mirror != NULL) {
2413                                 /* wrap up last mirror */
2414                                 if (lsa.lsa_comp_end == 0)
2415                                         lsa.lsa_comp_end = LUSTRE_EOF;
2416
2417                                 result = comp_args_to_layout(lpp, &lsa);
2418                                 if (result) {
2419                                         lfs_mirror_free(new_mirror);
2420                                         goto error;
2421                                 }
2422
2423                                 setstripe_args_init_inherit(&lsa);
2424
2425                                 last_mirror->m_next = new_mirror;
2426                         }
2427
2428                         last_mirror = new_mirror;
2429                         lpp = &last_mirror->m_layout;
2430                         break;
2431                 case 'o':
2432                         lsa.lsa_nr_tgts = parse_targets(osts,
2433                                                 sizeof(osts) / sizeof(__u32),
2434                                                 lsa.lsa_nr_tgts, optarg);
2435                         if (lsa.lsa_nr_tgts < 0) {
2436                                 fprintf(stderr,
2437                                         "%s %s: invalid OST target(s) '%s'\n",
2438                                         progname, argv[0], optarg);
2439                                 goto usage_error;
2440                         }
2441
2442                         lsa.lsa_tgts = osts;
2443                         if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
2444                                 lsa.lsa_stripe_off = osts[0];
2445                         break;
2446                 case 'p':
2447                         if (optarg == NULL)
2448                                 goto usage_error;
2449                         lsa.lsa_pool_name = optarg;
2450                         break;
2451                 case 'S':
2452                         result = llapi_parse_size(optarg, &lsa.lsa_stripe_size,
2453                                                   &size_units, 0);
2454                         if (result) {
2455                                 fprintf(stderr,
2456                                         "%s %s: invalid stripe size '%s'\n",
2457                                         progname, argv[0], optarg);
2458                                 goto usage_error;
2459                         }
2460                         break;
2461                 case 'v':
2462                         if (!migrate_mode) {
2463                                 fprintf(stderr,
2464                                         "%s %s: -v|--verbose valid only for migrate command\n",
2465                                         progname, argv[0]);
2466                                 goto usage_error;
2467                         }
2468                         migrate_mdt_param.fp_verbose = VERBOSE_DETAIL;
2469                         break;
2470                 default:
2471                         fprintf(stderr, "%s %s: unrecognized option '%s'\n",
2472                                 progname, argv[0], argv[optind - 1]);
2473                         goto usage_error;
2474                 }
2475         }
2476
2477         fname = argv[optind];
2478
2479         if (optind == argc) {
2480                 fprintf(stderr, "%s %s: FILE must be specified\n",
2481                         progname, argv[0]);
2482                 goto usage_error;
2483         }
2484
2485         if (mirror_mode && mirror_count == 0) {
2486                 fprintf(stderr,
2487                         "error: %s: --mirror-count|-N option is required\n",
2488                         progname);
2489                 result = -EINVAL;
2490                 goto error;
2491         }
2492
2493         if (mirror_mode) {
2494                 if (lsa.lsa_comp_end == 0)
2495                         lsa.lsa_comp_end = LUSTRE_EOF;
2496         }
2497
2498         if (lsa.lsa_comp_end != 0) {
2499                 result = comp_args_to_layout(lpp, &lsa);
2500                 if (result)
2501                         goto error;
2502         }
2503
2504         if (mirror_flags & NO_VERIFY) {
2505                 if (opc != SO_MIRROR_EXTEND) {
2506                         fprintf(stderr,
2507                                 "error: %s: --no-verify is valid only for lfs mirror extend command\n",
2508                                 progname);
2509                         result = -EINVAL;
2510                         goto error;
2511                 } else if (!has_m_file) {
2512                         fprintf(stderr,
2513                                 "error: %s: --no-verify must be specified with -f <victim_file> option\n",
2514                                 progname);
2515                         result = -EINVAL;
2516                         goto error;
2517                 }
2518         }
2519
2520         /* Only LCME_FL_INIT flags is used in PFL, and it shouldn't be
2521          * altered by user space tool, so we don't need to support the
2522          * --component-set for this moment. */
2523         if (comp_set && !comp_id) {
2524                 fprintf(stderr, "%s %s: --component-set doesn't have component-id set\n",
2525                         progname, argv[0]);
2526                 goto usage_error;
2527         }
2528
2529         if ((delete + comp_set + comp_del + comp_add) > 1) {
2530                 fprintf(stderr,
2531                         "%s %s: options --component-set, --component-del, --component-add and -d are mutually exclusive\n",
2532                         progname, argv[0]);
2533                 goto usage_error;
2534         }
2535
2536         if (delete && (setstripe_args_specified(&lsa) || comp_id != 0 ||
2537                        lsa.lsa_comp_flags != 0 || layout != NULL)) {
2538                 fprintf(stderr,
2539                         "%s %s: option -d is mutually exclusive with -s, -c, -o, -p, -I, -F and -E options\n",
2540                         progname, argv[0]);
2541                 goto usage_error;
2542         }
2543
2544         if ((comp_set || comp_del) &&
2545             (setstripe_args_specified(&lsa) || layout != NULL)) {
2546                 fprintf(stderr,
2547                         "%s %s: options --component-del and --component-set are mutually exclusive when used with -c, -E, -o, -p, or -s\n",
2548                         progname, argv[0]);
2549                 goto usage_error;
2550         }
2551
2552         if (comp_del && comp_id != 0 && lsa.lsa_comp_flags != 0) {
2553                 fprintf(stderr,
2554                         "%s %s: options -I and -F are mutually exclusive when used with --component-del\n",
2555                         progname, argv[0]);
2556                 goto usage_error;
2557         }
2558
2559         if (comp_add || comp_del) {
2560                 struct stat st;
2561
2562                 result = lstat(fname, &st);
2563                 if (result == 0 && S_ISDIR(st.st_mode)) {
2564                         fprintf(stderr,
2565                                 "%s setstripe: cannot use --component-add or --component-del for directory\n",
2566                                 progname);
2567                         goto usage_error;
2568                 }
2569
2570                 if (mirror_mode) {
2571                         fprintf(stderr, "error: %s: can't use --component-add "
2572                                 "or --component-del for mirror operation\n",
2573                                 progname);
2574                         goto usage_error;
2575                 }
2576         }
2577
2578         if (comp_add) {
2579                 if (layout == NULL) {
2580                         fprintf(stderr,
2581                                 "%s %s: option -E must be specified with --component-add\n",
2582                                 progname, argv[0]);
2583                         goto usage_error;
2584                 }
2585
2586                 result = adjust_first_extent(fname, layout);
2587                 if (result == -ENODATA)
2588                         comp_add = 0;
2589                 else if (result != 0)
2590                         goto error;
2591         }
2592
2593         if (mdt_idx_arg != NULL && optind > 3) {
2594                 fprintf(stderr,
2595                         "%s %s: option -m cannot be used with other options\n",
2596                         progname, argv[0]);
2597                 goto usage_error;
2598         }
2599
2600         if ((migration_flags & MIGRATION_NONBLOCK) && migration_block) {
2601                 fprintf(stderr,
2602                         "%s %s: options --non-block and --block are mutually exclusive\n",
2603                         progname, argv[0]);
2604                 goto usage_error;
2605         }
2606
2607         if (!comp_del && !comp_set && comp_id != 0) {
2608                 fprintf(stderr,
2609                         "%s %s: option -I can only be used with --component-del\n",
2610                         progname, argv[0]);
2611                 goto usage_error;
2612         }
2613
2614         if (mdt_idx_arg != NULL) {
2615                 /* initialize migrate mdt parameters */
2616                 migrate_mdt_param.fp_mdt_index = strtoul(mdt_idx_arg, &end, 0);
2617                 if (*end != '\0') {
2618                         fprintf(stderr, "%s %s: invalid MDT index '%s'\n",
2619                                 progname, argv[0], mdt_idx_arg);
2620                         goto usage_error;
2621                 }
2622                 migrate_mdt_param.fp_migrate = 1;
2623         } else if (layout == NULL) {
2624                 /* initialize stripe parameters */
2625                 param = calloc(1, offsetof(typeof(*param),
2626                                lsp_osts[lsa.lsa_nr_tgts]));
2627                 if (param == NULL) {
2628                         fprintf(stderr,
2629                                 "%s %s: cannot allocate memory for parameters: %s\n",
2630                                 progname, argv[0], strerror(ENOMEM));
2631                         result = -ENOMEM;
2632                         goto error;
2633                 }
2634
2635                 if (lsa.lsa_stripe_size != LLAPI_LAYOUT_DEFAULT)
2636                         param->lsp_stripe_size = lsa.lsa_stripe_size;
2637                 if (lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT) {
2638                         if (lsa.lsa_stripe_count == LLAPI_LAYOUT_WIDE)
2639                                 param->lsp_stripe_count = -1;
2640                         else
2641                                 param->lsp_stripe_count = lsa.lsa_stripe_count;
2642                 }
2643                 if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
2644                         param->lsp_stripe_offset = -1;
2645                 else
2646                         param->lsp_stripe_offset = lsa.lsa_stripe_off;
2647                 param->lsp_pool = lsa.lsa_pool_name;
2648                 param->lsp_is_specific = false;
2649                 if (lsa.lsa_nr_tgts > 0) {
2650                         if (lsa.lsa_stripe_count > 0 &&
2651                             lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT &&
2652                             lsa.lsa_stripe_count != LLAPI_LAYOUT_WIDE &&
2653                             lsa.lsa_nr_tgts != lsa.lsa_stripe_count) {
2654                                 fprintf(stderr, "error: %s: stripe count %lld "
2655                                         "doesn't match the number of OSTs: %d\n"
2656                                         , argv[0], lsa.lsa_stripe_count,
2657                                         lsa.lsa_nr_tgts);
2658                                 free(param);
2659                                 goto usage_error;
2660                         }
2661
2662                         param->lsp_is_specific = true;
2663                         param->lsp_stripe_count = lsa.lsa_nr_tgts;
2664                         memcpy(param->lsp_osts, osts,
2665                                sizeof(*osts) * lsa.lsa_nr_tgts);
2666                 }
2667         }
2668
2669         for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) {
2670                 if (mdt_idx_arg != NULL) {
2671                         result = llapi_migrate_mdt(fname, &migrate_mdt_param);
2672                 } else if (migrate_mode) {
2673                         result = lfs_migrate(fname, migration_flags, param,
2674                                              layout);
2675                 } else if (comp_set != 0) {
2676                         result = lfs_component_set(fname, comp_id,
2677                                                    lsa.lsa_comp_flags,
2678                                                    lsa.lsa_comp_neg_flags);
2679                 } else if (comp_del != 0) {
2680                         result = lfs_component_del(fname, comp_id,
2681                                                    lsa.lsa_comp_flags,
2682                                                    lsa.lsa_comp_neg_flags);
2683                 } else if (comp_add != 0) {
2684                         result = lfs_component_add(fname, layout);
2685                 } else if (opc == SO_MIRROR_CREATE) {
2686                         result = mirror_create(fname, mirror_list);
2687                 } else if (opc == SO_MIRROR_EXTEND) {
2688                         result = mirror_extend(fname, mirror_list,
2689                                                mirror_flags);
2690                 } else if (layout != NULL) {
2691                         result = lfs_component_create(fname, O_CREAT | O_WRONLY,
2692                                                       0644, layout);
2693                         if (result >= 0) {
2694                                 close(result);
2695                                 result = 0;
2696                         }
2697                 } else {
2698                         result = llapi_file_open_param(fname,
2699                                                        O_CREAT | O_WRONLY,
2700                                                        0644, param);
2701                         if (result >= 0) {
2702                                 close(result);
2703                                 result = 0;
2704                         }
2705                 }
2706                 if (result) {
2707                         /* Save the first error encountered. */
2708                         if (result2 == 0)
2709                                 result2 = result;
2710                         continue;
2711                 }
2712         }
2713
2714         free(param);
2715         llapi_layout_free(layout);
2716         lfs_mirror_list_free(mirror_list);
2717         return result2;
2718 usage_error:
2719         result = CMD_HELP;
2720 error:
2721         llapi_layout_free(layout);
2722         lfs_mirror_list_free(mirror_list);
2723         return result;
2724 }
2725
2726 static int lfs_poollist(int argc, char **argv)
2727 {
2728         if (argc != 2)
2729                 return CMD_HELP;
2730
2731         return llapi_poollist(argv[1]);
2732 }
2733
2734 static int set_time(time_t *time, time_t *set, char *str)
2735 {
2736         time_t t;
2737         int res = 0;
2738
2739         if (str[0] == '+')
2740                 res = 1;
2741         else if (str[0] == '-')
2742                 res = -1;
2743
2744         if (res)
2745                 str++;
2746
2747         t = strtol(str, NULL, 0);
2748         if (*time < t * 24 * 60 * 60) {
2749                 if (res)
2750                         str--;
2751                 fprintf(stderr, "Wrong time '%s' is specified.\n", str);
2752                 return INT_MAX;
2753         }
2754
2755         *set = *time - t * 24 * 60 * 60;
2756         return res;
2757 }
2758 static int name2uid(unsigned int *id, const char *name)
2759 {
2760         struct passwd *passwd;
2761
2762         passwd = getpwnam(name);
2763         if (passwd == NULL)
2764                 return -ENOENT;
2765         *id = passwd->pw_uid;
2766
2767         return 0;
2768 }
2769
2770 static int name2gid(unsigned int *id, const char *name)
2771 {
2772         struct group *group;
2773
2774         group = getgrnam(name);
2775         if (group == NULL)
2776                 return -ENOENT;
2777         *id = group->gr_gid;
2778
2779         return 0;
2780 }
2781
2782 static inline int name2projid(unsigned int *id, const char *name)
2783 {
2784         return -ENOTSUP;
2785 }
2786
2787 static int uid2name(char **name, unsigned int id)
2788 {
2789         struct passwd *passwd;
2790
2791         passwd = getpwuid(id);
2792         if (passwd == NULL)
2793                 return -ENOENT;
2794         *name = passwd->pw_name;
2795
2796         return 0;
2797 }
2798
2799 static inline int gid2name(char **name, unsigned int id)
2800 {
2801         struct group *group;
2802
2803         group = getgrgid(id);
2804         if (group == NULL)
2805                 return -ENOENT;
2806         *name = group->gr_name;
2807
2808         return 0;
2809 }
2810
2811 static int name2layout(__u32 *layout, char *name)
2812 {
2813         char *ptr, *layout_name;
2814
2815         *layout = 0;
2816         for (ptr = name; ; ptr = NULL) {
2817                 layout_name = strtok(ptr, ",");
2818                 if (layout_name == NULL)
2819                         break;
2820                 if (strcmp(layout_name, "released") == 0)
2821                         *layout |= LOV_PATTERN_F_RELEASED;
2822                 else if (strcmp(layout_name, "raid0") == 0)
2823                         *layout |= LOV_PATTERN_RAID0;
2824                 else if (strcmp(layout_name, "mdt") == 0)
2825                         *layout |= LOV_PATTERN_MDT;
2826                 else
2827                         return -1;
2828         }
2829         return 0;
2830 }
2831
2832 static int lfs_find(int argc, char **argv)
2833 {
2834         int c, rc;
2835         int ret = 0;
2836         time_t t;
2837         struct find_param param = {
2838                 .fp_max_depth = -1,
2839                 .fp_quiet = 1,
2840         };
2841         struct option long_opts[] = {
2842         { .val = 'A',   .name = "atime",        .has_arg = required_argument },
2843         { .val = LFS_COMP_COUNT_OPT,
2844                         .name = "comp-count",   .has_arg = required_argument },
2845         { .val = LFS_COMP_COUNT_OPT,
2846                         .name = "component-count",
2847                                                 .has_arg = required_argument },
2848         { .val = LFS_COMP_FLAGS_OPT,
2849                         .name = "comp-flags",   .has_arg = required_argument },
2850         { .val = LFS_COMP_FLAGS_OPT,
2851                         .name = "component-flags",
2852                                                 .has_arg = required_argument },
2853         { .val = LFS_COMP_START_OPT,
2854                         .name = "comp-start",   .has_arg = required_argument },
2855         { .val = LFS_COMP_START_OPT,
2856                         .name = "component-start",
2857                                                 .has_arg = required_argument },
2858         { .val = 'c',   .name = "stripe-count", .has_arg = required_argument },
2859         { .val = 'c',   .name = "stripe_count", .has_arg = required_argument },
2860         { .val = 'C',   .name = "ctime",        .has_arg = required_argument },
2861         { .val = 'D',   .name = "maxdepth",     .has_arg = required_argument },
2862         { .val = 'E',   .name = "comp-end",     .has_arg = required_argument },
2863         { .val = 'E',   .name = "component-end",
2864                                                 .has_arg = required_argument },
2865         { .val = 'g',   .name = "gid",          .has_arg = required_argument },
2866         { .val = 'G',   .name = "group",        .has_arg = required_argument },
2867         { .val = 'H',   .name = "mdt-hash",     .has_arg = required_argument },
2868         { .val = 'i',   .name = "stripe-index", .has_arg = required_argument },
2869         { .val = 'i',   .name = "stripe_index", .has_arg = required_argument },
2870         /*{"component-id", required_argument, 0, 'I'},*/
2871         { .val = 'L',   .name = "layout",       .has_arg = required_argument },
2872         { .val = 'm',   .name = "mdt",          .has_arg = required_argument },
2873         { .val = 'm',   .name = "mdt-index",    .has_arg = required_argument },
2874         { .val = 'm',   .name = "mdt_index",    .has_arg = required_argument },
2875         { .val = 'M',   .name = "mtime",        .has_arg = required_argument },
2876         { .val = 'n',   .name = "name",         .has_arg = required_argument },
2877      /* reserve {"or",           no_argument,     , 0, 'o'}, to match find(1) */
2878         { .val = 'O',   .name = "obd",          .has_arg = required_argument },
2879         { .val = 'O',   .name = "ost",          .has_arg = required_argument },
2880         /* no short option for pool, p/P already used */
2881         { .val = LFS_POOL_OPT,
2882                         .name = "pool",         .has_arg = required_argument },
2883         { .val = 'p',   .name = "print0",       .has_arg = no_argument },
2884         { .val = 'P',   .name = "print",        .has_arg = no_argument },
2885         { .val = LFS_PROJID_OPT,
2886                         .name = "projid",       .has_arg = required_argument },
2887         { .val = 's',   .name = "size",         .has_arg = required_argument },
2888         { .val = 'S',   .name = "stripe-size",  .has_arg = required_argument },
2889         { .val = 'S',   .name = "stripe_size",  .has_arg = required_argument },
2890         { .val = 't',   .name = "type",         .has_arg = required_argument },
2891         { .val = 'T',   .name = "mdt-count",    .has_arg = required_argument },
2892         { .val = 'u',   .name = "uid",          .has_arg = required_argument },
2893         { .val = 'U',   .name = "user",         .has_arg = required_argument },
2894         { .name = NULL } };
2895         int pathstart = -1;
2896         int pathend = -1;
2897         int neg_opt = 0;
2898         time_t *xtime;
2899         int *xsign;
2900         int isoption;
2901         char *endptr;
2902
2903         time(&t);
2904
2905         /* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
2906         while ((c = getopt_long_only(argc, argv,
2907                         "-A:c:C:D:E:g:G:H:i:L:m:M:n:O:Ppqrs:S:t:T:u:U:v",
2908                         long_opts, NULL)) >= 0) {
2909                 xtime = NULL;
2910                 xsign = NULL;
2911                 if (neg_opt)
2912                         --neg_opt;
2913                 /* '!' is part of option */
2914                 /* when getopt_long_only() finds a string which is not
2915                  * an option nor a known option argument it returns 1
2916                  * in that case if we already have found pathstart and pathend
2917                  * (i.e. we have the list of pathnames),
2918                  * the only supported value is "!"
2919                  */
2920                 isoption = (c != 1) || (strcmp(optarg, "!") == 0);
2921                 if (!isoption && pathend != -1) {
2922                         fprintf(stderr, "err: %s: filename|dirname must either "
2923                                         "precede options or follow options\n",
2924                                         argv[0]);
2925                         ret = CMD_HELP;
2926                         goto err;
2927                 }
2928                 if (!isoption && pathstart == -1)
2929                         pathstart = optind - 1;
2930                 if (isoption && pathstart != -1 && pathend == -1)
2931                         pathend = optind - 2;
2932                 switch (c) {
2933                 case 0:
2934                         /* Long options. */
2935                         break;
2936                 case 1:
2937                         /* unknown; opt is "!" or path component,
2938                          * checking done above.
2939                          */
2940                         if (strcmp(optarg, "!") == 0)
2941                                 neg_opt = 2;
2942                         break;
2943                 case 'A':
2944                         xtime = &param.fp_atime;
2945                         xsign = &param.fp_asign;
2946                         param.fp_exclude_atime = !!neg_opt;
2947                         /* no break, this falls through to 'C' for ctime */
2948                 case 'C':
2949                         if (c == 'C') {
2950                                 xtime = &param.fp_ctime;
2951                                 xsign = &param.fp_csign;
2952                                 param.fp_exclude_ctime = !!neg_opt;
2953                         }
2954                         /* no break, this falls through to 'M' for mtime */
2955                 case 'M':
2956                         if (c == 'M') {
2957                                 xtime = &param.fp_mtime;
2958                                 xsign = &param.fp_msign;
2959                                 param.fp_exclude_mtime = !!neg_opt;
2960                         }
2961                         rc = set_time(&t, xtime, optarg);
2962                         if (rc == INT_MAX) {
2963                                 ret = -1;
2964                                 goto err;
2965                         }
2966                         if (rc)
2967                                 *xsign = rc;
2968                         break;
2969                 case LFS_COMP_COUNT_OPT:
2970                         if (optarg[0] == '+') {
2971                                 param.fp_comp_count_sign = -1;
2972                                 optarg++;
2973                         } else if (optarg[0] == '-') {
2974                                 param.fp_comp_count_sign =  1;
2975                                 optarg++;
2976                         }
2977
2978                         param.fp_comp_count = strtoul(optarg, &endptr, 0);
2979                         if (*endptr != '\0') {
2980                                 fprintf(stderr, "error: bad component count "
2981                                         "'%s'\n", optarg);
2982                                 goto err;
2983                         }
2984                         param.fp_check_comp_count = 1;
2985                         param.fp_exclude_comp_count = !!neg_opt;
2986                         break;
2987                 case LFS_COMP_FLAGS_OPT:
2988                         rc = comp_str2flags(optarg, &param.fp_comp_flags,
2989                                             &param.fp_comp_neg_flags);
2990                         if (rc) {
2991                                 fprintf(stderr, "error: bad component flags "
2992                                         "'%s'\n", optarg);
2993                                 goto err;
2994                         }
2995                         param.fp_check_comp_flags = 1;
2996                         if (neg_opt) {
2997                                 __u32 flags = param.fp_comp_neg_flags;
2998                                 param.fp_comp_neg_flags = param.fp_comp_flags;
2999                                 param.fp_comp_flags = flags;
3000                         }
3001                         break;
3002                 case LFS_COMP_START_OPT:
3003                         if (optarg[0] == '+') {
3004                                 param.fp_comp_start_sign = -1;
3005                                 optarg++;
3006                         } else if (optarg[0] == '-') {
3007                                 param.fp_comp_start_sign =  1;
3008                                 optarg++;
3009                         }
3010
3011                         rc = llapi_parse_size(optarg, &param.fp_comp_start,
3012                                               &param.fp_comp_start_units, 0);
3013                         if (rc) {
3014                                 fprintf(stderr, "error: bad component start "
3015                                         "'%s'\n", optarg);
3016                                 goto err;
3017                         }
3018                         param.fp_check_comp_start = 1;
3019                         param.fp_exclude_comp_start = !!neg_opt;
3020                         break;
3021                 case 'c':
3022                         if (optarg[0] == '+') {
3023                                 param.fp_stripe_count_sign = -1;
3024                                 optarg++;
3025                         } else if (optarg[0] == '-') {
3026                                 param.fp_stripe_count_sign =  1;
3027                                 optarg++;
3028                         }
3029
3030                         param.fp_stripe_count = strtoul(optarg, &endptr, 0);
3031                         if (*endptr != '\0') {
3032                                 fprintf(stderr,"error: bad stripe_count '%s'\n",
3033                                         optarg);
3034                                 ret = -1;
3035                                 goto err;
3036                         }
3037                         param.fp_check_stripe_count = 1;
3038                         param.fp_exclude_stripe_count = !!neg_opt;
3039                         break;
3040                 case 'D':
3041                         param.fp_max_depth = strtol(optarg, 0, 0);
3042                         break;
3043                 case 'E':
3044                         if (optarg[0] == '+') {
3045                                 param.fp_comp_end_sign = -1;
3046                                 optarg++;
3047                         } else if (optarg[0] == '-') {
3048                                 param.fp_comp_end_sign =  1;
3049                                 optarg++;
3050                         }
3051
3052                         if (arg_is_eof(optarg)) {
3053                                 param.fp_comp_end = LUSTRE_EOF;
3054                                 param.fp_comp_end_units = 1;
3055                                 rc = 0;
3056                         } else {
3057                                 rc = llapi_parse_size(optarg,
3058                                                 &param.fp_comp_end,
3059                                                 &param.fp_comp_end_units, 0);
3060                         }
3061                         if (rc) {
3062                                 fprintf(stderr, "error: bad component end "
3063                                         "'%s'\n", optarg);
3064                                 goto err;
3065                         }
3066                         param.fp_check_comp_end = 1;
3067                         param.fp_exclude_comp_end = !!neg_opt;
3068                         break;
3069                 case 'g':
3070                 case 'G':
3071                         rc = name2gid(&param.fp_gid, optarg);
3072                         if (rc) {
3073                                 param.fp_gid = strtoul(optarg, &endptr, 10);
3074                                 if (*endptr != '\0') {
3075                                         fprintf(stderr, "Group/GID: %s cannot "
3076                                                 "be found.\n", optarg);
3077                                         ret = -1;
3078                                         goto err;
3079                                 }
3080                         }
3081                         param.fp_exclude_gid = !!neg_opt;
3082                         param.fp_check_gid = 1;
3083                         break;
3084                 case 'H':
3085                         param.fp_hash_type = check_hashtype(optarg);
3086                         if (param.fp_hash_type == 0) {
3087                                 fprintf(stderr, "error: bad hash_type '%s'\n",
3088                                         optarg);
3089                                 ret = -1;
3090                                 goto err;
3091                         }
3092                         param.fp_check_hash_type = 1;
3093                         param.fp_exclude_hash_type = !!neg_opt;
3094                         break;
3095                 case 'L':
3096                         ret = name2layout(&param.fp_layout, optarg);
3097                         if (ret)
3098                                 goto err;
3099                         param.fp_exclude_layout = !!neg_opt;
3100                         param.fp_check_layout = 1;
3101                         break;
3102                 case 'u':
3103                 case 'U':
3104                         rc = name2uid(&param.fp_uid, optarg);
3105                         if (rc) {
3106                                 param.fp_uid = strtoul(optarg, &endptr, 10);
3107                                 if (*endptr != '\0') {
3108                                         fprintf(stderr, "User/UID: %s cannot "
3109                                                 "be found.\n", optarg);
3110                                         ret = -1;
3111                                         goto err;
3112                                 }
3113                         }
3114                         param.fp_exclude_uid = !!neg_opt;
3115                         param.fp_check_uid = 1;
3116                         break;
3117                 case LFS_POOL_OPT:
3118                         if (strlen(optarg) > LOV_MAXPOOLNAME) {
3119                                 fprintf(stderr,
3120                                         "Pool name %s is too long"
3121                                         " (max is %d)\n", optarg,
3122                                         LOV_MAXPOOLNAME);
3123                                 ret = -1;
3124                                 goto err;
3125                         }
3126                         /* we do check for empty pool because empty pool
3127                          * is used to find V1 lov attributes */
3128                         strncpy(param.fp_poolname, optarg, LOV_MAXPOOLNAME);
3129                         param.fp_poolname[LOV_MAXPOOLNAME] = '\0';
3130                         param.fp_exclude_pool = !!neg_opt;
3131                         param.fp_check_pool = 1;
3132                         break;
3133                 case 'n':
3134                         param.fp_pattern = (char *)optarg;
3135                         param.fp_exclude_pattern = !!neg_opt;
3136                         break;
3137                 case 'm':
3138                 case 'i':
3139                 case 'O': {
3140                         char *buf, *token, *next, *p;
3141                         int len = 1;
3142                         void *tmp;
3143
3144                         buf = strdup(optarg);
3145                         if (buf == NULL) {
3146                                 ret = -ENOMEM;
3147                                 goto err;
3148                         }
3149
3150                         param.fp_exclude_obd = !!neg_opt;
3151
3152                         token = buf;
3153                         while (token && *token) {
3154                                 token = strchr(token, ',');
3155                                 if (token) {
3156                                         len++;
3157                                         token++;
3158                                 }
3159                         }
3160                         if (c == 'm') {
3161                                 param.fp_exclude_mdt = !!neg_opt;
3162                                 param.fp_num_alloc_mdts += len;
3163                                 tmp = realloc(param.fp_mdt_uuid,
3164                                               param.fp_num_alloc_mdts *
3165                                               sizeof(*param.fp_mdt_uuid));
3166                                 if (tmp == NULL) {
3167                                         ret = -ENOMEM;
3168                                         goto err_free;
3169                                 }
3170
3171                                 param.fp_mdt_uuid = tmp;
3172                         } else {
3173                                 param.fp_exclude_obd = !!neg_opt;
3174                                 param.fp_num_alloc_obds += len;
3175                                 tmp = realloc(param.fp_obd_uuid,
3176                                               param.fp_num_alloc_obds *
3177                                               sizeof(*param.fp_obd_uuid));
3178                                 if (tmp == NULL) {
3179                                         ret = -ENOMEM;
3180                                         goto err_free;
3181                                 }
3182
3183                                 param.fp_obd_uuid = tmp;
3184                         }
3185                         for (token = buf; token && *token; token = next) {
3186                                 struct obd_uuid *puuid;
3187                                 if (c == 'm') {
3188                                         puuid =
3189                                         &param.fp_mdt_uuid[param.fp_num_mdts++];
3190                                 } else {
3191                                         puuid =
3192                                         &param.fp_obd_uuid[param.fp_num_obds++];
3193                                 }
3194                                 p = strchr(token, ',');
3195                                 next = 0;
3196                                 if (p) {
3197                                         *p = 0;
3198                                         next = p+1;
3199                                 }
3200
3201                                 if (strlen(token) > sizeof(puuid->uuid) - 1) {
3202                                         ret = -E2BIG;
3203                                         goto err_free;
3204                                 }
3205
3206                                 strncpy(puuid->uuid, token,
3207                                         sizeof(puuid->uuid));
3208                         }
3209 err_free:
3210                         if (buf)
3211                                 free(buf);
3212                         break;
3213                 }
3214                 case 'p':
3215                         param.fp_zero_end = 1;
3216                         break;
3217                 case 'P':
3218                         break;
3219                 case LFS_PROJID_OPT:
3220                         rc = name2projid(&param.fp_projid, optarg);
3221                         if (rc) {
3222                                 param.fp_projid = strtoul(optarg, &endptr, 10);
3223                                 if (*endptr != '\0') {
3224                                         fprintf(stderr,
3225                                                 "Invalid project ID: %s",
3226                                                 optarg);
3227                                         ret = -1;
3228                                         goto err;
3229                                 }
3230                         }
3231                         param.fp_exclude_projid = !!neg_opt;
3232                         param.fp_check_projid = 1;
3233                         break;
3234                 case 's':
3235                         if (optarg[0] == '+') {
3236                                 param.fp_size_sign = -1;
3237                                 optarg++;
3238                         } else if (optarg[0] == '-') {
3239                                 param.fp_size_sign =  1;
3240                                 optarg++;
3241                         }
3242
3243                         ret = llapi_parse_size(optarg, &param.fp_size,
3244                                                &param.fp_size_units, 0);
3245                         if (ret) {
3246                                 fprintf(stderr, "error: bad file size '%s'\n",
3247                                         optarg);
3248                                 goto err;
3249                         }
3250                         param.fp_check_size = 1;
3251                         param.fp_exclude_size = !!neg_opt;
3252                         break;
3253                 case 'S':
3254                         if (optarg[0] == '+') {
3255                                 param.fp_stripe_size_sign = -1;
3256                                 optarg++;
3257                         } else if (optarg[0] == '-') {
3258                                 param.fp_stripe_size_sign =  1;
3259                                 optarg++;
3260                         }
3261
3262                         ret = llapi_parse_size(optarg, &param.fp_stripe_size,
3263                                                &param.fp_stripe_size_units, 0);
3264                         if (ret) {
3265                                 fprintf(stderr, "error: bad stripe_size '%s'\n",
3266                                         optarg);
3267                                 goto err;
3268                         }
3269                         param.fp_check_stripe_size = 1;
3270                         param.fp_exclude_stripe_size = !!neg_opt;
3271                         break;
3272                 case 't':
3273                         param.fp_exclude_type = !!neg_opt;
3274                         switch (optarg[0]) {
3275                         case 'b':
3276                                 param.fp_type = S_IFBLK;
3277                                 break;
3278                         case 'c':
3279                                 param.fp_type = S_IFCHR;
3280                                 break;
3281                         case 'd':
3282                                 param.fp_type = S_IFDIR;
3283                                 break;
3284                         case 'f':
3285                                 param.fp_type = S_IFREG;
3286                                 break;
3287                         case 'l':
3288                                 param.fp_type = S_IFLNK;
3289                                 break;
3290                         case 'p':
3291                                 param.fp_type = S_IFIFO;
3292                                 break;
3293                         case 's':
3294                                 param.fp_type = S_IFSOCK;
3295                                 break;
3296                         default:
3297                                 fprintf(stderr, "error: %s: bad type '%s'\n",
3298                                         argv[0], optarg);
3299                                 ret = CMD_HELP;
3300                                 goto err;
3301                         };
3302                         break;
3303                 case 'T':
3304                         if (optarg[0] == '+') {
3305                                 param.fp_mdt_count_sign = -1;
3306                                 optarg++;
3307                         } else if (optarg[0] == '-') {
3308                                 param.fp_mdt_count_sign =  1;
3309                                 optarg++;
3310                         }
3311
3312                         param.fp_mdt_count = strtoul(optarg, &endptr, 0);
3313                         if (*endptr != '\0') {
3314                                 fprintf(stderr, "error: bad mdt_count '%s'\n",
3315                                         optarg);
3316                                 ret = -1;
3317                                 goto err;
3318                         }
3319                         param.fp_check_mdt_count = 1;
3320                         param.fp_exclude_mdt_count = !!neg_opt;
3321                         break;
3322                 default:
3323                         ret = CMD_HELP;
3324                         goto err;
3325                 };
3326         }
3327
3328         if (pathstart == -1) {
3329                 fprintf(stderr, "error: %s: no filename|pathname\n",
3330                         argv[0]);
3331                 ret = CMD_HELP;
3332                 goto err;
3333         } else if (pathend == -1) {
3334                 /* no options */
3335                 pathend = argc;
3336         }
3337
3338         do {
3339                 rc = llapi_find(argv[pathstart], &param);
3340                 if (rc != 0 && ret == 0)
3341                         ret = rc;
3342         } while (++pathstart < pathend);
3343
3344         if (ret)
3345                 fprintf(stderr, "error: %s failed for %s.\n",
3346                         argv[0], argv[optind - 1]);
3347 err:
3348         if (param.fp_obd_uuid && param.fp_num_alloc_obds)
3349                 free(param.fp_obd_uuid);
3350
3351         if (param.fp_mdt_uuid && param.fp_num_alloc_mdts)
3352                 free(param.fp_mdt_uuid);
3353
3354         return ret;
3355 }
3356
3357 static int lfs_getstripe_internal(int argc, char **argv,
3358                                   struct find_param *param)
3359 {
3360         struct option long_opts[] = {
3361         { .val = LFS_COMP_COUNT_OPT,
3362                         .name = "comp-count",   .has_arg = no_argument },
3363         { .val = LFS_COMP_COUNT_OPT,
3364                 .name = "component-count",      .has_arg = no_argument },
3365         { .val = LFS_COMP_FLAGS_OPT,
3366                         .name = "comp-flags",   .has_arg = optional_argument },
3367         { .val = LFS_COMP_FLAGS_OPT,
3368                 .name = "component-flags",      .has_arg = optional_argument },
3369         { .val = LFS_COMP_START_OPT,
3370                         .name = "comp-start",   .has_arg = optional_argument },
3371         { .val = LFS_COMP_START_OPT,
3372                 .name = "component-start",      .has_arg = optional_argument },
3373 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0)
3374         /* This formerly implied "stripe-count", but was explicitly
3375          * made "stripe-count" for consistency with other options,
3376          * and to separate it from "mdt-count" when DNE arrives. */
3377         { .val = 'c',   .name = "count",        .has_arg = no_argument },
3378 #endif
3379         { .val = 'c',   .name = "stripe-count", .has_arg = no_argument },
3380         { .val = 'c',   .name = "stripe_count", .has_arg = no_argument },
3381         { .val = 'd',   .name = "directory",    .has_arg = no_argument },
3382         { .val = 'D',   .name = "default",      .has_arg = no_argument },
3383         { .val = 'E',   .name = "comp-end",     .has_arg = optional_argument },
3384         { .val = 'E',   .name = "component-end",
3385                                                 .has_arg = optional_argument },
3386         { .val = 'F',   .name = "fid",          .has_arg = no_argument },
3387         { .val = 'g',   .name = "generation",   .has_arg = no_argument },
3388         /* dirstripe { .val = 'H',      .name = "mdt-hash",
3389          *             .has_arg = required_argument }, */
3390 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0)
3391         /* This formerly implied "stripe-index", but was explicitly
3392          * made "stripe-index" for consistency with other options,
3393          * and to separate it from "mdt-index" when DNE arrives. */
3394         { .val = 'i',   .name = "index",        .has_arg = no_argument },
3395 #endif
3396         { .val = 'i',   .name = "stripe-index", .has_arg = no_argument },
3397         { .val = 'i',   .name = "stripe_index", .has_arg = no_argument },
3398         { .val = 'I',   .name = "comp-id",      .has_arg = optional_argument },
3399         { .val = 'I',   .name = "component-id", .has_arg = optional_argument },
3400         { .val = 'L',   .name = "layout",       .has_arg = no_argument },
3401         { .val = 'm',   .name = "mdt",          .has_arg = no_argument },
3402         { .val = 'm',   .name = "mdt-index",    .has_arg = no_argument },
3403         { .val = 'm',   .name = "mdt_index",    .has_arg = no_argument },
3404 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
3405         { .val = 'M',   .name = "mdt-index",    .has_arg = no_argument },
3406         { .val = 'M',   .name = "mdt_index",    .has_arg = no_argument },
3407 #endif
3408 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0)
3409         /* This formerly implied "stripe-index", but was confusing
3410          * with "file offset" (which will eventually be needed for
3411          * with different layouts by offset), so deprecate it. */
3412         { .val = 'o',   .name = "offset",       .has_arg = no_argument },
3413 #endif
3414         { .val = 'O',   .name = "obd",          .has_arg = required_argument },
3415         { .val = 'O',   .name = "ost",          .has_arg = required_argument },
3416         { .val = 'p',   .name = "pool",         .has_arg = no_argument },
3417         { .val = 'q',   .name = "quiet",        .has_arg = no_argument },
3418         { .val = 'r',   .name = "recursive",    .has_arg = no_argument },
3419         { .val = 'R',   .name = "raw",          .has_arg = no_argument },
3420 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0)
3421         /* This formerly implied "--stripe-size", but was confusing
3422          * with "lfs find --size|-s", which means "file size", so use
3423          * the consistent "--stripe-size|-S" for all commands. */
3424         { .val = 's',   .name = "size",         .has_arg = no_argument },
3425 #endif
3426         { .val = 'S',   .name = "stripe-size",  .has_arg = no_argument },
3427         { .val = 'S',   .name = "stripe_size",  .has_arg = no_argument },
3428         /* dirstripe { .val = 'T',      .name = "mdt-count",
3429          *             .has_arg = required_argument }, */
3430         { .val = 'v',   .name = "verbose",      .has_arg = no_argument },
3431         { .val = 'y',   .name = "yaml",         .has_arg = no_argument },
3432         { .name = NULL } };
3433         int c, rc;
3434         char *end, *tmp;
3435
3436         while ((c = getopt_long(argc, argv, "cdDE::FghiI::LmMoO:pqrRsSvy",
3437                                 long_opts, NULL)) != -1) {
3438                 switch (c) {
3439                 case 'c':
3440                         if (strcmp(argv[optind - 1], "--count") == 0)
3441                                 fprintf(stderr, "warning: '--count' deprecated,"
3442                                         " use '--stripe-count' instead\n");
3443                         if (!(param->fp_verbose & VERBOSE_DETAIL)) {
3444                                 param->fp_verbose |= VERBOSE_COUNT;
3445                                 param->fp_max_depth = 0;
3446                         }
3447                         break;
3448                 case LFS_COMP_COUNT_OPT: