Whamcloud - gitweb
LU-80 utils: Large stripe support
[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
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
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 (c) 2002, 2010, Oracle and/or its affiliates. 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 <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <sys/stat.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <sys/un.h>
50 #include <sys/wait.h>
51
52 #include <ctype.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <glob.h>
56 #include <signal.h>
57 #include <stdarg.h>
58 #include <stdbool.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <time.h>
63 #include <unistd.h>
64
65 #include "obdctl.h"
66
67 #include <obd.h>          /* for struct lov_stripe_md */
68 #include <lustre/lustre_build_version.h>
69
70 #include <obd_class.h>
71 #include <lnet/lnetctl.h>
72 #include <libcfs/libcfsutil.h>
73 #include <lustre/liblustreapi.h>
74
75 #define MAX_STRING_SIZE 128
76 #define DEVICES_LIST "/proc/fs/lustre/devices"
77
78 #if HAVE_LIBPTHREAD
79 #include <sys/ipc.h>
80 #include <sys/shm.h>
81 #include <pthread.h>
82
83 #define MAX_THREADS 4096
84 #define MAX_BASE_ID 0xffffffff
85 struct shared_data {
86         l_mutex_t mutex;
87         l_cond_t  cond;
88         int       stopping;
89         struct {
90                 __u64 counters[MAX_THREADS];
91                 __u64 offsets[MAX_THREADS];
92                 int   thr_running;
93                 int   start_barrier;
94                 int   stop_barrier;
95                 struct timeval start_time;
96                 struct timeval end_time;
97         } body;
98 };
99
100 static struct shared_data *shared_data;
101 static __u64 counter_snapshot[2][MAX_THREADS];
102 static int prev_valid;
103 static struct timeval prev_time;
104 static int thread;
105 static int nthreads;
106 #else
107 const int thread = 0;
108 const int nthreads = 1;
109 #endif
110
111 #define MAX_IOC_BUFLEN 8192
112
113 static int cur_device = -1;
114
115 struct lov_oinfo lov_oinfos[LOV_MAX_STRIPE_COUNT];
116
117 struct lsm_buffer {
118         struct lov_stripe_md lsm;
119         struct lov_oinfo *ptrs[LOV_MAX_STRIPE_COUNT];
120 } lsm_buffer;
121
122 static int l2_ioctl(int dev_id, int opc, void *buf)
123 {
124         return l_ioctl(dev_id, opc, buf);
125 }
126
127 int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg)
128 {
129         struct obd_ioctl_data data;
130         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
131         int rc;
132
133         memset(&data, 0, sizeof(data));
134         data.ioc_dev = cur_device;
135         data.ioc_type = LUSTRE_CFG_TYPE;
136         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
137                                         lcfg->lcfg_buflens);
138         data.ioc_pbuf1 = (void *)lcfg;
139         memset(buf, 0, sizeof(rawbuf));
140         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
141         if (rc) {
142                 fprintf(stderr, "error: %s: invalid ioctl\n",
143                         jt_cmdname(func));
144                 return rc;
145         }
146
147         rc =  l_ioctl(dev_id, OBD_IOC_PROCESS_CFG, buf);
148
149         return rc;
150 }
151
152 static int do_device(char *func, char *devname);
153
154 static int get_mgs_device()
155 {
156         char mgs[] = "$MGS";
157         static int mgs_device = -1;
158
159         if (mgs_device == -1) {
160                 int rc;
161                 do_disconnect(NULL, 1);
162                 rc = do_device("mgsioc", mgs);
163                 if (rc) {
164                         fprintf(stderr,
165                                 "This command must be run on the MGS.\n");
166                         errno = ENODEV;
167                         return -1;
168                 }
169                 mgs_device = cur_device;
170         }
171         return mgs_device;
172 }
173
174 /* Returns -1 on error with errno set */
175 int lcfg_mgs_ioctl(char *func, int dev_id, struct lustre_cfg *lcfg)
176 {
177         struct obd_ioctl_data data;
178         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
179         int rc;
180
181         memset(&data, 0, sizeof(data));
182         rc = data.ioc_dev = get_mgs_device();
183         if (rc < 0)
184                 goto out;
185         data.ioc_type = LUSTRE_CFG_TYPE;
186         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
187                                         lcfg->lcfg_buflens);
188         data.ioc_pbuf1 = (void *)lcfg;
189         memset(buf, 0, sizeof(rawbuf));
190         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
191         if (rc) {
192                 fprintf(stderr, "error: %s: invalid ioctl\n",
193                         jt_cmdname(func));
194                 return rc;
195         }
196
197         rc = l_ioctl(dev_id, OBD_IOC_PARAM, buf);
198 out:
199         if (rc) {
200                 if (errno == ENOSYS)
201                         fprintf(stderr, "Make sure cfg_device is set first.\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_seq, 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         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
230         int rc;
231
232         memset(&data, 0, sizeof(data));
233         data.ioc_dev = cur_device;
234         data.ioc_inllen1 = strlen(name) + 1;
235         data.ioc_inlbuf1 = name;
236
237         memset(buf, 0, sizeof(rawbuf));
238         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
239         if (rc) {
240                 fprintf(stderr, "error: %s: invalid ioctl\n",
241                         jt_cmdname(func));
242                 return rc;
243         }
244         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
245         if (rc < 0)
246                 return errno;
247         rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
248         if (rc) {
249                 fprintf(stderr, "error: %s: invalid reply\n",
250                         jt_cmdname(func));
251                 return rc;
252         }
253
254         return data.ioc_dev + N2D_OFF;
255 }
256
257 /*
258  * resolve a device name to a device number.
259  * supports a number, $name or %uuid.
260  */
261 int parse_devname(char *func, char *name)
262 {
263         int rc;
264         int ret = -1;
265
266         if (!name)
267                 return ret;
268         if (isdigit(name[0])) {
269                 ret = strtoul(name, NULL, 0);
270         } else {
271                 if (name[0] == '$' || name[0] == '%')
272                         name++;
273                 rc = do_name2dev(func, name);
274                 if (rc >= N2D_OFF) {
275                         ret = rc - N2D_OFF;
276                         // printf("Name %s is device %d\n", name, ret);
277                 } else {
278                         fprintf(stderr, "No device found for name %s: %s\n",
279                                 name, strerror(rc));
280                 }
281         }
282         return ret;
283 }
284
285 static void
286 reset_lsmb (struct lsm_buffer *lsmb)
287 {
288         memset (&lsmb->lsm, 0, sizeof (lsmb->lsm));
289         memset(lov_oinfos, 0, sizeof(lov_oinfos));
290         lsmb->lsm.lsm_magic = LOV_MAGIC;
291 }
292
293 static int
294 parse_lsm (struct lsm_buffer *lsmb, char *string)
295 {
296         struct lov_stripe_md *lsm = &lsmb->lsm;
297         char                 *end;
298         int                   i;
299
300         /*
301          * object_id[=size#count[@offset:id]*]
302          */
303
304         reset_lsmb (lsmb);
305
306         lsm->lsm_object_id = strtoull (string, &end, 0);
307         if (end == string)
308                 return (-1);
309         string = end;
310
311         if (*string == 0)
312                 return (0);
313
314         if (*string != '=')
315                 return (-1);
316         string++;
317
318         lsm->lsm_stripe_size = strtoul (string, &end, 0);
319         if (end == string)
320                 return (-1);
321         string = end;
322
323         if (*string != '#')
324                 return (-1);
325         string++;
326
327         lsm->lsm_stripe_count = strtoul (string, &end, 0);
328         if (end == string)
329                 return (-1);
330         string = end;
331
332         if (*string == 0)               /* don't have to specify obj ids */
333                 return (0);
334
335         for (i = 0; i < lsm->lsm_stripe_count; i++) {
336                 if (*string != '@')
337                         return (-1);
338                 string++;
339                 lsm->lsm_oinfo[i]->loi_ost_idx = strtoul(string, &end, 0);
340                 if (*end != ':')
341                         return (-1);
342                 string = end + 1;
343                 lsm->lsm_oinfo[i]->loi_id = strtoull(string, &end, 0);
344                 string = end;
345         }
346
347         if (*string != 0)
348                 return (-1);
349
350         return (0);
351 }
352
353 char *jt_cmdname(char *func)
354 {
355         static char buf[512];
356
357         if (thread) {
358                 sprintf(buf, "%s-%d", func, thread);
359                 return buf;
360         }
361
362         return func;
363 }
364
365 #define difftime(a, b)                                  \
366         ((a)->tv_sec - (b)->tv_sec +                    \
367          ((a)->tv_usec - (b)->tv_usec) / 1000000.0)
368
369 static int be_verbose(int verbose, struct timeval *next_time,
370                       __u64 num, __u64 *next_num, int num_total)
371 {
372         struct timeval now;
373
374         if (!verbose)
375                 return 0;
376
377         if (next_time != NULL)
378                 gettimeofday(&now, NULL);
379
380         /* A positive verbosity means to print every X iterations */
381         if (verbose > 0 && (num >= *next_num || num >= num_total)) {
382                 *next_num += verbose;
383                 if (next_time) {
384                         next_time->tv_sec = now.tv_sec - verbose;
385                         next_time->tv_usec = now.tv_usec;
386                 }
387                 return 1;
388         }
389
390         /* A negative verbosity means to print at most each X seconds */
391         if (verbose < 0 && next_time != NULL &&
392             difftime(&now, next_time) >= 0.0){
393                 next_time->tv_sec = now.tv_sec - verbose;
394                 next_time->tv_usec = now.tv_usec;
395                 *next_num = num;
396                 return 1;
397         }
398
399         return 0;
400 }
401
402 static int get_verbose(char *func, const char *arg)
403 {
404         int verbose;
405         char *end;
406
407         if (!arg || arg[0] == 'v')
408                 verbose = 1;
409         else if (arg[0] == 's' || arg[0] == 'q')
410                 verbose = 0;
411         else {
412                 verbose = (int)strtoul(arg, &end, 0);
413                 if (*end) {
414                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
415                                 jt_cmdname(func), arg);
416                         return BAD_VERBOSE;
417                 }
418         }
419
420         if (verbose < 0)
421                 printf("Print status every %d seconds\n", -verbose);
422         else if (verbose == 1)
423                 printf("Print status every operation\n");
424         else if (verbose > 1)
425                 printf("Print status every %d operations\n", verbose);
426
427         return verbose;
428 }
429
430 int do_disconnect(char *func, int verbose)
431 {
432         lcfg_set_devname(NULL);
433         cur_device = -1;
434         return 0;
435 }
436
437 #ifdef MAX_THREADS
438 static int shmem_setup(void)
439 {
440         pthread_mutexattr_t mattr;
441         pthread_condattr_t  cattr;
442         int                 rc;
443         int                 shmid;
444
445         /* Create new segment */
446         shmid = shmget(IPC_PRIVATE, sizeof(*shared_data), 0600);
447         if (shmid == -1) {
448                 fprintf(stderr, "Can't create shared data: %s\n",
449                         strerror(errno));
450                 return errno;
451         }
452
453         /* Attatch to new segment */
454         shared_data = (struct shared_data *)shmat(shmid, NULL, 0);
455
456         if (shared_data == (struct shared_data *)(-1)) {
457                 fprintf(stderr, "Can't attach shared data: %s\n",
458                         strerror(errno));
459                 shared_data = NULL;
460                 return errno;
461         }
462
463         /* Mark segment as destroyed, so it will disappear when we exit.
464          * Forks will inherit attached segments, so we should be OK.
465          */
466         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
467                 fprintf(stderr, "Can't destroy shared data: %s\n",
468                         strerror(errno));
469                 return errno;
470         }
471
472         pthread_mutexattr_init(&mattr);
473         pthread_condattr_init(&cattr);
474
475         rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
476         if (rc != 0) {
477                 fprintf(stderr, "Can't set shared mutex attr\n");
478                 return rc;
479         }
480
481         rc = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
482         if (rc != 0) {
483                 fprintf(stderr, "Can't set shared cond attr\n");
484                 return rc;
485         }
486
487         pthread_mutex_init(&shared_data->mutex, &mattr);
488         pthread_cond_init(&shared_data->cond, &cattr);
489
490         pthread_mutexattr_destroy(&mattr);
491         pthread_condattr_destroy(&cattr);
492
493         return 0;
494 }
495
496 static inline void shmem_lock(void)
497 {
498         l_mutex_lock(&shared_data->mutex);
499 }
500
501 static inline void shmem_unlock(void)
502 {
503         l_mutex_unlock(&shared_data->mutex);
504 }
505
506 static inline void shmem_wait(void)
507 {
508         l_cond_wait(&shared_data->cond, &shared_data->mutex);
509 }
510
511 static inline void shmem_wakeup_all(void)
512 {
513         l_cond_broadcast(&shared_data->cond);
514 }
515
516 static inline void shmem_reset(int total_threads)
517 {
518         if (shared_data == NULL)
519                 return;
520
521         memset(&shared_data->body, 0, sizeof(shared_data->body));
522         memset(counter_snapshot, 0, sizeof(counter_snapshot));
523         prev_valid = 0;
524         shared_data->stopping = 0;
525         shared_data->body.start_barrier = total_threads;
526         shared_data->body.stop_barrier = total_threads;
527 }
528
529 static inline void shmem_bump(__u32 counter)
530 {
531         static bool running_not_bumped = true;
532
533         if (shared_data == NULL || thread <= 0 || thread > MAX_THREADS)
534                 return;
535
536         shmem_lock();
537         shared_data->body.counters[thread - 1] += counter;
538         if (running_not_bumped) {
539                 shared_data->body.thr_running++;
540                 running_not_bumped = false;
541         }
542         shmem_unlock();
543 }
544
545 static void shmem_total(int total_threads)
546 {
547         __u64 total = 0;
548         double secs;
549         int i;
550
551         if (shared_data == NULL || total_threads > MAX_THREADS)
552                 return;
553
554         shmem_lock();
555         for (i = 0; i < total_threads; i++)
556                 total += shared_data->body.counters[i];
557
558         secs = difftime(&shared_data->body.end_time,
559                         &shared_data->body.start_time);
560         shmem_unlock();
561
562         printf("Total: total %llu threads %d sec %f %f/second\n", total,
563                 total_threads, secs, total / secs);
564
565         return;
566 }
567
568 static void shmem_snap(int total_threads, int live_threads)
569 {
570         struct timeval this_time;
571         int non_zero = 0;
572         __u64 total = 0;
573         double secs;
574         int running;
575         int i;
576
577         if (shared_data == NULL || total_threads > MAX_THREADS)
578                 return;
579
580         shmem_lock();
581         memcpy(counter_snapshot[0], shared_data->body.counters,
582                total_threads * sizeof(counter_snapshot[0][0]));
583         running = shared_data->body.thr_running;
584         shmem_unlock();
585
586         gettimeofday(&this_time, NULL);
587
588         for (i = 0; i < total_threads; i++) {
589                 long long this_count =
590                         counter_snapshot[0][i] - counter_snapshot[1][i];
591
592                 if (this_count != 0) {
593                         non_zero++;
594                         total += this_count;
595                 }
596         }
597
598         secs = difftime(&this_time, &prev_time);
599         if (prev_valid && secs > 1.0)    /* someone screwed with the time? */
600                 printf("%d/%d Total: %f/second\n", non_zero, total_threads,
601                        total / secs);
602
603         memcpy(counter_snapshot[1], counter_snapshot[0],
604                total_threads * sizeof(counter_snapshot[0][0]));
605         prev_time = this_time;
606         if (!prev_valid &&
607             running == total_threads)
608                 prev_valid = 1;
609 }
610
611 static void shmem_stop(void)
612 {
613         if (shared_data == NULL)
614                 return;
615
616         shared_data->stopping = 1;
617 }
618
619 static void shmem_cleanup(void)
620 {
621         if (shared_data == NULL)
622                 return;
623
624         shmem_stop();
625
626         pthread_mutex_destroy(&shared_data->mutex);
627         pthread_cond_destroy(&shared_data->cond);
628 }
629
630 static int shmem_running(void)
631 {
632         return (shared_data == NULL || !shared_data->stopping);
633 }
634 #else
635 static int shmem_setup(void)
636 {
637         return 0;
638 }
639
640 static inline void shmem_reset(int total_threads)
641 {
642 }
643
644 static inline void shmem_bump(__u32 counters)
645 {
646 }
647
648 static void shmem_lock()
649 {
650 }
651
652 static void shmem_unlock()
653 {
654 }
655
656 static void shmem_cleanup(void)
657 {
658 }
659
660 static int shmem_running(void)
661 {
662         return 1;
663 }
664 #endif
665
666 extern command_t cmdlist[];
667
668 static int do_device(char *func, char *devname)
669 {
670         int dev;
671
672         dev = parse_devname(func, devname);
673         if (dev < 0)
674                 return -1;
675
676         lcfg_set_devname(devname);
677         cur_device = dev;
678         return 0;
679 }
680
681 int jt_obd_get_device()
682 {
683         return cur_device;
684 }
685
686 int jt_obd_device(int argc, char **argv)
687 {
688         int rc;
689
690         if (argc > 2)
691                 return CMD_HELP;
692
693         if (argc == 1) {
694                 printf("current device is %d - %s\n",
695                        cur_device, lcfg_get_devname() ? : "not set");
696                 return 0;
697         }
698         rc = do_device("device", argv[1]);
699         return rc;
700 }
701
702 int jt_opt_device(int argc, char **argv)
703 {
704         int ret;
705         int rc;
706
707         if (argc < 3)
708                 return CMD_HELP;
709
710         rc = do_device("device", argv[1]);
711
712         if (!rc)
713                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
714
715         ret = do_disconnect(argv[0], 0);
716         if (!rc)
717                 rc = ret;
718
719         return rc;
720 }
721
722 #ifdef MAX_THREADS
723 static void parent_sighandler (int sig)
724 {
725         return;
726 }
727
728 int jt_opt_threads(int argc, char **argv)
729 {
730         static char      cmdstr[128];
731         sigset_t         saveset;
732         sigset_t         sigset;
733         struct sigaction sigact;
734         struct sigaction saveact1;
735         struct sigaction saveact2;
736         unsigned long    threads;
737         __u64            next_thread;
738         int verbose;
739         int rc = 0;
740         int report_count = -1;
741         char *end;
742         int i;
743
744         if (argc < 5)
745                 return CMD_HELP;
746
747         threads = strtoul(argv[1], &end, 0);
748
749         if (*end == '.')
750                 report_count = strtoul(end + 1, &end, 0);
751
752         if (*end || threads > MAX_THREADS) {
753                 fprintf(stderr, "error: %s: invalid thread count '%s'\n",
754                         jt_cmdname(argv[0]), argv[1]);
755                 return CMD_HELP;
756         }
757
758         verbose = get_verbose(argv[0], argv[2]);
759         if (verbose == BAD_VERBOSE)
760                 return CMD_HELP;
761
762         if (verbose != 0) {
763                 snprintf(cmdstr, sizeof(cmdstr), "%s", argv[4]);
764                 for (i = 5; i < argc; i++)
765                         snprintf(cmdstr + strlen(cmdstr), sizeof(cmdstr),
766                                  " %s", argv[i]);
767
768                 printf("%s: starting %ld threads on device %s running %s\n",
769                        argv[0], threads, argv[3], cmdstr);
770         }
771
772         shmem_reset(threads);
773
774         sigemptyset(&sigset);
775         sigaddset(&sigset, SIGALRM);
776         sigaddset(&sigset, SIGCHLD);
777         sigprocmask(SIG_BLOCK, &sigset, &saveset);
778
779         nthreads = threads;
780
781         for (i = 1, next_thread = verbose; i <= threads; i++) {
782                 rc = fork();
783                 if (rc < 0) {
784                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
785                                 strerror(rc = errno));
786                         break;
787                 } else if (rc == 0) {
788                         sigprocmask(SIG_SETMASK, &saveset, NULL);
789
790                         thread = i;
791                         argv[2] = "--device";
792                         exit(jt_opt_device(argc - 2, argv + 2));
793                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
794                         printf("%s: thread #%d (PID %d) started\n",
795                                argv[0], i, rc);
796                 rc = 0;
797         }
798
799         if (!thread) {          /* parent process */
800                 int live_threads = threads;
801
802                 sigemptyset(&sigset);
803                 sigemptyset(&sigact.sa_mask);
804                 sigact.sa_handler = parent_sighandler;
805                 sigact.sa_flags = 0;
806
807                 sigaction(SIGALRM, &sigact, &saveact1);
808                 sigaction(SIGCHLD, &sigact, &saveact2);
809
810                 while (live_threads > 0) {
811                         int status;
812                         pid_t ret;
813
814                         if (verbose < 0)        /* periodic stats */
815                                 alarm(-verbose);
816
817                         sigsuspend(&sigset);
818                         alarm(0);
819
820                         while (live_threads > 0) {
821                                 ret = waitpid(0, &status, WNOHANG);
822                                 if (ret == 0)
823                                         break;
824
825                                 if (ret < 0) {
826                                         fprintf(stderr, "error: %s: wait - %s\n",
827                                                 argv[0], strerror(errno));
828                                         if (!rc)
829                                                 rc = errno;
830                                         continue;
831                                 } else {
832                                         /*
833                                          * This is a hack.  We _should_ be able
834                                          * to use WIFEXITED(status) to see if
835                                          * there was an error, but it appears
836                                          * to be broken and it always returns 1
837                                          * (OK).  See wait(2).
838                                          */
839                                         int err = WEXITSTATUS(status);
840                                         if (err || WIFSIGNALED(status))
841                                                 fprintf(stderr,
842                                                         "%s: PID %d had rc=%d\n",
843                                                         argv[0], ret, err);
844                                         if (!rc)
845                                                 rc = err;
846
847                                         live_threads--;
848                                 }
849                         }
850
851                         /* Show stats while all threads running */
852                         if (verbose < 0) {
853                                 shmem_snap(threads, live_threads);
854                                 if (report_count > 0 && --report_count == 0)
855                                         shmem_stop();
856                         }
857                 }
858                 sigaction(SIGCHLD, &saveact2, NULL);
859                 sigaction(SIGALRM, &saveact1, NULL);
860         }
861
862         shmem_total(threads);
863         sigprocmask(SIG_SETMASK, &saveset, NULL);
864
865         return rc;
866 }
867 #else
868 int jt_opt_threads(int argc, char **argv)
869 {
870         fprintf(stderr, "%s not-supported in a single-threaded runtime\n",
871                 jt_cmdname(argv[0]));
872         return CMD_HELP;
873 }
874 #endif
875
876 int jt_opt_net(int argc, char **argv)
877 {
878         char *arg2[3];
879         int rc;
880
881         if (argc < 3)
882                 return CMD_HELP;
883
884         arg2[0] = argv[0];
885         arg2[1] = argv[1];
886         arg2[2] = NULL;
887         rc = jt_ptl_network (2, arg2);
888
889         if (!rc)
890                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
891
892         return rc;
893 }
894
895 int jt_obd_no_transno(int argc, char **argv)
896 {
897         struct obd_ioctl_data data;
898         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
899         int rc;
900
901         memset(&data, 0, sizeof(data));
902         data.ioc_dev = cur_device;
903
904         if (argc != 1)
905                 return CMD_HELP;
906
907         memset(buf, 0, sizeof(rawbuf));
908         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
909         if (rc) {
910                 fprintf(stderr, "error: %s: invalid ioctl\n",
911                         jt_cmdname(argv[0]));
912                 return rc;
913         }
914         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf);
915         if (rc < 0)
916                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
917                         strerror(rc = errno));
918
919         return rc;
920 }
921
922 int jt_obd_set_readonly(int argc, char **argv)
923 {
924         struct obd_ioctl_data data;
925         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
926         int rc;
927
928         memset(&data, 0, sizeof(data));
929         data.ioc_dev = cur_device;
930
931         if (argc != 1)
932                 return CMD_HELP;
933
934         memset(buf, 0, sizeof(rawbuf));
935         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
936         if (rc) {
937                 fprintf(stderr, "error: %s: invalid ioctl\n",
938                         jt_cmdname(argv[0]));
939                 return rc;
940         }
941         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf);
942         if (rc < 0)
943                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
944                         strerror(rc = errno));
945
946         return rc;
947 }
948
949 int jt_obd_abort_recovery(int argc, char **argv)
950 {
951         struct obd_ioctl_data data;
952         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
953         int rc;
954
955         memset(&data, 0, sizeof(data));
956         data.ioc_dev = cur_device;
957
958         if (argc != 1)
959                 return CMD_HELP;
960
961         memset(buf, 0, sizeof(rawbuf));
962         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
963         if (rc) {
964                 fprintf(stderr, "error: %s: invalid ioctl\n",
965                         jt_cmdname(argv[0]));
966                 return rc;
967         }
968         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf);
969         if (rc < 0)
970                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
971                         strerror(rc = errno));
972
973         return rc;
974 }
975
976 int jt_get_version(int argc, char **argv)
977 {
978         int rc;
979         char rawbuf[MAX_IOC_BUFLEN];
980         char *version;
981
982         if (argc != 1)
983                 return CMD_HELP;
984
985         rc = llapi_get_version(rawbuf, MAX_IOC_BUFLEN, &version);
986         if (rc)
987                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
988                         strerror(-rc));
989         else
990                 printf("Lustre version: %s\n", version);
991
992         printf("lctl   version: %s\n", BUILD_VERSION);
993         return rc;
994 }
995
996 /*
997  * Print an obd device line with the ost_conn_uuid inserted, if the obd
998  * is an osc.
999  */
1000 static void print_obd_line(char *s)
1001 {
1002         char buf[MAX_STRING_SIZE];
1003         char obd_name[MAX_OBD_NAME];
1004         FILE *fp = NULL;
1005         char *ptr;
1006
1007         if (sscanf(s, " %*d %*s osc %s %*s %*d ", obd_name) == 0)
1008                 goto try_mdc;
1009         snprintf(buf, sizeof(buf),
1010                  "/proc/fs/lustre/osc/%s/ost_conn_uuid", obd_name);
1011         if ((fp = fopen(buf, "r")) == NULL)
1012                 goto try_mdc;
1013         goto got_one;
1014
1015 try_mdc:
1016         if (sscanf(s, " %*d %*s mdc %s %*s %*d ", obd_name) == 0)
1017                 goto fail;
1018         snprintf(buf, sizeof(buf),
1019                  "/proc/fs/lustre/mdc/%s/mds_conn_uuid", obd_name);
1020         if ((fp = fopen(buf, "r")) == NULL)
1021                 goto fail;
1022
1023 got_one:
1024         /* should not ignore fgets(3)'s return value */
1025         if (!fgets(buf, sizeof(buf), fp)) {
1026                 fprintf(stderr, "reading from %s: %s", buf, strerror(errno));
1027                 fclose(fp);
1028                 return;
1029         }
1030         fclose(fp);
1031
1032         /* trim trailing newlines */
1033         ptr = strrchr(buf, '\n');
1034         if (ptr) *ptr = '\0';
1035         ptr = strrchr(s, '\n');
1036         if (ptr) *ptr = '\0';
1037
1038         printf("%s %s\n", s, buf);
1039         return;
1040
1041 fail:
1042         printf("%s", s);
1043         return;
1044 }
1045
1046 /* get device list by ioctl */
1047 int jt_obd_list_ioctl(int argc, char **argv)
1048 {
1049         int rc, index;
1050         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1051         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
1052
1053         if (argc > 2)
1054                 return CMD_HELP;
1055         /* Just ignore a -t option.  Only supported with /proc. */
1056         else if (argc == 2 && strcmp(argv[1], "-t") != 0)
1057                 return CMD_HELP;
1058
1059         for (index = 0;; index++) {
1060                 memset(buf, 0, sizeof(rawbuf));
1061                 data->ioc_version = OBD_IOCTL_VERSION;
1062                 data->ioc_inllen1 =
1063                         sizeof(rawbuf) - cfs_size_round(sizeof(*data));
1064                 data->ioc_inlbuf1 = buf + cfs_size_round(sizeof(*data));
1065                 data->ioc_len = obd_ioctl_packlen(data);
1066                 data->ioc_count = index;
1067
1068                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETDEVICE, buf);
1069                 if (rc != 0)
1070                         break;
1071                 printf("%s\n", (char *)data->ioc_bulk);
1072         }
1073         if (rc != 0) {
1074                 if (errno == ENOENT)
1075                         /* no device or the last device */
1076                         rc = 0;
1077                 else
1078                         fprintf(stderr, "Error getting device list: %s: "
1079                                 "check dmesg.\n", strerror(errno));
1080         }
1081         return rc;
1082 }
1083
1084 int jt_obd_list(int argc, char **argv)
1085 {
1086         int rc;
1087         char buf[MAX_STRING_SIZE];
1088         FILE *fp = NULL;
1089         int print_obd = 0;
1090
1091         if (argc > 2)
1092                 return CMD_HELP;
1093         else if (argc == 2) {
1094                 if (strcmp(argv[1], "-t") == 0)
1095                         print_obd = 1;
1096                 else
1097                         return CMD_HELP;
1098         }
1099
1100         fp = fopen(DEVICES_LIST, "r");
1101         if (fp == NULL) {
1102                 fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
1103                         jt_cmdname(argv[0]), strerror(rc =  errno));
1104                 return jt_obd_list_ioctl(argc, argv);
1105         }
1106
1107         while (fgets(buf, sizeof(buf), fp) != NULL)
1108                 if (print_obd)
1109                         print_obd_line(buf);
1110                 else
1111                         printf("%s", buf);
1112
1113         fclose(fp);
1114         return 0;
1115 }
1116
1117 struct jt_fid_space {
1118         obd_seq jt_seq;
1119         obd_id  jt_id;
1120         int     jt_width;
1121 };
1122
1123 int jt_obd_alloc_fids(struct jt_fid_space *space, struct lu_fid *fid,
1124                       __u64 *count)
1125 {
1126         int rc;
1127
1128         if (space->jt_seq == 0 || space->jt_id == space->jt_width) {
1129                 struct obd_ioctl_data  data;
1130                 char rawbuf[MAX_IOC_BUFLEN];
1131                 char *buf = rawbuf;
1132                 __u64 seqnr;
1133                 int max_count;
1134
1135                 memset(&data, 0, sizeof(data));
1136                 data.ioc_dev = cur_device;
1137
1138                 data.ioc_pbuf1 = (char *)&seqnr;
1139                 data.ioc_plen1 = sizeof(seqnr);
1140
1141                 data.ioc_pbuf2 = (char *)&max_count;
1142                 data.ioc_plen2 = sizeof(max_count);
1143
1144                 memset(buf, 0, sizeof(rawbuf));
1145                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1146                 if (rc) {
1147                         fprintf(stderr, "error: invalid ioctl rc = %d\n", rc);
1148                         return rc;
1149                 }
1150
1151                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ECHO_ALLOC_SEQ, buf);
1152                 if (rc) {
1153                         fprintf(stderr, "ioctl error: rc = %d\n", rc);
1154                         return rc;
1155                 }
1156
1157                 space->jt_seq = *(__u64 *)data.ioc_pbuf1;
1158                 space->jt_width = *(int *)data.ioc_pbuf2;
1159                 space->jt_id = 1;
1160         }
1161         fid->f_seq = space->jt_seq;
1162         fid->f_oid = space->jt_id;
1163         fid->f_ver = 0;
1164
1165         space->jt_id = min(space->jt_id + *count, space->jt_width);
1166
1167         *count = space->jt_id - fid->f_oid;
1168         return 0;
1169 }
1170
1171 #define MD_STEP_COUNT 1000
1172 int jt_obd_md_common(int argc, char **argv, int cmd)
1173 {
1174         struct obd_ioctl_data  data;
1175         struct timeval         start;
1176         struct timeval         next_time;
1177         struct timeval         end_time;
1178         char                   rawbuf[MAX_IOC_BUFLEN];
1179         char                  *buf = rawbuf;
1180         int                    verbose = 1;
1181         int                    mode = 0000644;
1182         int                    create_mode;
1183         int                    rc = 0;
1184         char                  *parent_basedir = NULL;
1185         char                   dirname[4096];
1186         int                    parent_base_id = 0;
1187         int                    parent_count = 1;
1188         __u64                  child_base_id = -1;
1189         int                    stripe_count = 0;
1190         int                    stripe_index = -1;
1191         int                    count = 0;
1192         char                  *end;
1193         __u64                  seconds = 0;
1194         double                 diff;
1195         int                    c;
1196         int                    xattr_size = 0;
1197         __u64                  total_count = 0;
1198         char                  *name = NULL;
1199         struct jt_fid_space    fid_space = {0};
1200         int                    version = 0;
1201         struct option          long_opts[] = {
1202                 {"child_base_id",     required_argument, 0, 'b'},
1203                 {"stripe_count",      required_argument, 0, 'c'},
1204                 {"parent_basedir",    required_argument, 0, 'd'},
1205                 {"parent_dircount",   required_argument, 0, 'D'},
1206                 {"stripe_index",      required_argument, 0, 'i'},
1207                 {"mode",              required_argument, 0, 'm'},
1208                 {"count",             required_argument, 0, 'n'},
1209                 {"time",              required_argument, 0, 't'},
1210                 {"version",           no_argument,       0, 'v'},
1211                 {"xattr_size",        required_argument, 0, 'x'},
1212                 {0, 0, 0, 0}
1213         };
1214
1215         optind = 0;
1216         while ((c = getopt_long(argc, argv, "b:c:d:D:m:n:t:vx:",
1217                                 long_opts, NULL)) >= 0) {
1218                 switch (c) {
1219                 case 'b':
1220                         child_base_id = strtoull(optarg, &end, 0);
1221                         if (*end) {
1222                                 fprintf(stderr, "error: %s: bad child_base_id"
1223                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1224                                 return CMD_HELP;
1225                         }
1226                         break;
1227                 case 'c':
1228                         stripe_count = strtoul(optarg, &end, 0);
1229                         if (*end) {
1230                                 fprintf(stderr, "error: %s: bad stripe count"
1231                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1232                                 return CMD_HELP;
1233                         }
1234                         break;
1235                 case 'd':
1236                         parent_basedir = optarg;
1237                         break;
1238                 case 'D':
1239                         parent_count = strtoul(optarg, &end, 0);
1240                         if (*end) {
1241                                 fprintf(stderr, "error: %s: bad parent count"
1242                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1243                                 return CMD_HELP;
1244                         }
1245                         break;
1246                 case 'i':
1247                         stripe_index = strtoul(optarg, &end, 0);
1248                         if (*end) {
1249                                 fprintf(stderr, "error: %s: bad stripe index"
1250                                         " '%s'\n", jt_cmdname(argv[0]), optarg);
1251                                 return CMD_HELP;
1252                         }
1253                         break;
1254                 case 'm':
1255                         mode = strtoul(optarg, &end, 0);
1256                         if (*end) {
1257                                 fprintf(stderr, "error: %s: bad mode '%s'\n",
1258                                         jt_cmdname(argv[0]), optarg);
1259                                 return CMD_HELP;
1260                         }
1261                         break;
1262                 case 'n':
1263                         total_count = strtoul(optarg, &end, 0);
1264                         if (*end || total_count == 0) {
1265                                 fprintf(stderr, "%s: bad child count '%s'\n",
1266                                         jt_cmdname(argv[0]), optarg);
1267                                 return CMD_HELP;
1268                         }
1269                         break;
1270                 case 't':
1271                         seconds = strtoull(optarg, &end, 0);
1272                         if (*end) {
1273                                 fprintf(stderr, "error: %s: senconds '%s'\n",
1274                                         jt_cmdname(argv[0]), optarg);
1275                                 return CMD_HELP;
1276                         }
1277                         break;
1278                 case 'v':
1279                         version = 1;
1280                         break;
1281                 case 'x':
1282                         xattr_size = strtoul(optarg, &end, 0);
1283                         if (*end) {
1284                                 fprintf(stderr, "error: %s: senconds '%s'\n",
1285                                         jt_cmdname(argv[0]), optarg);
1286                                 return CMD_HELP;
1287                         }
1288                         break;
1289                 default:
1290                         fprintf(stderr, "error: %s: option '%s' "
1291                                 "unrecognized\n", argv[0], argv[optind - 1]);
1292                         return CMD_HELP;
1293                 }
1294         }
1295
1296         memset(&data, 0, sizeof(data));
1297         data.ioc_dev = cur_device;
1298         if (child_base_id == -1) {
1299                 if (optind >= argc)
1300                         return CMD_HELP;
1301                 name = argv[optind];
1302                 total_count = 1;
1303         } else {
1304                 if (optind < argc) {
1305                         fprintf(stderr, "child_base_id and name can not"
1306                                         " specified at the same time\n");
1307                         return CMD_HELP;
1308                 }
1309         }
1310
1311         if (stripe_count == 0 && stripe_index != -1) {
1312                 fprintf(stderr, "If stripe_count is 0, stripe_index can not"
1313                                 "be specified\n");
1314                 return CMD_HELP;
1315         }
1316
1317         if (total_count == 0 && seconds == 0) {
1318                 fprintf(stderr, "count or seconds needs to be indicated\n");
1319                 return CMD_HELP;
1320         }
1321
1322         if (parent_count <= 0) {
1323                 fprintf(stderr, "parent count must < 0\n");
1324                 return CMD_HELP;
1325         }
1326
1327 #ifdef MAX_THREADS
1328         if (thread) {
1329                 shmem_lock();
1330                 /* threads interleave */
1331                 if (parent_base_id != -1)
1332                         parent_base_id += (thread - 1) % parent_count;
1333
1334                 if (child_base_id != -1)
1335                         child_base_id +=  (thread - 1) * \
1336                                           (MAX_BASE_ID / nthreads);
1337
1338                 shared_data->body.start_barrier--;
1339                 if (shared_data->body.start_barrier == 0) {
1340                         shmem_wakeup_all();
1341
1342                         gettimeofday(&shared_data->body.start_time, NULL);
1343                         printf("%s: start at %s", jt_cmdname(argv[0]),
1344                                ctime(&shared_data->body.start_time.tv_sec));
1345                 } else {
1346                         shmem_wait();
1347                 }
1348                 shmem_unlock();
1349         }
1350 #endif
1351         /* If parent directory is not specified, try to get the directory
1352          * from name */
1353         if (parent_basedir == NULL) {
1354                 char *last_lash;
1355                 if (name == NULL) {
1356                         fprintf(stderr, "parent_basedir or name must be"
1357                                         "indicated!\n");
1358                         return CMD_HELP;
1359                 }
1360                 /*Get directory and name from name*/
1361                 last_lash = strrchr(name, '/');
1362                 if (last_lash == NULL || name[0] != '/') {
1363                         fprintf(stderr, "Can not locate %s\n", name);
1364                         return CMD_HELP;
1365                 }
1366
1367                 if (last_lash == name) {
1368                         sprintf(dirname, "%s", "/");
1369                         name++;
1370                 } else {
1371                         int namelen = (unsigned long)last_lash -
1372                                       (unsigned long)name;
1373                         snprintf(dirname, namelen, "%s", name);
1374                 }
1375
1376                 data.ioc_pbuf1 = dirname;
1377                 data.ioc_plen1 = strlen(dirname);
1378
1379                 data.ioc_pbuf2 = name;
1380                 data.ioc_plen2 = strlen(name);
1381         } else {
1382                 if (name != NULL) {
1383                         data.ioc_pbuf2 = name;
1384                         data.ioc_plen2 = strlen(name);
1385                 } else {
1386                         if (parent_base_id > 0)
1387                                 sprintf(dirname, "%s%d", parent_basedir,
1388                                         parent_base_id);
1389                         else
1390                                 sprintf(dirname, "%s", parent_basedir);
1391                 }
1392                 data.ioc_pbuf1 = dirname;
1393                 data.ioc_plen1 = strlen(dirname);
1394         }
1395
1396         if (cmd == ECHO_MD_MKDIR || cmd == ECHO_MD_RMDIR)
1397                 create_mode = S_IFDIR;
1398         else
1399                 create_mode = S_IFREG;
1400
1401         data.ioc_obdo1.o_mode = mode | S_IFDIR;
1402         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE |
1403                                  OBD_MD_FLFLAGS | OBD_MD_FLGROUP;
1404         data.ioc_command = cmd;
1405
1406         gettimeofday(&start, NULL);
1407         next_time.tv_sec = start.tv_sec - verbose;
1408         next_time.tv_usec = start.tv_usec;
1409         while (shmem_running()) {
1410                 struct lu_fid fid;
1411
1412                 data.ioc_obdo2.o_id = child_base_id;
1413                 data.ioc_obdo2.o_mode = mode | create_mode;
1414                 data.ioc_obdo2.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE |
1415                                          OBD_MD_FLMODE | OBD_MD_FLFLAGS |
1416                                          OBD_MD_FLGROUP;
1417                 data.ioc_obdo2.o_misc = stripe_count;
1418                 data.ioc_obdo2.o_stripe_idx = stripe_index;
1419
1420                 if (total_count > 0) {
1421                         if ((total_count - count) > MD_STEP_COUNT)
1422                                 data.ioc_count = MD_STEP_COUNT;
1423                         else
1424                                 data.ioc_count = total_count - count;
1425                 } else {
1426                         data.ioc_count = MD_STEP_COUNT;
1427                 }
1428
1429                 child_base_id += data.ioc_count;
1430                 count += data.ioc_count;
1431                 if (cmd == ECHO_MD_CREATE || cmd == ECHO_MD_MKDIR) {
1432                         /*Allocate fids for the create */
1433                         rc = jt_obd_alloc_fids(&fid_space, &fid,
1434                                                &data.ioc_count);
1435                         if (rc) {
1436                                 fprintf(stderr, "Allocate fids error %d.\n",rc);
1437                                 return rc;
1438                         }
1439                         data.ioc_obdo1.o_seq = fid.f_seq;
1440                         data.ioc_obdo1.o_id = fid.f_oid;
1441                 }
1442                 memset(buf, 0, sizeof(rawbuf));
1443                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1444                 if (rc) {
1445                         fprintf(stderr, "error: %s: invalid ioctl %d\n",
1446                                 jt_cmdname(argv[0]), rc);
1447                         return rc;
1448                 }
1449
1450                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ECHO_MD, buf);
1451                 if (rc) {
1452                         fprintf(stderr, "error: %s: %s\n",
1453                                 jt_cmdname(argv[0]), strerror(rc = errno));
1454                         return rc;
1455                 }
1456                 shmem_bump(data.ioc_count);
1457
1458                 gettimeofday(&end_time, NULL);
1459                 diff = difftime(&end_time, &start);
1460                 if (seconds > 0 && (__u64)diff > seconds)
1461                         break;
1462
1463                 if (count >= total_count && total_count > 0)
1464                         break;
1465         }
1466
1467         if (count > 0 && version) {
1468                 gettimeofday(&end_time, NULL);
1469                 diff = difftime(&end_time, &start);
1470                 printf("%s: %d in %.3fs (%.3f /s): %s",
1471                         jt_cmdname(argv[0]), count, diff,
1472                         (double)count/diff, ctime(&end_time.tv_sec));
1473         }
1474
1475 #ifdef MAX_THREADS
1476         if (thread) {
1477                 shmem_lock();
1478                 shared_data->body.stop_barrier--;
1479                 if (shared_data->body.stop_barrier == 0) {
1480                         gettimeofday(&shared_data->body.end_time, NULL);
1481                         printf("%s: end at %s", jt_cmdname(argv[0]),
1482                                 ctime(&shared_data->body.end_time.tv_sec));
1483                 }
1484                 shmem_unlock();
1485         }
1486 #endif
1487         return rc;
1488 }
1489
1490 int jt_obd_test_create(int argc, char **argv)
1491 {
1492         return jt_obd_md_common(argc, argv, ECHO_MD_CREATE);
1493 }
1494
1495 int jt_obd_test_mkdir(int argc, char **argv)
1496 {
1497         return jt_obd_md_common(argc, argv, ECHO_MD_MKDIR);
1498 }
1499
1500 int jt_obd_test_destroy(int argc, char **argv)
1501 {
1502         return jt_obd_md_common(argc, argv, ECHO_MD_DESTROY);
1503 }
1504
1505 int jt_obd_test_rmdir(int argc, char **argv)
1506 {
1507         return jt_obd_md_common(argc, argv, ECHO_MD_RMDIR);
1508 }
1509
1510 int jt_obd_test_lookup(int argc, char **argv)
1511 {
1512         return jt_obd_md_common(argc, argv, ECHO_MD_LOOKUP);
1513 }
1514
1515 int jt_obd_test_setxattr(int argc, char **argv)
1516 {
1517         return jt_obd_md_common(argc, argv, ECHO_MD_SETATTR);
1518 }
1519
1520 int jt_obd_test_md_getattr(int argc, char **argv)
1521 {
1522         return jt_obd_md_common(argc, argv, ECHO_MD_GETATTR);
1523 }
1524
1525 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1526  * not, defaults assumed.  This echo-client instance stashes the stripe
1527  * object ids.  Use get_stripe on this node to print full lsm and
1528  * set_stripe on another node to cut/paste between nodes.
1529  */
1530 /* create <count> [<file_create_mode>] [q|v|# verbosity] [striping] */
1531 int jt_obd_create(int argc, char **argv)
1532 {
1533         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1534         struct obd_ioctl_data data;
1535         struct timeval next_time;
1536         __u64 count = 1, next_count, base_id = 0;
1537         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
1538         char *end;
1539
1540         memset(&data, 0, sizeof(data));
1541         data.ioc_dev = cur_device;
1542         if (argc < 2 || argc > 5)
1543                 return CMD_HELP;
1544
1545         count = strtoull(argv[1], &end, 0);
1546         if (*end) {
1547                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1548                         jt_cmdname(argv[0]), argv[1]);
1549                 return CMD_HELP;
1550         }
1551
1552         if (argc > 2) {
1553                 mode = strtoul(argv[2], &end, 0);
1554                 if (*end) {
1555                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1556                                 jt_cmdname(argv[0]), argv[2]);
1557                         return CMD_HELP;
1558                 }
1559                 if (!(mode & S_IFMT))
1560                         mode |= S_IFREG;
1561         }
1562
1563         if (argc > 3) {
1564                 verbose = get_verbose(argv[0], argv[3]);
1565                 if (verbose == BAD_VERBOSE)
1566                         return CMD_HELP;
1567         }
1568
1569         if (argc < 5) {
1570                 reset_lsmb (&lsm_buffer);       /* will set default */
1571         } else {
1572                 rc = parse_lsm (&lsm_buffer, argv[4]);
1573                 if (rc != 0) {
1574                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1575                                 jt_cmdname(argv[0]), argv[4]);
1576                         return CMD_HELP;
1577                 }
1578                 base_id = lsm_buffer.lsm.lsm_object_id;
1579                 valid_lsm = 1;
1580         }
1581
1582         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1583         gettimeofday(&next_time, NULL);
1584         next_time.tv_sec -= verbose;
1585
1586         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1587                 data.ioc_obdo1.o_mode = mode;
1588                 data.ioc_obdo1.o_id = base_id;
1589                 data.ioc_obdo1.o_uid = 0;
1590                 data.ioc_obdo1.o_gid = 0;
1591                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1592                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1593
1594                 if (valid_lsm) {
1595                         data.ioc_plen1 = sizeof lsm_buffer;
1596                         data.ioc_pbuf1 = (char *)&lsm_buffer;
1597                 }
1598
1599                 memset(buf, 0, sizeof(rawbuf));
1600                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1601                 if (rc) {
1602                         fprintf(stderr, "error: %s: invalid ioctl\n",
1603                                 jt_cmdname(argv[0]));
1604                         return rc;
1605                 }
1606                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1607                 obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1608                 shmem_bump(1);
1609                 if (rc < 0) {
1610                         fprintf(stderr, "error: %s: #%d - %s\n",
1611                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1612                         break;
1613                 }
1614                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1615                         fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n",
1616                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1617                         rc = EINVAL;
1618                         break;
1619                 }
1620
1621                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1622                         printf("%s: #%d is object id "LPX64"\n",
1623                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1624         }
1625         return rc;
1626 }
1627
1628 int jt_obd_setattr(int argc, char **argv)
1629 {
1630         struct obd_ioctl_data data;
1631         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1632         char *end;
1633         int rc;
1634
1635         memset(&data, 0, sizeof(data));
1636         data.ioc_dev = cur_device;
1637         if (argc != 2)
1638                 return CMD_HELP;
1639
1640         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1641         if (*end) {
1642                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1643                         jt_cmdname(argv[0]), argv[1]);
1644                 return CMD_HELP;
1645         }
1646         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1647         if (*end) {
1648                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1649                         jt_cmdname(argv[0]), argv[2]);
1650                 return CMD_HELP;
1651         }
1652         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1653
1654         memset(buf, 0, sizeof(rawbuf));
1655         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1656         if (rc) {
1657                 fprintf(stderr, "error: %s: invalid ioctl\n",
1658                         jt_cmdname(argv[0]));
1659                 return rc;
1660         }
1661         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1662         if (rc < 0)
1663                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1664                         strerror(rc = errno));
1665
1666         return rc;
1667 }
1668
1669 int jt_obd_test_setattr(int argc, char **argv)
1670 {
1671         struct obd_ioctl_data data;
1672         struct timeval start, next_time;
1673         __u64 i, count, next_count;
1674         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1675         int verbose = 1;
1676         obd_id objid = 3;
1677         char *end;
1678         int rc = 0;
1679
1680         if (argc < 2 || argc > 4)
1681                 return CMD_HELP;
1682
1683         memset(&data, 0, sizeof(data));
1684         data.ioc_dev = cur_device;
1685         count = strtoull(argv[1], &end, 0);
1686         if (*end) {
1687                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1688                         jt_cmdname(argv[0]), argv[1]);
1689                 return CMD_HELP;
1690         }
1691
1692         if (argc >= 3) {
1693                 verbose = get_verbose(argv[0], argv[2]);
1694                 if (verbose == BAD_VERBOSE)
1695                         return CMD_HELP;
1696         }
1697
1698         if (argc >= 4) {
1699                 if (argv[3][0] == 't') {
1700                         objid = strtoull(argv[3] + 1, &end, 0);
1701                         if (thread)
1702                                 objid += thread - 1;
1703                 } else
1704                         objid = strtoull(argv[3], &end, 0);
1705                 if (*end) {
1706                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1707                                 jt_cmdname(argv[0]), argv[3]);
1708                         return CMD_HELP;
1709                 }
1710         }
1711
1712         gettimeofday(&start, NULL);
1713         next_time.tv_sec = start.tv_sec - verbose;
1714         next_time.tv_usec = start.tv_usec;
1715         if (verbose != 0)
1716                 printf("%s: setting "LPD64" attrs (objid "LPX64"): %s",
1717                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1718
1719         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1720                 data.ioc_obdo1.o_id = objid;
1721                 data.ioc_obdo1.o_mode = S_IFREG;
1722                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1723                 memset(buf, 0, sizeof(rawbuf));
1724                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1725                 if (rc) {
1726                         fprintf(stderr, "error: %s: invalid ioctl\n",
1727                                 jt_cmdname(argv[0]));
1728                         return rc;
1729                 }
1730                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data);
1731                 shmem_bump(1);
1732                 if (rc < 0) {
1733                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1734                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1735                         break;
1736                 } else {
1737                         if (be_verbose
1738                             (verbose, &next_time, i, &next_count, count))
1739                                 printf("%s: set attr #"LPD64"\n",
1740                                        jt_cmdname(argv[0]), i);
1741                 }
1742         }
1743
1744         if (!rc) {
1745                 struct timeval end;
1746                 double diff;
1747
1748                 gettimeofday(&end, NULL);
1749
1750                 diff = difftime(&end, &start);
1751
1752                 --i;
1753                 if (verbose != 0)
1754                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1755                                jt_cmdname(argv[0]), i, diff, i / diff,
1756                                ctime(&end.tv_sec));
1757         }
1758         return rc;
1759 }
1760
1761 int jt_obd_destroy(int argc, char **argv)
1762 {
1763         struct obd_ioctl_data data;
1764         struct timeval next_time;
1765         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1766         __u64 count = 1, next_count;
1767         int verbose = 1;
1768         __u64 id;
1769         char *end;
1770         int rc = 0, i;
1771
1772         memset(&data, 0, sizeof(data));
1773         data.ioc_dev = cur_device;
1774         if (argc < 2 || argc > 4)
1775                 return CMD_HELP;
1776
1777         id = strtoull(argv[1], &end, 0);
1778         if (*end || id == 0 || errno != 0) {
1779                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1780                         jt_cmdname(argv[0]), argv[1]);
1781                 return CMD_HELP;
1782         }
1783         if (argc > 2) {
1784                 count = strtoull(argv[2], &end, 0);
1785                 if (*end) {
1786                         fprintf(stderr,
1787                                 "error: %s: invalid iteration count '%s'\n",
1788                                 jt_cmdname(argv[0]), argv[2]);
1789                         return CMD_HELP;
1790                 }
1791         }
1792
1793         if (argc > 3) {
1794                 verbose = get_verbose(argv[0], argv[3]);
1795                 if (verbose == BAD_VERBOSE)
1796                         return CMD_HELP;
1797         }
1798
1799         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1800         gettimeofday(&next_time, NULL);
1801         next_time.tv_sec -= verbose;
1802
1803         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++, id++) {
1804                 data.ioc_obdo1.o_id = id;
1805                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1806                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1807
1808                 memset(buf, 0, sizeof(rawbuf));
1809                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1810                 if (rc) {
1811                         fprintf(stderr, "error: %s: invalid ioctl\n",
1812                                 jt_cmdname(argv[0]));
1813                         return rc;
1814                 }
1815                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1816                 obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1817                 shmem_bump(1);
1818                 if (rc < 0) {
1819                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1820                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1821                         break;
1822                 }
1823
1824                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1825                         printf("%s: #%d is object id "LPX64"\n",
1826                                jt_cmdname(argv[0]), i, id);
1827         }
1828
1829         return rc;
1830 }
1831
1832 int jt_obd_getattr(int argc, char **argv)
1833 {
1834         struct obd_ioctl_data data;
1835         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1836         char *end;
1837         int rc;
1838
1839         if (argc != 2)
1840                 return CMD_HELP;
1841
1842         memset(&data, 0, sizeof(data));
1843         data.ioc_dev = cur_device;
1844         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1845         if (*end) {
1846                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1847                         jt_cmdname(argv[0]), argv[1]);
1848                 return CMD_HELP;
1849         }
1850         /* to help obd filter */
1851         data.ioc_obdo1.o_mode = 0100644;
1852         data.ioc_obdo1.o_valid = 0xffffffff;
1853         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1854
1855         memset(buf, 0, sizeof(rawbuf));
1856         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1857         if (rc) {
1858                 fprintf(stderr, "error: %s: invalid ioctl\n",
1859                         jt_cmdname(argv[0]));
1860                 return rc;
1861         }
1862         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1863         obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1864         if (rc) {
1865                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1866                         strerror(rc = errno));
1867         } else {
1868                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1869                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1870         }
1871         return rc;
1872 }
1873
1874 int jt_obd_test_getattr(int argc, char **argv)
1875 {
1876         struct obd_ioctl_data data;
1877         struct timeval start, next_time;
1878         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1879         __u64 i, count, next_count;
1880         int verbose = 1;
1881         obd_id objid = 3;
1882         char *end;
1883         int rc = 0;
1884
1885         if (argc < 2 || argc > 4)
1886                 return CMD_HELP;
1887
1888         memset(&data, 0, sizeof(data));
1889         data.ioc_dev = cur_device;
1890         count = strtoull(argv[1], &end, 0);
1891         if (*end) {
1892                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1893                         jt_cmdname(argv[0]), argv[1]);
1894                 return CMD_HELP;
1895         }
1896
1897         if (argc >= 3) {
1898                 verbose = get_verbose(argv[0], argv[2]);
1899                 if (verbose == BAD_VERBOSE)
1900                         return CMD_HELP;
1901         }
1902
1903         if (argc >= 4) {
1904                 if (argv[3][0] == 't') {
1905                         objid = strtoull(argv[3] + 1, &end, 0);
1906                         if (thread)
1907                                 objid += thread - 1;
1908                 } else
1909                         objid = strtoull(argv[3], &end, 0);
1910                 if (*end) {
1911                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1912                                 jt_cmdname(argv[0]), argv[3]);
1913                         return CMD_HELP;
1914                 }
1915         }
1916
1917         gettimeofday(&start, NULL);
1918         next_time.tv_sec = start.tv_sec - verbose;
1919         next_time.tv_usec = start.tv_usec;
1920         if (verbose != 0)
1921                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1922                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1923
1924         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1925                 data.ioc_obdo1.o_id = objid;
1926                 data.ioc_obdo1.o_mode = S_IFREG;
1927                 data.ioc_obdo1.o_valid = 0xffffffff;
1928                 memset(buf, 0, sizeof(rawbuf));
1929                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1930                 if (rc) {
1931                         fprintf(stderr, "error: %s: invalid ioctl\n",
1932                                 jt_cmdname(argv[0]));
1933                         return rc;
1934                 }
1935                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1936                 shmem_bump(1);
1937                 if (rc < 0) {
1938                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1939                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1940                         break;
1941                 } else {
1942                         if (be_verbose
1943                             (verbose, &next_time, i, &next_count, count))
1944                                 printf("%s: got attr #"LPD64"\n",
1945                                        jt_cmdname(argv[0]), i);
1946                 }
1947         }
1948
1949         if (!rc) {
1950                 struct timeval end;
1951                 double diff;
1952
1953                 gettimeofday(&end, NULL);
1954
1955                 diff = difftime(&end, &start);
1956
1957                 --i;
1958                 if (verbose != 0)
1959                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1960                                jt_cmdname(argv[0]), i, diff, i / diff,
1961                                ctime(&end.tv_sec));
1962         }
1963         return rc;
1964 }
1965
1966 /* test_brw <cnt>                                               count
1967         <r|w[r(repeat)x(noverify)]>                             mode
1968         <q|v|#(print interval)>                                 verbosity
1969         <npages[+offset]>                                       blocksize
1970         <[[<interleave_threads>]t(inc obj by thread#)]obj>      object
1971         [p|g<args>]                                             batch */
1972 int jt_obd_test_brw(int argc, char **argv)
1973 {
1974         struct obd_ioctl_data data;
1975         struct timeval start, next_time;
1976         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1977         __u64 count, next_count, len, stride, thr_offset = 0, objid = 3;
1978         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1979         int offset_pages = 0;
1980         long n;
1981         int repeat_offset = 0;
1982         unsigned long long ull;
1983         int  nthr_per_obj = 0;
1984         int  verify = 1;
1985         int  obj_idx = 0;
1986         char *end;
1987
1988         if (argc < 2 || argc > 7) {
1989                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1990                         jt_cmdname(argv[0]), argc);
1991                 return CMD_HELP;
1992         }
1993
1994         count = strtoull(argv[1], &end, 0);
1995         if (*end) {
1996                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1997                         jt_cmdname(argv[0]), argv[1]);
1998                 return CMD_HELP;
1999         }
2000
2001         if (argc >= 3) {
2002                 if (argv[2][0] == 'w' || argv[2][0] == '1')
2003                         write = 1;
2004                 /* else it's a read */
2005
2006                 if (argv[2][0] != 0)
2007                         for (i = 1; argv[2][i] != 0; i++)
2008                                 switch (argv[2][i]) {
2009                                 case 'r':
2010                                         repeat_offset = 1;
2011                                         break;
2012
2013                                 case 'x':
2014                                         verify = 0;
2015                                         break;
2016
2017                                 default:
2018                                         fprintf (stderr, "Can't parse cmd '%s'\n",
2019                                                  argv[2]);
2020                                         return CMD_HELP;
2021                                 }
2022         }
2023
2024         if (argc >= 4) {
2025                 verbose = get_verbose(argv[0], argv[3]);
2026                 if (verbose == BAD_VERBOSE)
2027                         return CMD_HELP;
2028         }
2029
2030         if (argc >= 5) {
2031                 pages = strtoul(argv[4], &end, 0);
2032
2033                 if (*end == '+')
2034                         offset_pages = strtoul(end + 1, &end, 0);
2035
2036                 if (*end != 0 ||
2037                     offset_pages < 0 || offset_pages >= pages) {
2038                         fprintf(stderr, "error: %s: bad npages[+offset] parameter '%s'\n",
2039                                 jt_cmdname(argv[0]), argv[4]);
2040                         return CMD_HELP;
2041                 }
2042         }
2043
2044         if (argc >= 6) {
2045                 if (thread &&
2046                     (n = strtol(argv[5], &end, 0)) > 0 &&
2047                     *end == 't' &&
2048                     (ull = strtoull(end + 1, &end, 0)) > 0 &&
2049                     *end == 0) {
2050                         nthr_per_obj = n;
2051                         objid = ull;
2052                 } else if (thread &&
2053                            argv[5][0] == 't') {
2054                         nthr_per_obj = 1;
2055                         objid = strtoull(argv[5] + 1, &end, 0);
2056                 } else {
2057                         nthr_per_obj = 0;
2058                         objid = strtoull(argv[5], &end, 0);
2059                 }
2060                 if (*end) {
2061                         fprintf(stderr, "error: %s: bad objid '%s'\n",
2062                                 jt_cmdname(argv[0]), argv[5]);
2063                         return CMD_HELP;
2064                 }
2065         }
2066
2067         memset(&data, 0, sizeof(data));
2068         data.ioc_dev = cur_device;
2069
2070         /* communicate the 'type' of brw test and batching to echo_client.
2071          * don't start.  we'd love to refactor this lctl->echo_client
2072          * interface */
2073         data.ioc_pbuf1 = (void *)1;
2074         data.ioc_plen1 = 1;
2075
2076         if (argc >= 7) {
2077                 switch(argv[6][0]) {
2078                         case 'g': /* plug and unplug */
2079                                 data.ioc_pbuf1 = (void *)2;
2080                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
2081                                                           0);
2082                                 break;
2083                         case 'p': /* prep and commit */
2084                                 data.ioc_pbuf1 = (void *)3;
2085                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
2086                                                           0);
2087                                 break;
2088                         default:
2089                                 fprintf(stderr, "error: %s: batching '%s' "
2090                                         "needs to specify 'p' or 'g'\n",
2091                                         jt_cmdname(argv[0]), argv[6]);
2092                                 return CMD_HELP;
2093                 }
2094
2095                 if (*end) {
2096                         fprintf(stderr, "error: %s: bad batching '%s'\n",
2097                                 jt_cmdname(argv[0]), argv[6]);
2098                         return CMD_HELP;
2099                 }
2100                 data.ioc_plen1 *= getpagesize();
2101         }
2102
2103         len = pages * getpagesize();
2104         thr_offset = offset_pages * getpagesize();
2105         stride = len;
2106
2107 #ifdef MAX_THREADS
2108         if (thread) {
2109                 shmem_lock ();
2110                 if (nthr_per_obj != 0) {
2111                         /* threads interleave */
2112                         obj_idx = (thread - 1)/nthr_per_obj;
2113                         objid += obj_idx;
2114                         stride *= nthr_per_obj;
2115                         if ((thread - 1) % nthr_per_obj == 0) {
2116                                 shared_data->body.offsets[obj_idx] =
2117                                         stride + thr_offset;
2118                         }
2119                         thr_offset += ((thread - 1) % nthr_per_obj) * len;
2120                 } else {
2121                         /* threads disjoint */
2122                         thr_offset += (thread - 1) * len;
2123                 }
2124
2125                 shared_data->body.start_barrier--;
2126                 if (shared_data->body.start_barrier == 0)
2127                         shmem_wakeup_all();
2128                 else
2129                         shmem_wait();
2130
2131                 shmem_unlock ();
2132         }
2133 #endif
2134
2135         data.ioc_obdo1.o_id = objid;
2136         data.ioc_obdo1.o_mode = S_IFREG;
2137         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS;
2138         data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0);
2139         data.ioc_count = len;
2140         data.ioc_offset = (repeat_offset ? 0 : thr_offset);
2141
2142         gettimeofday(&start, NULL);
2143         next_time.tv_sec = start.tv_sec - verbose;
2144         next_time.tv_usec = start.tv_usec;
2145
2146         if (verbose != 0)
2147                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
2148                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
2149                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
2150
2151         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
2152         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
2153                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
2154                 memset(buf, 0, sizeof(rawbuf));
2155                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2156                 if (rc) {
2157                         fprintf(stderr, "error: %s: invalid ioctl\n",
2158                                 jt_cmdname(argv[0]));
2159                         return rc;
2160                 }
2161                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
2162                 shmem_bump(1);
2163                 if (rc) {
2164                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
2165                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
2166                                 write ? "write" : "read");
2167                         break;
2168                 } else if (be_verbose(verbose, &next_time,i, &next_count,count)) {
2169                         shmem_lock ();
2170                         printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n",
2171                                jt_cmdname(argv[0]), write ? "write" : "read", i,
2172                                data.ioc_obdo1.o_id, data.ioc_offset,
2173                                (int)(pages * getpagesize()));
2174                         shmem_unlock ();
2175                 }
2176
2177                 if (!repeat_offset) {
2178 #ifdef MAX_THREADS
2179                         if (stride == len) {
2180                                 data.ioc_offset += stride;
2181                         } else if (i < count) {
2182                                 shmem_lock ();
2183                                 data.ioc_offset =
2184                                         shared_data->body.offsets[obj_idx];
2185                                 shared_data->body.offsets[obj_idx] += len;
2186                                 shmem_unlock ();
2187                         }
2188 #else
2189                         data.ioc_offset += len;
2190                         obj_idx = 0; /* avoids an unused var warning */
2191 #endif
2192                 }
2193         }
2194
2195         if (!rc) {
2196                 struct timeval end;
2197                 double diff;
2198
2199                 gettimeofday(&end, NULL);
2200
2201                 diff = difftime(&end, &start);
2202
2203                 --i;
2204                 if (verbose != 0)
2205                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
2206                                jt_cmdname(argv[0]), write ? "wrote" : "read",
2207                                i, pages, diff,
2208                                ((double)i * pages * getpagesize()) /
2209                                (diff * 1048576.0),
2210                                ctime(&end.tv_sec));
2211         }
2212
2213         return rc;
2214 }
2215
2216 int jt_obd_lov_getconfig(int argc, char **argv)
2217 {
2218         struct obd_ioctl_data data;
2219         struct lov_desc desc;
2220         struct obd_uuid *uuidarray;
2221         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2222         __u32 *obdgens;
2223         char *path;
2224         int rc, fd;
2225
2226         memset(&data, 0, sizeof(data));
2227         data.ioc_dev = cur_device;
2228
2229         if (argc != 2)
2230                 return CMD_HELP;
2231
2232         path = argv[1];
2233         fd = open(path, O_RDONLY);
2234         if (fd < 0) {
2235                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
2236                         strerror(errno));
2237                 return -errno;
2238         }
2239
2240         memset(&desc, 0, sizeof(desc));
2241         obd_str2uuid(&desc.ld_uuid, argv[1]);
2242         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
2243                              (sizeof(*uuidarray) + sizeof(*obdgens)));
2244
2245 repeat:
2246         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
2247         if (!uuidarray) {
2248                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
2249                         jt_cmdname(argv[0]), desc.ld_tgt_count);
2250                 rc = -ENOMEM;
2251                 goto out;
2252         }
2253         obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens));
2254         if (!obdgens) {
2255                 fprintf(stderr, "error: %s: no memory for %d generation #'s\n",
2256                         jt_cmdname(argv[0]), desc.ld_tgt_count);
2257                 rc = -ENOMEM;
2258                 goto out_uuidarray;
2259         }
2260
2261         memset(buf, 0, sizeof(rawbuf));
2262         data.ioc_inllen1 = sizeof(desc);
2263         data.ioc_inlbuf1 = (char *)&desc;
2264         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
2265         data.ioc_inlbuf2 = (char *)uuidarray;
2266         data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens);
2267         data.ioc_inlbuf3 = (char *)obdgens;
2268
2269         if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) {
2270                 fprintf(stderr, "error: %s: invalid ioctl\n",
2271                         jt_cmdname(argv[0]));
2272                 rc = -EINVAL;
2273                 goto out_obdgens;
2274         }
2275         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
2276         if (rc == -ENOSPC) {
2277                 free(uuidarray);
2278                 free(obdgens);
2279                 goto repeat;
2280         } else if (rc) {
2281                 fprintf(stderr, "error: %s: ioctl error: %s\n",
2282                         jt_cmdname(argv[0]), strerror(rc = errno));
2283         } else {
2284                 struct obd_uuid *uuidp;
2285                 __u32 *genp;
2286                 int i;
2287
2288                 if (obd_ioctl_unpack(&data, buf, sizeof(rawbuf))) {
2289                         fprintf(stderr, "error: %s: invalid reply\n",
2290                                 jt_cmdname(argv[0]));
2291                         rc = -EINVAL;
2292                         goto out;
2293                 }
2294                 if (desc.ld_default_stripe_count == (__u32)-1)
2295                         printf("default_stripe_count: %d\n", -1);
2296                 else
2297                         printf("default_stripe_count: %u\n",
2298                                desc.ld_default_stripe_count);
2299                 printf("default_stripe_size: "LPU64"\n",
2300                        desc.ld_default_stripe_size);
2301                 printf("default_stripe_offset: "LPU64"\n",
2302                        desc.ld_default_stripe_offset);
2303                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
2304                 printf("obd_count: %u\n", desc.ld_tgt_count);
2305                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
2306                 uuidp = uuidarray;
2307                 genp = obdgens;
2308                 for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++)
2309                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp);
2310         }
2311 out_obdgens:
2312         free(obdgens);
2313 out_uuidarray:
2314         free(uuidarray);
2315 out:
2316         close(fd);
2317         return rc;
2318 }
2319
2320 int jt_obd_ldlm_regress_start(int argc, char **argv)
2321 {
2322         int rc;
2323         struct obd_ioctl_data data;
2324         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2325         char argstring[200];
2326         int i, count = sizeof(argstring) - 1;
2327
2328         memset(&data, 0, sizeof(data));
2329         data.ioc_dev = cur_device;
2330         if (argc > 5)
2331                 return CMD_HELP;
2332
2333         argstring[0] = '\0';
2334         for (i = 1; i < argc; i++) {
2335                 strncat(argstring, " ", count);
2336                 count--;
2337                 strncat(argstring, argv[i], count);
2338                 count -= strlen(argv[i]);
2339         }
2340
2341         if (strlen(argstring)) {
2342                 data.ioc_inlbuf1 = argstring;
2343                 data.ioc_inllen1 = strlen(argstring) + 1;
2344         }
2345
2346         memset(buf, 0, sizeof(rawbuf));
2347         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2348         if (rc) {
2349                 fprintf(stderr, "error: %s: invalid ioctl\n",
2350                         jt_cmdname(argv[0]));
2351                 return rc;
2352         }
2353         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
2354         if (rc)
2355                 fprintf(stderr, "error: %s: test failed: %s\n",
2356                         jt_cmdname(argv[0]), strerror(rc = errno));
2357
2358         return rc;
2359 }
2360
2361 int jt_obd_ldlm_regress_stop(int argc, char **argv)
2362 {
2363         int rc;
2364         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2365         struct obd_ioctl_data data;
2366
2367         memset(&data, 0, sizeof(data));
2368         data.ioc_dev = cur_device;
2369
2370         if (argc != 1)
2371                 return CMD_HELP;
2372
2373         memset(buf, 0, sizeof(rawbuf));
2374         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2375         if (rc) {
2376                 fprintf(stderr, "error: %s: invalid ioctl\n",
2377                         jt_cmdname(argv[0]));
2378                 return rc;
2379         }
2380         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
2381
2382         if (rc)
2383                 fprintf(stderr, "error: %s: test failed: %s\n",
2384                         jt_cmdname(argv[0]), strerror(rc = errno));
2385         return rc;
2386 }
2387
2388 static int do_activate(int argc, char **argv, int flag)
2389 {
2390         struct obd_ioctl_data data;
2391         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2392         int rc;
2393
2394         memset(&data, 0, sizeof(data));
2395         data.ioc_dev = cur_device;
2396         if (argc != 1)
2397                 return CMD_HELP;
2398
2399         /* reuse offset for 'active' */
2400         data.ioc_offset = flag;
2401
2402         memset(buf, 0, sizeof(rawbuf));
2403         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2404         if (rc) {
2405                 fprintf(stderr, "error: %s: invalid ioctl\n",
2406                         jt_cmdname(argv[0]));
2407                 return rc;
2408         }
2409         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
2410         if (rc)
2411                 fprintf(stderr, "error: %s: failed: %s\n",
2412                         jt_cmdname(argv[0]), strerror(rc = errno));
2413
2414         return rc;
2415 }
2416
2417 int jt_obd_deactivate(int argc, char **argv)
2418 {
2419         return do_activate(argc, argv, 0);
2420 }
2421
2422 int jt_obd_activate(int argc, char **argv)
2423 {
2424         return do_activate(argc, argv, 1);
2425 }
2426
2427 int jt_obd_recover(int argc, char **argv)
2428 {
2429         int rc;
2430         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2431         struct obd_ioctl_data data;
2432
2433         memset(&data, 0, sizeof(data));
2434         data.ioc_dev = cur_device;
2435         if (argc > 2)
2436                 return CMD_HELP;
2437
2438         if (argc == 2) {
2439                 data.ioc_inllen1 = strlen(argv[1]) + 1;
2440                 data.ioc_inlbuf1 = argv[1];
2441         }
2442
2443         memset(buf, 0, sizeof(rawbuf));
2444         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2445         if (rc) {
2446                 fprintf(stderr, "error: %s: invalid ioctl\n",
2447                         jt_cmdname(argv[0]));
2448                 return rc;
2449         }
2450         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
2451         if (rc < 0) {
2452                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
2453                         strerror(rc = errno));
2454         }
2455
2456         return rc;
2457 }
2458
2459 int jt_obd_mdc_lookup(int argc, char **argv)
2460 {
2461         struct obd_ioctl_data data;
2462         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2463         char *parent, *child;
2464         int rc, fd, verbose = 1;
2465
2466         if (argc < 3 || argc > 4)
2467                 return CMD_HELP;
2468
2469         parent = argv[1];
2470         child = argv[2];
2471         if (argc == 4)
2472                 verbose = get_verbose(argv[0], argv[3]);
2473
2474         memset(&data, 0, sizeof(data));
2475         data.ioc_dev = cur_device;
2476
2477         data.ioc_inllen1 = strlen(child) + 1;
2478         data.ioc_inlbuf1 = child;
2479
2480         memset(buf, 0, sizeof(rawbuf));
2481         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2482         if (rc) {
2483                 fprintf(stderr, "error: %s: invalid ioctl\n",
2484                         jt_cmdname(argv[0]));
2485                 return rc;
2486         }
2487
2488         fd = open(parent, O_RDONLY);
2489         if (fd < 0) {
2490                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
2491                         strerror(errno));
2492                 return -1;
2493         }
2494
2495         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
2496         if (rc < 0) {
2497                 fprintf(stderr, "error: %s: ioctl error: %s\n",
2498                         jt_cmdname(argv[0]), strerror(rc = errno));
2499         }
2500         close(fd);
2501
2502         if (verbose) {
2503                 rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
2504                 if (rc) {
2505                         fprintf(stderr, "error: %s: invalid reply\n",
2506                                 jt_cmdname(argv[0]));
2507                         return rc;
2508                 }
2509                 printf("%s: mode %o uid %d gid %d\n", child,
2510                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
2511                        data.ioc_obdo1.o_gid);
2512         }
2513
2514         return rc;
2515 }
2516
2517 int jt_cfg_dump_log(int argc, char **argv)
2518 {
2519         struct obd_ioctl_data data;
2520         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2521         int rc;
2522
2523         if (argc != 2)
2524                 return CMD_HELP;
2525
2526         memset(&data, 0, sizeof(data));
2527         data.ioc_dev = cur_device;
2528         data.ioc_inllen1 = strlen(argv[1]) + 1;
2529         data.ioc_inlbuf1 = argv[1];
2530
2531         memset(buf, 0, sizeof(rawbuf));
2532         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2533         if (rc) {
2534                 fprintf(stderr, "error: %s: invalid ioctl\n",
2535                         jt_cmdname(argv[0]));
2536                 return rc;
2537         }
2538         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
2539         if (rc < 0)
2540                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
2541                         strerror(errno));
2542
2543         return rc;
2544 }
2545
2546 int jt_llog_catlist(int argc, char **argv)
2547 {
2548         struct obd_ioctl_data data;
2549         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2550         int rc;
2551
2552         if (argc != 1)
2553                 return CMD_HELP;
2554
2555         memset(&data, 0, sizeof(data));
2556         data.ioc_dev = cur_device;
2557         data.ioc_inllen1 = sizeof(rawbuf) - cfs_size_round(sizeof(data));
2558         memset(buf, 0, sizeof(rawbuf));
2559         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2560         if (rc) {
2561                 fprintf(stderr, "error: %s: invalid ioctl\n",
2562                         jt_cmdname(argv[0]));
2563                 return rc;
2564         }
2565         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
2566         if (rc == 0)
2567                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2568         else
2569                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n",
2570                         strerror(errno));
2571
2572         return rc;
2573 }
2574
2575 int jt_llog_info(int argc, char **argv)
2576 {
2577         struct obd_ioctl_data data;
2578         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2579         int rc;
2580
2581         if (argc != 2)
2582                 return CMD_HELP;
2583
2584         memset(&data, 0, sizeof(data));
2585         data.ioc_dev = cur_device;
2586         data.ioc_inllen1 = strlen(argv[1]) + 1;
2587         data.ioc_inlbuf1 = argv[1];
2588         data.ioc_inllen2 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
2589                 cfs_size_round(data.ioc_inllen1);
2590         memset(buf, 0, sizeof(rawbuf));
2591         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2592         if (rc) {
2593                 fprintf(stderr, "error: %s: invalid ioctl\n",
2594                         jt_cmdname(argv[0]));
2595                 return rc;
2596         }
2597
2598         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
2599         if (rc == 0)
2600                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2601         else
2602                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
2603                         strerror(errno));
2604
2605         return rc;
2606 }
2607
2608 int jt_llog_print(int argc, char **argv)
2609 {
2610         struct obd_ioctl_data data;
2611         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2612         int rc;
2613
2614         if (argc != 2 && argc != 4)
2615                 return CMD_HELP;
2616
2617         memset(&data, 0, sizeof(data));
2618         data.ioc_dev = cur_device;
2619         data.ioc_inllen1 = strlen(argv[1]) + 1;
2620         data.ioc_inlbuf1 = argv[1];
2621         if (argc == 4) {
2622                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2623                 data.ioc_inlbuf2 = argv[2];
2624                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2625                 data.ioc_inlbuf3 = argv[3];
2626         } else {
2627                 char from[2] = "1", to[3] = "-1";
2628                 data.ioc_inllen2 = strlen(from) + 1;
2629                 data.ioc_inlbuf2 = from;
2630                 data.ioc_inllen3 = strlen(to) + 1;
2631                 data.ioc_inlbuf3 = to;
2632         }
2633         data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
2634                 cfs_size_round(data.ioc_inllen1) -
2635                 cfs_size_round(data.ioc_inllen2) -
2636                 cfs_size_round(data.ioc_inllen3);
2637         memset(buf, 0, sizeof(rawbuf));
2638         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2639         if (rc) {
2640                 fprintf(stderr, "error: %s: invalid ioctl\n",
2641                         jt_cmdname(argv[0]));
2642                 return rc;
2643         }
2644
2645         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
2646         if (rc == 0)
2647                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2648         else
2649                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
2650                         strerror(errno));
2651
2652         return rc;
2653 }
2654
2655 int jt_llog_cancel(int argc, char **argv)
2656 {
2657         struct obd_ioctl_data data;
2658         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2659         int rc;
2660
2661         if (argc != 4)
2662                 return CMD_HELP;
2663
2664         memset(&data, 0, sizeof(data));
2665         data.ioc_dev = cur_device;
2666         data.ioc_inllen1 = strlen(argv[1]) + 1;
2667         data.ioc_inlbuf1 = argv[1];
2668         data.ioc_inllen2 = strlen(argv[2]) + 1;
2669         data.ioc_inlbuf2 = argv[2];
2670         data.ioc_inllen3 = strlen(argv[3]) + 1;
2671         data.ioc_inlbuf3 = argv[3];
2672         memset(buf, 0, sizeof(rawbuf));
2673         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2674         if (rc) {
2675                 fprintf(stderr, "error: %s: invalid ioctl\n",
2676                         jt_cmdname(argv[0]));
2677                 return rc;
2678         }
2679
2680         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
2681         if (rc == 0)
2682                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
2683         else
2684                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
2685                         strerror(errno));
2686
2687         return rc;
2688
2689 }
2690 int jt_llog_check(int argc, char **argv)
2691 {
2692         struct obd_ioctl_data data;
2693         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2694         int rc;
2695
2696         if (argc != 2 && argc != 4)
2697                 return CMD_HELP;
2698
2699         memset(&data, 0, sizeof(data));
2700         data.ioc_dev = cur_device;
2701         data.ioc_inllen1 = strlen(argv[1]) + 1;
2702         data.ioc_inlbuf1 = argv[1];
2703         if (argc == 4) {
2704                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2705                 data.ioc_inlbuf2 = argv[2];
2706                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2707                 data.ioc_inlbuf3 = argv[3];
2708         } else {
2709                 char from[2] = "1", to[3] = "-1";
2710                 data.ioc_inllen2 = strlen(from) + 1;
2711                 data.ioc_inlbuf2 = from;
2712                 data.ioc_inllen3 = strlen(to) + 1;
2713                 data.ioc_inlbuf3 = to;
2714         }
2715         data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) -
2716                 cfs_size_round(data.ioc_inllen1) -
2717                 cfs_size_round(data.ioc_inllen2) -
2718                 cfs_size_round(data.ioc_inllen3);
2719         memset(buf, 0, sizeof(rawbuf));
2720         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2721         if (rc) {
2722                 fprintf(stderr, "error: %s: invalid ioctl\n",
2723                         jt_cmdname(argv[0]));
2724                 return rc;
2725         }
2726
2727         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
2728         if (rc == 0)
2729                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2730         else
2731                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
2732                         strerror(errno));
2733         return rc;
2734 }
2735
2736 int jt_llog_remove(int argc, char **argv)
2737 {
2738         struct obd_ioctl_data data;
2739         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2740         int rc;
2741
2742         if (argc != 3 && argc != 2)
2743                 return CMD_HELP;
2744
2745         memset(&data, 0, sizeof(data));
2746         data.ioc_dev = cur_device;
2747         data.ioc_inllen1 = strlen(argv[1]) + 1;
2748         data.ioc_inlbuf1 = argv[1];
2749         if (argc == 3){
2750                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2751                 data.ioc_inlbuf2 = argv[2];
2752         }
2753         memset(buf, 0, sizeof(rawbuf));
2754         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2755         if (rc) {
2756                 fprintf(stderr, "error: %s: invalid ioctl\n",
2757                         jt_cmdname(argv[0]));
2758                 return rc;
2759         }
2760
2761         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
2762         if (rc == 0) {
2763                 if (argc == 3)
2764                         fprintf(stdout, "log %s are removed.\n", argv[2]);
2765                 else
2766                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
2767         } else
2768                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
2769                         strerror(errno));
2770
2771         return rc;
2772 }
2773
2774 /* attach a regular file to virtual block device.
2775  * return vaule:
2776  *  -1: fatal error
2777  *  1: error, it always means the command run failed
2778  *  0: success
2779  */
2780 static int jt_blockdev_run_process(const char *file, char *argv[])
2781 {
2782         pid_t pid;
2783         int rc;
2784
2785         pid = vfork();
2786         if (pid == 0) { /* child process */
2787                 /* don't print error messages */
2788                 close(1), close(2);
2789                 (void)execvp(file, argv);
2790                 exit(-1);
2791         } else if (pid > 0) {
2792                 int status;
2793
2794                 rc = waitpid(pid, &status, 0);
2795                 if (rc < 0 || !WIFEXITED(status))
2796                         return -1;
2797
2798                 return WEXITSTATUS(status);
2799         }
2800
2801         return -1;
2802 }
2803
2804 static int jt_blockdev_find_module(const char *module)
2805 {
2806         FILE *fp;
2807         int found = 0;
2808         char buf[1024];
2809
2810         fp = fopen("/proc/modules", "r");
2811         if (fp == NULL)
2812                 return -1;
2813
2814         while (fgets(buf, 1024, fp) != NULL) {
2815                 *strchr(buf, ' ') = 0;
2816                 if (strcmp(module, buf) == 0) {
2817                         found = 1;
2818                         break;
2819                 }
2820         }
2821         fclose(fp);
2822
2823         return found;
2824 }
2825
2826 static int jt_blockdev_probe_module(const char *module)
2827 {
2828         char buf[1024];
2829         char *argv[10];
2830         int c, rc;
2831
2832         if (jt_blockdev_find_module(module) == 1)
2833                 return 0;
2834
2835         /* run modprobe first */
2836         c = 0;
2837         argv[c++] = "/sbin/modprobe";
2838         argv[c++] = "-q";
2839         argv[c++] = (char *)module;
2840         argv[c++] = NULL;
2841         rc = jt_blockdev_run_process("modprobe", argv);
2842         if (rc != 1)
2843                 return rc;
2844
2845         /* cannot find the module in default directory ... */
2846         sprintf(buf, "../llite/%s.ko", module);
2847         c = 0;
2848         argv[c++] = "/sbin/insmod";
2849         argv[c++] = buf;
2850         argv[c++] = NULL;
2851         rc = jt_blockdev_run_process("insmod", argv);
2852         return rc ? -1 : 0;
2853 }
2854
2855 int jt_blockdev_attach(int argc, char **argv)
2856 {
2857         int rc, fd;
2858         struct stat st;
2859         char *filename, *devname;
2860         unsigned long dev;
2861
2862         if (argc != 3)
2863                 return CMD_HELP;
2864
2865         if (jt_blockdev_probe_module("llite_lloop") < 0) {
2866                 fprintf(stderr, "error: cannot find module llite_lloop.(k)o\n");
2867                 return ENOENT;
2868         }
2869
2870         filename = argv[1];
2871         devname = argv[2];
2872
2873         fd = open(filename, O_RDWR);
2874         if (fd < 0) {
2875                 fprintf(stderr, "file %s can't be opened(%s)\n\n",
2876                         filename, strerror(errno));
2877                 return CMD_HELP;
2878         }
2879
2880         rc = ioctl(fd, LL_IOC_LLOOP_ATTACH, &dev);
2881         if (rc < 0) {
2882                 rc = errno;
2883                 fprintf(stderr, "attach error(%s)\n", strerror(rc));
2884                 goto out;
2885         }
2886
2887         rc = stat(devname, &st);
2888         if (rc == 0 && (!S_ISBLK(st.st_mode) || st.st_rdev != dev)) {
2889                 rc = EEXIST;
2890         } else if (rc < 0) {
2891                 if (errno == ENOENT &&
2892                     !mknod(devname, S_IFBLK|S_IRUSR|S_IWUSR, dev))
2893                         rc = 0;
2894                 else
2895                         rc = errno;
2896         }
2897
2898         if (rc) {
2899                 fprintf(stderr, "error: the file %s could be attached to block "
2900                                 "device %X but creating %s failed: %s\n"
2901                                 "now detaching the block device..",
2902                         filename, (int)dev, devname, strerror(rc));
2903
2904                 (void)ioctl(fd, LL_IOC_LLOOP_DETACH_BYDEV, dev);
2905                 fprintf(stderr, "%s\n", strerror(errno));
2906         }
2907 out:
2908         close(fd);
2909         return -rc;
2910 }
2911
2912 int jt_blockdev_detach(int argc, char **argv)
2913 {
2914         char *filename;
2915         int rc, fd;
2916
2917         if (argc != 2)
2918                 return CMD_HELP;
2919
2920         filename = argv[1];
2921         fd = open(filename, O_RDONLY);
2922         if (fd < 0) {
2923                 fprintf(stderr, "cannot open file %s error %s\n",
2924                         filename, strerror(errno));
2925                 return CMD_HELP;
2926         }
2927
2928         rc = ioctl(fd, LL_IOC_LLOOP_DETACH, 0);
2929         if (rc < 0) {
2930                 rc = errno;
2931                 fprintf(stderr, "detach error(%s)\n", strerror(rc));
2932         } else {
2933                 (void)unlink(filename);
2934         }
2935
2936         close(fd);
2937         return -rc;
2938 }
2939
2940 int jt_blockdev_info(int argc, char **argv)
2941 {
2942         char *filename;
2943         int rc, fd;
2944         struct lu_fid fid;
2945
2946         if (argc != 2)
2947                 return CMD_HELP;
2948
2949         filename = argv[1];
2950         fd = open(filename, O_RDONLY);
2951         if (fd < 0) {
2952                 fprintf(stderr, "cannot open file %s error: %s\n",
2953                         filename, strerror(errno));
2954                 return CMD_HELP;
2955         }
2956
2957         rc = ioctl(fd, LL_IOC_LLOOP_INFO, &fid);
2958         if (rc < 0) {
2959                 rc = errno;
2960                 fprintf(stderr, "error: %s\n", strerror(errno));
2961                 goto out;
2962         }
2963         fprintf(stdout, "lloop device info: ");
2964         if (fid_is_zero(&fid))
2965                 fprintf(stdout, "Not attached\n");
2966         else
2967                 fprintf(stdout, "attached to inode "DFID"\n", PFID(&fid));
2968 out:
2969         close(fd);
2970         return -rc;
2971 }
2972
2973 static void signal_server(int sig)
2974 {
2975         if (sig == SIGINT) {
2976                 do_disconnect("sigint", 1);
2977                 exit(1);
2978         } else
2979                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2980 }
2981
2982 int obd_initialize(int argc, char **argv)
2983 {
2984         int i;
2985
2986         for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++)
2987                 lsm_buffer.lsm.lsm_oinfo[i] = lov_oinfos + i;
2988
2989         if (shmem_setup() != 0)
2990                 return -1;
2991
2992         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH,
2993                          OBD_DEV_MAJOR, OBD_DEV_MINOR);
2994
2995         return 0;
2996 }
2997
2998 void obd_finalize(int argc, char **argv)
2999 {
3000         struct sigaction sigact;
3001
3002         sigact.sa_handler = signal_server;
3003         sigfillset(&sigact.sa_mask);
3004         sigact.sa_flags = SA_RESTART;
3005         sigaction(SIGINT, &sigact, NULL);
3006
3007         shmem_cleanup();
3008         do_disconnect(argv[0], 1);
3009 }
3010
3011 static int check_pool_cmd(enum lcfg_command_type cmd,
3012                           char *fsname, char *poolname,
3013                           char *ostname)
3014 {
3015         int rc;
3016
3017         rc = llapi_search_ost(fsname, poolname, ostname);
3018         if (rc < 0 && (cmd != LCFG_POOL_NEW)) {
3019                 fprintf(stderr, "Pool %s.%s not found\n",
3020                         fsname, poolname);
3021                 return rc;
3022         }
3023
3024         switch (cmd) {
3025         case LCFG_POOL_NEW: {
3026                 LASSERT(ostname == NULL);
3027                 if (rc >= 0) {
3028                         fprintf(stderr, "Pool %s.%s already exists\n",
3029                                 fsname, poolname);
3030                         return -EEXIST;
3031                 }
3032                 return 0;
3033         }
3034         case LCFG_POOL_DEL: {
3035                 LASSERT(ostname == NULL);
3036                 if (rc == 1) {
3037                         fprintf(stderr, "Pool %s.%s not empty, "
3038                                 "please remove all members\n",
3039                                 fsname, poolname);
3040                         return -ENOTEMPTY;
3041                 }
3042                 return 0;
3043         }
3044         case LCFG_POOL_ADD: {
3045                 if (rc == 1) {
3046                         fprintf(stderr, "OST %s is already in pool %s.%s\n",
3047                                 ostname, fsname, poolname);
3048                         return -EEXIST;
3049                 }
3050                 rc = llapi_search_ost(fsname, NULL, ostname);
3051                 if (rc == 0) {
3052                         fprintf(stderr, "OST %s is not part of the '%s' fs.\n",
3053                                 ostname, fsname);
3054                         return -ENOENT;
3055                 }
3056                 return 0;
3057         }
3058         case LCFG_POOL_REM: {
3059                 if (rc == 0) {
3060                         fprintf(stderr, "OST %s not found in pool %s.%s\n",
3061                                 ostname, fsname, poolname);
3062                         return -ENOENT;
3063                 }
3064                 return 0;
3065         }
3066         default:
3067                 break;
3068         } /* switch */
3069         return -EINVAL;
3070 }
3071
3072 /* This check only verifies that the changes have been "pushed out" to
3073    the client successfully.  This involves waiting for a config update,
3074    and so may fail because of problems in that code or post-command
3075    network loss. So reporting a warning is appropriate, but not a failure.
3076 */
3077 static int check_pool_cmd_result(enum lcfg_command_type cmd,
3078                                  char *fsname, char *poolname,
3079                                  char *ostname)
3080 {
3081         int cpt = 10;
3082         int rc = 0;
3083
3084         switch (cmd) {
3085         case LCFG_POOL_NEW: {
3086                 do {
3087                         rc = llapi_search_ost(fsname, poolname, NULL);
3088                         if (rc == -ENODEV)
3089                                 return rc;
3090                         if (rc < 0)
3091                                 sleep(2);
3092                         cpt--;
3093                 } while ((rc < 0) && (cpt > 0));
3094                 if (rc >= 0) {
3095                         fprintf(stderr, "Pool %s.%s created\n",
3096                                 fsname, poolname);
3097                         return 0;
3098                 } else {
3099                         fprintf(stderr, "Warning, pool %s.%s not found\n",
3100                                 fsname, poolname);
3101                         return -ENOENT;
3102                 }
3103         }
3104         case LCFG_POOL_DEL: {
3105                 do {
3106                         rc = llapi_search_ost(fsname, poolname, NULL);
3107                         if (rc == -ENODEV)
3108                                 return rc;
3109                         if (rc >= 0)
3110                                 sleep(2);
3111                         cpt--;
3112                 } while ((rc >= 0) && (cpt > 0));
3113                 if (rc < 0) {
3114                         fprintf(stderr, "Pool %s.%s destroyed\n",
3115                                 fsname, poolname);
3116                         return 0;
3117                 } else {
3118                         fprintf(stderr, "Warning, pool %s.%s still found\n",
3119                                 fsname, poolname);
3120                         return -EEXIST;
3121                 }
3122         }
3123         case LCFG_POOL_ADD: {
3124                 do {
3125                         rc = llapi_search_ost(fsname, poolname, ostname);
3126                         if (rc == -ENODEV)
3127                                 return rc;
3128                         if (rc != 1)
3129                                 sleep(2);
3130                         cpt--;
3131                 } while ((rc != 1) && (cpt > 0));
3132                 if (rc == 1) {
3133                         fprintf(stderr, "OST %s added to pool %s.%s\n",
3134                                 ostname, fsname, poolname);
3135                         return 0;
3136                 } else {
3137                         fprintf(stderr, "Warning, OST %s not found in pool %s.%s\n",
3138                                 ostname, fsname, poolname);
3139                         return -ENOENT;
3140                 }
3141         }
3142         case LCFG_POOL_REM: {
3143                 do {
3144                         rc = llapi_search_ost(fsname, poolname, ostname);
3145                         if (rc == -ENODEV)
3146                                 return rc;
3147                         if (rc == 1)
3148                                 sleep(2);
3149                         cpt--;
3150                 } while ((rc == 1) && (cpt > 0));
3151                 if (rc != 1) {
3152                         fprintf(stderr, "OST %s removed from pool %s.%s\n",
3153                                 ostname, fsname, poolname);
3154                         return 0;
3155                 } else {
3156                         fprintf(stderr, "Warning, OST %s still found in pool %s.%s\n",
3157                                 ostname, fsname, poolname);
3158                         return -EEXIST;
3159                 }
3160         }
3161         default:
3162                 break;
3163         }
3164         return -EINVAL;
3165 }
3166
3167 static int check_and_complete_ostname(char *fsname, char *ostname)
3168 {
3169         char *ptr;
3170         char real_ostname[MAX_OBD_NAME + 1];
3171         char i;
3172
3173         /* if OST name does not start with fsname, we add it */
3174         /* if not check if the fsname is the right one */
3175         ptr = strchr(ostname, '-');
3176         if (ptr == NULL) {
3177                 sprintf(real_ostname, "%s-%s", fsname, ostname);
3178         } else if (strncmp(ostname, fsname, strlen(fsname)) != 0) {
3179                 fprintf(stderr, "%s does not start with fsname %s\n",
3180                         ostname, fsname);
3181                 return -EINVAL;
3182         } else {
3183              strcpy(real_ostname, ostname);
3184         }
3185         /* real_ostname is fsname-????? */
3186         ptr = real_ostname + strlen(fsname) + 1;
3187         if (strncmp(ptr, "OST", 3) != 0) {
3188                 fprintf(stderr, "%s does not start by %s-OST nor OST\n",
3189                         ostname, fsname);
3190                 return -EINVAL;
3191         }
3192         /* real_ostname is fsname-OST????? */
3193         ptr += 3;
3194         for (i = 0; i < 4; i++) {
3195                 if (!isxdigit(*ptr)) {
3196                         fprintf(stderr,
3197                                 "ost's index in %s is not an hexa number\n",
3198                                 ostname);
3199                         return -EINVAL;
3200                 }
3201                 ptr++;
3202         }
3203         /* real_ostname is fsname-OSTXXXX????? */
3204         /* if OST name does not end with _UUID, we add it */
3205         if (*ptr == '\0') {
3206                 strcat(real_ostname, "_UUID");
3207         } else if (strcmp(ptr, "_UUID") != 0) {
3208                 fprintf(stderr,
3209                         "ostname %s does not end with _UUID\n", ostname);
3210                 return -EINVAL;
3211         }
3212         /* real_ostname is fsname-OSTXXXX_UUID */
3213         strcpy(ostname, real_ostname);
3214         return 0;
3215 }
3216
3217 /* returns 0 or -errno */
3218 static int pool_cmd(enum lcfg_command_type cmd,
3219                     char *cmdname, char *fullpoolname,
3220                     char *fsname, char *poolname, char *ostname)
3221 {
3222         int rc = 0;
3223         struct obd_ioctl_data data;
3224         struct lustre_cfg_bufs bufs;
3225         struct lustre_cfg *lcfg;
3226         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
3227
3228         rc = check_pool_cmd(cmd, fsname, poolname, ostname);
3229         if (rc == -ENODEV)
3230                 fprintf(stderr, "Can't verify pool command since there "
3231                         "is no local MDT or client, proceeding anyhow...\n");
3232         else if (rc)
3233                 return rc;
3234
3235         lustre_cfg_bufs_reset(&bufs, NULL);
3236         lustre_cfg_bufs_set_string(&bufs, 0, cmdname);
3237         lustre_cfg_bufs_set_string(&bufs, 1, fullpoolname);
3238         if (ostname != NULL)
3239                 lustre_cfg_bufs_set_string(&bufs, 2, ostname);
3240
3241         lcfg = lustre_cfg_new(cmd, &bufs);
3242         if (IS_ERR(lcfg)) {
3243                 rc = PTR_ERR(lcfg);
3244                 return rc;
3245         }
3246
3247         memset(&data, 0, sizeof(data));
3248         rc = data.ioc_dev = get_mgs_device();
3249         if (rc < 0)
3250                 goto out;
3251
3252         data.ioc_type = LUSTRE_CFG_TYPE;
3253         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
3254                                         lcfg->lcfg_buflens);
3255         data.ioc_pbuf1 = (void *)lcfg;
3256
3257         memset(buf, 0, sizeof(rawbuf));
3258         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
3259         if (rc) {
3260                 fprintf(stderr, "error: %s: invalid ioctl\n",
3261                         jt_cmdname(cmdname));
3262                 return rc;
3263         }
3264         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_POOL, buf);
3265 out:
3266         if (rc)
3267                 rc = -errno;
3268         lustre_cfg_free(lcfg);
3269         return rc;
3270 }
3271
3272 /*
3273  * this function tranforms a rule [start-end/step] into an array
3274  * of matching numbers
3275  * supported forms are:
3276  * [start]                : just this number
3277  * [start-end]            : all numbers from start to end
3278  * [start-end/step]       : numbers from start to end with increment of step
3279  * on return, format contains a printf format string which can be used
3280  * to generate all the strings
3281  */
3282 static int get_array_idx(char *rule, char *format, int **array)
3283 {
3284         char *start, *end, *ptr;
3285         unsigned int lo, hi, step;
3286         int array_sz = 0;
3287         int i, array_idx;
3288         int rc;
3289
3290         start = strchr(rule, '[');
3291         end = strchr(rule, ']');
3292         if ((start == NULL) || (end == NULL)) {
3293                 *array = malloc(sizeof(int));
3294                 if (*array == NULL)
3295                         return 0;
3296                 strcpy(format, rule);
3297                 array_sz = 1;
3298                 return array_sz;
3299         }
3300         *start = '\0';
3301         *end = '\0';
3302         end++;
3303         start++;
3304         /* put in format the printf format (the rule without the range) */
3305         sprintf(format, "%s%%.4x%s", rule, end);
3306
3307         array_idx = 0;
3308         array_sz = 0;
3309         *array = NULL;
3310         /* loop on , separator */
3311         do {
3312        &n