Whamcloud - gitweb
merge b_devel into HEAD (20030626 merge tag) for 0.7.1
[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
39 #ifndef __KERNEL__
40 #include <liblustre.h>
41 #endif
42 #include <linux/lustre_lib.h>
43 #include <linux/lustre_idl.h>
44 #include <linux/lustre_dlm.h>
45 #include <linux/obd.h>          /* for struct lov_stripe_md */
46 #include <linux/lustre_build_version.h>
47
48 #include <unistd.h>
49 #include <sys/un.h>
50 #include <time.h>
51 #include <sys/time.h>
52 #include <errno.h>
53 #include <string.h>
54
55 #include <asm/page.h>           /* needed for PAGE_SIZE - rread */
56
57 #define __KERNEL__
58 #include <linux/list.h>
59 #undef __KERNEL__
60
61 #include "obdctl.h"
62 #include <portals/ptlctl.h>
63 #include "parser.h"
64 #include <stdio.h>
65
66 #define SHMEM_STATS 1
67 #if SHMEM_STATS
68 # include <sys/ipc.h>
69 # include <sys/shm.h>
70
71 # define MAX_SHMEM_COUNT 1024
72 static long long *shared_counters;
73 static long long counter_snapshot[2][MAX_SHMEM_COUNT];
74 struct timeval prev_time;
75 #endif
76
77 uint64_t conn_cookie = -1;
78 char rawbuf[8192];
79 char *buf = rawbuf;
80 int max = sizeof(rawbuf);
81
82 static int thread;
83
84 union lsm_buffer {
85         char                 space [4096];
86         struct lov_stripe_md lsm;
87 } lsm_buffer;
88
89 static char *cmdname(char *func);
90
91 #define IOC_INIT(data)                                                  \
92 do {                                                                    \
93         memset(&data, 0, sizeof(data));                                 \
94         data.ioc_cookie = conn_cookie;                                  \
95 } while (0)
96
97 #define IOC_PACK(func, data)                                            \
98 do {                                                                    \
99         memset(buf, 0, sizeof(rawbuf));                                 \
100         if (obd_ioctl_pack(&data, &buf, max)) {                         \
101                 fprintf(stderr, "error: %s: invalid ioctl\n",           \
102                         cmdname(func));                                 \
103                 return -2;                                              \
104         }                                                               \
105 } while (0)
106
107 #define IOC_UNPACK(func, data)                                          \
108 do {                                                                    \
109         if (obd_ioctl_unpack(&data, buf, max)) {                        \
110                 fprintf(stderr, "error: %s: invalid reply\n",           \
111                         cmdname(func));                                 \
112                 return -2;                                              \
113         }                                                               \
114 } while (0)
115
116 char *obdo_print(struct obdo *obd)
117 {
118         char buf[1024];
119
120         sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
121                 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
122                 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
123                 "obdflags: %x\nnlink: %d,\nvalid %x\n",
124                 obd->o_id, obd->o_gr, obd->o_atime, obd->o_mtime, obd->o_ctime,
125                 obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
126                 obd->o_uid, obd->o_gid, obd->o_flags, obd->o_obdflags,
127                 obd->o_nlink, obd->o_valid);
128         return strdup(buf);
129 }
130
131
132 #define BAD_VERBOSE (-999999999)
133
134 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
135
136 static int do_name2dev(char *func, char *name)
137 {
138         struct obd_ioctl_data data;
139         int rc;
140
141         IOC_INIT(data);
142
143         data.ioc_inllen1 = strlen(name) + 1;
144         data.ioc_inlbuf1 = name;
145
146         IOC_PACK(func, data);
147         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
148         if (rc < 0)
149                 return errno;
150         IOC_UNPACK(func, data);
151
152         return data.ioc_dev + N2D_OFF;
153 }
154
155 static int do_uuid2dev(char *func, char *uuid)
156 {
157         struct obd_ioctl_data data;
158         int rc;
159
160         IOC_INIT(data);
161
162         data.ioc_inllen1 = strlen(uuid) + 1;
163         data.ioc_inlbuf1 = uuid;
164
165         IOC_PACK(func, data);
166         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_UUID2DEV, buf);
167         if (rc < 0)
168                 return errno;
169         IOC_UNPACK(func, data);
170
171         return data.ioc_dev + N2D_OFF;
172 }
173
174 /*
175  * resolve a device name to a device number.
176  * supports a number, $name or %uuid.
177  */
178 static int parse_devname(char *func, char *name)
179 {
180         int rc;
181         int ret = -1;
182
183         if (!name)
184                 return ret;
185         if (name[0] == '$') {
186                 name++;
187                 rc = do_name2dev(func, name);
188                 if (rc >= N2D_OFF) {
189                         ret = rc - N2D_OFF;
190                         printf("Name %s is device %d\n", name, ret);
191                 } else {
192                         printf("No device found for name %s: %s\n",
193                                name, strerror(rc));
194                 }
195         } else if (name[0] == '%') {
196                 name++;
197                 rc = do_uuid2dev(func, name);
198                 if (rc >= N2D_OFF) {
199                         ret = rc - N2D_OFF;
200                         printf("UUID %s is device %d\n", name, ret);
201                 } else {
202                         printf("No device found for UUID %s: %s\n",
203                                name, strerror(rc));
204                 }
205         } else {
206                 /* Assume it's a number.  This means that bogus strings become
207                  * 0.  I might care about that some day. */
208                 ret = strtoul(name, NULL, 0);
209                 printf("Selected device %d\n", ret);
210         }
211
212         return ret;
213 }
214
215 static char *
216 lsm_string (struct lov_stripe_md *lsm)
217 {
218         static char buffer[4096];
219         char       *p = buffer;
220         int         space = sizeof (buffer);
221         int         i;
222         int         nob;
223
224         *p = 0;
225         space--;
226
227         nob = snprintf(p, space, LPX64, lsm->lsm_object_id);
228         p += nob;
229         space -= nob;
230
231         if (lsm->lsm_stripe_count != 0) {
232                 nob = snprintf (p, space, "=%u#%u@%d",
233                                 lsm->lsm_stripe_size,
234                                 lsm->lsm_stripe_count,
235                                 lsm->lsm_stripe_offset);
236                 p += nob;
237                 space -= nob;
238
239                 for (i = 0; i < lsm->lsm_stripe_count; i++) {
240                         nob = snprintf (p, space, ":"LPX64,
241                                         lsm->lsm_oinfo[i].loi_id);
242                         p += nob;
243                         space -= nob;
244                 }
245         }
246
247         if (space == 0) {                       /* probable overflow */
248                 fprintf (stderr, "lsm_string() overflowed buffer\n");
249                 abort ();
250         }
251
252         return (buffer);
253 }
254
255 static void
256 reset_lsmb (union lsm_buffer *lsmb)
257 {
258         memset (lsmb->space, 0, sizeof (lsmb->space));
259         lsmb->lsm.lsm_magic = LOV_MAGIC;
260 }
261
262 static int
263 parse_lsm (union lsm_buffer *lsmb, char *string)
264 {
265         struct lov_stripe_md *lsm = &lsmb->lsm;
266         char                 *end;
267         int                   i;
268
269         /*
270          * object_id[=size#count[@offset][:id]*]
271          */
272
273         reset_lsmb (lsmb);
274
275         lsm->lsm_object_id = strtoull (string, &end, 0);
276         if (end == string)
277                 return (-1);
278         string = end;
279
280         if (*string == 0)
281                 return (0);
282
283         if (*string != '=')
284                 return (-1);
285         string++;
286
287         lsm->lsm_stripe_size = strtoul (string, &end, 0);
288         if (end == string)
289                 return (-1);
290         string = end;
291
292         if (*string != '#')
293                 return (-1);
294         string++;
295
296         lsm->lsm_stripe_count = strtoul (string, &end, 0);
297         if (end == string)
298                 return (-1);
299         string = end;
300
301         if (*string == '@') {
302                 string++;
303                 lsm->lsm_stripe_offset = strtol (string, &end, 0);
304                 if (end == string)
305                         return (-1);
306                 string = end;
307         }
308
309         if (*string == 0)               /* don't have to specify obj ids */
310                 return (0);
311
312         for (i = 0; i < lsm->lsm_stripe_count; i++) {
313                 if (*string != ':')
314                         return (-1);
315                 string++;
316                 lsm->lsm_oinfo[i].loi_id = strtoull (string, &end, 0);
317                 string = end;
318         }
319
320         if (*string != 0)
321                 return (-1);
322
323         return (0);
324 }
325
326 static char *cmdname(char *func)
327 {
328         static char buf[512];
329
330         if (thread) {
331                 sprintf(buf, "%s-%d", func, thread);
332                 return buf;
333         }
334
335         return func;
336 }
337
338 #define difftime(a, b)                                          \
339         ((double)(a)->tv_sec - (b)->tv_sec +                    \
340          ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
341
342 static int be_verbose(int verbose, struct timeval *next_time,
343                       __u64 num, __u64 *next_num, int num_total)
344 {
345         struct timeval now;
346
347         if (!verbose)
348                 return 0;
349
350         if (next_time != NULL)
351                 gettimeofday(&now, NULL);
352
353         /* A positive verbosity means to print every X iterations */
354         if (verbose > 0 &&
355             (next_num == NULL || num >= *next_num || num >= num_total)) {
356                 *next_num += verbose;
357                 if (next_time) {
358                         next_time->tv_sec = now.tv_sec - verbose;
359                         next_time->tv_usec = now.tv_usec;
360                 }
361                 return 1;
362         }
363
364         /* A negative verbosity means to print at most each X seconds */
365         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
366                 next_time->tv_sec = now.tv_sec - verbose;
367                 next_time->tv_usec = now.tv_usec;
368                 if (next_num)
369                         *next_num = num;
370                 return 1;
371         }
372
373         return 0;
374 }
375
376 static int get_verbose(char *func, const char *arg)
377 {
378         int verbose;
379         char *end;
380
381         if (!arg || arg[0] == 'v')
382                 verbose = 1;
383         else if (arg[0] == 's' || arg[0] == 'q')
384                 verbose = 0;
385         else {
386                 verbose = (int)strtoul(arg, &end, 0);
387                 if (*end) {
388                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
389                                 cmdname(func), arg);
390                         return BAD_VERBOSE;
391                 }
392         }
393
394         if (verbose < 0)
395                 printf("Print status every %d seconds\n", -verbose);
396         else if (verbose == 1)
397                 printf("Print status every operation\n");
398         else if (verbose > 1)
399                 printf("Print status every %d operations\n", verbose);
400
401         return verbose;
402 }
403
404 int do_disconnect(char *func, int verbose)
405 {
406         int rc;
407         struct obd_ioctl_data data;
408
409         if (conn_cookie == -1)
410                 return 0;
411
412         IOC_INIT(data);
413
414         IOC_PACK(func, data);
415         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DISCONNECT, buf);
416         if (rc < 0) {
417                 fprintf(stderr, "error: %s: OPD_IOC_DISCONNECT %s\n",
418                         cmdname(func),strerror(errno));
419         } else {
420                 if (verbose)
421                         printf("%s: disconnected conn "LPX64"\n", cmdname(func),
422                                conn_cookie);
423                 conn_cookie = -1;
424         }
425
426         return rc;
427 }
428
429 #if SHMEM_STATS
430 static void shmem_setup(void)
431 {
432         /* Create new segment */
433         int shmid = shmget(IPC_PRIVATE, sizeof(counter_snapshot[0]), 0600);
434
435         if (shmid == -1) {
436                 fprintf(stderr, "Can't create shared memory counters: %s\n",
437                         strerror(errno));
438                 return;
439         }
440
441         /* Attatch to new segment */
442         shared_counters = (long long *)shmat(shmid, NULL, 0);
443
444         if (shared_counters == (long long *)(-1)) {
445                 fprintf(stderr, "Can't attach shared memory counters: %s\n",
446                         strerror(errno));
447                 shared_counters = NULL;
448                 return;
449         }
450
451         /* Mark segment as destroyed, so it will disappear when we exit.
452          * Forks will inherit attached segments, so we should be OK.
453          */
454         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
455                 fprintf(stderr, "Can't destroy shared memory counters: %s\n",
456                         strerror(errno));
457         }
458 }
459
460 static inline void shmem_reset(void)
461 {
462         if (shared_counters == NULL)
463                 return;
464
465         memset(shared_counters, 0, sizeof(counter_snapshot[0]));
466         memset(counter_snapshot, 0, sizeof(counter_snapshot));
467         gettimeofday(&prev_time, NULL);
468 }
469
470 static inline void shmem_bump(void)
471 {
472         if (shared_counters == NULL || thread <= 0 || thread > MAX_SHMEM_COUNT)
473                 return;
474
475         shared_counters[thread - 1]++;
476 }
477
478 static void shmem_snap(int n)
479 {
480         struct timeval this_time;
481         int non_zero = 0;
482         long long total = 0;
483         double secs;
484         int i;
485
486         if (shared_counters == NULL || n > MAX_SHMEM_COUNT)
487                 return;
488
489         memcpy(counter_snapshot[1], counter_snapshot[0],
490                n * sizeof(counter_snapshot[0][0]));
491         memcpy(counter_snapshot[0], shared_counters,
492                n * sizeof(counter_snapshot[0][0]));
493         gettimeofday(&this_time, NULL);
494
495         for (i = 0; i < n; i++) {
496                 long long this_count =
497                         counter_snapshot[0][i] - counter_snapshot[1][i];
498
499                 if (this_count != 0) {
500                         non_zero++;
501                         total += this_count;
502                 }
503         }
504
505         secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
506                 (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
507
508         printf("%d/%d Total: %f/second\n", non_zero, n, total / secs);
509
510         prev_time = this_time;
511 }
512
513 #define SHMEM_SETUP()   shmem_setup()
514 #define SHMEM_RESET()   shmem_reset()
515 #define SHMEM_BUMP()    shmem_bump()
516 #define SHMEM_SNAP(n)   shmem_snap(n)
517 #else
518 #define SHMEM_SETUP()
519 #define SHMEM_RESET()
520 #define SHMEM_BUMP()
521 #define SHMEM_SNAP(n)
522 #endif
523
524 extern command_t cmdlist[];
525
526 static int do_device(char *func, int dev)
527 {
528         struct obd_ioctl_data data;
529
530         memset(&data, 0, sizeof(data));
531
532         data.ioc_dev = dev;
533
534         IOC_PACK(func, data);
535         return l_ioctl(OBD_DEV_ID, OBD_IOC_DEVICE, buf);
536 }
537
538 int jt_obd_device(int argc, char **argv)
539 {
540         int rc, dev;
541         do_disconnect(argv[0], 1);
542
543         if (argc != 2)
544                 return CMD_HELP;
545
546         dev = parse_devname(argv[0], argv[1]);
547         if (dev < 0)
548                 return -1;
549
550         rc = do_device(argv[0], dev);
551         if (rc < 0)
552                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
553                         strerror(rc = errno));
554
555         return rc;
556 }
557
558 int jt_obd_connect(int argc, char **argv)
559 {
560         struct obd_ioctl_data data;
561         int rc;
562
563         IOC_INIT(data);
564
565         do_disconnect(argv[0], 1);
566
567         /* XXX TODO: implement timeout per lctl usage for probe */
568         if (argc != 1)
569                 return CMD_HELP;
570
571         IOC_PACK(argv[0], data);
572         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CONNECT, buf);
573         IOC_UNPACK(argv[0], data);
574         if (rc < 0)
575                 fprintf(stderr, "error: %s: OBD_IOC_CONNECT %s\n",
576                         cmdname(argv[0]), strerror(rc = errno));
577         else
578                 conn_cookie = data.ioc_cookie;
579         return rc;
580 }
581
582 int jt_obd_disconnect(int argc, char **argv)
583 {
584         if (argc != 1)
585                 return CMD_HELP;
586
587         if (conn_cookie == -1)
588                 return 0;
589
590         return do_disconnect(argv[0], 0);
591 }
592
593 int jt_opt_device(int argc, char **argv)
594 {
595         char *arg2[3];
596         int ret;
597         int rc;
598
599         if (argc < 3)
600                 return CMD_HELP;
601
602         rc = do_device("device", parse_devname(argv[0], argv[1]));
603
604         if (!rc) {
605                 arg2[0] = "connect";
606                 arg2[1] = NULL;
607                 rc = jt_obd_connect(1, arg2);
608         }
609
610         if (!rc)
611                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
612
613         ret = do_disconnect(argv[0], 0);
614         if (!rc)
615                 rc = ret;
616
617         return rc;
618 }
619
620 int jt_opt_threads(int argc, char **argv)
621 {
622         __u64 threads, next_thread;
623         int verbose;
624         int rc = 0;
625         char *end;
626         int i;
627
628         if (argc < 5)
629                 return CMD_HELP;
630
631         threads = strtoull(argv[1], &end, 0);
632         if (*end) {
633                 fprintf(stderr, "error: %s: invalid page count '%s'\n",
634                         cmdname(argv[0]), argv[1]);
635                 return CMD_HELP;
636         }
637
638         verbose = get_verbose(argv[0], argv[2]);
639         if (verbose == BAD_VERBOSE)
640                 return CMD_HELP;
641
642         if (verbose != 0)
643                 printf("%s: starting "LPD64" threads on device %s running %s\n",
644                        argv[0], threads, argv[3], argv[4]);
645
646         SHMEM_RESET();
647
648         for (i = 1, next_thread = verbose; i <= threads; i++) {
649                 rc = fork();
650                 if (rc < 0) {
651                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
652                                 strerror(rc = errno));
653                         break;
654                 } else if (rc == 0) {
655                         thread = i;
656                         argv[2] = "--device";
657                         return jt_opt_device(argc - 2, argv + 2);
658                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
659                         printf("%s: thread #%d (PID %d) started\n",
660                                argv[0], i, rc);
661                 rc = 0;
662         }
663
664         if (!thread) {          /* parent process */
665                 int live_threads = threads;
666
667                 while (live_threads > 0) {
668                         int status;
669                         pid_t ret;
670
671                         ret = waitpid(0, &status, verbose < 0 ? WNOHANG : 0);
672                         if (ret == 0) {
673                                 if (verbose >= 0)
674                                         abort();
675
676                                 sleep(-verbose);
677                                 SHMEM_SNAP(threads);
678                                 continue;
679                         }
680
681                         if (ret < 0) {
682                                 fprintf(stderr, "error: %s: wait - %s\n",
683                                         argv[0], strerror(errno));
684                                 if (!rc)
685                                         rc = errno;
686                         } else {
687                                 /*
688                                  * This is a hack.  We _should_ be able to use
689                                  * WIFEXITED(status) to see if there was an
690                                  * error, but it appears to be broken and it
691                                  * always returns 1 (OK).  See wait(2).
692                                  */
693                                 int err = WEXITSTATUS(status);
694                                 if (err || WIFSIGNALED(status))
695                                         fprintf(stderr,
696                                                 "%s: PID %d had rc=%d\n",
697                                                 argv[0], ret, err);
698                                 if (!rc)
699                                         rc = err;
700
701                                 live_threads--;
702                         }
703                 }
704         }
705
706         return rc;
707 }
708
709 int jt_obd_detach(int argc, char **argv)
710 {
711         struct obd_ioctl_data data;
712         int rc;
713
714         IOC_INIT(data);
715
716         if (argc != 1)
717                 return CMD_HELP;
718
719         IOC_PACK(argv[0], data);
720         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DETACH, buf);
721         if (rc < 0)
722                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
723                         strerror(rc = errno));
724
725         return rc;
726 }
727
728 int jt_obd_cleanup(int argc, char **argv)
729 {
730         struct obd_ioctl_data data;
731         char force = 'F';
732         char failover = 'A';
733         char flags[3];
734         int flag_cnt = 0, n;
735         int rc;
736
737         IOC_INIT(data);
738
739         if (argc < 1 || argc > 3)
740                 return CMD_HELP;
741
742         for (n = 1; n < argc; n++) 
743                 if (strcmp(argv[n], "force") == 0) {
744                         flags[flag_cnt++] = force;
745                 } else if (strcmp(argv[n], "failover") == 0) {
746                         flags[flag_cnt++] = failover;
747                 } else {
748                         fprintf(stderr, "unknown option: %s", argv[n]);
749                         return CMD_HELP;
750                 }
751
752         data.ioc_inllen1 = flag_cnt;
753         if (flag_cnt)
754                 data.ioc_inlbuf1 = flags;
755
756         IOC_PACK(argv[0], data);
757         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLEANUP, buf);
758         if (rc < 0)
759                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
760                         strerror(rc = errno));
761
762         return rc;
763 }
764
765 int jt_obd_no_transno(int argc, char **argv)
766 {
767         struct obd_ioctl_data data;
768         int rc;
769
770         IOC_INIT(data);
771
772         if (argc != 1)
773                 return CMD_HELP;
774
775         IOC_PACK(argv[0], data);
776         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf);
777         if (rc < 0)
778                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
779                         strerror(rc = errno));
780
781         return rc;
782 }
783
784 int jt_obd_set_readonly(int argc, char **argv)
785 {
786         struct obd_ioctl_data data;
787         int rc;
788
789         IOC_INIT(data);
790
791         if (argc != 1)
792                 return CMD_HELP;
793
794         IOC_PACK(argv[0], data);
795         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf);
796         if (rc < 0)
797                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
798                         strerror(rc = errno));
799
800         return rc;
801 }
802
803 int jt_obd_abort_recovery(int argc, char **argv)
804 {
805         struct obd_ioctl_data data;
806         int rc;
807
808         IOC_INIT(data);
809
810         if (argc != 1)
811                 return CMD_HELP;
812
813         IOC_PACK(argv[0], data);
814         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf);
815         if (rc < 0)
816                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
817                         strerror(rc = errno));
818
819         return rc;
820 }
821
822 int jt_obd_newdev(int argc, char **argv)
823 {
824         int rc;
825         struct obd_ioctl_data data;
826
827         IOC_INIT(data);
828
829         if (argc != 1)
830                 return CMD_HELP;
831
832         IOC_PACK(argv[0], data);
833         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NEWDEV, buf);
834         if (rc < 0)
835                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
836                         strerror(rc = errno));
837         else {
838                 IOC_UNPACK(argv[0], data);
839                 printf("Current device set to %d\n", data.ioc_dev);
840         }
841
842         return rc;
843 }
844
845 int jt_obd_mount_option(int argc, char **argv)
846 {
847         int rc;
848         struct obd_ioctl_data data;
849
850         IOC_INIT(data);
851
852         if (argc != 2)
853                 return CMD_HELP;
854
855         data.ioc_inllen1 = strlen(argv[1]) + 1;
856         data.ioc_inlbuf1 = argv[1];
857
858         IOC_PACK(argv[0], data);
859         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_MOUNTOPT, buf);
860         if (rc < 0) {
861                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
862                         strerror(rc = errno));
863         }
864
865         return rc;
866 }
867
868 int jt_get_version(int argc, char **argv)
869 {
870         int rc;
871         char buf[8192];
872         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
873
874         if (argc != 1)
875                 return CMD_HELP;
876
877         memset(buf, 0, sizeof(buf));
878         data->ioc_version = OBD_IOCTL_VERSION;
879         data->ioc_cookie = conn_cookie;
880         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
881         data->ioc_len = obd_ioctl_packlen(data);
882
883         rc = l_ioctl(OBD_DEV_ID, OBD_GET_VERSION, buf);
884         if (rc < 0)
885                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
886                         strerror(rc = errno));
887         else {
888                 printf("Lustre version: %s\n", data->ioc_bulk);
889         }
890
891         printf("lctl   version: %s\n", BUILD_VERSION);
892         return rc;
893 }
894
895 int jt_obd_list(int argc, char **argv)
896 {
897         int rc;
898         char buf[8192];
899         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
900
901         if (argc != 1)
902                 return CMD_HELP;
903
904         memset(buf, 0, sizeof(buf));
905         data->ioc_version = OBD_IOCTL_VERSION;
906         data->ioc_cookie = conn_cookie;
907         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
908         data->ioc_len = obd_ioctl_packlen(data);
909
910         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LIST, data);
911         if (rc < 0)
912                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
913                         strerror(rc = errno));
914         else {
915                 printf("%s", data->ioc_bulk);
916         }
917
918         return rc;
919 }
920
921 int jt_obd_attach(int argc, char **argv)
922 {
923         struct obd_ioctl_data data;
924         int rc;
925
926         IOC_INIT(data);
927
928         if (argc != 2 && argc != 3 && argc != 4)
929                 return CMD_HELP;
930
931         data.ioc_inllen1 = strlen(argv[1]) + 1;
932         data.ioc_inlbuf1 = argv[1];
933         if (argc >= 3) {
934                 data.ioc_inllen2 = strlen(argv[2]) + 1;
935                 data.ioc_inlbuf2 = argv[2];
936         }
937
938         if (argc == 4) {
939                 data.ioc_inllen3 = strlen(argv[3]) + 1;
940                 data.ioc_inlbuf3 = argv[3];
941         }
942
943         IOC_PACK(argv[0], data);
944         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ATTACH, buf);
945         if (rc < 0)
946                 fprintf(stderr, "error: %s: OBD_IOC_ATTACH %s\n",
947                         cmdname(argv[0]), strerror(rc = errno));
948         else if (argc == 3) {
949                 char name[1024];
950                 if (strlen(argv[2]) > 128) {
951                         printf("Name too long to set environment\n");
952                         return -EINVAL;
953                 }
954                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
955                 rc = setenv(name, argv[1], 1);
956                 if (rc) {
957                         printf("error setting env variable %s\n", name);
958                 }
959         }
960
961         return rc;
962 }
963
964 int jt_obd_setup(int argc, char **argv)
965 {
966         struct obd_ioctl_data data;
967         int rc;
968
969         IOC_INIT(data);
970
971         if (argc > 5)
972                 return CMD_HELP;
973
974         data.ioc_dev = -1;
975         if (argc > 1) {
976                 data.ioc_dev = parse_devname(argv[0], argv[1]);
977                 if (data.ioc_dev < 0)
978                         return -1;
979                 data.ioc_inllen1 = strlen(argv[1]) + 1;
980                 data.ioc_inlbuf1 = argv[1];
981         }
982         if (argc > 2) {
983                 data.ioc_inllen2 = strlen(argv[2]) + 1;
984                 data.ioc_inlbuf2 = argv[2];
985         }
986         if (argc > 3) {
987                 data.ioc_inllen3 = strlen(argv[3]) + 1;
988                 data.ioc_inlbuf3 = argv[3];
989         }
990         if (argc > 4) {
991                 data.ioc_inllen4 = strlen(argv[4]) + 1;
992                 data.ioc_inlbuf4 = argv[4];
993         }
994
995         IOC_PACK(argv[0], data);
996         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SETUP, buf);
997         if (rc < 0)
998                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
999                         strerror(rc = errno));
1000
1001         return rc;
1002 }
1003
1004 /* Get echo client's stripe meta-data for the given object
1005  */
1006 int jt_obd_get_stripe (int argc, char **argv)
1007 {
1008         struct obd_ioctl_data data;
1009         __u64 id;
1010         int   rc;
1011         char *end;
1012
1013         if (argc != 2)
1014                 return (CMD_HELP);
1015
1016         id = strtoull (argv[1], &end, 0);
1017         if (*end) {
1018                 fprintf (stderr, "Error: %s: invalid object id '%s'\n",
1019                          cmdname (argv[0]), argv[1]);
1020                 return (CMD_HELP);
1021         }
1022
1023         memset (&lsm_buffer, 0, sizeof (lsm_buffer));
1024
1025         IOC_INIT (data);
1026         data.ioc_obdo1.o_id = id;
1027         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1028         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1029         data.ioc_pbuf1 = (char *)&lsm_buffer;
1030         data.ioc_plen1 = sizeof (lsm_buffer);
1031
1032         IOC_PACK(argv[0], data);
1033         rc = l_ioctl(OBD_DEV_ID, ECHO_IOC_GET_STRIPE, buf);
1034         IOC_UNPACK(argv[0], data);
1035
1036         if (rc != 0) {
1037                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1038                          cmdname (argv[0]), rc, strerror (errno));
1039                 return (rc);
1040         }
1041
1042         printf ("%s\n", lsm_string (&lsm_buffer.lsm));
1043
1044         return (rc);
1045 }
1046
1047 /* Set stripe meta-data for 1 or more objects.  Object must be new to
1048  * this echo client instance.
1049  */
1050 int jt_obd_set_stripe (int argc, char **argv)
1051 {
1052         struct obd_ioctl_data data;
1053         char *end;
1054         int count = 1;
1055         int i;
1056         int rc;
1057
1058         if (argc < 2 || argc > 3)
1059                 return CMD_HELP;
1060
1061         rc = parse_lsm (&lsm_buffer, argv[1]);
1062         if (rc != 0) {
1063                 fprintf (stderr, "error: %s: invalid object '%s'\n",
1064                          cmdname (argv[0]), argv[1]);
1065                 return CMD_HELP;
1066         }
1067
1068         if (argc > 2) {
1069                 count = strtol (argv[2], &end, 0);
1070                 if (*end != 0) {
1071                         fprintf (stderr, "error: %s: invalid count '%s'\n",
1072                                  cmdname (argv[0]), argv[1]);
1073                         return CMD_HELP;
1074                 }
1075         }
1076
1077         for (i = 0; i < count; i++) {
1078                 IOC_INIT (data);
1079                 data.ioc_obdo1.o_id = lsm_buffer.lsm.lsm_object_id + i;
1080                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1081                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1082                 data.ioc_pbuf1 = (char *)&lsm_buffer;
1083                 data.ioc_plen1 = sizeof (lsm_buffer);
1084
1085                 IOC_PACK (argv[0], data);
1086                 rc = l_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1087                 IOC_UNPACK (argv[0], data);
1088
1089                 if (rc != 0) {
1090                         fprintf (stderr, "Error: %s: rc %d(%s)\n",
1091                                  cmdname (argv[0]), rc, strerror (errno));
1092                         return (rc);
1093                 }
1094         }
1095
1096         return (0);
1097 }
1098
1099 /* Clear stripe meta-data info for an object on this echo-client instance
1100  */
1101 int jt_obd_unset_stripe (int argc, char **argv)
1102 {
1103         struct obd_ioctl_data data;
1104         char *end;
1105         obd_id id;
1106         int rc;
1107
1108         if (argc != 2)
1109                 return CMD_HELP;
1110
1111         id = strtoull (argv[1], &end, 0);
1112         if (*end != 0) {
1113                 fprintf (stderr, "error: %s: invalid object id '%s'\n",
1114                          cmdname (argv[0]), argv[1]);
1115                 return CMD_HELP;
1116         }
1117
1118         IOC_INIT (data);
1119         data.ioc_obdo1.o_id = id;
1120         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1121         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1122
1123         IOC_PACK (argv[0], data);
1124         rc = l_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1125         IOC_UNPACK (argv[0], data);
1126
1127         if (rc != 0)
1128                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1129                          cmdname (argv[0]), rc, strerror (errno));
1130
1131         return (0);
1132 }
1133
1134 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1135  * not, defaults assumed.  This echo-client instance stashes the stripe
1136  * object ids.  Use get_stripe on this node to print full lsm and
1137  * set_stripe on another node to cut/paste between nodes.
1138  */
1139 int jt_obd_create(int argc, char **argv)
1140 {
1141         static __u64 base_id = 1;
1142
1143         struct obd_ioctl_data data;
1144         struct timeval next_time;
1145         __u64 count = 1, next_count;
1146         int verbose = 1, mode = 0100644, rc = 0, i;
1147         char *end;
1148
1149         IOC_INIT(data);
1150         if (argc < 2 || argc > 5)
1151                 return CMD_HELP;
1152
1153         count = strtoull(argv[1], &end, 0);
1154         if (*end) {
1155                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1156                         cmdname(argv[0]), argv[1]);
1157                 return CMD_HELP;
1158         }
1159
1160         if (argc > 2) {
1161                 mode = strtoul(argv[2], &end, 0);
1162                 if (*end) {
1163                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1164                                 cmdname(argv[0]), argv[2]);
1165                         return CMD_HELP;
1166                 }
1167                 if (!(mode & S_IFMT))
1168                         mode |= S_IFREG;
1169         }
1170
1171         if (argc > 3) {
1172                 verbose = get_verbose(argv[0], argv[3]);
1173                 if (verbose == BAD_VERBOSE)
1174                         return CMD_HELP;
1175         }
1176
1177         if (argc < 5)
1178                 reset_lsmb (&lsm_buffer);       /* will set default */
1179         else {
1180                 rc = parse_lsm (&lsm_buffer, argv[4]);
1181                 if (rc != 0) {
1182                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1183                                 cmdname(argv[0]), argv[4]);
1184                         return CMD_HELP;
1185                 }
1186                 base_id = lsm_buffer.lsm.lsm_object_id;
1187         }
1188
1189         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
1190         gettimeofday(&next_time, NULL);
1191         next_time.tv_sec -= verbose;
1192
1193         for (i = 1, next_count = verbose; i <= count; i++) {
1194                 data.ioc_obdo1.o_mode = mode;
1195                 data.ioc_obdo1.o_id = base_id++;
1196                 data.ioc_obdo1.o_uid = 0;
1197                 data.ioc_obdo1.o_gid = 0;
1198                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1199                                          OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1200
1201                 data.ioc_plen1 = sizeof (lsm_buffer);
1202                 data.ioc_pbuf1 = (char *)&lsm_buffer;
1203
1204                 IOC_PACK(argv[0], data);
1205                 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1206                 IOC_UNPACK(argv[0], data);
1207                 SHMEM_BUMP();
1208                 if (rc < 0) {
1209                         fprintf(stderr, "error: %s: #%d - %s\n",
1210                                 cmdname(argv[0]), i, strerror(rc = errno));
1211                         break;
1212                 }
1213                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1214                         fprintf(stderr, "error: %s: objid not valid #%d:%08x\n",
1215                                 cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1216                         rc = EINVAL;
1217                         break;
1218                 }
1219
1220                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1221                         printf("%s: #%d is object id "LPX64"\n",
1222                                 cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1223         }
1224         return rc;
1225 }
1226
1227 int jt_obd_setattr(int argc, char **argv)
1228 {
1229         struct obd_ioctl_data data;
1230         char *end;
1231         int rc;
1232
1233         IOC_INIT(data);
1234         if (argc != 2)
1235                 return CMD_HELP;
1236
1237         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1238         if (*end) {
1239                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1240                         cmdname(argv[0]), argv[1]);
1241                 return CMD_HELP;
1242         }
1243         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1244         if (*end) {
1245                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1246                         cmdname(argv[0]), argv[2]);
1247                 return CMD_HELP;
1248         }
1249         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1250
1251         IOC_PACK(argv[0], data);
1252         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1253         if (rc < 0)
1254                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1255                         strerror(rc = errno));
1256
1257         return rc;
1258 }
1259
1260 int jt_obd_destroy(int argc, char **argv)
1261 {
1262         struct obd_ioctl_data data;
1263         struct timeval next_time;
1264         __u64 count = 1, next_count;
1265         int verbose = 1;
1266         __u64 id;
1267         char *end;
1268         int rc = 0, i;
1269
1270         IOC_INIT(data);
1271         if (argc < 2 || argc > 4)
1272                 return CMD_HELP;
1273
1274         id = strtoull(argv[1], &end, 0);
1275         if (*end) {
1276                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1277                         cmdname(argv[0]), argv[1]);
1278                 return CMD_HELP;
1279         }
1280         if (argc > 2) {
1281                 count = strtoull(argv[2], &end, 0);
1282                 if (*end) {
1283                         fprintf(stderr,
1284                                 "error: %s: invalid iteration count '%s'\n",
1285                                 cmdname(argv[0]), argv[2]);
1286                         return CMD_HELP;
1287                 }
1288         }
1289
1290         if (argc > 3) {
1291                 verbose = get_verbose(argv[0], argv[3]);
1292                 if (verbose == BAD_VERBOSE)
1293                         return CMD_HELP;
1294         }
1295
1296         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
1297         gettimeofday(&next_time, NULL);
1298         next_time.tv_sec -= verbose;
1299
1300         for (i = 1, next_count = verbose; i <= count; i++, id++) {
1301                 data.ioc_obdo1.o_id = id;
1302                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1303                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1304
1305                 IOC_PACK(argv[0], data);
1306                 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1307                 IOC_UNPACK(argv[0], data);
1308                 SHMEM_BUMP();
1309                 if (rc < 0) {
1310                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1311                                 cmdname(argv[0]), id, strerror(rc = errno));
1312                         break;
1313                 }
1314
1315                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1316                         printf("%s: #%d is object id "LPX64"\n",
1317                                cmdname(argv[0]), i, id);
1318         }
1319
1320         return rc;
1321 }
1322
1323 int jt_obd_getattr(int argc, char **argv)
1324 {
1325         struct obd_ioctl_data data;
1326         char *end;
1327         int rc;
1328
1329         if (argc != 2)
1330                 return CMD_HELP;
1331
1332         IOC_INIT(data);
1333         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1334         if (*end) {
1335                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1336                         cmdname(argv[0]), argv[1]);
1337                 return CMD_HELP;
1338         }
1339         /* to help obd filter */
1340         data.ioc_obdo1.o_mode = 0100644;
1341         data.ioc_obdo1.o_valid = 0xffffffff;
1342         printf("%s: object id "LPX64"\n", cmdname(argv[0]),data.ioc_obdo1.o_id);
1343
1344         IOC_PACK(argv[0], data);
1345         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1346         IOC_UNPACK(argv[0], data);
1347         if (rc) {
1348                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1349                         strerror(rc = errno));
1350         } else {
1351                 printf("%s: object id "LPX64", mode %o\n", cmdname(argv[0]),
1352                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1353         }
1354         return rc;
1355 }
1356
1357 int jt_obd_test_getattr(int argc, char **argv)
1358 {
1359         struct obd_ioctl_data data;
1360         struct timeval start, next_time;
1361         __u64 i, count, next_count;
1362         int verbose = 1;
1363         obd_id objid = 3;
1364         char *end;
1365         int rc = 0;
1366
1367         if (argc < 2 && argc > 4)
1368                 return CMD_HELP;
1369
1370         IOC_INIT(data);
1371         count = strtoull(argv[1], &end, 0);
1372         if (*end) {
1373                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1374                         cmdname(argv[0]), argv[1]);
1375                 return CMD_HELP;
1376         }
1377
1378         if (argc >= 3) {
1379                 verbose = get_verbose(argv[0], argv[2]);
1380                 if (verbose == BAD_VERBOSE)
1381                         return CMD_HELP;
1382         }
1383
1384         if (argc >= 4) {
1385                 if (argv[3][0] == 't') {
1386                         objid = strtoull(argv[3] + 1, &end, 0);
1387                         if (thread)
1388                                 objid += thread - 1;
1389                 } else
1390                         objid = strtoull(argv[3], &end, 0);
1391                 if (*end) {
1392                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1393                                 cmdname(argv[0]), argv[3]);
1394                         return CMD_HELP;
1395                 }
1396         }
1397
1398         gettimeofday(&start, NULL);
1399         next_time.tv_sec = start.tv_sec - verbose;
1400         next_time.tv_usec = start.tv_usec;
1401         if (verbose != 0)
1402                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1403                        cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1404
1405         for (i = 1, next_count = verbose; i <= count; i++) {
1406                 data.ioc_obdo1.o_id = objid;
1407                 data.ioc_obdo1.o_mode = S_IFREG;
1408                 data.ioc_obdo1.o_valid = 0xffffffff;
1409                 IOC_PACK(argv[0], data);
1410                 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1411                 SHMEM_BUMP();
1412                 if (rc < 0) {
1413                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1414                                 cmdname(argv[0]), i, errno, strerror(rc = errno));
1415                         break;
1416                 } else {
1417                         if (be_verbose
1418                             (verbose, &next_time, i, &next_count, count))
1419                                 printf("%s: got attr #"LPD64"\n",
1420                                        cmdname(argv[0]), i);
1421                 }
1422         }
1423
1424         if (!rc) {
1425                 struct timeval end;
1426                 double diff;
1427
1428                 gettimeofday(&end, NULL);
1429
1430                 diff = difftime(&end, &start);
1431
1432                 --i;
1433                 if (verbose != 0)
1434                         printf("%s: "LPD64" attrs in %.4gs (%.4g attr/s): %s",
1435                                cmdname(argv[0]), i, diff, (double)i / diff,
1436                                ctime(&end.tv_sec));
1437         }
1438         return rc;
1439 }
1440
1441 int jt_obd_test_brw(int argc, char **argv)
1442 {
1443         struct obd_ioctl_data data;
1444         struct timeval start, next_time;
1445         int pages = 1;
1446         __u64 count, next_count;
1447         __u64 objid = 3;
1448         int verbose = 1, write = 0, rw;
1449         char *end;
1450         int thr_offset = 0;
1451         int i;
1452         int len;
1453         int rc = 0;
1454
1455         if (argc < 2 || argc > 6) {
1456                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1457                         cmdname(argv[0]), argc);
1458                 return CMD_HELP;
1459         }
1460
1461         /* make each thread write to a different offset */
1462         if (argv[1][0] == 't') {
1463                 count = strtoull(argv[1] + 1, &end, 0);
1464                 if (thread)
1465                         thr_offset = thread - 1;
1466         } else
1467                 count = strtoull(argv[1], &end, 0);
1468
1469         if (*end) {
1470                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1471                         cmdname(argv[0]), argv[1]);
1472                 return CMD_HELP;
1473         }
1474
1475         if (argc >= 3) {
1476                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1477                         write = 1;
1478                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
1479                         write = 0;
1480         }
1481
1482         if (argc >= 4) {
1483                 verbose = get_verbose(argv[0], argv[3]);
1484                 if (verbose == BAD_VERBOSE)
1485                         return CMD_HELP;
1486         }
1487
1488         if (argc >= 5) {
1489                 pages = strtoul(argv[4], &end, 0);
1490                 if (*end) {
1491                         fprintf(stderr, "error: %s: bad page count '%s'\n",
1492                                 cmdname(argv[0]), argv[4]);
1493                         return CMD_HELP;
1494                 }
1495         }
1496         if (argc >= 6) {
1497                 if (argv[5][0] == 't') {
1498                         objid = strtoull(argv[5] + 1, &end, 0);
1499                         if (thread)
1500                                 objid += thread - 1;
1501                 } else
1502                         objid = strtoull(argv[5], &end, 0);
1503                 if (*end) {
1504                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1505                                 cmdname(argv[0]), argv[5]);
1506                         return CMD_HELP;
1507                 }
1508         }
1509
1510         len = pages * PAGE_SIZE;
1511
1512         IOC_INIT(data);
1513         data.ioc_obdo1.o_id = objid;
1514         data.ioc_obdo1.o_mode = S_IFREG;
1515         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1516         data.ioc_count = len;
1517         data.ioc_offset = thr_offset * len * count;
1518
1519         gettimeofday(&start, NULL);
1520         next_time.tv_sec = start.tv_sec - verbose;
1521         next_time.tv_usec = start.tv_usec;
1522
1523         if (verbose != 0)
1524                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1525                        cmdname(argv[0]), write ? "writing" : "reading", count,
1526                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1527
1528         IOC_PACK(argv[0], data);
1529         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_OPEN, buf);
1530         IOC_UNPACK(argv[0], data);
1531         if (rc) {
1532                 fprintf(stderr, "error: brw_open: %s\n", strerror(rc = errno));
1533                 return rc;
1534         }
1535
1536         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1537         for (i = 1, next_count = verbose; i <= count; i++) {
1538                 rc = l_ioctl(OBD_DEV_ID, rw, buf);
1539                 SHMEM_BUMP();
1540                 if (rc) {
1541                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1542                                 cmdname(argv[0]), i, strerror(rc = errno),
1543                                 write ? "write" : "read");
1544                         break;
1545                 } else if (be_verbose(verbose, &next_time,i, &next_count,count))
1546                         printf("%s: %s number %dx%d\n", cmdname(argv[0]),
1547                                write ? "write" : "read", i, pages);
1548
1549                 data.ioc_offset += len;
1550         }
1551
1552         if (!rc) {
1553                 struct timeval end;
1554                 double diff;
1555
1556                 gettimeofday(&end, NULL);
1557
1558                 diff = difftime(&end, &start);
1559
1560                 --i;
1561                 if (verbose != 0)
1562                         printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s",
1563                                cmdname(argv[0]), write ? "wrote" : "read",
1564                                i, pages, diff, (double)i * pages / diff,
1565                                ctime(&end.tv_sec));
1566         }
1567         rw = l_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE, buf);
1568         if (rw) {
1569                 fprintf(stderr, "error: brw_close: %s\n", strerror(rw = errno));
1570                 if (!rc)
1571                         rc = rw;
1572         }
1573
1574         return rc;
1575 }
1576
1577 int jt_obd_lov_setconfig(int argc, char **argv)
1578 {
1579         struct obd_ioctl_data data;
1580         struct lov_desc desc;
1581         struct obd_uuid *uuidarray, *ptr;
1582         int rc, i;
1583         char *end;
1584
1585         IOC_INIT(data);
1586
1587         if (argc <= 6)
1588                 return CMD_HELP;
1589
1590         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
1591                 fprintf(stderr,
1592                         "error: %s: LOV uuid '%s' longer than "LPSZ" chars\n",
1593                         cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
1594                 return -EINVAL;
1595         }
1596
1597         memset(&desc, 0, sizeof(desc));
1598         obd_str2uuid(&desc.ld_uuid, argv[1]);
1599         desc.ld_tgt_count = argc - 6;
1600         desc.ld_default_stripe_count = strtoul(argv[2], &end, 0);
1601         if (*end) {
1602                 fprintf(stderr, "error: %s: bad default stripe count '%s'\n",
1603                         cmdname(argv[0]), argv[2]);
1604                 return CMD_HELP;
1605         }
1606         if (desc.ld_default_stripe_count > desc.ld_tgt_count) {
1607                 fprintf(stderr,
1608                         "error: %s: default stripe count %u > OST count %u\n",
1609                         cmdname(argv[0]), desc.ld_default_stripe_count,
1610                         desc.ld_tgt_count);
1611                 return -EINVAL;
1612         }
1613
1614         desc.ld_default_stripe_size = strtoull(argv[3], &end, 0);
1615         if (*end) {
1616                 fprintf(stderr, "error: %s: bad default stripe size '%s'\n",
1617                         cmdname(argv[0]), argv[3]);
1618                 return CMD_HELP;
1619         }
1620         if (desc.ld_default_stripe_size < 4096) {
1621                 fprintf(stderr,
1622                         "error: %s: default stripe size "LPU64" too small\n",
1623                         cmdname(argv[0]), desc.ld_default_stripe_size);
1624                 return -EINVAL;
1625         } else if ((long)desc.ld_default_stripe_size <
1626                    desc.ld_default_stripe_size) {
1627                 fprintf(stderr,
1628                         "error: %s: default stripe size "LPU64" too large\n",
1629                         cmdname(argv[0]), desc.ld_default_stripe_size);
1630                 return -EINVAL;
1631         }
1632         desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0);
1633         if (*end) {
1634                 fprintf(stderr, "error: %s: bad default stripe offset '%s'\n",
1635                         cmdname(argv[0]), argv[4]);
1636                 return CMD_HELP;
1637         }
1638         desc.ld_pattern = strtoul(argv[5], &end, 0);
1639         if (*end) {
1640                 fprintf(stderr, "error: %s: bad stripe pattern '%s'\n",
1641                         cmdname(argv[0]), argv[5]);
1642                 return CMD_HELP;
1643         }
1644
1645         /* NOTE: it is possible to overwrite the default striping parameters,
1646          *       but EXTREME care must be taken when saving the OST UUID list.
1647          *       It must be EXACTLY the same, or have only additions at the
1648          *       end of the list, or only overwrite individual OST entries
1649          *       that are restored from backups of the previous OST.
1650          */
1651         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1652         if (!uuidarray) {
1653                 fprintf(stderr, "error: %s: no memory for %d UUIDs\n",
1654                         cmdname(argv[0]), desc.ld_tgt_count);
1655                 rc = -ENOMEM;
1656                 goto out;
1657         }
1658         for (i = 6, ptr = uuidarray; i < argc; i++, ptr++) {
1659                 if (strlen(argv[i]) >= sizeof(*ptr)) {
1660                         fprintf(stderr, "error: %s: arg %d (%s) too long\n",
1661                                 cmdname(argv[0]), i, argv[i]);
1662                         rc = -EINVAL;
1663                         goto out;
1664                 }
1665                 strcpy((char *)ptr, argv[i]);
1666         }
1667
1668         data.ioc_inllen1 = sizeof(desc);
1669         data.ioc_inlbuf1 = (char *)&desc;
1670         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1671         data.ioc_inlbuf2 = (char *)uuidarray;
1672
1673         if (obd_ioctl_pack(&data, &buf, max)) {
1674                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1675                 rc = -EINVAL;
1676                 goto out;
1677         }
1678         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LOV_SET_CONFIG, buf);
1679         if (rc)
1680                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1681                         cmdname(argv[0]), strerror(rc = errno));
1682 out:
1683         free(uuidarray);
1684         return rc;
1685 }
1686
1687 #define DEF_UUID_ARRAY_LEN (8192 / 40)
1688
1689 int jt_obd_lov_getconfig(int argc, char **argv)
1690 {
1691         struct obd_ioctl_data data;
1692         struct lov_desc desc;
1693         struct obd_uuid *uuidarray;
1694         char *path;
1695         int rc, fd;
1696
1697         IOC_INIT(data);
1698
1699         if (argc != 2)
1700                 return CMD_HELP;
1701
1702         path = argv[1];
1703         fd = open(path, O_RDONLY);
1704         if (fd < 0) {
1705                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1706                         strerror(errno));
1707                 return -1;
1708         }
1709
1710         memset(&desc, 0, sizeof(desc));
1711         obd_str2uuid(&desc.ld_uuid, argv[1]);
1712         desc.ld_tgt_count = DEF_UUID_ARRAY_LEN;
1713 repeat:
1714         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1715         if (!uuidarray) {
1716                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1717                         cmdname(argv[0]), desc.ld_tgt_count);
1718                 rc = -ENOMEM;
1719                 goto out;
1720         }
1721
1722         data.ioc_inllen1 = sizeof(desc);
1723         data.ioc_inlbuf1 = (char *)&desc;
1724         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1725         data.ioc_inlbuf2 = (char *)uuidarray;
1726
1727         if (obd_ioctl_pack(&data, &buf, max)) {
1728                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1729                 rc = -EINVAL;
1730                 goto out;
1731         }
1732         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1733         if (rc == -ENOSPC) {
1734                 free(uuidarray);
1735                 goto repeat;
1736         } else if (rc) {
1737                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1738                         cmdname(argv[0]), strerror(rc = errno));
1739         } else {
1740                 struct obd_uuid *ptr;
1741                 int i;
1742
1743                 if (obd_ioctl_unpack(&data, buf, max)) {
1744                         fprintf(stderr, "error: %s: invalid reply\n",
1745                                 cmdname(argv[0]));
1746                         rc = -EINVAL;
1747                         goto out;
1748                 }
1749                 printf("default_stripe_count: %u\n",
1750                        desc.ld_default_stripe_count);
1751                 printf("default_stripe_size: "LPU64"\n",
1752                        desc.ld_default_stripe_size);
1753                 printf("default_stripe_offset: "LPU64"\n",
1754                        desc.ld_default_stripe_offset);
1755                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1756                 printf("obd_count: %u\n", desc.ld_tgt_count);
1757                 for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
1758                         printf("%u: %s\n", i, (char *)ptr);
1759         }
1760 out:
1761         free(uuidarray);
1762         close(fd);
1763         return rc;
1764 }
1765
1766 int jt_obd_test_ldlm(int argc, char **argv)
1767 {
1768         struct obd_ioctl_data data;
1769         int rc;
1770
1771         IOC_INIT(data);
1772         if (argc != 1)
1773                 return CMD_HELP;
1774
1775         IOC_PACK(argv[0], data);
1776         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_TEST, buf);
1777         if (rc)
1778                 fprintf(stderr, "error: %s: test failed: %s\n",
1779                         cmdname(argv[0]), strerror(rc = errno));
1780         return rc;
1781 }
1782
1783 int jt_obd_dump_ldlm(int argc, char **argv)
1784 {
1785         struct obd_ioctl_data data;
1786         int rc;
1787
1788         IOC_INIT(data);
1789         if (argc != 1)
1790                 return CMD_HELP;
1791
1792         IOC_PACK(argv[0], data);
1793         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf);
1794         if (rc)
1795                 fprintf(stderr, "error: %s failed: %s\n",
1796                         cmdname(argv[0]), strerror(rc = errno));
1797         return rc;
1798 }
1799
1800 int jt_obd_ldlm_regress_start(int argc, char **argv)
1801 {
1802         int rc;
1803         struct obd_ioctl_data data;
1804         char argstring[200];
1805         int i, count = sizeof(argstring) - 1;
1806
1807         IOC_INIT(data);
1808         if (argc > 5)
1809                 return CMD_HELP;
1810
1811         argstring[0] = '\0';
1812         for (i = 1; i < argc; i++) {
1813                 strncat(argstring, " ", count);
1814                 count--;
1815                 strncat(argstring, argv[i], count);
1816                 count -= strlen(argv[i]);
1817         }
1818
1819         if (strlen(argstring)) {
1820                 data.ioc_inlbuf1 = argstring;
1821                 data.ioc_inllen1 = strlen(argstring) + 1;
1822         }
1823
1824         IOC_PACK(argv[0], data);
1825         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1826         if (rc)
1827                 fprintf(stderr, "error: %s: test failed: %s\n",
1828                         cmdname(argv[0]), strerror(rc = errno));
1829
1830         return rc;
1831 }
1832
1833 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1834 {
1835         int rc;
1836         struct obd_ioctl_data data;
1837         IOC_INIT(data);
1838
1839         if (argc != 1)
1840                 return CMD_HELP;
1841
1842         IOC_PACK(argv[0], data);
1843         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1844
1845         if (rc)
1846                 fprintf(stderr, "error: %s: test failed: %s\n",
1847                         cmdname(argv[0]), strerror(rc = errno));
1848         return rc;
1849 }
1850
1851 static int do_activate(int argc, char **argv, int flag)
1852 {
1853         struct obd_ioctl_data data;
1854         int rc;
1855
1856         IOC_INIT(data);
1857         if (argc != 1)
1858                 return CMD_HELP;
1859
1860         /* reuse offset for 'active' */
1861         data.ioc_offset = flag;
1862
1863         IOC_PACK(argv[0], data);
1864         rc = l_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1865         if (rc)
1866                 fprintf(stderr, "error: %s: failed: %s\n",
1867                         cmdname(argv[0]), strerror(rc = errno));
1868
1869         return rc;
1870 }
1871
1872 int jt_obd_deactivate(int argc, char **argv)
1873 {
1874         return do_activate(argc, argv, 0);
1875 }
1876
1877 int jt_obd_activate(int argc, char **argv)
1878 {
1879         return do_activate(argc, argv, 1);
1880 }
1881
1882 int jt_obd_recover(int argc, char **argv)
1883 {
1884         int rc;
1885         struct obd_ioctl_data data;
1886
1887         IOC_INIT(data);
1888         if (argc > 2)
1889                 return CMD_HELP;
1890
1891         if (argc == 2) {
1892                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1893                 data.ioc_inlbuf1 = argv[1];
1894         }
1895
1896         IOC_PACK(argv[0], data);
1897         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1898         if (rc < 0) {
1899                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1900                         strerror(rc = errno));
1901         }
1902
1903         return rc;
1904 }
1905
1906 int jt_obd_mdc_lookup(int argc, char **argv)
1907 {
1908         struct obd_ioctl_data data;
1909         char *parent, *child;
1910         int rc, fd, verbose = 1;
1911
1912         if (argc < 3 || argc > 4)
1913                 return CMD_HELP;
1914
1915         parent = argv[1];
1916         child = argv[2];
1917         if (argc == 4)
1918                 verbose = get_verbose(argv[0], argv[3]);
1919
1920         IOC_INIT(data);
1921
1922         data.ioc_inllen1 = strlen(child) + 1;
1923         data.ioc_inlbuf1 = child;
1924
1925         IOC_PACK(argv[0], data);
1926
1927         fd = open(parent, O_RDONLY);
1928         if (fd < 0) {
1929                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1930                         strerror(errno));
1931                 return -1;
1932         }
1933
1934         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1935         if (rc < 0) {
1936                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1937                         cmdname(argv[0]), strerror(rc = errno));
1938         }
1939         close(fd);
1940
1941         if (verbose) {
1942                 IOC_UNPACK(argv[0], data);
1943                 printf("%s: mode %o uid %d gid %d\n", child,
1944                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
1945                        data.ioc_obdo1.o_gid);
1946         }
1947
1948         return rc;
1949 }
1950
1951 static 
1952 int do_add_uuid(char * func, char *uuid, ptl_nid_t nid, int nal) 
1953 {
1954         char tmp[64];
1955         int rc;
1956         struct obd_ioctl_data data;
1957
1958         IOC_INIT(data);
1959         data.ioc_nid = nid;
1960         data.ioc_inllen1 = strlen(uuid) + 1;
1961         data.ioc_inlbuf1 = uuid;
1962         data.ioc_nal = nal;
1963
1964         IOC_PACK(func, data);
1965         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ADD_UUID, buf);
1966         if (rc) {
1967                 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
1968                         strerror(errno));
1969                 return -1;
1970         }
1971
1972         printf ("Added uuid %s: %s\n", uuid, ptl_nid2str (tmp, nid));
1973         return 0;
1974 }
1975
1976 int jt_obd_add_uuid(int argc, char **argv)
1977 {
1978         ptl_nid_t nid = 0;
1979         int nal;
1980         
1981         if (argc != 4) {                
1982                 return CMD_HELP;
1983         }
1984
1985         if (ptl_parse_nid (&nid, argv[2]) != 0) {
1986                 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
1987                         return (-1);
1988         }
1989
1990         nal = ptl_name2nal(argv[3]);
1991
1992         if (nal == 0) {
1993                 fprintf (stderr, "Can't parse NAL %s\n", argv[3]);
1994                 return -1;
1995         }
1996
1997         return do_add_uuid(argv[0], argv[1], nid, nal);
1998 }
1999
2000 int jt_obd_close_uuid(int argc, char **argv)
2001 {
2002         int rc, nal;
2003         struct obd_ioctl_data data;
2004
2005         if (argc != 3) {
2006                 fprintf(stderr, "usage: %s <uuid> <net-type>\n", argv[0]);
2007                 return 0;
2008         }
2009
2010         nal = ptl_name2nal(argv[2]);
2011
2012         if (nal == 0) {
2013                 fprintf (stderr, "Can't parse NAL %s\n", argv[2]);
2014                 return -1;
2015         }
2016
2017         IOC_INIT(data);
2018         data.ioc_inllen1 = strlen(argv[1]) + 1;
2019         data.ioc_inlbuf1 = argv[1];
2020         data.ioc_nal = nal;
2021
2022         IOC_PACK(argv[0], data);
2023         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf);
2024         if (rc) {
2025                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
2026                         strerror(errno));
2027                 return -1;
2028         }
2029         return 0;
2030 }
2031
2032
2033 int jt_obd_del_uuid(int argc, char **argv)
2034 {
2035         int rc;
2036         struct obd_ioctl_data data;
2037
2038         if (argc != 2) {
2039                 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
2040                 return 0;
2041         }
2042
2043         IOC_INIT(data);
2044
2045         if (strcmp (argv[1], "_all_"))
2046         {
2047                 data.ioc_inllen1 = strlen(argv[1]) + 1;
2048                 data.ioc_inlbuf1 = argv[1];
2049         }
2050         
2051         IOC_PACK(argv[0], data);
2052         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DEL_UUID, buf);
2053         if (rc) {
2054                 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
2055                         strerror(errno));
2056                 return -1;
2057         }
2058         return 0;
2059 }
2060
2061 static void signal_server(int sig)
2062 {
2063         if (sig == SIGINT) {
2064                 do_disconnect("sigint", 1);
2065                 exit(1);
2066         } else
2067                 fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
2068 }
2069
2070 int obd_initialize(int argc, char **argv)
2071 {
2072         SHMEM_SETUP();
2073         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH);
2074
2075         return 0;
2076 }
2077
2078
2079 void obd_cleanup(int argc, char **argv)
2080 {
2081         struct sigaction sigact;
2082
2083         sigact.sa_handler = signal_server;
2084         sigfillset(&sigact.sa_mask);
2085         sigact.sa_flags = SA_RESTART;
2086         sigaction(SIGINT, &sigact, NULL);
2087
2088         do_disconnect(argv[0], 1);
2089 }