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