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