Whamcloud - gitweb
land b_md onto HEAD. the highlights:
[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: OPD_IOC_DISCONNECT %s\n", 
297                         cmdname(func),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: OBD_IOC_CONNECT %s\n",
456                         cmdname(argv[0]), 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: OBD_IOC_ATTACH %s\n", 
745                         cmdname(argv[0]), 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.   It only saves the LSM when the ioctl indicates that it
814  * is valid by overloading 'ioc_conn2' as a boolean. */
815 int jt_obd_create(int argc, char **argv)
816 {
817         struct obd_ioctl_data data;
818         struct timeval next_time;
819         __u64 count = 1, next_count;
820         int verbose = 1, mode = 0100644, rc = 0, i;
821         char *end;
822
823         IOCINIT(data);
824         if (argc < 2 || argc > 4)
825                 return CMD_HELP;
826
827         count = strtoull(argv[1], &end, 0);
828         if (*end) {
829                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
830                         cmdname(argv[0]), argv[1]);
831                 return CMD_HELP;
832         }
833
834         if (argc > 2) {
835                 mode = strtoul(argv[2], &end, 0);
836                 if (*end) {
837                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
838                                 cmdname(argv[0]), argv[2]);
839                         return CMD_HELP;
840                 }
841                 if (!(mode & S_IFMT))
842                         mode |= S_IFREG;
843         }
844
845         if (argc > 3) {
846                 verbose = get_verbose(argv[0], argv[3]);
847                 if (verbose == BAD_VERBOSE)
848                         return CMD_HELP;
849         }
850
851         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
852         gettimeofday(&next_time, NULL);
853         next_time.tv_sec -= verbose;
854
855         for (i = 1, next_count = verbose; i <= count; i++) {
856                 data.ioc_obdo1.o_mode = mode;
857                 data.ioc_obdo1.o_id = i;
858                 data.ioc_obdo1.o_uid = 0;
859                 data.ioc_obdo1.o_gid = 0;
860                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
861                                 OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;;
862
863                 data.ioc_inllen1 = sizeof(saved_lsm);
864                 data.ioc_inlbuf1 = (char *)&saved_lsm;
865
866                 IOC_PACK(argv[0], data);
867                 rc = ioctl(fd, OBD_IOC_CREATE, buf);
868                 IOC_UNPACK(argv[0], data);
869                 fprintf(stderr, "lsm->lsm_o_id: "LPX64"\n",
870                         saved_lsm.lsm_object_id);
871                 SHMEM_BUMP();
872                 if (rc < 0) {
873                         fprintf(stderr, "error: %s: #%d - %s\n",
874                                 cmdname(argv[0]), i, strerror(rc = errno));
875                         break;
876                 }
877                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
878                         fprintf(stderr, "error: %s: objid not valid #%d:%08x\n",
879                                 cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
880                         rc = EINVAL;
881                         break;
882                 }
883
884                 lsm_valid = data.ioc_conn2;
885
886                 if (be_verbose(verbose, &next_time, i, &next_count, count))
887                         printf("%s: #%d is object id "LPX64"\n",
888                                cmdname(argv[0]), i, data.ioc_obdo1.o_id);
889         }
890         return rc;
891 }
892
893 int jt_obd_setattr(int argc, char **argv)
894 {
895         struct obd_ioctl_data data;
896         char *end;
897         int rc;
898
899         IOCINIT(data);
900         if (argc != 2)
901                 return CMD_HELP;
902
903         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
904         if (*end) {
905                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
906                         cmdname(argv[0]), argv[1]);
907                 return CMD_HELP;
908         }
909         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
910         if (*end) {
911                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
912                         cmdname(argv[0]), argv[2]);
913                 return CMD_HELP;
914         }
915         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
916
917         if (lsm_valid == 1) {
918                 data.ioc_inllen1 = sizeof(saved_lsm);
919                 data.ioc_inlbuf1 = (char *)&saved_lsm;
920         }
921
922         IOC_PACK(argv[0], data);
923         rc = ioctl(fd, OBD_IOC_SETATTR, buf);
924         if (rc < 0)
925                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
926                         strerror(rc = errno));
927
928         return rc;
929 }
930
931 int jt_obd_destroy(int argc, char **argv)
932 {
933         struct obd_ioctl_data data;
934         struct timeval next_time;
935         __u64 count = 1, next_count;
936         int verbose = 1;
937         __u64 id;
938         char *end;
939         int rc = 0, i;
940
941         IOCINIT(data);
942         if (argc < 2 || argc > 4)
943                 return CMD_HELP;
944
945         id = strtoull(argv[1], &end, 0);
946         if (*end) {
947                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
948                         cmdname(argv[0]), argv[1]);
949                 return CMD_HELP;
950         }
951         if (argc > 2) {
952                 count = strtoull(argv[2], &end, 0);
953                 if (*end) {
954                         fprintf(stderr,
955                                 "error: %s: invalid iteration count '%s'\n",
956                                 cmdname(argv[0]), argv[2]);
957                         return CMD_HELP;
958                 }
959         }
960
961         if (argc > 3) {
962                 verbose = get_verbose(argv[0], argv[3]);
963                 if (verbose == BAD_VERBOSE)
964                         return CMD_HELP;
965         }
966
967         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
968         gettimeofday(&next_time, NULL);
969         next_time.tv_sec -= verbose;
970
971         for (i = 1, next_count = verbose; i <= count; i++, id++) {
972                 data.ioc_obdo1.o_id = id;
973                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
974                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
975
976                 data.ioc_inllen1 = sizeof(saved_lsm);
977                 data.ioc_inlbuf1 = (char *)&saved_lsm;
978
979                 IOC_PACK(argv[0], data);
980                 rc = ioctl(fd, OBD_IOC_DESTROY, buf);
981                 IOC_UNPACK(argv[0], data);
982                 SHMEM_BUMP();
983                 if (rc < 0) {
984                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
985                                 cmdname(argv[0]), id, strerror(rc = errno));
986                         break;
987                 }
988                 lsm_valid = 0;
989
990                 if (be_verbose(verbose, &next_time, i, &next_count, count))
991                         printf("%s: #%d is object id "LPX64"\n",
992                                cmdname(argv[0]), i, id);
993         }
994
995         return rc;
996 }
997
998 int jt_obd_getattr(int argc, char **argv)
999 {
1000         struct obd_ioctl_data data;
1001         char *end;
1002         int rc;
1003
1004         if (argc != 2)
1005                 return CMD_HELP;
1006
1007         IOCINIT(data);
1008         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1009         if (*end) {
1010                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1011                         cmdname(argv[0]), argv[1]);
1012                 return CMD_HELP;
1013         }
1014         /* to help obd filter */
1015         data.ioc_obdo1.o_mode = 0100644;
1016         data.ioc_obdo1.o_valid = 0xffffffff;
1017         printf("%s: object id "LPX64"\n", cmdname(argv[0]),data.ioc_obdo1.o_id);
1018
1019         if (lsm_valid == 1) {
1020                 data.ioc_inllen1 = sizeof(saved_lsm);
1021                 data.ioc_inlbuf1 = (char *)&saved_lsm;
1022         }
1023
1024         IOC_PACK(argv[0], data);
1025         rc = ioctl(fd, OBD_IOC_GETATTR, buf);
1026         IOC_UNPACK(argv[0], data);
1027         if (rc) {
1028                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1029                         strerror(rc = errno));
1030         } else {
1031                 printf("%s: object id "LPX64", mode %o\n", cmdname(argv[0]),
1032                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1033         }
1034         return rc;
1035 }
1036
1037 int jt_obd_test_getattr(int argc, char **argv)
1038 {
1039         struct obd_ioctl_data data;
1040         struct timeval start, next_time;
1041         __u64 i, count, next_count;
1042         int verbose = 1;
1043         obd_id objid = 3;
1044         char *end;
1045         int rc = 0;
1046
1047         if (argc < 2 && argc > 4)
1048                 return CMD_HELP;
1049
1050         IOCINIT(data);
1051         count = strtoull(argv[1], &end, 0);
1052         if (*end) {
1053                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1054                         cmdname(argv[0]), argv[1]);
1055                 return CMD_HELP;
1056         }
1057
1058         if (argc >= 3) {
1059                 verbose = get_verbose(argv[0], argv[2]);
1060                 if (verbose == BAD_VERBOSE)
1061                         return CMD_HELP;
1062         }
1063
1064         if (argc >= 4) {
1065                 if (argv[3][0] == 't') {
1066                         objid = strtoull(argv[3] + 1, &end, 0);
1067                         if (thread)
1068                                 objid += thread - 1;
1069                 } else
1070                         objid = strtoull(argv[3], &end, 0);
1071                 if (*end) {
1072                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1073                                 cmdname(argv[0]), argv[3]);
1074                         return CMD_HELP;
1075                 }
1076         }
1077
1078         gettimeofday(&start, NULL);
1079         next_time.tv_sec = start.tv_sec - verbose;
1080         next_time.tv_usec = start.tv_usec;
1081         if (verbose != 0)
1082                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1083                        cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1084
1085         for (i = 1, next_count = verbose; i <= count; i++) {
1086                 data.ioc_obdo1.o_id = objid;
1087                 data.ioc_obdo1.o_mode = S_IFREG;
1088                 data.ioc_obdo1.o_valid = 0xffffffff;
1089                 rc = ioctl(fd, OBD_IOC_GETATTR, &data);
1090                 SHMEM_BUMP();
1091                 if (rc < 0) {
1092                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1093                                 cmdname(argv[0]), i, errno, strerror(rc = errno));
1094                         break;
1095                 } else {
1096                         if (be_verbose
1097                             (verbose, &next_time, i, &next_count, count))
1098                                 printf("%s: got attr #"LPD64"\n",
1099                                        cmdname(argv[0]), i);
1100                 }
1101         }
1102
1103         if (!rc) {
1104                 struct timeval end;
1105                 double diff;
1106
1107                 gettimeofday(&end, NULL);
1108
1109                 diff = difftime(&end, &start);
1110
1111                 --i;
1112                 if (verbose != 0)
1113                         printf("%s: "LPD64" attrs in %.4gs (%.4g attr/s): %s",
1114                                cmdname(argv[0]), i, diff, (double)i / diff,
1115                                ctime(&end.tv_sec));
1116         }
1117         return rc;
1118 }
1119
1120 int jt_obd_test_brw(int argc, char **argv)
1121 {
1122         struct obd_ioctl_data data;
1123         struct timeval start, next_time;
1124         int pages = 1;
1125         __u64 count, next_count;
1126         __u64 objid = 3;
1127         int verbose = 1, write = 0, rw;
1128         char *end;
1129         int thr_offset = 0;
1130         int i;
1131         int len;
1132         int rc = 0;
1133
1134         if (argc < 2 || argc > 6) {
1135                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1136                         cmdname(argv[0]), argc);
1137                 return CMD_HELP;
1138         }
1139
1140         /* make each thread write to a different offset */
1141         if (argv[1][0] == 't') {
1142                 count = strtoull(argv[1] + 1, &end, 0);
1143                 if (thread)
1144                         thr_offset = thread - 1;
1145         } else
1146                 count = strtoull(argv[1], &end, 0);
1147
1148         if (*end) {
1149                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1150                         cmdname(argv[0]), argv[1]);
1151                 return CMD_HELP;
1152         }
1153
1154         if (argc >= 3) {
1155                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1156                         write = 1;
1157                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
1158                         write = 0;
1159         }
1160
1161         if (argc >= 4) {
1162                 verbose = get_verbose(argv[0], argv[3]);
1163                 if (verbose == BAD_VERBOSE)
1164                         return CMD_HELP;
1165         }
1166
1167         if (argc >= 5) {
1168                 pages = strtoul(argv[4], &end, 0);
1169                 if (*end) {
1170                         fprintf(stderr, "error: %s: bad page count '%s'\n",
1171                                 cmdname(argv[0]), argv[4]);
1172                         return CMD_HELP;
1173                 }
1174         }
1175         if (argc >= 6) {
1176                 if (argv[5][0] == 't') {
1177                         objid = strtoull(argv[5] + 1, &end, 0);
1178                         if (thread)
1179                                 objid += thread - 1;
1180                 } else
1181                         objid = strtoull(argv[5], &end, 0);
1182                 if (*end) {
1183                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1184                                 cmdname(argv[0]), argv[5]);
1185                         return CMD_HELP;
1186                 }
1187         }
1188
1189         len = pages * PAGE_SIZE;
1190
1191         IOCINIT(data);
1192         data.ioc_obdo1.o_id = objid;
1193         data.ioc_obdo1.o_mode = S_IFREG;
1194         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1195         data.ioc_count = len;
1196         data.ioc_offset = thr_offset * len * count;
1197
1198         if (lsm_valid == 1) {
1199                 data.ioc_inllen1 = sizeof(saved_lsm);
1200                 data.ioc_inlbuf1 = (char *)&saved_lsm;
1201         }
1202
1203         gettimeofday(&start, NULL);
1204         next_time.tv_sec = start.tv_sec - verbose;
1205         next_time.tv_usec = start.tv_usec;
1206
1207         if (verbose != 0)
1208                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1209                        cmdname(argv[0]), write ? "writing" : "reading", count,
1210                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1211
1212         IOC_PACK(argv[0], data);
1213         rc = ioctl(fd, OBD_IOC_OPEN, buf);
1214         IOC_UNPACK(argv[0], data);
1215         if (rc) {
1216                 fprintf(stderr, "error: brw_open: %s\n", strerror(rc = errno));
1217                 return rc;
1218         }
1219
1220         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1221         for (i = 1, next_count = verbose; i <= count; i++) {
1222                 rc = ioctl(fd, rw, buf);
1223                 SHMEM_BUMP();
1224                 if (rc) {
1225                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1226                                 cmdname(argv[0]), i, strerror(rc = errno),
1227                                 write ? "write" : "read");
1228                         break;
1229                 } else if (be_verbose(verbose, &next_time,i, &next_count,count))
1230                         printf("%s: %s number %dx%d\n", cmdname(argv[0]),
1231                                write ? "write" : "read", i, pages);
1232
1233                 data.ioc_offset += len;
1234         }
1235
1236         if (!rc) {
1237                 struct timeval end;
1238                 double diff;
1239
1240                 gettimeofday(&end, NULL);
1241
1242                 diff = difftime(&end, &start);
1243
1244                 --i;
1245                 if (verbose != 0)
1246                         printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s",
1247                                cmdname(argv[0]), write ? "wrote" : "read",
1248                                i, pages, diff, (double)i * pages / diff,
1249                                ctime(&end.tv_sec));
1250         }
1251         rw = ioctl(fd, OBD_IOC_CLOSE, buf);
1252         if (rw) {
1253                 fprintf(stderr, "error: brw_close: %s\n", strerror(rw = errno));
1254                 if (!rc)
1255                         rc = rw;
1256         }
1257
1258         return rc;
1259 }
1260
1261 int jt_obd_lov_setconfig(int argc, char **argv)
1262 {
1263         struct obd_ioctl_data data;
1264         struct lov_desc desc;
1265         obd_uuid_t *uuidarray, *ptr;
1266         int rc, i;
1267         char *end;
1268
1269         IOCINIT(data);
1270
1271         if (argc <= 6)
1272                 return CMD_HELP;
1273
1274         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
1275                 fprintf(stderr,
1276                         "error: %s: LOV uuid '%s' longer than %zd characters\n",
1277                         cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
1278                 return -EINVAL;
1279         }
1280
1281         memset(&desc, 0, sizeof(desc));
1282         strncpy(desc.ld_uuid, argv[1], sizeof(desc.ld_uuid) - 1);
1283         desc.ld_tgt_count = argc - 6;
1284         desc.ld_default_stripe_count = strtoul(argv[2], &end, 0);
1285         if (*end) {
1286                 fprintf(stderr, "error: %s: bad default stripe count '%s'\n",
1287                         cmdname(argv[0]), argv[2]);
1288                 return CMD_HELP;
1289         }
1290         if (desc.ld_default_stripe_count > desc.ld_tgt_count) {
1291                 fprintf(stderr,
1292                         "error: %s: default stripe count %u > OST count %u\n",
1293                         cmdname(argv[0]), desc.ld_default_stripe_count,
1294                         desc.ld_tgt_count);
1295                 return -EINVAL;
1296         }
1297
1298         desc.ld_default_stripe_size = strtoull(argv[3], &end, 0);
1299         if (*end) {
1300                 fprintf(stderr, "error: %s: bad default stripe size '%s'\n",
1301                         cmdname(argv[0]), argv[3]);
1302                 return CMD_HELP;
1303         }
1304         if (desc.ld_default_stripe_size < 4096) {
1305                 fprintf(stderr,
1306                         "error: %s: default stripe size "LPU64" too small\n",
1307                         cmdname(argv[0]), desc.ld_default_stripe_size);
1308                 return -EINVAL;
1309         } else if ((long)desc.ld_default_stripe_size <
1310                    desc.ld_default_stripe_size) {
1311                 fprintf(stderr,
1312                         "error: %s: default stripe size "LPU64" too large\n",
1313                         cmdname(argv[0]), desc.ld_default_stripe_size);
1314                 return -EINVAL;
1315         }
1316         desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0);
1317         if (*end) {
1318                 fprintf(stderr, "error: %s: bad default stripe offset '%s'\n",
1319                         cmdname(argv[0]), argv[4]);
1320                 return CMD_HELP;
1321         }
1322         desc.ld_pattern = strtoul(argv[5], &end, 0);
1323         if (*end) {
1324                 fprintf(stderr, "error: %s: bad stripe pattern '%s'\n",
1325                         cmdname(argv[0]), argv[5]);
1326                 return CMD_HELP;
1327         }
1328
1329         /* NOTE: it is possible to overwrite the default striping parameters,
1330          *       but EXTREME care must be taken when saving the OST UUID list.
1331          *       It must be EXACTLY the same, or have only additions at the
1332          *       end of the list, or only overwrite individual OST entries
1333          *       that are restored from backups of the previous OST.
1334          */
1335         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1336         if (!uuidarray) {
1337                 fprintf(stderr, "error: %s: no memory for %d UUIDs\n",
1338                         cmdname(argv[0]), desc.ld_tgt_count);
1339                 rc = -ENOMEM;
1340                 goto out;
1341         }
1342         for (i = 6, ptr = uuidarray; i < argc; i++, ptr++) {
1343                 if (strlen(argv[i]) >= sizeof(*ptr)) {
1344                         fprintf(stderr, "error: %s: arg %d (%s) too long\n",
1345                                 cmdname(argv[0]), i, argv[i]);
1346                         rc = -EINVAL;
1347                         goto out;
1348                 }
1349                 strcpy((char *)ptr, argv[i]);
1350         }
1351
1352         data.ioc_inllen1 = sizeof(desc);
1353         data.ioc_inlbuf1 = (char *)&desc;
1354         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1355         data.ioc_inlbuf2 = (char *)uuidarray;
1356
1357         if (obd_ioctl_pack(&data, &buf, max)) {
1358                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1359                 rc = -EINVAL;
1360                 goto out;
1361         }
1362         rc = ioctl(fd, OBD_IOC_LOV_SET_CONFIG, buf);
1363         if (rc)
1364                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1365                         cmdname(argv[0]), strerror(rc = errno));
1366 out:
1367         free(uuidarray);
1368         return rc;
1369 }
1370
1371 #define DEF_UUID_ARRAY_LEN (8192 / 40)
1372
1373 int jt_obd_lov_getconfig(int argc, char **argv)
1374 {
1375         struct obd_ioctl_data data;
1376         struct lov_desc desc;
1377         obd_uuid_t *uuidarray;
1378         int rc;
1379
1380         IOCINIT(data);
1381
1382         if (argc != 2)
1383                 return CMD_HELP;
1384
1385         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
1386                 fprintf(stderr,
1387                         "error: %s: LOV uuid '%s' longer than %zd characters\n",
1388                         cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
1389                 return -EINVAL;
1390         }
1391
1392         memset(&desc, 0, sizeof(desc));
1393         strncpy(desc.ld_uuid, argv[1], sizeof(desc.ld_uuid) - 1);
1394         desc.ld_tgt_count = DEF_UUID_ARRAY_LEN;
1395 repeat:
1396         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1397         if (!uuidarray) {
1398                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1399                         cmdname(argv[0]), desc.ld_tgt_count);
1400                 return -ENOMEM;
1401         }
1402
1403         data.ioc_inllen1 = sizeof(desc);
1404         data.ioc_inlbuf1 = (char *)&desc;
1405         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1406         data.ioc_inlbuf2 = (char *)uuidarray;
1407
1408         if (obd_ioctl_pack(&data, &buf, max)) {
1409                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1410                 rc = -EINVAL;
1411                 goto out;
1412         }
1413         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1414         if (rc == -ENOSPC) {
1415                 free(uuidarray);
1416                 goto repeat;
1417         } else if (rc) {
1418                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1419                         cmdname(argv[0]), strerror(rc = errno));
1420         } else {
1421                 obd_uuid_t *ptr;
1422                 int i;
1423
1424                 if (obd_ioctl_unpack(&data, buf, max)) {
1425                         fprintf(stderr, "error: %s: invalid reply\n",
1426                                 cmdname(argv[0]));
1427                         rc = -EINVAL;
1428                         goto out;
1429                 }
1430                 printf("default_stripe_count: %u\n",
1431                        desc.ld_default_stripe_count);
1432                 printf("default_stripe_size: "LPU64"\n",
1433                        desc.ld_default_stripe_size);
1434                 printf("default_stripe_offset: "LPU64"\n",
1435                        desc.ld_default_stripe_offset);
1436                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1437                 printf("obd_count: %u\n", desc.ld_tgt_count);
1438                 for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
1439                         printf("%u: %s\n", i, (char *)ptr);
1440         }
1441 out:
1442         free(uuidarray);
1443         return rc;
1444 }
1445
1446 int jt_obd_test_ldlm(int argc, char **argv)
1447 {
1448         struct obd_ioctl_data data;
1449         int rc;
1450
1451         IOCINIT(data);
1452         if (argc != 1)
1453                 return CMD_HELP;
1454
1455         rc = ioctl(fd, IOC_LDLM_TEST, &data);
1456         if (rc)
1457                 fprintf(stderr, "error: %s: test failed: %s\n",
1458                         cmdname(argv[0]), strerror(rc = errno));
1459         return rc;
1460 }
1461
1462 int jt_obd_dump_ldlm(int argc, char **argv)
1463 {
1464         struct obd_ioctl_data data;
1465         int rc;
1466
1467         IOCINIT(data);
1468         if (argc != 1)
1469                 return CMD_HELP;
1470
1471         rc = ioctl(fd, IOC_LDLM_DUMP, &data);
1472         if (rc)
1473                 fprintf(stderr, "error: %s failed: %s\n",
1474                         cmdname(argv[0]), strerror(rc = errno));
1475         return rc;
1476 }
1477
1478 int jt_obd_ldlm_regress_start(int argc, char **argv)
1479 {
1480         int rc;
1481         struct obd_ioctl_data data;
1482         char argstring[200];
1483         int i, count = sizeof(argstring) - 1;
1484
1485         IOCINIT(data);
1486         if (argc > 5)
1487                 return CMD_HELP;
1488
1489         argstring[0] = '\0';
1490         for (i = 1; i < argc; i++) {
1491                 strncat(argstring, " ", count);
1492                 count--;
1493                 strncat(argstring, argv[i], count);
1494                 count -= strlen(argv[i]);
1495         }
1496
1497         if (strlen(argstring)) {
1498                 data.ioc_inlbuf1 = argstring;
1499                 data.ioc_inllen1 = strlen(argstring) + 1;
1500         }
1501
1502         IOC_PACK(argv[0], data);
1503         rc = ioctl(fd, IOC_LDLM_REGRESS_START, buf);
1504         if (rc)
1505                 fprintf(stderr, "error: %s: test failed: %s\n",
1506                         cmdname(argv[0]), strerror(rc = errno));
1507
1508         return rc;
1509 }
1510
1511 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1512 {
1513         int rc;
1514         struct obd_ioctl_data data;
1515         IOCINIT(data);
1516
1517         if (argc != 1)
1518                 return CMD_HELP;
1519
1520         rc = ioctl(fd, IOC_LDLM_REGRESS_STOP, &data);
1521
1522         if (rc)
1523                 fprintf(stderr, "error: %s: test failed: %s\n",
1524                         cmdname(argv[0]), strerror(rc = errno));
1525         return rc;
1526 }
1527
1528 int jt_obd_lov_set_osc_active(int argc, char **argv)
1529 {
1530         struct obd_ioctl_data data;
1531         int rc;
1532
1533         IOCINIT(data);
1534         if (argc != 3)
1535                 return CMD_HELP;
1536
1537         data.ioc_inlbuf1 = argv[1];
1538         data.ioc_inllen1 = strlen(argv[1]) + 1;
1539
1540         /* reuse offset for 'active' */
1541         data.ioc_offset = atoi(argv[2]);
1542
1543         IOC_PACK(argv[0], data);
1544         rc = ioctl(fd, IOC_LOV_SET_OSC_ACTIVE, buf);
1545         if (rc)
1546                 fprintf(stderr, "error: %s: failed: %s\n",
1547                         cmdname(argv[0]), strerror(rc = errno));
1548
1549         return rc;
1550 }
1551
1552 int jt_obd_newconn(int argc, char **argv)
1553 {
1554         int rc;
1555         struct obd_ioctl_data data;
1556
1557         IOCINIT(data);
1558         if (argc < 2 || argc > 3)
1559                 return CMD_HELP;
1560
1561         data.ioc_inllen1 = strlen(argv[1]) + 1;
1562         data.ioc_inlbuf1 = argv[1];
1563
1564         if (argc == 3) {
1565                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1566                 data.ioc_inlbuf2 = argv[2];
1567         }
1568
1569         IOC_PACK(argv[0], data);
1570         rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN, buf);
1571         if (rc < 0)
1572                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1573                         strerror(rc = errno));
1574
1575         return rc;
1576 }
1577
1578 int jt_obd_failconn(int argc, char **argv)
1579 {
1580         int rc;
1581         struct obd_ioctl_data data;
1582
1583         IOCINIT(data);
1584         if (argc < 2)
1585                 return CMD_HELP;
1586
1587         data.ioc_inllen1 = strlen(argv[1]) + 1;
1588         data.ioc_inlbuf1 = argv[1];
1589
1590         IOC_PACK(argv[0], data);
1591         rc = ioctl(fd, OBD_IOC_RECOVD_FAILCONN, buf);
1592         if (rc < 0)
1593                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1594                         strerror(rc = errno));
1595         
1596         return rc;
1597 }
1598
1599 static void signal_server(int sig)
1600 {
1601         if (sig == SIGINT) {
1602                 do_disconnect("sigint", 1);
1603                 exit(1);
1604         } else
1605                 fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
1606 }
1607
1608 int obd_initialize(int argc, char **argv)
1609 {
1610         SHMEM_SETUP();
1611         return 0;
1612 }
1613
1614
1615 void obd_cleanup(int argc, char **argv)
1616 {
1617         struct sigaction sigact;
1618
1619         sigact.sa_handler = signal_server;
1620         sigfillset(&sigact.sa_mask);
1621         sigact.sa_flags = SA_RESTART;
1622         sigaction(SIGINT, &sigact, NULL);
1623
1624         do_disconnect(argv[0], 1);
1625 }