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