Whamcloud - gitweb
mgs_llog_read_header
[fs/lustre-release.git] / lustre / utils / obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Andreas Dilger <adilger@clusterfs.com>
8  *   Author: Robert Read <rread@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28 #include <stdlib.h>
29 #include <sys/ioctl.h>
30 #include <fcntl.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/stat.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <signal.h>
38
39 #include "obdctl.h"
40
41 #include <linux/obd.h>          /* for struct lov_stripe_md */
42 #include <linux/lustre_build_version.h>
43
44 #include <unistd.h>
45 #include <sys/un.h>
46 #include <time.h>
47 #include <sys/time.h>
48 #include <errno.h>
49 #include <string.h>
50
51 #ifdef HAVE_ASM_PAGE_H
52 #include <asm/page.h>           /* needed for PAGE_SIZE - rread */
53 #endif
54
55 #include <linux/obd_class.h>
56 #include <lnet/lnetctl.h>
57 #include "parser.h"
58 #include <stdio.h>
59
60 #define MAX_STRING_SIZE 128
61 #define DEVICES_LIST "/proc/fs/lustre/devices"
62
63 #if HAVE_LIBPTHREAD
64 #include <sys/ipc.h>
65 #include <sys/shm.h>
66 #include <pthread.h>
67
68 #define MAX_THREADS 1024
69
70 struct shared_data {
71         __u64 counters[MAX_THREADS];
72         __u64 offsets[MAX_THREADS];
73         int   running;
74         int   barrier;
75         pthread_mutex_t mutex;
76         pthread_cond_t  cond;
77 };
78
79 static struct shared_data *shared_data;
80 static __u64 counter_snapshot[2][MAX_THREADS];
81 static int prev_valid;
82 static struct timeval prev_time;
83 static int thread;
84 static int nthreads;
85 #else
86 const int thread = 0;
87 const int nthreads = 1;
88 #endif
89
90 static int jt_recording;
91 static char rawbuf[8192];
92 static char *buf = rawbuf;
93 static int max = sizeof(rawbuf);
94
95 static int cur_device = MAX_OBD_DEVICES;
96
97 union lsm_buffer {
98         char                 space [4096];
99         struct lov_stripe_md lsm;
100 } lsm_buffer;
101
102 static int l2_ioctl(int dev_id, int opc, void *buf)
103 {
104         return l_ioctl(dev_id, opc, buf);
105 }
106
107 #define IOC_INIT(data)                                                  \
108 do {                                                                    \
109         memset(&data, 0, sizeof(data));                                 \
110         data.ioc_dev = cur_device;                                      \
111 } while (0)
112
113 #define IOC_PACK(func, data)                                            \
114 do {                                                                    \
115         memset(buf, 0, sizeof(rawbuf));                                 \
116         if (obd_ioctl_pack(&data, &buf, max)) {                         \
117                 fprintf(stderr, "error: %s: invalid ioctl\n",           \
118                         jt_cmdname(func));                                 \
119                 return -2;                                              \
120         }                                                               \
121 } while (0)
122
123 #define IOC_UNPACK(func, data)                                          \
124 do {                                                                    \
125         if (obd_ioctl_unpack(&data, buf, max)) {                        \
126                 fprintf(stderr, "error: %s: invalid reply\n",           \
127                         jt_cmdname(func));                                 \
128                 return -2;                                              \
129         }                                                               \
130 } while (0)
131
132 int obd_record(enum cfg_record_type type, int len, void *ptr)
133 {
134         struct obd_ioctl_data data;
135
136         IOC_INIT(data);
137         data.ioc_type = type;
138         data.ioc_plen1 = len;
139         data.ioc_pbuf1 = ptr;
140         IOC_PACK("obd_record", data);
141
142         return  l_ioctl(OBD_DEV_ID, OBD_IOC_DORECORD, &data);
143 }
144
145 int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg)
146 {
147         int opc;
148         struct obd_ioctl_data data;
149         int rc;
150
151         IOC_INIT(data);
152         data.ioc_type = LUSTRE_CFG_TYPE;
153         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
154                                         lcfg->lcfg_buflens);
155         data.ioc_pbuf1 = (void *)lcfg;
156         IOC_PACK(func, data);
157
158         if (jt_recording) {
159                 opc = OBD_IOC_DORECORD;
160         } else {
161                 opc = OBD_IOC_PROCESS_CFG;
162         }
163         rc =  l_ioctl(dev_id, opc, buf);
164
165         return rc;
166 }
167
168 char *obdo_print(struct obdo *obd)
169 {
170         char buf[1024];
171
172         sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
173                 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
174                 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
175                 "misc: %x\nnlink: %d,\nvalid "LPX64"\n",
176                 obd->o_id, obd->o_gr, obd->o_atime, obd->o_mtime, obd->o_ctime,
177                 obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
178                 obd->o_uid, obd->o_gid, obd->o_flags, obd->o_misc,
179                 obd->o_nlink, obd->o_valid);
180         return strdup(buf);
181 }
182
183
184 #define BAD_VERBOSE (-999999999)
185
186 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
187
188 static int do_name2dev(char *func, char *name)
189 {
190         struct obd_ioctl_data data;
191         int rc;
192
193         IOC_INIT(data);
194
195         data.ioc_inllen1 = strlen(name) + 1;
196         data.ioc_inlbuf1 = name;
197
198         IOC_PACK(func, data);
199         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
200         if (rc < 0)
201                 return errno;
202         IOC_UNPACK(func, data);
203
204         return data.ioc_dev + N2D_OFF;
205 }
206
207 /*
208  * resolve a device name to a device number.
209  * supports a number, $name or %uuid.
210  */
211 int parse_devname(char *func, char *name)
212 {
213         int rc;
214         int ret = -1;
215
216         if (!name)
217                 return ret;
218         if (name[0] == '$' || name[0] == '%') {
219                 name++;
220                 rc = do_name2dev(func, name);
221                 if (rc >= N2D_OFF) {
222                         ret = rc - N2D_OFF;
223                         printf("Name %s is device %d\n", name, ret);
224                 } else {
225                         printf("No device found for name %s: %s\n",
226                                name, strerror(rc));
227                 }
228         } else {
229                 /* Assume it's a number.  This means that bogus strings become
230                  * 0.  I might care about that some day. */
231                 ret = strtoul(name, NULL, 0);
232                 // printf("Selected device %d\n", ret);
233         }
234
235         return ret;
236 }
237
238 static char *
239 lsm_string (struct lov_stripe_md *lsm)
240 {
241         static char buffer[4096];
242         char       *p = buffer;
243         int         space = sizeof (buffer);
244         int         i;
245         int         nob;
246
247         *p = 0;
248         space--;
249
250         nob = snprintf(p, space, LPX64, lsm->lsm_object_id);
251         p += nob;
252         space -= nob;
253
254         if (lsm->lsm_stripe_count != 0) {
255                 nob = snprintf (p, space, "=%u#%u",
256                                 lsm->lsm_stripe_size,
257                                 lsm->lsm_stripe_count);
258                 p += nob;
259                 space -= nob;
260
261                 for (i = 0; i < lsm->lsm_stripe_count; i++) {
262                         nob = snprintf (p, space, "@%u:"LPX64,
263                                         lsm->lsm_oinfo[i].loi_ost_idx,
264                                         lsm->lsm_oinfo[i].loi_id);
265                         p += nob;
266                         space -= nob;
267                 }
268         }
269
270         if (space == 0) {                       /* probable overflow */
271                 fprintf (stderr, "lsm_string() overflowed buffer\n");
272                 abort ();
273         }
274
275         return (buffer);
276 }
277
278 static void
279 reset_lsmb (union lsm_buffer *lsmb)
280 {
281         memset (lsmb->space, 0, sizeof (lsmb->space));
282         lsmb->lsm.lsm_magic = LOV_MAGIC;
283 }
284
285 static int
286 parse_lsm (union lsm_buffer *lsmb, char *string)
287 {
288         struct lov_stripe_md *lsm = &lsmb->lsm;
289         char                 *end;
290         int                   i;
291
292         /*
293          * object_id[=size#count[@offset:id]*]
294          */
295
296         reset_lsmb (lsmb);
297
298         lsm->lsm_object_id = strtoull (string, &end, 0);
299         if (end == string)
300                 return (-1);
301         string = end;
302
303         if (*string == 0)
304                 return (0);
305
306         if (*string != '=')
307                 return (-1);
308         string++;
309
310         lsm->lsm_stripe_size = strtoul (string, &end, 0);
311         if (end == string)
312                 return (-1);
313         string = end;
314
315         if (*string != '#')
316                 return (-1);
317         string++;
318
319         lsm->lsm_stripe_count = strtoul (string, &end, 0);
320         if (end == string)
321                 return (-1);
322         string = end;
323
324         if (*string == 0)               /* don't have to specify obj ids */
325                 return (0);
326
327         for (i = 0; i < lsm->lsm_stripe_count; i++) {
328                 if (*string != '@')
329                         return (-1);
330                 string++;
331                 lsm->lsm_oinfo[i].loi_ost_idx = strtoul(string, &end, 0);
332                 if (*end != ':')
333                         return (-1);
334                 string = end + 1;
335                 lsm->lsm_oinfo[i].loi_id = strtoull(string, &end, 0);
336                 string = end;
337         }
338
339         if (*string != 0)
340                 return (-1);
341
342         return (0);
343 }
344
345 char *jt_cmdname(char *func)
346 {
347         static char buf[512];
348
349         if (thread) {
350                 sprintf(buf, "%s-%d", func, thread);
351                 return buf;
352         }
353
354         return func;
355 }
356
357 #define difftime(a, b)                                  \
358         ((a)->tv_sec - (b)->tv_sec +                    \
359          ((a)->tv_usec - (b)->tv_usec) / 1000000.0)
360
361 static int be_verbose(int verbose, struct timeval *next_time,
362                       __u64 num, __u64 *next_num, int num_total)
363 {
364         struct timeval now;
365
366         if (!verbose)
367                 return 0;
368
369         if (next_time != NULL)
370                 gettimeofday(&now, NULL);
371
372         /* A positive verbosity means to print every X iterations */
373         if (verbose > 0 &&
374             (next_num == NULL || num >= *next_num || num >= num_total)) {
375                 *next_num += verbose;
376                 if (next_time) {
377                         next_time->tv_sec = now.tv_sec - verbose;
378                         next_time->tv_usec = now.tv_usec;
379                 }
380                 return 1;
381         }
382
383         /* A negative verbosity means to print at most each X seconds */
384         if (verbose < 0 && next_time != NULL &&
385             difftime(&now, next_time) >= 0.0){
386                 next_time->tv_sec = now.tv_sec - verbose;
387                 next_time->tv_usec = now.tv_usec;
388                 if (next_num)
389                         *next_num = num;
390                 return 1;
391         }
392
393         return 0;
394 }
395
396 static int get_verbose(char *func, const char *arg)
397 {
398         int verbose;
399         char *end;
400
401         if (!arg || arg[0] == 'v')
402                 verbose = 1;
403         else if (arg[0] == 's' || arg[0] == 'q')
404                 verbose = 0;
405         else {
406                 verbose = (int)strtoul(arg, &end, 0);
407                 if (*end) {
408                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
409                                 jt_cmdname(func), arg);
410                         return BAD_VERBOSE;
411                 }
412         }
413
414         if (verbose < 0)
415                 printf("Print status every %d seconds\n", -verbose);
416         else if (verbose == 1)
417                 printf("Print status every operation\n");
418         else if (verbose > 1)
419                 printf("Print status every %d operations\n", verbose);
420
421         return verbose;
422 }
423
424 int do_disconnect(char *func, int verbose)
425 {
426         cur_device = MAX_OBD_DEVICES;
427         return 0;
428 }
429
430 #ifdef MAX_THREADS
431 static void shmem_setup(void)
432 {
433         /* Create new segment */
434         int shmid = shmget(IPC_PRIVATE, sizeof(*shared_data), 0600);
435
436         if (shmid == -1) {
437                 fprintf(stderr, "Can't create shared data: %s\n",
438                         strerror(errno));
439                 return;
440         }
441
442         /* Attatch to new segment */
443         shared_data = (struct shared_data *)shmat(shmid, NULL, 0);
444
445         if (shared_data == (struct shared_data *)(-1)) {
446                 fprintf(stderr, "Can't attach shared data: %s\n",
447                         strerror(errno));
448                 shared_data = NULL;
449                 return;
450         }
451
452         /* Mark segment as destroyed, so it will disappear when we exit.
453          * Forks will inherit attached segments, so we should be OK.
454          */
455         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
456                 fprintf(stderr, "Can't destroy shared data: %s\n",
457                         strerror(errno));
458         }
459 }
460
461 static inline void shmem_lock(void)
462
463         pthread_mutex_lock(&shared_data->mutex);
464 }
465
466 static inline void shmem_unlock(void)
467
468         pthread_mutex_unlock(&shared_data->mutex);
469 }
470
471 static inline void shmem_reset(int total_threads)
472 {
473         if (shared_data == NULL)
474                 return;
475
476         memset(shared_data, 0, sizeof(*shared_data));
477         pthread_mutex_init(&shared_data->mutex, NULL);
478         pthread_cond_init(&shared_data->cond, NULL);
479         memset(counter_snapshot, 0, sizeof(counter_snapshot));
480         prev_valid = 0;
481         shared_data->barrier = total_threads;
482 }
483
484 static inline void shmem_bump(void)
485 {
486         static int bumped_running;
487
488         if (shared_data == NULL || thread <= 0 || thread > MAX_THREADS)
489                 return;
490
491         shmem_lock();
492         shared_data->counters[thread - 1]++;
493         if (!bumped_running)
494                 shared_data->running++;
495         shmem_unlock();
496         bumped_running = 1;
497 }
498
499 static void shmem_snap(int total_threads, int live_threads)
500 {
501         struct timeval this_time;
502         int non_zero = 0;
503         __u64 total = 0;
504         double secs;
505         int running;
506         int i;
507
508         if (shared_data == NULL || total_threads > MAX_THREADS)
509                 return;
510
511         shmem_lock();
512         memcpy(counter_snapshot[0], shared_data->counters,
513                total_threads * sizeof(counter_snapshot[0][0]));
514         running = shared_data->running;
515         shmem_unlock();
516
517         gettimeofday(&this_time, NULL);
518
519         for (i = 0; i < total_threads; i++) {
520                 long long this_count =
521                         counter_snapshot[0][i] - counter_snapshot[1][i];
522
523                 if (this_count != 0) {
524                         non_zero++;
525                         total += this_count;
526                 }
527         }
528
529         secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
530                (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
531
532         if (prev_valid && 
533             live_threads == total_threads &&
534             secs > 0.0)                    /* someone screwed with the time? */
535                 printf("%d/%d Total: %f/second\n", non_zero, total_threads, total / secs);
536
537         memcpy(counter_snapshot[1], counter_snapshot[0],
538                total_threads * sizeof(counter_snapshot[0][0]));
539         prev_time = this_time;
540         if (!prev_valid && 
541             running == total_threads)
542                 prev_valid = 1;
543 }
544 #else
545 static void shmem_setup(void)
546 {
547 }
548
549 static inline void shmem_reset(int total_threads)
550 {
551 }
552
553 static inline void shmem_bump(void)
554 {
555 }
556
557 static void shmem_lock()
558 {
559 }
560
561 static void shmem_unlock()
562 {
563 }
564 #endif
565
566 extern command_t cmdlist[];
567
568 static int do_device(char *func, char *devname)
569 {
570         struct obd_ioctl_data data;
571         int dev;
572
573         memset(&data, 0, sizeof(data));
574
575         dev = parse_devname(func, devname);
576         if (dev < 0)
577                 return -1;
578
579         cur_device = dev;
580         return 0;
581 }
582
583 int jt_obd_device(int argc, char **argv)
584 {
585         int rc;
586         do_disconnect(argv[0], 1);
587
588         if (argc != 2)
589                 return CMD_HELP;
590
591         rc = do_device(argv[0], argv[1]);
592         return rc;
593 }
594
595 int jt_obd_connect(int argc, char **argv)
596 {
597         return 0;
598 }
599
600 int jt_obd_disconnect(int argc, char **argv)
601 {
602         if (argc != 1)
603                 return CMD_HELP;
604
605         return do_disconnect(argv[0], 0);
606 }
607
608 int jt_opt_device(int argc, char **argv)
609 {
610         int ret;
611         int rc;
612
613         if (argc < 3)
614                 return CMD_HELP;
615
616         rc = do_device("device", argv[1]);
617
618         if (!rc)
619                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
620
621         ret = do_disconnect(argv[0], 0);
622         if (!rc)
623                 rc = ret;
624
625         return rc;
626 }
627
628 #ifdef MAX_THREADS
629 static void parent_sighandler (int sig)
630 {
631         return;
632 }
633
634 int jt_opt_threads(int argc, char **argv)
635 {
636         sigset_t         saveset;
637         sigset_t         sigset;
638         struct sigaction sigact;
639         struct sigaction saveact1;
640         struct sigaction saveact2;
641         __u64 threads, next_thread;
642         int verbose;
643         int rc = 0;
644         char *end;
645         int i;
646
647         if (argc < 5)
648                 return CMD_HELP;
649
650         threads = strtoull(argv[1], &end, 0);
651         if (*end || threads > MAX_THREADS) {
652                 fprintf(stderr, "error: %s: invalid thread count '%s'\n",
653                         jt_cmdname(argv[0]), argv[1]);
654                 return CMD_HELP;
655         }
656
657         verbose = get_verbose(argv[0], argv[2]);
658         if (verbose == BAD_VERBOSE)
659                 return CMD_HELP;
660
661         if (verbose != 0)
662                 printf("%s: starting "LPD64" threads on device %s running %s\n",
663                        argv[0], threads, argv[3], argv[4]);
664
665         shmem_reset(threads);
666
667         sigemptyset(&sigset);
668         sigaddset(&sigset, SIGALRM);
669         sigaddset(&sigset, SIGCHLD);
670         sigprocmask(SIG_BLOCK, &sigset, &saveset);
671
672         nthreads = threads;
673
674         for (i = 1, next_thread = verbose; i <= threads; i++) {
675                 rc = fork();
676                 if (rc < 0) {
677                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
678                                 strerror(rc = errno));
679                         break;
680                 } else if (rc == 0) {
681                         sigprocmask(SIG_SETMASK, &saveset, NULL);
682
683                         thread = i;
684                         argv[2] = "--device";
685                         return jt_opt_device(argc - 2, argv + 2);
686                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
687                         printf("%s: thread #%d (PID %d) started\n",
688                                argv[0], i, rc);
689                 rc = 0;
690         }
691
692         if (!thread) {          /* parent process */
693                 int live_threads = threads;
694
695                 sigemptyset(&sigset);
696                 sigemptyset(&sigact.sa_mask);
697                 sigact.sa_handler = parent_sighandler;
698                 sigact.sa_flags = 0;
699                 
700                 sigaction(SIGALRM, &sigact, &saveact1);
701                 sigaction(SIGCHLD, &sigact, &saveact2);
702
703                 while (live_threads > 0) {
704                         int status;
705                         pid_t ret;
706
707                         if (verbose < 0)        /* periodic stats */
708                                 alarm(-verbose);
709
710                         sigsuspend(&sigset);
711                         alarm(0);
712
713                         while (live_threads > 0) {
714                                 ret = waitpid(0, &status, WNOHANG);
715                                 if (ret == 0)
716                                         break;
717                                 
718                                 if (ret < 0) {
719                                         fprintf(stderr, "error: %s: wait - %s\n",
720                                                 argv[0], strerror(errno));
721                                         if (!rc)
722                                                 rc = errno;
723                                         continue;
724                                 } else {
725                                         /*
726                                          * This is a hack.  We _should_ be able
727                                          * to use WIFEXITED(status) to see if
728                                          * there was an error, but it appears
729                                          * to be broken and it always returns 1
730                                          * (OK).  See wait(2).
731                                          */
732                                         int err = WEXITSTATUS(status);
733                                         if (err || WIFSIGNALED(status))
734                                                 fprintf(stderr,
735                                                         "%s: PID %d had rc=%d\n",
736                                                         argv[0], ret, err);
737                                         if (!rc)
738                                                 rc = err;
739
740                                         live_threads--;
741                                 }
742                         }
743
744                         /* Show stats while all threads running */
745                         if (verbose < 0)
746                                 shmem_snap(threads, live_threads);
747                 }
748                 sigaction(SIGCHLD, &saveact2, NULL);
749                 sigaction(SIGALRM, &saveact1, NULL);
750         }
751
752         sigprocmask(SIG_SETMASK, &saveset, NULL);
753         return rc;
754 }
755 #else
756 int jt_opt_threads(int argc, char **argv)
757 {
758         fprintf(stderr, "%s not-supported in a single-threaded runtime\n",
759                 jt_cmdname(argv[0]));
760         return CMD_HELP;
761 }
762 #endif
763
764 int jt_opt_net(int argc, char **argv)
765 {
766         char *arg2[3];
767         int rc;
768
769         if (argc < 3)
770                 return CMD_HELP;
771
772         arg2[0] = argv[0];
773         arg2[1] = argv[1];
774         arg2[2] = NULL;
775         rc = jt_ptl_network (2, arg2);
776
777         if (!rc)
778                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
779
780         return rc;
781 }
782
783 int jt_obd_no_transno(int argc, char **argv)
784 {
785         struct obd_ioctl_data data;
786         int rc;
787
788         IOC_INIT(data);
789
790         if (argc != 1)
791                 return CMD_HELP;
792
793         IOC_PACK(argv[0], data);
794         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf);
795         if (rc < 0)
796                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
797                         strerror(rc = errno));
798
799         return rc;
800 }
801
802 int jt_obd_set_readonly(int argc, char **argv)
803 {
804         struct obd_ioctl_data data;
805         int rc;
806
807         IOC_INIT(data);
808
809         if (argc != 1)
810                 return CMD_HELP;
811
812         IOC_PACK(argv[0], data);
813         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf);
814         if (rc < 0)
815                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
816                         strerror(rc = errno));
817
818         return rc;
819 }
820
821 int jt_obd_abort_recovery(int argc, char **argv)
822 {
823         struct obd_ioctl_data data;
824         int rc;
825
826         IOC_INIT(data);
827
828         if (argc != 1)
829                 return CMD_HELP;
830
831         IOC_PACK(argv[0], data);
832         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf);
833         if (rc < 0)
834                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
835                         strerror(rc = errno));
836
837         return rc;
838 }
839
840 int jt_get_version(int argc, char **argv)
841 {
842         int rc;
843         char buf[8192];
844         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
845
846         if (argc != 1)
847                 return CMD_HELP;
848
849         memset(buf, 0, sizeof(buf));
850         data->ioc_version = OBD_IOCTL_VERSION;
851         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
852         data->ioc_len = obd_ioctl_packlen(data);
853
854         rc = l2_ioctl(OBD_DEV_ID, OBD_GET_VERSION, buf);
855         if (rc < 0)
856                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
857                         strerror(rc = errno));
858         else {
859                 printf("Lustre version: %s\n", data->ioc_bulk);
860         }
861
862         printf("lctl   version: %s\n", BUILD_VERSION);
863         return rc;
864 }
865
866 int jt_obd_list(int argc, char **argv)
867 {
868         int rc;
869         char buf[MAX_STRING_SIZE];
870         FILE *fp = fopen(DEVICES_LIST, "r");
871
872         if (fp == NULL) {
873                 fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
874                         jt_cmdname(argv[0]), strerror(rc =  errno));
875                 return rc;
876         }
877
878         if (argc != 1)
879                 return CMD_HELP;
880
881         while (fgets(buf, sizeof(buf), fp) != NULL)
882                 printf("%s", buf);
883
884         fclose(fp);
885
886         return 0;
887 }
888
889 /* Get echo client's stripe meta-data for the given object
890  */
891 int jt_obd_get_stripe (int argc, char **argv)
892 {
893         struct obd_ioctl_data data;
894         __u64 id;
895         int   rc;
896         char *end;
897
898         if (argc != 2)
899                 return (CMD_HELP);
900
901         id = strtoull (argv[1], &end, 0);
902         if (*end) {
903                 fprintf (stderr, "Error: %s: invalid object id '%s'\n",
904                          jt_cmdname (argv[0]), argv[1]);
905                 return (CMD_HELP);
906         }
907
908         memset (&lsm_buffer, 0, sizeof (lsm_buffer));
909
910         IOC_INIT (data);
911         data.ioc_obdo1.o_id = id;
912         data.ioc_obdo1.o_mode = S_IFREG | 0644;
913         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
914         data.ioc_pbuf1 = (char *)&lsm_buffer;
915         data.ioc_plen1 = sizeof (lsm_buffer);
916
917         IOC_PACK(argv[0], data);
918         rc = l2_ioctl(OBD_DEV_ID, ECHO_IOC_GET_STRIPE, buf);
919         IOC_UNPACK(argv[0], data);
920
921         if (rc != 0) {
922                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
923                          jt_cmdname (argv[0]), rc, strerror (errno));
924                 return (rc);
925         }
926
927         printf ("%s\n", lsm_string (&lsm_buffer.lsm));
928
929         return (rc);
930 }
931
932 /* Set stripe meta-data for 1 or more objects.  Object must be new to
933  * this echo client instance.
934  */
935 int jt_obd_set_stripe (int argc, char **argv)
936 {
937         struct obd_ioctl_data data;
938         char *end;
939         int count = 1;
940         int i;
941         int rc;
942
943         if (argc < 2 || argc > 3)
944                 return CMD_HELP;
945
946         rc = parse_lsm (&lsm_buffer, argv[1]);
947         if (rc != 0) {
948                 fprintf (stderr, "error: %s: invalid object '%s'\n",
949                          jt_cmdname (argv[0]), argv[1]);
950                 return CMD_HELP;
951         }
952
953         if (argc > 2) {
954                 count = strtol (argv[2], &end, 0);
955                 if (*end != 0) {
956                         fprintf (stderr, "error: %s: invalid count '%s'\n",
957                                  jt_cmdname (argv[0]), argv[1]);
958                         return CMD_HELP;
959                 }
960         }
961
962         for (i = 0; i < count; i++) {
963                 IOC_INIT (data);
964                 data.ioc_obdo1.o_id = lsm_buffer.lsm.lsm_object_id + i;
965                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
966                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
967                 data.ioc_pbuf1 = (char *)&lsm_buffer;
968                 data.ioc_plen1 = sizeof (lsm_buffer);
969
970                 IOC_PACK (argv[0], data);
971                 rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
972                 IOC_UNPACK (argv[0], data);
973
974                 if (rc != 0) {
975                         fprintf (stderr, "Error: %s: rc %d(%s)\n",
976                                  jt_cmdname (argv[0]), rc, strerror (errno));
977                         return (rc);
978                 }
979         }
980
981         return (0);
982 }
983
984 /* Clear stripe meta-data info for an object on this echo-client instance
985  */
986 int jt_obd_unset_stripe (int argc, char **argv)
987 {
988         struct obd_ioctl_data data;
989         char *end;
990         obd_id id;
991         int rc;
992
993         if (argc != 2)
994                 return CMD_HELP;
995
996         id = strtoull (argv[1], &end, 0);
997         if (*end != 0) {
998                 fprintf (stderr, "error: %s: invalid object id '%s'\n",
999                          jt_cmdname (argv[0]), argv[1]);
1000                 return CMD_HELP;
1001         }
1002
1003         IOC_INIT (data);
1004         data.ioc_obdo1.o_id = id;
1005         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1006         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1007
1008         IOC_PACK (argv[0], data);
1009         rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1010         IOC_UNPACK (argv[0], data);
1011
1012         if (rc != 0)
1013                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1014                          jt_cmdname (argv[0]), rc, strerror (errno));
1015
1016         return (0);
1017 }
1018
1019 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1020  * not, defaults assumed.  This echo-client instance stashes the stripe
1021  * object ids.  Use get_stripe on this node to print full lsm and
1022  * set_stripe on another node to cut/paste between nodes.
1023  */
1024 int jt_obd_create(int argc, char **argv)
1025 {
1026         struct obd_ioctl_data data;
1027         struct timeval next_time;
1028         __u64 count = 1, next_count, base_id = 0;
1029         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
1030         char *end;
1031
1032         IOC_INIT(data);
1033         if (argc < 2 || argc > 5)
1034                 return CMD_HELP;
1035
1036         count = strtoull(argv[1], &end, 0);
1037         if (*end) {
1038                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1039                         jt_cmdname(argv[0]), argv[1]);
1040                 return CMD_HELP;
1041         }
1042
1043         if (argc > 2) {
1044                 mode = strtoul(argv[2], &end, 0);
1045                 if (*end) {
1046                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1047                                 jt_cmdname(argv[0]), argv[2]);
1048                         return CMD_HELP;
1049                 }
1050                 if (!(mode & S_IFMT))
1051                         mode |= S_IFREG;
1052         }
1053
1054         if (argc > 3) {
1055                 verbose = get_verbose(argv[0], argv[3]);
1056                 if (verbose == BAD_VERBOSE)
1057                         return CMD_HELP;
1058         }
1059
1060         if (argc < 5)
1061                 reset_lsmb (&lsm_buffer);       /* will set default */
1062         else {
1063                 rc = parse_lsm (&lsm_buffer, argv[4]);
1064                 if (rc != 0) {
1065                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1066                                 jt_cmdname(argv[0]), argv[4]);
1067                         return CMD_HELP;
1068                 }
1069                 base_id = lsm_buffer.lsm.lsm_object_id;
1070                 valid_lsm = 1;
1071         }
1072
1073         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1074         gettimeofday(&next_time, NULL);
1075         next_time.tv_sec -= verbose;
1076
1077         for (i = 1, next_count = verbose; i <= count; i++) {
1078                 data.ioc_obdo1.o_mode = mode;
1079                 data.ioc_obdo1.o_id = base_id;
1080                 data.ioc_obdo1.o_uid = 0;
1081                 data.ioc_obdo1.o_gid = 0;
1082                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1083                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1084
1085                 if (valid_lsm) {
1086                         data.ioc_plen1 = sizeof lsm_buffer;
1087                         data.ioc_pbuf1 = (char *)&lsm_buffer;
1088                 }
1089
1090                 IOC_PACK(argv[0], data);
1091                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1092                 IOC_UNPACK(argv[0], data);
1093                 shmem_bump();
1094                 if (rc < 0) {
1095                         fprintf(stderr, "error: %s: #%d - %s\n",
1096                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1097                         break;
1098                 }
1099                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1100                         fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n",
1101                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1102                         rc = EINVAL;
1103                         break;
1104                 }
1105
1106                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1107                         printf("%s: #%d is object id "LPX64"\n",
1108                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1109         }
1110         return rc;
1111 }
1112
1113 int jt_obd_setattr(int argc, char **argv)
1114 {
1115         struct obd_ioctl_data data;
1116         char *end;
1117         int rc;
1118
1119         IOC_INIT(data);
1120         if (argc != 2)
1121                 return CMD_HELP;
1122
1123         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1124         if (*end) {
1125                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1126                         jt_cmdname(argv[0]), argv[1]);
1127                 return CMD_HELP;
1128         }
1129         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1130         if (*end) {
1131                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1132                         jt_cmdname(argv[0]), argv[2]);
1133                 return CMD_HELP;
1134         }
1135         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1136
1137         IOC_PACK(argv[0], data);
1138         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1139         if (rc < 0)
1140                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1141                         strerror(rc = errno));
1142
1143         return rc;
1144 }
1145
1146 int jt_obd_test_setattr(int argc, char **argv)
1147 {
1148         struct obd_ioctl_data data;
1149         struct timeval start, next_time;
1150         __u64 i, count, next_count;
1151         int verbose = 1;
1152         obd_id objid = 3;
1153         char *end;
1154         int rc = 0;
1155
1156         if (argc < 2 || argc > 4)
1157                 return CMD_HELP;
1158
1159         IOC_INIT(data);
1160         count = strtoull(argv[1], &end, 0);
1161         if (*end) {
1162                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1163                         jt_cmdname(argv[0]), argv[1]);
1164                 return CMD_HELP;
1165         }
1166
1167         if (argc >= 3) {
1168                 verbose = get_verbose(argv[0], argv[2]);
1169                 if (verbose == BAD_VERBOSE)
1170                         return CMD_HELP;
1171         }
1172
1173         if (argc >= 4) {
1174                 if (argv[3][0] == 't') {
1175                         objid = strtoull(argv[3] + 1, &end, 0);
1176                         if (thread)
1177                                 objid += thread - 1;
1178                 } else
1179                         objid = strtoull(argv[3], &end, 0);
1180                 if (*end) {
1181                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1182                                 jt_cmdname(argv[0]), argv[3]);
1183                         return CMD_HELP;
1184                 }
1185         }
1186
1187         gettimeofday(&start, NULL);
1188         next_time.tv_sec = start.tv_sec - verbose;
1189         next_time.tv_usec = start.tv_usec;
1190         if (verbose != 0)
1191                 printf("%s: setting "LPD64" attrs (objid "LPX64"): %s",
1192                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1193
1194         for (i = 1, next_count = verbose; i <= count; i++) {
1195                 data.ioc_obdo1.o_id = objid;
1196                 data.ioc_obdo1.o_mode = S_IFREG;
1197                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1198                 IOC_PACK(argv[0], data);
1199                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data);
1200                 shmem_bump();
1201                 if (rc < 0) {
1202                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1203                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1204                         break;
1205                 } else {
1206                         if (be_verbose
1207                             (verbose, &next_time, i, &next_count, count))
1208                                 printf("%s: set attr #"LPD64"\n",
1209                                        jt_cmdname(argv[0]), i);
1210                 }
1211         }
1212
1213         if (!rc) {
1214                 struct timeval end;
1215                 double diff;
1216
1217                 gettimeofday(&end, NULL);
1218
1219                 diff = difftime(&end, &start);
1220
1221                 --i;
1222                 if (verbose != 0)
1223                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1224                                jt_cmdname(argv[0]), i, diff, i / diff,
1225                                ctime(&end.tv_sec));
1226         }
1227         return rc;
1228 }
1229
1230 int jt_obd_destroy(int argc, char **argv)
1231 {
1232         struct obd_ioctl_data data;
1233         struct timeval next_time;
1234         __u64 count = 1, next_count;
1235         int verbose = 1;
1236         __u64 id;
1237         char *end;
1238         int rc = 0, i;
1239
1240         IOC_INIT(data);
1241         if (argc < 2 || argc > 4)
1242                 return CMD_HELP;
1243
1244         id = strtoull(argv[1], &end, 0);
1245         if (*end) {
1246                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1247                         jt_cmdname(argv[0]), argv[1]);
1248                 return CMD_HELP;
1249         }
1250         if (argc > 2) {
1251                 count = strtoull(argv[2], &end, 0);
1252                 if (*end) {
1253                         fprintf(stderr,
1254                                 "error: %s: invalid iteration count '%s'\n",
1255                                 jt_cmdname(argv[0]), argv[2]);
1256                         return CMD_HELP;
1257                 }
1258         }
1259
1260         if (argc > 3) {
1261                 verbose = get_verbose(argv[0], argv[3]);
1262                 if (verbose == BAD_VERBOSE)
1263                         return CMD_HELP;
1264         }
1265
1266         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1267         gettimeofday(&next_time, NULL);
1268         next_time.tv_sec -= verbose;
1269
1270         for (i = 1, next_count = verbose; i <= count; i++, id++) {
1271                 data.ioc_obdo1.o_id = id;
1272                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1273                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1274
1275                 IOC_PACK(argv[0], data);
1276                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1277                 IOC_UNPACK(argv[0], data);
1278                 shmem_bump();
1279                 if (rc < 0) {
1280                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1281                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1282                         break;
1283                 }
1284
1285                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1286                         printf("%s: #%d is object id "LPX64"\n",
1287                                jt_cmdname(argv[0]), i, id);
1288         }
1289
1290         return rc;
1291 }
1292
1293 int jt_obd_getattr(int argc, char **argv)
1294 {
1295         struct obd_ioctl_data data;
1296         char *end;
1297         int rc;
1298
1299         if (argc != 2)
1300                 return CMD_HELP;
1301
1302         IOC_INIT(data);
1303         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1304         if (*end) {
1305                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1306                         jt_cmdname(argv[0]), argv[1]);
1307                 return CMD_HELP;
1308         }
1309         /* to help obd filter */
1310         data.ioc_obdo1.o_mode = 0100644;
1311         data.ioc_obdo1.o_valid = 0xffffffff;
1312         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1313
1314         IOC_PACK(argv[0], data);
1315         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1316         IOC_UNPACK(argv[0], data);
1317         if (rc) {
1318                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1319                         strerror(rc = errno));
1320         } else {
1321                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1322                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1323         }
1324         return rc;
1325 }
1326
1327 int jt_obd_test_getattr(int argc, char **argv)
1328 {
1329         struct obd_ioctl_data data;
1330         struct timeval start, next_time;
1331         __u64 i, count, next_count;
1332         int verbose = 1;
1333         obd_id objid = 3;
1334         char *end;
1335         int rc = 0;
1336
1337         if (argc < 2 || argc > 4)
1338                 return CMD_HELP;
1339
1340         IOC_INIT(data);
1341         count = strtoull(argv[1], &end, 0);
1342         if (*end) {
1343                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1344                         jt_cmdname(argv[0]), argv[1]);
1345                 return CMD_HELP;
1346         }
1347
1348         if (argc >= 3) {
1349                 verbose = get_verbose(argv[0], argv[2]);
1350                 if (verbose == BAD_VERBOSE)
1351                         return CMD_HELP;
1352         }
1353
1354         if (argc >= 4) {
1355                 if (argv[3][0] == 't') {
1356                         objid = strtoull(argv[3] + 1, &end, 0);
1357                         if (thread)
1358                                 objid += thread - 1;
1359                 } else
1360                         objid = strtoull(argv[3], &end, 0);
1361                 if (*end) {
1362                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1363                                 jt_cmdname(argv[0]), argv[3]);
1364                         return CMD_HELP;
1365                 }
1366         }
1367
1368         gettimeofday(&start, NULL);
1369         next_time.tv_sec = start.tv_sec - verbose;
1370         next_time.tv_usec = start.tv_usec;
1371         if (verbose != 0)
1372                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1373                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1374
1375         for (i = 1, next_count = verbose; i <= count; i++) {
1376                 data.ioc_obdo1.o_id = objid;
1377                 data.ioc_obdo1.o_mode = S_IFREG;
1378                 data.ioc_obdo1.o_valid = 0xffffffff;
1379                 IOC_PACK(argv[0], data);
1380                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1381                 shmem_bump();
1382                 if (rc < 0) {
1383                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1384                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1385                         break;
1386                 } else {
1387                         if (be_verbose
1388                             (verbose, &next_time, i, &next_count, count))
1389                                 printf("%s: got attr #"LPD64"\n",
1390                                        jt_cmdname(argv[0]), i);
1391                 }
1392         }
1393
1394         if (!rc) {
1395                 struct timeval end;
1396                 double diff;
1397
1398                 gettimeofday(&end, NULL);
1399
1400                 diff = difftime(&end, &start);
1401
1402                 --i;
1403                 if (verbose != 0)
1404                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1405                                jt_cmdname(argv[0]), i, diff, i / diff,
1406                                ctime(&end.tv_sec));
1407         }
1408         return rc;
1409 }
1410
1411 int jt_obd_test_brw(int argc, char **argv)
1412 {
1413         struct obd_ioctl_data data;
1414         struct timeval start, next_time;
1415         __u64 count, next_count, len, stride, thr_offset = 0, objid = 3;
1416         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1417         int offset_pages = 0;
1418         long n;
1419         int repeat_offset = 0;
1420         unsigned long long ull;
1421         int  nthr_per_obj = 0;
1422         int  verify = 1;
1423         int  obj_idx = 0;
1424         char *end;
1425
1426         if (argc < 2 || argc > 7) {
1427                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1428                         jt_cmdname(argv[0]), argc);
1429                 return CMD_HELP;
1430         }
1431
1432         count = strtoull(argv[1], &end, 0);
1433         if (*end) {
1434                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1435                         jt_cmdname(argv[0]), argv[1]);
1436                 return CMD_HELP;
1437         }
1438
1439         if (argc >= 3) {
1440                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1441                         write = 1;
1442                 /* else it's a read */
1443
1444                 if (argv[2][0] != 0)
1445                         for (i = 1; argv[2][i] != 0; i++)
1446                                 switch (argv[2][i]) {
1447                                 case 'r':
1448                                         repeat_offset = 1;
1449                                         break;
1450
1451                                 case 'x':
1452                                         verify = 0;
1453                                         break;
1454
1455                                 default:
1456                                         fprintf (stderr, "Can't parse cmd '%s'\n",
1457                                                  argv[2]);
1458                                         return CMD_HELP;
1459                                 }
1460         }
1461
1462         if (argc >= 4) {
1463                 verbose = get_verbose(argv[0], argv[3]);
1464                 if (verbose == BAD_VERBOSE)
1465                         return CMD_HELP;
1466         }
1467
1468         if (argc >= 5) {
1469                 pages = strtoul(argv[4], &end, 0);
1470
1471                 if (*end == '+')
1472                         offset_pages = strtoul(end + 1, &end, 0);
1473
1474                 if (*end != 0 ||
1475                     offset_pages < 0 || offset_pages >= pages) {
1476                         fprintf(stderr, "error: %s: bad npages[+offset] parameter '%s'\n",
1477                                 jt_cmdname(argv[0]), argv[4]);
1478                         return CMD_HELP;
1479                 }
1480         }
1481
1482         if (argc >= 6) {
1483                 if (thread &&
1484                     (n = strtol(argv[5], &end, 0)) > 0 &&
1485                     *end == 't' &&
1486                     (ull = strtoull(end + 1, &end, 0)) > 0 &&
1487                     *end == 0) {
1488                         nthr_per_obj = n;
1489                         objid = ull;
1490                 } else if (thread &&
1491                            argv[5][0] == 't') {
1492                         nthr_per_obj = 1;
1493                         objid = strtoull(argv[5] + 1, &end, 0);
1494                 } else {
1495                         nthr_per_obj = 0;
1496                         objid = strtoull(argv[5], &end, 0);
1497                 }
1498                 if (*end) {
1499                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1500                                 jt_cmdname(argv[0]), argv[5]);
1501                         return CMD_HELP;
1502                 }
1503         }
1504
1505         IOC_INIT(data);
1506
1507         /* communicate the 'type' of brw test and batching to echo_client.
1508          * don't start.  we'd love to refactor this lctl->echo_client
1509          * interface */
1510         data.ioc_pbuf1 = (void *)1;
1511         data.ioc_plen1 = 1;
1512
1513         if (argc >= 7) {
1514                 switch(argv[6][0]) {
1515                         case 'g': /* plug and unplug */
1516                                 data.ioc_pbuf1 = (void *)2;
1517                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1518                                                           0);
1519                                 break;
1520                         case 'p': /* prep and commit */
1521                                 data.ioc_pbuf1 = (void *)3;
1522                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1523                                                           0);
1524                                 break;
1525                         default:
1526                                 fprintf(stderr, "error: %s: batching '%s' "
1527                                         "needs to specify 'p' or 'g'\n",
1528                                         jt_cmdname(argv[0]), argv[6]);
1529                                 return CMD_HELP;
1530                 }
1531
1532                 if (*end) {
1533                         fprintf(stderr, "error: %s: bad batching '%s'\n",
1534                                 jt_cmdname(argv[0]), argv[6]);
1535                         return CMD_HELP;
1536                 }
1537                 data.ioc_plen1 *= getpagesize();
1538         }
1539
1540         len = pages * getpagesize();
1541         thr_offset = offset_pages * getpagesize();
1542         stride = len;
1543
1544 #ifdef MAX_THREADS
1545         if (thread) {
1546                 shmem_lock ();
1547                 if (nthr_per_obj != 0) {
1548                         /* threads interleave */
1549                         obj_idx = (thread - 1)/nthr_per_obj;
1550                         objid += obj_idx;
1551                         stride *= nthr_per_obj;
1552                         if (thread == 1)
1553                                 shared_data->offsets[obj_idx] = stride + thr_offset;
1554                         thr_offset += ((thread - 1) % nthr_per_obj) * len;
1555                 } else {
1556                         /* threads disjoint */
1557                         thr_offset += (thread - 1) * len;
1558                 }
1559
1560                 shared_data->barrier--;
1561                 if (shared_data->barrier == 0)
1562                         pthread_cond_broadcast(&shared_data->cond);
1563                 else
1564                         pthread_cond_wait(&shared_data->cond,
1565                                           &shared_data->mutex);
1566
1567                 shmem_unlock ();
1568         }
1569 #endif
1570
1571         data.ioc_obdo1.o_id = objid;
1572         data.ioc_obdo1.o_mode = S_IFREG;
1573         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS;
1574         data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0);
1575         data.ioc_count = len;
1576         data.ioc_offset = (repeat_offset ? 0 : thr_offset);
1577
1578         gettimeofday(&start, NULL);
1579         next_time.tv_sec = start.tv_sec - verbose;
1580         next_time.tv_usec = start.tv_usec;
1581
1582         if (verbose != 0)
1583                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1584                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
1585                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1586
1587         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1588         for (i = 1, next_count = verbose; i <= count; i++) {
1589                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
1590                 IOC_PACK(argv[0], data);
1591                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
1592                 shmem_bump();
1593                 if (rc) {
1594                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1595                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
1596                                 write ? "write" : "read");
1597                         break;
1598                 } else if (be_verbose(verbose, &next_time,i, &next_count,count)) {
1599                         shmem_lock ();
1600                         printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n",
1601                                jt_cmdname(argv[0]), write ? "write" : "read", i,
1602                                data.ioc_obdo1.o_id, data.ioc_offset,
1603                                (int)(pages * getpagesize()));
1604                         shmem_unlock ();
1605                 }
1606                 
1607                 if (!repeat_offset) {
1608 #ifdef MAX_THREADS
1609                         if (stride == len) {
1610                                 data.ioc_offset += stride;
1611                         } else if (i < count) {
1612                                 shmem_lock ();
1613                                 data.ioc_offset = shared_data->offsets[obj_idx];
1614                                 shared_data->offsets[obj_idx] += len;
1615                                 shmem_unlock ();
1616                         }
1617 #else
1618                         data.ioc_offset += len;
1619                         obj_idx = 0; /* avoids an unused var warning */
1620 #endif
1621                 }
1622         }
1623
1624         if (!rc) {
1625                 struct timeval end;
1626                 double diff;
1627
1628                 gettimeofday(&end, NULL);
1629
1630                 diff = difftime(&end, &start);
1631
1632                 --i;
1633                 if (verbose != 0)
1634                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
1635                                jt_cmdname(argv[0]), write ? "wrote" : "read",
1636                                i, pages, diff,
1637                                ((double)i * pages * getpagesize()) /
1638                                (diff * 1048576.0),
1639                                ctime(&end.tv_sec));
1640         }
1641
1642         return rc;
1643 }
1644
1645 int jt_obd_lov_getconfig(int argc, char **argv)
1646 {
1647         struct obd_ioctl_data data;
1648         struct lov_desc desc;
1649         struct obd_uuid *uuidarray;
1650         __u32 *obdgens;
1651         char *path;
1652         int rc, fd;
1653
1654         IOC_INIT(data);
1655
1656         if (argc != 2)
1657                 return CMD_HELP;
1658
1659         path = argv[1];
1660         fd = open(path, O_RDONLY);
1661         if (fd < 0) {
1662                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1663                         strerror(errno));
1664                 return -errno;
1665         }
1666
1667         memset(&desc, 0, sizeof(desc));
1668         obd_str2uuid(&desc.ld_uuid, argv[1]);
1669         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
1670                              (sizeof(*uuidarray) + sizeof(*obdgens)));
1671
1672
1673 repeat:
1674         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1675         if (!uuidarray) {
1676                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1677                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1678                 rc = -ENOMEM;
1679                 goto out;
1680         }
1681         obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens));
1682         if (!obdgens) {
1683                 fprintf(stderr, "error: %s: no memory for %d generation #'s\n",
1684                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1685                 rc = -ENOMEM;
1686                 goto out_uuidarray;
1687         }
1688
1689         data.ioc_inllen1 = sizeof(desc);
1690         data.ioc_inlbuf1 = (char *)&desc;
1691         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1692         data.ioc_inlbuf2 = (char *)uuidarray;
1693         data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens);
1694         data.ioc_inlbuf3 = (char *)obdgens;
1695
1696         if (obd_ioctl_pack(&data, &buf, max)) {
1697                 fprintf(stderr, "error: %s: invalid ioctl\n",
1698                         jt_cmdname(argv[0]));
1699                 rc = -EINVAL;
1700                 goto out_obdgens;
1701         }
1702         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1703         if (rc == -ENOSPC) {
1704                 free(uuidarray);
1705                 free(obdgens);
1706                 goto repeat;
1707         } else if (rc) {
1708                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1709                         jt_cmdname(argv[0]), strerror(rc = errno));
1710         } else {
1711                 struct obd_uuid *uuidp;
1712                 __u32 *genp;
1713                 int i;
1714
1715                 if (obd_ioctl_unpack(&data, buf, max)) {
1716                         fprintf(stderr, "error: %s: invalid reply\n",
1717                                 jt_cmdname(argv[0]));
1718                         rc = -EINVAL;
1719                         goto out;
1720                 }
1721                 printf("default_stripe_count: %u\n",
1722                        desc.ld_default_stripe_count);
1723                 printf("default_stripe_size: "LPU64"\n",
1724                        desc.ld_default_stripe_size);
1725                 printf("default_stripe_offset: "LPU64"\n",
1726                        desc.ld_default_stripe_offset);
1727                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1728                 printf("obd_count: %u\n", desc.ld_tgt_count);
1729                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
1730                 uuidp = uuidarray;
1731                 genp = obdgens;
1732                 for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++)
1733                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp);
1734         }
1735 out_obdgens:
1736         free(obdgens);
1737 out_uuidarray:
1738         free(uuidarray);
1739 out:
1740         close(fd);
1741         return rc;
1742 }
1743
1744 int jt_obd_dump_ldlm(int argc, char **argv)
1745 {
1746         struct obd_ioctl_data data;
1747         int rc;
1748
1749         IOC_INIT(data);
1750         if (argc != 1)
1751                 return CMD_HELP;
1752
1753         IOC_PACK(argv[0], data);
1754         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf);
1755         if (rc)
1756                 fprintf(stderr, "error: %s failed: %s\n",
1757                         jt_cmdname(argv[0]), strerror(rc = errno));
1758         return rc;
1759 }
1760
1761 int jt_obd_ldlm_regress_start(int argc, char **argv)
1762 {
1763         int rc;
1764         struct obd_ioctl_data data;
1765         char argstring[200];
1766         int i, count = sizeof(argstring) - 1;
1767
1768         IOC_INIT(data);
1769         if (argc > 5)
1770                 return CMD_HELP;
1771
1772         argstring[0] = '\0';
1773         for (i = 1; i < argc; i++) {
1774                 strncat(argstring, " ", count);
1775                 count--;
1776                 strncat(argstring, argv[i], count);
1777                 count -= strlen(argv[i]);
1778         }
1779
1780         if (strlen(argstring)) {
1781                 data.ioc_inlbuf1 = argstring;
1782                 data.ioc_inllen1 = strlen(argstring) + 1;
1783         }
1784
1785         IOC_PACK(argv[0], data);
1786         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1787         if (rc)
1788                 fprintf(stderr, "error: %s: test failed: %s\n",
1789                         jt_cmdname(argv[0]), strerror(rc = errno));
1790
1791         return rc;
1792 }
1793
1794 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1795 {
1796         int rc;
1797         struct obd_ioctl_data data;
1798         IOC_INIT(data);
1799
1800         if (argc != 1)
1801                 return CMD_HELP;
1802
1803         IOC_PACK(argv[0], data);
1804         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1805
1806         if (rc)
1807                 fprintf(stderr, "error: %s: test failed: %s\n",
1808                         jt_cmdname(argv[0]), strerror(rc = errno));
1809         return rc;
1810 }
1811
1812 static int do_activate(int argc, char **argv, int flag)
1813 {
1814         struct obd_ioctl_data data;
1815         int rc;
1816
1817         IOC_INIT(data);
1818         if (argc != 1)
1819                 return CMD_HELP;
1820
1821         /* reuse offset for 'active' */
1822         data.ioc_offset = flag;
1823
1824         IOC_PACK(argv[0], data);
1825         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1826         if (rc)
1827                 fprintf(stderr, "error: %s: failed: %s\n",
1828                         jt_cmdname(argv[0]), strerror(rc = errno));
1829
1830         return rc;
1831 }
1832
1833 int jt_obd_deactivate(int argc, char **argv)
1834 {
1835         return do_activate(argc, argv, 0);
1836 }
1837
1838 int jt_obd_activate(int argc, char **argv)
1839 {
1840         return do_activate(argc, argv, 1);
1841 }
1842
1843 int jt_obd_recover(int argc, char **argv)
1844 {
1845         int rc;
1846         struct obd_ioctl_data data;
1847
1848         IOC_INIT(data);
1849         if (argc > 2)
1850                 return CMD_HELP;
1851
1852         if (argc == 2) {
1853                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1854                 data.ioc_inlbuf1 = argv[1];
1855         }
1856
1857         IOC_PACK(argv[0], data);
1858         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1859         if (rc < 0) {
1860                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1861                         strerror(rc = errno));
1862         }
1863
1864         return rc;
1865 }
1866
1867 int jt_obd_mdc_lookup(int argc, char **argv)
1868 {
1869         struct obd_ioctl_data data;
1870         char *parent, *child;
1871         int rc, fd, verbose = 1;
1872
1873         if (argc < 3 || argc > 4)
1874                 return CMD_HELP;
1875
1876         parent = argv[1];
1877         child = argv[2];
1878         if (argc == 4)
1879                 verbose = get_verbose(argv[0], argv[3]);
1880
1881         IOC_INIT(data);
1882
1883         data.ioc_inllen1 = strlen(child) + 1;
1884         data.ioc_inlbuf1 = child;
1885
1886         IOC_PACK(argv[0], data);
1887
1888         fd = open(parent, O_RDONLY);
1889         if (fd < 0) {
1890                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1891                         strerror(errno));
1892                 return -1;
1893         }
1894
1895         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1896         if (rc < 0) {
1897                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1898                         jt_cmdname(argv[0]), strerror(rc = errno));
1899         }
1900         close(fd);
1901
1902         if (verbose) {
1903                 IOC_UNPACK(argv[0], data);
1904                 printf("%s: mode %o uid %d gid %d\n", child,
1905                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
1906                        data.ioc_obdo1.o_gid);
1907         }
1908
1909         return rc;
1910 }
1911
1912
1913 int jt_obd_close_uuid(int argc, char **argv)
1914 {
1915         int rc;
1916         struct obd_ioctl_data data;
1917
1918         if (argc != 2) {
1919                 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
1920                 return 0;
1921         }
1922
1923         IOC_INIT(data);
1924         data.ioc_inllen1 = strlen(argv[1]) + 1;
1925         data.ioc_inlbuf1 = argv[1];
1926
1927         IOC_PACK(argv[0], data);
1928         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf);
1929         if (rc) {
1930                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
1931                         strerror(errno));
1932                 return -1;
1933         }
1934         return 0;
1935 }
1936
1937
1938 int jt_cfg_record(int argc, char **argv)
1939 {
1940         struct obd_ioctl_data data;
1941         int rc;
1942
1943         IOC_INIT(data);
1944
1945         if (argc != 2)
1946                 return CMD_HELP;
1947
1948         data.ioc_inllen1 = strlen(argv[1]) + 1;
1949         data.ioc_inlbuf1 = argv[1];
1950
1951         IOC_PACK(argv[0], data);
1952         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_RECORD, buf);
1953         if (rc == 0) {
1954                 jt_recording = 1;
1955                 // ptl_set_cfg_record_cb(obd_record);
1956         } else {
1957                 fprintf(stderr, "OBD_IOC_RECORD failed: %s\n",
1958                         strerror(errno));
1959         }
1960
1961         return rc;
1962 }
1963
1964 int jt_cfg_parse(int argc, char **argv)
1965 {
1966         struct obd_ioctl_data data;
1967         int rc;
1968
1969         IOC_INIT(data);
1970
1971         if (argc != 2)
1972                 return CMD_HELP;
1973
1974         data.ioc_inllen1 = strlen(argv[1]) + 1;
1975         data.ioc_inlbuf1 = argv[1];
1976
1977         IOC_PACK(argv[0], data);
1978         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PARSE, buf);
1979         if (rc < 0)
1980                 fprintf(stderr, "OBD_IOC_PARSE failed: %s\n",
1981                         strerror(errno));
1982
1983         return rc;
1984 }
1985
1986
1987 int jt_cfg_dump_log(int argc, char **argv)
1988 {
1989         struct obd_ioctl_data data;
1990         int rc;
1991
1992         IOC_INIT(data);
1993
1994         if (argc != 2)
1995                 return CMD_HELP;
1996
1997         data.ioc_inllen1 = strlen(argv[1]) + 1;
1998         data.ioc_inlbuf1 = argv[1];
1999
2000         IOC_PACK(argv[0], data);
2001         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
2002         if (rc < 0)
2003                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
2004                         strerror(errno));
2005
2006         return rc;
2007 }
2008
2009 int jt_cfg_clear_log(int argc, char **argv)
2010 {
2011         struct obd_ioctl_data data;
2012         int rc;
2013
2014         IOC_INIT(data);
2015
2016         if (argc != 2)
2017                 return CMD_HELP;
2018
2019         data.ioc_inllen1 = strlen(argv[1]) + 1;
2020         data.ioc_inlbuf1 = argv[1];
2021
2022         IOC_PACK(argv[0], data);
2023         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLEAR_LOG, buf);
2024         if (rc < 0)
2025                 fprintf(stderr, "OBD_IOC_CLEAR_LOG failed: %s\n",
2026                         strerror(errno));
2027
2028         return rc;
2029 }
2030
2031
2032
2033 int jt_cfg_endrecord(int argc, char **argv)
2034 {
2035         struct obd_ioctl_data data;
2036         int rc;
2037
2038         IOC_INIT(data);
2039
2040         if (argc != 1)
2041                 return CMD_HELP;
2042
2043         if (!jt_recording) {
2044                 fprintf(stderr, "Not recording, so endrecord doesn't make sense.\n");
2045                 return 0;
2046         }
2047
2048         IOC_PACK(argv[0], data);
2049         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ENDRECORD, buf);
2050         if (rc == 0) {
2051                 jt_recording = 0;
2052                 // ptl_set_cfg_record_cb(NULL);
2053         } else {
2054                 fprintf(stderr, "OBD_IOC_ENDRECORD failed: %s\n",
2055                         strerror(errno));
2056         }
2057         return rc;
2058 }
2059
2060 int jt_llog_catlist(int argc, char **argv)
2061 {
2062         struct obd_ioctl_data data;
2063         int rc;
2064
2065         if (argc != 1)
2066                 return CMD_HELP;
2067
2068         IOC_INIT(data);
2069         data.ioc_inllen1 = max - size_round(sizeof(data));
2070         IOC_PACK(argv[0], data);
2071
2072         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
2073         if (rc == 0)
2074                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2075         else
2076                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n",
2077                         strerror(errno));
2078
2079         return rc;
2080 }
2081
2082 int jt_llog_info(int argc, char **argv)
2083 {
2084         struct obd_ioctl_data data;
2085         int rc;
2086
2087         if (argc != 2)
2088                 return CMD_HELP;
2089
2090         IOC_INIT(data);
2091         data.ioc_inllen1 = strlen(argv[1]) + 1;
2092         data.ioc_inlbuf1 = argv[1];
2093         data.ioc_inllen2 = max - size_round(sizeof(data)) - 
2094                 size_round(data.ioc_inllen1);
2095         IOC_PACK(argv[0], data);
2096
2097         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
2098         if (rc == 0)
2099                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2100         else
2101                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
2102                         strerror(errno));
2103
2104         return rc;
2105 }
2106
2107 int jt_llog_print(int argc, char **argv)
2108 {
2109         struct obd_ioctl_data data;
2110         int rc;
2111
2112         if (argc != 2 && argc != 4)
2113                 return CMD_HELP;
2114
2115         IOC_INIT(data);
2116         data.ioc_inllen1 = strlen(argv[1]) + 1;
2117         data.ioc_inlbuf1 = argv[1];
2118         if (argc == 4) {
2119                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2120                 data.ioc_inlbuf2 = argv[2];
2121                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2122                 data.ioc_inlbuf3 = argv[3];
2123         } else {
2124                 char from[2] = "1", to[3] = "-1";
2125                 data.ioc_inllen2 = strlen(from) + 1;
2126                 data.ioc_inlbuf2 = from;
2127                 data.ioc_inllen3 = strlen(to) + 1;
2128                 data.ioc_inlbuf3 = to;
2129         }
2130         data.ioc_inllen4 = max - size_round(sizeof(data)) -
2131                 size_round(data.ioc_inllen1) -
2132                 size_round(data.ioc_inllen2) -
2133                 size_round(data.ioc_inllen3);
2134         IOC_PACK(argv[0], data);
2135
2136         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
2137         if (rc == 0)
2138                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2139         else
2140                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
2141                         strerror(errno));
2142
2143         return rc;
2144 }
2145
2146 int jt_llog_cancel(int argc, char **argv)
2147 {
2148         struct obd_ioctl_data data;
2149         int rc;
2150
2151         if (argc != 4)
2152                 return CMD_HELP;
2153
2154         IOC_INIT(data);
2155         data.ioc_inllen1 = strlen(argv[1]) + 1;
2156         data.ioc_inlbuf1 = argv[1];
2157         data.ioc_inllen2 = strlen(argv[2]) + 1;
2158         data.ioc_inlbuf2 = argv[2];
2159         data.ioc_inllen3 = strlen(argv[3]) + 1;
2160         data.ioc_inlbuf3 = argv[3];
2161         IOC_PACK(argv[0], data);
2162
2163         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
2164         if (rc == 0)
2165                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
2166         else
2167                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
2168                         strerror(errno));
2169
2170         return rc;
2171
2172 }
2173 int jt_llog_check(int argc, char **argv)
2174 {
2175         struct obd_ioctl_data data;
2176         int rc;
2177
2178         if (argc != 2 && argc != 4)
2179                 return CMD_HELP;
2180
2181         IOC_INIT(data);
2182         data.ioc_inllen1 = strlen(argv[1]) + 1;
2183         data.ioc_inlbuf1 = argv[1];
2184         if (argc == 4) {
2185                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2186                 data.ioc_inlbuf2 = argv[2];
2187                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2188                 data.ioc_inlbuf3 = argv[3];
2189         } else {
2190                 char from[2] = "1", to[3] = "-1";
2191                 data.ioc_inllen2 = strlen(from) + 1;
2192                 data.ioc_inlbuf2 = from;
2193                 data.ioc_inllen3 = strlen(to) + 1;
2194                 data.ioc_inlbuf3 = to;
2195         }
2196         data.ioc_inllen4 = max - size_round(sizeof(data)) -
2197                 size_round(data.ioc_inllen1) -
2198                 size_round(data.ioc_inllen2) -
2199                 size_round(data.ioc_inllen3);
2200         IOC_PACK(argv[0], data);
2201
2202         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
2203         if (rc == 0)
2204                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2205         else
2206                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
2207                         strerror(errno));
2208         return rc;
2209 }
2210
2211 int jt_llog_remove(int argc, char **argv)
2212 {
2213         struct obd_ioctl_data data;
2214         int rc;
2215
2216         if (argc != 3 && argc != 2)
2217                 return CMD_HELP;
2218
2219         IOC_INIT(data);
2220         data.ioc_inllen1 = strlen(argv[1]) + 1;
2221         data.ioc_inlbuf1 = argv[1];
2222         if (argc == 3){
2223                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2224                 data.ioc_inlbuf2 = argv[2];
2225         }
2226         IOC_PACK(argv[0], data);
2227
2228         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
2229         if (rc == 0) {
2230                 if (argc == 3)
2231                         fprintf(stdout, "log %s are removed.\n", argv[2]);
2232                 else
2233                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
2234         } else
2235                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
2236                         strerror(errno));
2237
2238         return rc;
2239 }
2240
2241 static void signal_server(int sig)
2242 {
2243         if (sig == SIGINT) {
2244                 do_disconnect("sigint", 1);
2245                 exit(1);
2246         } else
2247                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2248 }
2249
2250 int obd_initialize(int argc, char **argv)
2251 {
2252         shmem_setup();
2253         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH,
2254                          OBD_DEV_MAJOR, OBD_DEV_MINOR);
2255
2256         return 0;
2257 }
2258
2259
2260 void obd_finalize(int argc, char **argv)
2261 {
2262         struct sigaction sigact;
2263
2264         sigact.sa_handler = signal_server;
2265         sigfillset(&sigact.sa_mask);
2266         sigact.sa_flags = SA_RESTART;
2267         sigaction(SIGINT, &sigact, NULL);
2268
2269         if (jt_recording) {
2270                 printf("END RECORD\n");
2271                 jt_cfg_endrecord(argc, argv);
2272         }
2273
2274         do_disconnect(argv[0], 1);
2275 }