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