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