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