Whamcloud - gitweb
b=17299
[fs/lustre-release.git] / lustre / utils / obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/utils/obd.c
37  *
38  * Author: Peter J. Braam <braam@clusterfs.com>
39  * Author: Phil Schwan <phil@clusterfs.com>
40  * Author: Andreas Dilger <adilger@clusterfs.com>
41  * Author: Robert Read <rread@clusterfs.com>
42  */
43
44 #include <stdlib.h>
45 #include <sys/ioctl.h>
46 #include <fcntl.h>
47 #include <sys/socket.h>
48 #include <sys/types.h>
49 #include <sys/wait.h>
50 #include <sys/stat.h>
51 #include <stdio.h>
52 #include <stdarg.h>
53 #include <signal.h>
54 #include <ctype.h>
55 #include <glob.h>
56
57 #include "obdctl.h"
58
59 #include <obd.h>          /* for struct lov_stripe_md */
60 #include <lustre/lustre_build_version.h>
61
62 #include <unistd.h>
63 #include <sys/un.h>
64 #include <time.h>
65 #include <sys/time.h>
66 #include <errno.h>
67 #include <string.h>
68
69 #include <obd_class.h>
70 #include <lnet/lnetctl.h>
71 #include <libcfs/libcfsutil.h>
72 #include <stdio.h>
73 #include <lustre/liblustreapi.h>
74
75 #define MAX_STRING_SIZE 128
76 #define DEVICES_LIST "/proc/fs/lustre/devices"
77
78 #if HAVE_LIBPTHREAD
79 #include <sys/ipc.h>
80 #include <sys/shm.h>
81 #include <pthread.h>
82
83 #define MAX_THREADS 1024
84
85 struct shared_data {
86         __u64 counters[MAX_THREADS];
87         __u64 offsets[MAX_THREADS];
88         int   running;
89         int   barrier;
90         int   stop;
91         l_mutex_t mutex;
92         l_cond_t  cond;
93 };
94
95 static struct shared_data *shared_data;
96 static __u64 counter_snapshot[2][MAX_THREADS];
97 static int prev_valid;
98 static struct timeval prev_time;
99 static int thread;
100 static int nthreads;
101 #else
102 const int thread = 0;
103 const int nthreads = 1;
104 #endif
105
106 static char rawbuf[8192];
107 static char *buf = rawbuf;
108 static int max = sizeof(rawbuf);
109
110 static int cur_device = -1;
111
112 #define MAX_STRIPES     170
113 struct lov_oinfo lov_oinfos[MAX_STRIPES];
114
115 struct lsm_buffer {
116         struct lov_stripe_md lsm;
117         struct lov_oinfo *ptrs[MAX_STRIPES];
118 } lsm_buffer;
119
120 static int l2_ioctl(int dev_id, int opc, void *buf)
121 {
122         return l_ioctl(dev_id, opc, buf);
123 }
124
125 #define IOC_INIT(data)                                                  \
126 do {                                                                    \
127         memset(&data, 0, sizeof(data));                                 \
128         data.ioc_dev = cur_device;                                      \
129 } while (0)
130
131 #define IOC_PACK(func, data)                                            \
132 do {                                                                    \
133         memset(buf, 0, sizeof(rawbuf));                                 \
134         if (obd_ioctl_pack(&data, &buf, max)) {                         \
135                 fprintf(stderr, "error: %s: invalid ioctl\n",           \
136                         jt_cmdname(func));                                 \
137                 return -2;                                              \
138         }                                                               \
139 } while (0)
140
141 #define IOC_UNPACK(func, data)                                          \
142 do {                                                                    \
143         if (obd_ioctl_unpack(&data, buf, max)) {                        \
144                 fprintf(stderr, "error: %s: invalid reply\n",           \
145                         jt_cmdname(func));                                 \
146                 return -2;                                              \
147         }                                                               \
148 } while (0)
149
150 int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg)
151 {
152         struct obd_ioctl_data data;
153         int rc;
154
155         IOC_INIT(data);
156         data.ioc_type = LUSTRE_CFG_TYPE;
157         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
158                                         lcfg->lcfg_buflens);
159         data.ioc_pbuf1 = (void *)lcfg;
160         IOC_PACK(func, data);
161
162         rc =  l_ioctl(dev_id, OBD_IOC_PROCESS_CFG, buf);
163
164         return rc;
165 }
166
167 static int do_device(char *func, char *devname);
168
169 static int get_mgs_device()
170 {
171         char mgs[] = "$MGS";
172         static int mgs_device = -1;
173
174         if (mgs_device == -1) {
175                 int rc;
176                 do_disconnect(NULL, 1);
177                 rc = do_device("mgsioc", mgs);
178                 if (rc) {
179                         fprintf(stderr,
180                                 "This command must be run on the MGS.\n");
181                         errno = ENODEV;
182                         return -1;
183                 }
184                 mgs_device = cur_device;
185         }
186         return mgs_device;
187 }
188
189 /* Returns -1 on error with errno set */
190 int lcfg_mgs_ioctl(char *func, int dev_id, struct lustre_cfg *lcfg)
191 {
192         struct obd_ioctl_data data;
193         int rc;
194
195         IOC_INIT(data);
196         rc = data.ioc_dev = get_mgs_device();
197         if (rc < 0)
198                 goto out;
199         data.ioc_type = LUSTRE_CFG_TYPE;
200         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
201                                         lcfg->lcfg_buflens);
202         data.ioc_pbuf1 = (void *)lcfg;
203         IOC_PACK(func, data);
204
205         rc = l_ioctl(dev_id, OBD_IOC_PARAM, buf);
206 out:
207         if (rc) {
208                 if (errno == ENOSYS)
209                         fprintf(stderr, "Make sure cfg_device is set first.\n");
210                 if (errno == EINVAL)
211                         fprintf(stderr, "cfg_device should be of the form "
212                                 "'lustre-MDT0000'\n");
213         }
214         return rc;
215 }
216
217 char *obdo_print(struct obdo *obd)
218 {
219         char buf[1024];
220
221         sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
222                 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
223                 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
224                 "misc: %x\nnlink: %d,\nvalid "LPX64"\n",
225                 obd->o_id, obd->o_gr, obd->o_atime, obd->o_mtime, obd->o_ctime,
226                 obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
227                 obd->o_uid, obd->o_gid, obd->o_flags, obd->o_misc,
228                 obd->o_nlink, obd->o_valid);
229         return strdup(buf);
230 }
231
232
233 #define BAD_VERBOSE (-999999999)
234
235 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
236
237 static int do_name2dev(char *func, char *name)
238 {
239         struct obd_ioctl_data data;
240         int rc;
241
242         IOC_INIT(data);
243
244         data.ioc_inllen1 = strlen(name) + 1;
245         data.ioc_inlbuf1 = name;
246
247         IOC_PACK(func, data);
248         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
249         if (rc < 0)
250                 return errno;
251         IOC_UNPACK(func, data);
252
253         return data.ioc_dev + N2D_OFF;
254 }
255
256 /*
257  * resolve a device name to a device number.
258  * supports a number, $name or %uuid.
259  */
260 int parse_devname(char *func, char *name)
261 {
262         int rc;
263         int ret = -1;
264
265         if (!name)
266                 return ret;
267         if (isdigit(name[0])) {
268                 ret = strtoul(name, NULL, 0);
269         } else {
270                 if (name[0] == '$' || name[0] == '%')
271                         name++;
272                 rc = do_name2dev(func, name);
273                 if (rc >= N2D_OFF) {
274                         ret = rc - N2D_OFF;
275                         // printf("Name %s is device %d\n", name, ret);
276                 } else {
277                         fprintf(stderr, "No device found for name %s: %s\n",
278                                name, strerror(rc));
279                 }
280         }
281         return ret;
282 }
283
284 static void
285 reset_lsmb (struct lsm_buffer *lsmb)
286 {
287         memset (&lsmb->lsm, 0, sizeof (lsmb->lsm));
288         memset(lov_oinfos, 0, sizeof(lov_oinfos));
289         lsmb->lsm.lsm_magic = LOV_MAGIC;
290 }
291
292 static int
293 parse_lsm (struct lsm_buffer *lsmb, char *string)
294 {
295         struct lov_stripe_md *lsm = &lsmb->lsm;
296         char                 *end;
297         int                   i;
298
299         /*
300          * object_id[=size#count[@offset:id]*]
301          */
302
303         reset_lsmb (lsmb);
304
305         lsm->lsm_object_id = strtoull (string, &end, 0);
306         if (end == string)
307                 return (-1);
308         string = end;
309
310         if (*string == 0)
311                 return (0);
312
313         if (*string != '=')
314                 return (-1);
315         string++;
316
317         lsm->lsm_stripe_size = strtoul (string, &end, 0);
318         if (end == string)
319                 return (-1);
320         string = end;
321
322         if (*string != '#')
323                 return (-1);
324         string++;
325
326         lsm->lsm_stripe_count = strtoul (string, &end, 0);
327         if (end == string)
328                 return (-1);
329         string = end;
330
331         if (*string == 0)               /* don't have to specify obj ids */
332                 return (0);
333
334         for (i = 0; i < lsm->lsm_stripe_count; i++) {
335                 if (*string != '@')
336                         return (-1);
337                 string++;
338                 lsm->lsm_oinfo[i]->loi_ost_idx = strtoul(string, &end, 0);
339                 if (*end != ':')
340                         return (-1);
341                 string = end + 1;
342                 lsm->lsm_oinfo[i]->loi_id = strtoull(string, &end, 0);
343                 string = end;
344         }
345
346         if (*string != 0)
347                 return (-1);
348
349         return (0);
350 }
351
352 char *jt_cmdname(char *func)
353 {
354         static char buf[512];
355
356         if (thread) {
357                 sprintf(buf, "%s-%d", func, thread);
358                 return buf;
359         }
360
361         return func;
362 }
363
364 #define difftime(a, b)                                  \
365         ((a)->tv_sec - (b)->tv_sec +                    \
366          ((a)->tv_usec - (b)->tv_usec) / 1000000.0)
367
368 static int be_verbose(int verbose, struct timeval *next_time,
369                       __u64 num, __u64 *next_num, int num_total)
370 {
371         struct timeval now;
372
373         if (!verbose)
374                 return 0;
375
376         if (next_time != NULL)
377                 gettimeofday(&now, NULL);
378
379         /* A positive verbosity means to print every X iterations */
380         if (verbose > 0 && (num >= *next_num || num >= num_total)) {
381                 *next_num += verbose;
382                 if (next_time) {
383                         next_time->tv_sec = now.tv_sec - verbose;
384                         next_time->tv_usec = now.tv_usec;
385                 }
386                 return 1;
387         }
388
389         /* A negative verbosity means to print at most each X seconds */
390         if (verbose < 0 && next_time != NULL &&
391             difftime(&now, next_time) >= 0.0){
392                 next_time->tv_sec = now.tv_sec - verbose;
393                 next_time->tv_usec = now.tv_usec;
394                 *next_num = num;
395                 return 1;
396         }
397
398         return 0;
399 }
400
401 static int get_verbose(char *func, const char *arg)
402 {
403         int verbose;
404         char *end;
405
406         if (!arg || arg[0] == 'v')
407                 verbose = 1;
408         else if (arg[0] == 's' || arg[0] == 'q')
409                 verbose = 0;
410         else {
411                 verbose = (int)strtoul(arg, &end, 0);
412                 if (*end) {
413                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
414                                 jt_cmdname(func), arg);
415                         return BAD_VERBOSE;
416                 }
417         }
418
419         if (verbose < 0)
420                 printf("Print status every %d seconds\n", -verbose);
421         else if (verbose == 1)
422                 printf("Print status every operation\n");
423         else if (verbose > 1)
424                 printf("Print status every %d operations\n", verbose);
425
426         return verbose;
427 }
428
429 int do_disconnect(char *func, int verbose)
430 {
431         lcfg_set_devname(NULL);
432         cur_device = -1;
433         return 0;
434 }
435
436 #ifdef MAX_THREADS
437 static void shmem_setup(void)
438 {
439         /* Create new segment */
440         int shmid = shmget(IPC_PRIVATE, sizeof(*shared_data), 0600);
441
442         if (shmid == -1) {
443                 fprintf(stderr, "Can't create shared data: %s\n",
444                         strerror(errno));
445                 return;
446         }
447
448         /* Attatch to new segment */
449         shared_data = (struct shared_data *)shmat(shmid, NULL, 0);
450
451         if (shared_data == (struct shared_data *)(-1)) {
452                 fprintf(stderr, "Can't attach shared data: %s\n",
453                         strerror(errno));
454                 shared_data = NULL;
455                 return;
456         }
457
458         /* Mark segment as destroyed, so it will disappear when we exit.
459          * Forks will inherit attached segments, so we should be OK.
460          */
461         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
462                 fprintf(stderr, "Can't destroy shared data: %s\n",
463                         strerror(errno));
464         }
465 }
466
467 static inline void shmem_lock(void)
468 {
469         l_mutex_lock(&shared_data->mutex);
470 }
471
472 static inline void shmem_unlock(void)
473 {
474         l_mutex_unlock(&shared_data->mutex);
475 }
476
477 static inline void shmem_reset(int total_threads)
478 {
479         if (shared_data == NULL)
480                 return;
481
482         memset(shared_data, 0, sizeof(*shared_data));
483         l_mutex_init(&shared_data->mutex);
484         l_cond_init(&shared_data->cond);
485         memset(counter_snapshot, 0, sizeof(counter_snapshot));
486         prev_valid = 0;
487         shared_data->barrier = total_threads;
488 }
489
490 static inline void shmem_bump(void)
491 {
492         static int bumped_running;
493
494         if (shared_data == NULL || thread <= 0 || thread > MAX_THREADS)
495                 return;
496
497         shmem_lock();
498         shared_data->counters[thread - 1]++;
499         if (!bumped_running)
500                 shared_data->running++;
501         shmem_unlock();
502         bumped_running = 1;
503 }
504
505 static void shmem_snap(int total_threads, int live_threads)
506 {
507         struct timeval this_time;
508         int non_zero = 0;
509         __u64 total = 0;
510         double secs;
511         int running;
512         int i;
513
514         if (shared_data == NULL || total_threads > MAX_THREADS)
515                 return;
516
517         shmem_lock();
518         memcpy(counter_snapshot[0], shared_data->counters,
519                total_threads * sizeof(counter_snapshot[0][0]));
520         running = shared_data->running;
521         shmem_unlock();
522
523         gettimeofday(&this_time, NULL);
524
525         for (i = 0; i < total_threads; i++) {
526                 long long this_count =
527                         counter_snapshot[0][i] - counter_snapshot[1][i];
528
529                 if (this_count != 0) {
530                         non_zero++;
531                         total += this_count;
532                 }
533         }
534
535         secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
536                (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
537
538         if (prev_valid &&
539             live_threads == total_threads &&
540             secs > 0.0)                    /* someone screwed with the time? */
541                 printf("%d/%d Total: %f/second\n", non_zero, total_threads, total / secs);
542
543         memcpy(counter_snapshot[1], counter_snapshot[0],
544                total_threads * sizeof(counter_snapshot[0][0]));
545         prev_time = this_time;
546         if (!prev_valid &&
547             running == total_threads)
548                 prev_valid = 1;
549 }
550
551 static void shmem_stop(void)
552 {
553         if (shared_data == NULL)
554                 return;
555
556         shared_data->stop = 1;
557 }
558
559 static int shmem_running(void)
560 {
561         return (shared_data == NULL ||
562                 !shared_data->stop);
563 }
564 #else
565 static void shmem_setup(void)
566 {
567 }
568
569 static inline void shmem_reset(int total_threads)
570 {
571 }
572
573 static inline void shmem_bump(void)
574 {
575 }
576
577 static void shmem_lock()
578 {
579 }
580
581 static void shmem_unlock()
582 {
583 }
584
585 static void shmem_stop(void)
586 {
587 }
588
589 static int shmem_running(void)
590 {
591         return 1;
592 }
593 #endif
594
595 extern command_t cmdlist[];
596
597 static int do_device(char *func, char *devname)
598 {
599         int dev;
600
601         dev = parse_devname(func, devname);
602         if (dev < 0)
603                 return -1;
604
605         lcfg_set_devname(devname);
606         cur_device = dev;
607         return 0;
608 }
609
610 int jt_obd_get_device()
611 {
612         return cur_device;
613 }
614
615 int jt_obd_device(int argc, char **argv)
616 {
617         int rc;
618
619         if (argc > 2)
620                 return CMD_HELP;
621
622         if (argc == 1) {
623                 printf("current device is %d - %s\n",
624                        cur_device, lcfg_get_devname() ? : "not set");
625                 return 0;
626         }
627         rc = do_device("device", argv[1]);
628         return rc;
629 }
630
631 int jt_opt_device(int argc, char **argv)
632 {
633         int ret;
634         int rc;
635
636         if (argc < 3)
637                 return CMD_HELP;
638
639         rc = do_device("device", argv[1]);
640
641         if (!rc)
642                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
643
644         ret = do_disconnect(argv[0], 0);
645         if (!rc)
646                 rc = ret;
647
648         return rc;
649 }
650
651 #ifdef MAX_THREADS
652 static void parent_sighandler (int sig)
653 {
654         return;
655 }
656
657 int jt_opt_threads(int argc, char **argv)
658 {
659         static char      cmdstr[128];
660         sigset_t         saveset;
661         sigset_t         sigset;
662         struct sigaction sigact;
663         struct sigaction saveact1;
664         struct sigaction saveact2;
665         unsigned long    threads;
666         __u64            next_thread;
667         int verbose;
668         int rc = 0;
669         int report_count = -1;
670         char *end;
671         int i;
672
673         if (argc < 5)
674                 return CMD_HELP;
675
676         threads = strtoul(argv[1], &end, 0);
677
678         if (*end == '.')
679                 report_count = strtoul(end + 1, &end, 0);
680
681         if (*end || threads > MAX_THREADS) {
682                 fprintf(stderr, "error: %s: invalid thread count '%s'\n",
683                         jt_cmdname(argv[0]), argv[1]);
684                 return CMD_HELP;
685         }
686
687         verbose = get_verbose(argv[0], argv[2]);
688         if (verbose == BAD_VERBOSE)
689                 return CMD_HELP;
690
691         if (verbose != 0) {
692                 snprintf(cmdstr, sizeof(cmdstr), "%s", argv[4]);
693                 for (i = 5; i < argc; i++)
694                         snprintf(cmdstr + strlen(cmdstr), sizeof(cmdstr),
695                                  " %s", argv[i]);
696
697                 printf("%s: starting %ld threads on device %s running %s\n",
698                        argv[0], threads, argv[3], cmdstr);
699         }
700
701         shmem_reset(threads);
702
703         sigemptyset(&sigset);
704         sigaddset(&sigset, SIGALRM);
705         sigaddset(&sigset, SIGCHLD);
706         sigprocmask(SIG_BLOCK, &sigset, &saveset);
707
708         nthreads = threads;
709
710         for (i = 1, next_thread = verbose; i <= threads; i++) {
711                 rc = fork();
712                 if (rc < 0) {
713                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
714                                 strerror(rc = errno));
715                         break;
716                 } else if (rc == 0) {
717                         sigprocmask(SIG_SETMASK, &saveset, NULL);
718
719                         thread = i;
720                         argv[2] = "--device";
721                         return jt_opt_device(argc - 2, argv + 2);
722                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
723                         printf("%s: thread #%d (PID %d) started\n",
724                                argv[0], i, rc);
725                 rc = 0;
726         }
727
728         if (!thread) {          /* parent process */
729                 int live_threads = threads;
730
731                 sigemptyset(&sigset);
732                 sigemptyset(&sigact.sa_mask);
733                 sigact.sa_handler = parent_sighandler;
734                 sigact.sa_flags = 0;
735
736                 sigaction(SIGALRM, &sigact, &saveact1);
737                 sigaction(SIGCHLD, &sigact, &saveact2);
738
739                 while (live_threads > 0) {
740                         int status;
741                         pid_t ret;
742
743                         if (verbose < 0)        /* periodic stats */
744                                 alarm(-verbose);
745
746                         sigsuspend(&sigset);
747                         alarm(0);
748
749                         while (live_threads > 0) {
750                                 ret = waitpid(0, &status, WNOHANG);
751                                 if (ret == 0)
752                                         break;
753
754                                 if (ret < 0) {
755                                         fprintf(stderr, "error: %s: wait - %s\n",
756                                                 argv[0], strerror(errno));
757                                         if (!rc)
758                                                 rc = errno;
759                                         continue;
760                                 } else {
761                                         /*
762                                          * This is a hack.  We _should_ be able
763                                          * to use WIFEXITED(status) to see if
764                                          * there was an error, but it appears
765                                          * to be broken and it always returns 1
766                                          * (OK).  See wait(2).
767                                          */
768                                         int err = WEXITSTATUS(status);
769                                         if (err || WIFSIGNALED(status))
770                                                 fprintf(stderr,
771                                                         "%s: PID %d had rc=%d\n",
772                                                         argv[0], ret, err);
773                                         if (!rc)
774                                                 rc = err;
775
776                                         live_threads--;
777                                 }
778                         }
779
780                         /* Show stats while all threads running */
781                         if (verbose < 0) {
782                                 shmem_snap(threads, live_threads);
783                                 if (report_count > 0 && --report_count == 0)
784                                         shmem_stop();
785                         }
786                 }
787                 sigaction(SIGCHLD, &saveact2, NULL);
788                 sigaction(SIGALRM, &saveact1, NULL);
789         }
790
791         sigprocmask(SIG_SETMASK, &saveset, NULL);
792
793         return rc;
794 }
795 #else
796 int jt_opt_threads(int argc, char **argv)
797 {
798         fprintf(stderr, "%s not-supported in a single-threaded runtime\n",
799                 jt_cmdname(argv[0]));
800         return CMD_HELP;
801 }
802 #endif
803
804 int jt_opt_net(int argc, char **argv)
805 {
806         char *arg2[3];
807         int rc;
808
809         if (argc < 3)
810                 return CMD_HELP;
811
812         arg2[0] = argv[0];
813         arg2[1] = argv[1];
814         arg2[2] = NULL;
815         rc = jt_ptl_network (2, arg2);
816
817         if (!rc)
818                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
819
820         return rc;
821 }
822
823 int jt_obd_no_transno(int argc, char **argv)
824 {
825         struct obd_ioctl_data data;
826         int rc;
827
828         IOC_INIT(data);
829
830         if (argc != 1)
831                 return CMD_HELP;
832
833         IOC_PACK(argv[0], data);
834         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf);
835         if (rc < 0)
836                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
837                         strerror(rc = errno));
838
839         return rc;
840 }
841
842 int jt_obd_set_readonly(int argc, char **argv)
843 {
844         struct obd_ioctl_data data;
845         int rc;
846
847         IOC_INIT(data);
848
849         if (argc != 1)
850                 return CMD_HELP;
851
852         IOC_PACK(argv[0], data);
853         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf);
854         if (rc < 0)
855                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
856                         strerror(rc = errno));
857
858         return rc;
859 }
860
861 int jt_obd_abort_recovery(int argc, char **argv)
862 {
863         struct obd_ioctl_data data;
864         int rc;
865
866         IOC_INIT(data);
867
868         if (argc != 1)
869                 return CMD_HELP;
870
871         IOC_PACK(argv[0], data);
872         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf);
873         if (rc < 0)
874                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
875                         strerror(rc = errno));
876
877         return rc;
878 }
879
880 int jt_get_version(int argc, char **argv)
881 {
882         int rc;
883         char buf[8192];
884         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
885
886         if (argc != 1)
887                 return CMD_HELP;
888
889         memset(buf, 0, sizeof(buf));
890         data->ioc_version = OBD_IOCTL_VERSION;
891         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
892         data->ioc_inlbuf1 = buf + size_round(sizeof(*data));
893         data->ioc_len = obd_ioctl_packlen(data);
894
895         rc = l2_ioctl(OBD_DEV_ID, OBD_GET_VERSION, buf);
896         if (rc < 0)
897                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
898                         strerror(rc = errno));
899         else {
900                 printf("Lustre version: %s\n", data->ioc_bulk);
901         }
902
903         printf("lctl   version: %s\n", BUILD_VERSION);
904         return rc;
905 }
906
907 /*
908  * Print an obd device line with the ost_conn_uuid inserted, if the obd
909  * is an osc.
910  */
911 static void print_obd_line(char *s)
912 {
913         char buf[MAX_STRING_SIZE];
914         char obd_name[MAX_OBD_NAME];
915         FILE *fp = NULL;
916         char *ptr;
917
918         if (sscanf(s, " %*d %*s osc %s %*s %*d ", obd_name) == 0)
919                 goto try_mdc;
920         snprintf(buf, sizeof(buf),
921                  "/proc/fs/lustre/osc/%s/ost_conn_uuid", obd_name);
922         if ((fp = fopen(buf, "r")) == NULL)
923                 goto try_mdc;
924         goto got_one;
925
926 try_mdc:
927         if (sscanf(s, " %*d %*s mdc %s %*s %*d ", obd_name) == 0)
928                 goto fail;
929         snprintf(buf, sizeof(buf),
930                  "/proc/fs/lustre/mdc/%s/mds_conn_uuid", obd_name);
931         if ((fp = fopen(buf, "r")) == NULL)
932                 goto fail;
933
934 got_one:
935         fgets(buf, sizeof(buf), fp);
936         fclose(fp);
937
938         /* trim trailing newlines */
939         ptr = strrchr(buf, '\n');
940         if (ptr) *ptr = '\0';
941         ptr = strrchr(s, '\n');
942         if (ptr) *ptr = '\0';
943
944         printf("%s %s\n", s, buf);
945         return;
946
947 fail:
948         printf("%s", s);
949         return;
950 }
951
952 /* get device list by ioctl */
953 int jt_obd_list_ioctl(int argc, char **argv)
954 {
955         int rc, index;
956         char buf[8192];
957         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
958
959         if (argc > 2)
960                 return CMD_HELP;
961         /* Just ignore a -t option.  Only supported with /proc. */
962         else if (argc == 2 && strcmp(argv[1], "-t") != 0)
963                 return CMD_HELP;
964
965         for (index = 0;; index++) {
966                 memset(buf, 0, sizeof(buf));
967                 data->ioc_version = OBD_IOCTL_VERSION;
968                 data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
969                 data->ioc_inlbuf1 = buf + size_round(sizeof(*data));
970                 data->ioc_len = obd_ioctl_packlen(data);
971                 data->ioc_count = index;
972
973                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETDEVICE, buf);
974                 if (rc != 0)
975                         break;
976                 printf("%s\n", (char *)data->ioc_bulk);
977         }
978         if (rc != 0) {
979                 if (errno == ENOENT)
980                         /* no device or the last device */
981                         rc = 0;
982                 else
983                         fprintf(stderr, "Error getting device list: %s: "
984                                         "check dmesg.\n",
985                                         strerror(errno));
986         }
987         return rc;
988 }
989
990 int jt_obd_list(int argc, char **argv)
991 {
992         int rc;
993         char buf[MAX_STRING_SIZE];
994         FILE *fp = NULL;
995         int print_obd = 0;
996
997         if (argc > 2)
998                 return CMD_HELP;
999         else if (argc == 2) {
1000                 if (strcmp(argv[1], "-t") == 0)
1001                         print_obd = 1;
1002                 else
1003                         return CMD_HELP;
1004         }
1005
1006         fp = fopen(DEVICES_LIST, "r");
1007         if (fp == NULL) {
1008                 fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
1009                         jt_cmdname(argv[0]), strerror(rc =  errno));
1010                 return jt_obd_list_ioctl(argc, argv);
1011         }
1012
1013         while (fgets(buf, sizeof(buf), fp) != NULL)
1014                 if (print_obd)
1015                         print_obd_line(buf);
1016                 else
1017                         printf("%s", buf);
1018
1019         fclose(fp);
1020         return 0;
1021 }
1022
1023
1024
1025
1026 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1027  * not, defaults assumed.  This echo-client instance stashes the stripe
1028  * object ids.  Use get_stripe on this node to print full lsm and
1029  * set_stripe on another node to cut/paste between nodes.
1030  */
1031 /* create <count> [<file_create_mode>] [q|v|# verbosity] [striping] */
1032 int jt_obd_create(int argc, char **argv)
1033 {
1034         struct obd_ioctl_data data;
1035         struct timeval next_time;
1036         __u64 count = 1, next_count, base_id = 0;
1037         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
1038         char *end;
1039
1040         IOC_INIT(data);
1041         if (argc < 2 || argc > 5)
1042                 return CMD_HELP;
1043
1044         count = strtoull(argv[1], &end, 0);
1045         if (*end) {
1046                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1047                         jt_cmdname(argv[0]), argv[1]);
1048                 return CMD_HELP;
1049         }
1050
1051         if (argc > 2) {
1052                 mode = strtoul(argv[2], &end, 0);
1053                 if (*end) {
1054                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1055                                 jt_cmdname(argv[0]), argv[2]);
1056                         return CMD_HELP;
1057                 }
1058                 if (!(mode & S_IFMT))
1059                         mode |= S_IFREG;
1060         }
1061
1062         if (argc > 3) {
1063                 verbose = get_verbose(argv[0], argv[3]);
1064                 if (verbose == BAD_VERBOSE)
1065                         return CMD_HELP;
1066         }
1067
1068         if (argc < 5)
1069                 reset_lsmb (&lsm_buffer);       /* will set default */
1070         else {
1071                 rc = parse_lsm (&lsm_buffer, argv[4]);
1072                 if (rc != 0) {
1073                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1074                                 jt_cmdname(argv[0]), argv[4]);
1075                         return CMD_HELP;
1076                 }
1077                 base_id = lsm_buffer.lsm.lsm_object_id;
1078                 valid_lsm = 1;
1079         }
1080
1081         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1082         gettimeofday(&next_time, NULL);
1083         next_time.tv_sec -= verbose;
1084
1085         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1086                 data.ioc_obdo1.o_mode = mode;
1087                 data.ioc_obdo1.o_id = base_id;
1088                 data.ioc_obdo1.o_uid = 0;
1089                 data.ioc_obdo1.o_gid = 0;
1090                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1091                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1092
1093                 if (valid_lsm) {
1094                         data.ioc_plen1 = sizeof lsm_buffer;
1095                         data.ioc_pbuf1 = (char *)&lsm_buffer;
1096                 }
1097
1098                 IOC_PACK(argv[0], data);
1099                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1100                 IOC_UNPACK(argv[0], data);
1101                 shmem_bump();
1102                 if (rc < 0) {
1103                         fprintf(stderr, "error: %s: #%d - %s\n",
1104                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1105                         break;
1106                 }
1107                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1108                         fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n",
1109                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1110                         rc = EINVAL;
1111                         break;
1112                 }
1113
1114                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1115                         printf("%s: #%d is object id "LPX64"\n",
1116                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1117         }
1118         return rc;
1119 }
1120
1121 int jt_obd_setattr(int argc, char **argv)
1122 {
1123         struct obd_ioctl_data data;
1124         char *end;
1125         int rc;
1126
1127         IOC_INIT(data);
1128         if (argc != 2)
1129                 return CMD_HELP;
1130
1131         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1132         if (*end) {
1133                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1134                         jt_cmdname(argv[0]), argv[1]);
1135                 return CMD_HELP;
1136         }
1137         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1138         if (*end) {
1139                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1140                         jt_cmdname(argv[0]), argv[2]);
1141                 return CMD_HELP;
1142         }
1143         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1144
1145         IOC_PACK(argv[0], data);
1146         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1147         if (rc < 0)
1148                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1149                         strerror(rc = errno));
1150
1151         return rc;
1152 }
1153
1154 int jt_obd_test_setattr(int argc, char **argv)
1155 {
1156         struct obd_ioctl_data data;
1157         struct timeval start, next_time;
1158         __u64 i, count, next_count;
1159         int verbose = 1;
1160         obd_id objid = 3;
1161         char *end;
1162         int rc = 0;
1163
1164         if (argc < 2 || argc > 4)
1165                 return CMD_HELP;
1166
1167         IOC_INIT(data);
1168         count = strtoull(argv[1], &end, 0);
1169         if (*end) {
1170                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1171                         jt_cmdname(argv[0]), argv[1]);
1172                 return CMD_HELP;
1173         }
1174
1175         if (argc >= 3) {
1176                 verbose = get_verbose(argv[0], argv[2]);
1177                 if (verbose == BAD_VERBOSE)
1178                         return CMD_HELP;
1179         }
1180
1181         if (argc >= 4) {
1182                 if (argv[3][0] == 't') {
1183                         objid = strtoull(argv[3] + 1, &end, 0);
1184                         if (thread)
1185                                 objid += thread - 1;
1186                 } else
1187                         objid = strtoull(argv[3], &end, 0);
1188                 if (*end) {
1189                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1190                                 jt_cmdname(argv[0]), argv[3]);
1191                         return CMD_HELP;
1192                 }
1193         }
1194
1195         gettimeofday(&start, NULL);
1196         next_time.tv_sec = start.tv_sec - verbose;
1197         next_time.tv_usec = start.tv_usec;
1198         if (verbose != 0)
1199                 printf("%s: setting "LPD64" attrs (objid "LPX64"): %s",
1200                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1201
1202         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1203                 data.ioc_obdo1.o_id = objid;
1204                 data.ioc_obdo1.o_mode = S_IFREG;
1205                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1206                 IOC_PACK(argv[0], data);
1207                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data);
1208                 shmem_bump();
1209                 if (rc < 0) {
1210                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1211                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1212                         break;
1213                 } else {
1214                         if (be_verbose
1215                             (verbose, &next_time, i, &next_count, count))
1216                                 printf("%s: set attr #"LPD64"\n",
1217                                        jt_cmdname(argv[0]), i);
1218                 }
1219         }
1220
1221         if (!rc) {
1222                 struct timeval end;
1223                 double diff;
1224
1225                 gettimeofday(&end, NULL);
1226
1227                 diff = difftime(&end, &start);
1228
1229                 --i;
1230                 if (verbose != 0)
1231                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1232                                jt_cmdname(argv[0]), i, diff, i / diff,
1233                                ctime(&end.tv_sec));
1234         }
1235         return rc;
1236 }
1237
1238 int jt_obd_destroy(int argc, char **argv)
1239 {
1240         struct obd_ioctl_data data;
1241         struct timeval next_time;
1242         __u64 count = 1, next_count;
1243         int verbose = 1;
1244         __u64 id;
1245         char *end;
1246         int rc = 0, i;
1247
1248         IOC_INIT(data);
1249         if (argc < 2 || argc > 4)
1250                 return CMD_HELP;
1251
1252         id = strtoull(argv[1], &end, 0);
1253         if (*end || id == 0 || errno != 0) {
1254                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1255                         jt_cmdname(argv[0]), argv[1]);
1256                 return CMD_HELP;
1257         }
1258         if (argc > 2) {
1259                 count = strtoull(argv[2], &end, 0);
1260                 if (*end) {
1261                         fprintf(stderr,
1262                                 "error: %s: invalid iteration count '%s'\n",
1263                                 jt_cmdname(argv[0]), argv[2]);
1264                         return CMD_HELP;
1265                 }
1266         }
1267
1268         if (argc > 3) {
1269                 verbose = get_verbose(argv[0], argv[3]);
1270                 if (verbose == BAD_VERBOSE)
1271                         return CMD_HELP;
1272         }
1273
1274         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1275         gettimeofday(&next_time, NULL);
1276         next_time.tv_sec -= verbose;
1277
1278         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++, id++) {
1279                 data.ioc_obdo1.o_id = id;
1280                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1281                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1282
1283                 IOC_PACK(argv[0], data);
1284                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1285                 IOC_UNPACK(argv[0], data);
1286                 shmem_bump();
1287                 if (rc < 0) {
1288                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1289                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1290                         break;
1291                 }
1292
1293                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1294                         printf("%s: #%d is object id "LPX64"\n",
1295                                jt_cmdname(argv[0]), i, id);
1296         }
1297
1298         return rc;
1299 }
1300
1301 int jt_obd_getattr(int argc, char **argv)
1302 {
1303         struct obd_ioctl_data data;
1304         char *end;
1305         int rc;
1306
1307         if (argc != 2)
1308                 return CMD_HELP;
1309
1310         IOC_INIT(data);
1311         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1312         if (*end) {
1313                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1314                         jt_cmdname(argv[0]), argv[1]);
1315                 return CMD_HELP;
1316         }
1317         /* to help obd filter */
1318         data.ioc_obdo1.o_mode = 0100644;
1319         data.ioc_obdo1.o_valid = 0xffffffff;
1320         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1321
1322         IOC_PACK(argv[0], data);
1323         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1324         IOC_UNPACK(argv[0], data);
1325         if (rc) {
1326                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1327                         strerror(rc = errno));
1328         } else {
1329                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1330                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1331         }
1332         return rc;
1333 }
1334
1335 int jt_obd_test_getattr(int argc, char **argv)
1336 {
1337         struct obd_ioctl_data data;
1338         struct timeval start, next_time;
1339         __u64 i, count, next_count;
1340         int verbose = 1;
1341         obd_id objid = 3;
1342         char *end;
1343         int rc = 0;
1344
1345         if (argc < 2 || argc > 4)
1346                 return CMD_HELP;
1347
1348         IOC_INIT(data);
1349         count = strtoull(argv[1], &end, 0);
1350         if (*end) {
1351                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1352                         jt_cmdname(argv[0]), argv[1]);
1353                 return CMD_HELP;
1354         }
1355
1356         if (argc >= 3) {
1357                 verbose = get_verbose(argv[0], argv[2]);
1358                 if (verbose == BAD_VERBOSE)
1359                         return CMD_HELP;
1360         }
1361
1362         if (argc >= 4) {
1363                 if (argv[3][0] == 't') {
1364                         objid = strtoull(argv[3] + 1, &end, 0);
1365                         if (thread)
1366                                 objid += thread - 1;
1367                 } else
1368                         objid = strtoull(argv[3], &end, 0);
1369                 if (*end) {
1370                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1371                                 jt_cmdname(argv[0]), argv[3]);
1372                         return CMD_HELP;
1373                 }
1374         }
1375
1376         gettimeofday(&start, NULL);
1377         next_time.tv_sec = start.tv_sec - verbose;
1378         next_time.tv_usec = start.tv_usec;
1379         if (verbose != 0)
1380                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1381                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1382
1383         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1384                 data.ioc_obdo1.o_id = objid;
1385                 data.ioc_obdo1.o_mode = S_IFREG;
1386                 data.ioc_obdo1.o_valid = 0xffffffff;
1387                 IOC_PACK(argv[0], data);
1388                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1389                 shmem_bump();
1390                 if (rc < 0) {
1391                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1392                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1393                         break;
1394                 } else {
1395                         if (be_verbose
1396                             (verbose, &next_time, i, &next_count, count))
1397                                 printf("%s: got attr #"LPD64"\n",
1398                                        jt_cmdname(argv[0]), i);
1399                 }
1400         }
1401
1402         if (!rc) {
1403                 struct timeval end;
1404                 double diff;
1405
1406                 gettimeofday(&end, NULL);
1407
1408                 diff = difftime(&end, &start);
1409
1410                 --i;
1411                 if (verbose != 0)
1412                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1413                                jt_cmdname(argv[0]), i, diff, i / diff,
1414                                ctime(&end.tv_sec));
1415         }
1416         return rc;
1417 }
1418
1419 /* test_brw <cnt>                                               count
1420         <r|w[r(repeat)x(noverify)]>                             mode
1421         <q|v|#(print interval)>                                 verbosity
1422         <npages[+offset]>                                       blocksize
1423         <[[<interleave_threads>]t(inc obj by thread#)]obj>      object
1424         [p|g<args>]                                             batch */
1425 int jt_obd_test_brw(int argc, char **argv)
1426 {
1427         struct obd_ioctl_data data;
1428         struct timeval start, next_time;
1429         __u64 count, next_count, len, stride, thr_offset = 0, objid = 3;
1430         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1431         int offset_pages = 0;
1432         long n;
1433         int repeat_offset = 0;
1434         unsigned long long ull;
1435         int  nthr_per_obj = 0;
1436         int  verify = 1;
1437         int  obj_idx = 0;
1438         char *end;
1439
1440         if (argc < 2 || argc > 7) {
1441                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1442                         jt_cmdname(argv[0]), argc);
1443                 return CMD_HELP;
1444         }
1445
1446         count = strtoull(argv[1], &end, 0);
1447         if (*end) {
1448                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1449                         jt_cmdname(argv[0]), argv[1]);
1450                 return CMD_HELP;
1451         }
1452
1453         if (argc >= 3) {
1454                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1455                         write = 1;
1456                 /* else it's a read */
1457
1458                 if (argv[2][0] != 0)
1459                         for (i = 1; argv[2][i] != 0; i++)
1460                                 switch (argv[2][i]) {
1461                                 case 'r':
1462                                         repeat_offset = 1;
1463                                         break;
1464
1465                                 case 'x':
1466                                         verify = 0;
1467                                         break;
1468
1469                                 default:
1470                                         fprintf (stderr, "Can't parse cmd '%s'\n",
1471                                                  argv[2]);
1472                                         return CMD_HELP;
1473                                 }
1474         }
1475
1476         if (argc >= 4) {
1477                 verbose = get_verbose(argv[0], argv[3]);
1478                 if (verbose == BAD_VERBOSE)
1479                         return CMD_HELP;
1480         }
1481
1482         if (argc >= 5) {
1483                 pages = strtoul(argv[4], &end, 0);
1484
1485                 if (*end == '+')
1486                         offset_pages = strtoul(end + 1, &end, 0);
1487
1488                 if (*end != 0 ||
1489                     offset_pages < 0 || offset_pages >= pages) {
1490                         fprintf(stderr, "error: %s: bad npages[+offset] parameter '%s'\n",
1491                                 jt_cmdname(argv[0]), argv[4]);
1492                         return CMD_HELP;
1493                 }
1494         }
1495
1496         if (argc >= 6) {
1497                 if (thread &&
1498                     (n = strtol(argv[5], &end, 0)) > 0 &&
1499                     *end == 't' &&
1500                     (ull = strtoull(end + 1, &end, 0)) > 0 &&
1501                     *end == 0) {
1502                         nthr_per_obj = n;
1503                         objid = ull;
1504                 } else if (thread &&
1505                            argv[5][0] == 't') {
1506                         nthr_per_obj = 1;
1507                         objid = strtoull(argv[5] + 1, &end, 0);
1508                 } else {
1509                         nthr_per_obj = 0;
1510                         objid = strtoull(argv[5], &end, 0);
1511                 }
1512                 if (*end) {
1513                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1514                                 jt_cmdname(argv[0]), argv[5]);
1515                         return CMD_HELP;
1516                 }
1517         }
1518
1519         IOC_INIT(data);
1520
1521         /* communicate the 'type' of brw test and batching to echo_client.
1522          * don't start.  we'd love to refactor this lctl->echo_client
1523          * interface */
1524         data.ioc_pbuf1 = (void *)1;
1525         data.ioc_plen1 = 1;
1526
1527         if (argc >= 7) {
1528                 switch(argv[6][0]) {
1529                         case 'g': /* plug and unplug */
1530                                 data.ioc_pbuf1 = (void *)2;
1531                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1532                                                           0);
1533                                 break;
1534                         case 'p': /* prep and commit */
1535                                 data.ioc_pbuf1 = (void *)3;
1536                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1537                                                           0);
1538                                 break;
1539                         default:
1540                                 fprintf(stderr, "error: %s: batching '%s' "
1541                                         "needs to specify 'p' or 'g'\n",
1542                                         jt_cmdname(argv[0]), argv[6]);
1543                                 return CMD_HELP;
1544                 }
1545
1546                 if (*end) {
1547                         fprintf(stderr, "error: %s: bad batching '%s'\n",
1548                                 jt_cmdname(argv[0]), argv[6]);
1549                         return CMD_HELP;
1550                 }
1551                 data.ioc_plen1 *= getpagesize();
1552         }
1553
1554         len = pages * getpagesize();
1555         thr_offset = offset_pages * getpagesize();
1556         stride = len;
1557
1558 #ifdef MAX_THREADS
1559         if (thread) {
1560                 shmem_lock ();
1561                 if (nthr_per_obj != 0) {
1562                         /* threads interleave */
1563                         obj_idx = (thread - 1)/nthr_per_obj;
1564                         objid += obj_idx;
1565                         stride *= nthr_per_obj;
1566                         if (thread == 1)
1567                                 shared_data->offsets[obj_idx] = stride + thr_offset;
1568                         thr_offset += ((thread - 1) % nthr_per_obj) * len;
1569                 } else {
1570                         /* threads disjoint */
1571                         thr_offset += (thread - 1) * len;
1572                 }
1573
1574                 shared_data->barrier--;
1575                 if (shared_data->barrier == 0)
1576                         l_cond_broadcast(&shared_data->cond);
1577                 else
1578                         l_cond_wait(&shared_data->cond,
1579                                           &shared_data->mutex);
1580
1581                 shmem_unlock ();
1582         }
1583 #endif
1584
1585         data.ioc_obdo1.o_id = objid;
1586         data.ioc_obdo1.o_mode = S_IFREG;
1587         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS;
1588         data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0);
1589         data.ioc_count = len;
1590         data.ioc_offset = (repeat_offset ? 0 : thr_offset);
1591
1592         gettimeofday(&start, NULL);
1593         next_time.tv_sec = start.tv_sec - verbose;
1594         next_time.tv_usec = start.tv_usec;
1595
1596         if (verbose != 0)
1597                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1598                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
1599                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1600
1601         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1602         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1603                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
1604                 IOC_PACK(argv[0], data);
1605                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
1606                 shmem_bump();
1607                 if (rc) {
1608                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1609                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
1610                                 write ? "write" : "read");
1611                         break;
1612                 } else if (be_verbose(verbose, &next_time,i, &next_count,count)) {
1613                         shmem_lock ();
1614                         printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n",
1615                                jt_cmdname(argv[0]), write ? "write" : "read", i,
1616                                data.ioc_obdo1.o_id, data.ioc_offset,
1617                                (int)(pages * getpagesize()));
1618                         shmem_unlock ();
1619                 }
1620
1621                 if (!repeat_offset) {
1622 #ifdef MAX_THREADS
1623                         if (stride == len) {
1624                                 data.ioc_offset += stride;
1625                         } else if (i < count) {
1626                                 shmem_lock ();
1627                                 data.ioc_offset = shared_data->offsets[obj_idx];
1628                                 shared_data->offsets[obj_idx] += len;
1629                                 shmem_unlock ();
1630                         }
1631 #else
1632                         data.ioc_offset += len;
1633                         obj_idx = 0; /* avoids an unused var warning */
1634 #endif
1635                 }
1636         }
1637
1638         if (!rc) {
1639                 struct timeval end;
1640                 double diff;
1641
1642                 gettimeofday(&end, NULL);
1643
1644                 diff = difftime(&end, &start);
1645
1646                 --i;
1647                 if (verbose != 0)
1648                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
1649                                jt_cmdname(argv[0]), write ? "wrote" : "read",
1650                                i, pages, diff,
1651                                ((double)i * pages * getpagesize()) /
1652                                (diff * 1048576.0),
1653                                ctime(&end.tv_sec));
1654         }
1655
1656         return rc;
1657 }
1658
1659 int jt_obd_lov_getconfig(int argc, char **argv)
1660 {
1661         struct obd_ioctl_data data;
1662         struct lov_desc desc;
1663         struct obd_uuid *uuidarray;
1664         __u32 *obdgens;
1665         char *path;
1666         int rc, fd;
1667
1668         IOC_INIT(data);
1669
1670         if (argc != 2)
1671                 return CMD_HELP;
1672
1673         path = argv[1];
1674         fd = open(path, O_RDONLY);
1675         if (fd < 0) {
1676                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1677                         strerror(errno));
1678                 return -errno;
1679         }
1680
1681         memset(&desc, 0, sizeof(desc));
1682         obd_str2uuid(&desc.ld_uuid, argv[1]);
1683         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
1684                              (sizeof(*uuidarray) + sizeof(*obdgens)));
1685
1686
1687 repeat:
1688         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1689         if (!uuidarray) {
1690                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1691                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1692                 rc = -ENOMEM;
1693                 goto out;
1694         }
1695         obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens));
1696         if (!obdgens) {
1697                 fprintf(stderr, "error: %s: no memory for %d generation #'s\n",
1698                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1699                 rc = -ENOMEM;
1700                 goto out_uuidarray;
1701         }
1702
1703         data.ioc_inllen1 = sizeof(desc);
1704         data.ioc_inlbuf1 = (char *)&desc;
1705         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1706         data.ioc_inlbuf2 = (char *)uuidarray;
1707         data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens);
1708         data.ioc_inlbuf3 = (char *)obdgens;
1709
1710         if (obd_ioctl_pack(&data, &buf, max)) {
1711                 fprintf(stderr, "error: %s: invalid ioctl\n",
1712                         jt_cmdname(argv[0]));
1713                 rc = -EINVAL;
1714                 goto out_obdgens;
1715         }
1716         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1717         if (rc == -ENOSPC) {
1718                 free(uuidarray);
1719                 free(obdgens);
1720                 goto repeat;
1721         } else if (rc) {
1722                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1723                         jt_cmdname(argv[0]), strerror(rc = errno));
1724         } else {
1725                 struct obd_uuid *uuidp;
1726                 __u32 *genp;
1727                 int i;
1728
1729                 if (obd_ioctl_unpack(&data, buf, max)) {
1730                         fprintf(stderr, "error: %s: invalid reply\n",
1731                                 jt_cmdname(argv[0]));
1732                         rc = -EINVAL;
1733                         goto out;
1734                 }
1735                 if (desc.ld_default_stripe_count == (__u32)-1)
1736                         printf("default_stripe_count: %d\n", -1);
1737                 else
1738                         printf("default_stripe_count: %u\n",
1739                                desc.ld_default_stripe_count);
1740                 printf("default_stripe_size: "LPU64"\n",
1741                        desc.ld_default_stripe_size);
1742                 printf("default_stripe_offset: "LPU64"\n",
1743                        desc.ld_default_stripe_offset);
1744                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1745                 printf("obd_count: %u\n", desc.ld_tgt_count);
1746                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
1747                 uuidp = uuidarray;
1748                 genp = obdgens;
1749                 for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++)
1750                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp);
1751         }
1752 out_obdgens:
1753         free(obdgens);
1754 out_uuidarray:
1755         free(uuidarray);
1756 out:
1757         close(fd);
1758         return rc;
1759 }
1760
1761 int jt_obd_ldlm_regress_start(int argc, char **argv)
1762 {
1763         int rc;
1764         struct obd_ioctl_data data;
1765         char argstring[200];
1766         int i, count = sizeof(argstring) - 1;
1767
1768         IOC_INIT(data);
1769         if (argc > 5)
1770                 return CMD_HELP;
1771
1772         argstring[0] = '\0';
1773         for (i = 1; i < argc; i++) {
1774                 strncat(argstring, " ", count);
1775                 count--;
1776                 strncat(argstring, argv[i], count);
1777                 count -= strlen(argv[i]);
1778         }
1779
1780         if (strlen(argstring)) {
1781                 data.ioc_inlbuf1 = argstring;
1782                 data.ioc_inllen1 = strlen(argstring) + 1;
1783         }
1784
1785         IOC_PACK(argv[0], data);
1786         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1787         if (rc)
1788                 fprintf(stderr, "error: %s: test failed: %s\n",
1789                         jt_cmdname(argv[0]), strerror(rc = errno));
1790
1791         return rc;
1792 }
1793
1794 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1795 {
1796         int rc;
1797         struct obd_ioctl_data data;
1798         IOC_INIT(data);
1799
1800         if (argc != 1)
1801                 return CMD_HELP;
1802
1803         IOC_PACK(argv[0], data);
1804         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1805
1806         if (rc)
1807                 fprintf(stderr, "error: %s: test failed: %s\n",
1808                         jt_cmdname(argv[0]), strerror(rc = errno));
1809         return rc;
1810 }
1811
1812 static int do_activate(int argc, char **argv, int flag)
1813 {
1814         struct obd_ioctl_data data;
1815         int rc;
1816
1817         IOC_INIT(data);
1818         if (argc != 1)
1819                 return CMD_HELP;
1820
1821         /* reuse offset for 'active' */
1822         data.ioc_offset = flag;
1823
1824         IOC_PACK(argv[0], data);
1825         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1826         if (rc)
1827                 fprintf(stderr, "error: %s: failed: %s\n",
1828                         jt_cmdname(argv[0]), strerror(rc = errno));
1829
1830         return rc;
1831 }
1832
1833 int jt_obd_deactivate(int argc, char **argv)
1834 {
1835         return do_activate(argc, argv, 0);
1836 }
1837
1838 int jt_obd_activate(int argc, char **argv)
1839 {
1840         return do_activate(argc, argv, 1);
1841 }
1842
1843 int jt_obd_recover(int argc, char **argv)
1844 {
1845         int rc;
1846         struct obd_ioctl_data data;
1847
1848         IOC_INIT(data);
1849         if (argc > 2)
1850                 return CMD_HELP;
1851
1852         if (argc == 2) {
1853                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1854                 data.ioc_inlbuf1 = argv[1];
1855         }
1856
1857         IOC_PACK(argv[0], data);
1858         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1859         if (rc < 0) {
1860                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1861                         strerror(rc = errno));
1862         }
1863
1864         return rc;
1865 }
1866
1867 int jt_obd_mdc_lookup(int argc, char **argv)
1868 {
1869         struct obd_ioctl_data data;
1870         char *parent, *child;
1871         int rc, fd, verbose = 1;
1872
1873         if (argc < 3 || argc > 4)
1874                 return CMD_HELP;
1875
1876         parent = argv[1];
1877         child = argv[2];
1878         if (argc == 4)
1879                 verbose = get_verbose(argv[0], argv[3]);
1880
1881         IOC_INIT(data);
1882
1883         data.ioc_inllen1 = strlen(child) + 1;
1884         data.ioc_inlbuf1 = child;
1885
1886         IOC_PACK(argv[0], data);
1887
1888         fd = open(parent, O_RDONLY);
1889         if (fd < 0) {
1890                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1891                         strerror(errno));
1892                 return -1;
1893         }
1894
1895         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1896         if (rc < 0) {
1897                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1898                         jt_cmdname(argv[0]), strerror(rc = errno));
1899         }
1900         close(fd);
1901
1902         if (verbose) {
1903                 IOC_UNPACK(argv[0], data);
1904                 printf("%s: mode %o uid %d gid %d\n", child,
1905                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
1906                        data.ioc_obdo1.o_gid);
1907         }
1908
1909         return rc;
1910 }
1911
1912 int jt_cfg_dump_log(int argc, char **argv)
1913 {
1914         struct obd_ioctl_data data;
1915         int rc;
1916
1917         IOC_INIT(data);
1918
1919         if (argc != 2)
1920                 return CMD_HELP;
1921
1922         data.ioc_inllen1 = strlen(argv[1]) + 1;
1923         data.ioc_inlbuf1 = argv[1];
1924
1925         IOC_PACK(argv[0], data);
1926         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
1927         if (rc < 0)
1928                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
1929                         strerror(errno));
1930
1931         return rc;
1932 }
1933
1934 int jt_llog_catlist(int argc, char **argv)
1935 {
1936         struct obd_ioctl_data data;
1937         int rc;
1938
1939         if (argc != 1)
1940                 return CMD_HELP;
1941
1942         IOC_INIT(data);
1943         data.ioc_inllen1 = max - size_round(sizeof(data));
1944         IOC_PACK(argv[0], data);
1945
1946         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
1947         if (rc == 0)
1948                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1949         else
1950                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n",
1951                         strerror(errno));
1952
1953         return rc;
1954 }
1955
1956 int jt_llog_info(int argc, char **argv)
1957 {
1958         struct obd_ioctl_data data;
1959         int rc;
1960
1961         if (argc != 2)
1962                 return CMD_HELP;
1963
1964         IOC_INIT(data);
1965         data.ioc_inllen1 = strlen(argv[1]) + 1;
1966         data.ioc_inlbuf1 = argv[1];
1967         data.ioc_inllen2 = max - size_round(sizeof(data)) -
1968                 size_round(data.ioc_inllen1);
1969         IOC_PACK(argv[0], data);
1970
1971         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
1972         if (rc == 0)
1973                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1974         else
1975                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
1976                         strerror(errno));
1977
1978         return rc;
1979 }
1980
1981 int jt_llog_print(int argc, char **argv)
1982 {
1983         struct obd_ioctl_data data;
1984         int rc;
1985
1986         if (argc != 2 && argc != 4)
1987                 return CMD_HELP;
1988
1989         IOC_INIT(data);
1990         data.ioc_inllen1 = strlen(argv[1]) + 1;
1991         data.ioc_inlbuf1 = argv[1];
1992         if (argc == 4) {
1993                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1994                 data.ioc_inlbuf2 = argv[2];
1995                 data.ioc_inllen3 = strlen(argv[3]) + 1;
1996                 data.ioc_inlbuf3 = argv[3];
1997         } else {
1998                 char from[2] = "1", to[3] = "-1";
1999                 data.ioc_inllen2 = strlen(from) + 1;
2000                 data.ioc_inlbuf2 = from;
2001                 data.ioc_inllen3 = strlen(to) + 1;
2002                 data.ioc_inlbuf3 = to;
2003         }
2004         data.ioc_inllen4 = max - size_round(sizeof(data)) -
2005                 size_round(data.ioc_inllen1) -
2006                 size_round(data.ioc_inllen2) -
2007                 size_round(data.ioc_inllen3);
2008         IOC_PACK(argv[0], data);
2009
2010         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
2011         if (rc == 0)
2012                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2013         else
2014                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
2015                         strerror(errno));
2016
2017         return rc;
2018 }
2019
2020 int jt_llog_cancel(int argc, char **argv)
2021 {
2022         struct obd_ioctl_data data;
2023         int rc;
2024
2025         if (argc != 4)
2026                 return CMD_HELP;
2027
2028         IOC_INIT(data);
2029         data.ioc_inllen1 = strlen(argv[1]) + 1;
2030         data.ioc_inlbuf1 = argv[1];
2031         data.ioc_inllen2 = strlen(argv[2]) + 1;
2032         data.ioc_inlbuf2 = argv[2];
2033         data.ioc_inllen3 = strlen(argv[3]) + 1;
2034         data.ioc_inlbuf3 = argv[3];
2035         IOC_PACK(argv[0], data);
2036
2037         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
2038         if (rc == 0)
2039                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
2040         else
2041                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
2042                         strerror(errno));
2043
2044         return rc;
2045
2046 }
2047 int jt_llog_check(int argc, char **argv)
2048 {
2049         struct obd_ioctl_data data;
2050         int rc;
2051
2052         if (argc != 2 && argc != 4)
2053                 return CMD_HELP;
2054
2055         IOC_INIT(data);
2056         data.ioc_inllen1 = strlen(argv[1]) + 1;
2057         data.ioc_inlbuf1 = argv[1];
2058         if (argc == 4) {
2059                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2060                 data.ioc_inlbuf2 = argv[2];
2061                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2062                 data.ioc_inlbuf3 = argv[3];
2063         } else {
2064                 char from[2] = "1", to[3] = "-1";
2065                 data.ioc_inllen2 = strlen(from) + 1;
2066                 data.ioc_inlbuf2 = from;
2067                 data.ioc_inllen3 = strlen(to) + 1;
2068                 data.ioc_inlbuf3 = to;
2069         }
2070         data.ioc_inllen4 = max - size_round(sizeof(data)) -
2071                 size_round(data.ioc_inllen1) -
2072                 size_round(data.ioc_inllen2) -
2073                 size_round(data.ioc_inllen3);
2074         IOC_PACK(argv[0], data);
2075
2076         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
2077         if (rc == 0)
2078                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2079         else
2080                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
2081                         strerror(errno));
2082         return rc;
2083 }
2084
2085 int jt_llog_remove(int argc, char **argv)
2086 {
2087         struct obd_ioctl_data data;
2088         int rc;
2089
2090         if (argc != 3 && argc != 2)
2091                 return CMD_HELP;
2092
2093         IOC_INIT(data);
2094         data.ioc_inllen1 = strlen(argv[1]) + 1;
2095         data.ioc_inlbuf1 = argv[1];
2096         if (argc == 3){
2097                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2098                 data.ioc_inlbuf2 = argv[2];
2099         }
2100         IOC_PACK(argv[0], data);
2101
2102         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
2103         if (rc == 0) {
2104                 if (argc == 3)
2105                         fprintf(stdout, "log %s are removed.\n", argv[2]);
2106                 else
2107                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
2108         } else
2109                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
2110                         strerror(errno));
2111
2112         return rc;
2113 }
2114
2115 /* attach a regular file to virtual block device.
2116  * return vaule:
2117  *  -1: fatal error
2118  *  1: error, it always means the command run failed
2119  *  0: success
2120  */
2121 static int jt_blockdev_run_process(const char *file, char *argv[])
2122 {
2123         pid_t pid;
2124         int rc;
2125
2126         pid = vfork();
2127         if (pid == 0) { /* child process */
2128                 /* don't print error messages */
2129                 close(1), close(2);
2130                 (void)execvp(file, argv);
2131                 exit(-1);
2132         } else if (pid > 0) {
2133                 int status;
2134
2135                 rc = waitpid(pid, &status, 0);
2136                 if (rc < 0 || !WIFEXITED(status))
2137                         return -1;
2138
2139                 return WEXITSTATUS(status);
2140         }
2141
2142         return -1;
2143 }
2144
2145 static int jt_blockdev_find_module(const char *module)
2146 {
2147         FILE *fp;
2148         int found = 0;
2149         char modname[256];
2150
2151         fp = fopen("/proc/modules", "r");
2152         if (fp == NULL)
2153                 return -1;
2154
2155         while (fscanf(fp, "%s %*s %*s %*s %*s %*s", modname) == 1) {
2156                 if (strcmp(module, modname) == 0) {
2157                         found = 1;
2158                         break;
2159                 }
2160         }
2161         fclose(fp);
2162
2163         return found;
2164 }
2165
2166 static int jt_blockdev_probe_module(const char *module)
2167 {
2168         char buf[1024];
2169         char *argv[10];
2170         int c, rc;
2171
2172         if (jt_blockdev_find_module(module) == 1)
2173                 return 0;
2174
2175         /* run modprobe first */
2176         c = 0;
2177         argv[c++] = "/sbin/modprobe";
2178         argv[c++] = "-q";
2179         argv[c++] = (char *)module;
2180         argv[c++] = NULL;
2181         rc = jt_blockdev_run_process("modprobe", argv);
2182         if (rc != 1)
2183                 return rc;
2184
2185         /* cannot find the module in default directory ... */
2186         sprintf(buf, "../llite/%s.ko", module);
2187         c = 0;
2188         argv[c++] = "/sbin/insmod";
2189         argv[c++] = buf;
2190         argv[c++] = NULL;
2191         rc = jt_blockdev_run_process("insmod", argv);
2192         return rc ? -1 : 0;
2193 }
2194
2195 int jt_blockdev_attach(int argc, char **argv)
2196 {
2197         int rc, fd;
2198         struct stat st;
2199         char *filename, *devname;
2200         unsigned long dev;
2201
2202         if (argc != 3)
2203                 return CMD_HELP;
2204
2205         if (jt_blockdev_probe_module("llite_lloop") < 0) {
2206                 fprintf(stderr, "error: cannot find module llite_lloop.(k)o\n");
2207                 return ENOENT;
2208         }
2209
2210         filename = argv[1];
2211         devname = argv[2];
2212
2213         fd = open(filename, O_RDWR);
2214         if (fd < 0) {
2215                 fprintf(stderr, "file %s can't be opened(%s)\n\n",
2216                         filename, strerror(errno));
2217                 return CMD_HELP;
2218         }
2219
2220         rc = ioctl(fd, LL_IOC_LLOOP_ATTACH, &dev);
2221         if (rc < 0) {
2222                 rc = errno;
2223                 fprintf(stderr, "attach error(%s)\n", strerror(rc));
2224                 goto out;
2225         }
2226
2227         rc = stat(devname, &st);
2228         if (rc == 0 && (!S_ISBLK(st.st_mode) || st.st_rdev != dev)) {
2229                 rc = EEXIST;
2230         } else if (rc < 0) {
2231                 if (errno == ENOENT &&
2232                     !mknod(devname, S_IFBLK|S_IRUSR|S_IWUSR, dev))
2233                         rc = 0;
2234                 else
2235                         rc = errno;
2236         }
2237
2238         if (rc) {
2239                 fprintf(stderr, "error: the file %s could be attached to block "
2240                                 "device %X but creating %s failed: %s\n"
2241                                 "now detaching the block device..",
2242                         filename, (int)dev, devname, strerror(rc));
2243
2244                 (void)ioctl(fd, LL_IOC_LLOOP_DETACH_BYDEV, dev);
2245                 fprintf(stderr, "%s\n", strerror(errno));
2246         }
2247 out:
2248         close(fd);
2249         return -rc;
2250 }
2251
2252 int jt_blockdev_detach(int argc, char **argv)
2253 {
2254         char *filename;
2255         int rc, fd;
2256
2257         if (argc != 2)
2258                 return CMD_HELP;
2259
2260         filename = argv[1];
2261         fd = open(filename, O_RDONLY);
2262         if (fd < 0) {
2263                 fprintf(stderr, "cannot open file %s error %s\n",
2264                         filename, strerror(errno));
2265                 return CMD_HELP;
2266         }
2267
2268         rc = ioctl(fd, LL_IOC_LLOOP_DETACH, 0);
2269         if (rc < 0) {
2270                 rc = errno;
2271                 fprintf(stderr, "detach error(%s)\n", strerror(rc));
2272         } else {
2273                 (void)unlink(filename);
2274         }
2275
2276         close(fd);
2277         return -rc;
2278 }
2279
2280 int jt_blockdev_info(int argc, char **argv)
2281 {
2282         char *filename;
2283         int rc, fd;
2284         __u64  ino;
2285
2286         if (argc != 2)
2287                 return CMD_HELP;
2288
2289         filename = argv[1];
2290         fd = open(filename, O_RDONLY);
2291         if (fd < 0) {
2292                 fprintf(stderr, "cannot open file %s error: %s\n",
2293                         filename, strerror(errno));
2294                 return CMD_HELP;
2295         }
2296
2297         rc = ioctl(fd, LL_IOC_LLOOP_INFO, &ino);
2298         if (rc < 0) {
2299                 rc = errno;
2300                 fprintf(stderr, "error: %s\n", strerror(errno));
2301                 goto out;
2302         }
2303         fprintf(stdout, "lloop device info: ");
2304         if (ino == 0ULL)
2305                 fprintf(stdout, "Not attached\n");
2306         else
2307                 fprintf(stdout, "attached to inode "LPU64"\n", ino);
2308 out:
2309         close(fd);
2310         return -rc;
2311 }
2312
2313 static void signal_server(int sig)
2314 {
2315         if (sig == SIGINT) {
2316                 do_disconnect("sigint", 1);
2317                 exit(1);
2318         } else
2319                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2320 }
2321
2322 int obd_initialize(int argc, char **argv)
2323 {
2324         int i;
2325
2326         for (i = 0; i < MAX_STRIPES; i++)
2327                 lsm_buffer.lsm.lsm_oinfo[i] = lov_oinfos + i;
2328
2329         shmem_setup();
2330         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH,
2331                          OBD_DEV_MAJOR, OBD_DEV_MINOR);
2332
2333         return 0;
2334 }
2335
2336 void obd_finalize(int argc, char **argv)
2337 {
2338         struct sigaction sigact;
2339
2340         sigact.sa_handler = signal_server;
2341         sigfillset(&sigact.sa_mask);
2342         sigact.sa_flags = SA_RESTART;
2343         sigaction(SIGINT, &sigact, NULL);
2344
2345         shmem_stop();
2346         do_disconnect(argv[0], 1);
2347 }
2348
2349 static int find_target_obdpath(char *fsname, char *path)
2350 {
2351         glob_t glob_info;
2352         char pattern[PATH_MAX + 1];
2353         int rc;
2354
2355         snprintf(pattern, PATH_MAX,
2356                  "/proc/fs/lustre/lov/%s-*/target_obd",
2357                  fsname);
2358         rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
2359         if (rc)
2360                 return -EINVAL;
2361
2362         if (glob_info.gl_pathc == 0) {
2363                 globfree(&glob_info);
2364                 return -EINVAL;
2365         }
2366
2367         strcpy(path, glob_info.gl_pathv[0]);
2368         return 0;
2369 }
2370
2371 static int find_poolpath(char *fsname, char *poolname, char *poolpath)
2372 {
2373         glob_t glob_info;
2374         char pattern[PATH_MAX + 1];
2375         int rc;
2376
2377         snprintf(pattern, PATH_MAX,
2378                  "/proc/fs/lustre/lov/%s-*/pools/%s",
2379                  fsname, poolname);
2380         rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
2381         if (rc)
2382                 return -EINVAL;
2383
2384         if (glob_info.gl_pathc == 0) {
2385                 globfree(&glob_info);
2386                 return -EINVAL;
2387         }
2388
2389         strcpy(poolpath, glob_info.gl_pathv[0]);
2390         return 0;
2391 }
2392
2393 /*
2394  * if pool is NULL, search ostname in target_obd
2395  * if pool is no NULL
2396  *  if pool not found returns < 0
2397  *  if ostname is NULL, returns 1 if pool is not empty and 0 if pool empty
2398  *  if ostname is not NULL, returns 1 if OST is in pool and 0 if not
2399  */
2400 static int search_ost(char *fsname, char *poolname, char *ostname)
2401 {
2402         FILE *fd;
2403         char buffer[PATH_MAX + 1];
2404         int len = 0, rc;
2405
2406         if (ostname != NULL)
2407                 len = strlen(ostname);
2408
2409         if (poolname == NULL)
2410                 rc = find_target_obdpath(fsname, buffer);
2411         else
2412                 rc = find_poolpath(fsname, poolname, buffer);
2413         if (rc)
2414                 return rc;
2415
2416         if ((fd = fopen(buffer, "r")) == NULL)
2417                 return -EINVAL;
2418
2419         while (fgets(buffer, sizeof(buffer), fd) != NULL) {
2420                 if (poolname == NULL) {
2421                         /* we search ostname in target_obd */
2422                         if (strncmp(buffer + 3, ostname, len) == 0) {
2423                                 fclose(fd);
2424                                 return 1;
2425                         }
2426                 } else {
2427                         /* we search a non empty pool or
2428                            an ostname in a pool */
2429                         if ((ostname == NULL) ||
2430                             (strncmp(buffer, ostname, len) == 0)) {
2431                                 fclose(fd);
2432                                 return 1;
2433                         }
2434                 }
2435         }
2436         fclose(fd);
2437         return 0;
2438 }
2439
2440 static int check_pool_cmd(enum lcfg_command_type cmd,
2441                           char *fsname, char *poolname,
2442                           char *ostname)
2443 {
2444         int rc = 0;
2445
2446         switch (cmd) {
2447         case LCFG_POOL_NEW: {
2448                 if (search_ost(fsname, poolname, NULL) >= 0) {
2449                         fprintf(stderr, "Pool %s.%s already exists\n",
2450                                 fsname, poolname);
2451                         return -EEXIST;
2452                 }
2453                 return 0;
2454         }
2455         case LCFG_POOL_DEL: {
2456                 rc = search_ost(fsname, poolname, NULL);
2457                 if (rc < 0) {
2458                         fprintf(stderr, "Pool %s.%s not found\n",
2459                                 fsname, poolname);
2460                         return -ENOENT;
2461                 }
2462                 if (rc == 1) {
2463                         fprintf(stderr, "Pool %s.%s not empty, "
2464                                 "please remove all members\n",
2465                                 fsname, poolname);
2466                         return -ENOTEMPTY;
2467                 }
2468                 return 0;
2469         }
2470         case LCFG_POOL_ADD: {
2471                 rc = search_ost(fsname, NULL, ostname);
2472                 if (rc == 0) {
2473                         fprintf(stderr, "OST %s not found in lov of %s\n",
2474                                 ostname, fsname);
2475                         return -ENOENT;
2476                 }
2477                 rc = search_ost(fsname, poolname, ostname);
2478                 if (rc < 0) {
2479                         fprintf(stderr, "Pool %s.%s not found\n",
2480                                 fsname, poolname);
2481                         return -ENOENT;
2482                 }
2483                 if (rc == 1) {
2484                         fprintf(stderr, "OST %s already in pool %s.%s\n",
2485                                 ostname, fsname, poolname);
2486                         return -EEXIST;
2487                 }
2488                 return 0;
2489         }
2490         case LCFG_POOL_REM: {
2491                 rc = search_ost(fsname, poolname, ostname);
2492                 if (rc < 0) {
2493                         fprintf(stderr, "Pool %s.%s not found\n",
2494                                 fsname, poolname);
2495                         return -ENOENT;
2496                 }
2497                 if (rc == 0) {
2498                         fprintf(stderr, "OST %s not found in pool %s.%s\n",
2499                                 ostname, fsname, poolname);
2500                         return -ENOENT;
2501                 }
2502                 return 0;
2503         }
2504         default: {
2505         }
2506         }
2507         return 0;
2508 }
2509
2510 static void check_pool_cmd_result(enum lcfg_command_type cmd,
2511                                   char *fsname, char *poolname,
2512                                   char *ostname)
2513 {
2514         int cpt, rc = 0;
2515
2516         cpt = 10;
2517         switch (cmd) {
2518         case LCFG_POOL_NEW: {
2519                 do {
2520                         rc = search_ost(fsname, poolname, NULL);
2521                         if (rc < 0)
2522                                 sleep(2);
2523                         cpt--;
2524                 } while ((rc < 0) && (cpt > 0));
2525                 if (rc >= 0)
2526                         fprintf(stderr, "Pool %s.%s created\n",
2527                                 fsname, poolname);
2528                 else
2529                         fprintf(stderr, "Warning, pool %s.%s not found\n",
2530                                 fsname, poolname);
2531                 return;
2532         }
2533         case LCFG_POOL_DEL: {
2534                 do {
2535                          rc = search_ost(fsname, poolname, NULL);
2536                          if (rc >= 0)
2537                                 sleep(2);
2538                          cpt--;
2539                 } while ((rc >= 0) && (cpt > 0));
2540                 if (rc < 0)
2541                         fprintf(stderr, "Pool %s.%s destroyed\n",
2542                                 fsname, poolname);
2543                 else
2544                         fprintf(stderr, "Warning, pool %s.%s still found\n",
2545                                 fsname, poolname);
2546                 return;
2547         }
2548         case LCFG_POOL_ADD: {
2549                 do {
2550                         rc = search_ost(fsname, poolname, ostname);
2551                         if (rc != 1)
2552                                 sleep(2);
2553                         cpt--;
2554                 } while ((rc != 1) && (cpt > 0));
2555                 if (rc == 1)
2556                         fprintf(stderr, "OST %s added to pool %s.%s\n",
2557                                 ostname, fsname, poolname);
2558                 else
2559                         fprintf(stderr, "Warning, OST %s not found in pool %s.%s\n",
2560                                 ostname, fsname, poolname);
2561                 return;
2562         }
2563         case LCFG_POOL_REM: {
2564                 do {
2565                         rc = search_ost(fsname, poolname, ostname);
2566                         if (rc == 1)
2567                                 sleep(2);
2568                         cpt--;
2569                 } while ((rc == 1) && (cpt > 0));
2570                 if (rc != 1)
2571                         fprintf(stderr, "OST %s removed from pool %s.%s\n",
2572                                 ostname, fsname, poolname);
2573                 else
2574                         fprintf(stderr, "Warning, OST %s still found in pool %s.%s\n",
2575                                 ostname, fsname, poolname);
2576                 return;
2577         }
2578         default: {
2579         }
2580         }
2581 }
2582
2583 static int check_and_complete_ostname(char *fsname, char *ostname)
2584 {
2585         char *ptr;
2586         char real_ostname[MAX_OBD_NAME + 1];
2587         char i;
2588
2589         /* if OST name does not start with fsname, we add it */
2590         /* if not check if the fsname is the right one */
2591         ptr = strchr(ostname, '-');
2592         if (ptr == NULL) {
2593                 sprintf(real_ostname, "%s-%s", fsname, ostname);
2594         } else if (strncmp(ostname, fsname, strlen(fsname)) != 0) {
2595                 fprintf(stderr, "%s does not start with fsname %s\n",
2596                         ostname, fsname);
2597                 return -EINVAL;
2598         } else {
2599              strcpy(real_ostname, ostname);
2600         }
2601         /* real_ostname is fsname-????? */
2602         ptr = real_ostname + strlen(fsname) + 1;
2603         if (strncmp(ptr, "OST", 3) != 0) {
2604                 fprintf(stderr, "%s does not start by %s-OST nor OST\n",
2605                         ostname, fsname);
2606                 return -EINVAL;
2607         }
2608         /* real_ostname is fsname-OST????? */
2609         ptr += 3;
2610         for (i = 0; i < 4; i++) {
2611                 if (!isxdigit(*ptr)) {
2612                         fprintf(stderr,
2613                                 "ost's index in %s is not an hexa number\n",
2614                                 ostname);
2615                         return -EINVAL;
2616                 }
2617                 ptr++;
2618         }
2619         /* real_ostname is fsname-OSTXXXX????? */
2620         /* if OST name does not end with _UUID, we add it */
2621         if (*ptr == '\0') {
2622                 strcat(real_ostname, "_UUID");
2623         } else if (strcmp(ptr, "_UUID") != 0) {
2624                 fprintf(stderr,
2625                         "ostname %s does not end with _UUID\n", ostname);
2626                 return -EINVAL;
2627         }
2628         /* real_ostname is fsname-OSTXXXX_UUID */
2629         strcpy(ostname, real_ostname);
2630         return 0;
2631 }
2632
2633 /* returns 0 or -errno */
2634 static int pool_cmd(enum lcfg_command_type cmd,
2635                     char *cmdname, char *fullpoolname,
2636                     char *fsname, char *poolname, char *ostname)
2637 {
2638         int rc = 0;
2639         struct obd_ioctl_data data;
2640         struct lustre_cfg_bufs bufs;
2641         struct lustre_cfg *lcfg;
2642
2643         rc = check_pool_cmd(cmd, fsname, poolname, ostname);
2644         if (rc)
2645                 return rc;
2646
2647         lustre_cfg_bufs_reset(&bufs, NULL);
2648         lustre_cfg_bufs_set_string(&bufs, 0, cmdname);
2649         lustre_cfg_bufs_set_string(&bufs, 1, fullpoolname);
2650         if (ostname != NULL)
2651                 lustre_cfg_bufs_set_string(&bufs, 2, ostname);
2652
2653         lcfg = lustre_cfg_new(cmd, &bufs);
2654         if (IS_ERR(lcfg)) {
2655                 rc = PTR_ERR(lcfg);
2656                 return rc;
2657         }
2658
2659         IOC_INIT(data);
2660         rc = data.ioc_dev = get_mgs_device();
2661         if (rc < 0)
2662                 goto out;
2663
2664         data.ioc_type = LUSTRE_CFG_TYPE;
2665         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
2666                                         lcfg->lcfg_buflens);
2667         data.ioc_pbuf1 = (void *)lcfg;
2668         IOC_PACK(cmdname, data);
2669
2670         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_POOL, buf);
2671 out:
2672         if (rc)
2673                 rc = -errno;
2674         lustre_cfg_free(lcfg);
2675         return rc;
2676 }
2677
2678 /*
2679  * this function tranforms a rule [start-end/step] into an array
2680  * of matching numbers
2681  * supported forms are:
2682  * [start]                : just this number
2683  * [start-end]            : all numbers from start to end
2684  * [start-end/step]       : numbers from start to end with increment of step
2685  * on return, format contains a printf format string which can be used
2686  * to generate all the strings
2687  */
2688 static int get_array_idx(char *rule, char *format, int **array)
2689 {
2690         char *start, *end, *ptr;
2691         unsigned int lo, hi, step;
2692         int array_sz = 0;
2693         int i, array_idx;
2694         int rc;
2695
2696         start = strchr(rule, '[');
2697         end = strchr(rule, ']');
2698         if ((start == NULL) || (end == NULL)) {
2699                 *array = malloc(sizeof(int));
2700                 if (*array == NULL)
2701                         return 0;
2702                 strcpy(format, rule);
2703                 array_sz = 1;
2704                 return array_sz;
2705         }
2706         *start = '\0';
2707         *end = '\0';
2708         end++;
2709         start++;
2710         /* put in format the printf format (the rule without the range) */
2711         sprintf(format, "%s%%.4d%s", rule, end);
2712
2713         array_idx = 0;
2714         array_sz = 0;
2715         *array = NULL;
2716         /* loop on , separator */
2717         do {
2718                 /* extract the 3 fields */
2719                 rc = sscanf(start, "%u-%u/%u", &lo, &hi, &step);
2720                 switch (rc) {
2721                 case 0: {
2722                         return 0;
2723                 }
2724                 case 1: {
2725                         array_sz++;
2726                         *array = realloc(*array, array_sz * sizeof(int));
2727                         if (*array == NULL)
2728                                 return 0;
2729                         (*array)[array_idx] = lo;
2730                         array_idx++;
2731                         break;
2732                 }
2733                 case 2: {
2734                         step = 1;
2735                         /* do not break to share code with case 3: */
2736                 }
2737                 case 3: {
2738                         if ((hi < lo) || (step == 0))
2739                                 return 0;
2740                         array_sz += (hi - lo) / step + 1;
2741                         *array = realloc(*array, sizeof(int) * array_sz);
2742                         if (*array == NULL)
2743                                 return 0;
2744                         for (i = lo; i <= hi; i+=step, array_idx++)
2745                                 (*array)[array_idx] = i;
2746                         break;
2747                 }
2748                 }
2749                 ptr = strchr(start, ',');
2750                 if (ptr != NULL)
2751                         start = ptr + 1;
2752
2753         } while (ptr != NULL);
2754         return array_sz;
2755 }
2756
2757 static int extract_fsname_poolname(char *arg, char *fsname, char *poolname)
2758 {
2759         char *ptr;
2760         int len;
2761         int rc;
2762
2763         strcpy(fsname, arg);
2764         ptr = strchr(fsname, '.');
2765         if (ptr == NULL) {
2766                 fprintf(stderr, ". is missing in %s\n", fsname);
2767                 rc = -EINVAL;
2768                 goto err;
2769         }
2770
2771         len = ptr - fsname;
2772         if (len == 0) {
2773                 fprintf(stderr, "fsname is empty\n");
2774                 rc = -EINVAL;
2775                 goto err;
2776         }
2777
2778         len = strlen(ptr + 1);
2779         if (len == 0) {
2780                 fprintf(stderr, "poolname is empty\n");
2781                 rc = -EINVAL;
2782                 goto err;
2783         }
2784         if (len > LOV_MAXPOOLNAME) {
2785                 fprintf(stderr,
2786                         "poolname %s is too long (length is %d max is %d)\n",
2787                         ptr + 1, len, LOV_MAXPOOLNAME);
2788                 rc = -ENAMETOOLONG;
2789                 goto err;
2790         }
2791         strncpy(poolname, ptr + 1, LOV_MAXPOOLNAME);
2792         poolname[LOV_MAXPOOLNAME] = '\0';
2793         *ptr = '\0';
2794         return 0;
2795
2796 err:
2797         fprintf(stderr, "argument %s must be <fsname>.<poolname>\n", arg);
2798         return rc;
2799 }
2800
2801 int jt_pool_cmd(int argc, char **argv)
2802 {
2803         enum lcfg_command_type cmd;
2804         char fsname[PATH_MAX + 1];
2805         char poolname[LOV_MAXPOOLNAME + 1];
2806         char *ostnames_buf = NULL;
2807         int i, rc;
2808         int *array = NULL, array_sz;
2809         struct {
2810                 int     rc;
2811                 char   *ostname;
2812         } *cmds = NULL;
2813
2814         switch (argc) {
2815         case 0:
2816         case 1: return CMD_HELP;
2817         case 2: {
2818                 if (strcmp("pool_new", argv[0]) == 0)
2819                         cmd = LCFG_POOL_NEW;
2820                 else if (strcmp("pool_destroy", argv[0]) == 0)
2821                         cmd = LCFG_POOL_DEL;
2822                 else if (strcmp("pool_list", argv[0]) == 0)
2823                          return llapi_poollist(argv[1]);
2824                 else return CMD_HELP;
2825
2826                 rc = extract_fsname_poolname(argv[1], fsname, poolname);
2827                 if (rc)
2828                         break;
2829
2830                 rc = pool_cmd(cmd, argv[0], argv[1],
2831                               fsname, poolname, NULL);
2832                 if (rc)
2833                         break;
2834
2835                 check_pool_cmd_result(cmd, fsname, poolname, NULL);
2836                 break;
2837         }
2838         default: {
2839                 char format[2*MAX_OBD_NAME];
2840
2841                 if (strcmp("pool_remove", argv[0]) == 0) {
2842                         cmd = LCFG_POOL_REM;
2843                 } else if (strcmp("pool_add", argv[0]) == 0) {
2844                         cmd = LCFG_POOL_ADD;
2845                 } else {
2846                         return CMD_HELP;
2847                 }
2848
2849                 rc = extract_fsname_poolname(argv[1], fsname, poolname);
2850                 if (rc)
2851                         break;
2852
2853                 for (i = 2; i < argc; i++) {
2854                         int j;
2855
2856                         array_sz = get_array_idx(argv[i], format, &array);
2857                         if (array_sz == 0)
2858                                 return CMD_HELP;
2859
2860                         cmds = malloc(array_sz * sizeof(cmds[0]));
2861                         if (cmds != NULL) {
2862                                 ostnames_buf = malloc(array_sz *
2863                                                       (MAX_OBD_NAME + 1));
2864                         } else {
2865                                 free(array);
2866                                 rc = -ENOMEM;
2867                                 goto out;
2868                         }
2869
2870                         for (j = 0; j < array_sz; j++) {
2871                                 char ostname[MAX_OBD_NAME + 1];
2872
2873                                 snprintf(ostname, MAX_OBD_NAME, format,
2874                                          array[j]);
2875                                 ostname[MAX_OBD_NAME] = '\0';
2876
2877                                 rc = check_and_complete_ostname(fsname,ostname);
2878                                 if (rc) {
2879                                         free(array);
2880                                         free(cmds);
2881                                         if (ostnames_buf)
2882                                                 free(ostnames_buf);
2883                                         goto out;
2884                                 }
2885                                 if (ostnames_buf != NULL) {
2886                                         cmds[j].ostname =
2887                                           &ostnames_buf[(MAX_OBD_NAME + 1) * j];
2888                                         strcpy(cmds[j].ostname, ostname);
2889                                 } else {
2890                                         cmds[j].ostname = NULL;
2891                                 }
2892                                 cmds[j].rc = pool_cmd(cmd, argv[0], argv[1],
2893                                                       fsname, poolname,
2894                                                       ostname);
2895                         }
2896                         for (j = 0; j < array_sz; j++) {
2897                                 if (!cmds[j].rc) {
2898                                         char ostname[MAX_OBD_NAME + 1];
2899
2900                                         if (!cmds[j].ostname) {
2901                                                 snprintf(ostname, MAX_OBD_NAME,
2902                                                          format, array[j]);
2903                                                 ostname[MAX_OBD_NAME] = '\0';
2904                                                 check_and_complete_ostname(
2905                                                         fsname, ostname);
2906                                         } else {
2907                                                 strcpy(ostname,
2908                                                        cmds[j].ostname);
2909                                         }
2910                                         check_pool_cmd_result(cmd, fsname,
2911                                                               poolname,ostname);
2912                                 }
2913                         }
2914                         if (array_sz > 0)
2915                                 free(array);
2916                         if (cmds)
2917                                 free(cmds);
2918                         if (ostnames_buf);
2919                                 free(ostnames_buf);
2920                 }
2921                 return 0;
2922         }
2923         }
2924
2925
2926 out:
2927         if ((rc == -EINVAL) || (rc == -ENOENT))
2928                 fprintf(stderr, "Does the fs, pool or ost exist?\n");
2929         if (rc != 0) {
2930                 errno = -rc;
2931                 perror(argv[0]);
2932         }
2933
2934         return rc;
2935 }