Whamcloud - gitweb
Land b_smallfix onto HEAD (20040512_1806)
[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 opening "DEVICES_LIST"\n",
785                         jt_cmdname(argv[0]), strerror(rc =  errno));
786                 return rc;
787         }
788
789         if (argc != 1)
790                 return CMD_HELP;
791
792         while (fgets(buf, sizeof(buf), fp) != NULL)
793                 printf("%s", buf);
794
795         fclose(fp);
796
797         return 0;
798 }
799
800 /* Get echo client's stripe meta-data for the given object
801  */
802 int jt_obd_get_stripe (int argc, char **argv)
803 {
804         struct obd_ioctl_data data;
805         __u64 id;
806         int   rc;
807         char *end;
808
809         if (argc != 2)
810                 return (CMD_HELP);
811
812         id = strtoull (argv[1], &end, 0);
813         if (*end) {
814                 fprintf (stderr, "Error: %s: invalid object id '%s'\n",
815                          jt_cmdname (argv[0]), argv[1]);
816                 return (CMD_HELP);
817         }
818
819         memset (&lsm_buffer, 0, sizeof (lsm_buffer));
820
821         IOC_INIT (data);
822         data.ioc_obdo1.o_id = id;
823         data.ioc_obdo1.o_mode = S_IFREG | 0644;
824         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
825         data.ioc_pbuf1 = (char *)&lsm_buffer;
826         data.ioc_plen1 = sizeof (lsm_buffer);
827
828         IOC_PACK(argv[0], data);
829         rc = l2_ioctl(OBD_DEV_ID, ECHO_IOC_GET_STRIPE, buf);
830         IOC_UNPACK(argv[0], data);
831
832         if (rc != 0) {
833                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
834                          jt_cmdname (argv[0]), rc, strerror (errno));
835                 return (rc);
836         }
837
838         printf ("%s\n", lsm_string (&lsm_buffer.lsm));
839
840         return (rc);
841 }
842
843 /* Set stripe meta-data for 1 or more objects.  Object must be new to
844  * this echo client instance.
845  */
846 int jt_obd_set_stripe (int argc, char **argv)
847 {
848         struct obd_ioctl_data data;
849         char *end;
850         int count = 1;
851         int i;
852         int rc;
853
854         if (argc < 2 || argc > 3)
855                 return CMD_HELP;
856
857         rc = parse_lsm (&lsm_buffer, argv[1]);
858         if (rc != 0) {
859                 fprintf (stderr, "error: %s: invalid object '%s'\n",
860                          jt_cmdname (argv[0]), argv[1]);
861                 return CMD_HELP;
862         }
863
864         if (argc > 2) {
865                 count = strtol (argv[2], &end, 0);
866                 if (*end != 0) {
867                         fprintf (stderr, "error: %s: invalid count '%s'\n",
868                                  jt_cmdname (argv[0]), argv[1]);
869                         return CMD_HELP;
870                 }
871         }
872
873         for (i = 0; i < count; i++) {
874                 IOC_INIT (data);
875                 data.ioc_obdo1.o_id = lsm_buffer.lsm.lsm_object_id + i;
876                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
877                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
878                 data.ioc_pbuf1 = (char *)&lsm_buffer;
879                 data.ioc_plen1 = sizeof (lsm_buffer);
880
881                 IOC_PACK (argv[0], data);
882                 rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
883                 IOC_UNPACK (argv[0], data);
884
885                 if (rc != 0) {
886                         fprintf (stderr, "Error: %s: rc %d(%s)\n",
887                                  jt_cmdname (argv[0]), rc, strerror (errno));
888                         return (rc);
889                 }
890         }
891
892         return (0);
893 }
894
895 /* Clear stripe meta-data info for an object on this echo-client instance
896  */
897 int jt_obd_unset_stripe (int argc, char **argv)
898 {
899         struct obd_ioctl_data data;
900         char *end;
901         obd_id id;
902         int rc;
903
904         if (argc != 2)
905                 return CMD_HELP;
906
907         id = strtoull (argv[1], &end, 0);
908         if (*end != 0) {
909                 fprintf (stderr, "error: %s: invalid object id '%s'\n",
910                          jt_cmdname (argv[0]), argv[1]);
911                 return CMD_HELP;
912         }
913
914         IOC_INIT (data);
915         data.ioc_obdo1.o_id = id;
916         data.ioc_obdo1.o_mode = S_IFREG | 0644;
917         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
918
919         IOC_PACK (argv[0], data);
920         rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
921         IOC_UNPACK (argv[0], data);
922
923         if (rc != 0)
924                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
925                          jt_cmdname (argv[0]), rc, strerror (errno));
926
927         return (0);
928 }
929
930 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
931  * not, defaults assumed.  This echo-client instance stashes the stripe
932  * object ids.  Use get_stripe on this node to print full lsm and
933  * set_stripe on another node to cut/paste between nodes.
934  */
935 int jt_obd_create(int argc, char **argv)
936 {
937         struct obd_ioctl_data data;
938         struct timeval next_time;
939         __u64 count = 1, next_count, base_id = 0;
940         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
941         char *end;
942
943         IOC_INIT(data);
944         if (argc < 2 || argc > 5)
945                 return CMD_HELP;
946
947         count = strtoull(argv[1], &end, 0);
948         if (*end) {
949                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
950                         jt_cmdname(argv[0]), argv[1]);
951                 return CMD_HELP;
952         }
953
954         if (argc > 2) {
955                 mode = strtoul(argv[2], &end, 0);
956                 if (*end) {
957                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
958                                 jt_cmdname(argv[0]), argv[2]);
959                         return CMD_HELP;
960                 }
961                 if (!(mode & S_IFMT))
962                         mode |= S_IFREG;
963         }
964
965         if (argc > 3) {
966                 verbose = get_verbose(argv[0], argv[3]);
967                 if (verbose == BAD_VERBOSE)
968                         return CMD_HELP;
969         }
970
971         if (argc < 5)
972                 reset_lsmb (&lsm_buffer);       /* will set default */
973         else {
974                 rc = parse_lsm (&lsm_buffer, argv[4]);
975                 if (rc != 0) {
976                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
977                                 jt_cmdname(argv[0]), argv[4]);
978                         return CMD_HELP;
979                 }
980                 base_id = lsm_buffer.lsm.lsm_object_id;
981                 valid_lsm = 1;
982         }
983
984         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
985         gettimeofday(&next_time, NULL);
986         next_time.tv_sec -= verbose;
987
988         for (i = 1, next_count = verbose; i <= count; i++) {
989                 data.ioc_obdo1.o_mode = mode;
990                 data.ioc_obdo1.o_id = base_id;
991                 data.ioc_obdo1.o_uid = 0;
992                 data.ioc_obdo1.o_gid = 0;
993                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
994                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
995
996                 if (valid_lsm) {
997                         data.ioc_plen1 = sizeof lsm_buffer;
998                         data.ioc_pbuf1 = (char *)&lsm_buffer;
999                 }
1000
1001                 IOC_PACK(argv[0], data);
1002                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1003                 IOC_UNPACK(argv[0], data);
1004                 SHMEM_BUMP();
1005                 if (rc < 0) {
1006                         fprintf(stderr, "error: %s: #%d - %s\n",
1007                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1008                         break;
1009                 }
1010                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1011                         fprintf(stderr, "error: %s: objid not valid #%d:%08x\n",
1012                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1013                         rc = EINVAL;
1014                         break;
1015                 }
1016
1017                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1018                         printf("%s: #%d is object id "LPX64"\n",
1019                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1020         }
1021         return rc;
1022 }
1023
1024 int jt_obd_setattr(int argc, char **argv)
1025 {
1026         struct obd_ioctl_data data;
1027         char *end;
1028         int rc;
1029
1030         IOC_INIT(data);
1031         if (argc != 2)
1032                 return CMD_HELP;
1033
1034         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1035         if (*end) {
1036                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1037                         jt_cmdname(argv[0]), argv[1]);
1038                 return CMD_HELP;
1039         }
1040         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1041         if (*end) {
1042                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1043                         jt_cmdname(argv[0]), argv[2]);
1044                 return CMD_HELP;
1045         }
1046         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1047
1048         IOC_PACK(argv[0], data);
1049         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1050         if (rc < 0)
1051                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1052                         strerror(rc = errno));
1053
1054         return rc;
1055 }
1056
1057 int jt_obd_destroy(int argc, char **argv)
1058 {
1059         struct obd_ioctl_data data;
1060         struct timeval next_time;
1061         __u64 count = 1, next_count;
1062         int verbose = 1;
1063         __u64 id;
1064         char *end;
1065         int rc = 0, i;
1066
1067         IOC_INIT(data);
1068         if (argc < 2 || argc > 4)
1069                 return CMD_HELP;
1070
1071         id = strtoull(argv[1], &end, 0);
1072         if (*end) {
1073                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1074                         jt_cmdname(argv[0]), argv[1]);
1075                 return CMD_HELP;
1076         }
1077         if (argc > 2) {
1078                 count = strtoull(argv[2], &end, 0);
1079                 if (*end) {
1080                         fprintf(stderr,
1081                                 "error: %s: invalid iteration count '%s'\n",
1082                                 jt_cmdname(argv[0]), argv[2]);
1083                         return CMD_HELP;
1084                 }
1085         }
1086
1087         if (argc > 3) {
1088                 verbose = get_verbose(argv[0], argv[3]);
1089                 if (verbose == BAD_VERBOSE)
1090                         return CMD_HELP;
1091         }
1092
1093         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1094         gettimeofday(&next_time, NULL);
1095         next_time.tv_sec -= verbose;
1096
1097         for (i = 1, next_count = verbose; i <= count; i++, id++) {
1098                 data.ioc_obdo1.o_id = id;
1099                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1100                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1101
1102                 IOC_PACK(argv[0], data);
1103                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1104                 IOC_UNPACK(argv[0], data);
1105                 SHMEM_BUMP();
1106                 if (rc < 0) {
1107                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1108                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1109                         break;
1110                 }
1111
1112                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1113                         printf("%s: #%d is object id "LPX64"\n",
1114                                jt_cmdname(argv[0]), i, id);
1115         }
1116
1117         return rc;
1118 }
1119
1120 int jt_obd_getattr(int argc, char **argv)
1121 {
1122         struct obd_ioctl_data data;
1123         char *end;
1124         int rc;
1125
1126         if (argc != 2)
1127                 return CMD_HELP;
1128
1129         IOC_INIT(data);
1130         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1131         if (*end) {
1132                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1133                         jt_cmdname(argv[0]), argv[1]);
1134                 return CMD_HELP;
1135         }
1136         /* to help obd filter */
1137         data.ioc_obdo1.o_mode = 0100644;
1138         data.ioc_obdo1.o_valid = 0xffffffff;
1139         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1140
1141         IOC_PACK(argv[0], data);
1142         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1143         IOC_UNPACK(argv[0], data);
1144         if (rc) {
1145                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1146                         strerror(rc = errno));
1147         } else {
1148                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1149                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1150         }
1151         return rc;
1152 }
1153
1154 int jt_obd_test_getattr(int argc, char **argv)
1155 {
1156         struct obd_ioctl_data data;
1157         struct timeval start, next_time;
1158         __u64 i, count, next_count;
1159         int verbose = 1;
1160         obd_id objid = 3;
1161         char *end;
1162         int rc = 0;
1163
1164         if (argc < 2 && argc > 4)
1165                 return CMD_HELP;
1166
1167         IOC_INIT(data);
1168         count = strtoull(argv[1], &end, 0);
1169         if (*end) {
1170                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1171                         jt_cmdname(argv[0]), argv[1]);
1172                 return CMD_HELP;
1173         }
1174
1175         if (argc >= 3) {
1176                 verbose = get_verbose(argv[0], argv[2]);
1177                 if (verbose == BAD_VERBOSE)
1178                         return CMD_HELP;
1179         }
1180
1181         if (argc >= 4) {
1182                 if (argv[3][0] == 't') {
1183                         objid = strtoull(argv[3] + 1, &end, 0);
1184                         if (thread)
1185                                 objid += thread - 1;
1186                 } else
1187                         objid = strtoull(argv[3], &end, 0);
1188                 if (*end) {
1189                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1190                                 jt_cmdname(argv[0]), argv[3]);
1191                         return CMD_HELP;
1192                 }
1193         }
1194
1195         gettimeofday(&start, NULL);
1196         next_time.tv_sec = start.tv_sec - verbose;
1197         next_time.tv_usec = start.tv_usec;
1198         if (verbose != 0)
1199                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1200                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1201
1202         for (i = 1, next_count = verbose; i <= count; i++) {
1203                 data.ioc_obdo1.o_id = objid;
1204                 data.ioc_obdo1.o_mode = S_IFREG;
1205                 data.ioc_obdo1.o_valid = 0xffffffff;
1206                 IOC_PACK(argv[0], data);
1207                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1208                 SHMEM_BUMP();
1209                 if (rc < 0) {
1210                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1211                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1212                         break;
1213                 } else {
1214                         if (be_verbose
1215                             (verbose, &next_time, i, &next_count, count))
1216                                 printf("%s: got attr #"LPD64"\n",
1217                                        jt_cmdname(argv[0]), i);
1218                 }
1219         }
1220
1221         if (!rc) {
1222                 struct timeval end;
1223                 double diff;
1224
1225                 gettimeofday(&end, NULL);
1226
1227                 diff = difftime(&end, &start);
1228
1229                 --i;
1230                 if (verbose != 0)
1231                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1232                                jt_cmdname(argv[0]), i, diff, i / diff,
1233                                ctime(&end.tv_sec));
1234         }
1235         return rc;
1236 }
1237
1238 int jt_obd_test_brw(int argc, char **argv)
1239 {
1240         struct obd_ioctl_data data;
1241         struct timeval start, next_time;
1242         __u64 count, next_count, len, thr_offset = 0, objid = 3;
1243         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1244         int repeat_offset = 0;
1245         char *end;
1246
1247         if (argc < 2 || argc > 7) {
1248                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1249                         jt_cmdname(argv[0]), argc);
1250                 return CMD_HELP;
1251         }
1252
1253         /* make each thread write to a different offset */
1254         if (argv[1][0] == 't') {
1255                 count = strtoull(argv[1] + 1, &end, 0);
1256                 if (thread)
1257                         thr_offset = thread - 1;
1258         } else
1259                 count = strtoull(argv[1], &end, 0);
1260
1261         if (*end) {
1262                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1263                         jt_cmdname(argv[0]), argv[1]);
1264                 return CMD_HELP;
1265         }
1266
1267         if (argc >= 3) {
1268                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1269                         write = 1;
1270                 /* else it's a read */
1271
1272                 if (argv[2][0] != 0 &&
1273                     argv[2][1] == 'r')
1274                         repeat_offset = 1;
1275         }
1276
1277         if (argc >= 4) {
1278                 verbose = get_verbose(argv[0], argv[3]);
1279                 if (verbose == BAD_VERBOSE)
1280                         return CMD_HELP;
1281         }
1282
1283         if (argc >= 5) {
1284                 pages = strtoul(argv[4], &end, 0);
1285                 if (*end) {
1286                         fprintf(stderr, "error: %s: bad page count '%s'\n",
1287                                 jt_cmdname(argv[0]), argv[4]);
1288                         return CMD_HELP;
1289                 }
1290         }
1291         if (argc >= 6) {
1292                 if (argv[5][0] == 't') {
1293                         objid = strtoull(argv[5] + 1, &end, 0);
1294                         if (thread)
1295                                 objid += thread - 1;
1296                 } else
1297                         objid = strtoull(argv[5], &end, 0);
1298                 if (*end) {
1299                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1300                                 jt_cmdname(argv[0]), argv[5]);
1301                         return CMD_HELP;
1302                 }
1303         }
1304
1305         IOC_INIT(data);
1306
1307         /* communicate the 'type' of brw test and batching to echo_client.
1308          * don't start.  we'd love to refactor this lctl->echo_client
1309          * interface */
1310         data.ioc_pbuf1 = (void *)1;
1311         data.ioc_plen1 = 1;
1312
1313         if (argc >= 7) {
1314                 switch(argv[6][0]) {
1315                         case 'g': /* plug and unplug */
1316                                 data.ioc_pbuf1 = (void *)2;
1317                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1318                                                           0);
1319                                 break;
1320                         case 'p': /* prep and commit */
1321                                 data.ioc_pbuf1 = (void *)3;
1322                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1323                                                           0);
1324                                 break;
1325                         default:
1326                                 fprintf(stderr, "error: %s: batching '%s' "
1327                                         "needs to specify 'p' or 'g'\n",
1328                                         jt_cmdname(argv[0]), argv[6]);
1329                                 return CMD_HELP;
1330                 }
1331
1332                 if (*end) {
1333                         fprintf(stderr, "error: %s: bad batching '%s'\n",
1334                                 jt_cmdname(argv[0]), argv[6]);
1335                         return CMD_HELP;
1336                 }
1337                 data.ioc_plen1 *= PAGE_SIZE;
1338         }
1339
1340         len = pages * PAGE_SIZE;
1341
1342         data.ioc_obdo1.o_id = objid;
1343         data.ioc_obdo1.o_mode = S_IFREG;
1344         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1345         data.ioc_count = len;
1346         data.ioc_offset = thr_offset * len * count;
1347
1348         gettimeofday(&start, NULL);
1349         next_time.tv_sec = start.tv_sec - verbose;
1350         next_time.tv_usec = start.tv_usec;
1351
1352         if (verbose != 0)
1353                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1354                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
1355                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1356
1357         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1358         for (i = 1, next_count = verbose; i <= count; i++) {
1359                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
1360                 IOC_PACK(argv[0], data);
1361                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
1362                 SHMEM_BUMP();
1363                 if (rc) {
1364                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1365                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
1366                                 write ? "write" : "read");
1367                         break;
1368                 } else if (be_verbose(verbose, &next_time,i, &next_count,count))
1369                         printf("%s: %s number %dx%d\n", jt_cmdname(argv[0]),
1370                                write ? "write" : "read", i, pages);
1371
1372                 if (!repeat_offset)
1373                         data.ioc_offset += len;
1374         }
1375
1376         if (!rc) {
1377                 struct timeval end;
1378                 double diff;
1379
1380                 gettimeofday(&end, NULL);
1381
1382                 diff = difftime(&end, &start);
1383
1384                 --i;
1385                 if (verbose != 0)
1386                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
1387                                jt_cmdname(argv[0]), write ? "wrote" : "read",
1388                                i, pages, diff,
1389                                ((double)i * pages * getpagesize()) /
1390                                (diff * 1048576.0),
1391                                ctime(&end.tv_sec));
1392         }
1393
1394         return rc;
1395 }
1396
1397 int jt_obd_lov_getconfig(int argc, char **argv)
1398 {
1399         struct obd_ioctl_data data;
1400         struct lov_desc desc;
1401         struct obd_uuid *uuidarray;
1402         char *path;
1403         int rc, fd;
1404
1405         IOC_INIT(data);
1406
1407         if (argc != 2)
1408                 return CMD_HELP;
1409
1410         path = argv[1];
1411         fd = open(path, O_RDONLY);
1412         if (fd < 0) {
1413                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1414                         strerror(errno));
1415                 return -1;
1416         }
1417
1418         memset(&desc, 0, sizeof(desc));
1419         obd_str2uuid(&desc.ld_uuid, argv[1]);
1420         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
1421                              sizeof(*uuidarray));
1422
1423 repeat:
1424         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1425         if (!uuidarray) {
1426                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1427                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1428                 rc = -ENOMEM;
1429                 goto out;
1430         }
1431
1432         data.ioc_inllen1 = sizeof(desc);
1433         data.ioc_inlbuf1 = (char *)&desc;
1434         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1435         data.ioc_inlbuf2 = (char *)uuidarray;
1436
1437         if (obd_ioctl_pack(&data, &buf, max)) {
1438                 fprintf(stderr, "error: %s: invalid ioctl\n",
1439                         jt_cmdname(argv[0]));
1440                 rc = -EINVAL;
1441                 goto out;
1442         }
1443         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1444         if (rc == -ENOSPC) {
1445                 free(uuidarray);
1446                 goto repeat;
1447         } else if (rc) {
1448                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1449                         jt_cmdname(argv[0]), strerror(rc = errno));
1450         } else {
1451                 struct obd_uuid *ptr;
1452                 int i;
1453
1454                 if (obd_ioctl_unpack(&data, buf, max)) {
1455                         fprintf(stderr, "error: %s: invalid reply\n",
1456                                 jt_cmdname(argv[0]));
1457                         rc = -EINVAL;
1458                         goto out;
1459                 }
1460                 printf("default_stripe_count: %u\n",
1461                        desc.ld_default_stripe_count);
1462                 printf("default_stripe_size: "LPU64"\n",
1463                        desc.ld_default_stripe_size);
1464                 printf("default_stripe_offset: "LPU64"\n",
1465                        desc.ld_default_stripe_offset);
1466                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1467                 printf("obd_count: %u\n", desc.ld_tgt_count);
1468                 for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
1469                         printf("%u: %s\n", i, (char *)ptr);
1470         }
1471 out:
1472         free(uuidarray);
1473         close(fd);
1474         return rc;
1475 }
1476
1477 int jt_obd_test_ldlm(int argc, char **argv)
1478 {
1479         struct obd_ioctl_data data;
1480         int rc;
1481
1482         IOC_INIT(data);
1483         if (argc != 1)
1484                 return CMD_HELP;
1485
1486         IOC_PACK(argv[0], data);
1487         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_TEST, buf);
1488         if (rc)
1489                 fprintf(stderr, "error: %s: test failed: %s\n",
1490                         jt_cmdname(argv[0]), strerror(rc = errno));
1491         return rc;
1492 }
1493
1494 int jt_obd_dump_ldlm(int argc, char **argv)
1495 {
1496         struct obd_ioctl_data data;
1497         int rc;
1498
1499         IOC_INIT(data);
1500         if (argc != 1)
1501                 return CMD_HELP;
1502
1503         IOC_PACK(argv[0], data);
1504         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf);
1505         if (rc)
1506                 fprintf(stderr, "error: %s failed: %s\n",
1507                         jt_cmdname(argv[0]), strerror(rc = errno));
1508         return rc;
1509 }
1510
1511 int jt_obd_ldlm_regress_start(int argc, char **argv)
1512 {
1513         int rc;
1514         struct obd_ioctl_data data;
1515         char argstring[200];
1516         int i, count = sizeof(argstring) - 1;
1517
1518         IOC_INIT(data);
1519         if (argc > 5)
1520                 return CMD_HELP;
1521
1522         argstring[0] = '\0';
1523         for (i = 1; i < argc; i++) {
1524                 strncat(argstring, " ", count);
1525                 count--;
1526                 strncat(argstring, argv[i], count);
1527                 count -= strlen(argv[i]);
1528         }
1529
1530         if (strlen(argstring)) {
1531                 data.ioc_inlbuf1 = argstring;
1532                 data.ioc_inllen1 = strlen(argstring) + 1;
1533         }
1534
1535         IOC_PACK(argv[0], data);
1536         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1537         if (rc)
1538                 fprintf(stderr, "error: %s: test failed: %s\n",
1539                         jt_cmdname(argv[0]), strerror(rc = errno));
1540
1541         return rc;
1542 }
1543
1544 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1545 {
1546         int rc;
1547         struct obd_ioctl_data data;
1548         IOC_INIT(data);
1549
1550         if (argc != 1)
1551                 return CMD_HELP;
1552
1553         IOC_PACK(argv[0], data);
1554         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1555
1556         if (rc)
1557                 fprintf(stderr, "error: %s: test failed: %s\n",
1558                         jt_cmdname(argv[0]), strerror(rc = errno));
1559         return rc;
1560 }
1561
1562 static int do_activate(int argc, char **argv, int flag)
1563 {
1564         struct obd_ioctl_data data;
1565         int rc;
1566
1567         IOC_INIT(data);
1568         if (argc != 1)
1569                 return CMD_HELP;
1570
1571         /* reuse offset for 'active' */
1572         data.ioc_offset = flag;
1573
1574         IOC_PACK(argv[0], data);
1575         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1576         if (rc)
1577                 fprintf(stderr, "error: %s: failed: %s\n",
1578                         jt_cmdname(argv[0]), strerror(rc = errno));
1579
1580         return rc;
1581 }
1582
1583 int jt_obd_deactivate(int argc, char **argv)
1584 {
1585         return do_activate(argc, argv, 0);
1586 }
1587
1588 int jt_obd_activate(int argc, char **argv)
1589 {
1590         return do_activate(argc, argv, 1);
1591 }
1592
1593 int jt_obd_recover(int argc, char **argv)
1594 {
1595         int rc;
1596         struct obd_ioctl_data data;
1597
1598         IOC_INIT(data);
1599         if (argc > 2)
1600                 return CMD_HELP;
1601
1602         if (argc == 2) {
1603                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1604                 data.ioc_inlbuf1 = argv[1];
1605         }
1606
1607         IOC_PACK(argv[0], data);
1608         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1609         if (rc < 0) {
1610                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1611                         strerror(rc = errno));
1612         }
1613
1614         return rc;
1615 }
1616
1617 int jt_obd_mdc_lookup(int argc, char **argv)
1618 {
1619         struct obd_ioctl_data data;
1620         char *parent, *child;
1621         int rc, fd, verbose = 1;
1622
1623         if (argc < 3 || argc > 4)
1624                 return CMD_HELP;
1625
1626         parent = argv[1];
1627         child = argv[2];
1628         if (argc == 4)
1629                 verbose = get_verbose(argv[0], argv[3]);
1630
1631         IOC_INIT(data);
1632
1633         data.ioc_inllen1 = strlen(child) + 1;
1634         data.ioc_inlbuf1 = child;
1635
1636         IOC_PACK(argv[0], data);
1637
1638         fd = open(parent, O_RDONLY);
1639         if (fd < 0) {
1640                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1641                         strerror(errno));
1642                 return -1;
1643         }
1644
1645         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1646         if (rc < 0) {
1647                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1648                         jt_cmdname(argv[0]), strerror(rc = errno));
1649         }
1650         close(fd);
1651
1652         if (verbose) {
1653                 IOC_UNPACK(argv[0], data);
1654                 printf("%s: mode %o uid %d gid %d\n", child,
1655                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
1656                        data.ioc_obdo1.o_gid);
1657         }
1658
1659         return rc;
1660 }
1661
1662
1663 int jt_obd_close_uuid(int argc, char **argv)
1664 {
1665         int rc, nal;
1666         struct obd_ioctl_data data;
1667
1668         if (argc != 3) {
1669                 fprintf(stderr, "usage: %s <uuid> <net-type>\n", argv[0]);
1670                 return 0;
1671         }
1672
1673         nal = ptl_name2nal(argv[2]);
1674
1675         if (nal <= 0) {
1676                 fprintf (stderr, "Can't parse NAL %s\n", argv[2]);
1677                 return -1;
1678         }
1679
1680         IOC_INIT(data);
1681         data.ioc_inllen1 = strlen(argv[1]) + 1;
1682         data.ioc_inlbuf1 = argv[1];
1683         data.ioc_nal = nal;
1684
1685         IOC_PACK(argv[0], data);
1686         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf);
1687         if (rc) {
1688                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
1689                         strerror(errno));
1690                 return -1;
1691         }
1692         return 0;
1693 }
1694
1695
1696 int jt_cfg_record(int argc, char **argv)
1697 {
1698         struct obd_ioctl_data data;
1699         int rc;
1700
1701         IOC_INIT(data);
1702
1703         if (argc != 2)
1704                 return CMD_HELP;
1705
1706         data.ioc_inllen1 = strlen(argv[1]) + 1;
1707         data.ioc_inlbuf1 = argv[1];
1708
1709         IOC_PACK(argv[0], data);
1710         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_RECORD, buf);
1711         if (rc == 0) {
1712                 jt_recording = 1;
1713                 ptl_set_cfg_record_cb(obd_record);
1714         } else {
1715                 fprintf(stderr, "OBD_IOC_RECORD failed: %s\n",
1716                         strerror(errno));
1717         }
1718
1719         return rc;
1720 }
1721
1722 int jt_cfg_parse(int argc, char **argv)
1723 {
1724         struct obd_ioctl_data data;
1725         int rc;
1726
1727         IOC_INIT(data);
1728
1729         if (argc != 2)
1730                 return CMD_HELP;
1731
1732         data.ioc_inllen1 = strlen(argv[1]) + 1;
1733         data.ioc_inlbuf1 = argv[1];
1734
1735         IOC_PACK(argv[0], data);
1736         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PARSE, buf);
1737         if (rc < 0)
1738                 fprintf(stderr, "OBD_IOC_PARSE failed: %s\n",
1739                         strerror(errno));
1740
1741         return rc;
1742 }
1743
1744
1745 int jt_cfg_dump_log(int argc, char **argv)
1746 {
1747         struct obd_ioctl_data data;
1748         int rc;
1749
1750         IOC_INIT(data);
1751
1752         if (argc != 2)
1753                 return CMD_HELP;
1754
1755         data.ioc_inllen1 = strlen(argv[1]) + 1;
1756         data.ioc_inlbuf1 = argv[1];
1757
1758         IOC_PACK(argv[0], data);
1759         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
1760         if (rc < 0)
1761                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
1762                         strerror(errno));
1763
1764         return rc;
1765 }
1766
1767 int jt_cfg_clear_log(int argc, char **argv)
1768 {
1769         struct obd_ioctl_data data;
1770         int rc;
1771
1772         IOC_INIT(data);
1773
1774         if (argc != 2)
1775                 return CMD_HELP;
1776
1777         data.ioc_inllen1 = strlen(argv[1]) + 1;
1778         data.ioc_inlbuf1 = argv[1];
1779
1780         IOC_PACK(argv[0], data);
1781         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLEAR_LOG, buf);
1782         if (rc < 0)
1783                 fprintf(stderr, "OBD_IOC_CLEAR_LOG failed: %s\n",
1784                         strerror(errno));
1785
1786         return rc;
1787 }
1788
1789
1790
1791 int jt_cfg_endrecord(int argc, char **argv)
1792 {
1793         struct obd_ioctl_data data;
1794         int rc;
1795
1796         IOC_INIT(data);
1797
1798         if (argc != 1)
1799                 return CMD_HELP;
1800
1801         if (!jt_recording) {
1802                 fprintf(stderr, "Not recording, so endrecord doesn't make sense.\n");
1803                 return 0;
1804         }
1805
1806         IOC_PACK(argv[0], data);
1807         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ENDRECORD, buf);
1808         if (rc == 0) {
1809                 jt_recording = 0;
1810                 ptl_set_cfg_record_cb(NULL);
1811         } else {
1812                 fprintf(stderr, "OBD_IOC_ENDRECORD failed: %s\n",
1813                         strerror(errno));
1814         }
1815         return rc;
1816 }
1817
1818 int jt_llog_catlist(int argc, char **argv)
1819 {
1820         struct obd_ioctl_data data;
1821         int rc;
1822
1823         if (argc != 1)
1824                 return CMD_HELP;
1825
1826         IOC_INIT(data);
1827         data.ioc_inllen1 = max - size_round(sizeof(data));
1828         IOC_PACK(argv[0], data);
1829         
1830         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
1831         if (rc == 0) 
1832                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1833         else
1834                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n", 
1835                         strerror(errno));
1836         
1837         return rc;
1838 }
1839
1840 int jt_llog_info(int argc, char **argv)
1841 {
1842         struct obd_ioctl_data data;
1843         int rc;
1844
1845         if (argc != 2)
1846                 return CMD_HELP;
1847
1848         IOC_INIT(data);
1849         data.ioc_inllen1 = strlen(argv[1]) + 1;
1850         data.ioc_inlbuf1 = argv[1];
1851         data.ioc_inllen2 = max - size_round(sizeof(data)) - 
1852                 size_round(data.ioc_inllen1);
1853         IOC_PACK(argv[0], data);
1854
1855         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
1856         if (rc == 0)
1857                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1858         else
1859                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
1860                         strerror(errno));
1861
1862         return rc;
1863 }
1864
1865 int jt_llog_print(int argc, char **argv)
1866 {
1867         struct obd_ioctl_data data;
1868         int rc;
1869
1870         if (argc != 2 && argc != 4)
1871                 return CMD_HELP;
1872
1873         IOC_INIT(data);
1874         data.ioc_inllen1 = strlen(argv[1]) + 1;
1875         data.ioc_inlbuf1 = argv[1];
1876         if (argc == 4) {
1877                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1878                 data.ioc_inlbuf2 = argv[2];
1879                 data.ioc_inllen3 = strlen(argv[3]) + 1;
1880                 data.ioc_inlbuf3 = argv[3];
1881         } else {
1882                 char from[2] = "1", to[3] = "-1";
1883                 data.ioc_inllen2 = strlen(from) + 1;
1884                 data.ioc_inlbuf2 = from;
1885                 data.ioc_inllen3 = strlen(to) + 1;
1886                 data.ioc_inlbuf3 = to;
1887         }
1888         data.ioc_inllen4 = max - size_round(sizeof(data)) -
1889                 size_round(data.ioc_inllen1) -
1890                 size_round(data.ioc_inllen2) -
1891                 size_round(data.ioc_inllen3);
1892         IOC_PACK(argv[0], data);
1893
1894         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
1895         if (rc == 0)
1896                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1897         else
1898                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
1899                         strerror(errno));
1900
1901         return rc;
1902 }
1903
1904 int jt_llog_cancel(int argc, char **argv)
1905 {
1906         struct obd_ioctl_data data;
1907         int rc;
1908
1909         if (argc != 4)
1910                 return CMD_HELP;
1911
1912         IOC_INIT(data);
1913         data.ioc_inllen1 = strlen(argv[1]) + 1;
1914         data.ioc_inlbuf1 = argv[1];
1915         data.ioc_inllen2 = strlen(argv[2]) + 1;
1916         data.ioc_inlbuf2 = argv[2];
1917         data.ioc_inllen3 = strlen(argv[3]) + 1;
1918         data.ioc_inlbuf3 = argv[3];
1919         IOC_PACK(argv[0], data);
1920
1921         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
1922         if (rc == 0)
1923                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
1924         else
1925                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
1926                         strerror(errno));
1927
1928         return rc;
1929
1930 }
1931 int jt_llog_check(int argc, char **argv)
1932 {
1933         struct obd_ioctl_data data;
1934         int rc;
1935
1936         if (argc != 2 && argc != 4)
1937                 return CMD_HELP;
1938
1939         IOC_INIT(data);
1940         data.ioc_inllen1 = strlen(argv[1]) + 1;
1941         data.ioc_inlbuf1 = argv[1];
1942         if (argc == 4) {
1943                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1944                 data.ioc_inlbuf2 = argv[2];
1945                 data.ioc_inllen3 = strlen(argv[3]) + 1;
1946                 data.ioc_inlbuf3 = argv[3];
1947         } else {
1948                 char from[2] = "1", to[3] = "-1";
1949                 data.ioc_inllen2 = strlen(from) + 1;
1950                 data.ioc_inlbuf2 = from;
1951                 data.ioc_inllen3 = strlen(to) + 1;
1952                 data.ioc_inlbuf3 = to;
1953         }
1954         data.ioc_inllen4 = max - size_round(sizeof(data)) -
1955                 size_round(data.ioc_inllen1) -
1956                 size_round(data.ioc_inllen2) -
1957                 size_round(data.ioc_inllen3);
1958         IOC_PACK(argv[0], data);
1959
1960         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
1961         if (rc == 0)
1962                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
1963         else
1964                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
1965                         strerror(errno));
1966         return rc;
1967 }
1968
1969 int jt_llog_remove(int argc, char **argv)
1970 {
1971         struct obd_ioctl_data data;
1972         int rc;
1973
1974         if (argc != 3 && argc != 2)
1975                 return CMD_HELP;
1976
1977         IOC_INIT(data);
1978         data.ioc_inllen1 = strlen(argv[1]) + 1;
1979         data.ioc_inlbuf1 = argv[1];
1980         if (argc == 3){
1981                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1982                 data.ioc_inlbuf2 = argv[2];
1983         }
1984         IOC_PACK(argv[0], data);
1985
1986         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
1987         if (rc == 0) {
1988                 if (argc == 3)
1989                         fprintf(stdout, "log %s are removed.\n", argv[2]);
1990                 else
1991                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
1992         } else
1993                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
1994                         strerror(errno));
1995
1996         return rc;
1997 }
1998
1999 static void signal_server(int sig)
2000 {
2001         if (sig == SIGINT) {
2002                 do_disconnect("sigint", 1);
2003                 exit(1);
2004         } else
2005                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2006 }
2007
2008 int obd_initialize(int argc, char **argv)
2009 {
2010         SHMEM_SETUP();
2011         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH);
2012
2013         return 0;
2014 }
2015
2016
2017 void obd_finalize(int argc, char **argv)
2018 {
2019         struct sigaction sigact;
2020
2021         sigact.sa_handler = signal_server;
2022         sigfillset(&sigact.sa_mask);
2023         sigact.sa_flags = SA_RESTART;
2024         sigaction(SIGINT, &sigact, NULL);
2025
2026         if (jt_recording) {
2027                 printf("END RECORD\n");
2028                 jt_cfg_endrecord(argc, argv);
2029         }
2030
2031         do_disconnect(argv[0], 1);
2032 }