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