Whamcloud - gitweb
b=17187
[fs/lustre-release.git] / lustre / utils / lfs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/utils/lfs.c
37  *
38  * Author: Peter J. Braam <braam@clusterfs.com>
39  * Author: Phil Schwan <phil@clusterfs.com>
40  * Author: Robert Read <rread@clusterfs.com>
41  */
42
43 /* for O_DIRECTORY */
44 #ifndef _GNU_SOURCE
45 #define _GNU_SOURCE
46 #endif
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <getopt.h>
51 #include <string.h>
52 #include <mntent.h>
53 #include <errno.h>
54 #include <pwd.h>
55 #include <grp.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <fcntl.h>
59 #include <dirent.h>
60 #include <time.h>
61 #include <ctype.h>
62 /* For dirname() */
63 #include <libgen.h>
64
65 #include <lnet/api-support.h>
66 #include <lnet/lnetctl.h>
67
68 #include <liblustre.h>
69 #include <lustre/lustre_idl.h>
70 #include <lustre/liblustreapi.h>
71 #include <lustre/lustre_user.h>
72
73 #include <libcfs/libcfsutil.h>
74 #include "obdctl.h"
75
76 unsigned int libcfs_subsystem_debug = 0;
77
78 /* all functions */
79 static int lfs_setstripe(int argc, char **argv);
80 static int lfs_find(int argc, char **argv);
81 static int lfs_getstripe(int argc, char **argv);
82 static int lfs_osts(int argc, char **argv);
83 static int lfs_df(int argc, char **argv);
84 static int lfs_check(int argc, char **argv);
85 static int lfs_catinfo(int argc, char **argv);
86 #ifdef HAVE_QUOTA_SUPPORT
87 static int lfs_quotachown(int argc, char **argv);
88 static int lfs_quotacheck(int argc, char **argv);
89 static int lfs_quotaon(int argc, char **argv);
90 static int lfs_quotaoff(int argc, char **argv);
91 static int lfs_setquota(int argc, char **argv);
92 static int lfs_quota(int argc, char **argv);
93 #endif
94 static int lfs_flushctx(int argc, char **argv);
95 static int lfs_join(int argc, char **argv);
96 static int lfs_lsetfacl(int argc, char **argv);
97 static int lfs_lgetfacl(int argc, char **argv);
98 static int lfs_rsetfacl(int argc, char **argv);
99 static int lfs_rgetfacl(int argc, char **argv);
100 static int lfs_cp(int argc, char **argv);
101 static int lfs_ls(int argc, char **argv);
102 static int lfs_poollist(int argc, char **argv);
103 static int lfs_path2fid(int argc, char **argv);
104
105 /* all avaialable commands */
106 command_t cmdlist[] = {
107         {"setstripe", lfs_setstripe, 0,
108          "Create a new file with a specific striping pattern or\n"
109          "set the default striping pattern on an existing directory or\n"
110          "delete the default striping pattern from an existing directory\n"
111          "usage: setstripe [--size|-s stripe_size] [--offset|-o start_ost]\n"
112          "                 [--count|-c stripe_count] [--pool|-p pool_name]\n"
113          "                 <dir|filename>\n"
114          "       or \n"
115          "       setstripe -d <dir>   (to delete default striping)\n"
116          "\tstripe_size:  Number of bytes on each OST (0 filesystem default)\n"
117          "\t              Can be specified with k, m or g (in KB, MB and GB\n"
118          "\t              respectively)\n"
119          "\tstart_ost:    OST index of first stripe (-1 filesystem default)\n"
120          "\tstripe_count: Number of OSTs to stripe over (0 default, -1 all)\n"
121          "\tpool_name:    Name of OST pool"},
122         {"getstripe", lfs_getstripe, 0,
123          "To list the striping info for a given file or files in a\n"
124          "directory or recursively for all files in a directory tree.\n"
125          "usage: getstripe [--obd|-O <uuid>] [--quiet | -q] [--verbose | -v]\n"
126          "                 [--recursive | -r] <dir|file> ..."},
127         {"poollist", lfs_poollist, 0,
128          "List pools or pool OSTs\n"
129          "usage: poollist <fsname>[.<poolname>] | <pathname>\n"},
130         {"find", lfs_find, 0,
131          "To find files that match given parameters recursively in a directory tree.\n"
132          "usage: find <dir|file> ... \n"
133          "     [[!] --atime|-A [+-]N] [[!] --mtime|-M [+-]N] [[!] --ctime|-C [+-]N]\n"
134          "     [--maxdepth|-D N] [[!] --name|-n <pattern>] [--print0|-P]\n"
135          "     [--print|-p] [--obd|-O <uuid[s]>] [[!] --size|-s [+-]N[bkMGTP]]\n"
136          "     [[!] --type|-t <filetype>] [[!] --gid|-g N] [[!] --group|-G <name>]\n"
137          "     [[!] --uid|-u N] [[!] --user|-U <name>]\n"
138          "     [[!] --pool <name>]\n"
139          "\t !: used before an option indicates 'NOT' the requested attribute\n"
140          "\t -: used before an value indicates 'AT MOST' the requested value\n"
141          "\t +: used before an option indicates 'AT LEAST' the requested value\n"},
142         {"check", lfs_check, 0,
143          "Display the status of MDS or OSTs (as specified in the command)\n"
144          "or all the servers (MDS and OSTs).\n"
145          "usage: check <osts|mds|servers>"},
146         {"catinfo", lfs_catinfo, 0,
147          "Show information of specified type logs.\n"
148          "usage: catinfo {keyword} [node name]\n"
149          "\tkeywords are one of followings: config, deletions.\n"
150          "\tnode name must be provided when use keyword config."},
151         {"join", lfs_join, 0,
152          "join two lustre files into one - join A, B, will be like cat B >> A & del B\n"
153          "usage: join <filename_A> <filename_B>\n"},
154         {"osts", lfs_osts, 0, "osts"},
155         {"df", lfs_df, 0,
156          "report filesystem disk space usage or inodes usage"
157          "of each MDS/OSD.\n"
158          "Usage: df [-i] [-h] [path]"},
159 #ifdef HAVE_QUOTA_SUPPORT
160         {"quotachown",lfs_quotachown, 0,
161          "Change files' owner or group on the specified filesystem.\n"
162          "usage: quotachown [-i] <filesystem>\n"
163          "\t-i: ignore error if file is not exist\n"},
164         {"quotacheck", lfs_quotacheck, 0,
165          "Scan the specified filesystem for disk usage, and create,\n"
166          "or update quota files.\n"
167          "usage: quotacheck [ -ug ] <filesystem>"},
168         {"quotaon", lfs_quotaon, 0, "Turn filesystem quotas on.\n"
169          "usage: quotaon [ -ugf ] <filesystem>"},
170         {"quotaoff", lfs_quotaoff, 0, "Turn filesystem quotas off.\n"
171          "usage: quotaoff [ -ug ] <filesystem>"},
172         {"setquota", lfs_setquota, 0, "Set filesystem quotas.\n"
173          "usage: setquota [ -u | -g ] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>\n"
174          "       setquota -t [ -u | -g ] <block-grace> <inode-grace> <filesystem>"},
175         {"quota", lfs_quota, 0, "Display disk usage and limits.\n"
176          "usage: quota [ -o obd_uuid ] [{-u|-g  <name>}|-t] <filesystem>"},
177 #endif
178         {"flushctx", lfs_flushctx, 0, "Flush security context for current user.\n"
179          "usage: flushctx [-k] [mountpoint...]"},
180         {"lsetfacl", lfs_lsetfacl, 0,
181          "Remote user setfacl for user/group on the same remote client.\n"
182          "usage: lsetfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ..."},
183         {"lgetfacl", lfs_lgetfacl, 0,
184          "Remote user getfacl for user/group on the same remote client.\n"
185          "usage: lgetfacl [-dRLPvh] file ..."},
186         {"rsetfacl", lfs_rsetfacl, 0,
187          "Remote user setfacl for user/group on other clients.\n"
188          "usage: rsetfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ..."},
189         {"rgetfacl", lfs_rgetfacl, 0,
190          "Remote user getfacl for user/group on other clients.\n"
191          "usage: rgetfacl [-dRLPvh] file ..."},
192         {"cp", lfs_cp, 0,
193          "Remote user copy files and directories.\n"
194          "usage: cp [OPTION]... [-T] SOURCE DEST\n\tcp [OPTION]... SOURCE... DIRECTORY\n\tcp [OPTION]... -t DIRECTORY SOURCE..."},
195         {"ls", lfs_ls, 0,
196          "Remote user list directory contents.\n"
197          "usage: ls [OPTION]... [FILE]..."},
198         {"path2fid", lfs_path2fid, 0, "Display the fid for a given path.\n"
199          "usage: path2fid <path>"},
200         {"help", Parser_help, 0, "help"},
201         {"exit", Parser_quit, 0, "quit"},
202         {"quit", Parser_quit, 0, "quit"},
203         { 0, 0, 0, NULL }
204 };
205
206 static int isnumber(const char *str)
207 {
208         const char *ptr;
209
210         if (str[0] != '-' && !isdigit(str[0]))
211                 return 0;
212
213         for (ptr = str + 1; *ptr != '\0'; ptr++) {
214                 if (!isdigit(*ptr))
215                         return 0;
216         }
217
218         return 1;
219 }
220
221 /* functions */
222 static int lfs_setstripe(int argc, char **argv)
223 {
224         char *fname;
225         int result;
226         unsigned long long st_size;
227         int  st_offset, st_count;
228         char *end;
229         int c;
230         int delete = 0;
231         char *stripe_size_arg = NULL;
232         char *stripe_off_arg = NULL;
233         char *stripe_count_arg = NULL;
234         char *pool_name_arg = NULL;
235         unsigned long long size_units;
236
237         struct option long_opts[] = {
238                 {"size",        required_argument, 0, 's'},
239                 {"count",       required_argument, 0, 'c'},
240                 {"index",       required_argument, 0, 'i'},
241                 {"offset",      required_argument, 0, 'o'},
242                 {"pool",        required_argument, 0, 'p'},
243                 {"delete",      no_argument,       0, 'd'},
244                 {0, 0, 0, 0}
245         };
246
247         st_size = 0;
248         st_offset = -1;
249         st_count = 0;
250
251 #if LUSTRE_VERSION < OBD_OCD_VERSION(2,1,0,0)
252         if (argc == 5 && argv[1][0] != '-' &&
253             isnumber(argv[2]) && isnumber(argv[3]) && isnumber(argv[4])) {
254                 fprintf(stderr, "warning: deprecated usage of setstripe "
255                         "positional parameters.  Use -c, -i, -s instead.\n");
256                 /* for compatibility with the existing positional parameter
257                  * usage */
258                 fname = argv[1];
259                 stripe_size_arg = argv[2];
260                 stripe_off_arg = argv[3];
261                 stripe_count_arg = argv[4];
262                 optind = 4;
263         } else
264 #else
265 #warning "remove obsolete positional parameter code"
266 #endif
267         {
268                 optind = 0;
269                 while ((c = getopt_long(argc, argv, "c:di:o:s:p:",
270                                                 long_opts, NULL)) >= 0) {
271                         switch (c) {
272                         case 0:
273                                 /* Long options. */
274                                 break;
275                         case 'c':
276                                 stripe_count_arg = optarg;
277                                 break;
278                         case 'd':
279                                 /* delete the default striping pattern */
280                                 delete = 1;
281                                 break;
282                         case 'i':
283                         case 'o':
284                                 stripe_off_arg = optarg;
285                                 break;
286                         case 's':
287                                 stripe_size_arg = optarg;
288                                 break;
289                         case 'p':
290                                 pool_name_arg = optarg;
291                                 break;
292                         case '?':
293                                 return CMD_HELP;
294                         default:
295                                 fprintf(stderr, "error: %s: option '%s' "
296                                                 "unrecognized\n",
297                                                 argv[0], argv[optind - 1]);
298                                 return CMD_HELP;
299                         }
300                 }
301
302                 fname = argv[optind];
303
304                 if (delete &&
305                     (stripe_size_arg != NULL || stripe_off_arg != NULL ||
306                      stripe_count_arg != NULL || pool_name_arg != NULL)) {
307                         fprintf(stderr, "error: %s: cannot specify -d with "
308                                         "-s, -c -o or -p options\n",
309                                         argv[0]);
310                         return CMD_HELP;
311                 }
312         }
313
314         if (optind == argc) {
315                 fprintf(stderr, "error: %s: missing filename|dirname\n",
316                                 argv[0]);
317                 return CMD_HELP;
318         }
319
320         /* get the stripe size */
321         if (stripe_size_arg != NULL) {
322                 result = parse_size(stripe_size_arg, &st_size, &size_units);
323                 if (result) {
324                         fprintf(stderr, "error: %s: bad size '%s'\n",
325                                 argv[0], stripe_size_arg);
326                         return result;
327                 }
328         }
329         /* get the stripe offset */
330         if (stripe_off_arg != NULL) {
331                 st_offset = strtoul(stripe_off_arg, &end, 0);
332                 if (*end != '\0') {
333                         fprintf(stderr, "error: %s: bad stripe offset '%s'\n",
334                                 argv[0], stripe_off_arg);
335                         return CMD_HELP;
336                 }
337         }
338         /* get the stripe count */
339         if (stripe_count_arg != NULL) {
340                 st_count = strtoul(stripe_count_arg, &end, 0);
341                 if (*end != '\0') {
342                         fprintf(stderr, "error: %s: bad stripe count '%s'\n",
343                                 argv[0], stripe_count_arg);
344                         return CMD_HELP;
345                 }
346         }
347
348         do {
349                 result = llapi_file_create_pool(fname, st_size, st_offset,
350                                                 st_count, 0, pool_name_arg);
351                 if (result) {
352                         fprintf(stderr,"error: %s: create stripe file '%s' "
353                                 "failed\n", argv[0], fname);
354                         break;
355                 }
356                 fname = argv[++optind];
357         } while (fname != NULL);
358
359         return result;
360 }
361
362 static int lfs_poollist(int argc, char **argv)
363 {
364         if (argc != 2)
365                 return CMD_HELP;
366
367         return llapi_poollist(argv[1]);
368 }
369
370 static int set_time(time_t *time, time_t *set, char *str)
371 {
372         time_t t;
373         int res = 0;
374
375         if (str[0] == '+')
376                 res = 1;
377         else if (str[0] == '-')
378                 res = -1;
379
380         if (res)
381                 str++;
382
383         t = strtol(str, NULL, 0);
384         if (*time < t * 24 * 60 * 60) {
385                 if (res)
386                         str--;
387                 fprintf(stderr, "Wrong time '%s' is specified.\n", str);
388                 return INT_MAX;
389         }
390
391         *set = *time - t * 24 * 60 * 60;
392         return res;
393 }
394
395 static int name2id(unsigned int *id, char *name, int type)
396 {
397         if (type == USRQUOTA) {
398                 struct passwd *entry;
399
400                 if (!(entry = getpwnam(name))) {
401                         if (!errno)
402                                 errno = ENOENT;
403                         return -1;
404                 }
405
406                 *id = entry->pw_uid;
407         } else {
408                 struct group *entry;
409
410                 if (!(entry = getgrnam(name))) {
411                         if (!errno)
412                                 errno = ENOENT;
413                         return -1;
414                 }
415
416                 *id = entry->gr_gid;
417         }
418
419         return 0;
420 }
421
422 static int id2name(char **name, unsigned int id, int type)
423 {
424         if (type == USRQUOTA) {
425                 struct passwd *entry;
426
427                 if (!(entry = getpwuid(id))) {
428                         if (!errno)
429                                 errno = ENOENT;
430                         return -1;
431                 }
432
433                 *name = entry->pw_name;
434         } else {
435                 struct group *entry;
436
437                 if (!(entry = getgrgid(id))) {
438                         if (!errno)
439                                 errno = ENOENT;
440                         return -1;
441                 }
442
443                 *name = entry->gr_name;
444         }
445
446         return 0;
447 }
448
449 #define FIND_POOL_OPT 3
450 static int lfs_find(int argc, char **argv)
451 {
452         int new_fashion = 1;
453         int c, ret;
454         time_t t;
455         struct find_param param = { .maxdepth = -1 };
456         char str[1024];
457         struct option long_opts[] = {
458                 /* New find options. */
459                 {"atime",     required_argument, 0, 'A'},
460                 {"ctime",     required_argument, 0, 'C'},
461                 {"mtime",     required_argument, 0, 'M'},
462                 {"maxdepth",  required_argument, 0, 'D'},
463                 {"gid",       required_argument, 0, 'g'},
464                 {"group",     required_argument, 0, 'G'},
465                 {"uid",       required_argument, 0, 'u'},
466                 {"user",      required_argument, 0, 'U'},
467                 {"name",      required_argument, 0, 'n'},
468                 /* no short option for pool, p/P already used */
469                 {"pool",      required_argument, 0, FIND_POOL_OPT},
470                 /* --obd is considered as a new option. */
471                 {"obd",       required_argument, 0, 'O'},
472                 {"ost",       required_argument, 0, 'O'},
473                 {"print",     no_argument,       0, 'P'},
474                 {"print0",    no_argument,       0, 'p'},
475                 /* Old find options. */
476                 {"quiet",     no_argument,       0, 'q'},
477                 {"recursive", no_argument,       0, 'r'},
478                 {"size",      required_argument, 0, 's'},
479                 {"type",      required_argument, 0, 't'},
480                 {"verbose",   no_argument,       0, 'v'},
481                 {0, 0, 0, 0}
482         };
483         int pathstart = -1;
484         int pathend = -1;
485         int neg_opt = 0;
486         time_t *xtime;
487         int *xsign;
488         int isoption;
489         char *endptr;
490
491         time(&t);
492
493         optind = 0;
494         /* when getopt_long_only() hits '!' it returns 1 and puts "!" in optarg */
495         while ((c = getopt_long_only(argc, argv, "-A:C:D:g:G:M:n:PpO:qrs:t:u:U:v",
496                                      long_opts, NULL)) >= 0) {
497                 xtime = NULL;
498                 xsign = NULL;
499                 if (neg_opt)
500                         --neg_opt;
501                 /* '!' is part of option */
502                 /* when getopt_long_only() finds a string which is not
503                  * an option nor a known option argument it returns 1
504                  * in that case if we already have found pathstart and pathend
505                  * (i.e. we have the list of pathnames),
506                  * the only supported value is "!"
507                  */
508                 isoption = (c != 1) || (strcmp(optarg, "!") == 0);
509                 if (!isoption && pathend != -1) {
510                         fprintf(stderr, "err: %s: filename|dirname must either "
511                                         "precede options or follow options\n",
512                                         argv[0]);
513                         return CMD_HELP;
514                 }
515                 if (!isoption && pathstart == -1)
516                         pathstart = optind - 1;
517                 if (isoption && pathstart != -1 && pathend == -1) {
518                         pathend = optind - 2;
519                         if ((c == 1 && strcmp(optarg, "!") == 0) ||
520                             c == 'P' || c == 'p' || c == 'O' ||
521                             c == 'q' || c == 'r' || c == 'v')
522                                 pathend = optind - 1;
523                 }
524                 switch (c) {
525                 case 0:
526                         /* Long options. */
527                         break;
528                 case 1:
529                         /* unknown; opt is "!" or path component,
530                          * checking done above.
531                          */
532                         if (strcmp(optarg, "!") == 0)
533                                 neg_opt = 2;
534                         break;
535                 case 'A':
536                         xtime = &param.atime;
537                         xsign = &param.asign;
538                 case 'C':
539                         if (c == 'C') {
540                                 xtime = &param.ctime;
541                                 xsign = &param.csign;
542                         }
543                 case 'M':
544                         if (c == 'M') {
545                                 xtime = &param.mtime;
546                                 xsign = &param.msign;
547                         }
548                         new_fashion = 1;
549                         if (neg_opt) {
550                                 if (optarg[0] == '-')
551                                         optarg[0] = '+';
552                                 else if (optarg[0] == '+')
553                                         optarg[0] = '-';
554                                 else {
555                                         str[0] = '-';
556                                         str[1] = '\0';
557                                         strcat(str, optarg);
558                                         optarg = str;
559                                 }
560                         }
561                         ret = set_time(&t, xtime, optarg);
562                         if (ret == INT_MAX)
563                                 return -1;
564                         if (ret)
565                                 *xsign = ret;
566                         break;
567                 case 'D':
568                         new_fashion = 1;
569                         param.maxdepth = strtol(optarg, 0, 0);
570                         break;
571                 case 'g':
572                         new_fashion = 1;
573                         param.gid = strtol(optarg, &endptr, 10);
574                         if (optarg == endptr) {
575                                 fprintf(stderr, "Bad gid: %s\n", optarg);
576                                 return CMD_HELP;
577                         }
578                         param.exclude_gid = !!neg_opt;
579                         param.check_gid = 1;
580                         break;
581                 case 'G':
582                         new_fashion = 1;
583                         param.gid = strtol(optarg, &endptr, 10);
584                         if (optarg == endptr) {
585                                 ret = name2id(&param.gid, optarg, GRPQUOTA);
586                                 if (ret != 0) {
587                                         fprintf(stderr, "Group/GID: %s cannot "
588                                                 "be found.\n", optarg);
589                                         return -1;
590                                 }
591                         }
592                         param.exclude_gid = !!neg_opt;
593                         param.check_gid = 1;
594                         break;
595                 case 'u':
596                         new_fashion = 1;
597                         param.uid = strtol(optarg, &endptr, 10);
598                         if (optarg == endptr) {
599                                 fprintf(stderr, "Bad uid: %s\n", optarg);
600                                 return CMD_HELP;
601                         }
602                         param.exclude_uid = !!neg_opt;
603                         param.check_uid = 1;
604                         break;
605                 case 'U':
606                         new_fashion = 1;
607                         param.uid = strtol(optarg, &endptr, 10);
608                         if (optarg == endptr) {
609                                 ret = name2id(&param.uid, optarg, USRQUOTA);
610                                 if (ret != 0) {
611                                         fprintf(stderr, "User/UID: %s cannot "
612                                                 "be found.\n", optarg);
613                                         return -1;
614                                 }
615                         }
616                         param.exclude_uid = !!neg_opt;
617                         param.check_uid = 1;
618                         break;
619                 case FIND_POOL_OPT:
620                         new_fashion = 1;
621                         if (strlen(optarg) > LOV_MAXPOOLNAME) {
622                                 fprintf(stderr,
623                                         "Pool name %s is too long"
624                                         " (max is %d)\n", optarg,
625                                         LOV_MAXPOOLNAME);
626                                 return -1;
627                         }
628                         /* we do check for empty pool because empty pool
629                          * is used to find V1 lov attributes */
630                         strncpy(param.poolname, optarg, LOV_MAXPOOLNAME);
631                         param.poolname[LOV_MAXPOOLNAME] = '\0';
632                         param.exclude_pool = !!neg_opt;
633                         param.check_pool = 1;
634                         break;
635                 case 'n':
636                         new_fashion = 1;
637                         param.pattern = (char *)optarg;
638                         param.exclude_pattern = !!neg_opt;
639                         break;
640                 case 'O': {
641                         char *buf, *token, *next, *p;
642                         int len;
643
644                         len = strlen((char *)optarg);
645                         buf = malloc(len+1);
646                         if (buf == NULL)
647                                 return -ENOMEM;
648                         strcpy(buf, (char *)optarg);
649
650                         if (param.num_alloc_obds == 0) {
651                                 param.obduuid = malloc(FIND_MAX_OSTS *
652                                                        sizeof(struct obd_uuid));
653                                 if (param.obduuid == NULL)
654                                         return -ENOMEM;
655                                 param.num_alloc_obds = INIT_ALLOC_NUM_OSTS;
656                         }
657
658                         for (token = buf; token && *token; token = next) {
659                                 p = strchr(token, ',');
660                                 next = 0;
661                                 if (p) {
662                                         *p = 0;
663                                         next = p+1;
664                                 }
665                                 strcpy((char *)&param.obduuid[param.num_obds++].uuid,
666                                        token);
667                         }
668
669                         if (buf)
670                                 free(buf);
671                         break;
672                 }
673                 case 'p':
674                         new_fashion = 1;
675                         param.zeroend = 1;
676                         break;
677                 case 'P':
678                         break;
679                 case 'q':
680                         new_fashion = 0;
681                         param.quiet++;
682                         param.verbose = 0;
683                         break;
684                 case 'r':
685                         new_fashion = 0;
686                         param.recursive = 1;
687                         break;
688                 case 't':
689                         param.exclude_type = !!neg_opt;
690                         switch(optarg[0]) {
691                         case 'b': param.type = S_IFBLK; break;
692                         case 'c': param.type = S_IFCHR; break;
693                         case 'd': param.type = S_IFDIR; break;
694                         case 'f': param.type = S_IFREG; break;
695                         case 'l': param.type = S_IFLNK; break;
696                         case 'p': param.type = S_IFIFO; break;
697                         case 's': param.type = S_IFSOCK; break;
698 #ifdef S_IFDOOR /* Solaris only */
699                         case 'D': param.type = S_IFDOOR; break;
700 #endif
701                         default: fprintf(stderr, "error: %s: bad type '%s'\n",
702                                          argv[0], optarg);
703                                  return CMD_HELP;
704                         };
705                         break;
706                 case 's':
707                         if (neg_opt) {
708                                 if (optarg[0] == '-')
709                                         optarg[0] = '+';
710                                 else if (optarg[0] == '+')
711                                         optarg[0] = '-';
712                                 else {
713                                         str[0] = '-';
714                                         str[1] = '\0';
715                                         strcat(str, optarg);
716                                         optarg = str;
717                                 }
718                         }
719                         if (optarg[0] == '+')
720                                 param.size_sign = -1;
721                         else if (optarg[0] == '-')
722                                 param.size_sign = +1;
723
724                         if (param.size_sign)
725                                 optarg++;
726                         ret = parse_size(optarg, &param.size,&param.size_units);
727                         if (ret) {
728                                 fprintf(stderr,"error: bad size '%s'\n",
729                                         optarg);
730                                 return ret;
731                         }
732                         break;
733                 case 'v':
734                         new_fashion = 0;
735                         param.verbose++;
736                         param.quiet = 0;
737                         break;
738                 case '?':
739                         return CMD_HELP;
740                 default:
741                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
742                                 argv[0], argv[optind - 1]);
743                         return CMD_HELP;
744                 };
745         }
746
747         if (pathstart == -1) {
748                 fprintf(stderr, "error: %s: no filename|pathname\n",
749                         argv[0]);
750                 return CMD_HELP;
751         } else if (pathend == -1) {
752                 /* no options */
753                 pathend = argc;
754         }
755
756         if (new_fashion) {
757                 param.quiet = 1;
758         } else {
759                 static int deprecated_warning;
760                 if (!deprecated_warning) {
761                         fprintf(stderr, "lfs find: -q, -r, -v options "
762                                 "deprecated.  Use 'lfs getstripe' instead.\n");
763                         deprecated_warning = 1;
764                 }
765                 if (!param.recursive && param.maxdepth == -1)
766                         param.maxdepth = 1;
767         }
768
769         do {
770                 if (new_fashion)
771                         ret = llapi_find(argv[pathstart], &param);
772                 else
773                         ret = llapi_getstripe(argv[pathstart], &param);
774         } while (++pathstart < pathend && !ret);
775
776         if (ret)
777                 fprintf(stderr, "error: %s failed for %s.\n",
778                         argv[0], argv[optind - 1]);
779
780         if (param.obduuid && param.num_alloc_obds)
781                 free(param.obduuid);
782
783         return ret;
784 }
785
786 static int lfs_getstripe(int argc, char **argv)
787 {
788         struct option long_opts[] = {
789                 {"obd", 1, 0, 'O'},
790                 {"quiet", 0, 0, 'q'},
791                 {"recursive", 0, 0, 'r'},
792                 {"verbose", 0, 0, 'v'},
793                 {0, 0, 0, 0}
794         };
795         char short_opts[] = "hO:qrv";
796         int c, rc;
797         struct find_param param = { 0 };
798
799         optind = 0;
800         while ((c = getopt_long(argc, argv, short_opts,
801                                 long_opts, NULL)) != -1) {
802                 switch (c) {
803                 case 'O':
804                         if (param.obduuid) {
805                                 fprintf(stderr,
806                                         "error: %s: only one obduuid allowed",
807                                         argv[0]);
808                                 return CMD_HELP;
809                         }
810                         param.obduuid = (struct obd_uuid *)optarg;
811                         break;
812                 case 'q':
813                         param.quiet++;
814                         param.verbose = 0;
815                         break;
816                 case 'r':
817                         param.recursive = 1;
818                         break;
819                 case 'v':
820                         param.verbose++;
821                         param.quiet = 0;
822                         break;
823                 case '?':
824                         return CMD_HELP;
825                 default:
826                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
827                                 argv[0], argv[optind - 1]);
828                         return CMD_HELP;
829                 }
830         }
831
832         if (optind >= argc)
833                 return CMD_HELP;
834
835         param.maxdepth = param.recursive ? -1 : 1;
836
837         do {
838                 rc = llapi_getstripe(argv[optind], &param);
839         } while (++optind < argc && !rc);
840
841         if (rc)
842                 fprintf(stderr, "error: %s failed for %s.\n",
843                         argv[0], argv[optind - 1]);
844         return rc;
845 }
846
847 static int lfs_osts(int argc, char **argv)
848 {
849         FILE *fp;
850         struct mntent *mnt = NULL;
851         struct find_param param;
852         int rc=0;
853
854         if (argc != 1)
855                 return CMD_HELP;
856
857         fp = setmntent(MOUNTED, "r");
858
859         if (fp == NULL) {
860                  fprintf(stderr, "%s: setmntent(%s): %s:", argv[0], MOUNTED,
861                         strerror (errno));
862         } else {
863                 mnt = getmntent(fp);
864                 while (feof(fp) == 0 && ferror(fp) ==0) {
865                         memset(&param, 0, sizeof(param));
866                         if (llapi_is_lustre_mnt(mnt)) {
867                                 rc = llapi_getstripe(mnt->mnt_dir, &param);
868                                 if (rc)
869                                         fprintf(stderr,
870                                                "error: %s: failed on %s\n",
871                                                argv[0], mnt->mnt_dir);
872                         }
873                         mnt = getmntent(fp);
874                 }
875                 endmntent(fp);
876         }
877
878         return rc;
879 }
880
881 static int lfs_path2fid(int argc, char **argv)
882 {
883         char *path;
884         unsigned long long seq;
885         unsigned long oid, ver;
886         int rc;
887
888         if (argc != 2)
889                 return CMD_HELP;
890
891         path = argv[1];
892         rc = llapi_path2fid(path, &seq, &oid, &ver);
893         if (rc) {
894                 fprintf(stderr, "error: can't get fid for %s\n", path);
895                 return rc;
896         }
897
898         printf("%llu:%lu", seq, oid);
899         if (ver)
900                 printf(":%lu", ver);
901
902         printf("\n");
903
904         return 0;
905 }
906
907 #define COOK(value)                                                     \
908 ({                                                                      \
909         int radix = 0;                                                  \
910         while (value > 1024) {                                          \
911                 value /= 1024;                                          \
912                 radix++;                                                \
913         }                                                               \
914         radix;                                                          \
915 })
916 #define UUF     "%-20s"
917 #define CSF     "%9s"
918 #define CDF     "%9llu"
919 #define HSF     "%8s"
920 #define HDF     "%6.1f"
921 #define RSF     "%5s"
922 #define RDF     "%4d%%"
923
924 static int path2mnt(char *path, FILE *fp, char *mntdir, int dir_len)
925 {
926         char rpath[PATH_MAX] = {'\0'};
927         struct mntent *mnt;
928         int rc, len, out_len = 0;
929
930         if (!realpath(path, rpath)) {
931                 rc = -errno;
932                 fprintf(stderr, "error: lfs df: invalid path '%s': %s\n",
933                         path, strerror(-rc));
934                 return rc;
935         }
936
937         len = 0;
938         mnt = getmntent(fp);
939         while (feof(fp) == 0 && ferror(fp) == 0) {
940                 if (llapi_is_lustre_mnt(mnt)) {
941                         len = strlen(mnt->mnt_dir);
942                         if (len > out_len &&
943                             !strncmp(rpath, mnt->mnt_dir, len)) {
944                                 out_len = len;
945                                 memset(mntdir, 0, dir_len);
946                                 strncpy(mntdir, mnt->mnt_dir, dir_len);
947                         }
948                 }
949                 mnt = getmntent(fp);
950         }
951
952         if (out_len > 0)
953                 return 0;
954
955         fprintf(stderr, "error: lfs df: %s isn't mounted on lustre\n", path);
956         return -EINVAL;
957 }
958
959 static int showdf(char *mntdir, struct obd_statfs *stat,
960                   char *uuid, int ishow, int cooked,
961                   char *type, int index, int rc)
962 {
963         long long avail, used, total;
964         double ratio = 0;
965         char *suffix = "KMGTPEZY";
966         /* Note if we have >2^64 bytes/fs these buffers will need to be grown */
967         char tbuf[20], ubuf[20], abuf[20], rbuf[20];
968
969         if (!uuid || !stat)
970                 return -EINVAL;
971
972         switch (rc) {
973         case 0:
974                 if (ishow) {
975                         avail = stat->os_ffree;
976                         used = stat->os_files - stat->os_ffree;
977                         total = stat->os_files;
978                 } else {
979                         int shift = cooked ? 0 : 10;
980
981                         avail = (stat->os_bavail * stat->os_bsize) >> shift;
982                         used  = ((stat->os_blocks - stat->os_bfree) *
983                                  stat->os_bsize) >> shift;
984                         total = (stat->os_blocks * stat->os_bsize) >> shift;
985                 }
986
987                 if (total > 0)
988                         ratio = (double)used / (double)total;
989
990                 if (cooked) {
991                         int i;
992                         double cook_val;
993
994                         cook_val = (double)total;
995                         i = COOK(cook_val);
996                         if (i > 0)
997                                 sprintf(tbuf, HDF"%c", cook_val, suffix[i - 1]);
998                         else
999                                 sprintf(tbuf, CDF, total);
1000
1001                         cook_val = (double)used;
1002                         i = COOK(cook_val);
1003                         if (i > 0)
1004                                 sprintf(ubuf, HDF"%c", cook_val, suffix[i - 1]);
1005                         else
1006                                 sprintf(ubuf, CDF, used);
1007
1008                         cook_val = (double)avail;
1009                         i = COOK(cook_val);
1010                         if (i > 0)
1011                                 sprintf(abuf, HDF"%c", cook_val, suffix[i - 1]);
1012                         else
1013                                 sprintf(abuf, CDF, avail);
1014                 } else {
1015                         sprintf(tbuf, CDF, total);
1016                         sprintf(ubuf, CDF, used);
1017                         sprintf(abuf, CDF, avail);
1018                 }
1019
1020                 sprintf(rbuf, RDF, (int)(ratio * 100));
1021                 printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s",
1022                        uuid, tbuf, ubuf, abuf, rbuf, mntdir);
1023                 if (type)
1024                         printf("[%s:%d]\n", type, index);
1025                 else
1026                         printf("\n");
1027
1028                 break;
1029         case -ENODATA:
1030                 printf(UUF": inactive device\n", uuid);
1031                 break;
1032         default:
1033                 printf(UUF": %s\n", uuid, strerror(-rc));
1034                 break;
1035         }
1036
1037         return 0;
1038 }
1039
1040 static int mntdf(char *mntdir, int ishow, int cooked)
1041 {
1042         struct obd_statfs stat_buf, sum = { .os_bsize = 1 };
1043         struct obd_uuid uuid_buf;
1044         __u32 index;
1045         int rc;
1046
1047         if (ishow)
1048                 printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s\n",
1049                        "UUID", "Inodes", "IUsed", "IFree",
1050                        "IUse%", "Mounted on");
1051         else
1052                 printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s\n",
1053                        "UUID", cooked ? "bytes" : "1K-blocks",
1054                        "Used", "Available", "Use%", "Mounted on");
1055
1056         for (index = 0; ; index++) {
1057                 memset(&stat_buf, 0, sizeof(struct obd_statfs));
1058                 memset(&uuid_buf, 0, sizeof(struct obd_uuid));
1059                 rc = llapi_obd_statfs(mntdir, LL_STATFS_MDC, index,
1060                                       &stat_buf, &uuid_buf);
1061                 if (rc == -ENODEV)
1062                         break;
1063
1064                 if (rc == -EAGAIN)
1065                         continue;
1066
1067                 if (rc == -ENOTCONN || rc == -ETIMEDOUT || rc == -EIO ||
1068                     rc == -ENODATA || rc == 0) {
1069                         showdf(mntdir, &stat_buf, uuid_buf.uuid, ishow, cooked,
1070                                "MDT", index, rc);
1071                 } else {
1072                         fprintf(stderr,
1073                                 "error: llapi_obd_statfs(%s): %s (%d)\n",
1074                                 uuid_buf.uuid, strerror(-rc), rc);
1075                         return rc;
1076                 }
1077                 if (rc == 0) {
1078                         sum.os_ffree += stat_buf.os_ffree;
1079                         sum.os_files += stat_buf.os_files;
1080                 }
1081         }
1082
1083         for (index = 0; ; index++) {
1084                 memset(&stat_buf, 0, sizeof(struct obd_statfs));
1085                 memset(&uuid_buf, 0, sizeof(struct obd_uuid));
1086                 rc = llapi_obd_statfs(mntdir, LL_STATFS_LOV, index,
1087                                       &stat_buf, &uuid_buf);
1088                 if (rc == -ENODEV)
1089                         break;
1090
1091                 if (rc == -EAGAIN)
1092                         continue;
1093
1094                 if (rc == -ENOTCONN || rc == -ETIMEDOUT || rc == -EIO ||
1095                     rc == -ENODATA || rc == 0) {
1096                         showdf(mntdir, &stat_buf, uuid_buf.uuid, ishow, cooked,
1097                                "OST", index, rc);
1098                 } else {
1099                         fprintf(stderr,
1100                                 "error: llapi_obd_statfs failed: %s (%d)\n",
1101                                 strerror(-rc), rc);
1102                         return rc;
1103                 }
1104                 if (rc == 0) {
1105                         sum.os_blocks += stat_buf.os_blocks * stat_buf.os_bsize;
1106                         sum.os_bfree  += stat_buf.os_bfree * stat_buf.os_bsize;
1107                         sum.os_bavail += stat_buf.os_bavail * stat_buf.os_bsize;
1108                 }
1109         }
1110
1111         printf("\n");
1112         showdf(mntdir, &sum, "filesystem summary:", ishow, cooked, NULL, 0,0);
1113
1114         return 0;
1115 }
1116
1117 static int lfs_df(int argc, char **argv)
1118 {
1119         FILE *fp;
1120         char *path = NULL;
1121         struct mntent *mnt = NULL;
1122         char *mntdir = NULL;
1123         int ishow = 0, cooked = 0;
1124         int c, rc = 0;
1125
1126         optind = 0;
1127         while ((c = getopt(argc, argv, "ih")) != -1) {
1128                 switch (c) {
1129                 case 'i':
1130                         ishow = 1;
1131                         break;
1132                 case 'h':
1133                         cooked = 1;
1134                         break;
1135                 default:
1136                         return CMD_HELP;
1137                 }
1138         }
1139         if (optind < argc )
1140                 path = argv[optind];
1141
1142         fp = setmntent(MOUNTED, "r");
1143         if (fp == NULL) {
1144                 rc = -errno;
1145                 fprintf(stderr, "error: %s: open %s failed( %s )\n",
1146                         argv[0], MOUNTED, strerror(errno));
1147                 return rc;
1148         }
1149
1150         if ((mntdir = malloc(PATH_MAX)) == NULL) {
1151                 fprintf(stderr, "error: cannot allocate %d bytes\n",
1152                         PATH_MAX);
1153                 return -ENOMEM;
1154         }
1155         memset(mntdir, 0, PATH_MAX);
1156
1157         if (path) {
1158                 rc = path2mnt(path, fp, mntdir, PATH_MAX);
1159                 if (rc) {
1160                         endmntent(fp);
1161                         free(mntdir);
1162                         return rc;
1163                 }
1164
1165                 rc = mntdf(mntdir, ishow, cooked);
1166                 printf("\n");
1167                 endmntent(fp);
1168         } else {
1169                 mnt = getmntent(fp);
1170                 while (feof(fp) == 0 && ferror(fp) == 0) {
1171                         if (llapi_is_lustre_mnt(mnt)) {
1172                                 rc = mntdf(mnt->mnt_dir, ishow, cooked);
1173                                 if (rc)
1174                                         break;
1175                                 printf("\n");
1176                         }
1177                         mnt = getmntent(fp);
1178                 }
1179                 endmntent(fp);
1180         }
1181
1182         free(mntdir);
1183         return rc;
1184 }
1185
1186 static int lfs_check(int argc, char **argv)
1187 {
1188         int rc;
1189         FILE *fp;
1190         struct mntent *mnt = NULL;
1191         int num_types = 1;
1192         char *obd_types[2];
1193         char obd_type1[4];
1194         char obd_type2[4];
1195
1196         if (argc != 2)
1197                 return CMD_HELP;
1198
1199         obd_types[0] = obd_type1;
1200         obd_types[1] = obd_type2;
1201
1202         if (strcmp(argv[1], "osts") == 0) {
1203                 strcpy(obd_types[0], "osc");
1204         } else if (strcmp(argv[1], "mds") == 0) {
1205                 strcpy(obd_types[0], "mdc");
1206         } else if (strcmp(argv[1], "servers") == 0) {
1207                 num_types = 2;
1208                 strcpy(obd_types[0], "osc");
1209                 strcpy(obd_types[1], "mdc");
1210         } else {
1211                 fprintf(stderr, "error: %s: option '%s' unrecognized\n",
1212                                 argv[0], argv[1]);
1213                         return CMD_HELP;
1214         }
1215
1216         fp = setmntent(MOUNTED, "r");
1217         if (fp == NULL) {
1218                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
1219                         strerror (errno));
1220         } else {
1221                 mnt = getmntent(fp);
1222                 while (feof(fp) == 0 && ferror(fp) ==0) {
1223                         if (llapi_is_lustre_mnt(mnt))
1224                                 break;
1225                         mnt = getmntent(fp);
1226                 }
1227                 endmntent(fp);
1228         }
1229
1230         if (!mnt) {
1231                 fprintf(stderr, "No suitable Lustre mount found\n");
1232                 return -1;
1233         }
1234
1235         rc = llapi_target_check(num_types, obd_types, mnt->mnt_dir);
1236
1237         if (rc)
1238                 fprintf(stderr, "error: %s: %s status failed\n",
1239                                 argv[0],argv[1]);
1240
1241         return rc;
1242
1243 }
1244
1245 static int lfs_catinfo(int argc, char **argv)
1246 {
1247         FILE *fp;
1248         struct mntent *mnt = NULL;
1249         int rc;
1250
1251         if (argc < 2 || (!strcmp(argv[1],"config") && argc < 3))
1252                 return CMD_HELP;
1253
1254         if (strcmp(argv[1], "config") && strcmp(argv[1], "deletions"))
1255                 return CMD_HELP;
1256
1257         fp = setmntent(MOUNTED, "r");
1258         if (fp == NULL) {
1259                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
1260                          strerror(errno));
1261         } else {
1262                 mnt = getmntent(fp);
1263                 while (feof(fp) == 0 && ferror(fp) == 0) {
1264                         if (llapi_is_lustre_mnt(mnt))
1265                                 break;
1266                         mnt = getmntent(fp);
1267                 }
1268                 endmntent(fp);
1269         }
1270
1271         if (mnt) {
1272                 if (argc == 3)
1273                         rc = llapi_catinfo(mnt->mnt_dir, argv[1], argv[2]);
1274                 else
1275                         rc = llapi_catinfo(mnt->mnt_dir, argv[1], NULL);
1276         } else {
1277                 fprintf(stderr, "no lustre_lite mounted.\n");
1278                 rc = -1;
1279         }
1280
1281         return rc;
1282 }
1283
1284 int lfs_join(int argc, char **argv)
1285 {
1286         char *name_head, *name_tail;
1287         int fd, rc;
1288         loff_t size;
1289
1290         if (argc != 3)
1291                 return CMD_HELP;
1292         name_head = argv[1];
1293         fd = open(name_head, O_WRONLY);
1294         if (fd < 0) {
1295                 fprintf(stderr, "Can not open name_head %s rc=%d\n",
1296                         name_head, fd);
1297                 return fd;
1298         }
1299         size = lseek(fd, 0, SEEK_END);
1300         if (size % JOIN_FILE_ALIGN) {
1301                 fprintf(stderr,"head file %s size %llu must be mutiple of %d\n",
1302                         name_head, (long long)size, JOIN_FILE_ALIGN);
1303                 rc = -EINVAL;
1304                 goto out;
1305         }
1306         name_tail = argv[2];
1307         rc = ioctl(fd, LL_IOC_JOIN, name_tail);
1308 out:
1309         close(fd);
1310         if (rc) {
1311                 fprintf(stderr, "Lustre joining files: %s, %s, failed\n",
1312                         argv[1], argv[2]);
1313         }
1314         return rc;
1315 }
1316
1317 #ifdef HAVE_QUOTA_SUPPORT
1318 static int lfs_quotachown(int argc, char **argv)
1319 {
1320
1321         int c,rc;
1322         int flag = 0;
1323
1324         optind = 0;
1325         while ((c = getopt(argc, argv, "i")) != -1) {
1326                 switch (c) {
1327                 case 'i':
1328                         flag++;
1329                         break;
1330                 default:
1331                         fprintf(stderr, "error: %s: option '-%c' "
1332                                         "unrecognized\n", argv[0], c);
1333                         return CMD_HELP;
1334                 }
1335         }
1336         if (optind == argc)
1337                 return CMD_HELP;
1338         rc = llapi_quotachown(argv[optind], flag);
1339         if(rc)
1340                 fprintf(stderr,"error: change file owner/group failed.\n");
1341         return rc;
1342 }
1343
1344
1345 static int lfs_quotacheck(int argc, char **argv)
1346 {
1347         int c, check_type = 0;
1348         char *mnt;
1349         struct if_quotacheck qchk;
1350         struct if_quotactl qctl;
1351         char *obd_type = qchk.obd_type;
1352         char *obd_uuid = qchk.obd_uuid.uuid;
1353         int rc;
1354
1355         memset(&qchk, 0, sizeof(qchk));
1356
1357         optind = 0;
1358         while ((c = getopt(argc, argv, "ug")) != -1) {
1359                 switch (c) {
1360                 case 'u':
1361                         check_type |= 0x01;
1362                         break;
1363                 case 'g':
1364                         check_type |= 0x02;
1365                         break;
1366                 default:
1367                         fprintf(stderr, "error: %s: option '-%c' "
1368                                         "unrecognized\n", argv[0], c);
1369                         return CMD_HELP;
1370                 }
1371         }
1372
1373         if (check_type)
1374                 check_type--;
1375         else    /* do quotacheck for both user & group quota by default */
1376                 check_type = 0x02;
1377
1378         if (argc == optind)
1379                 return CMD_HELP;
1380
1381         mnt = argv[optind];
1382
1383         memset(&qctl, 0, sizeof(qctl));
1384         qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
1385         qctl.qc_id = QFMT_LDISKFS;
1386         qctl.qc_type = check_type;
1387         rc = llapi_quotactl(mnt, &qctl);
1388         if (rc) {
1389                 fprintf(stderr, "quota off failed: %s\n", strerror(errno));
1390                 return rc;
1391         }
1392
1393         rc = llapi_quotacheck(mnt, check_type);
1394         if (rc) {
1395                 fprintf(stderr, "quotacheck failed: %s\n", strerror(errno));
1396                 return rc;
1397         }
1398
1399         rc = llapi_poll_quotacheck(mnt, &qchk);
1400         if (rc) {
1401                 if (*obd_type)
1402                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1403                 fprintf(stderr, "quota check failed: %s\n", strerror(errno));
1404                 return rc;
1405         }
1406
1407         memset(&qctl, 0, sizeof(qctl));
1408         qctl.qc_cmd = LUSTRE_Q_QUOTAON;
1409         qctl.qc_id = QFMT_LDISKFS;
1410         qctl.qc_type = check_type;
1411         rc = llapi_quotactl(mnt, &qctl);
1412         if (rc) {
1413                 if (*obd_type)
1414                         fprintf(stderr, "%s %s ",
1415                                 qctl.obd_type, qctl.obd_uuid.uuid);
1416                 fprintf(stderr, "%s turn on quota failed: %s\n",
1417                         argv[0], strerror(errno));
1418                 return rc;
1419         }
1420
1421         return 0;
1422 }
1423
1424 static int lfs_quotaon(int argc, char **argv)
1425 {
1426         int c;
1427         char *mnt;
1428         struct if_quotactl qctl;
1429         char *obd_type = qctl.obd_type;
1430         char *obd_uuid = qctl.obd_uuid.uuid;
1431         int rc;
1432
1433         memset(&qctl, 0, sizeof(qctl));
1434         qctl.qc_cmd = LUSTRE_Q_QUOTAON;
1435         qctl.qc_id = QFMT_LDISKFS;
1436
1437         optind = 0;
1438         while ((c = getopt(argc, argv, "ugf")) != -1) {
1439                 switch (c) {
1440                 case 'u':
1441                         qctl.qc_type |= 0x01;
1442                         break;
1443                 case 'g':
1444                         qctl.qc_type |= 0x02;
1445                         break;
1446                 case 'f':
1447                         qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
1448                         break;
1449                 default:
1450                         fprintf(stderr, "error: %s: option '-%c' "
1451                                         "unrecognized\n", argv[0], c);
1452                         return CMD_HELP;
1453                 }
1454         }
1455
1456         if (qctl.qc_type)
1457                 qctl.qc_type--;
1458         else /* by default, enable quota for both user & group */
1459                 qctl.qc_type = 0x02;
1460
1461         if (argc == optind)
1462                 return CMD_HELP;
1463
1464         mnt = argv[optind];
1465
1466         rc = llapi_quotactl(mnt, &qctl);
1467         if (rc) {
1468                 if (*obd_type)
1469                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1470                 fprintf(stderr, "%s failed: %s\n", argv[0], strerror(errno));
1471                 return rc;
1472         }
1473
1474         return 0;
1475 }
1476
1477 static int lfs_quotaoff(int argc, char **argv)
1478 {
1479         int c;
1480         char *mnt;
1481         struct if_quotactl qctl;
1482         char *obd_type = qctl.obd_type;
1483         char *obd_uuid = qctl.obd_uuid.uuid;
1484         int rc;
1485
1486         memset(&qctl, 0, sizeof(qctl));
1487         qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
1488
1489         optind = 0;
1490         while ((c = getopt(argc, argv, "ug")) != -1) {
1491                 switch (c) {
1492                 case 'u':
1493                         qctl.qc_type |= 0x01;
1494                         break;
1495                 case 'g':
1496                         qctl.qc_type |= 0x02;
1497                         break;
1498                 default:
1499                         fprintf(stderr, "error: %s: option '-%c' "
1500                                         "unrecognized\n", argv[0], c);
1501                         return CMD_HELP;
1502                 }
1503         }
1504
1505         if (qctl.qc_type)
1506                 qctl.qc_type--;
1507         else /* by default, disable quota for both user & group */
1508                 qctl.qc_type = 0x02;
1509
1510         if (argc == optind)
1511                 return CMD_HELP;
1512
1513         mnt = argv[optind];
1514
1515         rc = llapi_quotactl(mnt, &qctl);
1516         if (rc) {
1517                 if (*obd_type)
1518                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1519                 fprintf(stderr, "quotaoff failed: %s\n", strerror(errno));
1520                 return rc;
1521         }
1522
1523         return 0;
1524 }
1525
1526 #define ARG2INT(nr, str, msg)                                           \
1527 do {                                                                    \
1528         char *endp;                                                     \
1529         nr = strtol(str, &endp, 0);                                     \
1530         if (*endp) {                                                    \
1531                 fprintf(stderr, "error: bad %s: %s\n", msg, str);       \
1532                 return CMD_HELP;                                        \
1533         }                                                               \
1534 } while (0)
1535
1536 #define ADD_OVERFLOW(a,b) ((a + b) < a) ? (a = ULONG_MAX) : (a = a + b)
1537
1538 /* Convert format time string "XXwXXdXXhXXmXXs" into seconds value
1539  * returns the value or ULONG_MAX on integer overflow or incorrect format
1540  * Notes:
1541  *        1. the order of specifiers is arbitrary (may be: 5w3s or 3s5w)
1542  *        2. specifiers may be encountered multiple times (2s3s is 5 seconds)
1543  *        3. empty integer value is interpreted as 0
1544  */
1545
1546 static unsigned long str2sec(const char* timestr) {
1547         const char spec[] = "smhdw";
1548         const unsigned long mult[] = {1, 60, 60*60, 24*60*60, 7*24*60*60};
1549         unsigned long val = 0;
1550         char *tail;
1551
1552         if (strpbrk(timestr, spec) == NULL) {
1553                 /* no specifiers inside the time string,
1554                    should treat it as an integer value */
1555                 val = strtoul(timestr, &tail, 10);
1556                 return *tail ? ULONG_MAX : val;
1557         }
1558
1559         /* format string is XXwXXdXXhXXmXXs */
1560         while (*timestr) {
1561                 unsigned long v;
1562                 int ind;
1563                 char* ptr;
1564
1565                 v = strtoul(timestr, &tail, 10);
1566                 if (v == ULONG_MAX || *tail == '\0')
1567                         /* value too large (ULONG_MAX or more)
1568                            or missing specifier */
1569                         goto error;
1570
1571                 ptr = strchr(spec, *tail);
1572                 if (ptr == NULL)
1573                         /* unknown specifier */
1574                         goto error;
1575
1576                 ind = ptr - spec;
1577
1578                 /* check if product will overflow the type */
1579                 if (!(v < ULONG_MAX / mult[ind]))
1580                         goto error;
1581
1582                 ADD_OVERFLOW(val, mult[ind] * v);
1583                 if (val == ULONG_MAX)
1584                         goto error;
1585
1586                 timestr = tail + 1;
1587         }
1588
1589         return val;
1590
1591 error:
1592         return ULONG_MAX;
1593 }
1594
1595 int lfs_setquota(int argc, char **argv)
1596 {
1597         int c;
1598         char *mnt;
1599         struct if_quotactl qctl;
1600         char *obd_type = qctl.obd_type;
1601         char *obd_uuid = qctl.obd_uuid.uuid;
1602         int rc;
1603
1604         memset(&qctl, 0, sizeof(qctl));
1605         qctl.qc_cmd = LUSTRE_Q_SETQUOTA;
1606
1607         optind = 0;
1608         while ((c = getopt(argc, argv, "ugt")) != -1) {
1609                 switch (c) {
1610                 case 'u':
1611                         qctl.qc_type |= 0x01;
1612                         break;
1613                 case 'g':
1614                         qctl.qc_type |= 0x02;
1615                         break;
1616                 case 't':
1617                         qctl.qc_cmd = LUSTRE_Q_SETINFO;
1618                         break;
1619                 default:
1620                         fprintf(stderr, "error: %s: option '-%c' "
1621                                         "unrecognized\n", argv[0], c);
1622                         return CMD_HELP;
1623                 }
1624         }
1625
1626         if (qctl.qc_type)
1627                 qctl.qc_type--;
1628
1629         if (qctl.qc_type == UGQUOTA) {
1630                 fprintf(stderr, "error: user and group quotas can't be set "
1631                                 "both\n");
1632                 return CMD_HELP;
1633         }
1634
1635         if (qctl.qc_cmd == LUSTRE_Q_SETQUOTA) {
1636                 struct obd_dqblk *dqb = &qctl.qc_dqblk;
1637
1638                 if (optind + 6 != argc)
1639                         return CMD_HELP;
1640
1641                 rc = name2id(&qctl.qc_id, argv[optind++], qctl.qc_type);
1642                 if (rc) {
1643                         fprintf(stderr, "error: find id for name %s failed: %s\n",
1644                                 argv[optind - 1], strerror(errno));
1645                         return CMD_HELP;
1646                 }
1647
1648                 ARG2INT(dqb->dqb_bsoftlimit, argv[optind++], "block-softlimit");
1649                 ARG2INT(dqb->dqb_bhardlimit, argv[optind++], "block-hardlimit");
1650                 ARG2INT(dqb->dqb_isoftlimit, argv[optind++], "inode-softlimit");
1651                 ARG2INT(dqb->dqb_ihardlimit, argv[optind++], "inode-hardlimit");
1652
1653                 dqb->dqb_valid = QIF_LIMITS;
1654         } else {
1655                 struct obd_dqinfo *dqi = &qctl.qc_dqinfo;
1656
1657                 if (optind + 3 != argc)
1658                         return CMD_HELP;
1659
1660                 if ((dqi->dqi_bgrace = str2sec(argv[optind++])) == ULONG_MAX) {
1661                         fprintf(stderr, "error: bad %s: %s\n", "block-grace", argv[optind - 1]);
1662                         return CMD_HELP;
1663                 }
1664                 if ((dqi->dqi_igrace = str2sec(argv[optind++])) == ULONG_MAX) {
1665                         fprintf(stderr, "error: bad %s: %s\n", "inode-grace", argv[optind - 1]);
1666                         return CMD_HELP;
1667                 }
1668         }
1669
1670         mnt = argv[optind];
1671
1672         rc = llapi_quotactl(mnt, &qctl);
1673         if (rc) {
1674                 if (*obd_type)
1675                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1676                 fprintf(stderr, "setquota failed: %s\n", strerror(errno));
1677                 return rc;
1678         }
1679
1680         return 0;
1681 }
1682
1683 static inline char *type2name(int check_type)
1684 {
1685         if (check_type == USRQUOTA)
1686                 return "user";
1687         else if (check_type == GRPQUOTA)
1688                 return "group";
1689         else
1690                 return "unknown";
1691 }
1692
1693
1694 /* Converts seconds value into format string
1695  * result is returned in buf
1696  * Notes:
1697  *        1. result is in descenting order: 1w2d3h4m5s
1698  *        2. zero fields are not filled (except for p. 3): 5d1s
1699  *        3. zero seconds value is presented as "0s"
1700  */
1701 static void sec2str(time_t seconds, char *buf)
1702 {
1703         const char spec[] = "smhdw";
1704         const unsigned long mult[] = {1, 60, 60*60, 24*60*60, 7*24*60*60};
1705         unsigned long c;
1706         char* tail = buf;
1707         int i;
1708
1709         for (i = sizeof(mult) / sizeof(mult[0]) - 1 ; i >= 0; i--) {
1710                 c = seconds / mult[i];
1711
1712                 if (c > 0 || (i == 0 && buf == tail))
1713                         tail += snprintf(tail, 40-(tail-buf), "%lu%c", c, spec[i]);
1714
1715                 seconds %= mult[i];
1716         }
1717 }
1718
1719
1720 static void diff2str(time_t seconds, char *buf, time_t now)
1721 {
1722
1723         buf[0] = 0;
1724         if (!seconds)
1725                 return;
1726         if (seconds <= now) {
1727                 strcpy(buf, "none");
1728                 return;
1729         }
1730         sec2str(seconds - now, buf);
1731 }
1732
1733 static void print_quota_title(char *name, struct if_quotactl *qctl)
1734 {
1735         printf("Disk quotas for %s %s (%cid %u):\n",
1736                type2name(qctl->qc_type), name,
1737                *type2name(qctl->qc_type), qctl->qc_id);
1738         printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n",
1739                "Filesystem",
1740                "kbytes", "quota", "limit", "grace",
1741                "files", "quota", "limit", "grace");
1742 }
1743
1744 static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
1745 {
1746         time_t now;
1747
1748         time(&now);
1749
1750         if (qctl->qc_cmd == LUSTRE_Q_GETQUOTA || qctl->qc_cmd == Q_GETOQUOTA) {
1751                 int bover = 0, iover = 0;
1752                 struct obd_dqblk *dqb = &qctl->qc_dqblk;
1753
1754                 if (dqb->dqb_bhardlimit &&
1755                     toqb(dqb->dqb_curspace) > dqb->dqb_bhardlimit) {
1756                         bover = 1;
1757                 } else if (dqb->dqb_bsoftlimit &&
1758                            toqb(dqb->dqb_curspace) > dqb->dqb_bsoftlimit) {
1759                         if (dqb->dqb_btime > now) {
1760                                 bover = 2;
1761                         } else {
1762                                 bover = 3;
1763                         }
1764                 }
1765
1766                 if (dqb->dqb_ihardlimit &&
1767                     dqb->dqb_curinodes > dqb->dqb_ihardlimit) {
1768                         iover = 1;
1769                 } else if (dqb->dqb_isoftlimit &&
1770                            dqb->dqb_curinodes > dqb->dqb_isoftlimit) {
1771                         if (dqb->dqb_btime > now) {
1772                                 iover = 2;
1773                         } else {
1774                                 iover = 3;
1775                         }
1776                 }
1777
1778 #if 0           /* XXX: always print quotas even when no usages */
1779                 if (dqb->dqb_curspace || dqb->dqb_curinodes)
1780 #endif
1781                 {
1782                         char numbuf[3][32];
1783                         char timebuf[40];
1784
1785                         if (strlen(mnt) > 15)
1786                                 printf("%s\n%15s", mnt, "");
1787                         else
1788                                 printf("%15s", mnt);
1789
1790                         if (bover)
1791                                 diff2str(dqb->dqb_btime, timebuf, now);
1792
1793                         sprintf(numbuf[0], LPU64, toqb(dqb->dqb_curspace));
1794                         sprintf(numbuf[1], LPU64, dqb->dqb_bsoftlimit);
1795                         sprintf(numbuf[2], LPU64, dqb->dqb_bhardlimit);
1796                         printf(" %7s%c %6s %7s %7s",
1797                                numbuf[0], bover ? '*' : ' ', numbuf[1],
1798                                numbuf[2], bover > 1 ? timebuf : "");
1799
1800                         if (iover)
1801                                 diff2str(dqb->dqb_itime, timebuf, now);
1802
1803                         sprintf(numbuf[0], LPU64, dqb->dqb_curinodes);
1804                         sprintf(numbuf[1], LPU64, dqb->dqb_isoftlimit);
1805                         sprintf(numbuf[2], LPU64, dqb->dqb_ihardlimit);
1806                         if (!ost_only)
1807                                 printf(" %7s%c %6s %7s %7s",
1808                                        numbuf[0], iover ? '*' : ' ', numbuf[1],
1809                                        numbuf[2], iover > 1 ? timebuf : "");
1810                         printf("\n");
1811                 }
1812         } else if (qctl->qc_cmd == LUSTRE_Q_GETINFO ||
1813                    qctl->qc_cmd == Q_GETOINFO) {
1814                 char bgtimebuf[40];
1815                 char igtimebuf[40];
1816
1817                 sec2str(qctl->qc_dqinfo.dqi_bgrace, bgtimebuf);
1818                 sec2str(qctl->qc_dqinfo.dqi_igrace, igtimebuf);
1819                 printf("Block grace time: %s; Inode grace time: %s\n",
1820                        bgtimebuf, igtimebuf);
1821         }
1822 }
1823
1824 static void print_mds_quota(char *mnt, struct if_quotactl *qctl)
1825 {
1826         int rc;
1827
1828         /* XXX: this is a flag to mark that only mds quota is wanted */
1829         qctl->qc_dqblk.dqb_valid = 1;
1830         rc = llapi_quotactl(mnt, qctl);
1831         if (rc) {
1832                 fprintf(stderr, "quotactl failed: %s\n", strerror(errno));
1833                 return;
1834         }
1835         qctl->qc_dqblk.dqb_valid = 0;
1836
1837         print_quota(qctl->obd_uuid.uuid, qctl, 0);
1838 }
1839
1840 static void print_lov_quota(char *mnt, struct if_quotactl *qctl)
1841 {
1842         DIR *dir;
1843         struct obd_uuid *uuids = NULL, *uuidp;
1844         int obdcount = 1024;
1845         int i, rc;
1846
1847         dir = opendir(mnt);
1848         if (!dir) {
1849                 fprintf(stderr, "open %s failed: %s\n", mnt, strerror(errno));
1850                 return;
1851         }
1852
1853         uuids = (struct obd_uuid *)malloc(INIT_ALLOC_NUM_OSTS *
1854                                           sizeof(struct obd_uuid));
1855         if (uuids == NULL)
1856                 goto out;
1857
1858 retry_get_uuids:
1859         rc = llapi_lov_get_uuids(dirfd(dir), uuids, &obdcount);
1860         if (rc != 0) {
1861                 struct obd_uuid *uuids_temp;
1862
1863                 if (rc == -EOVERFLOW) {
1864                         uuids_temp = realloc(uuids, obdcount *
1865                                              sizeof(struct obd_uuid));
1866                         if (uuids_temp != NULL)
1867                                 goto retry_get_uuids;
1868                         else
1869                                 rc = -ENOMEM;
1870                 }
1871
1872                 fprintf(stderr, "get ost uuid failed: %s\n", strerror(rc));
1873                 goto out;
1874         }
1875
1876         for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
1877                 memcpy(&qctl->obd_uuid, uuidp, sizeof(*uuidp));
1878
1879                 /* XXX clear this flag to get quota from osts */
1880                 qctl->qc_dqblk.dqb_valid = 0;
1881                 rc = llapi_quotactl(mnt, qctl);
1882                 if (rc) {
1883                         fprintf(stderr, "%s quotactl failed: %s\n",
1884                                 uuidp->uuid, strerror(errno));
1885                         continue;
1886                 }
1887
1888                 print_quota(uuidp->uuid, qctl, 1);
1889         }
1890
1891 out:
1892         closedir(dir);
1893         return;
1894 }
1895
1896 static int lfs_quota(int argc, char **argv)
1897 {
1898         int c;
1899         char *name = NULL, *mnt;
1900         struct if_quotactl qctl = { .qc_cmd = LUSTRE_Q_GETQUOTA,
1901                                     .qc_type = 0x01 };
1902         char *obd_type = qctl.obd_type;
1903         char *obd_uuid = qctl.obd_uuid.uuid;
1904         int rc;
1905
1906         optind = 0;
1907         while ((c = getopt(argc, argv, "ugto:")) != -1) {
1908                 switch (c) {
1909                 case 'u':
1910                         qctl.qc_type = 0x01;
1911                         break;
1912                 case 'g':
1913                         qctl.qc_type = 0x02;
1914                         break;
1915                 case 't':
1916                         qctl.qc_cmd = LUSTRE_Q_GETINFO;
1917                         break;
1918                 case 'o':
1919                         strncpy(obd_uuid, optarg, sizeof(qctl.obd_uuid));
1920                         break;
1921                 default:
1922                         fprintf(stderr, "error: %s: option '-%c' "
1923                                         "unrecognized\n", argv[0], c);
1924                         return CMD_HELP;
1925                 }
1926         }
1927
1928         if (qctl.qc_type)
1929                 qctl.qc_type--;
1930
1931
1932         if (qctl.qc_cmd == LUSTRE_Q_GETQUOTA) {
1933                 if (optind + 2 != argc) {
1934                         fprintf(stderr, "error: missing quota argument(s)\n");
1935                         return CMD_HELP;
1936                 }
1937
1938                 name = argv[optind++];
1939                 rc = name2id(&qctl.qc_id, name, qctl.qc_type);
1940                 if (rc) {
1941                         fprintf(stderr,"error: can't find id for name %s: %s\n",
1942                                 name, strerror(errno));
1943                         return CMD_HELP;
1944                 }
1945                 print_quota_title(name, &qctl);
1946         } else if (optind + 1 != argc) {
1947                 fprintf(stderr, "error: missing quota info argument(s)\n");
1948                 return CMD_HELP;
1949         }
1950
1951         mnt = argv[optind];
1952
1953         rc = llapi_quotactl(mnt, &qctl);
1954         if (rc) {
1955                 if (*obd_type)
1956                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1957                 fprintf(stderr, "quota failed: %s\n", strerror(errno));
1958                 return rc;
1959         }
1960
1961         if (!name)
1962                 rc = id2name(&name, getuid(), qctl.qc_type);
1963
1964         if (*obd_uuid) {
1965                 mnt = "";
1966                 name = obd_uuid;
1967         }
1968
1969         print_quota(mnt, &qctl, 0);
1970
1971         if (!*obd_uuid && qctl.qc_cmd != LUSTRE_Q_GETINFO) {
1972                 print_mds_quota(mnt, &qctl);
1973                 print_lov_quota(mnt, &qctl);
1974         }
1975
1976         return 0;
1977 }
1978 #endif /* HAVE_QUOTA_SUPPORT */
1979
1980 static int flushctx_ioctl(char *mp)
1981 {
1982         int fd, rc;
1983
1984         fd = open(mp, O_RDONLY);
1985         if (fd == -1) {
1986                 fprintf(stderr, "flushctx: error open %s: %s\n",
1987                         mp, strerror(errno));
1988                 return -1;
1989         }
1990
1991         rc = ioctl(fd, LL_IOC_FLUSHCTX);
1992         if (rc == -1)
1993                 fprintf(stderr, "flushctx: error ioctl %s: %s\n",
1994                         mp, strerror(errno));
1995
1996         close(fd);
1997         return rc;
1998 }
1999
2000 static int lfs_flushctx(int argc, char **argv)
2001 {
2002         int     kdestroy = 0, c;
2003         FILE   *proc;
2004         char    procline[PATH_MAX], *line;
2005         int     rc = 0;
2006
2007         optind = 0;
2008         while ((c = getopt(argc, argv, "k")) != -1) {
2009                 switch (c) {
2010                 case 'k':
2011                         kdestroy = 1;
2012                         break;
2013                 default:
2014                         fprintf(stderr, "error: %s: option '-%c' "
2015                                         "unrecognized\n", argv[0], c);
2016                         return CMD_HELP;
2017                 }
2018         }
2019
2020         if (kdestroy)
2021                 system("kdestroy > /dev/null");
2022
2023         if (optind >= argc) {
2024                 /* flush for all mounted lustre fs. */
2025                 proc = fopen("/proc/mounts", "r");
2026                 if (!proc) {
2027                         fprintf(stderr, "error: %s: can't open /proc/mounts\n",
2028                                 argv[0]);
2029                         return -1;
2030                 }
2031
2032                 while ((line = fgets(procline, PATH_MAX, proc)) != NULL) {
2033                         char dev[PATH_MAX];
2034                         char mp[PATH_MAX];
2035                         char fs[PATH_MAX];
2036
2037                         if (sscanf(line, "%s %s %s", dev, mp, fs) != 3) {
2038                                 fprintf(stderr, "%s: unexpected format in "
2039                                                 "/proc/mounts\n",
2040                                         argv[0]);
2041                                 return -1;
2042                         }
2043
2044                         if (strcmp(fs, "lustre") != 0)
2045                                 continue;
2046                         /* we use '@' to determine it's a client. are there
2047                          * any other better way?
2048                          */
2049                         if (strchr(dev, '@') == NULL)
2050                                 continue;
2051
2052                         if (flushctx_ioctl(mp))
2053                                 rc = -1;
2054                 }
2055         } else {
2056                 /* flush fs as specified */
2057                 while (optind < argc) {
2058                         if (flushctx_ioctl(argv[optind++]))
2059                                 rc = -1;
2060                 }
2061         }
2062
2063         return rc;
2064 }
2065
2066 static int lfs_lsetfacl(int argc, char **argv)
2067 {
2068         argv[0]++;
2069         return(llapi_lsetfacl(argc, argv));
2070 }
2071
2072 static int lfs_lgetfacl(int argc, char **argv)
2073 {
2074         argv[0]++;
2075         return(llapi_lgetfacl(argc, argv));
2076 }
2077
2078 static int lfs_rsetfacl(int argc, char **argv)
2079 {
2080         argv[0]++;
2081         return(llapi_rsetfacl(argc, argv));
2082 }
2083
2084 static int lfs_rgetfacl(int argc, char **argv)
2085 {
2086         argv[0]++;
2087         return(llapi_rgetfacl(argc, argv));
2088 }
2089
2090 static int lfs_cp(int argc, char **argv)
2091 {
2092         return(llapi_cp(argc, argv));
2093 }
2094
2095 static int lfs_ls(int argc, char **argv)
2096 {
2097         return(llapi_ls(argc, argv));
2098 }
2099
2100 int main(int argc, char **argv)
2101 {
2102         int rc;
2103
2104         setlinebuf(stdout);
2105
2106         ptl_initialize(argc, argv);
2107         if (obd_initialize(argc, argv) < 0)
2108                 exit(2);
2109         if (dbg_initialize(argc, argv) < 0)
2110                 exit(3);
2111
2112         Parser_init("lfs > ", cmdlist);
2113
2114         if (argc > 1) {
2115                 rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
2116         } else {
2117                 rc = Parser_commands();
2118         }
2119
2120         obd_finalize(argc, argv);
2121         return rc;
2122 }