Whamcloud - gitweb
* lctl set_route <nid> <up/down> enables or disables particular portals
[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_opt_net(int argc, char **argv)
681 {
682         char *arg2[3];
683         int rc;
684
685         if (argc < 3)
686                 return CMD_HELP;
687
688         arg2[0] = argv[0];
689         arg2[1] = argv[1];
690         arg2[2] = NULL;
691         rc = jt_ptl_network (2, arg2);
692
693         if (!rc)
694                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
695
696         return rc;
697 }
698
699 int jt_obd_detach(int argc, char **argv)
700 {
701         struct obd_ioctl_data data;
702         int rc;
703
704         IOC_INIT(data);
705
706         if (argc != 1)
707                 return CMD_HELP;
708
709         IOC_PACK(argv[0], data);
710         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DETACH, buf);
711         if (rc < 0)
712                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
713                         strerror(rc = errno));
714
715         return rc;
716 }
717
718 int jt_obd_cleanup(int argc, char **argv)
719 {
720         struct obd_ioctl_data data;
721         char force = 'F';
722         char failover = 'A';
723         char flags[3];
724         int flag_cnt = 0, n;
725         int rc;
726
727         IOC_INIT(data);
728
729         if (argc < 1 || argc > 3)
730                 return CMD_HELP;
731
732         for (n = 1; n < argc; n++) 
733                 if (strcmp(argv[n], "force") == 0) {
734                         flags[flag_cnt++] = force;
735                 } else if (strcmp(argv[n], "failover") == 0) {
736                         flags[flag_cnt++] = failover;
737                 } else {
738                         fprintf(stderr, "unknown option: %s", argv[n]);
739                         return CMD_HELP;
740                 }
741
742         data.ioc_inllen1 = flag_cnt;
743         if (flag_cnt)
744                 data.ioc_inlbuf1 = flags;
745
746         IOC_PACK(argv[0], data);
747         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLEANUP, 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_no_transno(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_NO_TRANSNO, 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_set_readonly(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_SET_READONLY, 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_abort_recovery(int argc, char **argv)
794 {
795         struct obd_ioctl_data data;
796         int rc;
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_ABORT_RECOVERY, buf);
805         if (rc < 0)
806                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
807                         strerror(rc = errno));
808
809         return rc;
810 }
811
812 int jt_obd_newdev(int argc, char **argv)
813 {
814         int rc;
815         struct obd_ioctl_data data;
816
817         IOC_INIT(data);
818
819         if (argc != 1)
820                 return CMD_HELP;
821
822         IOC_PACK(argv[0], data);
823         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NEWDEV, buf);
824         if (rc < 0)
825                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
826                         strerror(rc = errno));
827         else {
828                 IOC_UNPACK(argv[0], data);
829                 printf("Current device set to %d\n", data.ioc_dev);
830         }
831
832         return rc;
833 }
834
835 int jt_obd_mount_option(int argc, char **argv)
836 {
837         int rc;
838         struct obd_ioctl_data data;
839
840         IOC_INIT(data);
841
842         if (argc != 2)
843                 return CMD_HELP;
844
845         data.ioc_inllen1 = strlen(argv[1]) + 1;
846         data.ioc_inlbuf1 = argv[1];
847
848         IOC_PACK(argv[0], data);
849         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_MOUNTOPT, buf);
850         if (rc < 0) {
851                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
852                         strerror(rc = errno));
853         }
854
855         return rc;
856 }
857
858 int jt_get_version(int argc, char **argv)
859 {
860         int rc;
861         char buf[8192];
862         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
863
864         if (argc != 1)
865                 return CMD_HELP;
866
867         memset(buf, 0, sizeof(buf));
868         data->ioc_version = OBD_IOCTL_VERSION;
869         data->ioc_cookie = conn_cookie;
870         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
871         data->ioc_len = obd_ioctl_packlen(data);
872
873         rc = l_ioctl(OBD_DEV_ID, OBD_GET_VERSION, buf);
874         if (rc < 0)
875                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
876                         strerror(rc = errno));
877         else {
878                 printf("Lustre version: %s\n", data->ioc_bulk);
879         }
880
881         printf("lctl   version: %s\n", BUILD_VERSION);
882         return rc;
883 }
884
885 int jt_obd_list(int argc, char **argv)
886 {
887         int rc;
888         char buf[8192];
889         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
890
891         if (argc != 1)
892                 return CMD_HELP;
893
894         memset(buf, 0, sizeof(buf));
895         data->ioc_version = OBD_IOCTL_VERSION;
896         data->ioc_cookie = conn_cookie;
897         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
898         data->ioc_len = obd_ioctl_packlen(data);
899
900         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LIST, data);
901         if (rc < 0)
902                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
903                         strerror(rc = errno));
904         else {
905                 printf("%s", data->ioc_bulk);
906         }
907
908         return rc;
909 }
910
911 int jt_obd_attach(int argc, char **argv)
912 {
913         struct obd_ioctl_data data;
914         int rc;
915
916         IOC_INIT(data);
917
918         if (argc != 2 && argc != 3 && argc != 4)
919                 return CMD_HELP;
920
921         data.ioc_inllen1 = strlen(argv[1]) + 1;
922         data.ioc_inlbuf1 = argv[1];
923         if (argc >= 3) {
924                 data.ioc_inllen2 = strlen(argv[2]) + 1;
925                 data.ioc_inlbuf2 = argv[2];
926         }
927
928         if (argc == 4) {
929                 data.ioc_inllen3 = strlen(argv[3]) + 1;
930                 data.ioc_inlbuf3 = argv[3];
931         }
932
933         IOC_PACK(argv[0], data);
934         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ATTACH, buf);
935         if (rc < 0)
936                 fprintf(stderr, "error: %s: OBD_IOC_ATTACH %s\n",
937                         cmdname(argv[0]), strerror(rc = errno));
938         else if (argc == 3) {
939                 char name[1024];
940                 if (strlen(argv[2]) > 128) {
941                         printf("Name too long to set environment\n");
942                         return -EINVAL;
943                 }
944                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
945                 rc = setenv(name, argv[1], 1);
946                 if (rc) {
947                         printf("error setting env variable %s\n", name);
948                 }
949         }
950
951         return rc;
952 }
953
954 int jt_obd_setup(int argc, char **argv)
955 {
956         struct obd_ioctl_data data;
957         int rc;
958
959         IOC_INIT(data);
960
961         if (argc > 5)
962                 return CMD_HELP;
963
964         data.ioc_dev = -1;
965         if (argc > 1) {
966                 data.ioc_dev = parse_devname(argv[0], argv[1]);
967                 if (data.ioc_dev < 0)
968                         return -1;
969                 data.ioc_inllen1 = strlen(argv[1]) + 1;
970                 data.ioc_inlbuf1 = argv[1];
971         }
972         if (argc > 2) {
973                 data.ioc_inllen2 = strlen(argv[2]) + 1;
974                 data.ioc_inlbuf2 = argv[2];
975         }
976         if (argc > 3) {
977                 data.ioc_inllen3 = strlen(argv[3]) + 1;
978                 data.ioc_inlbuf3 = argv[3];
979         }
980         if (argc > 4) {
981                 data.ioc_inllen4 = strlen(argv[4]) + 1;
982                 data.ioc_inlbuf4 = argv[4];
983         }
984
985         IOC_PACK(argv[0], data);
986         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SETUP, buf);
987         if (rc < 0)
988                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
989                         strerror(rc = errno));
990
991         return rc;
992 }
993
994 /* Get echo client's stripe meta-data for the given object
995  */
996 int jt_obd_get_stripe (int argc, char **argv)
997 {
998         struct obd_ioctl_data data;
999         __u64 id;
1000         int   rc;
1001         char *end;
1002
1003         if (argc != 2)
1004                 return (CMD_HELP);
1005
1006         id = strtoull (argv[1], &end, 0);
1007         if (*end) {
1008                 fprintf (stderr, "Error: %s: invalid object id '%s'\n",
1009                          cmdname (argv[0]), argv[1]);
1010                 return (CMD_HELP);
1011         }
1012
1013         memset (&lsm_buffer, 0, sizeof (lsm_buffer));
1014
1015         IOC_INIT (data);
1016         data.ioc_obdo1.o_id = id;
1017         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1018         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1019         data.ioc_pbuf1 = (char *)&lsm_buffer;
1020         data.ioc_plen1 = sizeof (lsm_buffer);
1021
1022         IOC_PACK(argv[0], data);
1023         rc = l_ioctl(OBD_DEV_ID, ECHO_IOC_GET_STRIPE, buf);
1024         IOC_UNPACK(argv[0], data);
1025
1026         if (rc != 0) {
1027                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1028                          cmdname (argv[0]), rc, strerror (errno));
1029                 return (rc);
1030         }
1031
1032         printf ("%s\n", lsm_string (&lsm_buffer.lsm));
1033
1034         return (rc);
1035 }
1036
1037 /* Set stripe meta-data for 1 or more objects.  Object must be new to
1038  * this echo client instance.
1039  */
1040 int jt_obd_set_stripe (int argc, char **argv)
1041 {
1042         struct obd_ioctl_data data;
1043         char *end;
1044         int count = 1;
1045         int i;
1046         int rc;
1047
1048         if (argc < 2 || argc > 3)
1049                 return CMD_HELP;
1050
1051         rc = parse_lsm (&lsm_buffer, argv[1]);
1052         if (rc != 0) {
1053                 fprintf (stderr, "error: %s: invalid object '%s'\n",
1054                          cmdname (argv[0]), argv[1]);
1055                 return CMD_HELP;
1056         }
1057
1058         if (argc > 2) {
1059                 count = strtol (argv[2], &end, 0);
1060                 if (*end != 0) {
1061                         fprintf (stderr, "error: %s: invalid count '%s'\n",
1062                                  cmdname (argv[0]), argv[1]);
1063                         return CMD_HELP;
1064                 }
1065         }
1066
1067         for (i = 0; i < count; i++) {
1068                 IOC_INIT (data);
1069                 data.ioc_obdo1.o_id = lsm_buffer.lsm.lsm_object_id + i;
1070                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1071                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1072                 data.ioc_pbuf1 = (char *)&lsm_buffer;
1073                 data.ioc_plen1 = sizeof (lsm_buffer);
1074
1075                 IOC_PACK (argv[0], data);
1076                 rc = l_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1077                 IOC_UNPACK (argv[0], data);
1078
1079                 if (rc != 0) {
1080                         fprintf (stderr, "Error: %s: rc %d(%s)\n",
1081                                  cmdname (argv[0]), rc, strerror (errno));
1082                         return (rc);
1083                 }
1084         }
1085
1086         return (0);
1087 }
1088
1089 /* Clear stripe meta-data info for an object on this echo-client instance
1090  */
1091 int jt_obd_unset_stripe (int argc, char **argv)
1092 {
1093         struct obd_ioctl_data data;
1094         char *end;
1095         obd_id id;
1096         int rc;
1097
1098         if (argc != 2)
1099                 return CMD_HELP;
1100
1101         id = strtoull (argv[1], &end, 0);
1102         if (*end != 0) {
1103                 fprintf (stderr, "error: %s: invalid object id '%s'\n",
1104                          cmdname (argv[0]), argv[1]);
1105                 return CMD_HELP;
1106         }
1107
1108         IOC_INIT (data);
1109         data.ioc_obdo1.o_id = id;
1110         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1111         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1112
1113         IOC_PACK (argv[0], data);
1114         rc = l_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1115         IOC_UNPACK (argv[0], data);
1116
1117         if (rc != 0)
1118                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1119                          cmdname (argv[0]), rc, strerror (errno));
1120
1121         return (0);
1122 }
1123
1124 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1125  * not, defaults assumed.  This echo-client instance stashes the stripe
1126  * object ids.  Use get_stripe on this node to print full lsm and
1127  * set_stripe on another node to cut/paste between nodes.
1128  */
1129 int jt_obd_create(int argc, char **argv)
1130 {
1131         static __u64 base_id = 1;
1132
1133         struct obd_ioctl_data data;
1134         struct timeval next_time;
1135         __u64 count = 1, next_count;
1136         int verbose = 1, mode = 0100644, rc = 0, i;
1137         char *end;
1138
1139         IOC_INIT(data);
1140         if (argc < 2 || argc > 5)
1141                 return CMD_HELP;
1142
1143         count = strtoull(argv[1], &end, 0);
1144         if (*end) {
1145                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1146                         cmdname(argv[0]), argv[1]);
1147                 return CMD_HELP;
1148         }
1149
1150         if (argc > 2) {
1151                 mode = strtoul(argv[2], &end, 0);
1152                 if (*end) {
1153                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1154                                 cmdname(argv[0]), argv[2]);
1155                         return CMD_HELP;
1156                 }
1157                 if (!(mode & S_IFMT))
1158                         mode |= S_IFREG;
1159         }
1160
1161         if (argc > 3) {
1162                 verbose = get_verbose(argv[0], argv[3]);
1163                 if (verbose == BAD_VERBOSE)
1164                         return CMD_HELP;
1165         }
1166
1167         if (argc < 5)
1168                 reset_lsmb (&lsm_buffer);       /* will set default */
1169         else {
1170                 rc = parse_lsm (&lsm_buffer, argv[4]);
1171                 if (rc != 0) {
1172                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1173                                 cmdname(argv[0]), argv[4]);
1174                         return CMD_HELP;
1175                 }
1176                 base_id = lsm_buffer.lsm.lsm_object_id;
1177         }
1178
1179         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
1180         gettimeofday(&next_time, NULL);
1181         next_time.tv_sec -= verbose;
1182
1183         for (i = 1, next_count = verbose; i <= count; i++) {
1184                 data.ioc_obdo1.o_mode = mode;
1185                 data.ioc_obdo1.o_id = base_id++;
1186                 data.ioc_obdo1.o_uid = 0;
1187                 data.ioc_obdo1.o_gid = 0;
1188                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1189                                          OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1190
1191                 data.ioc_plen1 = sizeof (lsm_buffer);
1192                 data.ioc_pbuf1 = (char *)&lsm_buffer;
1193
1194                 IOC_PACK(argv[0], data);
1195                 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1196                 IOC_UNPACK(argv[0], data);
1197                 SHMEM_BUMP();
1198                 if (rc < 0) {
1199                         fprintf(stderr, "error: %s: #%d - %s\n",
1200                                 cmdname(argv[0]), i, strerror(rc = errno));
1201                         break;
1202                 }
1203                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1204                         fprintf(stderr, "error: %s: objid not valid #%d:%08x\n",
1205                                 cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1206                         rc = EINVAL;
1207                         break;
1208                 }
1209
1210                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1211                         printf("%s: #%d is object id "LPX64"\n",
1212                                 cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1213         }
1214         return rc;
1215 }
1216
1217 int jt_obd_setattr(int argc, char **argv)
1218 {
1219         struct obd_ioctl_data data;
1220         char *end;
1221         int rc;
1222
1223         IOC_INIT(data);
1224         if (argc != 2)
1225                 return CMD_HELP;
1226
1227         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1228         if (*end) {
1229                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1230                         cmdname(argv[0]), argv[1]);
1231                 return CMD_HELP;
1232         }
1233         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1234         if (*end) {
1235                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1236                         cmdname(argv[0]), argv[2]);
1237                 return CMD_HELP;
1238         }
1239         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1240
1241         IOC_PACK(argv[0], data);
1242         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1243         if (rc < 0)
1244                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1245                         strerror(rc = errno));
1246
1247         return rc;
1248 }
1249
1250 int jt_obd_destroy(int argc, char **argv)
1251 {
1252         struct obd_ioctl_data data;
1253         struct timeval next_time;
1254         __u64 count = 1, next_count;
1255         int verbose = 1;
1256         __u64 id;
1257         char *end;
1258         int rc = 0, i;
1259
1260         IOC_INIT(data);
1261         if (argc < 2 || argc > 4)
1262                 return CMD_HELP;
1263
1264         id = strtoull(argv[1], &end, 0);
1265         if (*end) {
1266                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1267                         cmdname(argv[0]), argv[1]);
1268                 return CMD_HELP;
1269         }
1270         if (argc > 2) {
1271                 count = strtoull(argv[2], &end, 0);
1272                 if (*end) {
1273                         fprintf(stderr,
1274                                 "error: %s: invalid iteration count '%s'\n",
1275                                 cmdname(argv[0]), argv[2]);
1276                         return CMD_HELP;
1277                 }
1278         }
1279
1280         if (argc > 3) {
1281                 verbose = get_verbose(argv[0], argv[3]);
1282                 if (verbose == BAD_VERBOSE)
1283                         return CMD_HELP;
1284         }
1285
1286         printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
1287         gettimeofday(&next_time, NULL);
1288         next_time.tv_sec -= verbose;
1289
1290         for (i = 1, next_count = verbose; i <= count; i++, id++) {
1291                 data.ioc_obdo1.o_id = id;
1292                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1293                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1294
1295                 IOC_PACK(argv[0], data);
1296                 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1297                 IOC_UNPACK(argv[0], data);
1298                 SHMEM_BUMP();
1299                 if (rc < 0) {
1300                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1301                                 cmdname(argv[0]), id, strerror(rc = errno));
1302                         break;
1303                 }
1304
1305                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1306                         printf("%s: #%d is object id "LPX64"\n",
1307                                cmdname(argv[0]), i, id);
1308         }
1309
1310         return rc;
1311 }
1312
1313 int jt_obd_getattr(int argc, char **argv)
1314 {
1315         struct obd_ioctl_data data;
1316         char *end;
1317         int rc;
1318
1319         if (argc != 2)
1320                 return CMD_HELP;
1321
1322         IOC_INIT(data);
1323         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1324         if (*end) {
1325                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1326                         cmdname(argv[0]), argv[1]);
1327                 return CMD_HELP;
1328         }
1329         /* to help obd filter */
1330         data.ioc_obdo1.o_mode = 0100644;
1331         data.ioc_obdo1.o_valid = 0xffffffff;
1332         printf("%s: object id "LPX64"\n", cmdname(argv[0]),data.ioc_obdo1.o_id);
1333
1334         IOC_PACK(argv[0], data);
1335         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1336         IOC_UNPACK(argv[0], data);
1337         if (rc) {
1338                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1339                         strerror(rc = errno));
1340         } else {
1341                 printf("%s: object id "LPX64", mode %o\n", cmdname(argv[0]),
1342                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1343         }
1344         return rc;
1345 }
1346
1347 int jt_obd_test_getattr(int argc, char **argv)
1348 {
1349         struct obd_ioctl_data data;
1350         struct timeval start, next_time;
1351         __u64 i, count, next_count;
1352         int verbose = 1;
1353         obd_id objid = 3;
1354         char *end;
1355         int rc = 0;
1356
1357         if (argc < 2 && argc > 4)
1358                 return CMD_HELP;
1359
1360         IOC_INIT(data);
1361         count = strtoull(argv[1], &end, 0);
1362         if (*end) {
1363                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1364                         cmdname(argv[0]), argv[1]);
1365                 return CMD_HELP;
1366         }
1367
1368         if (argc >= 3) {
1369                 verbose = get_verbose(argv[0], argv[2]);
1370                 if (verbose == BAD_VERBOSE)
1371                         return CMD_HELP;
1372         }
1373
1374         if (argc >= 4) {
1375                 if (argv[3][0] == 't') {
1376                         objid = strtoull(argv[3] + 1, &end, 0);
1377                         if (thread)
1378                                 objid += thread - 1;
1379                 } else
1380                         objid = strtoull(argv[3], &end, 0);
1381                 if (*end) {
1382                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1383                                 cmdname(argv[0]), argv[3]);
1384                         return CMD_HELP;
1385                 }
1386         }
1387
1388         gettimeofday(&start, NULL);
1389         next_time.tv_sec = start.tv_sec - verbose;
1390         next_time.tv_usec = start.tv_usec;
1391         if (verbose != 0)
1392                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1393                        cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1394
1395         for (i = 1, next_count = verbose; i <= count; i++) {
1396                 data.ioc_obdo1.o_id = objid;
1397                 data.ioc_obdo1.o_mode = S_IFREG;
1398                 data.ioc_obdo1.o_valid = 0xffffffff;
1399                 IOC_PACK(argv[0], data);
1400                 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1401                 SHMEM_BUMP();
1402                 if (rc < 0) {
1403                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1404                                 cmdname(argv[0]), i, errno, strerror(rc = errno));
1405                         break;
1406                 } else {
1407                         if (be_verbose
1408                             (verbose, &next_time, i, &next_count, count))
1409                                 printf("%s: got attr #"LPD64"\n",
1410                                        cmdname(argv[0]), i);
1411                 }
1412         }
1413
1414         if (!rc) {
1415                 struct timeval end;
1416                 double diff;
1417
1418                 gettimeofday(&end, NULL);
1419
1420                 diff = difftime(&end, &start);
1421
1422                 --i;
1423                 if (verbose != 0)
1424                         printf("%s: "LPD64" attrs in %.4gs (%.4g attr/s): %s",
1425                                cmdname(argv[0]), i, diff, (double)i / diff,
1426                                ctime(&end.tv_sec));
1427         }
1428         return rc;
1429 }
1430
1431 int jt_obd_test_brw(int argc, char **argv)
1432 {
1433         struct obd_ioctl_data data;
1434         struct timeval start, next_time;
1435         int pages = 1;
1436         __u64 count, next_count;
1437         __u64 objid = 3;
1438         int verbose = 1, write = 0, rw;
1439         char *end;
1440         int thr_offset = 0;
1441         int i;
1442         int len;
1443         int rc = 0;
1444
1445         if (argc < 2 || argc > 6) {
1446                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1447                         cmdname(argv[0]), argc);
1448                 return CMD_HELP;
1449         }
1450
1451         /* make each thread write to a different offset */
1452         if (argv[1][0] == 't') {
1453                 count = strtoull(argv[1] + 1, &end, 0);
1454                 if (thread)
1455                         thr_offset = thread - 1;
1456         } else
1457                 count = strtoull(argv[1], &end, 0);
1458
1459         if (*end) {
1460                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1461                         cmdname(argv[0]), argv[1]);
1462                 return CMD_HELP;
1463         }
1464
1465         if (argc >= 3) {
1466                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1467                         write = 1;
1468                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
1469                         write = 0;
1470         }
1471
1472         if (argc >= 4) {
1473                 verbose = get_verbose(argv[0], argv[3]);
1474                 if (verbose == BAD_VERBOSE)
1475                         return CMD_HELP;
1476         }
1477
1478         if (argc >= 5) {
1479                 pages = strtoul(argv[4], &end, 0);
1480                 if (*end) {
1481                         fprintf(stderr, "error: %s: bad page count '%s'\n",
1482                                 cmdname(argv[0]), argv[4]);
1483                         return CMD_HELP;
1484                 }
1485         }
1486         if (argc >= 6) {
1487                 if (argv[5][0] == 't') {
1488                         objid = strtoull(argv[5] + 1, &end, 0);
1489                         if (thread)
1490                                 objid += thread - 1;
1491                 } else
1492                         objid = strtoull(argv[5], &end, 0);
1493                 if (*end) {
1494                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1495                                 cmdname(argv[0]), argv[5]);
1496                         return CMD_HELP;
1497                 }
1498         }
1499
1500         len = pages * PAGE_SIZE;
1501
1502         IOC_INIT(data);
1503         data.ioc_obdo1.o_id = objid;
1504         data.ioc_obdo1.o_mode = S_IFREG;
1505         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1506         data.ioc_count = len;
1507         data.ioc_offset = thr_offset * len * count;
1508
1509         gettimeofday(&start, NULL);
1510         next_time.tv_sec = start.tv_sec - verbose;
1511         next_time.tv_usec = start.tv_usec;
1512
1513         if (verbose != 0)
1514                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1515                        cmdname(argv[0]), write ? "writing" : "reading", count,
1516                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1517
1518         IOC_PACK(argv[0], data);
1519         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_OPEN, buf);
1520         IOC_UNPACK(argv[0], data);
1521         if (rc) {
1522                 fprintf(stderr, "error: brw_open: %s\n", strerror(rc = errno));
1523                 return rc;
1524         }
1525
1526         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1527         for (i = 1, next_count = verbose; i <= count; i++) {
1528                 rc = l_ioctl(OBD_DEV_ID, rw, buf);
1529                 SHMEM_BUMP();
1530                 if (rc) {
1531                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1532                                 cmdname(argv[0]), i, strerror(rc = errno),
1533                                 write ? "write" : "read");
1534                         break;
1535                 } else if (be_verbose(verbose, &next_time,i, &next_count,count))
1536                         printf("%s: %s number %dx%d\n", cmdname(argv[0]),
1537                                write ? "write" : "read", i, pages);
1538
1539                 data.ioc_offset += len;
1540         }
1541
1542         if (!rc) {
1543                 struct timeval end;
1544                 double diff;
1545
1546                 gettimeofday(&end, NULL);
1547
1548                 diff = difftime(&end, &start);
1549
1550                 --i;
1551                 if (verbose != 0)
1552                         printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s",
1553                                cmdname(argv[0]), write ? "wrote" : "read",
1554                                i, pages, diff, (double)i * pages / diff,
1555                                ctime(&end.tv_sec));
1556         }
1557         rw = l_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE, buf);
1558         if (rw) {
1559                 fprintf(stderr, "error: brw_close: %s\n", strerror(rw = errno));
1560                 if (!rc)
1561                         rc = rw;
1562         }
1563
1564         return rc;
1565 }
1566
1567 int jt_obd_lov_setconfig(int argc, char **argv)
1568 {
1569         struct obd_ioctl_data data;
1570         struct lov_desc desc;
1571         struct obd_uuid *uuidarray, *ptr;
1572         int rc, i;
1573         char *end;
1574
1575         IOC_INIT(data);
1576
1577         if (argc <= 6)
1578                 return CMD_HELP;
1579
1580         if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
1581                 fprintf(stderr,
1582                         "error: %s: LOV uuid '%s' longer than "LPSZ" chars\n",
1583                         cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
1584                 return -EINVAL;
1585         }
1586
1587         memset(&desc, 0, sizeof(desc));
1588         obd_str2uuid(&desc.ld_uuid, argv[1]);
1589         desc.ld_tgt_count = argc - 6;
1590         desc.ld_default_stripe_count = strtoul(argv[2], &end, 0);
1591         if (*end) {
1592                 fprintf(stderr, "error: %s: bad default stripe count '%s'\n",
1593                         cmdname(argv[0]), argv[2]);
1594                 return CMD_HELP;
1595         }
1596         if (desc.ld_default_stripe_count > desc.ld_tgt_count) {
1597                 fprintf(stderr,
1598                         "error: %s: default stripe count %u > OST count %u\n",
1599                         cmdname(argv[0]), desc.ld_default_stripe_count,
1600                         desc.ld_tgt_count);
1601                 return -EINVAL;
1602         }
1603
1604         desc.ld_default_stripe_size = strtoull(argv[3], &end, 0);
1605         if (*end) {
1606                 fprintf(stderr, "error: %s: bad default stripe size '%s'\n",
1607                         cmdname(argv[0]), argv[3]);
1608                 return CMD_HELP;
1609         }
1610         if (desc.ld_default_stripe_size < 4096) {
1611                 fprintf(stderr,
1612                         "error: %s: default stripe size "LPU64" too small\n",
1613                         cmdname(argv[0]), desc.ld_default_stripe_size);
1614                 return -EINVAL;
1615         } else if ((long)desc.ld_default_stripe_size <
1616                    desc.ld_default_stripe_size) {
1617                 fprintf(stderr,
1618                         "error: %s: default stripe size "LPU64" too large\n",
1619                         cmdname(argv[0]), desc.ld_default_stripe_size);
1620                 return -EINVAL;
1621         }
1622         desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0);
1623         if (*end) {
1624                 fprintf(stderr, "error: %s: bad default stripe offset '%s'\n",
1625                         cmdname(argv[0]), argv[4]);
1626                 return CMD_HELP;
1627         }
1628         desc.ld_pattern = strtoul(argv[5], &end, 0);
1629         if (*end) {
1630                 fprintf(stderr, "error: %s: bad stripe pattern '%s'\n",
1631                         cmdname(argv[0]), argv[5]);
1632                 return CMD_HELP;
1633         }
1634
1635         /* NOTE: it is possible to overwrite the default striping parameters,
1636          *       but EXTREME care must be taken when saving the OST UUID list.
1637          *       It must be EXACTLY the same, or have only additions at the
1638          *       end of the list, or only overwrite individual OST entries
1639          *       that are restored from backups of the previous OST.
1640          */
1641         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1642         if (!uuidarray) {
1643                 fprintf(stderr, "error: %s: no memory for %d UUIDs\n",
1644                         cmdname(argv[0]), desc.ld_tgt_count);
1645                 rc = -ENOMEM;
1646                 goto out;
1647         }
1648         for (i = 6, ptr = uuidarray; i < argc; i++, ptr++) {
1649                 if (strlen(argv[i]) >= sizeof(*ptr)) {
1650                         fprintf(stderr, "error: %s: arg %d (%s) too long\n",
1651                                 cmdname(argv[0]), i, argv[i]);
1652                         rc = -EINVAL;
1653                         goto out;
1654                 }
1655                 strcpy((char *)ptr, argv[i]);
1656         }
1657
1658         data.ioc_inllen1 = sizeof(desc);
1659         data.ioc_inlbuf1 = (char *)&desc;
1660         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1661         data.ioc_inlbuf2 = (char *)uuidarray;
1662
1663         if (obd_ioctl_pack(&data, &buf, max)) {
1664                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1665                 rc = -EINVAL;
1666                 goto out;
1667         }
1668         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LOV_SET_CONFIG, buf);
1669         if (rc)
1670                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1671                         cmdname(argv[0]), strerror(rc = errno));
1672 out:
1673         free(uuidarray);
1674         return rc;
1675 }
1676
1677 #define DEF_UUID_ARRAY_LEN (8192 / 40)
1678
1679 int jt_obd_lov_getconfig(int argc, char **argv)
1680 {
1681         struct obd_ioctl_data data;
1682         struct lov_desc desc;
1683         struct obd_uuid *uuidarray;
1684         char *path;
1685         int rc, fd;
1686
1687         IOC_INIT(data);
1688
1689         if (argc != 2)
1690                 return CMD_HELP;
1691
1692         path = argv[1];
1693         fd = open(path, O_RDONLY);
1694         if (fd < 0) {
1695                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1696                         strerror(errno));
1697                 return -1;
1698         }
1699
1700         memset(&desc, 0, sizeof(desc));
1701         obd_str2uuid(&desc.ld_uuid, argv[1]);
1702         desc.ld_tgt_count = DEF_UUID_ARRAY_LEN;
1703 repeat:
1704         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1705         if (!uuidarray) {
1706                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1707                         cmdname(argv[0]), desc.ld_tgt_count);
1708                 rc = -ENOMEM;
1709                 goto out;
1710         }
1711
1712         data.ioc_inllen1 = sizeof(desc);
1713         data.ioc_inlbuf1 = (char *)&desc;
1714         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1715         data.ioc_inlbuf2 = (char *)uuidarray;
1716
1717         if (obd_ioctl_pack(&data, &buf, max)) {
1718                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1719                 rc = -EINVAL;
1720                 goto out;
1721         }
1722         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1723         if (rc == -ENOSPC) {
1724                 free(uuidarray);
1725                 goto repeat;
1726         } else if (rc) {
1727                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1728                         cmdname(argv[0]), strerror(rc = errno));
1729         } else {
1730                 struct obd_uuid *ptr;
1731                 int i;
1732
1733                 if (obd_ioctl_unpack(&data, buf, max)) {
1734                         fprintf(stderr, "error: %s: invalid reply\n",
1735                                 cmdname(argv[0]));
1736                         rc = -EINVAL;
1737                         goto out;
1738                 }
1739                 printf("default_stripe_count: %u\n",
1740                        desc.ld_default_stripe_count);
1741                 printf("default_stripe_size: "LPU64"\n",
1742                        desc.ld_default_stripe_size);
1743                 printf("default_stripe_offset: "LPU64"\n",
1744                        desc.ld_default_stripe_offset);
1745                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1746                 printf("obd_count: %u\n", desc.ld_tgt_count);
1747                 for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
1748                         printf("%u: %s\n", i, (char *)ptr);
1749         }
1750 out:
1751         free(uuidarray);
1752         close(fd);
1753         return rc;
1754 }
1755
1756 int jt_obd_test_ldlm(int argc, char **argv)
1757 {
1758         struct obd_ioctl_data data;
1759         int rc;
1760
1761         IOC_INIT(data);
1762         if (argc != 1)
1763                 return CMD_HELP;
1764
1765         IOC_PACK(argv[0], data);
1766         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_TEST, buf);
1767         if (rc)
1768                 fprintf(stderr, "error: %s: test failed: %s\n",
1769                         cmdname(argv[0]), strerror(rc = errno));
1770         return rc;
1771 }
1772
1773 int jt_obd_dump_ldlm(int argc, char **argv)
1774 {
1775         struct obd_ioctl_data data;
1776         int rc;
1777
1778         IOC_INIT(data);
1779         if (argc != 1)
1780                 return CMD_HELP;
1781
1782         IOC_PACK(argv[0], data);
1783         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf);
1784         if (rc)
1785                 fprintf(stderr, "error: %s failed: %s\n",
1786                         cmdname(argv[0]), strerror(rc = errno));
1787         return rc;
1788 }
1789
1790 int jt_obd_ldlm_regress_start(int argc, char **argv)
1791 {
1792         int rc;
1793         struct obd_ioctl_data data;
1794         char argstring[200];
1795         int i, count = sizeof(argstring) - 1;
1796
1797         IOC_INIT(data);
1798         if (argc > 5)
1799                 return CMD_HELP;
1800
1801         argstring[0] = '\0';
1802         for (i = 1; i < argc; i++) {
1803                 strncat(argstring, " ", count);
1804                 count--;
1805                 strncat(argstring, argv[i], count);
1806                 count -= strlen(argv[i]);
1807         }
1808
1809         if (strlen(argstring)) {
1810                 data.ioc_inlbuf1 = argstring;
1811                 data.ioc_inllen1 = strlen(argstring) + 1;
1812         }
1813
1814         IOC_PACK(argv[0], data);
1815         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1816         if (rc)
1817                 fprintf(stderr, "error: %s: test failed: %s\n",
1818                         cmdname(argv[0]), strerror(rc = errno));
1819
1820         return rc;
1821 }
1822
1823 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1824 {
1825         int rc;
1826         struct obd_ioctl_data data;
1827         IOC_INIT(data);
1828
1829         if (argc != 1)
1830                 return CMD_HELP;
1831
1832         IOC_PACK(argv[0], data);
1833         rc = l_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1834
1835         if (rc)
1836                 fprintf(stderr, "error: %s: test failed: %s\n",
1837                         cmdname(argv[0]), strerror(rc = errno));
1838         return rc;
1839 }
1840
1841 static int do_activate(int argc, char **argv, int flag)
1842 {
1843         struct obd_ioctl_data data;
1844         int rc;
1845
1846         IOC_INIT(data);
1847         if (argc != 1)
1848                 return CMD_HELP;
1849
1850         /* reuse offset for 'active' */
1851         data.ioc_offset = flag;
1852
1853         IOC_PACK(argv[0], data);
1854         rc = l_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1855         if (rc)
1856                 fprintf(stderr, "error: %s: failed: %s\n",
1857                         cmdname(argv[0]), strerror(rc = errno));
1858
1859         return rc;
1860 }
1861
1862 int jt_obd_deactivate(int argc, char **argv)
1863 {
1864         return do_activate(argc, argv, 0);
1865 }
1866
1867 int jt_obd_activate(int argc, char **argv)
1868 {
1869         return do_activate(argc, argv, 1);
1870 }
1871
1872 int jt_obd_recover(int argc, char **argv)
1873 {
1874         int rc;
1875         struct obd_ioctl_data data;
1876
1877         IOC_INIT(data);
1878         if (argc > 2)
1879                 return CMD_HELP;
1880
1881         if (argc == 2) {
1882                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1883                 data.ioc_inlbuf1 = argv[1];
1884         }
1885
1886         IOC_PACK(argv[0], data);
1887         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1888         if (rc < 0) {
1889                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1890                         strerror(rc = errno));
1891         }
1892
1893         return rc;
1894 }
1895
1896 int jt_obd_mdc_lookup(int argc, char **argv)
1897 {
1898         struct obd_ioctl_data data;
1899         char *parent, *child;
1900         int rc, fd, verbose = 1;
1901
1902         if (argc < 3 || argc > 4)
1903                 return CMD_HELP;
1904
1905         parent = argv[1];
1906         child = argv[2];
1907         if (argc == 4)
1908                 verbose = get_verbose(argv[0], argv[3]);
1909
1910         IOC_INIT(data);
1911
1912         data.ioc_inllen1 = strlen(child) + 1;
1913         data.ioc_inlbuf1 = child;
1914
1915         IOC_PACK(argv[0], data);
1916
1917         fd = open(parent, O_RDONLY);
1918         if (fd < 0) {
1919                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1920                         strerror(errno));
1921                 return -1;
1922         }
1923
1924         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1925         if (rc < 0) {
1926                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1927                         cmdname(argv[0]), strerror(rc = errno));
1928         }
1929         close(fd);
1930
1931         if (verbose) {
1932                 IOC_UNPACK(argv[0], data);
1933                 printf("%s: mode %o uid %d gid %d\n", child,
1934                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
1935                        data.ioc_obdo1.o_gid);
1936         }
1937
1938         return rc;
1939 }
1940
1941 static 
1942 int do_add_uuid(char * func, char *uuid, ptl_nid_t nid, int nal) 
1943 {
1944         char tmp[64];
1945         int rc;
1946         struct obd_ioctl_data data;
1947
1948         IOC_INIT(data);
1949         data.ioc_nid = nid;
1950         data.ioc_inllen1 = strlen(uuid) + 1;
1951         data.ioc_inlbuf1 = uuid;
1952         data.ioc_nal = nal;
1953
1954         IOC_PACK(func, data);
1955         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ADD_UUID, buf);
1956         if (rc) {
1957                 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
1958                         strerror(errno));
1959                 return -1;
1960         }
1961
1962         printf ("Added uuid %s: %s\n", uuid, ptl_nid2str (tmp, nid));
1963         return 0;
1964 }
1965
1966 int jt_obd_add_uuid(int argc, char **argv)
1967 {
1968         ptl_nid_t nid = 0;
1969         int nal;
1970         
1971         if (argc != 4) {                
1972                 return CMD_HELP;
1973         }
1974
1975         if (ptl_parse_nid (&nid, argv[2]) != 0) {
1976                 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
1977                         return (-1);
1978         }
1979
1980         nal = ptl_name2nal(argv[3]);
1981
1982         if (nal <= 0) {
1983                 fprintf (stderr, "Can't parse NAL %s\n", argv[3]);
1984                 return -1;
1985         }
1986
1987         return do_add_uuid(argv[0], argv[1], nid, nal);
1988 }
1989
1990 int jt_obd_close_uuid(int argc, char **argv)
1991 {
1992         int rc, nal;
1993         struct obd_ioctl_data data;
1994
1995         if (argc != 3) {
1996                 fprintf(stderr, "usage: %s <uuid> <net-type>\n", argv[0]);
1997                 return 0;
1998         }
1999
2000         nal = ptl_name2nal(argv[2]);
2001
2002         if (nal <= 0) {
2003                 fprintf (stderr, "Can't parse NAL %s\n", argv[2]);
2004                 return -1;
2005         }
2006
2007         IOC_INIT(data);
2008         data.ioc_inllen1 = strlen(argv[1]) + 1;
2009         data.ioc_inlbuf1 = argv[1];
2010         data.ioc_nal = nal;
2011
2012         IOC_PACK(argv[0], data);
2013         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf);
2014         if (rc) {
2015                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
2016                         strerror(errno));
2017                 return -1;
2018         }
2019         return 0;
2020 }
2021
2022
2023 int jt_obd_del_uuid(int argc, char **argv)
2024 {
2025         int rc;
2026         struct obd_ioctl_data data;
2027
2028         if (argc != 2) {
2029                 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
2030                 return 0;
2031         }
2032
2033         IOC_INIT(data);
2034
2035         if (strcmp (argv[1], "_all_"))
2036         {
2037                 data.ioc_inllen1 = strlen(argv[1]) + 1;
2038                 data.ioc_inlbuf1 = argv[1];
2039         }
2040         
2041         IOC_PACK(argv[0], data);
2042         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DEL_UUID, buf);
2043         if (rc) {
2044                 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
2045                         strerror(errno));
2046                 return -1;
2047         }
2048         return 0;
2049 }
2050
2051 static void signal_server(int sig)
2052 {
2053         if (sig == SIGINT) {
2054                 do_disconnect("sigint", 1);
2055                 exit(1);
2056         } else
2057                 fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
2058 }
2059
2060 int obd_initialize(int argc, char **argv)
2061 {
2062         SHMEM_SETUP();
2063         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH);
2064
2065         return 0;
2066 }
2067
2068
2069 void obd_cleanup(int argc, char **argv)
2070 {
2071         struct sigaction sigact;
2072
2073         sigact.sa_handler = signal_server;
2074         sigfillset(&sigact.sa_mask);
2075         sigact.sa_flags = SA_RESTART;
2076         sigaction(SIGINT, &sigact, NULL);
2077
2078         do_disconnect(argv[0], 1);
2079 }