Whamcloud - gitweb
- debug info to investigate a source of small writes
[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 <dirent.h>
33 #include <libgen.h>
34 #include <portals/ptlctl.h>
35
36 #include <liblustre.h>
37 #include <linux/lustre_idl.h>
38 #include <lustre/liblustreapi.h>
39 #include <lustre/lustre_user.h>
40
41 #include "parser.h"
42 #include "obdctl.h"
43
44 /* all functions */
45 static int lfs_setstripe(int argc, char **argv);
46 static int lfs_dirstripe(int argc, char **argv);
47 static int lfs_find(int argc, char **argv);
48 static int lfs_getstripe(int argc, char **argv);
49 static int lfs_showfid(int argc, char **argv);
50 static int lfs_osts(int argc, char **argv);
51 static int lfs_check(int argc, char **argv);
52 static int lfs_catinfo(int argc, char **argv);
53 static int lfs_getfacl(int argc, char **argv);
54 static int lfs_setfacl(int argc, char **argv);
55
56 /* all avaialable commands */
57 command_t cmdlist[] = {
58         {"setstripe", lfs_setstripe, 0,
59          "Create a new file with a specific striping pattern or\n"
60          "set the default striping pattern on an existing directory or\n"
61          "delete the default striping pattern from an existing directory\n"
62          "usage: setstripe <filename|dirname> <stripe size> <stripe start> <stripe count>\n"
63          "       or \n"
64          "       setstripe -d <dirname>\n"
65          "\tstripe size:  Number of bytes in each stripe (0 default)\n"
66          "\tstripe start: OST index of first stripe (-1 default)\n"
67          "\tstripe count: Number of OSTs to stripe over (0 default)"},
68         {"dirstripe", lfs_dirstripe, 0,
69          "To create a new dir with a specific striping pattern.\n"
70          "usage: dirstripe <dirname> <stripe count> [<mds idx list>]\n"
71          "\tstripe count: Number of MDSes to stripe over (0 default)\n"
72          "\tmds idx list: List of MDS servers to contain the dir (not implemented)"},
73         {"find", lfs_find, 0,
74          "To list the extended attributes for a given filename or files in a\n"
75          "directory or recursively for all files in a directory tree.\n"
76          "usage: find [--obd <uuid>] [--quiet | --verbose] [--recursive] <dir|file> ..."},
77         {"getstripe", lfs_getstripe, 0,
78          "To list the striping pattern for given filename.\n"
79          "usage: getstripe <filename>"},
80         {"showfid", lfs_showfid, 0,
81          "To list the fid and store cookie for given filename.\n"
82          "usage: showfid [--quiet | --verbose] [--recursive] <dir|file> ..."},
83         {"check", lfs_check, 0,
84          "Display the status of MDS or OSTs (as specified in the command)\n"
85          "or all the servers (MDS and OSTs).\n"
86          "usage: check <osts|mds|servers>"},
87         {"catinfo", lfs_catinfo, 0,
88          "Show information of specified type logs.\n"
89          "usage: catinfo {keyword} [node name]\n"
90          "\tkeywords are one of followings: config, deletions.\n"
91          "\tnode name must be provided when use keyword config."},
92         {"getfacl", lfs_getfacl, 0,
93          "Get file access control lists.\n"
94          "usage: getfacl [-dRLPvh] file"},
95         {"setfacl", lfs_setfacl, 0,
96          "Set file access control lists.\n"
97          "usage: setfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ..."},
98         {"osts", lfs_osts, 0, "osts"},
99         {"help", Parser_help, 0, "help"},
100         {"exit", Parser_quit, 0, "quit"},
101         {"quit", Parser_quit, 0, "quit"},
102         { 0, 0, 0, NULL }
103 };
104
105 /* functions */
106 static int lfs_setstripe(int argc, char **argv)
107 {
108         char *fname;
109         int result;
110         long st_size = 0;
111         int  st_offset = -1, st_count = 0;
112         char *end;
113
114         if (argc != 5 && argc != 3)
115                 return CMD_HELP;
116
117         if (argc == 3) {
118                 if (strcmp(argv[1], "-d") != 0)
119                         return CMD_HELP;
120
121                 fname = argv[2];
122                 st_size = -1;
123         } else {
124                 fname = argv[1];
125
126                 // get the stripe size
127                 st_size = strtoul(argv[2], &end, 0);
128                 if (*end != '\0') {
129                         fprintf(stderr, "error: %s: bad stripe size '%s'\n",
130                                         argv[0], argv[2]);
131                         return CMD_HELP;
132                 }
133                 // get the stripe offset
134                 st_offset = strtoul(argv[3], &end, 0);
135                 if (*end != '\0') {
136                         fprintf(stderr, "error: %s: bad stripe offset '%s'\n",
137                                         argv[0], argv[3]);
138                         return CMD_HELP;
139                 }
140                 // get the stripe count
141                 st_count = strtoul(argv[4], &end, 0);
142                 if (*end != '\0') {
143                         fprintf(stderr, "error: %s: bad stripe count '%s'\n",
144                                         argv[0], argv[4]);
145                         return CMD_HELP;
146                 }
147         }
148
149         result = llapi_file_create(fname, st_size, st_offset, st_count, 0);
150         if (result)
151                 fprintf(stderr, "error: %s: create stripe file failed\n",
152                                 argv[0]);
153
154         return result;
155 }
156
157 static int lfs_dirstripe(int argc, char **argv)
158 {
159         int result;
160         int st_count;
161         char *end;
162
163         if (argc != 3)
164                 return CMD_HELP;
165
166         // get the stripe size
167         st_count = strtoul(argv[2], &end, 0);
168         if (*end != '\0') {
169                 fprintf(stderr, "error: %s: bad count '%s'\n",
170                                 argv[0], argv[2]);
171                 return CMD_HELP;
172         }
173
174         result = op_create_dir(argv[1], st_count);
175         if (result)
176                 fprintf(stderr, "error: %s: create stripe dir failed\n",
177                                 argv[0]);
178
179         return result;
180 }
181
182 static int lfs_find(int argc, char **argv)
183 {
184         struct option long_opts[] = {
185                 {"obd", 1, 0, 'o'},
186                 {"quiet", 0, 0, 'q'},
187                 {"recursive", 0, 0, 'r'},
188                 {"verbose", 0, 0, 'v'},
189                 {0, 0, 0, 0}
190         };
191         char short_opts[] = "ho:qrv";
192         int quiet, verbose, recursive, c, rc;
193         struct obd_uuid *obduuid = NULL;
194
195         optind = 0;
196         quiet = verbose = recursive = 0;
197         while ((c = getopt_long(argc, argv, short_opts,
198                                         long_opts, NULL)) != -1) {
199                 switch (c) {
200                 case 'o':
201                         if (obduuid) {
202                                 fprintf(stderr,
203                                         "error: %s: only one obduuid allowed",
204                                         argv[0]);
205                                 return CMD_HELP;
206                         }
207                         obduuid = (struct obd_uuid *)optarg;
208                         break;
209                 case 'q':
210                         quiet++;
211                         verbose = 0;
212                         break;
213                 case 'r':
214                         recursive = 1;
215                         break;
216                 case 'v':
217                         verbose++;
218                         quiet = 0;
219                         break;
220                 case '?':
221                         return CMD_HELP;
222                         break;
223                 default:
224                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
225                                 argv[0], argv[optind - 1]);
226                         return CMD_HELP;
227                         break;
228                 }
229         }
230
231         if (optind >= argc)
232                 return CMD_HELP;
233
234         do {
235                 rc = llapi_find(argv[optind], obduuid, recursive, verbose, quiet, 0);
236         } while (++optind < argc && !rc);
237
238         if (rc)
239                 fprintf(stderr, "error: %s: find failed\n", argv[0]);
240         return rc;
241 }
242
243 static int lfs_getstripe(int argc, char **argv)
244 {
245         struct option long_opts[] = {
246                 {"quiet", 0, 0, 'q'},
247                 {"verbose", 0, 0, 'v'},
248                 {0, 0, 0, 0}
249         };
250         char short_opts[] = "qv";
251         int quiet, verbose, recursive, c, rc;
252         struct obd_uuid *obduuid = NULL;
253
254         optind = 0;
255         quiet = verbose = recursive = 0;
256         while ((c = getopt_long(argc, argv, short_opts,
257                                         long_opts, NULL)) != -1) {
258                 switch (c) {
259                 case 'o':
260                         if (obduuid) {
261                                 fprintf(stderr,
262                                         "error: %s: only one obduuid allowed",
263                                         argv[0]);
264                                 return CMD_HELP;
265                         }
266                         obduuid = (struct obd_uuid *)optarg;
267                         break;
268                 case 'q':
269                         quiet++;
270                         verbose = 0;
271                         break;
272                 case 'v':
273                         verbose++;
274                         quiet = 0;
275                         break;
276                 case '?':
277                         return CMD_HELP;
278                         break;
279                 default:
280                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
281                                 argv[0], argv[optind - 1]);
282                         return CMD_HELP;
283                         break;
284                 }
285         }
286
287         if (optind >= argc)
288                 return CMD_HELP;
289
290         do {
291                 rc = llapi_find(argv[optind], obduuid, recursive, verbose, quiet, 0);
292         } while (++optind < argc && !rc);
293
294         if (rc)
295                 fprintf(stderr, "error: %s: getstripe failed for %s\n",
296                         argv[0], argv[1]);
297
298         return rc;
299 }
300
301 static int lfs_showfid(int argc, char **argv)
302 {
303         struct option long_opts[] = {
304                 {"quiet", 0, 0, 'q'},
305                 {"recursive", 0, 0, 'r'},
306                 {"verbose", 0, 0, 'v'},
307                 {0, 0, 0, 0}
308         };
309         char short_opts[] = "hqrv";
310         int quiet, verbose, recursive, c, rc;
311
312         optind = 0;
313         quiet = verbose = recursive = 0;
314         while ((c = getopt_long(argc, argv, short_opts,
315                                 long_opts, NULL)) != -1) {
316                 switch (c) {
317                 case 'q':
318                         quiet++;
319                         verbose = 0;
320                         break;
321                 case 'r':
322                         recursive = 1;
323                         break;
324                 case 'v':
325                         verbose++;
326                         quiet = 0;
327                         break;
328                 case '?':
329                         return CMD_HELP;
330                         break;
331                 default:
332                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
333                                 argv[0], argv[optind - 1]);
334                         return CMD_HELP;
335                 }
336         }
337
338         if (optind >= argc)
339                 return CMD_HELP;
340
341         do {
342                 rc = llapi_find(argv[optind], NULL, recursive, verbose, quiet, 1);
343         } while (++optind < argc && !rc);
344
345         if (rc)
346                 fprintf(stderr, "error: %s: find failed\n", argv[0]);
347         
348         return rc;
349 }
350
351 static int lfs_osts(int argc, char **argv)
352 {
353         FILE *fp;
354         struct mntent *mnt = NULL;
355         struct obd_uuid *obduuid = NULL;
356         int rc=0;
357
358         if (argc != 1)
359                 return CMD_HELP;
360
361         fp = setmntent(MOUNTED, "r");
362
363         if (fp == NULL) {
364                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
365                         strerror (errno));
366         } else {
367                 mnt = getmntent(fp);
368                 while (feof(fp) == 0 && ferror(fp) ==0) {
369                         if (llapi_is_lustre_mnttype(mnt->mnt_type)) {
370                                 rc = llapi_find(mnt->mnt_dir, obduuid, 0, 0, 0, 0);
371                                 if (rc)
372                                         fprintf(stderr,
373                                                "error: lfs osts failed on %s\n",
374                                                mnt->mnt_dir);
375                         }
376                         mnt = getmntent(fp);
377                 }
378                 endmntent(fp);
379         }
380
381         return rc;
382 }
383
384 static int lfs_check(int argc, char **argv)
385 {
386         int rc;
387         FILE *fp;
388         struct mntent *mnt = NULL;
389         int num_types = 1;
390         char *obd_types[2];
391         char obd_type1[4];
392         char obd_type2[4];
393
394         if (argc != 2)
395                 return CMD_HELP;
396
397         obd_types[0] = obd_type1;
398         obd_types[1] = obd_type2;
399
400         if (strcmp(argv[1], "osts") == 0) {
401                 strcpy(obd_types[0], "osc");
402         } else if (strcmp(argv[1], "mds") == 0) {
403                 strcpy(obd_types[0], "mdc");
404         } else if (strcmp(argv[1], "servers") == 0) {
405                 num_types = 2;
406                 strcpy(obd_types[0], "osc");
407                 strcpy(obd_types[1], "mdc");
408         } else {
409                 fprintf(stderr, "error: %s: option '%s' unrecognized\n",
410                         argv[0], argv[1]);
411                 return CMD_HELP;
412         }
413
414         fp = setmntent(MOUNTED, "r");
415         if (fp == NULL) {
416                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
417                         strerror (errno));
418         } else {
419                 mnt = getmntent(fp);
420                 while (feof(fp) == 0 && ferror(fp) ==0) {
421                         if (llapi_is_lustre_mnttype(mnt->mnt_type))
422                                 break;
423                         mnt = getmntent(fp);
424                 }
425                 endmntent(fp);
426         }
427
428         rc = llapi_target_check(num_types, obd_types, mnt->mnt_dir);
429
430         if (rc)
431                 fprintf(stderr, "error: %s: %s status failed\n",
432                                 argv[0],argv[1]);
433
434         return rc;
435
436 }
437
438 static int lfs_catinfo(int argc, char **argv)
439 {
440         FILE *fp;
441         struct mntent *mnt = NULL;
442         int rc;
443
444         if (argc < 2 || (!strcmp(argv[1],"config") && argc < 3))
445                 return CMD_HELP;
446
447         if (strcmp(argv[1], "config") && strcmp(argv[1], "deletions"))
448                 return CMD_HELP;
449
450         fp = setmntent(MOUNTED, "r");
451         if (fp == NULL) {
452                  fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
453                          strerror(errno));
454         } else {
455                 mnt = getmntent(fp);
456                 while (feof(fp) == 0 && ferror(fp) == 0) {
457                         if (llapi_is_lustre_mnttype(mnt->mnt_type))
458                                 break;
459                         mnt = getmntent(fp);
460                 }
461                 endmntent(fp);
462         }
463
464         if (mnt) {
465                 if (argc == 3)
466                         rc = llapi_catinfo(mnt->mnt_dir, argv[1], argv[2]);
467                 else
468                         rc = llapi_catinfo(mnt->mnt_dir, argv[1], NULL);
469         } else {
470                 fprintf(stderr, "no lustre_lite mounted.\n");
471                 rc = -1;
472         }
473
474         return rc;
475 }
476
477 /*
478  * We assume one and only one filename is supplied as the
479  * last parameter.
480  */
481 static int acl_cmd_parse(int argc, char **argv,
482                          char *dirbuf, char *cmdbuf)
483 {
484         char path[PATH_MAX];
485         char path2[PATH_MAX];
486         FILE *fp;
487         struct mntent *mnt = NULL;
488         char *dir, *tgt;
489         int found = 0, i;
490
491         if (argc < 2)
492                 return -1;
493
494         /* get path prefix */
495         strncpy(path, argv[argc - 1], PATH_MAX);
496         dir = dirname(path);
497
498         /* try to resolve the pathname into relative to the
499          * root of the mounted lustre filesystem.
500          * FIXME we simply suppose there's no sub-mounted filesystems
501          * under this mounted lustre tree.
502          */
503         if (getcwd(path2, PATH_MAX) == NULL) {
504                 fprintf(stderr, "getcwd old: %s\n", strerror(errno));
505                 return -1;
506         }
507
508         if (chdir(dir) == -1) {
509                 fprintf(stderr, "chdir to %s: %s\n",
510                         dir, strerror(errno));
511                 return -1;
512         }
513
514         if (getcwd(path, PATH_MAX) == NULL) {
515                 fprintf(stderr, "getcwd new: %s\n", strerror(errno));
516                 return -1;
517         }
518
519         if (chdir(path2) == -1) {
520                 fprintf(stderr, "chdir back: %s\n", strerror(errno));
521                 return -1;
522         }
523
524         fp = setmntent(MOUNTED, "r");
525         if (fp == NULL) {
526                 fprintf(stderr, "setmntent(%s): %s\n", MOUNTED,
527                         strerror(errno));
528                 return -1;
529         }
530
531         while (1) {
532                 mnt = getmntent(fp);
533                 if (!mnt)
534                         break;
535                 
536                 if (!llapi_is_lustre_mnttype(mnt->mnt_type))
537                         continue;
538
539                 if (!strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir))) {
540                         char *p;
541
542                         /* save the mountpoint dir part */
543                         strncpy(dirbuf, mnt->mnt_dir, PATH_MAX);
544
545                         /* get rest of path under the mountpoint,
546                          * don't start with slash.
547                          */
548                         p = path + strlen(mnt->mnt_dir);
549                         while (*p == '/')
550                                 p++;
551                         snprintf(path2, PATH_MAX, "%s", p);
552
553                         /* remove trailing slash */
554                         if (path2[strlen(path2)] == '/')
555                                 path2[strlen(path2)] = '\0';
556                         found = 1;
557                         /* continue try to match more proper fs */
558                 }
559         }
560         endmntent(fp);
561
562         if (!found) {
563                 fprintf(stderr, "no mounted lustre fs\n");
564                 return -1;
565         }
566
567         /* get base name of target */
568         strncpy(path, argv[argc - 1], PATH_MAX);
569         tgt = basename(path);
570
571         cmdbuf[0] = '\0';
572         for (i = 1; i < argc - 1; i++) {
573                 strncat(cmdbuf, argv[i], PATH_MAX);
574                 strncat(cmdbuf, " ", PATH_MAX);
575         }
576         strncat(cmdbuf, path2, PATH_MAX);
577         if (path2[0] != '\0')
578                 strncat(cmdbuf, "/", PATH_MAX);
579         strncat(cmdbuf, tgt, PATH_MAX);
580
581         return 0;
582 }
583
584 static int lfs_getfacl(int argc, char **argv)
585 {
586         char dir[PATH_MAX];
587         char cmd[PATH_MAX];
588
589         if (acl_cmd_parse(argc, argv, dir, cmd))
590                 return CMD_HELP;
591
592         return llapi_getfacl(dir, cmd);
593 }
594
595 static int lfs_setfacl(int argc, char **argv)
596 {
597         char dir[PATH_MAX];
598         char cmd[PATH_MAX];
599
600         if (acl_cmd_parse(argc, argv, dir, cmd))
601                 return CMD_HELP;
602
603         return llapi_setfacl(dir, cmd);
604 }
605
606 int main(int argc, char **argv)
607 {
608         int rc;
609
610         setlinebuf(stdout);
611
612         ptl_initialize(argc, argv);
613         if (obd_initialize(argc, argv) < 0)
614                 exit(2);
615         if (dbg_initialize(argc, argv) < 0)
616                 exit(3);
617
618         Parser_init("lfs > ", cmdlist);
619
620         if (argc > 1) {
621                 rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
622         } else {
623                 rc = Parser_commands();
624         }
625
626         obd_finalize(argc, argv);
627         return rc;
628 }