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