Whamcloud - gitweb
- tagging RC_CURRENT
[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         char *path;
1404         int rc, fd;
1405
1406         IOC_INIT(data);
1407
1408         if (argc != 2)
1409                 return CMD_HELP;
1410
1411         path = argv[1];
1412         fd = open(path, O_RDONLY);
1413         if (fd < 0) {
1414                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1415                         strerror(errno));
1416                 return -1;
1417         }
1418
1419         memset(&desc, 0, sizeof(desc));
1420         obd_str2uuid(&desc.ld_uuid, argv[1]);
1421         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
1422                              sizeof(*uuidarray));
1423
1424 repeat:
1425         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1426         if (!uuidarray) {
1427                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1428                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1429                 rc = -ENOMEM;
1430                 goto out;
1431         }
1432
1433         data.ioc_inllen1 = sizeof(desc);
1434         data.ioc_inlbuf1 = (char *)&desc;
1435         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1436         data.ioc_inlbuf2 = (char *)uuidarray;
1437
1438         if (obd_ioctl_pack(&data, &buf, max)) {
1439                 fprintf(stderr, "error: %s: invalid ioctl\n",
1440                         jt_cmdname(argv[0]));
1441                 rc = -EINVAL;
1442                 goto out;
1443         }
1444         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1445         if (rc == -ENOSPC) {
1446                 free(uuidarray);
1447                 goto repeat;
1448         } else if (rc) {
1449                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1450                         jt_cmdname(argv[0]), strerror(rc = errno));
1451         } else {
1452                 struct obd_uuid *ptr;
1453                 int i;
1454
1455                 if (obd_ioctl_unpack(&data, buf, max)) {
1456                         fprintf(stderr, "error: %s: invalid reply\n",
1457                                 jt_cmdname(argv[0]));
1458                         rc = -EINVAL;
1459                         goto out;
1460                 }
1461                 printf("default_stripe_count: %u\n",
1462                        desc.ld_default_stripe_count);
1463                 printf("default_stripe_size: "LPU64"\n",
1464                        desc.ld_default_stripe_size);
1465                 printf("default_stripe_offset: "LPU64"\n",
1466                        desc.ld_default_stripe_offset);
1467                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1468                 printf("obd_count: %u\n", desc.ld_tgt_count);
1469                 for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
1470                         printf("%u: %s\n", i, (char *)ptr);
1471         }
1472 out:
1473         free(uuidarray);
1474         close(fd);
1475         return rc;
1476 }
1477
1478 int jt_obd_test_ldlm(int argc, char **argv)
1479 {
1480         struct obd_ioctl_data data;
1481         int rc;
1482
1483         IOC_INIT(data);
1484         if (argc != 1)
1485                 return CMD_HELP;
1486
1487         IOC_PACK(argv[0], data);
1488         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_TEST, buf);
1489         if (rc)
1490                 fprintf(stderr, "error: %s: test failed: %s\n",
1491                         jt_cmdname(argv[0]), strerror(rc = errno));
1492         return rc;
1493 }
1494
1495 int jt_obd_dump_ldlm(int argc, char **argv)
1496 {
1497         struct obd_ioctl_data data;
1498         int rc;
1499
1500         IOC_INIT(data);
1501         if (argc != 1)
1502                 return CMD_HELP;
1503
1504         IOC_PACK(argv[0], data);
1505         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf);
1506         if (rc)
1507                 fprintf(stderr, "error: %s failed: %s\n",
1508                         jt_cmdname(argv[0]), strerror(rc = errno));
1509         return rc;
1510 }
1511
1512 int jt_obd_ldlm_regress_start(int argc, char **argv)
1513 {
1514         int rc;
1515         struct obd_ioctl_data data;
1516         char argstring[200];
1517         int i, count = sizeof(argstring) - 1;
1518
1519         IOC_INIT(data);
1520         if (argc > 5)
1521                 return CMD_HELP;
1522
1523         argstring[0] = '\0';
1524         for (i = 1; i < argc; i++) {
1525                 strncat(argstring, " ", count);
1526                 count--;
1527                 strncat(argstring, argv[i], count);
1528                 count -= strlen(argv[i]);
1529         }
1530
1531         if (strlen(argstring)) {
1532                 data.ioc_inlbuf1 = argstring;
1533                 data.ioc_inllen1 = strlen(argstring) + 1;
1534         }
1535
1536         IOC_PACK(argv[0], data);
1537         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1538         if (rc)
1539                 fprintf(stderr, "error: %s: test failed: %s\n",
1540                         jt_cmdname(argv[0]), strerror(rc = errno));
1541
1542         return rc;
1543 }
1544
1545 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1546 {
1547         int rc;
1548         struct obd_ioctl_data data;
1549         IOC_INIT(data);
1550
1551         if (argc != 1)
1552                 return CMD_HELP;
1553
1554         IOC_PACK(argv[0], data);
1555         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1556
1557         if (rc)
1558                 fprintf(stderr, "error: %s: test failed: %s\n",
1559                         jt_cmdname(argv[0]), strerror(rc = errno));
1560         return rc;
1561 }
1562
1563 static int do_activate(int argc, char **argv, int flag)
1564 {
1565         struct obd_ioctl_data data;
1566         int rc;
1567
1568         IOC_INIT(data);
1569         if (argc != 1)
1570                 return CMD_HELP;
1571
1572         /* reuse offset for 'active' */
1573         data.ioc_offset = flag;
1574
1575         IOC_PACK(argv[0], data);
1576         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1577         if (rc)
1578                 fprintf(stderr, "error: %s: failed: %s\n",
1579                         jt_cmdname(argv[0]), strerror(rc = errno));
1580
1581         return rc;
1582 }
1583
1584 int jt_obd_deactivate(int argc, char **argv)
1585 {
1586         return do_activate(argc, argv, 0);
1587 }
1588
1589 int jt_obd_activate(int argc, char **argv)
1590 {
1591         return do_activate(argc, argv, 1);
1592 }
1593
1594 int jt_obd_recover(int argc, char **argv)
1595 {
1596         int rc;
1597         struct obd_ioctl_data data;
1598
1599         IOC_INIT(data);
1600         if (argc > 2)
1601                 return CMD_HELP;
1602
1603         if (argc == 2) {
1604                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1605                 data.ioc_inlbuf1 = argv[1];
1606         }
1607
1608         IOC_PACK(argv[0], data);
1609         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1610         if (rc < 0) {
1611                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1612                         strerror(rc = errno));
1613         }
1614
1615         return rc;
1616 }
1617
1618 int jt_obd_mdc_lookup(int argc, char **argv)
1619 {
1620         struct obd_ioctl_data data;
1621         char *parent, *child;
1622         int rc, fd, verbose = 1;
1623
1624         if (argc < 3 || argc > 4)
1625                 return CMD_HELP;
1626
1627         parent = argv[1];
1628         child = argv[2];
1629         if (argc == 4)
1630                 verbose = get_verbose(argv[0], argv[3]);
1631
1632         IOC_INIT(data);
1633
1634         data.ioc_inllen1 = strlen(child) + 1;
1635         data.ioc_inlbuf1 = child;
1636
1637         IOC_PACK(argv[0], data);
1638
1639         fd = open(parent, O_RDONLY);
1640         if (fd < 0) {
1641                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1642                         strerror(errno));
1643                 return -1;
1644         }
1645
1646         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1647         if (rc < 0) {
1648                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1649                         jt_cmdname(argv[0]), strerror(rc = errno));
1650         }
1651         close(fd);
1652
1653         if (verbose) {
1654                 IOC_UNPACK(argv[0], data);
1655                 printf("%s: mode %o uid %d gid %d\n", child,
1656                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
1657                        data.ioc_obdo1.o_gid);
1658         }
1659
1660         return rc;
1661 }
1662
1663
1664 int jt_obd_close_uuid(int argc, char **argv)
1665 {
1666         int rc, nal;
1667         struct obd_ioctl_data data;
1668
1669         if (argc != 3) {
1670                 fprintf(stderr, "usage: %s <uuid> <net-type>\n", argv[0]);
1671                 return 0;
1672         }
1673
1674         nal = ptl_name2nal(argv[2]);
1675
1676         if (nal <= 0) {
1677                 fprintf (stderr, "Can't parse NAL %s\n", argv[2]);
1678                 return -1;
1679         }
1680
1681         IOC_INIT(data);
1682         data.ioc_inllen1 = strlen(argv[1]) + 1;
1683         data.ioc_inlbuf1 = argv[1];
1684         data.ioc_nal = nal;
1685
1686         IOC_PACK(argv[0], data);
1687         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf);
1688         if (rc) {
1689                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
1690                         strerror(errno));
1691                 return -1;
1692         }
1693         return 0;
1694 }
1695
1696
1697 int jt_cfg_record(int argc, char **argv)
1698 {
1699         struct obd_ioctl_data data;
1700         int rc;
1701
1702         IOC_INIT(data);
1703
1704         if (argc != 2)
1705                 return CMD_HELP;
1706
1707         data.ioc_inllen1 = strlen(argv[1]) + 1;
1708         data.ioc_inlbuf1 = argv[1];
1709
1710         IOC_PACK(argv[0], data);
1711         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_RECORD, buf);
1712         if (rc == 0) {
1713                 jt_recording = 1;
1714                 ptl_set_cfg_record_cb(obd_record);
1715         } else {
1716                 fprintf(stderr, "OBD_IOC_RECORD failed: %s\n",
1717                         strerror(errno));
1718         }
1719
1720         return rc;
1721 }
1722
1723 int jt_cfg_parse(int argc, char **argv)
1724 {
1725         struct obd_ioctl_data data;
1726         int rc;
1727
1728         IOC_INIT(data);
1729
1730         if (argc != 2)
1731                 return CMD_HELP;
1732
1733         data.ioc_inllen1 = strlen(argv[1]) + 1;
1734         data.ioc_inlbuf1 = argv[1];
1735
1736         IOC_PACK(argv[0], data);
1737         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PARSE, buf);
1738         if (rc < 0)
1739                 fprintf(stderr, "OBD_IOC_PARSE failed: %s\n",
1740                         strerror(errno));
1741
1742         return rc;
1743 }
1744
1745
1746 int jt_cfg_dump_log(int argc, char **argv)
1747 {
1748         struct obd_ioctl_data data;
1749         int rc;
1750
1751         IOC_INIT(data);
1752
1753         if (argc != 2)
1754                 return CMD_HELP;
1755
1756         data.ioc_inllen1 = strlen(argv[1]) + 1;
1757         data.ioc_inlbuf1 = argv[1];
1758
1759         IOC_PACK(argv[0], data);
1760         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
1761         if (rc < 0)
1762                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
1763                         strerror(errno));
1764
1765         return rc;
1766 }
1767
1768 int jt_cfg_clear_log(int argc, char **argv)
1769 {
1770         struct obd_ioctl_data data;
1771         int rc;
1772
1773         IOC_INIT(data);
1774
1775         if (argc != 2)
1776                 return CMD_HELP;
1777
1778         data.ioc_inllen1 = strlen(argv[1]) + 1;
1779         data.ioc_inlbuf1 = argv[1];
1780
1781         IOC_PACK(argv[0], data);
1782         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLEAR_LOG, buf);
1783         if (rc < 0)
1784                 fprintf(stderr, "OBD_IOC_CLEAR_LOG failed: %s\n",
1785                         strerror(errno));
1786
1787         return rc;
1788 }
1789
1790
1791
1792 int jt_cfg_endrecord(int argc, char **argv)
1793 {
1794         struct obd_ioctl_data data;
1795         int rc;
1796
1797         IOC_INIT(data);
1798
1799         if (argc != 1)
1800                 return CMD_HELP;
1801
1802         if (!jt_recording) {
1803                 fprintf(stderr, "Not recording, so endrecord doesn't make sense.\n");
1804                 return 0;
1805         }
1806
1807         IOC_PACK(argv[0], data);
1808         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ENDRECORD, buf);
1809         if (rc == 0) {
1810                 jt_recording = 0;
1811                 ptl_set_cfg_record_cb(NULL);
1812         } else {
1813                 fprintf(stderr, "OBD_IOC_ENDRECORD failed: %s\n",
1814                         strerror(errno));
1815         }
1816         return rc;
1817 }
1818
1819 int jt_llog_catlist(int argc, char **argv)
1820 {
1821         struct obd_ioctl_data data;
1822         int rc;
1823
1824         if (argc != 1)
1825                 return CMD_HELP;
1826
1827         IOC_INIT(data);
1828         data.ioc_inllen1 = max - size_round(sizeof(data));
1829         IOC_PACK(argv[0], data);
1830         
1831         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
1832         if (rc == 0) 
1833                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1834         else
1835                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n", 
1836                         strerror(errno));
1837         
1838         return rc;
1839 }
1840
1841 int jt_llog_info(int argc, char **argv)
1842 {
1843         struct obd_ioctl_data data;
1844         int rc;
1845
1846         if (argc != 2)
1847                 return CMD_HELP;
1848
1849         IOC_INIT(data);
1850         data.ioc_inllen1 = strlen(argv[1]) + 1;
1851         data.ioc_inlbuf1 = argv[1];
1852         data.ioc_inllen2 = max - size_round(sizeof(data)) - 
1853                 size_round(data.ioc_inllen1);
1854         IOC_PACK(argv[0], data);
1855
1856         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
1857         if (rc == 0)
1858                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1859         else
1860                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
1861                         strerror(errno));
1862
1863         return rc;
1864 }
1865
1866 int jt_llog_print(int argc, char **argv)
1867 {
1868         struct obd_ioctl_data data;
1869         int rc;
1870
1871         if (argc != 2 && argc != 4)
1872                 return CMD_HELP;
1873
1874         IOC_INIT(data);
1875         data.ioc_inllen1 = strlen(argv[1]) + 1;
1876         data.ioc_inlbuf1 = argv[1];
1877         if (argc == 4) {
1878                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1879                 data.ioc_inlbuf2 = argv[2];
1880                 data.ioc_inllen3 = strlen(argv[3]) + 1;
1881                 data.ioc_inlbuf3 = argv[3];
1882         } else {
1883                 char from[2] = "1", to[3] = "-1";
1884                 data.ioc_inllen2 = strlen(from) + 1;
1885                 data.ioc_inlbuf2 = from;
1886                 data.ioc_inllen3 = strlen(to) + 1;
1887                 data.ioc_inlbuf3 = to;
1888         }
1889         data.ioc_inllen4 = max - size_round(sizeof(data)) -
1890                 size_round(data.ioc_inllen1) -
1891                 size_round(data.ioc_inllen2) -
1892                 size_round(data.ioc_inllen3);
1893         IOC_PACK(argv[0], data);
1894
1895         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
1896         if (rc == 0)
1897                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1898         else
1899                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
1900                         strerror(errno));
1901
1902         return rc;
1903 }
1904
1905 int jt_llog_cancel(int argc, char **argv)
1906 {
1907         struct obd_ioctl_data data;
1908         int rc;
1909
1910         if (argc != 4)
1911                 return CMD_HELP;
1912
1913         IOC_INIT(data);
1914         data.ioc_inllen1 = strlen(argv[1]) + 1;
1915         data.ioc_inlbuf1 = argv[1];
1916         data.ioc_inllen2 = strlen(argv[2]) + 1;
1917         data.ioc_inlbuf2 = argv[2];
1918         data.ioc_inllen3 = strlen(argv[3]) + 1;
1919         data.ioc_inlbuf3 = argv[3];
1920         IOC_PACK(argv[0], data);
1921
1922         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
1923         if (rc == 0)
1924                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
1925         else
1926                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
1927                         strerror(errno));
1928
1929         return rc;
1930
1931 }
1932 int jt_llog_check(int argc, char **argv)
1933 {
1934         struct obd_ioctl_data data;
1935         int rc;
1936
1937         if (argc != 2 && argc != 4)
1938                 return CMD_HELP;
1939
1940         IOC_INIT(data);
1941         data.ioc_inllen1 = strlen(argv[1]) + 1;
1942         data.ioc_inlbuf1 = argv[1];
1943         if (argc == 4) {
1944                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1945                 data.ioc_inlbuf2 = argv[2];
1946                 data.ioc_inllen3 = strlen(argv[3]) + 1;
1947                 data.ioc_inlbuf3 = argv[3];
1948         } else {
1949                 char from[2] = "1", to[3] = "-1";
1950                 data.ioc_inllen2 = strlen(from) + 1;
1951                 data.ioc_inlbuf2 = from;
1952                 data.ioc_inllen3 = strlen(to) + 1;
1953                 data.ioc_inlbuf3 = to;
1954         }
1955         data.ioc_inllen4 = max - size_round(sizeof(data)) -
1956                 size_round(data.ioc_inllen1) -
1957                 size_round(data.ioc_inllen2) -
1958                 size_round(data.ioc_inllen3);
1959         IOC_PACK(argv[0], data);
1960
1961         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
1962         if (rc == 0)
1963                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1964         else
1965                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
1966                         strerror(errno));
1967         return rc;
1968 }
1969
1970 int jt_llog_remove(int argc, char **argv)
1971 {
1972         struct obd_ioctl_data data;
1973         int rc;
1974
1975         if (argc != 3 && argc != 2)
1976                 return CMD_HELP;
1977
1978         IOC_INIT(data);
1979         data.ioc_inllen1 = strlen(argv[1]) + 1;
1980         data.ioc_inlbuf1 = argv[1];
1981         if (argc == 3){
1982                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1983                 data.ioc_inlbuf2 = argv[2];
1984         }
1985         IOC_PACK(argv[0], data);
1986
1987         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
1988         if (rc == 0) {
1989                 if (argc == 3)
1990                         fprintf(stdout, "log %s are removed.\n", argv[2]);
1991                 else
1992                         fprintf(stdout, "the log in catlog %s are removed. \n", argv[1]);
1993         } else
1994                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
1995                         strerror(errno));
1996
1997         return rc;
1998 }
1999
2000 static void signal_server(int sig)
2001 {
2002         if (sig == SIGINT) {
2003                 do_disconnect("sigint", 1);
2004                 exit(1);
2005         } else
2006                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2007 }
2008
2009 int obd_initialize(int argc, char **argv)
2010 {
2011         SHMEM_SETUP();
2012         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH);
2013
2014         return 0;
2015 }
2016
2017
2018 void obd_finalize(int argc, char **argv)
2019 {
2020         struct sigaction sigact;
2021
2022         sigact.sa_handler = signal_server;
2023         sigfillset(&sigact.sa_mask);
2024         sigact.sa_flags = SA_RESTART;
2025         sigaction(SIGINT, &sigact, NULL);
2026
2027         if (jt_recording) {
2028                 printf("END RECORD\n");
2029                 jt_cfg_endrecord(argc, argv);
2030         }
2031
2032         do_disconnect(argv[0], 1);
2033 }