Whamcloud - gitweb
05f29195b988946606099525745e973615494e75
[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  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Robert Read <rread@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <getopt.h>
30 #include <string.h>
31 #include <mntent.h>
32 #include <errno.h>
33 #include <pwd.h>
34 #include <grp.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <dirent.h>
39 #include <time.h>
40
41 #include <lnet/api-support.h>
42 #include <lnet/lnetctl.h>
43
44 #include <liblustre.h>
45 #include <lustre/lustre_idl.h>
46 #include <lustre/liblustreapi.h>
47 #include <lustre/lustre_user.h>
48
49 #include "parser.h"
50 #include "obdctl.h"
51
52 unsigned int libcfs_subsystem_debug = 0;
53
54 /* all functions */
55 static int lfs_setstripe(int argc, char **argv);
56 static int lfs_find(int argc, char **argv);
57 static int lfs_getstripe(int argc, char **argv);
58 static int lfs_osts(int argc, char **argv);
59 static int lfs_df(int argc, char **argv);
60 static int lfs_check(int argc, char **argv);
61 static int lfs_catinfo(int argc, char **argv);
62 #ifdef HAVE_QUOTA_SUPPORT
63 static int lfs_quotachown(int argc, char **argv);
64 static int lfs_quotacheck(int argc, char **argv);
65 static int lfs_quotaon(int argc, char **argv);
66 static int lfs_quotaoff(int argc, char **argv);
67 static int lfs_setquota(int argc, char **argv);
68 static int lfs_quota(int argc, char **argv);
69 #endif
70 static int lfs_join(int argc, char **argv);
71
72 /* all avaialable commands */
73 command_t cmdlist[] = {
74         {"setstripe", lfs_setstripe, 0,
75          "Create a new file with a specific striping pattern or\n"
76          "set the default striping pattern on an existing directory or\n"
77          "delete the default striping pattern from an existing directory\n"
78          "usage: setstripe <filename|dirname> <stripe_size> <stripe_index> <stripe_count>\n"
79          "       or \n"
80          "       setstripe <filename|dirname> [--size|-s stripe_size]\n"
81          "                                    [--index|-i stripe_index]\n"
82          "                                    [--count|-c stripe_count]\n"
83          "       or \n"
84          "       setstripe -d <dirname>   (to delete default striping)\n"
85          "\tstripe_size:  Number of bytes on each OST (0 filesystem default)\n"
86          "\tstripe_index: OST index of first stripe (-1 filesystem default)\n"
87          "\tstripe_count: Number of OSTs to stripe over (0 default, -1 all)"},
88         {"getstripe", lfs_getstripe, 0,
89          "To list the striping info for a given filename or files in a\n"
90          "directory or recursively for all files in a directory tree.\n"
91          "usage: getstripe [--obd|-O <uuid>] [--quiet | -q] [--verbose | -v]\n"
92          "                 [--recursive | -r] <dir|file> ..."},
93         {"find", lfs_find, 0,
94          "To find files that match given parameters recursively in a directory tree.\n"
95          "usage: find <dir/file> ... \n"
96          "     [[!] --atime|-A N] [[!] --mtime|-M N] [[!] --ctime|-C N] [--maxdepth|-D N]\n"
97          "     [[!] --name|-n <pattern>] [--print0|-P] [--print|-p] [--obd|-O <uuid>]\n"
98          "\t !: used before --atime, --mtime, --ctime specifies the negative value\n"
99          "\t !: used before --name means find exclude the regular expression pattern\n"
100          "If one of the options below is provided, find works the same as 'getstripe':\n"
101          "To list the striping info for a given filename or files in a directory or\n"
102          "recursively.\n"
103          "OBSOLETE usage: find [--quiet | -q] [--verbose | -v]\n"
104          "                     [--recursive | -r] <dir|file> ..."},
105         {"check", lfs_check, 0,
106          "Display the status of MDS or OSTs (as specified in the command)\n"
107          "or all the servers (MDS and OSTs).\n"
108          "usage: check <osts|mds|servers>"},
109         {"catinfo", lfs_catinfo, 0,
110          "Show information of specified type logs.\n"
111          "usage: catinfo {keyword} [node name]\n"
112          "\tkeywords are one of followings: config, deletions.\n"
113          "\tnode name must be provided when use keyword config."},
114         {"join", lfs_join, 0,
115          "join two lustre files into one - join A, B, will be like cat B >> A & del B\n"
116          "usage: join <filename_A> <filename_B>\n"},
117         {"osts", lfs_osts, 0, "osts"},
118         {"df", lfs_df, 0,
119          "report filesystem disk space usage or inodes usage"
120          "of each MDS/OSD.\n"
121          "Usage: df [-i] [-h] [path]"},
122 #ifdef HAVE_QUOTA_SUPPORT
123         {"quotachown",lfs_quotachown, 0,
124          "Change files' owner or group on the specified filesystem.\n"
125          "usage: quotachown [-i] <filesystem>\n"
126          "\t-i: ignore error if file is not exist\n"},
127         {"quotacheck", lfs_quotacheck, 0,
128          "Scan the specified filesystem for disk usage, and create,\n"
129          "or update quota files.\n"
130          "usage: quotacheck [ -ug ] <filesystem>"},
131         {"quotaon", lfs_quotaon, 0, "Turn filesystem quotas on.\n"
132          "usage: quotaon [ -ugf ] <filesystem>"},
133         {"quotaoff", lfs_quotaoff, 0, "Turn filesystem quotas off.\n"
134          "usage: quotaoff [ -ug ] <filesystem>"},
135         {"setquota", lfs_setquota, 0, "Set filesystem quotas.\n"
136          "usage: setquota [ -u | -g ] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>\n"
137          "       setquota -t [ -u | -g ] <block-grace> <inode-grace> <filesystem>"},
138         {"quota", lfs_quota, 0, "Display disk usage and limits.\n"
139          "usage: quota [ -o obd_uuid ] [ -u | -g ] [name] <filesystem>"},
140 #endif
141         {"help", Parser_help, 0, "help"},
142         {"exit", Parser_quit, 0, "quit"},
143         {"quit", Parser_quit, 0, "quit"},
144         { 0, 0, 0, NULL }
145 };
146
147 /* functions */
148 static int lfs_setstripe(int argc, char **argv)
149 {
150         char *fname;
151         int result;
152         long st_size;
153         int  st_offset, st_count;
154         char *end;
155         int c;
156         int delete = 0;
157         char *stripe_size_arg = NULL;
158         char *stripe_off_arg = NULL;
159         char *stripe_count_arg = NULL;
160
161         struct option long_opts[] = {
162                 {"size",        required_argument, 0, 's'},
163                 {"count",       required_argument, 0, 'c'},
164                 {"index",       required_argument, 0, 'i'},
165                 {"delete",      no_argument,       0, 'd'},
166                 {0, 0, 0, 0}
167         };
168
169         st_size = 0;
170         st_offset = -1;
171         st_count = 0;
172         if (argc == 3 && strcmp(argv[1], "-d") == 0) {
173                 /* for compatibility with the existing positional parameter
174                  * usage */
175                 fname = argv[2];
176                 optind = 2;
177         } else if (argc == 5  && 
178                    (argv[2][0] != '-' || isdigit(argv[2][1])) &&
179                    (argv[3][0] != '-' || isdigit(argv[3][1])) &&
180                    (argv[4][0] != '-' || isdigit(argv[4][1])) ) {
181                 /* for compatibility with the existing positional parameter
182                  * usage */
183                 fname = argv[1];
184                 stripe_size_arg = argv[2];
185                 stripe_off_arg = argv[3];
186                 stripe_count_arg = argv[4];
187                 optind = 4;
188         } else {
189                 while ((c = getopt_long(argc, argv, "c:di:s:",
190                                                 long_opts, NULL)) >= 0) 
191                 {
192                         switch (c) {
193                         case 0:
194                                 /* Long options. */
195                                 break;
196                         case 'c':
197                                 stripe_count_arg = optarg;
198                                 break;
199                         case 'd':
200                                 /* delete the default striping pattern */
201                                 delete = 1;
202                                 break;
203                         case 'i':
204                                 stripe_off_arg = optarg;
205                                 break;
206                         case 's':
207                                 stripe_size_arg = optarg;
208                                 break;
209                         case '?':
210                                 return CMD_HELP;
211                         default:
212                                 fprintf(stderr, "error: %s: option '%s' "
213                                                 "unrecognized\n",
214                                                 argv[0], argv[optind - 1]);
215                                 return CMD_HELP;
216                         }
217                 }
218
219                 if (optind < argc)
220                         fname = argv[optind];
221                 else
222                         return CMD_HELP;
223
224                 if (delete && 
225                     (stripe_size_arg != NULL || stripe_off_arg != NULL || 
226                      stripe_count_arg != NULL)) {
227                         fprintf(stderr, "error: %s: cannot specify -d with "
228                                         "-s, -c or -i options\n",
229                                         argv[0]);
230                         return CMD_HELP;
231                 }
232         }
233
234         if (optind != argc - 1) {
235                 fprintf(stderr, "error: %s: only 1 filename|dirname can be "
236                                 "specified: '%s'\n",
237                                 argv[0], argv[argc-1]);
238                 return CMD_HELP;
239         }
240
241         /* get the stripe size */
242         if (stripe_size_arg != NULL) {
243                 st_size = strtoul(stripe_size_arg, &end, 0);
244                 if (*end != '\0') {
245                         fprintf(stderr, "error: %s: bad stripe size '%s'\n",
246                                         argv[0], stripe_size_arg);
247                         return CMD_HELP;
248                 }
249         }
250         /* get the stripe offset */
251         if (stripe_off_arg != NULL) {
252                 st_offset = strtoul(stripe_off_arg, &end, 0);
253                 if (*end != '\0') {
254                         fprintf(stderr, "error: %s: bad stripe offset '%s'\n",
255                                         argv[0], stripe_off_arg);
256                         return CMD_HELP;
257                 }
258         }
259         /* get the stripe count */
260         if (stripe_count_arg != NULL) {
261                 st_count = strtoul(stripe_count_arg, &end, 0);
262                 if (*end != '\0') {
263                         fprintf(stderr, "error: %s: bad stripe count '%s'\n",
264                                         argv[0], stripe_count_arg);
265                         return CMD_HELP;
266                 }
267         }
268
269         result = llapi_file_create(fname, st_size, st_offset, st_count, 0);
270         if (result)
271                 fprintf(stderr, "error: %s: create stripe file failed\n",
272                                 argv[0]);
273
274         return result;
275 }
276
277 static int set_time(time_t *time, time_t *set, char *str)
278 {
279         time_t t;
280         int res = 0;
281         
282         if (str[0] == '+')
283                 res = 1;
284         else if (str[0] == '-')
285                 res = -1;
286
287         if (res)
288                 str++;
289
290         t = strtol(str, NULL, 0);
291         if (*time < t * 24 * 60 * 60) {
292                 if (res)
293                         str--;
294                 fprintf(stderr, "Wrong time '%s' is specified.\n", str);
295                 return INT_MAX;
296         }
297
298         *set = *time - t * 24 * 60 * 60;
299         return res;
300 }
301
302 static int lfs_find(int argc, char **argv)
303 {
304         int new_fashion = 1;
305         int c, ret;
306         int zeroend;
307         time_t t;
308         unsigned int depth;
309         int quiet, verbose, recursive;
310         struct find_param param;
311         struct obd_uuid *obduuid = NULL;
312         char timestr[1024];
313         struct option long_opts[] = {
314                 /* New find options. */
315                 {"atime",     required_argument, 0, 'A'},
316                 {"ctime",     required_argument, 0, 'C'},
317                 {"mtime",     required_argument, 0, 'M'},
318                 {"maxdepth",  required_argument, 0, 'D'},
319                 {"name",      required_argument, 0, 'n'},
320                 /* --obd is considered as a new option. */
321                 {"obd",       required_argument, 0, 'O'},
322                 {"ost",       required_argument, 0, 'O'},
323                 {"print",     no_argument,       0, 'P'},
324                 {"print0",    no_argument,       0, 'p'},
325                 /* Old find options. */
326                 {"quiet",     no_argument,       0, 'q'},
327                 {"recursive", no_argument,       0, 'r'},
328                 {"verbose",   no_argument,       0, 'v'},
329                 {0, 0, 0, 0}
330         };
331         int pathstart = -1;
332         int pathend = -1;
333         int neg_opt = 0;
334         time_t *xtime;
335         int *xsign;
336         int isoption;
337
338         time(&t);
339         zeroend = 0;
340         depth = -1;
341         quiet = verbose = recursive = 0;
342
343         memset(&param, 0, sizeof(param));
344
345         while ((c = getopt_long_only(argc, argv, "-A:C:D:M:n:PpOqrv",
346                                      long_opts, NULL)) >= 0)
347         {
348                 xtime = NULL;
349                 xsign = NULL;
350                 if (neg_opt)
351                         --neg_opt;
352                 /* '!' is part of option */
353                 isoption = (c != 1) || (strcmp(optarg, "!") == 0);
354                 if (!isoption && pathend != -1) {
355                         fprintf(stderr, "err: %s: filename|dirname must either "
356                                         "precede options or follow options\n",
357                                         argv[0]);
358                         return CMD_HELP;
359                 }
360                 if (!isoption && pathstart == -1)
361                         pathstart = optind - 1;
362                 if (isoption && pathstart != -1 && pathend == -1) {
363                         pathend = optind - 2;
364                         if ((c == 1 && strcmp(optarg, "!") == 0) ||
365                             c == 'P' || c == 'p' || c == 'O' ||
366                             c == 'q' || c == 'r' || c == 'v')
367                                 pathend = optind - 1;
368                 }
369                 switch (c) {
370                 case 0:
371                         /* Long options. */
372                         break;
373                 case 1:
374                         if (strcmp(optarg, "!") == 0)
375                                 neg_opt = 2;
376                       break;
377                 case 'A':
378                         xtime = &param.atime;
379                         xsign = &param.asign;
380                 case 'C':
381                         if (c == 'C') {
382                                 xtime = &param.ctime;
383                                 xsign = &param.csign;
384                         }
385                 case 'M':
386                         if (c == 'M') {
387                                 xtime = &param.mtime;
388                                 xsign = &param.msign;
389                         }
390                         new_fashion = 1;
391                         if (neg_opt) {
392                                 if (optarg[0] == '-')
393                                         optarg[0] = '+';
394                                 else if (optarg[0] == '+')
395                                         optarg[0] = '-';
396                                 else {
397                                         timestr[0] = '-';
398                                         timestr[1] = '\0';
399                                         strcat(timestr, optarg);
400                                         optarg = timestr;
401                                 }
402                         }
403                         ret = set_time(&t, xtime, optarg);
404                         if (ret == INT_MAX)
405                                 return -1;
406                         if (ret)
407                                 *xsign = ret;
408                         break;
409                 case 'D':
410                         depth = strtol(optarg, 0, 0);
411                         break;
412                 case 'n':
413                         new_fashion = 1;
414                         param.pattern = (char *)optarg;
415                         if (neg_opt)
416                                 param.exclude_pattern = 1;
417                         else
418                                 param.exclude_pattern = 0;
419                         break;
420                 case 'O':
421                         if (obduuid) {
422                                 fprintf(stderr,
423                                         "error: %s: only one obduuid allowed",
424                                         argv[0]);
425                                 return CMD_HELP;
426                         }
427                         obduuid = (struct obd_uuid *)optarg;
428                         break;
429                 case 'p':
430                         zeroend = 1;
431                         break;
432                 case 'P':
433                         break;
434                 case 'q':
435                         new_fashion = 0;
436                         quiet++;
437                         verbose = 0;
438                         break;
439                 case 'r':
440                         new_fashion = 0;
441                         recursive = 1;
442                         break;
443                 case 'v':
444                         new_fashion = 0;
445                         verbose++;
446                         quiet = 0;
447                         break;
448                 case '?':
449                         return CMD_HELP;
450                 default:
451                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
452                                 argv[0], argv[optind - 1]);
453                         return CMD_HELP;
454                 };
455         }
456
457         if (pathstart == -1) {
458                 fprintf(stderr, "error: %s: no filename|pathname\n",
459                                 argv[0]);
460                 return CMD_HELP;
461         } else if (pathend == -1) {
462                 /* no options */
463                 pathend = argc;
464         }
465
466         param.obduuid = obduuid;
467         if (new_fashion) {
468                 param.maxdepth = depth;
469                 param.zeroend = zeroend;
470                 param.quiet = 1;
471         } else {
472                 param.recursive = recursive;
473                 param.verbose = verbose;
474                 param.quiet = quiet;
475                 param.maxdepth = recursive ? -1 : 1;
476         }
477
478         do {
479                 if (new_fashion)
480                         ret = llapi_find(argv[pathstart], &param);
481                 else
482                         ret = llapi_getstripe(argv[pathstart], &param);
483         } while (++pathstart < pathend && !ret);
484
485         if (ret)
486                 fprintf(stderr, "error: %s failed for %s.\n",
487                         argv[0], argv[optind - 1]);
488
489         return ret;
490 }
491
492 static int lfs_getstripe(int argc, char **argv)
493 {
494         struct option long_opts[] = {
495                 {"obd", 1, 0, 'O'},
496                 {"quiet", 0, 0, 'q'},
497                 {"recursive", 0, 0, 'r'},
498                 {"verbose", 0, 0, 'v'},
499                 {0, 0, 0, 0}
500         };
501         char short_opts[] = "hO:qrv";
502         int quiet, verbose, recursive, c, rc;
503         struct obd_uuid *obduuid = NULL;
504         struct find_param param;
505
506         optind = 0;
507         quiet = verbose = recursive = 0;
508         while ((c = getopt_long(argc, argv, short_opts,
509                                 long_opts, NULL)) != -1) {
510                 switch (c) {
511                 case 'O':
512                         if (obduuid) {
513                                 fprintf(stderr,
514                                         "error: %s: only one obduuid allowed",
515                                         argv[0]);
516                                 return CMD_HELP;
517                         }
518                         obduuid = (struct obd_uuid *)optarg;
519                         break;
520                 case 'q':
521                         quiet++;
522                         verbose = 0;
523                         break;
524                 case 'r':
525                         recursive = 1;
526                         break;
527                 case 'v':
528                         verbose++;
529                         quiet = 0;
530                         break;
531                 case '?':
532                         return CMD_HELP;
533                 default:
534                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
535                                 argv[0], argv[optind - 1]);
536                         return CMD_HELP;
537                 }
538         }
539
540         if (optind >= argc)
541                 return CMD_HELP;
542
543         memset(&param, 0, sizeof(param));
544         param.recursive = recursive;
545         param.verbose = verbose;
546         param.quiet = quiet;
547         param.obduuid = obduuid;
548         param.maxdepth = recursive ? -1 : 1;
549
550         do {
551                 rc = llapi_getstripe(argv[optind], &param);
552         } while (++optind < argc && !rc);
553
554         if (rc)
555                 fprintf(stderr, "error: %s failed for %s.\n", 
556                         argv[0], argv[optind - 1]);
557         return rc;
558 }
559
560 static int lfs_osts(int argc, char **argv)
561 {
562         FILE *fp;
563         struct mntent *mnt = NULL;
564         struct obd_uuid *obduuid = NULL;
565         struct find_param param;
566         int rc=0;
567
568         if (argc != 1)
569                 return CMD_HELP;
570
571         fp = setmntent(MOUNTED, "r");
572
573         if (fp == NULL) {
574                  fprintf(stderr, "%s: setmntent(%s): %s:", argv[0], MOUNTED,
575                         strerror (errno));
576         } else {
577                 mnt = getmntent(fp);
578                 memset(&param, 0, sizeof(param));
579                 param.obduuid = obduuid;
580                 while (feof(fp) == 0 && ferror(fp) ==0) {
581                         if (llapi_is_lustre_mnt(mnt)) {
582                                 rc = llapi_getstripe(mnt->mnt_dir, &param);
583                                 if (rc)
584                                         fprintf(stderr,
585                                                "error: %s: failed on %s\n",
586                                                argv[0], mnt->mnt_dir);
587                         }
588                         mnt = getmntent(fp);
589                 }
590                 endmntent(fp);
591         }
592
593         return rc;
594 }
595
596 #define COOK(value)                                                     \
597 ({                                                                      \
598         int radix = 0;                                                  \
599         while (value > 1024) {                                          \
600                 value /= 1024;                                          \
601                 radix++;                                                \
602         }                                                               \
603         radix;                                                          \
604 })
605 #define UUF     "%-20s"
606 #define CSF     "%9s"
607 #define CDF     "%9llu"
608 #define HSF     "%8s"
609 #define HDF     "%6.1f"
610 #define RSF     "%5s"
611 #define RDF     "%4d%%"
612
613 static int path2mnt(char *path, FILE *fp, char *mntdir, int dir_len)
614 {
615         char rpath[PATH_MAX] = {'\0'};
616         struct mntent *mnt;
617         int rc, len, out_len = 0;
618
619         if (!realpath(path, rpath)) {
620                 rc = -errno;
621                 fprintf(stderr, "error: lfs df: invalid path '%s': %s\n",
622                         path, strerror(-rc));
623                 return rc;
624         }
625
626         len = 0;
627         mnt = getmntent(fp);
628         while (feof(fp) == 0 && ferror(fp) == 0) {
629                 if (llapi_is_lustre_mnt(mnt)) {
630                         len = strlen(mnt->mnt_dir);
631                         if (len > out_len &&
632                             !strncmp(rpath, mnt->mnt_dir, len)) {
633                                 out_len = len;
634                                 memset(mntdir, 0, dir_len);
635                                 strncpy(mntdir, mnt->mnt_dir, dir_len);
636                         }
637                 }
638                 mnt = getmntent(fp);
639         }
640
641         if (out_len > 0)
642                 return 0;
643
644         fprintf(stderr, "error: lfs df: %s isn't mounted on lustre\n", path);
645         return -EINVAL;
646 }
647
648 static int showdf(char *mntdir, struct obd_statfs *stat,
649                   char *uuid, int ishow, int cooked,
650                   char *type, int index, int rc)
651 {
652         long long avail, used, total;
653         double ratio = 0;
654         char *suffix = "KMGTPEZY";
655         char tbuf[10], ubuf[10], abuf[10], rbuf[10];
656
657         if (!uuid || !stat)
658                 return -EINVAL;
659
660         switch (rc) {
661         case 0:
662                 if (ishow) {
663                         avail = stat->os_ffree;
664                         used = stat->os_files - stat->os_ffree;
665                         total = stat->os_files;
666                 } else {
667                         int shift = cooked ? 0 : 10;
668
669                         avail = (stat->os_bavail * stat->os_bsize) >> shift;
670                         used = stat->os_blocks - stat->os_bavail;
671                         used = (used * stat->os_bsize) >> shift;
672                         total = (stat->os_blocks * stat->os_bsize) >> shift;
673                 }
674
675                 if (total > 0)
676                         ratio = (double)used / (double)total;
677
678                 if (cooked) {
679                         int i;
680                         double cook_val;
681
682                         cook_val = (double)total;
683                         i = COOK(cook_val);
684                         if (i > 0)
685                                 sprintf(tbuf, HDF"%c", cook_val, suffix[i - 1]);
686                         else
687                                 sprintf(tbuf, CDF, total);
688
689                         cook_val = (double)used;
690                         i = COOK(cook_val);
691                         if (i > 0)
692                                 sprintf(ubuf, HDF"%c", cook_val, suffix[i - 1]);
693                         else
694                                 sprintf(ubuf, CDF, used);
695
696                         cook_val = (double)avail;
697                         i = COOK(cook_val);
698                         if (i > 0)
699                                 sprintf(abuf, HDF"%c", cook_val, suffix[i - 1]);
700                         else
701                                 sprintf(abuf, CDF, avail);
702                 } else {
703                         sprintf(tbuf, CDF, total);
704                         sprintf(ubuf, CDF, used);
705                         sprintf(abuf, CDF, avail);
706                 }
707
708                 sprintf(rbuf, RDF, (int)(ratio * 100));
709                 printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s",
710                        uuid, tbuf, ubuf, abuf, rbuf, mntdir);
711                 if (type)
712                         printf("[%s:%d]\n", type, index);
713                 else
714                         printf("\n");
715
716                 break;
717         case -ENODATA:
718                 printf(UUF": inactive device\n", uuid);
719                 break;
720         default:
721                 printf(UUF": %s\n", uuid, strerror(-rc));
722                 break;
723         }
724
725         return 0;
726 }
727
728 static int mntdf(char *mntdir, int ishow, int cooked)
729 {
730         struct obd_statfs stat_buf, sum = { .os_bsize = 1 };
731         struct obd_uuid uuid_buf;
732         __u32 index;
733         int rc;
734
735         if (ishow)
736                 printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s\n",
737                        "UUID", "Inodes", "IUsed", "IFree",
738                        "IUse%", "Mounted on");
739         else
740                 printf(UUF" "CSF" "CSF" "CSF" "RSF" %-s\n",
741                        "UUID", cooked ? "bytes" : "1K-blocks",
742                        "Used", "Available", "Use%", "Mounted on");
743
744         for (index = 0; ; index++) {
745                 memset(&stat_buf, 0, sizeof(struct obd_statfs));
746                 memset(&uuid_buf, 0, sizeof(struct obd_uuid));
747                 rc = llapi_obd_statfs(mntdir, LL_STATFS_MDC, index,
748                                       &stat_buf, &uuid_buf);
749                 if (rc == -ENODEV)
750                         break;
751
752                 if (rc == -EAGAIN)
753                         continue;
754
755                 if (rc == -ENOTCONN || rc == -ETIMEDOUT || rc == -EIO ||
756                     rc == -ENODATA || rc == 0) {
757                         showdf(mntdir, &stat_buf, uuid_buf.uuid, ishow, cooked,
758                                "MDT", index, rc);
759                 } else {
760                         fprintf(stderr,
761                                 "error: llapi_obd_statfs(%s): %s (%d)\n",
762                                 uuid_buf.uuid, strerror(-rc), rc);
763                         return rc;
764                 }
765                 if (rc == 0) {
766                         sum.os_ffree += stat_buf.os_ffree;
767                         sum.os_files += stat_buf.os_files;
768                 }
769         }
770
771         for (index = 0; ; index++) {
772                 memset(&stat_buf, 0, sizeof(struct obd_statfs));
773                 memset(&uuid_buf, 0, sizeof(struct obd_uuid));
774                 rc = llapi_obd_statfs(mntdir, LL_STATFS_LOV, index,
775                                       &stat_buf, &uuid_buf);
776                 if (rc == -ENODEV)
777                         break;
778
779                 if (rc == -EAGAIN)
780                         continue;
781
782                 if (rc == -ENOTCONN || rc == -ETIMEDOUT || rc == -EIO ||
783                     rc == -ENODATA || rc == 0) {
784                         showdf(mntdir, &stat_buf, uuid_buf.uuid, ishow, cooked,
785                                "OST", index, rc);
786                 } else {
787                         fprintf(stderr,
788                                 "error: llapi_obd_statfs failed: %s (%d)\n",
789                                 strerror(-rc), rc);
790                         return rc;
791                 }
792                 if (rc == 0) {
793                         sum.os_blocks += stat_buf.os_blocks * stat_buf.os_bsize;
794                         sum.os_bfree  += stat_buf.os_bfree * stat_buf.os_bsize;
795                         sum.os_bavail += stat_buf.os_bavail * stat_buf.os_bsize;
796                 }
797         }
798
799         printf("\n");
800         showdf(mntdir, &sum, "filesystem summary:", ishow, cooked, NULL, 0,0);
801
802         return 0;
803 }
804
805 static int lfs_df(int argc, char **argv)
806 {
807         FILE *fp;
808         char *path = NULL;
809         struct mntent *mnt = NULL;
810         char mntdir[PATH_MAX] = {'\0'};
811         int ishow = 0, cooked = 0;
812         int c, rc = 0;
813
814         optind = 0;
815         while ((c = getopt(argc, argv, "ih")) != -1) {
816                 switch (c) {
817                 case 'i':
818                         ishow = 1;
819                         break;
820                 case 'h':
821                         cooked = 1;
822                         break;
823                 default:
824                         return CMD_HELP;
825                 }
826         }
827         if (optind < argc )
828                 path = argv[optind];
829
830         fp = setmntent(MOUNTED, "r");
831         if (fp == NULL) {
832                 rc = -errno;
833                 fprintf(stderr, "error: %s: open %s failed( %s )\n",
834                         argv[0], MOUNTED, strerror(errno));
835                 return rc;
836         }
837         if (path) {
838                 rc = path2mnt(path, fp, mntdir, sizeof(mntdir));
839                 if (rc) {
840                         endmntent(fp);
841                         return rc;
842                 }
843
844                 rc = mntdf(mntdir, ishow, cooked);
845                 printf("\n");
846                 endmntent(fp);
847         } else {
848                 mnt = getmntent(fp);
849                 while (feof(fp) == 0 && ferror(fp) == 0) {
850                         if (llapi_is_lustre_mnt(mnt)) {
851                                 rc = mntdf(mnt->mnt_dir, ishow, cooked);
852                                 if (rc)
853                                         break;
854                                 printf("\n");
855                         }
856                         mnt = getmntent(fp);
857                 }
858                 endmntent(fp);
859         }
860
861         return rc;
862 }
863
864 static int lfs_check(int argc, char **argv)
865 {
866         int rc;
867         FILE *fp;
868         struct mntent *mnt = NULL;
869         int num_types = 1;
870         char *obd_types[2];
871         char obd_type1[4];
872         char obd_type2[4];
873
874         if (argc != 2)
875                 return CMD_HELP;
876
877         obd_types[0] = obd_type1;
878         obd_types[1] = obd_type2;
879
880         if (strcmp(argv[1], "osts") == 0) {
881                 strcpy(obd_types[0], "osc");
882         } else if (strcmp(argv[1], "mds") == 0) {
883                 strcpy(obd_types[0], "mdc");
884         } else if (strcmp(argv[1], "servers") == 0) {
885                 num_types = 2;
886                 strcpy(obd_types[0], "osc");
887                 strcpy(obd_types[1], "mdc");
888         } else {
889                 fprintf(stderr, "error: %s: option '%s' unrecognized\n",
890                                 argv[0], argv[1]);
891                         return CMD_HELP;
892         }
893
894         fp = setmntent(MOUNTED, "r");
895         if (fp == NULL) {
896                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
897                         strerror (errno));
898         } else {
899                 mnt = getmntent(fp);
900                 while (feof(fp) == 0 && ferror(fp) ==0) {
901                         if (llapi_is_lustre_mnt(mnt))
902                                 break;
903                         mnt = getmntent(fp);
904                 }
905                 endmntent(fp);
906         }
907
908         if (!mnt) {
909                 fprintf(stderr, "No suitable Lustre mount found\n");
910                 return -1;
911         }
912
913         rc = llapi_target_check(num_types, obd_types, mnt->mnt_dir);
914
915         if (rc)
916                 fprintf(stderr, "error: %s: %s status failed\n",
917                                 argv[0],argv[1]);
918
919         return rc;
920
921 }
922
923 static int lfs_catinfo(int argc, char **argv)
924 {
925         FILE *fp;
926         struct mntent *mnt = NULL;
927         int rc;
928
929         if (argc < 2 || (!strcmp(argv[1],"config") && argc < 3))
930                 return CMD_HELP;
931
932         if (strcmp(argv[1], "config") && strcmp(argv[1], "deletions"))
933                 return CMD_HELP;
934
935         fp = setmntent(MOUNTED, "r");
936         if (fp == NULL) {
937                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
938                          strerror(errno));
939         } else {
940                 mnt = getmntent(fp);
941                 while (feof(fp) == 0 && ferror(fp) == 0) {
942                         if (llapi_is_lustre_mnt(mnt))
943                                 break;
944                         mnt = getmntent(fp);
945                 }
946                 endmntent(fp);
947         }
948
949         if (mnt) {
950                 if (argc == 3)
951                         rc = llapi_catinfo(mnt->mnt_dir, argv[1], argv[2]);
952                 else
953                         rc = llapi_catinfo(mnt->mnt_dir, argv[1], NULL);
954         } else {
955                 fprintf(stderr, "no lustre_lite mounted.\n");
956                 rc = -1;
957         }
958
959         return rc;
960 }
961
962 int lfs_join(int argc, char **argv)
963 {
964         char *name_head, *name_tail;
965         int fd, rc;
966         loff_t size;
967
968         if (argc != 3)
969                 return CMD_HELP;
970         name_head = argv[1];
971         fd = open(name_head, O_WRONLY);
972         if (fd < 0) {
973                 fprintf(stderr, "Can not open name_head %s rc=%d\n",
974                         name_head, fd);
975                 return fd;
976         }
977         size = lseek(fd, 0, SEEK_END);
978         if (size % JOIN_FILE_ALIGN) {
979                 fprintf(stderr,"head file %s size %llu must be mutiple of %d\n",
980                         name_head, (long long)size, JOIN_FILE_ALIGN);
981                 rc = -EINVAL;
982                 goto out;
983         }
984         name_tail = argv[2];
985         rc = ioctl(fd, LL_IOC_JOIN, name_tail);
986 out:
987         close(fd);
988         if (rc) {
989                 fprintf(stderr, "Lustre joining files: %s, %s, failed\n",
990                         argv[1], argv[2]);
991         }
992         return rc;
993 }
994
995 #ifdef HAVE_QUOTA_SUPPORT
996 static int lfs_quotachown(int argc, char **argv)
997 {
998
999         int c,rc;
1000         int flag = 0;
1001
1002         while ((c = getopt(argc, argv, "i")) != -1) {
1003                 switch (c) {
1004                 case 'i':
1005                         flag++;
1006                         break;
1007                 default:
1008                         fprintf(stderr, "error: %s: option '-%c' "
1009                                         "unrecognized\n", argv[0], c);
1010                         return CMD_HELP;
1011                 }
1012         }
1013         if (optind == argc)
1014                 return CMD_HELP;
1015         rc = llapi_quotachown(argv[optind], flag);
1016         if(rc)
1017                 fprintf(stderr,"error: change file owner/group failed.\n");
1018         return rc;
1019 }
1020
1021
1022 static int lfs_quotacheck(int argc, char **argv)
1023 {
1024         int c, check_type = 0;
1025         char *mnt;
1026         struct if_quotacheck qchk;
1027         struct if_quotactl qctl;
1028         char *obd_type = qchk.obd_type;
1029         char *obd_uuid = qchk.obd_uuid.uuid;
1030         int rc;
1031
1032         memset(&qchk, 0, sizeof(qchk));
1033
1034         optind = 0;
1035         while ((c = getopt(argc, argv, "ug")) != -1) {
1036                 switch (c) {
1037                 case 'u':
1038                         check_type |= 0x01;
1039                         break;
1040                 case 'g':
1041                         check_type |= 0x02;
1042                         break;
1043                 default:
1044                         fprintf(stderr, "error: %s: option '-%c' "
1045                                         "unrecognized\n", argv[0], c);
1046                         return CMD_HELP;
1047                 }
1048         }
1049
1050         if (check_type)
1051                 check_type--;
1052         else    /* do quotacheck for both user & group quota by default */
1053                 check_type = 0x02;
1054
1055         if (argc == optind)
1056                 return CMD_HELP;
1057
1058         mnt = argv[optind];
1059
1060         memset(&qctl, 0, sizeof(qctl));
1061         qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
1062         qctl.qc_id = QFMT_LDISKFS;
1063         qctl.qc_type = check_type;
1064         rc = llapi_quotactl(mnt, &qctl);
1065         if (rc) {
1066                 fprintf(stderr, "quota off failed: %s\n", strerror(errno));
1067                 return rc;
1068         }
1069
1070         rc = llapi_quotacheck(mnt, check_type);
1071         if (rc) {
1072                 fprintf(stderr, "quotacheck failed: %s\n", strerror(errno));
1073                 return rc;
1074         }
1075
1076         rc = llapi_poll_quotacheck(mnt, &qchk);
1077         if (rc) {
1078                 if (*obd_type)
1079                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1080                 fprintf(stderr, "quota check failed: %s\n", strerror(errno));
1081                 return rc;
1082         }
1083
1084         memset(&qctl, 0, sizeof(qctl));
1085         qctl.qc_cmd = LUSTRE_Q_QUOTAON;
1086         qctl.qc_id = QFMT_LDISKFS;
1087         qctl.qc_type = check_type;
1088         rc = llapi_quotactl(mnt, &qctl);
1089         if (rc) {
1090                 if (*obd_type)
1091                         fprintf(stderr, "%s %s ",
1092                                 qctl.obd_type, qctl.obd_uuid.uuid);
1093                 fprintf(stderr, "%s turn on quota failed: %s\n",
1094                         argv[0], strerror(errno));
1095                 return rc;
1096         }
1097
1098         return 0;
1099 }
1100
1101 static int lfs_quotaon(int argc, char **argv)
1102 {
1103         int c;
1104         char *mnt;
1105         struct if_quotactl qctl;
1106         char *obd_type = qctl.obd_type;
1107         char *obd_uuid = qctl.obd_uuid.uuid;
1108         int rc;
1109
1110         memset(&qctl, 0, sizeof(qctl));
1111         qctl.qc_cmd = LUSTRE_Q_QUOTAON;
1112         qctl.qc_id = QFMT_LDISKFS;
1113
1114         optind = 0;
1115         while ((c = getopt(argc, argv, "ugf")) != -1) {
1116                 switch (c) {
1117                 case 'u':
1118                         qctl.qc_type |= 0x01;
1119                         break;
1120                 case 'g':
1121                         qctl.qc_type |= 0x02;
1122                         break;
1123                 case 'f':
1124                         qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
1125                         break;
1126                 default:
1127                         fprintf(stderr, "error: %s: option '-%c' "
1128                                         "unrecognized\n", argv[0], c);
1129                         return CMD_HELP;
1130                 }
1131         }
1132
1133         if (qctl.qc_type)
1134                 qctl.qc_type--;
1135
1136         if (argc == optind)
1137                 return CMD_HELP;
1138
1139         mnt = argv[optind];
1140
1141         rc = llapi_quotactl(mnt, &qctl);
1142         if (rc) {
1143                 if (*obd_type)
1144                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1145                 fprintf(stderr, "%s failed: %s\n", argv[0], strerror(errno));
1146                 return rc;
1147         }
1148
1149         return 0;
1150 }
1151
1152 static int lfs_quotaoff(int argc, char **argv)
1153 {
1154         int c;
1155         char *mnt;
1156         struct if_quotactl qctl;
1157         char *obd_type = qctl.obd_type;
1158         char *obd_uuid = qctl.obd_uuid.uuid;
1159         int rc;
1160
1161         memset(&qctl, 0, sizeof(qctl));
1162         qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
1163
1164         optind = 0;
1165         while ((c = getopt(argc, argv, "ug")) != -1) {
1166                 switch (c) {
1167                 case 'u':
1168                         qctl.qc_type |= 0x01;
1169                         break;
1170                 case 'g':
1171                         qctl.qc_type |= 0x02;
1172                         break;
1173                 default:
1174                         fprintf(stderr, "error: %s: option '-%c' "
1175                                         "unrecognized\n", argv[0], c);
1176                         return CMD_HELP;
1177                 }
1178         }
1179
1180         if (qctl.qc_type)
1181                 qctl.qc_type--;
1182
1183         if (argc == optind)
1184                 return CMD_HELP;
1185
1186         mnt = argv[optind];
1187
1188         rc = llapi_quotactl(mnt, &qctl);
1189         if (rc) {
1190                 if (*obd_type)
1191                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1192                 fprintf(stderr, "quotaoff failed: %s\n", strerror(errno));
1193                 return rc;
1194         }
1195
1196         return 0;
1197 }
1198
1199 static int name2id(unsigned int *id, char *name, int type)
1200 {
1201         if (type == USRQUOTA) {
1202                 struct passwd *entry;
1203
1204                 if (!(entry = getpwnam(name))) {
1205                         if (!errno)
1206                                 errno = ENOENT;
1207                         return -1;
1208                 }
1209
1210                 *id = entry->pw_uid;
1211         } else {
1212                 struct group *entry;
1213
1214                 if (!(entry = getgrnam(name))) {
1215                         if (!errno)
1216                                 errno = ENOENT;
1217                         return -1;
1218                 }
1219
1220                 *id = entry->gr_gid;
1221         }
1222
1223         return 0;
1224 }
1225
1226 static int id2name(char **name, unsigned int id, int type)
1227 {
1228         if (type == USRQUOTA) {
1229                 struct passwd *entry;
1230
1231                 if (!(entry = getpwuid(id))) {
1232                         if (!errno)
1233                                 errno = ENOENT;
1234                         return -1;
1235                 }
1236
1237                 *name = entry->pw_name;
1238         } else {
1239                 struct group *entry;
1240
1241                 if (!(entry = getgrgid(id))) {
1242                         if (!errno)
1243                                 errno = ENOENT;
1244                         return -1;
1245                 }
1246
1247                 *name = entry->gr_name;
1248         }
1249
1250         return 0;
1251 }
1252
1253 #define ARG2INT(nr, str, msg)                                           \
1254 do {                                                                    \
1255         char *endp;                                                     \
1256         nr = strtol(str, &endp, 0);                                     \
1257         if (*endp) {                                                    \
1258                 fprintf(stderr, "error: bad %s: %s\n", msg, str);       \
1259                 return CMD_HELP;                                        \
1260         }                                                               \
1261 } while (0)
1262
1263 int lfs_setquota(int argc, char **argv)
1264 {
1265         int c;
1266         char *mnt;
1267         struct if_quotactl qctl;
1268         char *obd_type = qctl.obd_type;
1269         char *obd_uuid = qctl.obd_uuid.uuid;
1270         int rc;
1271
1272         memset(&qctl, 0, sizeof(qctl));
1273         qctl.qc_cmd = LUSTRE_Q_SETQUOTA;
1274
1275         optind = 0;
1276         while ((c = getopt(argc, argv, "ugt")) != -1) {
1277                 switch (c) {
1278                 case 'u':
1279                         qctl.qc_type |= 0x01;
1280                         break;
1281                 case 'g':
1282                         qctl.qc_type |= 0x02;
1283                         break;
1284                 case 't':
1285                         qctl.qc_cmd = LUSTRE_Q_SETINFO;
1286                         break;
1287                 default:
1288                         fprintf(stderr, "error: %s: option '-%c' "
1289                                         "unrecognized\n", argv[0], c);
1290                         return CMD_HELP;
1291                 }
1292         }
1293
1294         if (qctl.qc_type)
1295                 qctl.qc_type--;
1296
1297         if (qctl.qc_type == UGQUOTA) {
1298                 fprintf(stderr, "error: user and group quotas can't be set "
1299                                 "both\n");
1300                 return CMD_HELP;
1301         }
1302
1303         if (qctl.qc_cmd == LUSTRE_Q_SETQUOTA) {
1304                 struct obd_dqblk *dqb = &qctl.qc_dqblk;
1305
1306                 if (optind + 6 != argc)
1307                         return CMD_HELP;
1308
1309                 rc = name2id(&qctl.qc_id, argv[optind++], qctl.qc_type);
1310                 if (rc) {
1311                         fprintf(stderr, "error: find id for name %s failed: %s\n",
1312                                 argv[optind - 1], strerror(errno));
1313                         return CMD_HELP;
1314                 }
1315
1316                 ARG2INT(dqb->dqb_bsoftlimit, argv[optind++], "block-softlimit");
1317                 ARG2INT(dqb->dqb_bhardlimit, argv[optind++], "block-hardlimit");
1318                 ARG2INT(dqb->dqb_isoftlimit, argv[optind++], "inode-softlimit");
1319                 ARG2INT(dqb->dqb_ihardlimit, argv[optind++], "inode-hardlimit");
1320
1321                 dqb->dqb_valid = QIF_LIMITS;
1322         } else {
1323                 struct obd_dqinfo *dqi = &qctl.qc_dqinfo;
1324
1325                 if (optind + 3 != argc)
1326                         return CMD_HELP;
1327
1328                 ARG2INT(dqi->dqi_bgrace, argv[optind++], "block-grace");
1329                 ARG2INT(dqi->dqi_igrace, argv[optind++], "inode-grace");
1330         }
1331
1332         mnt = argv[optind];
1333
1334         rc = llapi_quotactl(mnt, &qctl);
1335         if (rc) {
1336                 if (*obd_type)
1337                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1338                 fprintf(stderr, "setquota failed: %s\n", strerror(errno));
1339                 return rc;
1340         }
1341
1342         return 0;
1343 }
1344
1345 static inline char *type2name(int check_type)
1346 {
1347         if (check_type == USRQUOTA)
1348                 return "user";
1349         else if (check_type == GRPQUOTA)
1350                 return "group";
1351         else
1352                 return "unknown";
1353 }
1354
1355
1356 static void grace2str(time_t seconds,char *buf)
1357 {
1358         uint minutes, hours, days;
1359
1360         minutes = (seconds + 30) / 60;
1361         hours = minutes / 60;
1362         minutes %= 60;
1363         days = hours / 24;
1364         hours %= 24;
1365         if (days >= 2)
1366                 snprintf(buf, 40, "%ddays", days);
1367         else
1368                 snprintf(buf, 40, "%02d:%02d", hours + days * 24, minutes);
1369 }
1370
1371
1372 static void diff2str(time_t seconds, char *buf, time_t now)
1373 {
1374
1375         buf[0] = 0;
1376         if (!seconds)
1377                 return;
1378         if (seconds <= now) {
1379                 strcpy(buf, "none");
1380                 return;
1381         }
1382         grace2str(seconds - now, buf);
1383 }
1384
1385 static void print_quota_title(char *name, struct if_quotactl *qctl)
1386 {
1387         printf("Disk quotas for %s %s (%cid %u):\n",
1388                type2name(qctl->qc_type), name,
1389                *type2name(qctl->qc_type), qctl->qc_id);
1390         printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n",
1391                "Filesystem",
1392                "blocks", "quota", "limit", "grace",
1393                "files", "quota", "limit", "grace");
1394 }
1395
1396 static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
1397 {
1398         time_t now;
1399
1400         time(&now);
1401
1402         if (qctl->qc_cmd == LUSTRE_Q_GETQUOTA || qctl->qc_cmd == Q_GETOQUOTA) {
1403                 int bover = 0, iover = 0;
1404                 struct obd_dqblk *dqb = &qctl->qc_dqblk;
1405
1406                 if (dqb->dqb_bhardlimit &&
1407                     toqb(dqb->dqb_curspace) > dqb->dqb_bhardlimit) {
1408                         bover = 1;
1409                 } else if (dqb->dqb_bsoftlimit &&
1410                            toqb(dqb->dqb_curspace) > dqb->dqb_bsoftlimit) {
1411                         if (dqb->dqb_btime > now) {
1412                                 bover = 2;
1413                         } else {
1414                                 bover = 3;
1415                         }
1416                 }
1417
1418                 if (dqb->dqb_ihardlimit &&
1419                     dqb->dqb_curinodes > dqb->dqb_ihardlimit) {
1420                         iover = 1;
1421                 } else if (dqb->dqb_isoftlimit &&
1422                            dqb->dqb_curinodes > dqb->dqb_isoftlimit) {
1423                         if (dqb->dqb_btime > now) {
1424                                 iover = 2;
1425                         } else {
1426                                 iover = 3;
1427                         }
1428                 }
1429
1430 #if 0           /* XXX: always print quotas even when no usages */
1431                 if (dqb->dqb_curspace || dqb->dqb_curinodes)
1432 #endif
1433                 {
1434                         char numbuf[3][32];
1435                         char timebuf[40];
1436
1437                         if (strlen(mnt) > 15)
1438                                 printf("%s\n%15s", mnt, "");
1439                         else
1440                                 printf("%15s", mnt);
1441
1442                         if (bover)
1443                                 diff2str(dqb->dqb_btime, timebuf, now);
1444
1445                         sprintf(numbuf[0], LPU64, toqb(dqb->dqb_curspace));
1446                         sprintf(numbuf[1], LPU64, dqb->dqb_bsoftlimit);
1447                         sprintf(numbuf[2], LPU64, dqb->dqb_bhardlimit);
1448                         printf(" %7s%c %6s %7s %7s",
1449                                numbuf[0], bover ? '*' : ' ', numbuf[1],
1450                                numbuf[2], bover > 1 ? timebuf : "");
1451
1452                         if (iover)
1453                                 diff2str(dqb->dqb_itime, timebuf, now);
1454
1455                         sprintf(numbuf[0], LPU64, dqb->dqb_curinodes);
1456                         sprintf(numbuf[1], LPU64, dqb->dqb_isoftlimit);
1457                         sprintf(numbuf[2], LPU64, dqb->dqb_ihardlimit);
1458                         if (!ost_only)
1459                                 printf(" %7s%c %6s %7s %7s",
1460                                        numbuf[0], iover ? '*' : ' ', numbuf[1],
1461                                        numbuf[2], iover > 1 ? timebuf : "");
1462                         printf("\n");
1463                 }
1464         } else if (qctl->qc_cmd == LUSTRE_Q_GETINFO ||
1465                    qctl->qc_cmd == Q_GETOINFO) {
1466                 char bgtimebuf[40];
1467                 char igtimebuf[40];
1468
1469                 grace2str(qctl->qc_dqinfo.dqi_bgrace, bgtimebuf);
1470                 grace2str(qctl->qc_dqinfo.dqi_igrace, igtimebuf);
1471                 printf("Block grace time: %s; Inode grace time: %s\n",
1472                        bgtimebuf, igtimebuf);
1473         }
1474 }
1475
1476 static void print_mds_quota(char *mnt, struct if_quotactl *qctl)
1477 {
1478         int rc;
1479
1480         /* XXX: this is a flag to mark that only mds quota is wanted */
1481         qctl->qc_dqblk.dqb_valid = 1;
1482         rc = llapi_quotactl(mnt, qctl);
1483         if (rc) {
1484                 fprintf(stderr, "quotactl failed: %s\n", strerror(errno));
1485                 return;
1486         }
1487         qctl->qc_dqblk.dqb_valid = 0;
1488
1489         print_quota(qctl->obd_uuid.uuid, qctl, 0);
1490 }
1491
1492 static void print_lov_quota(char *mnt, struct if_quotactl *qctl)
1493 {
1494         DIR *dir;
1495         struct obd_uuid uuids[1024], *uuidp;
1496         int obdcount = 1024;
1497         int i, rc;
1498
1499         dir = opendir(mnt);
1500         if (!dir) {
1501                 fprintf(stderr, "open %s failed: %s\n", mnt, strerror(errno));
1502                 return;
1503         }
1504
1505         rc = llapi_lov_get_uuids(dirfd(dir), uuids, &obdcount);
1506         if (rc != 0) {
1507                 fprintf(stderr, "get ost uuid failed: %s\n", strerror(errno));
1508                 goto out;
1509         }
1510
1511         for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
1512                 memcpy(&qctl->obd_uuid, uuidp, sizeof(*uuidp));
1513
1514                 /* XXX clear this flag to get quota from osts */
1515                 qctl->qc_dqblk.dqb_valid = 0;
1516                 rc = llapi_quotactl(mnt, qctl);
1517                 if (rc) {
1518                         fprintf(stderr, "%s quotactl failed: %s\n",
1519                                 uuidp->uuid, strerror(errno));
1520                         continue;
1521                 }
1522
1523                 print_quota(uuidp->uuid, qctl, 1);
1524         }
1525
1526 out:
1527         closedir(dir);
1528         return;
1529 }
1530
1531 static int lfs_quota(int argc, char **argv)
1532 {
1533         int c;
1534         char *name = NULL, *mnt;
1535         struct if_quotactl qctl;
1536         char *obd_type = qctl.obd_type;
1537         char *obd_uuid = qctl.obd_uuid.uuid;
1538         int rc;
1539
1540         memset(&qctl, 0, sizeof(qctl));
1541         qctl.qc_cmd = LUSTRE_Q_GETQUOTA;
1542
1543         optind = 0;
1544         while ((c = getopt(argc, argv, "ugto:")) != -1) {
1545                 switch (c) {
1546                 case 'u':
1547                         qctl.qc_type |= 0x01;
1548                         break;
1549                 case 'g':
1550                         qctl.qc_type |= 0x02;
1551                         break;
1552                 case 't':
1553                         qctl.qc_cmd = LUSTRE_Q_GETINFO;
1554                         break;
1555                 case 'o':
1556                         strncpy(obd_uuid, optarg, sizeof(qctl.obd_uuid));
1557                         break;
1558                 default:
1559                         fprintf(stderr, "error: %s: option '-%c' "
1560                                         "unrecognized\n", argv[0], c);
1561                         return CMD_HELP;
1562                 }
1563         }
1564
1565         if (qctl.qc_type)
1566                 qctl.qc_type--;
1567
1568         if (qctl.qc_type == UGQUOTA) {
1569                 fprintf(stderr, "error: user or group can't be specified"
1570                                 "both\n");
1571                 return CMD_HELP;
1572         }
1573
1574         if (qctl.qc_cmd == LUSTRE_Q_GETQUOTA) {
1575                 if (optind + 2 != argc)
1576                         return CMD_HELP;
1577
1578                 name = argv[optind++];
1579                 rc = name2id(&qctl.qc_id, name, qctl.qc_type);
1580                 if (rc) {
1581                         fprintf(stderr, "error: find id for name %s failed: %s\n",
1582                                 name, strerror(errno));
1583                         return CMD_HELP;
1584                 }
1585                 print_quota_title(name, &qctl);
1586         } else if (optind + 1 != argc) {
1587                 return CMD_HELP;
1588         }
1589
1590         mnt = argv[optind];
1591
1592         rc = llapi_quotactl(mnt, &qctl);
1593         if (rc) {
1594                 if (*obd_type)
1595                         fprintf(stderr, "%s %s ", obd_type, obd_uuid);
1596                 fprintf(stderr, "quota failed: %s\n", strerror(errno));
1597                 return rc;
1598         }
1599
1600         if (!name)
1601                 rc = id2name(&name, getuid(), qctl.qc_type);
1602
1603         if (*obd_uuid) {
1604                 mnt = "";
1605                 name = obd_uuid;
1606         }
1607
1608         print_quota(mnt, &qctl, 0);
1609
1610         if (!*obd_uuid && qctl.qc_cmd != LUSTRE_Q_GETINFO) {
1611                 print_mds_quota(mnt, &qctl);
1612                 print_lov_quota(mnt, &qctl);
1613         }
1614
1615         return 0;
1616 }
1617 #endif /* HAVE_QUOTA_SUPPORT */
1618
1619 int main(int argc, char **argv)
1620 {
1621         int rc;
1622
1623         setlinebuf(stdout);
1624
1625         ptl_initialize(argc, argv);
1626         if (obd_initialize(argc, argv) < 0)
1627                 exit(2);
1628         if (dbg_initialize(argc, argv) < 0)
1629                 exit(3);
1630
1631         Parser_init("lfs > ", cmdlist);
1632
1633         if (argc > 1) {
1634                 rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
1635         } else {
1636                 rc = Parser_commands();
1637         }
1638
1639         obd_finalize(argc, argv);
1640         return rc;
1641 }