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