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