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