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