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