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