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