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