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