Whamcloud - gitweb
Merge of b_md to HEAD:
[fs/lustre-release.git] / lustre / utils / obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Andreas Dilger <adilger@clusterfs.com>
8  *   Author: Robert Read <rread@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28 #include <stdlib.h>
29 #include <sys/ioctl.h>
30 #include <fcntl.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/stat.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <signal.h>
38 #define printk printf
39
40 #include <linux/lustre_lib.h>
41 #include <linux/lustre_idl.h>
42 #include <linux/lustre_dlm.h>
43 #include <linux/obd_lov.h>      /* for IOC_LOV_SET_OSC_ACTIVE */
44 #include <linux/obd.h>          /* for struct lov_stripe_md */
45 #include <linux/lustre_build_version.h>
46
47 #include <unistd.h>
48 #include <sys/un.h>
49 #include <time.h>
50 #include <sys/time.h>
51 #include <netinet/in.h>
52 #include <errno.h>
53 #include <string.h>
54
55 #include <asm/page.h>           /* needed for PAGE_SIZE - rread */
56
57 #define __KERNEL__
58 #include <linux/list.h>
59 #undef __KERNEL__
60
61 #include "obdctl.h"
62 #include "parser.h"
63 #include <stdio.h>
64
65 #define SHMEM_STATS 1
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 int fd = -1;
77 uint64_t conn_addr = -1;
78 uint64_t conn_cookie;
79 char rawbuf[8192];
80 char *buf = rawbuf;
81 int max = sizeof(rawbuf);
82
83 static int thread;
84 static struct lov_stripe_md saved_lsm;
85 static char lsm_valid = 0;
86
87 static int getfd(char *func);
88 static char *cmdname(char *func);
89
90 #define IOCINIT(data)                                                   \
91 do {                                                                    \
92         memset(&data, 0, sizeof(data));                                 \
93         data.ioc_version = OBD_IOCTL_VERSION;                           \
94         data.ioc_addr = conn_addr;                                      \
95         data.ioc_cookie = conn_cookie;                                  \
96         data.ioc_len = sizeof(data);                                    \
97         if (fd < 0) {                                                   \
98                 fprintf(stderr, "No device open, use device\n");        \
99                 return 1;                                               \
100         }                                                               \
101 } while (0)
102
103 #define IOC_PACK(func, data)                                            \
104 do {                                                                    \
105         if (obd_ioctl_pack(&data, &buf, max)) {                         \
106                 fprintf(stderr, "error: %s: invalid ioctl\n",           \
107                         cmdname(func));                                 \
108                 return -2;                                              \
109         }                                                               \
110 } while (0)
111
112 #define IOC_UNPACK(func, data)                                          \
113 do {                                                                    \
114         if (obd_ioctl_unpack(&data, buf, max)) {                        \
115                 fprintf(stderr, "error: %s: invalid reply\n",           \
116                         cmdname(func));                                 \
117                 return -2;                                              \
118         }                                                               \
119 } while (0)
120
121 char *obdo_print(struct obdo *obd)
122 {
123         char buf[1024];
124
125         sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
126                 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
127                 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
128                 "obdflags: %x\nnlink: %d,\nvalid %x\n",
129                 obd->o_id, obd->o_gr, obd->o_atime, obd->o_mtime, obd->o_ctime,
130                 obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
131                 obd->o_uid, obd->o_gid, obd->o_flags, obd->o_obdflags,
132                 obd->o_nlink, obd->o_valid);
133         return strdup(buf);
134 }
135
136
137 #define BAD_VERBOSE (-999999999)
138
139 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
140
141 static int do_name2dev(char *func, char *name)
142 {
143         struct obd_ioctl_data data;
144         int rc;
145
146         if (getfd(func))
147                 return -1;
148
149         IOCINIT(data);
150
151         data.ioc_inllen1 = strlen(name) + 1;
152         data.ioc_inlbuf1 = name;
153
154         IOC_PACK(func, data);
155         rc = ioctl(fd, OBD_IOC_NAME2DEV, buf);
156         if (rc < 0) {
157                 fprintf(stderr, "error: %s: %s - %s\n", cmdname(func),
158                         name, strerror(rc = errno));
159                 return rc;
160         }
161         IOC_UNPACK(func, data);
162
163         return data.ioc_dev + N2D_OFF;
164 }
165
166 /*
167  * resolve a device name to a device number.
168  * supports a number or name.
169  * FIXME: support UUID
170  */
171 static int parse_devname(char *func, char *name)
172 {
173         int rc;
174         int ret = -1;
175
176         if (!name)
177                 return ret;
178         if (name[0] == '$') {
179                 rc = do_name2dev(func, name + 1);
180                 if (rc >= N2D_OFF) {
181                         ret = rc - N2D_OFF;
182                         printf("%s is device %d\n", name, ret);
183                 } else {
184                         fprintf(stderr, "error: %s: %s: %s\n", cmdname(func),
185                                 name, "device not found");
186                 }
187         } else
188                 ret = strtoul(name, NULL, 0);
189
190         return ret;
191 }
192
193 static char *cmdname(char *func)
194 {
195         static char buf[512];
196
197         if (thread) {
198                 sprintf(buf, "%s-%d", func, thread);
199                 return buf;
200         }
201
202         return func;
203 }
204
205 static int getfd(char *func)
206 {
207         if (fd == -1)
208                 fd = open("/dev/obd", O_RDWR);
209         if (fd == -1) {
210                 fprintf(stderr, "error: %s: opening /dev/obd: %s\n"
211                         "hint: lustre kernel modules may not be loaded.\n",
212                         cmdname(func), strerror(errno));
213                 return -1;
214         }
215         return 0;
216 }
217
218 #define difftime(a, b)                                          \
219         ((double)(a)->tv_sec - (b)->tv_sec +                    \
220          ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
221
222 static int be_verbose(int verbose, struct timeval *next_time,
223                       __u64 num, __u64 *next_num, int num_total)
224 {
225         struct timeval now;
226
227         if (!verbose)
228                 return 0;
229
230         if (next_time != NULL)
231                 gettimeofday(&now, NULL);
232
233         /* A positive verbosity means to print every X iterations */
234         if (verbose > 0 &&
235             (next_num == NULL || num >= *next_num || num >= num_total)) {
236                 *next_num += verbose;
237                 if (next_time) {
238                         next_time->tv_sec = now.tv_sec - verbose;
239                         next_time->tv_usec = now.tv_usec;
240                 }
241                 return 1;
242         }
243
244         /* A negative verbosity means to print at most each X seconds */
245         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
246                 next_time->tv_sec = now.tv_sec - verbose;
247                 next_time->tv_usec = now.tv_usec;
248                 if (next_num)
249                         *next_num = num;
250                 return 1;
251         }
252
253         return 0;
254 }
255
256 static int get_verbose(char *func, const char *arg)
257 {
258         int verbose;
259         char *end;
260
261         if (!arg || arg[0] == 'v')
262                 verbose = 1;
263         else if (arg[0] == 's' || arg[0] == 'q')
264                 verbose = 0;
265         else {
266                 verbose = (int)strtoul(arg, &end, 0);
267                 if (*end) {
268                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
269                                 cmdname(func), arg);
270                         return BAD_VERBOSE;
271                 }
272         }
273
274         if (verbose < 0)
275                 printf("Print status every %d seconds\n", -verbose);
276         else if (verbose == 1)
277                 printf("Print status every operation\n");
278         else if (verbose > 1)
279                 printf("Print status every %d operations\n", verbose);
280
281         return verbose;
282 }
283
284 int do_disconnect(char *func, int verbose)
285 {
286         int rc;
287         struct obd_ioctl_data data;
288
289         if (conn_addr == -1)
290                 return 0;
291
292         IOCINIT(data);
293
294         rc = ioctl(fd, OBD_IOC_DISCONNECT, &data);
295         if (rc < 0) {
296                 fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
297                         OBD_IOC_DISCONNECT, strerror(errno));
298         } else {
299                 if (verbose)
300                         printf("%s: disconnected conn "LPX64"\n", cmdname(func),
301                                conn_addr);
302                 conn_addr = -1;
303         }
304
305         return rc;
306 }
307
308 #if SHMEM_STATS
309 static void shmem_setup(void)
310 {
311         /* Create new segment */
312         int shmid = shmget(IPC_PRIVATE, sizeof(counter_snapshot[0]), 0600);
313
314         if (shmid == -1) {
315                 fprintf(stderr, "Can't create shared memory counters: %s\n",
316                         strerror(errno));
317                 return;
318         }
319
320         /* Attatch to new segment */
321         shared_counters = (long long *)shmat(shmid, NULL, 0);
322
323         if (shared_counters == (long long *)(-1)) {
324                 fprintf(stderr, "Can't attach shared memory counters: %s\n",
325                         strerror(errno));
326                 shared_counters = NULL;
327                 return;
328         }
329
330         /* Mark segment as destroyed, so it will disappear when we exit.
331          * Forks will inherit attached segments, so we should be OK.
332          */
333         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
334                 fprintf(stderr, "Can't destroy shared memory counters: %s\n",
335                         strerror(errno));
336         }
337 }
338
339 static inline void shmem_reset(void)
340 {
341         if (shared_counters == NULL)
342                 return;
343
344         memset(shared_counters, 0, sizeof(counter_snapshot[0]));
345         memset(counter_snapshot, 0, sizeof(counter_snapshot));
346         gettimeofday(&prev_time, NULL);
347 }
348
349 static inline void shmem_bump(void)
350 {
351         if (shared_counters == NULL || thread <= 0 || thread > MAX_SHMEM_COUNT)
352                 return;
353
354         shared_counters[thread - 1]++;
355 }
356
357 static void shmem_snap(int n)
358 {
359         struct timeval this_time;
360         int non_zero = 0;
361         long long total = 0;
362         double secs;
363         int i;
364
365         if (shared_counters == NULL || n > MAX_SHMEM_COUNT)
366                 return;
367
368         memcpy(counter_snapshot[1], counter_snapshot[0],
369                n * sizeof(counter_snapshot[0][0]));
370         memcpy(counter_snapshot[0], shared_counters,
371                n * sizeof(counter_snapshot[0][0]));
372         gettimeofday(&this_time, NULL);
373
374         for (i = 0; i < n; i++) {
375                 long long this_count =
376                         counter_snapshot[0][i] - counter_snapshot[1][i];
377
378                 if (this_count != 0) {
379                         non_zero++;
380                         total += this_count;
381                 }
382         }
383
384         secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
385                 (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
386
387         printf("%d/%d Total: %f/second\n", non_zero, n, total / secs);
388
389         prev_time = this_time;
390 }
391
392 #define SHMEM_SETUP()   shmem_setup()
393 #define SHMEM_RESET()   shmem_reset()
394 #define SHMEM_BUMP()    shmem_bump()
395 #define SHMEM_SNAP(n)   shmem_snap(n)
396 #else
397 #define SHMEM_SETUP()
398 #define SHMEM_RESET()
399 #define SHMEM_BUMP()
400 #define SHMEM_SNAP(n)
401 #endif
402
403 extern command_t cmdlist[];
404
405 static int do_device(char *func, int dev)
406 {
407         struct obd_ioctl_data data;
408
409         memset(&data, 0, sizeof(data));
410
411         data.ioc_dev = dev;
412
413         if (getfd(func))
414                 return -1;
415
416         IOC_PACK(func, data);
417         return ioctl(fd, OBD_IOC_DEVICE, buf);
418 }
419
420 int jt_obd_device(int argc, char **argv)
421 {
422         int rc, dev;
423         do_disconnect(argv[0], 1);
424
425         if (argc != 2)
426                 return CMD_HELP;
427
428         dev = parse_devname(argv[0], argv[1]);
429         if (dev < 0)
430                 return -1;
431
432         rc = do_device(argv[0], dev);
433         if (rc < 0)
434                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
435                         strerror(rc = errno));
436
437         return rc;
438 }
439
440 int jt_obd_connect(int argc, char **argv)
441 {
442         struct obd_ioctl_data data;
443         int rc;
444
445         IOCINIT(data);
446
447         do_disconnect(argv[0], 1);
448
449 #warning TODO: implement timeout per lctl usage for probe
450         if (argc != 1)
451                 return CMD_HELP;
452
453         rc = ioctl(fd, OBD_IOC_CONNECT, &data);
454         if (rc < 0)
455                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
456                         OBD_IOC_CONNECT, strerror(rc = errno));
457         else {
458                 conn_addr = data.ioc_addr;
459                 conn_cookie = data.ioc_cookie;
460         }
461         return rc;
462 }
463
464 int jt_obd_disconnect(int argc, char **argv)
465 {
466         if (argc != 1)
467                 return CMD_HELP;
468
469         if (conn_addr == -1)
470                 return 0;
471
472         return do_disconnect(argv[0], 0);
473 }
474
475 int jt_opt_device(int argc, char **argv)
476 {
477         char *arg2[3];
478         int ret;
479         int rc;
480
481         if (argc < 3)
482                 return CMD_HELP;
483
484         rc = do_device("device", parse_devname(argv[0], argv[1]));
485
486         if (!rc) {
487                 arg2[0] = "connect";
488                 arg2[1] = NULL;
489                 rc = jt_obd_connect(1, arg2);
490         }
491
492         if (!rc)
493                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
494
495         ret = do_disconnect(argv[0], 0);
496         if (!rc)
497                 rc = ret;
498
499         return rc;
500 }
501
502 int jt_opt_threads(int argc, char **argv)
503 {
504         __u64 threads, next_thread;
505         int verbose;
506         int rc = 0;
507         char *end;
508         int i;
509
510         if (argc < 5)
511                 return CMD_HELP;
512
513         threads = strtoull(argv[1], &end, 0);
514         if (*end) {
515                 fprintf(stderr, "error: %s: invalid page count '%s'\n",
516                         cmdname(argv[0]), argv[1]);
517                 return CMD_HELP;
518         }
519
520         verbose = get_verbose(argv[0], argv[2]);
521         if (verbose == BAD_VERBOSE)
522                 return CMD_HELP;
523
524         if (verbose != 0)
525                 printf("%s: starting "LPD64" threads on device %s running %s\n",
526                        argv[0], threads, argv[3], argv[4]);
527
528         SHMEM_RESET();
529
530         for (i = 1, next_thread = verbose; i <= threads; i++) {
531                 rc = fork();
532                 if (rc < 0) {
533                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
534                                 strerror(rc = errno));
535                         break;
536                 } else if (rc == 0) {
537                         thread = i;
538                         argv[2] = "--device";
539                         return jt_opt_device(argc - 2, argv + 2);
540                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
541                         printf("%s: thread #%d (PID %d) started\n",
542                                argv[0], i, rc);
543                 rc = 0;
544         }
545
546         if (!thread) {          /* parent process */
547                 int live_threads = threads;
548
549                 while (live_threads > 0) {
550                         int status;
551                         pid_t ret;
552
553                         ret = waitpid(0, &status, verbose < 0 ? WNOHANG : 0);
554                         if (ret == 0) {
555                                 if (verbose >= 0)
556                                         abort();
557
558                                 sleep(-verbose);
559                                 SHMEM_SNAP(threads);
560                                 continue;
561                         }
562
563                         if (ret < 0) {
564                                 fprintf(stderr, "error: %s: wait - %s\n",
565                                         argv[0], strerror(errno));
566                                 if (!rc)
567                                         rc = errno;
568                         } else {
569                                 /*
570                                  * This is a hack.  We _should_ be able to use
571                                  * WIFEXITED(status) to see if there was an
572                                  * error, but it appears to be broken and it
573                                  * always returns 1 (OK).  See wait(2).
574                                  */
575                                 int err = WEXITSTATUS(status);
576                                 if (err || WIFSIGNALED(status))
577                                         fprintf(stderr,
578                                                 "%s: PID %d had rc=%d\n",
579                                                 argv[0], ret, err);
580                                 if (!rc)
581                                         rc = err;
582
583                                 live_threads--;
584                         }
585                 }
586         }
587
588         return rc;
589 }
590
591 int jt_obd_detach(int argc, char **argv)
592 {
593         struct obd_ioctl_data data;
594         char force = 'F';
595         int rc;
596
597         IOCINIT(data);
598
599         if (argc != 1 && argc != 2)
600                 return CMD_HELP;
601
602         if (argc == 2) {
603                 data.ioc_inllen1 = 1;
604                 data.ioc_inlbuf1 = &force;
605         }
606
607         IOC_PACK(argv[0], data);
608         rc = ioctl(fd, OBD_IOC_DETACH, buf);
609         if (rc < 0)
610                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
611                         strerror(rc = errno));
612
613         return rc;
614 }
615
616 int jt_obd_cleanup(int argc, char **argv)
617 {
618         struct obd_ioctl_data data;
619         int rc;
620
621         IOCINIT(data);
622
623         if (argc != 1)
624                 return CMD_HELP;
625
626         rc = ioctl(fd, OBD_IOC_CLEANUP, &data);
627         if (rc < 0)
628                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
629                         strerror(rc = errno));
630
631         return rc;
632 }
633
634 int jt_obd_newdev(int argc, char **argv)
635 {
636         int rc;
637         struct obd_ioctl_data data;
638
639         if (getfd(argv[0]))
640                 return -1;
641
642         IOCINIT(data);
643
644         if (argc != 1)
645                 return CMD_HELP;
646
647         rc = ioctl(fd, OBD_IOC_NEWDEV, &data);
648         if (rc < 0)
649                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
650                         strerror(rc = errno));
651         else {
652                 printf("Current device set to %d\n", data.ioc_dev);
653         }
654
655         return rc;
656 }
657
658 int jt_get_version(int argc, char **argv)
659 {
660         int rc;
661         char buf[8192];
662         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
663
664         if (getfd(argv[0]))
665                 return -1;
666
667         memset(buf, 0, sizeof(buf));
668         data->ioc_version = OBD_IOCTL_VERSION;
669         data->ioc_addr = conn_addr;
670         data->ioc_cookie = conn_addr;
671         data->ioc_len = sizeof(buf);
672         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
673
674         if (argc != 1)
675                 return CMD_HELP;
676
677         rc = ioctl(fd, OBD_GET_VERSION, data);
678         if (rc < 0)
679                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
680                         strerror(rc = errno));
681         else {
682                 printf("Lustre version: %s\n", data->ioc_bulk);
683         }
684         
685         printf("lctl version: %s\n",BUILD_VERSION);
686         return rc;
687 }
688
689 int jt_obd_list(int argc, char **argv)
690 {
691         int rc;
692         char buf[8192];
693         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
694
695         if (getfd(argv[0]))
696                 return -1;
697
698         memset(buf, 0, sizeof(buf));
699         data->ioc_version = OBD_IOCTL_VERSION;
700         data->ioc_addr = conn_addr;
701         data->ioc_cookie = conn_addr;
702         data->ioc_len = sizeof(buf);
703         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
704
705         if (argc != 1)
706                 return CMD_HELP;
707
708         rc = ioctl(fd, OBD_IOC_LIST, data);
709         if (rc < 0)
710                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
711                         strerror(rc = errno));
712         else {
713                 printf("%s", data->ioc_bulk);
714         }
715
716         return rc;
717 }
718
719 int jt_obd_attach(int argc, char **argv)
720 {
721         struct obd_ioctl_data data;
722         int rc;
723
724         IOCINIT(data);
725
726         if (argc != 2 && argc != 3 && argc != 4)
727                 return CMD_HELP;
728
729         data.ioc_inllen1 = strlen(argv[1]) + 1;
730         data.ioc_inlbuf1 = argv[1];
731         if (argc >= 3) {
732                 data.ioc_inllen2 = strlen(argv[2]) + 1;
733                 data.ioc_inlbuf2 = argv[2];
734         }
735
736         if (argc == 4) {
737                 data.ioc_inllen3 = strlen(argv[3]) + 1;
738                 data.ioc_inlbuf3 = argv[3];
739         }
740
741         IOC_PACK(argv[0], data);
742         rc = ioctl(fd, OBD_IOC_ATTACH, buf);
743         if (rc < 0)
744                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
745                         OBD_IOC_ATTACH, strerror(rc = errno));
746         else if (argc == 3) {
747                 char name[1024];
748                 if (strlen(argv[2]) > 128) {
749                         printf("Name too long to set environment\n");
750                         return -EINVAL;
751                 }
752                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
753                 rc = setenv(name, argv[1], 1);
754                 if (rc) {
755                         printf("error setting env variable %s\n", name);
756                 }
757         }
758
759         return rc;
760 }
761
762 int jt_obd_name2dev(int argc, char **argv)
763 {
764         int rc;
765
766         if (argc != 2)
767                 return CMD_HELP;
768
769         rc = do_name2dev(argv[0], argv[1]);
770         if (rc >= N2D_OFF) {
771                 int dev = rc - N2D_OFF;
772                 rc = do_device(argv[0], dev);
773                 if (rc == 0)
774                         printf("%d\n", dev);
775         }
776         return rc;
777 }
778
779 int jt_obd_setup(int argc, char **argv)
780 {
781         struct obd_ioctl_data data;
782         int rc;
783
784         IOCINIT(data);
785
786         if (argc > 3)
787                 return CMD_HELP;
788
789         data.ioc_dev = -1;
790         if (argc > 1) {
791                 data.ioc_dev = parse_devname(argv[0], argv[1]);
792                 if (data.ioc_dev < 0)
793                         return -1;
794                 data.ioc_inllen1 = strlen(argv[1]) + 1;
795                 data.ioc_inlbuf1 = argv[1];
796         }
797         if (argc == 3) {
798                 data.ioc_inllen2 = strlen(argv[2]) + 1;
799                 data.ioc_inlbuf2 = argv[2];
800         }
801
802         IOC_PACK(argv[0], data);
803         rc = ioctl(fd, OBD_IOC_SETUP, buf);
804         if (rc < 0)
805                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
806                         strerror(rc = errno));
807
808         return rc;
809 }
810
811 /* The ioctl API has been extended to provide the LOV stripe metadata to the
812  * caller when applicable.  This utility, however, only saves the LSM for the
813  * latest CREATE. */
814 int jt_obd_create(int argc, char **argv)
815 {
816         struct obd_ioctl_data data;
817         struct timeval next_time;
818         __u64 count = 1, next_count;
819         int verbose = 1, mode = 0100644, rc = 0, i;
820         char *end;
821
822         IOCINIT(data);
823         if (argc < 2 || argc > 4)
824                 return CMD_HELP;
825
826         count = strtoull(argv[1], &end, 0);
827         if (*end) {
828                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
829                         cmdname(argv[0]), argv[1]);
830                 return CMD_HELP;
831         }
832
833         if (argc > 2) {
834                 mode = strtoul(argv[2], &end, 0);
835                 if (*end) {
836                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
837                                 cmdname(argv[0]), argv[2]);
838                         return CMD_HELP;
839                 }
840                 if (!(mode & S_IFMT))
841                         mode |= S_IFREG;
842         }
843
844         if (argc > 3) {
845                 verbose = get_verbose(argv[0], argv[3]);
846                 if (verbose == BAD_VERBOSE)
847                         return CMD_HELP;
848         }
849
850         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
851         gettimeofday(&next_time, NULL);
852         next_time.tv_sec -= verbose;
853
854         for (i = 1, next_count = verbose; i <= count; i++) {
855                 data.ioc_obdo1.o_mode = mode;
856                 data.ioc_obdo1.o_id = i;
857                 data.ioc_obdo1.o_uid = 0;
858                 data.ioc_obdo1.o_gid = 0;
859                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
860                                 OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;;
861
862                 data.ioc_inllen1 = sizeof(saved_lsm);
863                 data.ioc_inlbuf1 = (char *)&saved_lsm;
864
865                 IOC_PACK(argv[0], data);
866                 rc = ioctl(fd, OBD_IOC_CREATE, buf);
867                 IOC_UNPACK(argv[0], data);
868                 fprintf(stderr, "lsm->lsm_o_id: "LPX64"\n",
869                         saved_lsm.lsm_object_id);
870                 SHMEM_BUMP();
871                 if (rc < 0) {
872                         fprintf(stderr, "error: %s: #%d - %s\n",
873                                 cmdname(argv[0]), i, strerror(rc = errno));
874                         break;
875                 }
876                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
877                         fprintf(stderr, "error: %s: objid not valid #%d:%08x\n",
878                                 cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
879                         rc = EINVAL;
880                         break;
881                 }
882
883                 lsm_valid = 1;
884
885                 if (be_verbose(verbose, &next_time, i, &next_count, count))
886                         printf("%s: #%d is object id "LPX64"\n",
887                                cmdname(argv[0]), i, data.ioc_obdo1.o_id);
888         }
889         return rc;
890 }
891
892 int jt_obd_setattr(int argc, char **argv)
893 {
894         struct obd_ioctl_data data;
895         char *end;
896         int rc;
897
898         IOCINIT(data);
899         if (argc != 2)
900                 return CMD_HELP;
901
902         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
903         if (*end) {
904                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
905                         cmdname(argv[0]), argv[1]);
906                 return CMD_HELP;
907         }
908         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
909         if (*end) {
910                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
911                         cmdname(argv[0]), argv[2]);
912                 return CMD_HELP;
913         }
914         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
915
916         if (lsm_valid == 1) {
917                 data.ioc_inllen1 = sizeof(saved_lsm);
918                 data.ioc_inlbuf1 = (char *)&saved_lsm;
919         }
920
921         IOC_PACK(argv[0], data);
922         rc = ioctl(fd, OBD_IOC_SETATTR, buf);
923         if (rc < 0)
924                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
925                         strerror(rc = errno));
926
927         return rc;
928 }
929
930 int jt_obd_destroy(int argc, char **argv)
931 {
932         struct obd_ioctl_data data;
933         struct timeval next_time;
934         __u64 count = 1, next_count;
935         int verbose = 1;
936         __u64 id;
937         char *end;
938         int rc = 0, i;
939
940         IOCINIT(data);
941         if (argc < 2 || argc > 4)
942                 return CMD_HELP;
943
944         id = strtoull(argv[1], &end, 0);
945         if (*end) {
946                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
947                         cmdname(argv[0]), argv[1]);
948                 return CMD_HELP;
949         }
950         if (argc > 2) {
951                 count = strtoull(argv[2], &end, 0);
952                 if (*end) {
953                         fprintf(stderr,
954                                 "error: %s: invalid iteration count '%s'\n",
955                                 cmdname(argv[0]), argv[2]);
956                         return CMD_HELP;
957                 }
958         }
959
960         if (argc > 3) {
961                 verbose = get_verbose(argv[0], argv[3]);
962                 if (verbose == BAD_VERBOSE)
963                         return CMD_HELP;
964         }
965
966         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
967         gettimeofday(&next_time, NULL);
968         next_time.tv_sec -= verbose;
969
970         for (i = 1, next_count = verbose; i <= count; i++, id++) {
971                 data.ioc_obdo1.o_id = id;
972                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
973                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
974
975                 data.ioc_inllen1 = sizeof(saved_lsm);
976                 data.ioc_inlbuf1 = (char *)&saved_lsm;
977
978                 IOC_PACK(argv[0], data);
979                 rc = ioctl(fd, OBD_IOC_DESTROY, buf);
980                 IOC_UNPACK(argv[0], data);
981                 SHMEM_BUMP();
982                 if (rc < 0) {
983                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
984                                 cmdname(argv[0]), id, strerror(rc = errno));
985                         break;
986                 }
987                 lsm_valid = 0;
988
989                 if (be_verbose(verbose, &next_time, i, &next_count, count))
990                         printf("%s: #%d is object id "LPX64"\n",
991                                cmdname(argv[0]), i, id);
992         }
993
994         return rc;
995 }
996
997 int jt_obd_getattr(int argc, char **argv)
998 {
999         struct obd_ioctl_data data;
1000         char *end;
1001         int rc;
1002
1003         if (argc != 2)
1004                 return CMD_HELP;
1005
1006         IOCINIT(data);
1007         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1008         if (*end) {
1009                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1010                         cmdname(argv[0]), argv[1]);
1011                 return CMD_HELP;
1012         }
1013         /* to help obd filter */
1014         data.ioc_obdo1.o_mode = 0100644;
1015         data.ioc_obdo1.o_valid = 0xffffffff;
1016         printf("%s: object id "LPX64"\n", cmdname(argv[0]),data.ioc_obdo1.o_id);
1017
1018         if (lsm_valid == 1) {
1019                 data.ioc_inllen1 = sizeof(saved_lsm);
1020                 data.ioc_inlbuf1 = (char *)&saved_lsm;
1021         }
1022
1023         IOC_PACK(argv[0], data);
1024         rc = ioctl(fd, OBD_IOC_GETATTR, buf);
1025         IOC_UNPACK(argv[0], data);
1026         if (rc) {
1027                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1028                         strerror(rc = errno));
1029         } else {
1030                 printf("%s: object id "LPX64", mode %o\n", cmdname(argv[0]),
1031                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1032         }
1033         return rc;
1034 }
1035
1036 int jt_obd_test_getattr(int argc, char **argv)
1037 {
1038         struct obd_ioctl_data data;
1039         struct timeval start, next_time;
1040         __u64 i, count, next_count;
1041         int verbose = 1;
1042         obd_id objid = 3;
1043         char *end;
1044         int rc = 0;
1045
1046         if (argc < 2 && argc > 4)
1047                 return CMD_HELP;
1048
1049         IOCINIT(data);
1050         count = strtoull(argv[1], &end, 0);
1051         if (*end) {
1052                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1053                         cmdname(argv[0]), argv[1]);
1054                 return CMD_HELP;
1055         }
1056
1057         if (argc >= 3) {
1058                 verbose = get_verbose(argv[0], argv[2]);
1059                 if (verbose == BAD_VERBOSE)
1060                         return CMD_HELP;
1061         }
1062
1063         if (argc >= 4) {
1064                 if (argv[3][0] == 't') {
1065                         objid = strtoull(argv[3] + 1, &end, 0);
1066                         if (thread)
1067                                 objid += thread - 1;
1068                 } else
1069                         objid = strtoull(argv[3], &end, 0);
1070                 if (*end) {
1071                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1072                                 cmdname(argv[0]), argv[3]);
1073                         return CMD_HELP;
1074                 }
1075         }
1076
1077         gettimeofday(&start, NULL);
1078         next_time.tv_sec = start.tv_sec - verbose;
1079         next_time.tv_usec = start.tv_usec;
1080         if (verbose != 0)
1081                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1082                        cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1083
1084         for (i = 1, next_count = verbose; i <= count; i++) {
1085                 data.ioc_obdo1.o_id = objid;
1086                 data.ioc_obdo1.o_mode = S_IFREG;
1087                 data.ioc_obdo1.o_valid = 0xffffffff;
1088                 rc = ioctl(fd, OBD_IOC_GETATTR, &data);
1089                 SHMEM_BUMP();
1090                 if (rc < 0) {
1091                         fprintf(stderr, "error: %s: #"LPD64" - %s\n",
1092                                 cmdname(argv[0]), i, strerror(rc = errno));
1093                         break;
1094                 } else {
1095                         if (be_verbose
1096                             (verbose, &next_time, i, &next_count, count))
1097                                 printf("%s: got attr #"LPD64"\n",
1098                                        cmdname(argv[0]), i);
1099                 }
1100         }
1101
1102         if (!rc) {
1103                 struct timeval end;
1104                 double diff;
1105
1106                 gettimeofday(&end, NULL);
1107
1108                 diff = difftime(&end, &start);
1109
1110                 --i;
1111                 if (verbose != 0)
1112                         printf("%s: "LPD64" attrs in %.4gs (%.4g attr/s): %s",
1113                                cmdname(argv[0]), i, diff, (double)i / diff,
1114                                ctime(&end.tv_sec));
1115         }
1116         return rc;
1117 }
1118
1119 int jt_obd_test_brw(int argc, char **argv)
1120 {
1121         struct obd_ioctl_data data;
1122         struct timeval start, next_time;
1123         int pages = 1;
1124         __u64 count, next_count;
1125         __u64 objid = 3;
1126         int verbose = 1, write = 0, rw;
1127         char *end;
1128         int thr_offset = 0;
1129         int i;
1130         int len;
1131         int rc = 0;
1132
1133         if (argc < 2 || argc > 6) {
1134                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1135                         cmdname(argv[0]), argc);
1136                 return CMD_HELP;
1137         }
1138
1139         /* make each thread write to a different offset */
1140         if (argv[1][0] == 't') {
1141                 count = strtoull(argv[1] + 1, &end, 0);
1142                 if (thread)
1143                         thr_offset = thread - 1;
1144         } else
1145                 count = strtoull(argv[1], &end, 0);
1146
1147         if (*end) {
1148                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1149                         cmdname(argv[0]), argv[1]);
1150                 return CMD_HELP;
1151         }
1152
1153         if (argc >= 3) {
1154                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1155                         write = 1;
1156                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
1157                         write = 0;
1158         }
1159
1160         if (argc >= 4) {
1161                 verbose = get_verbose(argv[0], argv[3]);
1162                 if (verbose == BAD_VERBOSE)
1163                         return CMD_HELP;
1164         }
1165
1166         if (argc >= 5) {
1167                 pages = strtoul(argv[4], &end, 0);
1168                 if (*end) {
1169                         fprintf(stderr, "error: %s: bad page count '%s'\n",
1170                                 cmdname(argv[0]), argv[4]);
1171                         return CMD_HELP;
1172                 }
1173         }
1174         if (argc >= 6) {
1175                 if (argv[5][0] == 't') {
1176                         objid = strtoull(argv[5] + 1, &end, 0);
1177                         if (thread)
1178                                 objid += thread - 1;
1179                 } else
1180                         objid = strtoull(argv[5], &end, 0);
1181                 if (*end) {
1182                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1183                                 cmdname(argv[0]), argv[5]);
1184                         return CMD_HELP;
1185                 }
1186         }
1187
1188         len = pages * PAGE_SIZE;
1189
1190         IOCINIT(data);
1191         data.ioc_obdo1.o_id = objid;
1192         data.ioc_obdo1.o_mode = S_IFREG;
1193         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1194         data.ioc_count = len;
1195         data.ioc_offset = thr_offset * len * count;
1196
1197         if (lsm_valid == 1) {
1198                 data.ioc_inllen1 = sizeof(saved_lsm);
1199                 data.ioc_inlbuf1 = (char *)&saved_lsm;
1200         }
1201
1202         gettimeofday(&start, NULL);
1203         next_time.tv_sec = start.tv_sec - verbose;
1204         next_time.tv_usec = start.tv_usec;
1205
1206         if (verbose != 0)
1207                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1208                        cmdname(argv[0]), write ? "writing" : "reading", count,
1209                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1210
1211         IOC_PACK(argv[0], data);
1212         rc = ioctl(fd, OBD_IOC_OPEN, buf);
1213         IOC_UNPACK(argv[0], data);
1214         if (rc) {
1215                 fprintf(stderr, "error: brw_open: %s\n", strerror(rc = errno));
1216                 return rc;
1217         }
1218
1219         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1220         for (i = 1, next_count = verbose; i <= count; i++) {
1221                 rc = ioctl(fd, rw, buf);
1222                 SHMEM_BUMP();
1223                 if (rc) {
1224                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1225                                 cmdname(argv[0]), i, strerror(rc = errno),
1226                                 write ? "write" : "read");
1227                         break;
1228                 } else if (be_verbose(verbose, &next_time,i, &next_count,count))
1229                         printf("%s: %s number %dx%d\n", cmdname(argv[0]),
1230                                write ? "write" : "read", i, pages);
1231
1232                 data.ioc_offset += len;
1233         }
1234
1235         if (!rc) {
1236                 struct timeval end;
1237                 double diff;
1238
1239                 gettimeofday(&end, NULL);
1240
1241                 diff = difftime(&end, &start);
1242
1243                 --i;
1244                 if (verbose != 0)
1245                         printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s",
1246                                cmdname(argv[0]), write ? "wrote" : "read",
1247                                i, pages, diff, (double)i * pages / diff,
1248                                ctime(&end.tv_sec));
1249         }
1250         rw = ioctl(fd, OBD_IOC_CLOSE, buf);
1251         if (rw) {
1252                 fprintf(stderr, "error: brw_close: %s\n", strerror(rw = errno));
1253                 if (!rc)
1254                         rc = rw;
1255         }
1256
1257         return rc;
1258 }
1259
1260 int jt_obd_lov_setconfig(int argc, char **argv)
1261 {
1262         struct obd_ioctl_data data;
1263         struct lov_desc desc;
1264         obd_uuid_t *uuidarray, *ptr;
1265         int rc, i;
1266         char *end;
1267
1268         IOCINIT(data);
1269
1270         if (argc <= 6)
1271                 return CMD_HELP;
1272
1273         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
1274                 fprintf(stderr,
1275                         "error: %s: LOV uuid '%s' longer than %d characters\n",
1276                         cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
1277                 return -EINVAL;
1278         }
1279
1280         memset(&desc, 0, sizeof(desc));
1281         strncpy(desc.ld_uuid, argv[1], sizeof(desc.ld_uuid) - 1);
1282         desc.ld_tgt_count = argc - 6;
1283         desc.ld_default_stripe_count = strtoul(argv[2], &end, 0);
1284         if (*end) {
1285                 fprintf(stderr, "error: %s: bad default stripe count '%s'\n",
1286                         cmdname(argv[0]), argv[2]);
1287                 return CMD_HELP;
1288         }
1289         if (desc.ld_default_stripe_count > desc.ld_tgt_count) {
1290                 fprintf(stderr,
1291                         "error: %s: default stripe count %u > OST count %u\n",
1292                         cmdname(argv[0]), desc.ld_default_stripe_count,
1293                         desc.ld_tgt_count);
1294                 return -EINVAL;
1295         }
1296
1297         desc.ld_default_stripe_size = strtoull(argv[3], &end, 0);
1298         if (*end) {
1299                 fprintf(stderr, "error: %s: bad default stripe size '%s'\n",
1300                         cmdname(argv[0]), argv[3]);
1301                 return CMD_HELP;
1302         }
1303         if (desc.ld_default_stripe_size < 4096) {
1304                 fprintf(stderr,
1305                         "error: %s: default stripe size "LPU64" too small\n",
1306                         cmdname(argv[0]), desc.ld_default_stripe_size);
1307                 return -EINVAL;
1308         } else if ((long)desc.ld_default_stripe_size <
1309                    desc.ld_default_stripe_size) {
1310                 fprintf(stderr,
1311                         "error: %s: default stripe size "LPU64" too large\n",
1312                         cmdname(argv[0]), desc.ld_default_stripe_size);
1313                 return -EINVAL;
1314         }
1315         desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0);
1316         if (*end) {
1317                 fprintf(stderr, "error: %s: bad default stripe offset '%s'\n",
1318                         cmdname(argv[0]), argv[4]);
1319                 return CMD_HELP;
1320         }
1321         desc.ld_pattern = strtoul(argv[5], &end, 0);
1322         if (*end) {
1323                 fprintf(stderr, "error: %s: bad stripe pattern '%s'\n",
1324                         cmdname(argv[0]), argv[5]);
1325                 return CMD_HELP;
1326         }
1327
1328         /* NOTE: it is possible to overwrite the default striping parameters,
1329          *       but EXTREME care must be taken when saving the OST UUID list.
1330          *       It must be EXACTLY the same, or have only additions at the
1331          *       end of the list, or only overwrite individual OST entries
1332          *       that are restored from backups of the previous OST.
1333          */
1334         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1335         if (!uuidarray) {
1336                 fprintf(stderr, "error: %s: no memory for %d UUIDs\n",
1337                         cmdname(argv[0]), desc.ld_tgt_count);
1338                 rc = -ENOMEM;
1339                 goto out;
1340         }
1341         for (i = 6, ptr = uuidarray; i < argc; i++, ptr++) {
1342                 if (strlen(argv[i]) >= sizeof(*ptr)) {
1343                         fprintf(stderr, "error: %s: arg %d (%s) too long\n",
1344                                 cmdname(argv[0]), i, argv[i]);
1345                         rc = -EINVAL;
1346                         goto out;
1347                 }
1348                 strcpy((char *)ptr, argv[i]);
1349         }
1350
1351         data.ioc_inllen1 = sizeof(desc);
1352         data.ioc_inlbuf1 = (char *)&desc;
1353         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1354         data.ioc_inlbuf2 = (char *)uuidarray;
1355
1356         if (obd_ioctl_pack(&data, &buf, max)) {
1357                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1358                 rc = -EINVAL;
1359                 goto out;
1360         }
1361         rc = ioctl(fd, OBD_IOC_LOV_SET_CONFIG, buf);
1362         if (rc)
1363                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1364                         cmdname(argv[0]), strerror(rc = errno));
1365 out:
1366         free(uuidarray);
1367         return rc;
1368 }
1369
1370 #define DEF_UUID_ARRAY_LEN (8192 / 40)
1371
1372 int jt_obd_lov_getconfig(int argc, char **argv)
1373 {
1374         struct obd_ioctl_data data;
1375         struct lov_desc desc;
1376         obd_uuid_t *uuidarray;
1377         int rc;
1378
1379         IOCINIT(data);
1380
1381         if (argc != 2)
1382                 return CMD_HELP;
1383
1384         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
1385                 fprintf(stderr,
1386                         "error: %s: LOV uuid '%s' longer than %d characters\n",
1387                         cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
1388                 return -EINVAL;
1389         }
1390
1391         memset(&desc, 0, sizeof(desc));
1392         strncpy(desc.ld_uuid, argv[1], sizeof(desc.ld_uuid) - 1);
1393         desc.ld_tgt_count = DEF_UUID_ARRAY_LEN;
1394 repeat:
1395         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1396         if (!uuidarray) {
1397                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1398                         cmdname(argv[0]), desc.ld_tgt_count);
1399                 return -ENOMEM;
1400         }
1401
1402         data.ioc_inllen1 = sizeof(desc);
1403         data.ioc_inlbuf1 = (char *)&desc;
1404         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1405         data.ioc_inlbuf2 = (char *)uuidarray;
1406
1407         if (obd_ioctl_pack(&data, &buf, max)) {
1408                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1409                 rc = -EINVAL;
1410                 goto out;
1411         }
1412         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1413         if (rc == -ENOSPC) {
1414                 free(uuidarray);
1415                 goto repeat;
1416         } else if (rc) {
1417                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1418                         cmdname(argv[0]), strerror(rc = errno));
1419         } else {
1420                 obd_uuid_t *ptr;
1421                 int i;
1422
1423                 if (obd_ioctl_unpack(&data, buf, max)) {
1424                         fprintf(stderr, "error: %s: invalid reply\n",
1425                                 cmdname(argv[0]));
1426                         rc = -EINVAL;
1427                         goto out;
1428                 }
1429                 printf("default_stripe_count: %u\n",
1430                        desc.ld_default_stripe_count);
1431                 printf("default_stripe_size: "LPU64"\n",
1432                        desc.ld_default_stripe_size);
1433                 printf("default_stripe_offset: "LPU64"\n",
1434                        desc.ld_default_stripe_offset);
1435                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1436                 printf("obd_count: %u\n", desc.ld_tgt_count);
1437                 for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
1438                         printf("%u: %s\n", i, (char *)ptr);
1439         }
1440 out:
1441         free(uuidarray);
1442         return rc;
1443 }
1444
1445 int jt_obd_test_ldlm(int argc, char **argv)
1446 {
1447         struct obd_ioctl_data data;
1448         int rc;
1449
1450         IOCINIT(data);
1451         if (argc != 1)
1452                 return CMD_HELP;
1453
1454         rc = ioctl(fd, IOC_LDLM_TEST, &data);
1455         if (rc)
1456                 fprintf(stderr, "error: %s: test failed: %s\n",
1457                         cmdname(argv[0]), strerror(rc = errno));
1458         return rc;
1459 }
1460
1461 int jt_obd_dump_ldlm(int argc, char **argv)
1462 {
1463         struct obd_ioctl_data data;
1464         int rc;
1465
1466         IOCINIT(data);
1467         if (argc != 1)
1468                 return CMD_HELP;
1469
1470         rc = ioctl(fd, IOC_LDLM_DUMP, &data);
1471         if (rc)
1472                 fprintf(stderr, "error: %s failed: %s\n",
1473                         cmdname(argv[0]), strerror(rc = errno));
1474         return rc;
1475 }
1476
1477 int jt_obd_ldlm_regress_start(int argc, char **argv)
1478 {
1479         int rc;
1480         struct obd_ioctl_data data;
1481         char argstring[200];
1482         int i, count = sizeof(argstring) - 1;
1483
1484         IOCINIT(data);
1485         if (argc > 5)
1486                 return CMD_HELP;
1487
1488         argstring[0] = '\0';
1489         for (i = 1; i < argc; i++) {
1490                 strncat(argstring, " ", count);
1491                 count--;
1492                 strncat(argstring, argv[i], count);
1493                 count -= strlen(argv[i]);
1494         }
1495
1496         if (strlen(argstring)) {
1497                 data.ioc_inlbuf1 = argstring;
1498                 data.ioc_inllen1 = strlen(argstring) + 1;
1499         }
1500
1501         IOC_PACK(argv[0], data);
1502         rc = ioctl(fd, IOC_LDLM_REGRESS_START, buf);
1503         if (rc)
1504                 fprintf(stderr, "error: %s: test failed: %s\n",
1505                         cmdname(argv[0]), strerror(rc = errno));
1506
1507         return rc;
1508 }
1509
1510 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1511 {
1512         int rc;
1513         struct obd_ioctl_data data;
1514         IOCINIT(data);
1515
1516         if (argc != 1)
1517                 return CMD_HELP;
1518
1519         rc = ioctl(fd, IOC_LDLM_REGRESS_STOP, &data);
1520
1521         if (rc)
1522                 fprintf(stderr, "error: %s: test failed: %s\n",
1523                         cmdname(argv[0]), strerror(rc = errno));
1524         return rc;
1525 }
1526
1527 int jt_obd_lov_set_osc_active(int argc, char **argv)
1528 {
1529         struct obd_ioctl_data data;
1530         int rc;
1531
1532         IOCINIT(data);
1533         if (argc != 3)
1534                 return CMD_HELP;
1535
1536         data.ioc_inlbuf1 = argv[1];
1537         data.ioc_inllen1 = strlen(argv[1]) + 1;
1538
1539         /* reuse offset for 'active' */
1540         data.ioc_offset = atoi(argv[2]);
1541
1542         IOC_PACK(argv[0], data);
1543         rc = ioctl(fd, IOC_LOV_SET_OSC_ACTIVE, buf);
1544         if (rc)
1545                 fprintf(stderr, "error: %s: failed: %s\n",
1546                         cmdname(argv[0]), strerror(rc = errno));
1547
1548         return rc;
1549 }
1550
1551 int jt_obd_newconn(int argc, char **argv)
1552 {
1553         int rc;
1554         struct obd_ioctl_data data;
1555
1556         IOCINIT(data);
1557         if (argc < 2 || argc > 3)
1558                 return CMD_HELP;
1559
1560         data.ioc_inllen1 = strlen(argv[1]) + 1;
1561         data.ioc_inlbuf1 = argv[1];
1562
1563         if (argc == 3) {
1564                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1565                 data.ioc_inlbuf2 = argv[2];
1566         }
1567
1568         IOC_PACK(argv[0], data);
1569         rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN, buf);
1570         if (rc < 0)
1571                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1572                         strerror(rc = errno));
1573
1574         return rc;
1575 }
1576
1577 int jt_obd_failconn(int argc, char **argv)
1578 {
1579         int rc;
1580         struct obd_ioctl_data data;
1581
1582         IOCINIT(data);
1583         if (argc < 2)
1584                 return CMD_HELP;
1585
1586         data.ioc_inllen1 = strlen(argv[1]) + 1;
1587         data.ioc_inlbuf1 = argv[1];
1588
1589         IOC_PACK(argv[0], data);
1590         rc = ioctl(fd, OBD_IOC_RECOVD_FAILCONN, buf);
1591         if (rc < 0)
1592                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1593                         strerror(rc = errno));
1594         
1595         return rc;
1596 }
1597
1598 static void signal_server(int sig)
1599 {
1600         if (sig == SIGINT) {
1601                 do_disconnect("sigint", 1);
1602                 exit(1);
1603         } else
1604                 fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
1605 }
1606
1607 int obd_initialize(int argc, char **argv)
1608 {
1609         SHMEM_SETUP();
1610         return 0;
1611 }
1612
1613
1614 void obd_cleanup(int argc, char **argv)
1615 {
1616         struct sigaction sigact;
1617
1618         sigact.sa_handler = signal_server;
1619         sigfillset(&sigact.sa_mask);
1620         sigact.sa_flags = SA_RESTART;
1621         sigaction(SIGINT, &sigact, NULL);
1622
1623         do_disconnect(argv[0], 1);
1624 }