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