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