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