Whamcloud - gitweb
LU-1818 quota: en/disable quota enforcement via conf_param
[fs/lustre-release.git] / lustre / utils / obd.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2012, Whamcloud, Inc.
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 <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <sys/stat.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <sys/un.h>
50 #include <sys/wait.h>
51
52 #include <ctype.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <glob.h>
56 #include <signal.h>
57 #include <stdarg.h>
58 #include <stdbool.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <time.h>
63 #include <unistd.h>
64
65 #include "obdctl.h"
66
67 #include <obd.h>          /* for struct lov_stripe_md */
68 #include <lustre/lustre_build_version.h>
69
70 #include <obd_class.h>
71 #include <lnet/lnetctl.h>
72 #include <libcfs/libcfsutil.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 4096
84 #define MAX_BASE_ID 0xffffffff
85 struct shared_data {
86         l_mutex_t mutex;
87         l_cond_t  cond;
88         int       stopping;
89         struct {
90                 __u64 counters[MAX_THREADS];
91                 __u64 offsets[MAX_THREADS];
92                 int   thr_running;
93                 int   start_barrier;
94                 int   stop_barrier;
95                 struct timeval start_time;
96                 struct timeval end_time;
97         } body;
98 };
99
100 static struct shared_data *shared_data;
101 static __u64 counter_snapshot[2][MAX_THREADS];
102 static int prev_valid;
103 static struct timeval prev_time;
104 static int thread;
105 static int nthreads;
106 #else
107 const int thread = 0;
108 const int nthreads = 1;
109 #endif
110
111 static int cur_device = -1;
112
113 struct lov_oinfo lov_oinfos[LOV_MAX_STRIPE_COUNT];
114
115 struct lsm_buffer {
116         struct lov_stripe_md lsm;
117         struct lov_oinfo *ptrs[LOV_MAX_STRIPE_COUNT];
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 int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg)
126 {
127         struct obd_ioctl_data data;
128         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
129         int rc;
130
131         memset(&data, 0, sizeof(data));
132         data.ioc_dev = cur_device;
133         data.ioc_type = LUSTRE_CFG_TYPE;
134         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
135                                         lcfg->lcfg_buflens);
136         data.ioc_pbuf1 = (void *)lcfg;
137         memset(buf, 0, sizeof(rawbuf));
138         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
139         if (rc) {
140                 fprintf(stderr, "error: %s: invalid ioctl\n",
141                         jt_cmdname(func));
142                 return rc;
143         }
144
145         rc =  l_ioctl(dev_id, OBD_IOC_PROCESS_CFG, buf);
146
147         return rc;
148 }
149
150 static int do_device(char *func, char *devname);
151
152 static int get_mgs_device()
153 {
154         char mgs[] = "$MGS";
155         static int mgs_device = -1;
156
157         if (mgs_device == -1) {
158                 int rc;
159                 do_disconnect(NULL, 1);
160                 rc = do_device("mgsioc", mgs);
161                 if (rc) {
162                         fprintf(stderr,
163                                 "This command must be run on the MGS.\n");
164                         errno = ENODEV;
165                         return -1;
166                 }
167                 mgs_device = cur_device;
168         }
169         return mgs_device;
170 }
171
172 /* Returns -1 on error with errno set */
173 int lcfg_mgs_ioctl(char *func, int dev_id, struct lustre_cfg *lcfg)
174 {
175         struct obd_ioctl_data data;
176         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
177         int rc;
178
179         memset(&data, 0, sizeof(data));
180         rc = data.ioc_dev = get_mgs_device();
181         if (rc < 0)
182                 goto out;
183         data.ioc_type = LUSTRE_CFG_TYPE;
184         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
185                                         lcfg->lcfg_buflens);
186         data.ioc_pbuf1 = (void *)lcfg;
187         memset(buf, 0, sizeof(rawbuf));
188         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
189         if (rc) {
190                 fprintf(stderr, "error: %s: invalid ioctl\n",
191                         jt_cmdname(func));
192                 return rc;
193         }
194
195         rc = l_ioctl(dev_id, OBD_IOC_PARAM, buf);
196 out:
197         if (rc) {
198                 if (errno == ENOSYS)
199                         fprintf(stderr, "Make sure cfg_device is set first.\n");
200         }
201         return rc;
202 }
203
204 char *obdo_print(struct obdo *obd)
205 {
206         char buf[1024];
207
208         sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
209                 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
210                 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
211                 "misc: %x\nnlink: %d,\nvalid "LPX64"\n",
212                 obd->o_id, obd->o_seq, obd->o_atime, obd->o_mtime, obd->o_ctime,
213                 obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
214                 obd->o_uid, obd->o_gid, obd->o_flags, obd->o_misc,
215                 obd->o_nlink, obd->o_valid);
216         return strdup(buf);
217 }
218
219
220 #define BAD_VERBOSE (-999999999)
221
222 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
223
224 static int do_name2dev(char *func, char *name)
225 {
226         struct obd_ioctl_data data;
227         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
228         int rc;
229
230         memset(&data, 0, sizeof(data));
231         data.ioc_dev = cur_device;
232         data.ioc_inllen1 = strlen(name) + 1;
233         data.ioc_inlbuf1 = name;
234
235         memset(buf, 0, sizeof(rawbuf));
236         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
237         if (rc) {
238                 fprintf(stderr, "error: %s: invalid ioctl\n",
239                         jt_cmdname(func));
240                 return rc;
241         }
242         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
243         if (rc < 0)
244                 return errno;
245         rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
246         if (rc) {
247                 fprintf(stderr, "error: %s: invalid reply\n",
248                         jt_cmdname(func));
249                 return rc;
250         }
251
252         return data.ioc_dev + N2D_OFF;
253 }
254
255 /*
256  * resolve a device name to a device number.
257  * supports a number, $name or %uuid.
258  */
259 int parse_devname(char *func, char *name)
260 {
261         int rc;
262         int ret = -1;
263
264         if (!name)
265                 return ret;
266         if (isdigit(name[0])) {
267                 ret = strtoul(name, NULL, 0);
268         } else {
269                 if (name[0] == '$' || name[0] == '%')
270                         name++;
271                 rc = do_name2dev(func, name);
272                 if (rc >= N2D_OFF) {
273                         ret = rc - N2D_OFF;
274                         // printf("Name %s is device %d\n", name, ret);
275                 } else {
276                         fprintf(stderr, "No device found for name %s: %s\n",
277                                 name, strerror(rc));
278                 }
279         }
280         return ret;
281 }
282
283 static void
284 reset_lsmb (struct lsm_buffer *lsmb)
285 {
286         memset (&lsmb->lsm, 0, sizeof (lsmb->lsm));
287         memset(lov_oinfos, 0, sizeof(lov_oinfos));
288         lsmb->lsm.lsm_magic = LOV_MAGIC;
289 }
290
291 static int
292 parse_lsm (struct lsm_buffer *lsmb, char *string)
293 {
294         struct lov_stripe_md *lsm = &lsmb->lsm;
295         char                 *end;
296         int                   i;
297
298         /*
299          * object_id[=size#count[@offset:id]*]
300          */
301
302         reset_lsmb (lsmb);
303
304         lsm->lsm_object_id = strtoull (string, &end, 0);
305         if (end == string)
306                 return (-1);
307         string = end;
308
309         if (*string == 0)
310                 return (0);
311
312         if (*string != '=')
313                 return (-1);
314         string++;
315
316         lsm->lsm_stripe_size = strtoul (string, &end, 0);
317         if (end == string)
318                 return (-1);
319         string = end;
320
321         if (*string != '#')
322                 return (-1);
323         string++;
324
325         lsm->lsm_stripe_count = strtoul (string, &end, 0);
326         if (end == string)
327                 return (-1);
328         string = end;
329
330         if (*string == 0)               /* don't have to specify obj ids */
331                 return (0);
332
333         for (i = 0; i < lsm->lsm_stripe_count; i++) {
334                 if (*string != '@')
335                         return (-1);
336                 string++;
337                 lsm->lsm_oinfo[i]->loi_ost_idx = strtoul(string, &end, 0);
338                 if (*end != ':')
339                         return (-1);
340                 string = end + 1;
341                 lsm->lsm_oinfo[i]->loi_id = strtoull(string, &end, 0);
342                 string = end;
343         }
344
345         if (*string != 0)
346                 return (-1);
347
348         return (0);
349 }
350
351 char *jt_cmdname(char *func)
352 {
353         static char buf[512];
354
355         if (thread) {
356                 sprintf(buf, "%s-%d", func, thread);
357                 return buf;
358         }
359
360         return func;
361 }
362
363 #define difftime(a, b)                                  \
364         ((a)->tv_sec - (b)->tv_sec +                    \
365          ((a)->tv_usec - (b)->tv_usec) / 1000000.0)
366
367 static int be_verbose(int verbose, struct timeval *next_time,
368                       __u64 num, __u64 *next_num, int num_total)
369 {
370         struct timeval now;
371
372         if (!verbose)
373                 return 0;
374
375         if (next_time != NULL)
376                 gettimeofday(&now, NULL);
377
378         /* A positive verbosity means to print every X iterations */
379         if (verbose > 0 && (num >= *next_num || num >= num_total)) {
380                 *next_num += verbose;
381                 if (next_time) {
382                         next_time->tv_sec = now.tv_sec - verbose;
383                         next_time->tv_usec = now.tv_usec;
384                 }
385                 return 1;
386         }
387
388         /* A negative verbosity means to print at most each X seconds */
389         if (verbose < 0 && next_time != NULL &&
390             difftime(&now, next_time) >= 0.0){
391                 next_time->tv_sec = now.tv_sec - verbose;
392                 next_time->tv_usec = now.tv_usec;
393                 *next_num = num;
394                 return 1;
395         }
396
397         return 0;
398 }
399
400 static int get_verbose(char *func, const char *arg)
401 {
402         int verbose;
403         char *end;
404
405         if (!arg || arg[0] == 'v')
406                 verbose = 1;
407         else if (arg[0] == 's' || arg[0] == 'q')
408                 verbose = 0;
409         else {
410                 verbose = (int)strtoul(arg, &end, 0);
411                 if (*end) {
412                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
413                                 jt_cmdname(func), arg);
414                         return BAD_VERBOSE;
415                 }
416         }
417
418         if (verbose < 0)
419                 printf("Print status every %d seconds\n", -verbose);
420         else if (verbose == 1)
421                 printf("Print status every operation\n");
422         else if (verbose > 1)
423                 printf("Print status every %d operations\n", verbose);
424
425         return verbose;
426 }
427
428 int do_disconnect(char *func, int verbose)
429 {
430         lcfg_set_devname(NULL);
431         cur_device = -1;
432         return 0;
433 }
434
435 #ifdef MAX_THREADS
436 static int shmem_setup(void)
437 {
438         pthread_mutexattr_t mattr;
439         pthread_condattr_t  cattr;
440         int                 rc;
441         int                 shmid;
442
443         /* Create new segment */
444         shmid = shmget(IPC_PRIVATE, sizeof(*shared_data), 0600);
445         if (shmid == -1) {
446                 fprintf(stderr, "Can't create shared data: %s\n",
447                         strerror(errno));
448                 return errno;
449         }
450
451         /* Attatch to new segment */
452         shared_data = (struct shared_data *)shmat(shmid, NULL, 0);
453
454         if (shared_data == (struct shared_data *)(-1)) {
455                 fprintf(stderr, "Can't attach shared data: %s\n",
456                         strerror(errno));
457                 shared_data = NULL;
458                 return errno;
459         }
460
461         /* Mark segment as destroyed, so it will disappear when we exit.
462          * Forks will inherit attached segments, so we should be OK.
463          */
464         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
465                 fprintf(stderr, "Can't destroy shared data: %s\n",
466                         strerror(errno));
467                 return errno;
468         }
469
470         pthread_mutexattr_init(&mattr);
471         pthread_condattr_init(&cattr);
472
473         rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
474         if (rc != 0) {
475                 fprintf(stderr, "Can't set shared mutex attr\n");
476                 return rc;
477         }
478
479         rc = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
480         if (rc != 0) {
481                 fprintf(stderr, "Can't set shared cond attr\n");
482                 return rc;
483         }
484
485         pthread_mutex_init(&shared_data->mutex, &mattr);
486         pthread_cond_init(&shared_data->cond, &cattr);
487
488         pthread_mutexattr_destroy(&mattr);
489         pthread_condattr_destroy(&cattr);
490
491         return 0;
492 }
493
494 static inline void shmem_lock(void)
495 {
496         l_mutex_lock(&shared_data->mutex);
497 }
498
499 static inline void shmem_unlock(void)
500 {
501         l_mutex_unlock(&shared_data->mutex);
502 }
503
504 static inline void shmem_wait(void)
505 {
506         l_cond_wait(&shared_data->cond, &shared_data->mutex);
507 }
508
509 static inline void shmem_wakeup_all(void)
510 {
511         l_cond_broadcast(&shared_data->cond);
512 }
513
514 static inline void shmem_reset(int total_threads)
515 {
516         if (shared_data == NULL)
517                 return;
518
519         memset(&shared_data->body, 0, sizeof(shared_data->body));
520         memset(counter_snapshot, 0, sizeof(counter_snapshot));
521         prev_valid = 0;
522         shared_data->stopping = 0;
523         shared_data->body.start_barrier = total_threads;
524         shared_data->body.stop_barrier = total_threads;
525 }
526
527 static inline void shmem_bump(__u32 counter)
528 {
529         static bool running_not_bumped = true;
530
531         if (shared_data == NULL || thread <= 0 || thread > MAX_THREADS)
532                 return;
533
534         shmem_lock();
535         shared_data->body.counters[thread - 1] += counter;
536         if (running_not_bumped) {
537                 shared_data->body.thr_running++;
538                 running_not_bumped = false;
539         }
540         shmem_unlock();
541 }
542
543 static void shmem_total(int total_threads)
544 {
545         __u64 total = 0;
546         double secs;
547         int i;
548
549         if (shared_data == NULL || total_threads > MAX_THREADS)
550                 return;
551
552         shmem_lock();
553         for (i = 0; i < total_threads; i++)
554                 total += shared_data->body.counters[i];
555
556         secs = difftime(&shared_data->body.end_time,
557                         &shared_data->body.start_time);
558         shmem_unlock();
559
560         printf("Total: total "LPU64" threads %d sec %f %f/second\n",
561                total, total_threads, secs, total / secs);
562
563         return;
564 }
565
566 static void shmem_snap(int total_threads, int live_threads)
567 {
568         struct timeval this_time;
569         int non_zero = 0;
570         __u64 total = 0;
571         double secs;
572         int running;
573         int i;
574
575         if (shared_data == NULL || total_threads > MAX_THREADS)
576                 return;
577
578         shmem_lock();
579         memcpy(counter_snapshot[0], shared_data->body.counters,
580                total_threads * sizeof(counter_snapshot[0][0]));
581         running = shared_data->body.thr_running;
582         shmem_unlock();
583
584         gettimeofday(&this_time, NULL);
585
586         for (i = 0; i < total_threads; i++) {
587                 long long this_count =
588                         counter_snapshot[0][i] - counter_snapshot[1][i];
589
590                 if (this_count != 0) {
591                         non_zero++;
592                         total += this_count;
593                 }
594         }
595
596         secs = difftime(&this_time, &prev_time);
597         if (prev_valid && secs > 1.0)    /* someone screwed with the time? */
598                 printf("%d/%d Total: %f/second\n", non_zero, total_threads,
599                        total / secs);
600
601         memcpy(counter_snapshot[1], counter_snapshot[0],
602                total_threads * sizeof(counter_snapshot[0][0]));
603         prev_time = this_time;
604         if (!prev_valid &&
605             running == total_threads)
606                 prev_valid = 1;
607 }
608
609 static void shmem_stop(void)
610 {
611         if (shared_data == NULL)
612                 return;
613
614         shared_data->stopping = 1;
615 }
616
617 static void shmem_cleanup(void)
618 {
619         if (shared_data == NULL)
620                 return;
621
622         shmem_stop();
623
624         pthread_mutex_destroy(&shared_data->mutex);
625         pthread_cond_destroy(&shared_data->cond);
626 }
627
628 static int shmem_running(void)
629 {
630         return (shared_data == NULL || !shared_data->stopping);
631 }
632
633 static void shmem_end_time_locked(void)
634 {
635         shared_data->body.stop_barrier--;
636         if (shared_data->body.stop_barrier == 0)
637                 gettimeofday(&shared_data->body.end_time, NULL);
638 }
639
640 static void shmem_start_time_locked(void)
641 {
642         shared_data->body.start_barrier--;
643         if (shared_data->body.start_barrier == 0) {
644                 shmem_wakeup_all();
645                 gettimeofday(&shared_data->body.start_time, NULL);
646         } else {
647                 shmem_wait();
648         }
649 }
650
651 #else
652 static int shmem_setup(void)
653 {
654         return 0;
655 }
656
657 static inline void shmem_reset(int total_threads)
658 {
659 }
660
661 static inline void shmem_bump(__u32 counters)
662 {
663 }
664
665 static void shmem_lock()
666 {
667 }
668
669 static void shmem_unlock()
670 {
671 }
672
673 static void shmem_cleanup(void)
674 {
675 }
676
677 static int shmem_running(void)
678 {
679         return 1;
680 }
681 #endif
682
683 extern command_t cmdlist[];
684
685 static int do_device(char *func, char *devname)
686 {
687         int dev;
688
689         dev = parse_devname(func, devname);
690         if (dev < 0)
691                 return -1;
692
693         lcfg_set_devname(devname);
694         cur_device = dev;
695         return 0;
696 }
697
698 int jt_obd_get_device()
699 {
700         return cur_device;
701 }
702
703 int jt_obd_device(int argc, char **argv)
704 {
705         int rc;
706
707         if (argc > 2)
708                 return CMD_HELP;
709
710         if (argc == 1) {
711                 printf("current device is %d - %s\n",
712                        cur_device, lcfg_get_devname() ? : "not set");
713                 return 0;
714         }
715         rc = do_device("device", argv[1]);
716         return rc;
717 }
718
719 int jt_opt_device(int argc, char **argv)
720 {
721         int ret;
722         int rc;
723
724         if (argc < 3)
725                 return CMD_HELP;
726
727         rc = do_device("device", argv[1]);
728
729         if (!rc)
730                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
731
732         ret = do_disconnect(argv[0], 0);
733         if (!rc)
734                 rc = ret;
735
736         return rc;
737 }
738
739 #ifdef MAX_THREADS
740 static void parent_sighandler (int sig)
741 {
742         return;
743 }
744
745 int jt_opt_threads(int argc, char **argv)
746 {
747         static char      cmdstr[128];
748         sigset_t         saveset;
749         sigset_t         sigset;
750         struct sigaction sigact;
751         struct sigaction saveact1;
752         struct sigaction saveact2;
753         unsigned long    threads;
754         __u64            next_thread;
755         int verbose;
756         int rc = 0;
757         int report_count = -1;
758         char *end;
759         int i;
760
761         if (argc < 5)
762                 return CMD_HELP;
763
764         threads = strtoul(argv[1], &end, 0);
765
766         if (*end == '.')
767                 report_count = strtoul(end + 1, &end, 0);
768
769         if (*end || threads > MAX_THREADS) {
770                 fprintf(stderr, "error: %s: invalid thread count '%s'\n",
771                         jt_cmdname(argv[0]), argv[1]);
772                 return CMD_HELP;
773         }
774
775         verbose = get_verbose(argv[0], argv[2]);
776         if (verbose == BAD_VERBOSE)
777                 return CMD_HELP;
778
779         if (verbose != 0) {
780                 snprintf(cmdstr, sizeof(cmdstr), "%s", argv[4]);
781                 for (i = 5; i < argc; i++)
782                         snprintf(cmdstr + strlen(cmdstr), sizeof(cmdstr),
783                                  " %s", argv[i]);
784
785                 printf("%s: starting %ld threads on device %s running %s\n",
786                        argv[0], threads, argv[3], cmdstr);
787         }
788
789         shmem_reset(threads);
790
791         sigemptyset(&sigset);
792         sigaddset(&sigset, SIGALRM);
793         sigaddset(&sigset, SIGCHLD);
794         sigprocmask(SIG_BLOCK, &sigset, &saveset);
795
796         nthreads = threads;
797
798         for (i = 1, next_thread = verbose; i <= threads; i++) {
799                 rc = fork();
800                 if (rc < 0) {
801                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
802                                 strerror(rc = errno));
803                         break;
804                 } else if (rc == 0) {
805                         sigprocmask(SIG_SETMASK, &saveset, NULL);
806
807                         thread = i;
808                         argv[2] = "--device";
809                         exit(jt_opt_device(argc - 2, argv + 2));
810                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
811                         printf("%s: thread #%d (PID %d) started\n",
812                                argv[0], i, rc);
813                 rc = 0;
814         }
815
816         if (!thread) {          /* parent process */
817                 int live_threads = threads;
818
819                 sigemptyset(&sigset);
820                 sigemptyset(&sigact.sa_mask);
821                 sigact.sa_handler = parent_sighandler;
822                 sigact.sa_flags = 0;
823
824                 sigaction(SIGALRM, &sigact, &saveact1);
825                 sigaction(SIGCHLD, &sigact, &saveact2);
826
827                 while (live_threads > 0) {
828                         int status;
829                         pid_t ret;
830
831                         if (verbose < 0)        /* periodic stats */
832                                 alarm(-verbose);
833
834                         sigsuspend(&sigset);
835                         alarm(0);
836
837                         while (live_threads > 0) {
838                                 ret = waitpid(0, &status, WNOHANG);
839                                 if (ret == 0)
840                                         break;
841
842                                 if (ret < 0) {
843                                         fprintf(stderr, "error: %s: wait - %s\n",
844                                                 argv[0], strerror(errno));
845                                         if (!rc)
846                                                 rc = errno;
847                                         continue;
848                                 } else {
849                                         /*
850                                          * This is a hack.  We _should_ be able
851                                          * to use WIFEXITED(status) to see if
852                                          * there was an error, but it appears
853                                          * to be broken and it always returns 1
854                                          * (OK).  See wait(2).
855                                          */
856                                         int err = WEXITSTATUS(status);
857                                         if (err || WIFSIGNALED(status))
858                                                 fprintf(stderr,
859                                                         "%s: PID %d had rc=%d\n",
860                                                         argv[0], ret, err);
861                                         if (!rc)
862                                                 rc = err;
863
864                                         live_threads--;
865                                 }
866                         }
867
868                         /* Show stats while all threads running */
869                         if (verbose < 0) {
870                                 shmem_snap(threads, live_threads);
871                                 if (report_count > 0 && --report_count == 0)
872                                         shmem_stop();
873                         }
874                 }
875                 sigaction(SIGCHLD, &saveact2, NULL);
876                 sigaction(SIGALRM, &saveact1, NULL);
877         }
878
879         shmem_total(threads);
880         sigprocmask(SIG_SETMASK, &saveset, NULL);
881
882         return rc;
883 }
884 #else
885 int jt_opt_threads(int argc, char **argv)
886 {
887         fprintf(stderr, "%s not-supported in a single-threaded runtime\n",
888                 jt_cmdname(argv[0]));
889         return CMD_HELP;
890 }
891 #endif
892
893 int jt_opt_net(int argc, char **argv)
894 {
895         char *arg2[3];
896         int rc;
897
898         if (argc < 3)
899                 return CMD_HELP;
900
901         arg2[0] = argv[0];
902         arg2[1] = argv[1];
903         arg2[2] = NULL;
904         rc = jt_ptl_network (2, arg2);
905
906         if (!rc)
907                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
908
909         return rc;
910 }
911
912 int jt_obd_no_transno(int argc, char **argv)
913 {
914         struct obd_ioctl_data data;
915         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
916         int rc;
917
918         memset(&data, 0, sizeof(data));
919         data.ioc_dev = cur_device;
920
921         if (argc != 1)
922                 return CMD_HELP;
923
924         memset(buf, 0, sizeof(rawbuf));
925         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
926         if (rc) {
927                 fprintf(stderr, "error: %s: invalid ioctl\n",
928                         jt_cmdname(argv[0]));
929                 return rc;
930         }
931         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf);
932         if (rc < 0)
933                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
934                         strerror(rc = errno));
935
936         return rc;
937 }
938
939 int jt_obd_set_readonly(int argc, char **argv)
940 {
941         struct obd_ioctl_data data;
942         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
943         int rc;
944
945         memset(&data, 0, sizeof(data));
946         data.ioc_dev = cur_device;
947
948         if (argc != 1)
949                 return CMD_HELP;
950
951         memset(buf, 0, sizeof(rawbuf));
952         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
953         if (rc) {
954                 fprintf(stderr, "error: %s: invalid ioctl\n",
955                         jt_cmdname(argv[0]));
956                 return rc;
957         }
958         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf);
959         if (rc < 0)
960                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
961                         strerror(rc = errno));
962
963         return rc;
964 }
965
966 int jt_obd_abort_recovery(int argc, char **argv)
967 {
968         struct obd_ioctl_data data;
969         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
970         int rc;
971
972         memset(&data, 0, sizeof(data));
973         data.ioc_dev = cur_device;
974
975         if (argc != 1)
976                 return CMD_HELP;
977
978         memset(buf, 0, sizeof(rawbuf));
979         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
980         if (rc) {
981                 fprintf(stderr, "error: %s: invalid ioctl\n",
982                         jt_cmdname(argv[0]));
983                 return rc;
984         }
985         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf);
986         if (rc < 0)
987                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
988                         strerror(rc = errno));
989
990         return rc;
991 }
992
993 int jt_get_version(int argc, char **argv)
994 {
995         int rc;
996         char rawbuf[MAX_IOC_BUFLEN];
997         char *version;
998
999         if (argc != 1)
1000                 return CMD_HELP;
1001
1002         rc = llapi_get_version(rawbuf, MAX_IOC_BUFLEN, &version);
1003         if (rc)
1004                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1005                         strerror(-rc));
1006         else
1007                 printf("Lustre version: %s\n", version);
1008
1009         printf("lctl   version: %s\n", BUILD_VERSION);
1010         return rc;
1011 }
1012
1013 /*
1014  * Print an obd device line with the ost_conn_uuid inserted, if the obd
1015  * is an osc.
1016  */
1017 static void print_obd_line(char *s)
1018 {
1019         char buf[MAX_STRING_SIZE];
1020         char obd_name[MAX_OBD_NAME];
1021         FILE *fp = NULL;
1022         char *ptr;
1023
1024         if (sscanf(s, " %*d %*s osc %s %*s %*d ", obd_name) == 0)
1025                 goto try_mdc;
1026         snprintf(buf, sizeof(buf),
1027                  "/proc/fs/lustre/osc/%s/ost_conn_uuid", obd_name);
1028         if ((fp = fopen(buf, "r")) == NULL)
1029                 goto try_mdc;
1030         goto got_one;
1031
1032 try_mdc:
1033         if (sscanf(s, " %*d %*s mdc %s %*s %*d ", obd_name) == 0)
1034                 goto fail;
1035         snprintf(buf, sizeof(buf),
1036                  "/proc/fs/lustre/mdc/%s/mds_conn_uuid", obd_name);
1037         if ((fp = fopen(buf, "r")) == NULL)
1038                 goto fail;
1039
1040 got_one:
1041         /* should not ignore fgets(3)'s return value */
1042         if (!fgets(buf, sizeof(buf), fp)) {
1043                 fprintf(stderr, "reading from %s: %s", buf, strerror(errno));
1044                 fclose(fp);
1045                 return;
1046         }
1047         fclose(fp);
1048
1049         /* trim trailing newlines */
1050         ptr = strrchr(buf, '\n');
1051         if (ptr) *ptr = '\0';
1052         ptr = strrchr(s, '\n');
1053         if (ptr) *ptr = '\0';
1054
1055         printf("%s %s\n", s, buf);
1056         return;
1057
1058 fail:
1059         printf("%s", s);
1060         return;
1061 }
1062
1063 /* get device list by ioctl */
1064 int jt_obd_list_ioctl(int argc, char **argv)
1065 {
1066         int rc, index;
1067         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1068         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
1069
1070         if (argc > 2)
1071                 return CMD_HELP;
1072         /* Just ignore a -t option.  Only supported with /proc. */
1073         else if (argc == 2 && strcmp(argv[1], "-t") != 0)
1074                 return CMD_HELP;
1075
1076         for (index = 0;; index++) {
1077                 memset(buf, 0, sizeof(rawbuf));
1078                 data->ioc_version = OBD_IOCTL_VERSION;
1079                 data->ioc_inllen1 =
1080                         sizeof(rawbuf) - cfs_size_round(sizeof(*data));
1081                 data->ioc_inlbuf1 = buf + cfs_size_round(sizeof(*data));
1082                 data->ioc_len = obd_ioctl_packlen(data);
1083                 data->ioc_count = index;
1084
1085                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETDEVICE, buf);
1086                 if (rc != 0)
1087                         break;
1088                 printf("%s\n", (char *)data->ioc_bulk);
1089         }
1090         if (rc != 0) {
1091                 if (errno == ENOENT)
1092                         /* no device or the last device */
1093                         rc = 0;
1094                 else
1095                         fprintf(stderr, "Error getting device list: %s: "
1096                                 "check dmesg.\n", strerror(errno));
1097         }
1098         return rc;
1099 }
1100
1101 int jt_obd_list(int argc, char **argv)
1102 {
1103         int rc;
1104         char buf[MAX_STRING_SIZE];
1105         FILE *fp = NULL;
1106         int print_obd = 0;
1107
1108         if (argc > 2)
1109                 return CMD_HELP;
1110         else if (argc == 2) {
1111                 if (strcmp(argv[1], "-t") == 0)
1112                         print_obd = 1;
1113                 else
1114                         return CMD_HELP;
1115         }
1116
1117         fp = fopen(DEVICES_LIST, "r");
1118         if (fp == NULL) {
1119                 fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
1120                         jt_cmdname(argv[0]), strerror(rc =  errno));
1121                 return jt_obd_list_ioctl(argc, argv);
1122         }
1123
1124         while (fgets(buf, sizeof(buf), fp) != NULL)
1125                 if (print_obd)
1126                         print_obd_line(buf);
1127                 else
1128                         printf("%s", buf);
1129
1130         fclose(fp);
1131         return 0;
1132 }
1133
1134 struct jt_fid_space {
1135         obd_seq jt_seq;
1136         obd_id  jt_id;
1137         int     jt_width;
1138 };
1139
1140 int jt_obd_alloc_fids(struct jt_fid_space *space, struct lu_fid *fid,
1141                       __u64 *count)
1142 {
1143         int rc;
1144
1145         if (space->jt_seq == 0 || space->jt_id == space->jt_width) {
1146                 struct obd_ioctl_data  data;
1147                 char rawbuf[MAX_IOC_BUFLEN];
1148                 char *buf = rawbuf;
1149                 __u64 seqnr;
1150                 int max_count;
1151
1152                 memset(&data, 0, sizeof(data));
1153                 data.ioc_dev = cur_device;
1154
1155                 data.ioc_pbuf1 = (char *)&seqnr;
1156                 data.ioc_plen1 = sizeof(seqnr);
1157
1158                 data.ioc_pbuf2 = (char *)&max_count;
1159                 data.ioc_plen2 = sizeof(max_count);
1160
1161                 memset(buf, 0, sizeof(rawbuf));
1162                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1163                 if (rc) {
1164                         fprintf(stderr, "error: invalid ioctl rc = %d\n", rc);
1165                         return rc;
1166                 }
1167
1168                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ECHO_ALLOC_SEQ, buf);
1169                 if (rc) {
1170                         fprintf(stderr, "ioctl error: rc = %d\n", rc);
1171                         return rc;
1172                 }
1173
1174                 space->jt_seq = *(__u64 *)data.ioc_pbuf1;
1175                 space->jt_width = *(int *)data.ioc_pbuf2;
1176                 space->jt_id = 1;
1177         }
1178         fid->f_seq = space->jt_seq;
1179         fid->f_oid = space->jt_id;
1180         fid->f_ver = 0;
1181
1182         space->jt_id = min(space->jt_id + *count, space->jt_width);
1183
1184         *count = space->jt_id - fid->f_oid;
1185         return 0;
1186 }
1187
1188 #define MD_STEP_COUNT 1000
1189 int jt_obd_md_common(int argc, char **argv, int cmd)
1190 {
1191         struct obd_ioctl_data  data;
1192         struct timeval         start;
1193         struct timeval         end_time;
1194         char                   rawbuf[MAX_IOC_BUFLEN];
1195         char                  *buf = rawbuf;
1196         int                    mode = 0000644;
1197         int                    create_mode;
1198         int                    rc = 0;
1199         char                  *parent_basedir = NULL;
1200         char                   dirname[4096];
1201         int                    parent_base_id = 0;
1202         int                    parent_count = 1;
1203         __u64                  child_base_id = -1;
1204         int                    stripe_count = 0;
1205         int                    stripe_index = -1;
1206         int                    count = 0;
1207         char                  *end;
1208         __u64                  seconds = 0;
1209         double                 diff;
1210         int                    c;
1211         int                    xattr_size = 0;
1212         __u64                  total_count = 0;
1213         char                  *name = NULL;
1214         struct jt_fid_space    fid_space = {0};
1215         int                    version = 0;
1216         struct option          long_opts[] = {
1217                 {"child_base_id",     required_argument, 0, 'b'},
1218                 {"stripe_count",      required_argument, 0, 'c'},
1219                 {"parent_basedir",    required_argument, 0, 'd'},
1220                 {"parent_dircount",   required_argument, 0, 'D'},
1221                 {"stripe_index",      required_argument, 0, 'i'},
1222                 {"mode",              required_argument, 0, 'm'},
1223                 {"count",             required_argument, 0, 'n'},
1224                 {"time",              required_argument, 0, 't'},
1225                 {"version",           no_argument,       0, 'v'},
1226                 {"xattr_size",        required_argument, 0, 'x'},
1227                 {0, 0, 0, 0}
1228         };
1229
1230         optind = 0;
1231         while ((c = getopt_long(argc, argv, "b:c:d:D:m:n:t:vx:",
1232                                 long_opts, NULL)) >= 0) {
1233                 switch (c) {
1234                 case 'b':
1235                         child_base_id = strtoull(optarg, &end, 0);
1236                         if (*end) {
1237                                 fprintf(stderr, "error: %s: bad child_base_id"
1238                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1239                                 return CMD_HELP;
1240                         }
1241                         break;
1242                 case 'c':
1243                         stripe_count = strtoul(optarg, &end, 0);
1244                         if (*end) {
1245                                 fprintf(stderr, "error: %s: bad stripe count"
1246                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1247                                 return CMD_HELP;
1248                         }
1249                         break;
1250                 case 'd':
1251                         parent_basedir = optarg;
1252                         break;
1253                 case 'D':
1254                         parent_count = strtoul(optarg, &end, 0);
1255                         if (*end) {
1256                                 fprintf(stderr, "error: %s: bad parent count"
1257                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1258                                 return CMD_HELP;
1259                         }
1260                         break;
1261                 case 'i':
1262                         stripe_index = strtoul(optarg, &end, 0);
1263                         if (*end) {
1264                                 fprintf(stderr, "error: %s: bad stripe index"
1265                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1266                                 return CMD_HELP;
1267                         }
1268                         break;
1269                 case 'm':
1270                         mode = strtoul(optarg, &end, 0);
1271                         if (*end) {
1272                                 fprintf(stderr, "error: %s: bad mode '%s'\n",
1273                                         jt_cmdname(argv[0]), optarg);
1274                                 return CMD_HELP;
1275                         }
1276                         break;
1277                 case 'n':
1278                         total_count = strtoul(optarg, &end, 0);
1279                         if (*end || total_count == 0) {
1280                                 fprintf(stderr, "%s: bad child count '%s'\n",
1281                                         jt_cmdname(argv[0]), optarg);
1282                                 return CMD_HELP;
1283                         }
1284                         break;
1285                 case 't':
1286                         seconds = strtoull(optarg, &end, 0);
1287                         if (*end) {
1288                                 fprintf(stderr, "error: %s: seconds '%s'\n",
1289                                         jt_cmdname(argv[0]), optarg);
1290                                 return CMD_HELP;
1291                         }
1292                         break;
1293                 case 'v':
1294                         version = 1;
1295                         break;
1296                 case 'x':
1297                         xattr_size = strtoul(optarg, &end, 0);
1298                         if (*end) {
1299                                 fprintf(stderr, "error: %s: xattr_size '%s'\n",
1300                                         jt_cmdname(argv[0]), optarg);
1301                                 return CMD_HELP;
1302                         }
1303                         SET_BUT_UNUSED(xattr_size);
1304                         break;
1305                 default:
1306                         fprintf(stderr, "error: %s: option '%s' "
1307                                 "unrecognized\n", argv[0], argv[optind - 1]);
1308                         return CMD_HELP;
1309                 }
1310         }
1311
1312         memset(&data, 0, sizeof(data));
1313         data.ioc_dev = cur_device;
1314         if (child_base_id == -1) {
1315                 if (optind >= argc)
1316                         return CMD_HELP;
1317                 name = argv[optind];
1318                 total_count = 1;
1319         } else {
1320                 if (optind < argc) {
1321                         fprintf(stderr, "child_base_id and name can not"
1322                                         " specified at the same time\n");
1323                         return CMD_HELP;
1324                 }
1325         }
1326
1327         if (stripe_count == 0 && stripe_index != -1) {
1328                 fprintf(stderr, "If stripe_count is 0, stripe_index can not"
1329                                 "be specified\n");
1330                 return CMD_HELP;
1331         }
1332
1333         if (total_count == 0 && seconds == 0) {
1334                 fprintf(stderr, "count or seconds needs to be indicated\n");
1335                 return CMD_HELP;
1336         }
1337
1338         if (parent_count <= 0) {
1339                 fprintf(stderr, "parent count must < 0\n");
1340                 return CMD_HELP;
1341         }
1342
1343 #ifdef MAX_THREADS
1344         if (thread) {
1345                 shmem_lock();
1346                 /* threads interleave */
1347                 if (parent_base_id != -1)
1348                         parent_base_id += (thread - 1) % parent_count;
1349
1350                 if (child_base_id != -1)
1351                         child_base_id +=  (thread - 1) * \
1352                                           (MAX_BASE_ID / nthreads);
1353
1354                 shmem_start_time_locked();
1355                 shmem_unlock();
1356         }
1357 #endif
1358         /* If parent directory is not specified, try to get the directory
1359          * from name */
1360         if (parent_basedir == NULL) {
1361                 char *last_lash;
1362                 if (name == NULL) {
1363                         fprintf(stderr, "parent_basedir or name must be"
1364                                         "indicated!\n");
1365                         return CMD_HELP;
1366                 }
1367                 /*Get directory and name from name*/
1368                 last_lash = strrchr(name, '/');
1369                 if (last_lash == NULL || name[0] != '/') {
1370                         fprintf(stderr, "Can not locate %s\n", name);
1371                         return CMD_HELP;
1372                 }
1373
1374                 if (last_lash == name) {
1375                         sprintf(dirname, "%s", "/");
1376                         name++;
1377                 } else {
1378                         int namelen = (unsigned long)last_lash -
1379                                       (unsigned long)name;
1380                         snprintf(dirname, namelen, "%s", name);
1381                 }
1382
1383                 data.ioc_pbuf1 = dirname;
1384                 data.ioc_plen1 = strlen(dirname);
1385
1386                 data.ioc_pbuf2 = name;
1387                 data.ioc_plen2 = strlen(name);
1388         } else {
1389                 if (name != NULL) {
1390                         data.ioc_pbuf2 = name;
1391                         data.ioc_plen2 = strlen(name);
1392                 } else {
1393                         if (parent_base_id > 0)
1394                                 sprintf(dirname, "%s%d", parent_basedir,
1395                                         parent_base_id);
1396                         else
1397                                 sprintf(dirname, "%s", parent_basedir);
1398                 }
1399                 data.ioc_pbuf1 = dirname;
1400                 data.ioc_plen1 = strlen(dirname);
1401         }
1402
1403         if (cmd == ECHO_MD_MKDIR || cmd == ECHO_MD_RMDIR)
1404                 create_mode = S_IFDIR;
1405         else
1406                 create_mode = S_IFREG;
1407
1408         data.ioc_obdo1.o_mode = mode | S_IFDIR;
1409         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE |
1410                                  OBD_MD_FLFLAGS | OBD_MD_FLGROUP;
1411         data.ioc_command = cmd;
1412
1413         gettimeofday(&start, NULL);
1414         while (shmem_running()) {
1415                 struct lu_fid fid;
1416
1417                 data.ioc_obdo2.o_id = child_base_id;
1418                 data.ioc_obdo2.o_mode = mode | create_mode;
1419                 data.ioc_obdo2.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE |
1420                                          OBD_MD_FLMODE | OBD_MD_FLFLAGS |
1421                                          OBD_MD_FLGROUP;
1422                 data.ioc_obdo2.o_misc = stripe_count;
1423                 data.ioc_obdo2.o_stripe_idx = stripe_index;
1424
1425                 if (total_count > 0) {
1426                         if ((total_count - count) > MD_STEP_COUNT)
1427                                 data.ioc_count = MD_STEP_COUNT;
1428                         else
1429                                 data.ioc_count = total_count - count;
1430                 } else {
1431                         data.ioc_count = MD_STEP_COUNT;
1432                 }
1433
1434                 if (cmd == ECHO_MD_CREATE || cmd == ECHO_MD_MKDIR) {
1435                         /*Allocate fids for the create */
1436                         rc = jt_obd_alloc_fids(&fid_space, &fid,
1437                                                &data.ioc_count);
1438                         if (rc) {
1439                                 fprintf(stderr, "Allocate fids error %d.\n",rc);
1440                                 return rc;
1441                         }
1442                         data.ioc_obdo1.o_seq = fid.f_seq;
1443                         data.ioc_obdo1.o_id = fid.f_oid;
1444                 }
1445
1446                 child_base_id += data.ioc_count;
1447                 count += data.ioc_count;
1448
1449                 memset(buf, 0, sizeof(rawbuf));
1450                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1451                 if (rc) {
1452                         fprintf(stderr, "error: %s: invalid ioctl %d\n",
1453                                 jt_cmdname(argv[0]), rc);
1454                         return rc;
1455                 }
1456
1457                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ECHO_MD, buf);
1458                 if (rc) {
1459                         fprintf(stderr, "error: %s: %s\n",
1460                                 jt_cmdname(argv[0]), strerror(rc = errno));
1461                         return rc;
1462                 }
1463                 shmem_bump(data.ioc_count);
1464
1465                 gettimeofday(&end_time, NULL);
1466                 diff = difftime(&end_time, &start);
1467                 if (seconds > 0 && (__u64)diff > seconds)
1468                         break;
1469
1470                 if (count >= total_count && total_count > 0)
1471                         break;
1472         }
1473
1474         if (count > 0 && version) {
1475                 gettimeofday(&end_time, NULL);
1476                 diff = difftime(&end_time, &start);
1477                 printf("%s: %d in %.3fs (%.3f /s): %s",
1478                         jt_cmdname(argv[0]), count, diff,
1479                         (double)count/diff, ctime(&end_time.tv_sec));
1480         }
1481
1482 #ifdef MAX_THREADS
1483         if (thread) {
1484                 shmem_lock();
1485                 shmem_end_time_locked();
1486                 shmem_unlock();
1487         }
1488 #endif
1489         return rc;
1490 }
1491
1492 int jt_obd_test_create(int argc, char **argv)
1493 {
1494         return jt_obd_md_common(argc, argv, ECHO_MD_CREATE);
1495 }
1496
1497 int jt_obd_test_mkdir(int argc, char **argv)
1498 {
1499         return jt_obd_md_common(argc, argv, ECHO_MD_MKDIR);
1500 }
1501
1502 int jt_obd_test_destroy(int argc, char **argv)
1503 {
1504         return jt_obd_md_common(argc, argv, ECHO_MD_DESTROY);
1505 }
1506
1507 int jt_obd_test_rmdir(int argc, char **argv)
1508 {
1509         return jt_obd_md_common(argc, argv, ECHO_MD_RMDIR);
1510 }
1511
1512 int jt_obd_test_lookup(int argc, char **argv)
1513 {
1514         return jt_obd_md_common(argc, argv, ECHO_MD_LOOKUP);
1515 }
1516
1517 int jt_obd_test_setxattr(int argc, char **argv)
1518 {
1519         return jt_obd_md_common(argc, argv, ECHO_MD_SETATTR);
1520 }
1521
1522 int jt_obd_test_md_getattr(int argc, char **argv)
1523 {
1524         return jt_obd_md_common(argc, argv, ECHO_MD_GETATTR);
1525 }
1526
1527 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1528  * not, defaults assumed.  This echo-client instance stashes the stripe
1529  * object ids.  Use get_stripe on this node to print full lsm and
1530  * set_stripe on another node to cut/paste between nodes.
1531  */
1532 /* create <count> [<file_create_mode>] [q|v|# verbosity] [striping] */
1533 int jt_obd_create(int argc, char **argv)
1534 {
1535         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1536         struct obd_ioctl_data data;
1537         struct timeval next_time;
1538         __u64 count = 1, next_count, base_id = 0;
1539         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
1540         char *end;
1541
1542         memset(&data, 0, sizeof(data));
1543         data.ioc_dev = cur_device;
1544         if (argc < 2 || argc > 5)
1545                 return CMD_HELP;
1546
1547         count = strtoull(argv[1], &end, 0);
1548         if (*end) {
1549                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1550                         jt_cmdname(argv[0]), argv[1]);
1551                 return CMD_HELP;
1552         }
1553
1554         if (argc > 2) {
1555                 mode = strtoul(argv[2], &end, 0);
1556                 if (*end) {
1557                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1558                                 jt_cmdname(argv[0]), argv[2]);
1559                         return CMD_HELP;
1560                 }
1561                 if (!(mode & S_IFMT))
1562                         mode |= S_IFREG;
1563         }
1564
1565         if (argc > 3) {
1566                 verbose = get_verbose(argv[0], argv[3]);
1567                 if (verbose == BAD_VERBOSE)
1568                         return CMD_HELP;
1569         }
1570
1571         if (argc < 5) {
1572                 reset_lsmb (&lsm_buffer);       /* will set default */
1573         } else {
1574                 rc = parse_lsm (&lsm_buffer, argv[4]);
1575                 if (rc != 0) {
1576                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1577                                 jt_cmdname(argv[0]), argv[4]);
1578                         return CMD_HELP;
1579                 }
1580                 base_id = lsm_buffer.lsm.lsm_object_id;
1581                 valid_lsm = 1;
1582         }
1583
1584         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1585         gettimeofday(&next_time, NULL);
1586         next_time.tv_sec -= verbose;
1587
1588         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1589                 data.ioc_obdo1.o_mode = mode;
1590                 data.ioc_obdo1.o_id = base_id;
1591                 data.ioc_obdo1.o_uid = 0;
1592                 data.ioc_obdo1.o_gid = 0;
1593                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1594                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1595
1596                 if (valid_lsm) {
1597                         data.ioc_plen1 = sizeof lsm_buffer;
1598                         data.ioc_pbuf1 = (char *)&lsm_buffer;
1599                 }
1600
1601                 memset(buf, 0, sizeof(rawbuf));
1602                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1603                 if (rc) {
1604                         fprintf(stderr, "error: %s: invalid ioctl\n",
1605                                 jt_cmdname(argv[0]));
1606                         return rc;
1607                 }
1608                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1609                 obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1610                 shmem_bump(1);
1611                 if (rc < 0) {
1612                         fprintf(stderr, "error: %s: #%d - %s\n",
1613                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1614                         break;
1615                 }
1616                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1617                         fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n",
1618                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1619                         rc = EINVAL;
1620                         break;
1621                 }
1622
1623                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1624                         printf("%s: #%d is object id "LPX64"\n",
1625                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1626         }
1627         return rc;
1628 }
1629
1630 int jt_obd_setattr(int argc, char **argv)
1631 {
1632         struct obd_ioctl_data data;
1633         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1634         char *end;
1635         int rc;
1636
1637         memset(&data, 0, sizeof(data));
1638         data.ioc_dev = cur_device;
1639         if (argc != 2)
1640                 return CMD_HELP;
1641
1642         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1643         if (*end) {
1644                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1645                         jt_cmdname(argv[0]), argv[1]);
1646                 return CMD_HELP;
1647         }
1648         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1649         if (*end) {
1650                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1651                         jt_cmdname(argv[0]), argv[2]);
1652                 return CMD_HELP;
1653         }
1654         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1655
1656         memset(buf, 0, sizeof(rawbuf));
1657         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1658         if (rc) {
1659                 fprintf(stderr, "error: %s: invalid ioctl\n",
1660                         jt_cmdname(argv[0]));
1661                 return rc;
1662         }
1663         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1664         if (rc < 0)
1665                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1666                         strerror(rc = errno));
1667
1668         return rc;
1669 }
1670
1671 int jt_obd_test_setattr(int argc, char **argv)
1672 {
1673         struct obd_ioctl_data data;
1674         struct timeval start, next_time;
1675         __u64 i, count, next_count;
1676         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1677         int verbose = 1;
1678         obd_id objid = 3;
1679         char *end;
1680         int rc = 0;
1681
1682         if (argc < 2 || argc > 4)
1683                 return CMD_HELP;
1684
1685         memset(&data, 0, sizeof(data));
1686         data.ioc_dev = cur_device;
1687         count = strtoull(argv[1], &end, 0);
1688         if (*end) {
1689                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1690                         jt_cmdname(argv[0]), argv[1]);
1691                 return CMD_HELP;
1692         }
1693
1694         if (argc >= 3) {
1695                 verbose = get_verbose(argv[0], argv[2]);
1696                 if (verbose == BAD_VERBOSE)
1697                         return CMD_HELP;
1698         }
1699
1700         if (argc >= 4) {
1701                 if (argv[3][0] == 't') {
1702                         objid = strtoull(argv[3] + 1, &end, 0);
1703                         if (thread)
1704                                 objid += thread - 1;
1705                 } else
1706                         objid = strtoull(argv[3], &end, 0);
1707                 if (*end) {
1708                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1709                                 jt_cmdname(argv[0]), argv[3]);
1710                         return CMD_HELP;
1711                 }
1712         }
1713
1714         gettimeofday(&start, NULL);
1715         next_time.tv_sec = start.tv_sec - verbose;
1716         next_time.tv_usec = start.tv_usec;
1717         if (verbose != 0)
1718                 printf("%s: setting "LPD64" attrs (objid "LPX64"): %s",
1719                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1720
1721         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1722                 data.ioc_obdo1.o_id = objid;
1723                 data.ioc_obdo1.o_mode = S_IFREG;
1724                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1725                 memset(buf, 0, sizeof(rawbuf));
1726                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1727                 if (rc) {
1728                         fprintf(stderr, "error: %s: invalid ioctl\n",
1729                                 jt_cmdname(argv[0]));
1730                         return rc;
1731                 }
1732                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data);
1733                 shmem_bump(1);
1734                 if (rc < 0) {
1735                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1736                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1737                         break;
1738                 } else {
1739                         if (be_verbose
1740                             (verbose, &next_time, i, &next_count, count))
1741                                 printf("%s: set attr #"LPD64"\n",
1742                                        jt_cmdname(argv[0]), i);
1743                 }
1744         }
1745
1746         if (!rc) {
1747                 struct timeval end;
1748                 double diff;
1749
1750                 gettimeofday(&end, NULL);
1751
1752                 diff = difftime(&end, &start);
1753
1754                 --i;
1755                 if (verbose != 0)
1756                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1757                                jt_cmdname(argv[0]), i, diff, i / diff,
1758                                ctime(&end.tv_sec));
1759         }
1760         return rc;
1761 }
1762
1763 int jt_obd_destroy(int argc, char **argv)
1764 {
1765         struct obd_ioctl_data data;
1766         struct timeval next_time;
1767         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1768         __u64 count = 1, next_count;
1769         int verbose = 1;
1770         __u64 id;
1771         char *end;
1772         int rc = 0, i;
1773
1774         memset(&data, 0, sizeof(data));
1775         data.ioc_dev = cur_device;
1776         if (argc < 2 || argc > 4)
1777                 return CMD_HELP;
1778
1779         id = strtoull(argv[1], &end, 0);
1780         if (*end || id == 0 || errno != 0) {
1781                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1782                         jt_cmdname(argv[0]), argv[1]);
1783                 return CMD_HELP;
1784         }
1785         if (argc > 2) {
1786                 count = strtoull(argv[2], &end, 0);
1787                 if (*end) {
1788                         fprintf(stderr,
1789                                 "error: %s: invalid iteration count '%s'\n",
1790                                 jt_cmdname(argv[0]), argv[2]);
1791                         return CMD_HELP;
1792                 }
1793         }
1794
1795         if (argc > 3) {
1796                 verbose = get_verbose(argv[0], argv[3]);
1797                 if (verbose == BAD_VERBOSE)
1798                         return CMD_HELP;
1799         }
1800
1801         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1802         gettimeofday(&next_time, NULL);
1803         next_time.tv_sec -= verbose;
1804
1805         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++, id++) {
1806                 data.ioc_obdo1.o_id = id;
1807                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1808                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1809
1810                 memset(buf, 0, sizeof(rawbuf));
1811                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1812                 if (rc) {
1813                         fprintf(stderr, "error: %s: invalid ioctl\n",
1814                                 jt_cmdname(argv[0]));
1815                         return rc;
1816                 }
1817                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1818                 obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1819                 shmem_bump(1);
1820                 if (rc < 0) {
1821                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1822                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1823                         break;
1824                 }
1825
1826                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1827                         printf("%s: #%d is object id "LPX64"\n",
1828                                jt_cmdname(argv[0]), i, id);
1829         }
1830
1831         return rc;
1832 }
1833
1834 int jt_obd_getattr(int argc, char **argv)
1835 {
1836         struct obd_ioctl_data data;
1837         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1838         char *end;
1839         int rc;
1840
1841         if (argc != 2)
1842                 return CMD_HELP;
1843
1844         memset(&data, 0, sizeof(data));
1845         data.ioc_dev = cur_device;
1846         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1847         if (*end) {
1848                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1849                         jt_cmdname(argv[0]), argv[1]);
1850                 return CMD_HELP;
1851         }
1852         /* to help obd filter */
1853         data.ioc_obdo1.o_mode = 0100644;
1854         data.ioc_obdo1.o_valid = 0xffffffff;
1855         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1856
1857         memset(buf, 0, sizeof(rawbuf));
1858         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1859         if (rc) {
1860                 fprintf(stderr, "error: %s: invalid ioctl\n",
1861                         jt_cmdname(argv[0]));
1862                 return rc;
1863         }
1864         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1865         obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1866         if (rc) {
1867                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1868                         strerror(rc = errno));
1869         } else {
1870                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1871                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1872         }
1873         return rc;
1874 }
1875
1876 int jt_obd_test_getattr(int argc, char **argv)
1877 {
1878         struct obd_ioctl_data data;
1879         struct timeval start, next_time;
1880         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1881         __u64 i, count, next_count;
1882         int verbose = 1;
1883         obd_id objid = 3;
1884         char *end;
1885         int rc = 0;
1886
1887         if (argc < 2 || argc > 4)
1888                 return CMD_HELP;
1889
1890         memset(&data, 0, sizeof(data));
1891         data.ioc_dev = cur_device;
1892         count = strtoull(argv[1], &end, 0);
1893         if (*end) {
1894                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1895                         jt_cmdname(argv[0]), argv[1]);
1896                 return CMD_HELP;
1897         }
1898
1899         if (argc >= 3) {
1900                 verbose = get_verbose(argv[0], argv[2]);
1901                 if (verbose == BAD_VERBOSE)
1902                         return CMD_HELP;
1903         }
1904
1905         if (argc >= 4) {
1906                 if (argv[3][0] == 't') {
1907                         objid = strtoull(argv[3] + 1, &end, 0);
1908                         if (thread)
1909                                 objid += thread - 1;
1910                 } else
1911                         objid = strtoull(argv[3], &end, 0);
1912                 if (*end) {
1913                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1914                                 jt_cmdname(argv[0]), argv[3]);
1915                         return CMD_HELP;
1916                 }
1917         }
1918
1919         gettimeofday(&start, NULL);
1920         next_time.tv_sec = start.tv_sec - verbose;
1921         next_time.tv_usec = start.tv_usec;
1922         if (verbose != 0)
1923                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1924                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1925
1926         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1927                 data.ioc_obdo1.o_id = objid;
1928                 data.ioc_obdo1.o_mode = S_IFREG;
1929                 data.ioc_obdo1.o_valid = 0xffffffff;
1930                 memset(buf, 0, sizeof(rawbuf));
1931                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1932                 if (rc) {
1933                         fprintf(stderr, "error: %s: invalid ioctl\n",
1934                                 jt_cmdname(argv[0]));
1935                         return rc;
1936                 }
1937                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1938                 shmem_bump(1);
1939                 if (rc < 0) {
1940                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1941                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1942                         break;
1943                 } else {
1944                         if (be_verbose
1945                             (verbose, &next_time, i, &next_count, count))
1946                                 printf("%s: got attr #"LPD64"\n",
1947                                        jt_cmdname(argv[0]), i);
1948                 }
1949         }
1950
1951         if (!rc) {
1952                 struct timeval end;
1953                 double diff;
1954
1955                 gettimeofday(&end, NULL);
1956
1957                 diff = difftime(&end, &start);
1958
1959                 --i;
1960                 if (verbose != 0)
1961                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1962                                jt_cmdname(argv[0]), i, diff, i / diff,
1963                                ctime(&end.tv_sec));
1964         }
1965         return rc;
1966 }
1967
1968 /* test_brw <cnt>                                               count
1969         <r|w[r(repeat)x(noverify)]>                             mode
1970         <q|v|#(print interval)>                                 verbosity
1971         <npages[+offset]>                                       blocksize
1972         <[[<interleave_threads>]t(inc obj by thread#)]obj>      object
1973         [p|g<args>]                                             batch */
1974 int jt_obd_test_brw(int argc, char **argv)
1975 {
1976         struct obd_ioctl_data data;
1977         struct timeval start, next_time;
1978         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1979         __u64 count, next_count, len, stride, thr_offset = 0, objid = 3;
1980         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1981         int offset_pages = 0;
1982         long n;
1983         int repeat_offset = 0;
1984         unsigned long long ull;
1985         int  nthr_per_obj = 0;
1986         int  verify = 1;
1987         int  obj_idx = 0;
1988         char *end;
1989
1990         if (argc < 2 || argc > 7) {
1991                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1992                         jt_cmdname(argv[0]), argc);
1993                 return CMD_HELP;
1994         }
1995
1996         count = strtoull(argv[1], &end, 0);
1997         if (*end) {
1998                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1999                         jt_cmdname(argv[0]), argv[1]);
2000                 return CMD_HELP;
2001         }
2002
2003         if (argc >= 3) {
2004                 if (argv[2][0] == 'w' || argv[2][0] == '1')
2005                         write = 1;
2006                 /* else it's a read */
2007
2008                 if (argv[2][0] != 0)
2009                         for (i = 1; argv[2][i] != 0; i++)
2010                                 switch (argv[2][i]) {
2011                                 case 'r':
2012                                         repeat_offset = 1;
2013                                         break;
2014
2015                                 case 'x':
2016                                         verify = 0;
2017                                         break;
2018
2019                                 default:
2020                                         fprintf (stderr, "Can't parse cmd '%s'\n",
2021                                                  argv[2]);
2022                                         return CMD_HELP;
2023                                 }
2024         }
2025
2026         if (argc >= 4) {
2027                 verbose = get_verbose(argv[0], argv[3]);
2028                 if (verbose == BAD_VERBOSE)
2029                         return CMD_HELP;
2030         }
2031
2032         if (argc >= 5) {
2033                 pages = strtoul(argv[4], &end, 0);
2034
2035                 if (*end == '+')
2036                         offset_pages = strtoul(end + 1, &end, 0);
2037
2038                 if (*end != 0 ||
2039                     offset_pages < 0 || offset_pages >= pages) {
2040                         fprintf(stderr, "error: %s: bad npages[+offset] parameter '%s'\n",
2041                                 jt_cmdname(argv[0]), argv[4]);
2042                         return CMD_HELP;
2043                 }
2044         }
2045
2046         if (argc >= 6) {
2047                 if (thread &&
2048                     (n = strtol(argv[5], &end, 0)) > 0 &&
2049                     *end == 't' &&
2050                     (ull = strtoull(end + 1, &end, 0)) > 0 &&
2051                     *end == 0) {
2052                         nthr_per_obj = n;
2053                         objid = ull;
2054                 } else if (thread &&
2055                            argv[5][0] == 't') {
2056                         nthr_per_obj = 1;
2057                         objid = strtoull(argv[5] + 1, &end, 0);
2058                 } else {
2059                         nthr_per_obj = 0;
2060                         objid = strtoull(argv[5], &end, 0);
2061                 }
2062                 if (*end) {
2063                         fprintf(stderr, "error: %s: bad objid '%s'\n",
2064                                 jt_cmdname(argv[0]), argv[5]);
2065                         return CMD_HELP;
2066                 }
2067         }
2068
2069         memset(&data, 0, sizeof(data));
2070         data.ioc_dev = cur_device;
2071
2072         /* communicate the 'type' of brw test and batching to echo_client.
2073          * don't start.  we'd love to refactor this lctl->echo_client
2074          * interface */
2075         data.ioc_pbuf1 = (void *)1;
2076         data.ioc_plen1 = 1;
2077
2078         if (argc >= 7) {
2079                 switch(argv[6][0]) {
2080                         case 'g': /* plug and unplug */
2081                                 data.ioc_pbuf1 = (void *)2;
2082                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
2083                                                           0);
2084                                 break;
2085                         case 'p': /* prep and commit */
2086                                 data.ioc_pbuf1 = (void *)3;
2087                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
2088                                                           0);
2089                                 break;
2090                         default:
2091                                 fprintf(stderr, "error: %s: batching '%s' "
2092                                         "needs to specify 'p' or 'g'\n",
2093                                         jt_cmdname(argv[0]), argv[6]);
2094                                 return CMD_HELP;
2095                 }
2096
2097                 if (*end) {
2098                         fprintf(stderr, "error: %s: bad batching '%s'\n",
2099                                 jt_cmdname(argv[0]), argv[6]);
2100                         return CMD_HELP;
2101                 }
2102                 data.ioc_plen1 *= getpagesize();
2103         }
2104
2105         len = pages * getpagesize();
2106         thr_offset = offset_pages * getpagesize();
2107         stride = len;
2108
2109 #ifdef MAX_THREADS
2110         if (thread) {
2111                 shmem_lock ();
2112                 if (nthr_per_obj != 0) {
2113                         /* threads interleave */
2114                         obj_idx = (thread - 1)/nthr_per_obj;
2115                         objid += obj_idx;
2116                         stride *= nthr_per_obj;
2117                         if ((thread - 1) % nthr_per_obj == 0) {
2118                                 shared_data->body.offsets[obj_idx] =
2119                                         stride + thr_offset;
2120                         }
2121                         thr_offset += ((thread - 1) % nthr_per_obj) * len;
2122                 } else {
2123                         /* threads disjoint */
2124                         thr_offset += (thread - 1) * len;
2125                 }
2126
2127                 shmem_start_time_locked();
2128                 shmem_unlock ();
2129         }
2130 #endif
2131
2132         data.ioc_obdo1.o_id = objid;
2133         data.ioc_obdo1.o_mode = S_IFREG;
2134         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS;
2135         data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0);
2136         data.ioc_count = len;
2137         data.ioc_offset = (repeat_offset ? 0 : thr_offset);
2138
2139         gettimeofday(&start, NULL);
2140         next_time.tv_sec = start.tv_sec - verbose;
2141         next_time.tv_usec = start.tv_usec;
2142
2143         if (verbose != 0)
2144                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
2145                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
2146                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
2147
2148         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
2149         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
2150                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
2151                 memset(buf, 0, sizeof(rawbuf));
2152                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2153                 if (rc) {
2154                         fprintf(stderr, "error: %s: invalid ioctl\n",
2155                                 jt_cmdname(argv[0]));
2156                         return rc;
2157                 }
2158                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
2159                 shmem_bump(1);
2160                 if (rc) {
2161                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
2162                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
2163                                 write ? "write" : "read");
2164                         break;
2165                 } else if (be_verbose(verbose, &next_time,i, &next_count,count)) {
2166                         shmem_lock ();
2167                         printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n",
2168                                jt_cmdname(argv[0]), write ? "write" : "read", i,
2169                                data.ioc_obdo1.o_id, data.ioc_offset,
2170                                (int)(pages * getpagesize()));
2171                         shmem_unlock ();
2172                 }
2173
2174                 if (!repeat_offset) {
2175 #ifdef MAX_THREADS
2176                         if (stride == len) {
2177                                 data.ioc_offset += stride;
2178                         } else if (i < count) {
2179                                 shmem_lock ();
2180                                 data.ioc_offset =
2181                                         shared_data->body.offsets[obj_idx];
2182                                 shared_data->body.offsets[obj_idx] += len;
2183                                 shmem_unlock ();
2184                         }
2185 #else
2186                         data.ioc_offset += len;
2187                         obj_idx = 0; /* avoids an unused var warning */
2188 #endif
2189                 }
2190         }
2191
2192         if (!rc) {
2193                 struct timeval end;
2194                 double diff;
2195
2196                 gettimeofday(&end, NULL);
2197
2198                 diff = difftime(&end, &start);
2199
2200                 --i;
2201                 if (verbose != 0)
2202                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
2203                                jt_cmdname(argv[0]), write ? "wrote" : "read",
2204                                i, pages, diff,
2205                                ((double)i * pages * getpagesize()) /
2206                                (diff * 1048576.0),
2207                                ctime(&end.tv_sec));
2208         }
2209
2210 #ifdef MAX_THREADS
2211         if (thread) {
2212                 shmem_lock();
2213                 shmem_end_time_locked();
2214                 shmem_unlock();
2215         }
2216 #endif
2217         return rc;
2218 }
2219
2220 int jt_obd_lov_getconfig(int argc, char **argv)
2221 {
2222         struct obd_ioctl_data data;
2223         struct lov_desc desc;
2224         struct obd_uuid *uuidarray;
2225         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2226         __u32 *obdgens;
2227         char *path;
2228         int rc, fd;
2229
2230         memset(&data, 0, sizeof(data));
2231         data.ioc_dev = cur_device;
2232
2233         if (argc != 2)
2234                 return CMD_HELP;
2235
2236         path = argv[1];
2237         fd = open(path, O_RDONLY);
2238         if (fd < 0) {
2239                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
2240                         strerror(errno));
2241                 return -errno;
2242         }
2243
2244         memset(&desc, 0, sizeof(desc));
2245         obd_str2uuid(&desc.ld_uuid, argv[1]);
2246         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
2247                              (sizeof(*uuidarray) + sizeof(*obdgens)));
2248
2249 repeat:
2250         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
2251         if (!uuidarray) {
2252                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
2253                         jt_cmdname(argv[0]), desc.ld_tgt_count);
2254                 rc = -ENOMEM;
2255                 goto out;
2256         }
2257         obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens));
2258         if (!obdgens) {
2259                 fprintf(stderr, "error: %s: no memory for %d generation #'s\n",
2260                         jt_cmdname(argv[0]), desc.ld_tgt_count);
2261                 rc = -ENOMEM;
2262                 goto out_uuidarray;
2263         }
2264
2265         memset(buf, 0, sizeof(rawbuf));
2266         data.ioc_inllen1 = sizeof(desc);
2267         data.ioc_inlbuf1 = (char *)&desc;
2268         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
2269         data.ioc_inlbuf2 = (char *)uuidarray;
2270         data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens);
2271         data.ioc_inlbuf3 = (char *)obdgens;
2272
2273         if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) {
2274                 fprintf(stderr, "error: %s: invalid ioctl\n",
2275                         jt_cmdname(argv[0]));
2276                 rc = -EINVAL;
2277                 goto out_obdgens;
2278         }
2279         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
2280         if (rc == -ENOSPC) {
2281                 free(uuidarray);
2282                 free(obdgens);
2283                 goto repeat;
2284         } else if (rc) {
2285                 fprintf(stderr, "error: %s: ioctl error: %s\n",
2286                         jt_cmdname(argv[0]), strerror(rc = errno));
2287         } else {
2288                 struct obd_uuid *uuidp;
2289                 __u32 *genp;
2290                 int i;
2291
2292                 if (obd_ioctl_unpack(&data, buf, sizeof(rawbuf))) {
2293                         fprintf(stderr, "error: %s: invalid reply\n",
2294                                 jt_cmdname(argv[0]));
2295                         rc = -EINVAL;
2296                         goto out;
2297                 }
2298                 if (desc.ld_default_stripe_count == (__u32)-1)
2299                         printf("default_stripe_count: %d\n", -1);
2300                 else
2301                         printf("default_stripe_count: %u\n",
2302                                desc.ld_default_stripe_count);
2303                 printf("default_stripe_size: "LPU64"\n",
2304                        desc.ld_default_stripe_size);
2305                 printf("default_stripe_offset: "LPU64"\n",
2306                        desc.ld_default_stripe_offset);
2307                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
2308                 printf("obd_count: %u\n", desc.ld_tgt_count);
2309                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
2310                 uuidp = uuidarray;
2311                 genp = obdgens;
2312                 for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++)
2313                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp);
2314         }
2315 out_obdgens:
2316         free(obdgens);
2317 out_uuidarray:
2318         free(uuidarray);
2319 out:
2320         close(fd);
2321         return rc;
2322 }
2323
2324 int jt_obd_ldlm_regress_start(int argc, char **argv)
2325 {
2326         int rc;
2327         struct obd_ioctl_data data;
2328         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2329         char argstring[200];
2330         int i, count = sizeof(argstring) - 1;
2331
2332         memset(&data, 0, sizeof(data));
2333         data.ioc_dev = cur_device;
2334         if (argc > 5)
2335                 return CMD_HELP;
2336
2337         argstring[0] = '\0';
2338         for (i = 1; i < argc; i++) {
2339                 strncat(argstring, " ", count);
2340                 count--;
2341                 strncat(argstring, argv[i], count);
2342                 count -= strlen(argv[i]);
2343         }
2344
2345         if (strlen(argstring)) {
2346                 data.ioc_inlbuf1 = argstring;
2347                 data.ioc_inllen1 = strlen(argstring) + 1;
2348         }
2349
2350         memset(buf, 0, sizeof(rawbuf));
2351         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2352         if (rc) {
2353                 fprintf(stderr, "error: %s: invalid ioctl\n",
2354                         jt_cmdname(argv[0]));
2355                 return rc;
2356         }
2357         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
2358         if (rc)
2359                 fprintf(stderr, "error: %s: test failed: %s\n",
2360                         jt_cmdname(argv[0]), strerror(rc = errno));
2361
2362         return rc;
2363 }
2364
2365 int jt_obd_ldlm_regress_stop(int argc, char **argv)
2366 {
2367         int rc;
2368         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2369         struct obd_ioctl_data data;
2370
2371         memset(&data, 0, sizeof(data));
2372         data.ioc_dev = cur_device;
2373
2374         if (argc != 1)
2375                 return CMD_HELP;
2376
2377         memset(buf, 0, sizeof(rawbuf));
2378         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2379         if (rc) {
2380                 fprintf(stderr, "error: %s: invalid ioctl\n",
2381                         jt_cmdname(argv[0]));
2382                 return rc;
2383         }
2384         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
2385
2386         if (rc)
2387                 fprintf(stderr, "error: %s: test failed: %s\n",
2388                         jt_cmdname(argv[0]), strerror(rc = errno));
2389         return rc;
2390 }
2391
2392 static int do_activate(int argc, char **argv, int flag)
2393 {
2394         struct obd_ioctl_data data;
2395         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2396         int rc;
2397
2398         memset(&data, 0, sizeof(data));
2399         data.ioc_dev = cur_device;
2400         if (argc != 1)
2401                 return CMD_HELP;
2402
2403         /* reuse offset for 'active' */
2404         data.ioc_offset = flag;
2405
2406         memset(buf, 0, sizeof(rawbuf));
2407         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2408         if (rc) {
2409                 fprintf(stderr, "error: %s: invalid ioctl\n",
2410                         jt_cmdname(argv[0]));
2411                 return rc;
2412         }
2413         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
2414         if (rc)
2415                 fprintf(stderr, "error: %s: failed: %s\n",
2416                         jt_cmdname(argv[0]), strerror(rc = errno));
2417
2418         return rc;
2419 }
2420
2421 int jt_obd_deactivate(int argc, char **argv)
2422 {
2423         return do_activate(argc, argv, 0);
2424 }
2425
2426 int jt_obd_activate(int argc, char **argv)
2427 {
2428         return do_activate(argc, argv, 1);
2429 }
2430
2431 int jt_obd_recover(int argc, char **argv)
2432 {
2433         int rc;
2434         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2435         struct obd_ioctl_data data;
2436
2437         memset(&data, 0, sizeof(data));
2438         data.ioc_dev = cur_device;
2439         if (argc > 2)
2440                 return CMD_HELP;
2441
2442         if (argc == 2) {
2443                 data.ioc_inllen1 = strlen(argv[1]) + 1;
2444                 data.ioc_inlbuf1 = argv[1];
2445         }
2446
2447         memset(buf, 0, sizeof(rawbuf));
2448         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2449         if (rc) {
2450                 fprintf(stderr, "error: %s: invalid ioctl\n",
2451                         jt_cmdname(argv[0]));
2452                 return rc;
2453         }
2454         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
2455         if (rc < 0) {
2456                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
2457                         strerror(rc = errno));
2458         }
2459
2460         return rc;
2461 }
2462
2463 int jt_obd_mdc_lookup(int argc, char **argv)
2464 {
2465         struct obd_ioctl_data data;
2466         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2467         char *parent, *child;
2468         int rc, fd, verbose = 1;
2469
2470         if (argc < 3 || argc > 4)
2471                 return CMD_HELP;
2472
2473         parent = argv[1];
2474         child = argv[2];
2475         if (argc == 4)
2476                 verbose = get_verbose(argv[0], argv[3]);
2477
2478         memset(&data, 0, sizeof(data));
2479         data.ioc_dev = cur_device;
2480
2481         data.ioc_inllen1 = strlen(child) + 1;
2482         data.ioc_inlbuf1 = child;
2483
2484         memset(buf, 0, sizeof(rawbuf));
2485         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2486         if (rc) {
2487                 fprintf(stderr, "error: %s: invalid ioctl\n",
2488                         jt_cmdname(argv[0]));
2489                 return rc;
2490         }
2491
2492         fd = open(parent, O_RDONLY);
2493         if (fd < 0) {
2494                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
2495                         strerror(errno));
2496                 return -1;
2497         }
2498
2499         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
2500         if (rc < 0) {
2501                 fprintf(stderr, "error: %s: ioctl error: %s\n",
2502                         jt_cmdname(argv[0]), strerror(rc = errno));
2503         }
2504         close(fd);
2505
2506         if (verbose) {
2507                 rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
2508                 if (rc) {
2509                         fprintf(stderr, "error: %s: invalid reply\n",
2510                                 jt_cmdname(argv[0]));
2511                         return rc;
2512                 }
2513                 printf("%s: mode %o uid %d gid %d\n", child,
2514                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
2515                        data.ioc_obdo1.o_gid);
2516         }
2517
2518         return rc;
2519 }
2520
2521 int jt_cfg_dump_log(int argc, char **argv)
2522 {
2523         struct obd_ioctl_data data;
2524         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2525         int rc;
2526
2527         if (argc != 2)
2528                 return CMD_HELP;
2529
2530         memset(&data, 0, sizeof(data));
2531         data.ioc_dev = cur_device;
2532         data.ioc_inllen1 = strlen(argv[1]) + 1;
2533         data.ioc_inlbuf1 = argv[1];
2534
2535         memset(buf, 0, sizeof(rawbuf));
2536         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2537         if (rc) {
2538                 fprintf(stderr, "error: %s: invalid ioctl\n",
2539                         jt_cmdname(argv[0]));
2540                 return rc;
2541         }
2542         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
2543         if (rc < 0)
2544                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
2545                         strerror(errno));
2546
2547         return rc;
2548 }
2549
2550 int jt_llog_catlist(int argc, char **argv)
2551 {
2552         struct obd_ioctl_data data;
2553         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2554         int rc;
2555
2556         if (argc != 1)
2557                 return CMD_HELP;
2558
2559         memset(&data, 0, sizeof(data));
2560         data.ioc_dev = cur_device;
2561         data.ioc_inllen1 = sizeof(rawbuf) - cfs_size_round(sizeof(data));
2562         memset(buf, 0, sizeof(rawbuf));
2563         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2564         if (rc) {
2565                 fprintf(stderr, "error: %s: invalid ioctl\n",
2566                         jt_cmdname(argv[0]));
2567                 return rc;
2568         }
2569         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
2570         if (rc == 0)
2571                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2572         else
2573                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n",
2574                         strerror(errno));
2575
2576         return rc;
2577 }
2578
2579 int jt_llog_info(int argc, char **argv)
2580 {
2581         struct obd_ioctl_data data;
2582         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2583         int rc;
2584
2585         if (argc != 2)
2586                 return CMD_HELP;
2587
2588         memset(&data, 0, sizeof(data));
2589         data.ioc_dev = cur_device;
2590         data.ioc_inllen1 = strlen(argv[1]) + 1;
2591         data.ioc_inlbuf1 = argv[1];
2592         data.ioc_inllen2 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
2593                 cfs_size_round(data.ioc_inllen1);
2594         memset(buf, 0, sizeof(rawbuf));
2595         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2596         if (rc) {
2597                 fprintf(stderr, "error: %s: invalid ioctl\n",
2598                         jt_cmdname(argv[0]));
2599                 return rc;
2600         }
2601
2602         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
2603         if (rc == 0)
2604                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2605         else
2606                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
2607                         strerror(errno));
2608
2609         return rc;
2610 }
2611
2612 int jt_llog_print(int argc, char **argv)
2613 {
2614         struct obd_ioctl_data data;
2615         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2616         int rc;
2617
2618         if (argc != 2 && argc != 4)
2619                 return CMD_HELP;
2620
2621         memset(&data, 0, sizeof(data));
2622         data.ioc_dev = cur_device;
2623         data.ioc_inllen1 = strlen(argv[1]) + 1;
2624         data.ioc_inlbuf1 = argv[1];
2625         if (argc == 4) {
2626                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2627                 data.ioc_inlbuf2 = argv[2];
2628                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2629                 data.ioc_inlbuf3 = argv[3];
2630         } else {
2631                 char from[2] = "1", to[3] = "-1";
2632                 data.ioc_inllen2 = strlen(from) + 1;
2633                 data.ioc_inlbuf2 = from;
2634                 data.ioc_inllen3 = strlen(to) + 1;
2635                 data.ioc_inlbuf3 = to;
2636         }
2637         data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
2638                 cfs_size_round(data.ioc_inllen1) -
2639                 cfs_size_round(data.ioc_inllen2) -
2640                 cfs_size_round(data.ioc_inllen3);
2641         memset(buf, 0, sizeof(rawbuf));
2642         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2643         if (rc) {
2644                 fprintf(stderr, "error: %s: invalid ioctl\n",
2645                         jt_cmdname(argv[0]));
2646                 return rc;
2647         }
2648
2649         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
2650         if (rc == 0)
2651                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2652         else
2653                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
2654                         strerror(errno));
2655
2656         return rc;
2657 }
2658
2659 int jt_llog_cancel(int argc, char **argv)
2660 {
2661         struct obd_ioctl_data data;
2662         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2663         int rc;
2664
2665         if (argc != 4)
2666                 return CMD_HELP;
2667
2668         memset(&data, 0, sizeof(data));
2669         data.ioc_dev = cur_device;
2670         data.ioc_inllen1 = strlen(argv[1]) + 1;
2671         data.ioc_inlbuf1 = argv[1];
2672         data.ioc_inllen2 = strlen(argv[2]) + 1;
2673         data.ioc_inlbuf2 = argv[2];
2674         data.ioc_inllen3 = strlen(argv[3]) + 1;
2675         data.ioc_inlbuf3 = argv[3];
2676         memset(buf, 0, sizeof(rawbuf));
2677         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2678         if (rc) {
2679                 fprintf(stderr, "error: %s: invalid ioctl\n",
2680                         jt_cmdname(argv[0]));
2681                 return rc;
2682         }
2683
2684         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
2685         if (rc == 0)
2686                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
2687         else
2688                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
2689                         strerror(errno));
2690
2691         return rc;
2692
2693 }
2694 int jt_llog_check(int argc, char **argv)
2695 {
2696         struct obd_ioctl_data data;
2697         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2698         int rc;
2699
2700         if (argc != 2 && argc != 4)
2701                 return CMD_HELP;
2702
2703         memset(&data, 0, sizeof(data));
2704         data.ioc_dev = cur_device;
2705         data.ioc_inllen1 = strlen(argv[1]) + 1;
2706         data.ioc_inlbuf1 = argv[1];
2707         if (argc == 4) {
2708                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2709                 data.ioc_inlbuf2 = argv[2];
2710                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2711                 data.ioc_inlbuf3 = argv[3];
2712         } else {
2713                 char from[2] = "1", to[3] = "-1";
2714                 data.ioc_inllen2 = strlen(from) + 1;
2715                 data.ioc_inlbuf2 = from;
2716                 data.ioc_inllen3 = strlen(to) + 1;
2717                 data.ioc_inlbuf3 = to;
2718         }
2719         data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
2720                 cfs_size_round(data.ioc_inllen1) -
2721                 cfs_size_round(data.ioc_inllen2) -
2722                 cfs_size_round(data.ioc_inllen3);
2723         memset(buf, 0, sizeof(rawbuf));
2724         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2725         if (rc) {
2726                 fprintf(stderr, "error: %s: invalid ioctl\n",
2727                         jt_cmdname(argv[0]));
2728                 return rc;
2729         }
2730
2731         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
2732         if (rc == 0)
2733                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2734         else
2735                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
2736                         strerror(errno));
2737         return rc;
2738 }
2739
2740 int jt_llog_remove(int argc, char **argv)
2741 {
2742         struct obd_ioctl_data data;
2743         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2744         int rc;
2745
2746         if (argc != 3 && argc != 2)
2747                 return CMD_HELP;
2748
2749         memset(&data, 0, sizeof(data));
2750         data.ioc_dev = cur_device;
2751         data.ioc_inllen1 = strlen(argv[1]) + 1;
2752         data.ioc_inlbuf1 = argv[1];
2753         if (argc == 3){
2754                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2755                 data.ioc_inlbuf2 = argv[2];
2756         }
2757         memset(buf, 0, sizeof(rawbuf));
2758         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2759         if (rc) {
2760                 fprintf(stderr, "error: %s: invalid ioctl\n",
2761                         jt_cmdname(argv[0]));
2762                 return rc;
2763         }
2764
2765         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
2766         if (rc == 0) {
2767                 if (argc == 3)
2768                         fprintf(stdout, "log %s are removed.\n", argv[2]);
2769                 else
2770                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
2771         } else
2772                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
2773                         strerror(errno));
2774
2775         return rc;
2776 }
2777
2778 /* attach a regular file to virtual block device.
2779  * return vaule:
2780  *  -1: fatal error
2781  *  1: error, it always means the command run failed
2782  *  0: success
2783  */
2784 static int jt_blockdev_run_process(const char *file, char *argv[])
2785 {
2786         pid_t pid;
2787         int rc;
2788
2789         pid = vfork();
2790         if (pid == 0) { /* child process */
2791                 /* don't print error messages */
2792                 close(1), close(2);
2793                 (void)execvp(file, argv);
2794                 exit(-1);
2795         } else if (pid > 0) {
2796                 int status;
2797
2798                 rc = waitpid(pid, &status, 0);
2799                 if (rc < 0 || !WIFEXITED(status))
2800                         return -1;
2801
2802                 return WEXITSTATUS(status);
2803         }
2804
2805         return -1;
2806 }
2807
2808 static int jt_blockdev_find_module(const char *module)
2809 {
2810         FILE *fp;
2811         int found = 0;
2812         char buf[1024];
2813
2814         fp = fopen("/proc/modules", "r");
2815         if (fp == NULL)
2816                 return -1;
2817
2818         while (fgets(buf, 1024, fp) != NULL) {
2819                 *strchr(buf, ' ') = 0;
2820                 if (strcmp(module, buf) == 0) {
2821                         found = 1;
2822                         break;
2823                 }
2824         }
2825         fclose(fp);
2826
2827         return found;
2828 }
2829
2830 static int jt_blockdev_probe_module(const char *module)
2831 {
2832         char buf[1024];
2833         char *argv[10];
2834         int c, rc;
2835
2836         if (jt_blockdev_find_module(module) == 1)
2837                 return 0;
2838
2839         /* run modprobe first */
2840         c = 0;
2841         argv[c++] = "/sbin/modprobe";
2842         argv[c++] = "-q";
2843         argv[c++] = (char *)module;
2844         argv[c++] = NULL;
2845         rc = jt_blockdev_run_process("modprobe", argv);
2846         if (rc != 1)
2847                 return rc;
2848
2849         /* cannot find the module in default directory ... */
2850         sprintf(buf, "../llite/%s.ko", module);
2851         c = 0;
2852         argv[c++] = "/sbin/insmod";
2853         argv[c++] = buf;
2854         argv[c++] = NULL;
2855         rc = jt_blockdev_run_process("insmod", argv);
2856         return rc ? -1 : 0;
2857 }
2858
2859 int jt_blockdev_attach(int argc, char **argv)
2860 {
2861         int rc, fd;
2862         struct stat st;
2863         char *filename, *devname;
2864         unsigned long dev;
2865
2866         if (argc != 3)
2867                 return CMD_HELP;
2868
2869         if (jt_blockdev_probe_module("llite_lloop") < 0) {
2870                 fprintf(stderr, "error: cannot find module llite_lloop.(k)o\n");
2871                 return ENOENT;
2872         }
2873
2874         filename = argv[1];
2875         devname = argv[2];
2876
2877         fd = open(filename, O_RDWR);
2878         if (fd < 0) {
2879                 fprintf(stderr, "file %s can't be opened(%s)\n\n",
2880                         filename, strerror(errno));
2881                 return CMD_HELP;
2882         }
2883
2884         rc = ioctl(fd, LL_IOC_LLOOP_ATTACH, &dev);
2885         if (rc < 0) {
2886                 rc = errno;
2887                 fprintf(stderr, "attach error(%s)\n", strerror(rc));
2888                 goto out;
2889         }
2890
2891         rc = stat(devname, &st);
2892         if (rc == 0 && (!S_ISBLK(st.st_mode) || st.st_rdev != dev)) {
2893                 rc = EEXIST;
2894         } else if (rc < 0) {
2895                 if (errno == ENOENT &&
2896                     !mknod(devname, S_IFBLK|S_IRUSR|S_IWUSR, dev))
2897                         rc = 0;
2898                 else
2899                         rc = errno;
2900         }
2901
2902         if (rc) {
2903                 fprintf(stderr, "error: the file %s could be attached to block "
2904                                 "device %X but creating %s failed: %s\n"
2905                                 "now detaching the block device..",
2906                         filename, (int)dev, devname, strerror(rc));
2907
2908                 (void)ioctl(fd, LL_IOC_LLOOP_DETACH_BYDEV, dev);
2909                 fprintf(stderr, "%s\n", strerror(errno));
2910         }
2911 out:
2912         close(fd);
2913         return -rc;
2914 }
2915
2916 int jt_blockdev_detach(int argc, char **argv)
2917 {
2918         char *filename;
2919         int rc, fd;
2920
2921         if (argc != 2)
2922                 return CMD_HELP;
2923
2924         filename = argv[1];
2925         fd = open(filename, O_RDONLY);
2926         if (fd < 0) {
2927                 fprintf(stderr, "cannot open file %s error %s\n",
2928                         filename, strerror(errno));
2929                 return CMD_HELP;
2930         }
2931
2932         rc = ioctl(fd, LL_IOC_LLOOP_DETACH, 0);
2933         if (rc < 0) {
2934                 rc = errno;
2935                 fprintf(stderr, "detach error(%s)\n", strerror(rc));
2936         } else {
2937                 (void)unlink(filename);
2938         }
2939
2940         close(fd);
2941         return -rc;
2942 }
2943
2944 int jt_blockdev_info(int argc, char **argv)
2945 {
2946         char *filename;
2947         int rc, fd;
2948         struct lu_fid fid;
2949
2950         if (argc != 2)
2951                 return CMD_HELP;
2952
2953         filename = argv[1];
2954         fd = open(filename, O_RDONLY);
2955         if (fd < 0) {
2956                 fprintf(stderr, "cannot open file %s error: %s\n",
2957                         filename, strerror(errno));
2958                 return CMD_HELP;
2959         }
2960
2961         rc = ioctl(fd, LL_IOC_LLOOP_INFO, &fid);
2962         if (rc < 0) {
2963                 rc = errno;
2964                 fprintf(stderr, "error: %s\n", strerror(errno));
2965                 goto out;
2966         }
2967         fprintf(stdout, "lloop device info: ");
2968         if (fid_is_zero(&fid))
2969                 fprintf(stdout, "Not attached\n");
2970         else
2971                 fprintf(stdout, "attached to inode "DFID"\n", PFID(&fid));
2972 out:
2973         close(fd);
2974         return -rc;
2975 }
2976
2977 static void signal_server(int sig)
2978 {
2979         if (sig == SIGINT) {
2980                 do_disconnect("sigint", 1);
2981                 exit(1);
2982         } else
2983                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2984 }
2985
2986 int obd_initialize(int argc, char **argv)
2987 {
2988         int i;
2989
2990         for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++)
2991                 lsm_buffer.lsm.lsm_oinfo[i] = lov_oinfos + i;
2992
2993         if (shmem_setup() != 0)
2994                 return -1;
2995
2996         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH,
2997                          OBD_DEV_MAJOR, OBD_DEV_MINOR);
2998
2999         return 0;
3000 }
3001
3002 void obd_finalize(int argc, char **argv)
3003 {
3004         struct sigaction sigact;
3005
3006         sigact.sa_handler = signal_server;
3007         sigfillset(&sigact.sa_mask);
3008         sigact.sa_flags = SA_RESTART;
3009         sigaction(SIGINT, &sigact, NULL);
3010
3011         shmem_cleanup();
3012         do_disconnect(argv[0], 1);
3013 }
3014
3015 static int check_pool_cmd(enum lcfg_command_type cmd,
3016                           char *fsname, char *poolname,
3017                           char *ostname)
3018 {
3019         int rc;
3020
3021         rc = llapi_search_ost(fsname, poolname, ostname);
3022         if (rc < 0 && (cmd != LCFG_POOL_NEW)) {
3023                 fprintf(stderr, "Pool %s.%s not found\n",
3024                         fsname, poolname);
3025                 return rc;
3026         }
3027
3028         switch (cmd) {
3029         case LCFG_POOL_NEW: {
3030                 LASSERT(ostname == NULL);
3031                 if (rc >= 0) {
3032                         fprintf(stderr, "Pool %s.%s already exists\n",
3033                                 fsname, poolname);
3034                         return -EEXIST;
3035                 }
3036                 return 0;
3037         }
3038         case LCFG_POOL_DEL: {
3039                 LASSERT(ostname == NULL);
3040                 if (rc == 1) {
3041                         fprintf(stderr, "Pool %s.%s not empty, "
3042                                 "please remove all members\n",
3043                                 fsname, poolname);
3044                         return -ENOTEMPTY;
3045                 }
3046                 return 0;
3047         }
3048         case LCFG_POOL_ADD: {
3049                 if (rc == 1) {
3050                         fprintf(stderr, "OST %s is already in pool %s.%s\n",
3051                                 ostname, fsname, poolname);
3052                         return -EEXIST;
3053                 }
3054                 rc = llapi_search_ost(fsname, NULL, ostname);
3055                 if (rc == 0) {
3056                         fprintf(stderr, "OST %s is not part of the '%s' fs.\n",
3057                                 ostname, fsname);
3058                         return -ENOENT;
3059                 }
3060                 return 0;
3061         }
3062         case LCFG_POOL_REM: {
3063                 if (rc == 0) {
3064                         fprintf(stderr, "OST %s not found in pool %s.%s\n",
3065                                 ostname, fsname, poolname);
3066                         return -ENOENT;
3067                 }
3068                 return 0;
3069         }
3070         default:
3071                 break;
3072         } /* switch */
3073         return -EINVAL;
3074 }
3075
3076 /* This check only verifies that the changes have been "pushed out" to
3077    the client successfully.  This involves waiting for a config update,
3078    and so may fail because of problems in that code or post-command
3079    network loss. So reporting a warning is appropriate, but not a failure.
3080 */
3081 static int check_pool_cmd_result(enum lcfg_command_type cmd,
3082                                  char *fsname, char *poolname,
3083                                  char *ostname)
3084 {
3085         int cpt = 10;
3086         int rc = 0;
3087
3088         switch (cmd) {
3089         case LCFG_POOL_NEW: {
3090                 do {
3091                         rc = llapi_search_ost(fsname, poolname, NULL);
3092                         if (rc == -ENODEV)
3093                                 return rc;
3094                         if (rc < 0)
3095                                 sleep(2);
3096                         cpt--;
3097                 } while ((rc < 0) && (cpt > 0));
3098                 if (rc >= 0) {
3099                         fprintf(stderr, "Pool %s.%s created\n",
3100                                 fsname, poolname);
3101                         return 0;
3102                 } else {
3103                         fprintf(stderr, "Warning, pool %s.%s not found\n",
3104                                 fsname, poolname);
3105                         return -ENOENT;
3106                 }
3107         }
3108         case LCFG_POOL_DEL: {
3109                 do {
3110                         rc = llapi_search_ost(fsname, poolname, NULL);
3111                         if (rc == -ENODEV)
3112                                 return rc;
3113                         if (rc >= 0)
3114                                 sleep(2);
3115                         cpt--;
3116                 } while ((rc >= 0) && (cpt > 0));
3117                 if (rc < 0) {
3118                         fprintf(stderr, "Pool %s.%s destroyed\n",
3119                                 fsname, poolname);
3120                         return 0;
3121                 } else {
3122                         fprintf(stderr, "Warning, pool %s.%s still found\n",
3123                                 fsname, poolname);
3124                         return -EEXIST;
3125                 }
3126         }
3127         case LCFG_POOL_ADD: {
3128                 do {
3129                         rc = llapi_search_ost(fsname, poolname, ostname);
3130                         if (rc == -ENODEV)
3131                                 return rc;
3132                         if (rc != 1)
3133                                 sleep(2);
3134                         cpt--;
3135                 } while ((rc != 1) && (cpt > 0));
3136                 if (rc == 1) {
3137                         fprintf(stderr, "OST %s added to pool %s.%s\n",
3138                                 ostname, fsname, poolname);
3139                         return 0;
3140                 } else {
3141                         fprintf(stderr, "Warning, OST %s not found in pool %s.%s\n",
3142                                 ostname, fsname, poolname);
3143                         return -ENOENT;
3144                 }
3145         }
3146         case LCFG_POOL_REM: {
3147                 do {
3148                         rc = llapi_search_ost(fsname, poolname, ostname);
3149                         if (rc == -ENODEV)
3150                                 return rc;
3151                         if (rc == 1)
3152                                 sleep(2);
3153                         cpt--;
3154                 } while ((rc == 1) && (cpt > 0));
3155                 if (rc != 1) {
3156                         fprintf(stderr, "OST %s removed from pool %s.%s\n",
3157                                 ostname, fsname, poolname);
3158                         return 0;
3159                 } else {
3160                         fprintf(stderr, "Warning, OST %s still found in pool %s.%s\n",
3161                                 ostname, fsname, poolname);
3162                         return -EEXIST;
3163                 }
3164         }
3165         default:
3166                 break;
3167         }
3168         return -EINVAL;
3169 }
3170
3171 static int check_and_complete_ostname(char *fsname, char *ostname)
3172 {
3173         char *ptr;
3174         char real_ostname[MAX_OBD_NAME + 1];
3175         char i;
3176
3177         /* if OST name does not start with fsname, we add it */
3178         /* if not check if the fsname is the right one */
3179         ptr = strchr(ostname, '-');
3180         if (ptr == NULL) {
3181                 sprintf(real_ostname, "%s-%s", fsname, ostname);
3182         } else if (strncmp(ostname, fsname, strlen(fsname)) != 0) {
3183                 fprintf(stderr, "%s does not start with fsname %s\n",
3184                         ostname, fsname);
3185                 return -EINVAL;
3186         } else {
3187              strcpy(real_ostname, ostname);
3188         }
3189         /* real_ostname is fsname-????? */
3190         ptr = real_ostname + strlen(fsname) + 1;
3191         if (strncmp(ptr, "OST", 3) != 0) {
3192                 fprintf(stderr, "%s does not start by %s-OST nor OST\n",
3193                         ostname, fsname);
3194                 return -EINVAL;
3195         }
3196         /* real_ostname is fsname-OST????? */
3197         ptr += 3;
3198         for (i = 0; i < 4; i++) {
3199                 if (!isxdigit(*ptr)) {
3200                         fprintf(stderr,
3201                                 "ost's index in %s is not an hexa number\n",
3202                                 ostname);
3203                         return -EINVAL;
3204                 }
3205                 ptr++;
3206         }
3207         /* real_ostname is fsname-OSTXXXX????? */
3208         /* if OST name does not end with _UUID, we add it */
3209         if (*ptr == '\0') {
3210                 strcat(real_ostname, "_UUID");
3211         } else if (strcmp(ptr, "_UUID") != 0) {
3212                 fprintf(stderr,
3213                         "ostname %s does not end with _UUID\n", ostname);
3214                 return -EINVAL;
3215         }
3216         /* real_ostname is fsname-OSTXXXX_UUID */
3217         strcpy(ostname, real_ostname);
3218         return 0;
3219 }
3220
3221 /* returns 0 or -errno */
3222 static int pool_cmd(enum lcfg_command_type cmd,
3223                     char *cmdname, char *fullpoolname,
3224                     char *fsname, char *poolname, char *ostname)
3225 {
3226         int rc = 0;
3227         struct obd_ioctl_data data;
3228         struct lustre_cfg_bufs bufs;
3229         struct lustre_cfg *lcfg;
3230         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
3231
3232         rc = check_pool_cmd(cmd, fsname, poolname, ostname);
3233         if (rc == -ENODEV)
3234                 fprintf(stderr, "Can't verify pool command since there "
3235                         "is no local MDT or client, proceeding anyhow...\n");
3236         else if (rc)
3237                 return rc;
3238
3239         lustre_cfg_bufs_reset(&bufs, NULL);
3240         lustre_cfg_bufs_set_string(&bufs, 0, cmdname);
3241         lustre_cfg_bufs_set_string(&bufs, 1, fullpoolname);
3242         if (ostname != NULL)
3243                 lustre_cfg_bufs_set_string(&bufs, 2, ostname);
3244
3245         lcfg = lustre_cfg_new(cmd, &bufs);
3246         if (IS_ERR(lcfg)) {
3247                 rc = PTR_ERR(lcfg);
3248                 return rc;
3249         }
3250
3251         memset(&data, 0, sizeof(data));
3252         rc = data.ioc_dev = get_mgs_device();
3253         if (rc < 0)
3254                 goto out;
3255
3256         data.ioc_type = LUSTRE_CFG_TYPE;
3257         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
3258                                         lcfg->lcfg_buflens);
3259         data.ioc_pbuf1 = (void *)lcfg;
3260
3261         memset(buf, 0, sizeof(rawbuf));
3262         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
3263         if (rc) {
3264                 fprintf(stderr, "error: %s: invalid ioctl\n",
3265                         jt_cmdname(cmdname));
3266                 return rc;
3267         }
3268         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_POOL, buf);
3269 out:
3270         if (rc)
3271                 rc = -errno;
3272         lustre_cfg_free(lcfg);
3273         return rc;
3274 }
3275
3276 /*
3277  * this function tranforms a rule [start-end/step] into an array
3278  * of matching numbers
3279  * supported forms are:
3280  * [start]                : just this number
3281  * [start-end]            : all numbers from start to end
3282  * [start-end/step]       : numbers from start to end with increment of step
3283  * on return, format contains a printf format string which can be used
3284  * to generate all the strings
3285  */
3286 static int get_array_idx(char *rule, char *format, int **array)
3287 {
3288         char *start, *end, *ptr;
3289         unsigned int lo, hi, step;
3290         int array_sz = 0;
3291         int i, array_idx;
3292         int rc;
3293
3294         start = strchr(rule, '[');
3295         end = strchr(rule, ']');
3296         if ((start == NULL) || (end == NULL)) {
3297                 *array = malloc(sizeof(int));
3298                 if (*array == NULL)
3299                         return 0;
3300                 strcpy(format, rule);
3301                 array_sz = 1;
3302                 return array_sz;
3303         }
3304         *start = '\0';
3305         *end = '\0';
3306         end++;
3307         start++;
3308         /* put in format the printf format (the rule without the range) */
3309         sprintf(format, "%s%%.4x%s", rule, end);
3310
3311         array_idx = 0;
3312         array_sz = 0;
3313         *array = NULL;
3314         /* loop on , separator */
3315         do {
3316                 /* extract the 3 fields */
3317                 rc = sscanf(start, "%x-%x/%u", &lo, &hi, &step);
3318                 switch (rc) {
3319                 case 0: {
3320                         return 0;
3321                 }
3322                 case 1: {
3323                         array_sz++;
3324                         *array = realloc(*array, array_sz * sizeof(int));
3325                         if (*array == NULL)
3326                                 return 0;
3327                         (*array)[array_idx] = lo;
3328                         array_idx++;
3329                         break;
3330                 }
3331                 case 2: {
3332                         step = 1;
3333                         /* do not break to share code with case 3: */
3334                 }
3335                 case 3: {
3336                         if ((hi < lo) || (step == 0))
3337                                 return 0;
3338                         array_sz += (hi - lo) / step + 1;
3339                         *array = realloc(*array, sizeof(int) * array_sz);
3340                         if (*array == NULL)
3341                                 return 0;
3342                         for (i = lo; i <= hi; i+=step, array_idx++)
3343                                 (*array)[array_idx] = i;
3344                         break;
3345                 }
3346                 }
3347                 ptr = strchr(start, ',');
3348                 if (ptr != NULL)
3349                         start = ptr + 1;
3350
3351         } while (ptr != NULL);
3352         return array_sz;
3353 }
3354
3355 static int extract_fsname_poolname(char *arg, char *fsname, char *poolname)
3356 {
3357         char *ptr;
3358         int len;
3359         int rc;
3360
3361         strcpy(fsname, arg);
3362         ptr = strchr(fsname, '.');
3363         if (ptr == NULL) {
3364                 fprintf(stderr, ". is missing in %s\n", fsname);
3365                 rc = -EINVAL;
3366                 goto err;
3367         }
3368
3369         len = ptr - fsname;
3370         if (len == 0) {
3371                 fprintf(stderr, "fsname is empty\n");
3372                 rc = -EINVAL;
3373                 goto err;
3374         }
3375
3376         len = strlen(ptr + 1);
3377         if (len == 0) {
3378                 fprintf(stderr, "poolname is empty\n");
3379                 rc = -EINVAL;
3380                 goto err;
3381         }
3382         if (len > LOV_MAXPOOLNAME) {
3383                 fprintf(stderr,
3384                         "poolname %s is too long (length is %d max is %d)\n",
3385                         ptr + 1, len, LOV_MAXPOOLNAME);
3386                 rc = -ENAMETOOLONG;
3387                 goto err;
3388         }
3389         strncpy(poolname, ptr + 1, LOV_MAXPOOLNAME);
3390         poolname[LOV_MAXPOOLNAME] = '\0';
3391         *ptr = '\0';
3392         return 0;
3393
3394 err:
3395         fprintf(stderr, "argument %s must be <fsname>.<poolname>\n", arg);
3396         return rc;
3397 }
3398
3399 int jt_pool_cmd(int argc, char **argv)
3400 {
3401         enum lcfg_command_type cmd;
3402         char fsname[PATH_MAX + 1];
3403         char poolname[LOV_MAXPOOLNAME + 1];
3404         char *ostnames_buf = NULL;
3405         int i, rc;
3406         int *array = NULL, array_sz;
3407         struct {
3408                 int     rc;
3409                 char   *ostname;
3410         } *cmds = NULL;
3411
3412         switch (argc) {
3413         case 0:
3414         case 1: return CMD_HELP;
3415         case 2: {
3416                 if (strcmp("pool_new", argv[0]) == 0)
3417                         cmd = LCFG_POOL_NEW;
3418                 else if (strcmp("pool_destroy", argv[0]) == 0)
3419                         cmd = LCFG_POOL_DEL;
3420                 else if (strcmp("pool_list", argv[0]) == 0)
3421                          return llapi_poollist(argv[1]);
3422                 else return CMD_HELP;
3423
3424                 rc = extract_fsname_poolname(argv[1], fsname, poolname);
3425                 if (rc)
3426                         break;
3427
3428                 rc = pool_cmd(cmd, argv[0], argv[1], fsname, poolname, NULL);
3429                 if (rc)
3430                         break;
3431
3432                 check_pool_cmd_result(cmd, fsname, poolname, NULL);
3433                 break;
3434         }
3435         default: {
3436                 char format[2*MAX_OBD_NAME];
3437
3438                 if (strcmp("pool_remove", argv[0]) == 0) {
3439                         cmd = LCFG_POOL_REM;
3440                 } else if (strcmp("pool_add", argv[0]) == 0) {
3441                         cmd = LCFG_POOL_ADD;
3442                 } else {
3443                         return CMD_HELP;
3444                 }
3445
3446                 rc = extract_fsname_poolname(argv[1], fsname, poolname);
3447                 if (rc)
3448                         break;
3449
3450                 for (i = 2; i < argc; i++) {
3451                         int j;
3452
3453                         array_sz = get_array_idx(argv[i], format, &array);
3454                         if (array_sz == 0)
3455                                 return CMD_HELP;
3456
3457                         cmds = malloc(array_sz * sizeof(cmds[0]));
3458                         if (cmds != NULL) {
3459                                 ostnames_buf = malloc(array_sz *
3460                                                       (MAX_OBD_NAME + 1));
3461                         } else {
3462                                 free(array);
3463                                 rc = -ENOMEM;
3464                                 goto out;
3465                         }
3466
3467                         for (j = 0; j < array_sz; j++) {
3468                                 char ostname[MAX_OBD_NAME + 1];
3469
3470                                 snprintf(ostname, MAX_OBD_NAME, format,
3471                                          array[j]);
3472                                 ostname[MAX_OBD_NAME] = '\0';
3473
3474                                 rc = check_and_complete_ostname(fsname,ostname);
3475                                 if (rc) {
3476                                         free(array);
3477                                         free(cmds);
3478                                         if (ostnames_buf)
3479                                                 free(ostnames_buf);
3480                                         goto out;
3481                                 }
3482                                 if (ostnames_buf != NULL) {
3483                                         cmds[j].ostname =
3484                                           &ostnames_buf[(MAX_OBD_NAME + 1) * j];
3485                                         strcpy(cmds[j].ostname, ostname);
3486                                 } else {
3487                                         cmds[j].ostname = NULL;
3488                                 }
3489                                 cmds[j].rc = pool_cmd(cmd, argv[0], argv[1],
3490                                                       fsname, poolname,
3491                                                       ostname);
3492                                 /* Return an err if any of the add/dels fail */
3493                                 if (!rc)
3494                                         rc = cmds[j].rc;
3495                         }
3496                         for (j = 0; j < array_sz; j++) {
3497                                 if (!cmds[j].rc) {
3498                                         char ostname[MAX_OBD_NAME + 1];
3499
3500                                         if (!cmds[j].ostname) {
3501                                                 snprintf(ostname, MAX_OBD_NAME,
3502                                                          format, array[j]);
3503                                                 ostname[MAX_OBD_NAME] = '\0';
3504                                                 check_and_complete_ostname(
3505                                                         fsname, ostname);
3506                                         } else {
3507                                                 strcpy(ostname,
3508                                                        cmds[j].ostname);
3509                                         }
3510                                         check_pool_cmd_result(cmd, fsname,
3511                                                               poolname,ostname);
3512                                 }
3513                         }
3514                         if (array_sz > 0)
3515                                 free(array);
3516                         if (cmds)
3517                                 free(cmds);
3518                         if (ostnames_buf);
3519                                 free(ostnames_buf);
3520                 }
3521                 /* fall through */
3522         }
3523         } /* switch */
3524
3525 out:
3526         if (rc != 0) {
3527                 errno = -rc;
3528                 perror(argv[0]);
3529         }
3530
3531         return rc;
3532 }
3533
3534 int jt_get_obj_version(int argc, char **argv)
3535 {
3536         struct lu_fid fid;
3537         struct obd_ioctl_data data;
3538         __u64 version;
3539         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf, *fidstr;
3540         int rc;
3541
3542         if (argc != 2)
3543                 return CMD_HELP;
3544
3545         fidstr = argv[1];
3546         while (*fidstr == '[')
3547                 fidstr++;
3548         sscanf(fidstr, SFID, RFID(&fid));
3549         if (!fid_is_sane(&fid)) {
3550                 fprintf(stderr, "bad FID format [%s], should be "DFID"\n",
3551                         fidstr, (__u64)1, 2, 0);
3552                 return -EINVAL;
3553         }
3554
3555         memset(&data, 0, sizeof data);
3556         data.ioc_dev = cur_device;
3557         data.ioc_inlbuf1 = (char *) &fid;
3558         data.ioc_inllen1 = sizeof fid;
3559         data.ioc_inlbuf2 = (char *) &version;
3560         data.ioc_inllen2 = sizeof version;
3561
3562         memset(buf, 0, sizeof *buf);
3563         rc = obd_ioctl_pack(&data, &buf, sizeof rawbuf);
3564         if (rc) {
3565                 fprintf(stderr, "error: %s: packing ioctl arguments: %s\n",
3566                         jt_cmdname(argv[0]), strerror(-rc));
3567                 return rc;
3568         }
3569
3570         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GET_OBJ_VERSION, buf);
3571         if (rc == -1) {
3572                 fprintf(stderr, "error: %s: ioctl: %s\n",
3573                         jt_cmdname(argv[0]), strerror(errno));
3574                 return -errno;
3575         }
3576
3577         obd_ioctl_unpack(&data, buf, sizeof rawbuf);
3578         printf(LPX64"\n", version);
3579         return 0;
3580 }
3581
3582 void  llapi_ping_target(char *obd_type, char *obd_name,
3583                         char *obd_uuid, void *args)
3584 {
3585         int  rc;
3586         struct obd_ioctl_data data;
3587         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
3588
3589         memset(&data, 0, sizeof(data));
3590         data.ioc_inlbuf4 = obd_name;
3591         data.ioc_inllen4 = strlen(obd_name) + 1;
3592         data.ioc_dev = OBD_DEV_BY_DEVNAME;
3593         memset(buf, 0, sizeof(rawbuf));
3594         if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) {
3595                 fprintf(stderr, "error: invalid ioctl\n");
3596                 return;
3597         }
3598         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PING_TARGET, buf);
3599         if (rc)
3600                 rc = errno;
3601         if (rc == ENOTCONN || rc == ESHUTDOWN) {
3602                 printf("%s: INACTIVE\n", obd_name);
3603         } else if (rc) {
3604                 printf("%s: check error: %s\n",
3605                         obd_name, strerror(errno));
3606         } else {
3607                 printf("%s: active\n", obd_name);
3608         }
3609 }
3610
3611 int jt_changelog_register(int argc, char **argv)
3612 {
3613         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
3614         struct obd_ioctl_data data;
3615         char devname[30];
3616         int rc;
3617
3618         if (argc > 2)
3619                 return CMD_HELP;
3620         else if (argc == 2 && strcmp(argv[1], "-n") != 0)
3621                 return CMD_HELP;
3622         if (cur_device < 0)
3623                 return CMD_HELP;
3624
3625         memset(&data, 0, sizeof(data));
3626         data.ioc_dev = cur_device;
3627         memset(buf, 0, sizeof(rawbuf));
3628         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
3629         if (rc) {
3630                 fprintf(stderr, "error: %s: invalid ioctl\n",
3631                         jt_cmdname(argv[0]));
3632                return rc;
3633         }
3634
3635         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CHANGELOG_REG, buf);
3636         if (rc < 0) {
3637                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
3638                         strerror(rc = errno));
3639                 return rc;
3640         }
3641         obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
3642
3643         if (data.ioc_u32_1 == 0) {
3644                 fprintf(stderr, "received invalid userid!\n");
3645                 return EPROTO;
3646         }
3647
3648         if (lcfg_get_devname() != NULL)
3649                 strcpy(devname, lcfg_get_devname());
3650         else
3651                 sprintf(devname, "dev %d", cur_device);
3652
3653         if (argc == 2)
3654                 /* -n means bare name */
3655                 printf(CHANGELOG_USER_PREFIX"%u\n", data.ioc_u32_1);
3656         else
3657                 printf("%s: Registered changelog userid '"CHANGELOG_USER_PREFIX
3658                        "%u'\n", devname, data.ioc_u32_1);
3659         return 0;
3660 }
3661
3662 int jt_changelog_deregister(int argc, char **argv)
3663 {
3664         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
3665         struct obd_ioctl_data data;
3666         char devname[30];
3667         int id, rc;
3668
3669         if (argc != 2 || cur_device < 0)
3670                 return CMD_HELP;
3671
3672         id = strtol(argv[1] + strlen(CHANGELOG_USER_PREFIX), NULL, 10);
3673         if ((id == 0) || (strncmp(argv[1], CHANGELOG_USER_PREFIX,
3674                                   strlen(CHANGELOG_USER_PREFIX)) != 0)) {
3675                 fprintf(stderr, "expecting id of the form '"
3676                         CHANGELOG_USER_PREFIX"<num>'; got '%s'\n", argv[1]);
3677                 return CMD_HELP;
3678         }
3679
3680         memset(&data, 0, sizeof(data));
3681         data.ioc_dev = cur_device;
3682         data.ioc_u32_1 = id;
3683         memset(buf, 0, sizeof(rawbuf));
3684         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
3685         if (rc) {
3686                 fprintf(stderr, "error: %s: invalid ioctl\n",
3687                         jt_cmdname(argv[0]));
3688                 return rc;
3689         }
3690
3691         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CHANGELOG_DEREG, buf);
3692         if (rc < 0) {
3693                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
3694                         strerror(rc = errno));
3695                 return rc;
3696         }
3697         obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
3698
3699         if (data.ioc_u32_1 != id) {
3700                 fprintf(stderr, "No changelog user '%s'.  Blocking user"
3701                         " is '"CHANGELOG_USER_PREFIX"%d'.\n", argv[1],
3702                         data.ioc_u32_1);
3703                 return ENOENT;
3704         }
3705
3706         if (lcfg_get_devname() != NULL)
3707                 strcpy(devname, lcfg_get_devname());
3708         else
3709                 sprintf(devname, "dev %d", cur_device);
3710
3711         printf("%s: Deregistered changelog user '"CHANGELOG_USER_PREFIX"%d'\n",
3712                devname, data.ioc_u32_1);
3713         return 0;
3714 }
3715
3716