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