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