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