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