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