Whamcloud - gitweb
LU-1520 ldlm: improve ldlm_pools_shrink algorithm
[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];
914         char *version;
915
916         if (argc != 1)
917                 return CMD_HELP;
918
919         rc = llapi_get_version(rawbuf, MAX_IOC_BUFLEN, &version);
920         if (rc)
921                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
922                         strerror(-rc));
923         else {
924                 printf("Lustre version: %s\n", version);
925         }
926
927         printf("lctl   version: %s\n", BUILD_VERSION);
928         return rc;
929 }
930
931 /*
932  * Print an obd device line with the ost_conn_uuid inserted, if the obd
933  * is an osc.
934  */
935 static void print_obd_line(char *s)
936 {
937         char buf[MAX_STRING_SIZE];
938         char obd_name[MAX_OBD_NAME];
939         FILE *fp = NULL;
940         char *ptr;
941
942         if (sscanf(s, " %*d %*s osc %s %*s %*d ", obd_name) == 0)
943                 goto try_mdc;
944         snprintf(buf, sizeof(buf),
945                  "/proc/fs/lustre/osc/%s/ost_conn_uuid", obd_name);
946         if ((fp = fopen(buf, "r")) == NULL)
947                 goto try_mdc;
948         goto got_one;
949
950 try_mdc:
951         if (sscanf(s, " %*d %*s mdc %s %*s %*d ", obd_name) == 0)
952                 goto fail;
953         snprintf(buf, sizeof(buf),
954                  "/proc/fs/lustre/mdc/%s/mds_conn_uuid", obd_name);
955         if ((fp = fopen(buf, "r")) == NULL)
956                 goto fail;
957
958 got_one:
959         /* should not ignore fgets(3)'s return value */
960         if (!fgets(buf, sizeof(buf), fp)) {
961                 fprintf(stderr, "reading from %s: %s", buf, strerror(errno));
962                 fclose(fp);
963                 return;
964         }
965         fclose(fp);
966
967         /* trim trailing newlines */
968         ptr = strrchr(buf, '\n');
969         if (ptr) *ptr = '\0';
970         ptr = strrchr(s, '\n');
971         if (ptr) *ptr = '\0';
972
973         printf("%s %s\n", s, buf);
974         return;
975
976 fail:
977         printf("%s", s);
978         return;
979 }
980
981 /* get device list by ioctl */
982 int jt_obd_list_ioctl(int argc, char **argv)
983 {
984         int rc, index;
985         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
986         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
987
988         if (argc > 2)
989                 return CMD_HELP;
990         /* Just ignore a -t option.  Only supported with /proc. */
991         else if (argc == 2 && strcmp(argv[1], "-t") != 0)
992                 return CMD_HELP;
993
994         for (index = 0;; index++) {
995                 memset(buf, 0, sizeof(rawbuf));
996                 data->ioc_version = OBD_IOCTL_VERSION;
997                 data->ioc_inllen1 = sizeof(rawbuf) - size_round(sizeof(*data));
998                 data->ioc_inlbuf1 = buf + size_round(sizeof(*data));
999                 data->ioc_len = obd_ioctl_packlen(data);
1000                 data->ioc_count = index;
1001
1002                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETDEVICE, buf);
1003                 if (rc != 0)
1004                         break;
1005                 printf("%s\n", (char *)data->ioc_bulk);
1006         }
1007         if (rc != 0) {
1008                 if (errno == ENOENT)
1009                         /* no device or the last device */
1010                         rc = 0;
1011                 else
1012                         fprintf(stderr, "Error getting device list: %s: "
1013                                 "check dmesg.\n", strerror(errno));
1014         }
1015         return rc;
1016 }
1017
1018 int jt_obd_list(int argc, char **argv)
1019 {
1020         int rc;
1021         char buf[MAX_STRING_SIZE];
1022         FILE *fp = NULL;
1023         int print_obd = 0;
1024
1025         if (argc > 2)
1026                 return CMD_HELP;
1027         else if (argc == 2) {
1028                 if (strcmp(argv[1], "-t") == 0)
1029                         print_obd = 1;
1030                 else
1031                         return CMD_HELP;
1032         }
1033
1034         fp = fopen(DEVICES_LIST, "r");
1035         if (fp == NULL) {
1036                 fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
1037                         jt_cmdname(argv[0]), strerror(rc =  errno));
1038                 return jt_obd_list_ioctl(argc, argv);
1039         }
1040
1041         while (fgets(buf, sizeof(buf), fp) != NULL)
1042                 if (print_obd)
1043                         print_obd_line(buf);
1044                 else
1045                         printf("%s", buf);
1046
1047         fclose(fp);
1048         return 0;
1049 }
1050
1051 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1052  * not, defaults assumed.  This echo-client instance stashes the stripe
1053  * object ids.  Use get_stripe on this node to print full lsm and
1054  * set_stripe on another node to cut/paste between nodes.
1055  */
1056 /* create <count> [<file_create_mode>] [q|v|# verbosity] [striping] */
1057 int jt_obd_create(int argc, char **argv)
1058 {
1059         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1060         struct obd_ioctl_data data;
1061         struct timeval next_time;
1062         __u64 count = 1, next_count, base_id = 0;
1063         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
1064         char *end;
1065
1066         memset(&data, 0x00, sizeof(data));
1067         data.ioc_dev = cur_device;
1068         if (argc < 2 || argc > 5)
1069                 return CMD_HELP;
1070
1071         count = strtoull(argv[1], &end, 0);
1072         if (*end) {
1073                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1074                         jt_cmdname(argv[0]), argv[1]);
1075                 return CMD_HELP;
1076         }
1077
1078         if (argc > 2) {
1079                 mode = strtoul(argv[2], &end, 0);
1080                 if (*end) {
1081                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1082                                 jt_cmdname(argv[0]), argv[2]);
1083                         return CMD_HELP;
1084                 }
1085                 if (!(mode & S_IFMT))
1086                         mode |= S_IFREG;
1087         }
1088
1089         if (argc > 3) {
1090                 verbose = get_verbose(argv[0], argv[3]);
1091                 if (verbose == BAD_VERBOSE)
1092                         return CMD_HELP;
1093         }
1094
1095         if (argc < 5)
1096                 reset_lsmb (&lsm_buffer);       /* will set default */
1097         else {
1098                 rc = parse_lsm (&lsm_buffer, argv[4]);
1099                 if (rc != 0) {
1100                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1101                                 jt_cmdname(argv[0]), argv[4]);
1102                         return CMD_HELP;
1103                 }
1104                 base_id = lsm_buffer.lsm.lsm_object_id;
1105                 valid_lsm = 1;
1106         }
1107
1108         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1109         gettimeofday(&next_time, NULL);
1110         next_time.tv_sec -= verbose;
1111
1112         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1113                 data.ioc_obdo1.o_mode = mode;
1114                 data.ioc_obdo1.o_id = base_id;
1115                 data.ioc_obdo1.o_uid = 0;
1116                 data.ioc_obdo1.o_gid = 0;
1117                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1118                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1119
1120                 if (valid_lsm) {
1121                         data.ioc_plen1 = sizeof lsm_buffer;
1122                         data.ioc_pbuf1 = (char *)&lsm_buffer;
1123                 }
1124
1125                 memset(buf, 0, sizeof(rawbuf));
1126                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1127                 if (rc) {
1128                         fprintf(stderr, "error: %s: invalid ioctl\n",
1129                                 jt_cmdname(argv[0]));
1130                         return rc;
1131                 }
1132                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1133                 obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1134                 shmem_bump();
1135                 if (rc < 0) {
1136                         fprintf(stderr, "error: %s: #%d - %s\n",
1137                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1138                         break;
1139                 }
1140                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1141                         fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n",
1142                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1143                         rc = EINVAL;
1144                         break;
1145                 }
1146
1147                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1148                         printf("%s: #%d is object id "LPX64"\n",
1149                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1150         }
1151         return rc;
1152 }
1153
1154 int jt_obd_setattr(int argc, char **argv)
1155 {
1156         struct obd_ioctl_data data;
1157         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1158         char *end;
1159         int rc;
1160
1161         memset(&data, 0x00, sizeof(data));
1162         data.ioc_dev = cur_device;
1163         if (argc != 2)
1164                 return CMD_HELP;
1165
1166         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1167         if (*end) {
1168                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1169                         jt_cmdname(argv[0]), argv[1]);
1170                 return CMD_HELP;
1171         }
1172         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1173         if (*end) {
1174                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1175                         jt_cmdname(argv[0]), argv[2]);
1176                 return CMD_HELP;
1177         }
1178         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1179
1180         memset(buf, 0, sizeof(rawbuf));
1181         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1182         if (rc) {
1183                 fprintf(stderr, "error: %s: invalid ioctl\n",
1184                         jt_cmdname(argv[0]));
1185                 return rc;
1186         }
1187         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1188         if (rc < 0)
1189                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1190                         strerror(rc = errno));
1191
1192         return rc;
1193 }
1194
1195 int jt_obd_test_setattr(int argc, char **argv)
1196 {
1197         struct obd_ioctl_data data;
1198         struct timeval start, next_time;
1199         __u64 i, count, next_count;
1200         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1201         int verbose = 1;
1202         obd_id objid = 3;
1203         char *end;
1204         int rc = 0;
1205
1206         if (argc < 2 || argc > 4)
1207                 return CMD_HELP;
1208
1209         memset(&data, 0x00, sizeof(data));
1210         data.ioc_dev = cur_device;
1211         count = strtoull(argv[1], &end, 0);
1212         if (*end) {
1213                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1214                         jt_cmdname(argv[0]), argv[1]);
1215                 return CMD_HELP;
1216         }
1217
1218         if (argc >= 3) {
1219                 verbose = get_verbose(argv[0], argv[2]);
1220                 if (verbose == BAD_VERBOSE)
1221                         return CMD_HELP;
1222         }
1223
1224         if (argc >= 4) {
1225                 if (argv[3][0] == 't') {
1226                         objid = strtoull(argv[3] + 1, &end, 0);
1227                         if (thread)
1228                                 objid += thread - 1;
1229                 } else
1230                         objid = strtoull(argv[3], &end, 0);
1231                 if (*end) {
1232                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1233                                 jt_cmdname(argv[0]), argv[3]);
1234                         return CMD_HELP;
1235                 }
1236         }
1237
1238         gettimeofday(&start, NULL);
1239         next_time.tv_sec = start.tv_sec - verbose;
1240         next_time.tv_usec = start.tv_usec;
1241         if (verbose != 0)
1242                 printf("%s: setting "LPD64" attrs (objid "LPX64"): %s",
1243                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1244
1245         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1246                 data.ioc_obdo1.o_id = objid;
1247                 data.ioc_obdo1.o_mode = S_IFREG;
1248                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1249                 memset(buf, 0x00, sizeof(rawbuf));
1250                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1251                 if (rc) {
1252                         fprintf(stderr, "error: %s: invalid ioctl\n",
1253                                 jt_cmdname(argv[0]));
1254                         return rc;
1255                 }
1256                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data);
1257                 shmem_bump();
1258                 if (rc < 0) {
1259                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1260                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1261                         break;
1262                 } else {
1263                         if (be_verbose
1264                             (verbose, &next_time, i, &next_count, count))
1265                                 printf("%s: set attr #"LPD64"\n",
1266                                        jt_cmdname(argv[0]), i);
1267                 }
1268         }
1269
1270         if (!rc) {
1271                 struct timeval end;
1272                 double diff;
1273
1274                 gettimeofday(&end, NULL);
1275
1276                 diff = difftime(&end, &start);
1277
1278                 --i;
1279                 if (verbose != 0)
1280                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1281                                jt_cmdname(argv[0]), i, diff, i / diff,
1282                                ctime(&end.tv_sec));
1283         }
1284         return rc;
1285 }
1286
1287 int jt_obd_destroy(int argc, char **argv)
1288 {
1289         struct obd_ioctl_data data;
1290         struct timeval next_time;
1291         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1292         __u64 count = 1, next_count;
1293         int verbose = 1;
1294         __u64 id;
1295         char *end;
1296         int rc = 0, i;
1297
1298         memset(&data, 0x00, sizeof(data));
1299         data.ioc_dev = cur_device;
1300         if (argc < 2 || argc > 4)
1301                 return CMD_HELP;
1302
1303         id = strtoull(argv[1], &end, 0);
1304         if (*end || id == 0 || errno != 0) {
1305                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1306                         jt_cmdname(argv[0]), argv[1]);
1307                 return CMD_HELP;
1308         }
1309         if (argc > 2) {
1310                 count = strtoull(argv[2], &end, 0);
1311                 if (*end) {
1312                         fprintf(stderr,
1313                                 "error: %s: invalid iteration count '%s'\n",
1314                                 jt_cmdname(argv[0]), argv[2]);
1315                         return CMD_HELP;
1316                 }
1317         }
1318
1319         if (argc > 3) {
1320                 verbose = get_verbose(argv[0], argv[3]);
1321                 if (verbose == BAD_VERBOSE)
1322                         return CMD_HELP;
1323         }
1324
1325         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1326         gettimeofday(&next_time, NULL);
1327         next_time.tv_sec -= verbose;
1328
1329         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++, id++) {
1330                 data.ioc_obdo1.o_id = id;
1331                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1332                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1333
1334                 memset(buf, 0, sizeof(rawbuf));
1335                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1336                 if (rc) {
1337                         fprintf(stderr, "error: %s: invalid ioctl\n",
1338                                 jt_cmdname(argv[0]));
1339                         return rc;
1340                 }
1341                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1342                 obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1343                 shmem_bump();
1344                 if (rc < 0) {
1345                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1346                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1347                         break;
1348                 }
1349
1350                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1351                         printf("%s: #%d is object id "LPX64"\n",
1352                                jt_cmdname(argv[0]), i, id);
1353         }
1354
1355         return rc;
1356 }
1357
1358 int jt_obd_getattr(int argc, char **argv)
1359 {
1360         struct obd_ioctl_data data;
1361         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1362         char *end;
1363         int rc;
1364
1365         if (argc != 2)
1366                 return CMD_HELP;
1367
1368         memset(&data, 0x00, sizeof(data));
1369         data.ioc_dev = cur_device;
1370         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1371         if (*end) {
1372                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1373                         jt_cmdname(argv[0]), argv[1]);
1374                 return CMD_HELP;
1375         }
1376         /* to help obd filter */
1377         data.ioc_obdo1.o_mode = 0100644;
1378         data.ioc_obdo1.o_valid = 0xffffffff;
1379         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1380
1381         memset(buf, 0, sizeof(rawbuf));
1382         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1383         if (rc) {
1384                 fprintf(stderr, "error: %s: invalid ioctl\n",
1385                         jt_cmdname(argv[0]));
1386                 return rc;
1387         }
1388         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1389         obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
1390         if (rc) {
1391                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1392                         strerror(rc = errno));
1393         } else {
1394                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1395                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1396         }
1397         return rc;
1398 }
1399
1400 int jt_obd_test_getattr(int argc, char **argv)
1401 {
1402         struct obd_ioctl_data data;
1403         struct timeval start, next_time;
1404         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1405         __u64 i, count, next_count;
1406         int verbose = 1;
1407         obd_id objid = 3;
1408         char *end;
1409         int rc = 0;
1410
1411         if (argc < 2 || argc > 4)
1412                 return CMD_HELP;
1413
1414         memset(&data, 0x00, sizeof(data));
1415         data.ioc_dev = cur_device;
1416         count = strtoull(argv[1], &end, 0);
1417         if (*end) {
1418                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1419                         jt_cmdname(argv[0]), argv[1]);
1420                 return CMD_HELP;
1421         }
1422
1423         if (argc >= 3) {
1424                 verbose = get_verbose(argv[0], argv[2]);
1425                 if (verbose == BAD_VERBOSE)
1426                         return CMD_HELP;
1427         }
1428
1429         if (argc >= 4) {
1430                 if (argv[3][0] == 't') {
1431                         objid = strtoull(argv[3] + 1, &end, 0);
1432                         if (thread)
1433                                 objid += thread - 1;
1434                 } else
1435                         objid = strtoull(argv[3], &end, 0);
1436                 if (*end) {
1437                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1438                                 jt_cmdname(argv[0]), argv[3]);
1439                         return CMD_HELP;
1440                 }
1441         }
1442
1443         gettimeofday(&start, NULL);
1444         next_time.tv_sec = start.tv_sec - verbose;
1445         next_time.tv_usec = start.tv_usec;
1446         if (verbose != 0)
1447                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1448                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1449
1450         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1451                 data.ioc_obdo1.o_id = objid;
1452                 data.ioc_obdo1.o_mode = S_IFREG;
1453                 data.ioc_obdo1.o_valid = 0xffffffff;
1454                 memset(buf, 0x00, sizeof(rawbuf));
1455                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1456                 if (rc) {
1457                         fprintf(stderr, "error: %s: invalid ioctl\n",
1458                                 jt_cmdname(argv[0]));
1459                         return rc;
1460                 }
1461                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1462                 shmem_bump();
1463                 if (rc < 0) {
1464                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1465                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1466                         break;
1467                 } else {
1468                         if (be_verbose
1469                             (verbose, &next_time, i, &next_count, count))
1470                                 printf("%s: got attr #"LPD64"\n",
1471                                        jt_cmdname(argv[0]), i);
1472                 }
1473         }
1474
1475         if (!rc) {
1476                 struct timeval end;
1477                 double diff;
1478
1479                 gettimeofday(&end, NULL);
1480
1481                 diff = difftime(&end, &start);
1482
1483                 --i;
1484                 if (verbose != 0)
1485                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1486                                jt_cmdname(argv[0]), i, diff, i / diff,
1487                                ctime(&end.tv_sec));
1488         }
1489         return rc;
1490 }
1491
1492 /* test_brw <cnt>                                               count
1493         <r|w[r(repeat)x(noverify)]>                             mode
1494         <q|v|#(print interval)>                                 verbosity
1495         <npages[+offset]>                                       blocksize
1496         <[[<interleave_threads>]t(inc obj by thread#)]obj>      object
1497         [p|g<args>]                                             batch */
1498 int jt_obd_test_brw(int argc, char **argv)
1499 {
1500         struct obd_ioctl_data data;
1501         struct timeval start, next_time;
1502         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1503         __u64 count, next_count, len, stride, thr_offset = 0, objid = 3;
1504         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1505         int offset_pages = 0;
1506         long n;
1507         int repeat_offset = 0;
1508         unsigned long long ull;
1509         int  nthr_per_obj = 0;
1510         int  verify = 1;
1511         int  obj_idx = 0;
1512         char *end;
1513
1514         if (argc < 2 || argc > 7) {
1515                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1516                         jt_cmdname(argv[0]), argc);
1517                 return CMD_HELP;
1518         }
1519
1520         count = strtoull(argv[1], &end, 0);
1521         if (*end) {
1522                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1523                         jt_cmdname(argv[0]), argv[1]);
1524                 return CMD_HELP;
1525         }
1526
1527         if (argc >= 3) {
1528                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1529                         write = 1;
1530                 /* else it's a read */
1531
1532                 if (argv[2][0] != 0)
1533                         for (i = 1; argv[2][i] != 0; i++)
1534                                 switch (argv[2][i]) {
1535                                 case 'r':
1536                                         repeat_offset = 1;
1537                                         break;
1538
1539                                 case 'x':
1540                                         verify = 0;
1541                                         break;
1542
1543                                 default:
1544                                         fprintf (stderr, "Can't parse cmd '%s'\n",
1545                                                  argv[2]);
1546                                         return CMD_HELP;
1547                                 }
1548         }
1549
1550         if (argc >= 4) {
1551                 verbose = get_verbose(argv[0], argv[3]);
1552                 if (verbose == BAD_VERBOSE)
1553                         return CMD_HELP;
1554         }
1555
1556         if (argc >= 5) {
1557                 pages = strtoul(argv[4], &end, 0);
1558
1559                 if (*end == '+')
1560                         offset_pages = strtoul(end + 1, &end, 0);
1561
1562                 if (*end != 0 ||
1563                     offset_pages < 0 || offset_pages >= pages) {
1564                         fprintf(stderr, "error: %s: bad npages[+offset] parameter '%s'\n",
1565                                 jt_cmdname(argv[0]), argv[4]);
1566                         return CMD_HELP;
1567                 }
1568         }
1569
1570         if (argc >= 6) {
1571                 if (thread &&
1572                     (n = strtol(argv[5], &end, 0)) > 0 &&
1573                     *end == 't' &&
1574                     (ull = strtoull(end + 1, &end, 0)) > 0 &&
1575                     *end == 0) {
1576                         nthr_per_obj = n;
1577                         objid = ull;
1578                 } else if (thread &&
1579                            argv[5][0] == 't') {
1580                         nthr_per_obj = 1;
1581                         objid = strtoull(argv[5] + 1, &end, 0);
1582                 } else {
1583                         nthr_per_obj = 0;
1584                         objid = strtoull(argv[5], &end, 0);
1585                 }
1586                 if (*end) {
1587                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1588                                 jt_cmdname(argv[0]), argv[5]);
1589                         return CMD_HELP;
1590                 }
1591         }
1592
1593         memset(&data, 0x00, sizeof(data));
1594         data.ioc_dev = cur_device;
1595
1596         /* communicate the 'type' of brw test and batching to echo_client.
1597          * don't start.  we'd love to refactor this lctl->echo_client
1598          * interface */
1599         data.ioc_pbuf1 = (void *)1;
1600         data.ioc_plen1 = 1;
1601
1602         if (argc >= 7) {
1603                 switch(argv[6][0]) {
1604                         case 'g': /* plug and unplug */
1605                                 data.ioc_pbuf1 = (void *)2;
1606                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1607                                                           0);
1608                                 break;
1609                         case 'p': /* prep and commit */
1610                                 data.ioc_pbuf1 = (void *)3;
1611                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1612                                                           0);
1613                                 break;
1614                         default:
1615                                 fprintf(stderr, "error: %s: batching '%s' "
1616                                         "needs to specify 'p' or 'g'\n",
1617                                         jt_cmdname(argv[0]), argv[6]);
1618                                 return CMD_HELP;
1619                 }
1620
1621                 if (*end) {
1622                         fprintf(stderr, "error: %s: bad batching '%s'\n",
1623                                 jt_cmdname(argv[0]), argv[6]);
1624                         return CMD_HELP;
1625                 }
1626                 data.ioc_plen1 *= getpagesize();
1627         }
1628
1629         len = pages * getpagesize();
1630         thr_offset = offset_pages * getpagesize();
1631         stride = len;
1632
1633 #ifdef MAX_THREADS
1634         if (thread) {
1635                 shmem_lock ();
1636                 if (nthr_per_obj != 0) {
1637                         /* threads interleave */
1638                         obj_idx = (thread - 1)/nthr_per_obj;
1639                         objid += obj_idx;
1640                         stride *= nthr_per_obj;
1641                         if (thread == 1)
1642                                 shared_data->offsets[obj_idx] = stride + thr_offset;
1643                         thr_offset += ((thread - 1) % nthr_per_obj) * len;
1644                 } else {
1645                         /* threads disjoint */
1646                         thr_offset += (thread - 1) * len;
1647                 }
1648
1649                 shared_data->barrier--;
1650                 if (shared_data->barrier == 0)
1651                         l_cond_broadcast(&shared_data->cond);
1652                 else
1653                         l_cond_wait(&shared_data->cond,
1654                                           &shared_data->mutex);
1655
1656                 shmem_unlock ();
1657         }
1658 #endif
1659
1660         data.ioc_obdo1.o_id = objid;
1661         data.ioc_obdo1.o_mode = S_IFREG;
1662         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS;
1663         data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0);
1664         data.ioc_count = len;
1665         data.ioc_offset = (repeat_offset ? 0 : thr_offset);
1666
1667         gettimeofday(&start, NULL);
1668         next_time.tv_sec = start.tv_sec - verbose;
1669         next_time.tv_usec = start.tv_usec;
1670
1671         if (verbose != 0)
1672                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1673                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
1674                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1675
1676         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1677         for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) {
1678                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
1679                 memset(buf, 0x00, sizeof(rawbuf));
1680                 rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1681                 if (rc) {
1682                         fprintf(stderr, "error: %s: invalid ioctl\n",
1683                                 jt_cmdname(argv[0]));
1684                         return rc;
1685                 }
1686                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
1687                 shmem_bump();
1688                 if (rc) {
1689                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1690                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
1691                                 write ? "write" : "read");
1692                         break;
1693                 } else if (be_verbose(verbose, &next_time,i, &next_count,count)) {
1694                         shmem_lock ();
1695                         printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n",
1696                                jt_cmdname(argv[0]), write ? "write" : "read", i,
1697                                data.ioc_obdo1.o_id, data.ioc_offset,
1698                                (int)(pages * getpagesize()));
1699                         shmem_unlock ();
1700                 }
1701
1702                 if (!repeat_offset) {
1703 #ifdef MAX_THREADS
1704                         if (stride == len) {
1705                                 data.ioc_offset += stride;
1706                         } else if (i < count) {
1707                                 shmem_lock ();
1708                                 data.ioc_offset = shared_data->offsets[obj_idx];
1709                                 shared_data->offsets[obj_idx] += len;
1710                                 shmem_unlock ();
1711                         }
1712 #else
1713                         data.ioc_offset += len;
1714                         obj_idx = 0; /* avoids an unused var warning */
1715 #endif
1716                 }
1717         }
1718
1719         if (!rc) {
1720                 struct timeval end;
1721                 double diff;
1722
1723                 gettimeofday(&end, NULL);
1724
1725                 diff = difftime(&end, &start);
1726
1727                 --i;
1728                 if (verbose != 0)
1729                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
1730                                jt_cmdname(argv[0]), write ? "wrote" : "read",
1731                                i, pages, diff,
1732                                ((double)i * pages * getpagesize()) /
1733                                (diff * 1048576.0),
1734                                ctime(&end.tv_sec));
1735         }
1736
1737         return rc;
1738 }
1739
1740 int jt_obd_lov_getconfig(int argc, char **argv)
1741 {
1742         struct obd_ioctl_data data;
1743         struct lov_desc desc;
1744         struct obd_uuid *uuidarray;
1745         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1746         __u32 *obdgens;
1747         char *path;
1748         int rc, fd;
1749
1750         memset(&data, 0x00, sizeof(data));
1751         data.ioc_dev = cur_device;
1752
1753         if (argc != 2)
1754                 return CMD_HELP;
1755
1756         path = argv[1];
1757         fd = open(path, O_RDONLY);
1758         if (fd < 0) {
1759                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1760                         strerror(errno));
1761                 return -errno;
1762         }
1763
1764         memset(&desc, 0, sizeof(desc));
1765         obd_str2uuid(&desc.ld_uuid, argv[1]);
1766         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
1767                              (sizeof(*uuidarray) + sizeof(*obdgens)));
1768
1769 repeat:
1770         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1771         if (!uuidarray) {
1772                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1773                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1774                 rc = -ENOMEM;
1775                 goto out;
1776         }
1777         obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens));
1778         if (!obdgens) {
1779                 fprintf(stderr, "error: %s: no memory for %d generation #'s\n",
1780                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1781                 rc = -ENOMEM;
1782                 goto out_uuidarray;
1783         }
1784
1785         memset(buf, 0x00, sizeof(rawbuf));
1786         data.ioc_inllen1 = sizeof(desc);
1787         data.ioc_inlbuf1 = (char *)&desc;
1788         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1789         data.ioc_inlbuf2 = (char *)uuidarray;
1790         data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens);
1791         data.ioc_inlbuf3 = (char *)obdgens;
1792
1793         if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) {
1794                 fprintf(stderr, "error: %s: invalid ioctl\n",
1795                         jt_cmdname(argv[0]));
1796                 rc = -EINVAL;
1797                 goto out_obdgens;
1798         }
1799         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1800         if (rc == -ENOSPC) {
1801                 free(uuidarray);
1802                 free(obdgens);
1803                 goto repeat;
1804         } else if (rc) {
1805                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1806                         jt_cmdname(argv[0]), strerror(rc = errno));
1807         } else {
1808                 struct obd_uuid *uuidp;
1809                 __u32 *genp;
1810                 int i;
1811
1812                 if (obd_ioctl_unpack(&data, buf, sizeof(rawbuf))) {
1813                         fprintf(stderr, "error: %s: invalid reply\n",
1814                                 jt_cmdname(argv[0]));
1815                         rc = -EINVAL;
1816                         goto out;
1817                 }
1818                 if (desc.ld_default_stripe_count == (__u16)-1)
1819                         printf("default_stripe_count: %d\n", -1);
1820                 else
1821                         printf("default_stripe_count: %u\n",
1822                                desc.ld_default_stripe_count);
1823                 printf("default_stripe_size: "LPU64"\n",
1824                        desc.ld_default_stripe_size);
1825                 printf("default_stripe_offset: "LPU64"\n",
1826                        desc.ld_default_stripe_offset);
1827                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1828                 printf("obd_count: %u\n", desc.ld_tgt_count);
1829                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
1830                 uuidp = uuidarray;
1831                 genp = obdgens;
1832                 for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++)
1833                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp);
1834         }
1835 out_obdgens:
1836         free(obdgens);
1837 out_uuidarray:
1838         free(uuidarray);
1839 out:
1840         close(fd);
1841         return rc;
1842 }
1843
1844 int jt_obd_ldlm_regress_start(int argc, char **argv)
1845 {
1846         int rc;
1847         struct obd_ioctl_data data;
1848         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1849         char argstring[200];
1850         int i, count = sizeof(argstring) - 1;
1851
1852         memset(&data, 0x00, sizeof(data));
1853         data.ioc_dev = cur_device;
1854         if (argc > 5)
1855                 return CMD_HELP;
1856
1857         argstring[0] = '\0';
1858         for (i = 1; i < argc; i++) {
1859                 strncat(argstring, " ", count);
1860                 count--;
1861                 strncat(argstring, argv[i], count);
1862                 count -= strlen(argv[i]);
1863         }
1864
1865         if (strlen(argstring)) {
1866                 data.ioc_inlbuf1 = argstring;
1867                 data.ioc_inllen1 = strlen(argstring) + 1;
1868         }
1869
1870         memset(buf, 0, sizeof(rawbuf));
1871         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1872         if (rc) {
1873                 fprintf(stderr, "error: %s: invalid ioctl\n",
1874                         jt_cmdname(argv[0]));
1875                 return rc;
1876         }
1877         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1878         if (rc)
1879                 fprintf(stderr, "error: %s: test failed: %s\n",
1880                         jt_cmdname(argv[0]), strerror(rc = errno));
1881
1882         return rc;
1883 }
1884
1885 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1886 {
1887         int rc;
1888         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1889         struct obd_ioctl_data data;
1890
1891         memset(&data, 0x00, sizeof(data));
1892         data.ioc_dev = cur_device;
1893
1894         if (argc != 1)
1895                 return CMD_HELP;
1896
1897         memset(buf, 0, sizeof(rawbuf));
1898         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1899         if (rc) {
1900                 fprintf(stderr, "error: %s: invalid ioctl\n",
1901                         jt_cmdname(argv[0]));
1902                 return rc;
1903         }
1904         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1905
1906         if (rc)
1907                 fprintf(stderr, "error: %s: test failed: %s\n",
1908                         jt_cmdname(argv[0]), strerror(rc = errno));
1909         return rc;
1910 }
1911
1912 static int do_activate(int argc, char **argv, int flag)
1913 {
1914         struct obd_ioctl_data data;
1915         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1916         int rc;
1917
1918         memset(&data, 0x00, sizeof(data));
1919         data.ioc_dev = cur_device;
1920         if (argc != 1)
1921                 return CMD_HELP;
1922
1923         /* reuse offset for 'active' */
1924         data.ioc_offset = flag;
1925
1926         memset(buf, 0, sizeof(rawbuf));
1927         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1928         if (rc) {
1929                 fprintf(stderr, "error: %s: invalid ioctl\n",
1930                         jt_cmdname(argv[0]));
1931                 return rc;
1932         }
1933         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1934         if (rc)
1935                 fprintf(stderr, "error: %s: failed: %s\n",
1936                         jt_cmdname(argv[0]), strerror(rc = errno));
1937
1938         return rc;
1939 }
1940
1941 int jt_obd_deactivate(int argc, char **argv)
1942 {
1943         return do_activate(argc, argv, 0);
1944 }
1945
1946 int jt_obd_activate(int argc, char **argv)
1947 {
1948         return do_activate(argc, argv, 1);
1949 }
1950
1951 int jt_obd_recover(int argc, char **argv)
1952 {
1953         int rc;
1954         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1955         struct obd_ioctl_data data;
1956
1957         memset(&data, 0x00, sizeof(data));
1958         data.ioc_dev = cur_device;
1959         if (argc > 2)
1960                 return CMD_HELP;
1961
1962         if (argc == 2) {
1963                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1964                 data.ioc_inlbuf1 = argv[1];
1965         }
1966
1967         memset(buf, 0, sizeof(rawbuf));
1968         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
1969         if (rc) {
1970                 fprintf(stderr, "error: %s: invalid ioctl\n",
1971                         jt_cmdname(argv[0]));
1972                 return rc;
1973         }
1974         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1975         if (rc < 0) {
1976                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1977                         strerror(rc = errno));
1978         }
1979
1980         return rc;
1981 }
1982
1983 int jt_obd_mdc_lookup(int argc, char **argv)
1984 {
1985         struct obd_ioctl_data data;
1986         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1987         char *parent, *child;
1988         int rc, fd, verbose = 1;
1989
1990         if (argc < 3 || argc > 4)
1991                 return CMD_HELP;
1992
1993         parent = argv[1];
1994         child = argv[2];
1995         if (argc == 4)
1996                 verbose = get_verbose(argv[0], argv[3]);
1997
1998         memset(&data, 0x00, sizeof(data));
1999         data.ioc_dev = cur_device;
2000
2001         data.ioc_inllen1 = strlen(child) + 1;
2002         data.ioc_inlbuf1 = child;
2003
2004         memset(buf, 0, sizeof(rawbuf));
2005         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2006         if (rc) {
2007                 fprintf(stderr, "error: %s: invalid ioctl\n",
2008                         jt_cmdname(argv[0]));
2009                 return rc;
2010         }
2011
2012         fd = open(parent, O_RDONLY);
2013         if (fd < 0) {
2014                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
2015                         strerror(errno));
2016                 return -1;
2017         }
2018
2019         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
2020         if (rc < 0) {
2021                 fprintf(stderr, "error: %s: ioctl error: %s\n",
2022                         jt_cmdname(argv[0]), strerror(rc = errno));
2023         }
2024         close(fd);
2025
2026         if (verbose) {
2027                 rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
2028                 if (rc) {
2029                         fprintf(stderr, "error: %s: invalid reply\n",
2030                                 jt_cmdname(argv[0]));
2031                         return rc;
2032                 }
2033                 printf("%s: mode %o uid %d gid %d\n", child,
2034                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
2035                        data.ioc_obdo1.o_gid);
2036         }
2037
2038         return rc;
2039 }
2040
2041 int jt_cfg_dump_log(int argc, char **argv)
2042 {
2043         struct obd_ioctl_data data;
2044         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2045         int rc;
2046
2047
2048         if (argc != 2)
2049                 return CMD_HELP;
2050
2051         memset(&data, 0x00, sizeof(data));
2052         data.ioc_dev = cur_device;
2053         data.ioc_inllen1 = strlen(argv[1]) + 1;
2054         data.ioc_inlbuf1 = argv[1];
2055
2056         memset(buf, 0, sizeof(rawbuf));
2057         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2058         if (rc) {
2059                 fprintf(stderr, "error: %s: invalid ioctl\n",
2060                         jt_cmdname(argv[0]));
2061                 return rc;
2062         }
2063         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
2064         if (rc < 0)
2065                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
2066                         strerror(errno));
2067
2068         return rc;
2069 }
2070
2071 int jt_llog_catlist(int argc, char **argv)
2072 {
2073         struct obd_ioctl_data data;
2074         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2075         int rc;
2076
2077         if (argc != 1)
2078                 return CMD_HELP;
2079
2080         memset(&data, 0x00, sizeof(data));
2081         data.ioc_dev = cur_device;
2082         data.ioc_inllen1 = sizeof(rawbuf) - size_round(sizeof(data));
2083         memset(buf, 0, sizeof(rawbuf));
2084         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2085         if (rc) {
2086                 fprintf(stderr, "error: %s: invalid ioctl\n",
2087                         jt_cmdname(argv[0]));
2088                 return rc;
2089         }
2090         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
2091         if (rc == 0)
2092                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2093         else
2094                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n",
2095                         strerror(errno));
2096
2097         return rc;
2098 }
2099
2100 int jt_llog_info(int argc, char **argv)
2101 {
2102         struct obd_ioctl_data data;
2103         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2104         int rc;
2105
2106         if (argc != 2)
2107                 return CMD_HELP;
2108
2109         memset(&data, 0x00, sizeof(data));
2110         data.ioc_dev = cur_device;
2111         data.ioc_inllen1 = strlen(argv[1]) + 1;
2112         data.ioc_inlbuf1 = argv[1];
2113         data.ioc_inllen2 = sizeof(rawbuf) - size_round(sizeof(data)) -
2114                 size_round(data.ioc_inllen1);
2115         memset(buf, 0, sizeof(rawbuf));
2116         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2117         if (rc) {
2118                 fprintf(stderr, "error: %s: invalid ioctl\n",
2119                         jt_cmdname(argv[0]));
2120                 return rc;
2121         }
2122
2123         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
2124         if (rc == 0)
2125                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2126         else
2127                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
2128                         strerror(errno));
2129
2130         return rc;
2131 }
2132
2133 int jt_llog_print(int argc, char **argv)
2134 {
2135         struct obd_ioctl_data data;
2136         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2137         int rc;
2138
2139         if (argc != 2 && argc != 4)
2140                 return CMD_HELP;
2141
2142         memset(&data, 0x00, sizeof(data));
2143         data.ioc_dev = cur_device;
2144         data.ioc_inllen1 = strlen(argv[1]) + 1;
2145         data.ioc_inlbuf1 = argv[1];
2146         if (argc == 4) {
2147                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2148                 data.ioc_inlbuf2 = argv[2];
2149                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2150                 data.ioc_inlbuf3 = argv[3];
2151         } else {
2152                 char from[2] = "1", to[3] = "-1";
2153                 data.ioc_inllen2 = strlen(from) + 1;
2154                 data.ioc_inlbuf2 = from;
2155                 data.ioc_inllen3 = strlen(to) + 1;
2156                 data.ioc_inlbuf3 = to;
2157         }
2158         data.ioc_inllen4 = sizeof(rawbuf) - size_round(sizeof(data)) -
2159                 size_round(data.ioc_inllen1) -
2160                 size_round(data.ioc_inllen2) -
2161                 size_round(data.ioc_inllen3);
2162         memset(buf, 0, sizeof(rawbuf));
2163         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2164         if (rc) {
2165                 fprintf(stderr, "error: %s: invalid ioctl\n",
2166                         jt_cmdname(argv[0]));
2167                 return rc;
2168         }
2169
2170         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
2171         if (rc == 0)
2172                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2173         else
2174                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
2175                         strerror(errno));
2176
2177         return rc;
2178 }
2179
2180 int jt_llog_cancel(int argc, char **argv)
2181 {
2182         struct obd_ioctl_data data;
2183         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2184         int rc;
2185
2186         if (argc != 4)
2187                 return CMD_HELP;
2188
2189         memset(&data, 0x00, sizeof(data));
2190         data.ioc_dev = cur_device;
2191         data.ioc_inllen1 = strlen(argv[1]) + 1;
2192         data.ioc_inlbuf1 = argv[1];
2193         data.ioc_inllen2 = strlen(argv[2]) + 1;
2194         data.ioc_inlbuf2 = argv[2];
2195         data.ioc_inllen3 = strlen(argv[3]) + 1;
2196         data.ioc_inlbuf3 = argv[3];
2197         memset(buf, 0, sizeof(rawbuf));
2198         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2199         if (rc) {
2200                 fprintf(stderr, "error: %s: invalid ioctl\n",
2201                         jt_cmdname(argv[0]));
2202                 return rc;
2203         }
2204
2205         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
2206         if (rc == 0)
2207                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
2208         else
2209                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
2210                         strerror(errno));
2211
2212         return rc;
2213
2214 }
2215 int jt_llog_check(int argc, char **argv)
2216 {
2217         struct obd_ioctl_data data;
2218         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2219         int rc;
2220
2221         if (argc != 2 && argc != 4)
2222                 return CMD_HELP;
2223
2224         memset(&data, 0x00, sizeof(data));
2225         data.ioc_dev = cur_device;
2226         data.ioc_inllen1 = strlen(argv[1]) + 1;
2227         data.ioc_inlbuf1 = argv[1];
2228         if (argc == 4) {
2229                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2230                 data.ioc_inlbuf2 = argv[2];
2231                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2232                 data.ioc_inlbuf3 = argv[3];
2233         } else {
2234                 char from[2] = "1", to[3] = "-1";
2235                 data.ioc_inllen2 = strlen(from) + 1;
2236                 data.ioc_inlbuf2 = from;
2237                 data.ioc_inllen3 = strlen(to) + 1;
2238                 data.ioc_inlbuf3 = to;
2239         }
2240         data.ioc_inllen4 = sizeof(rawbuf) - size_round(sizeof(data)) -
2241                 size_round(data.ioc_inllen1) -
2242                 size_round(data.ioc_inllen2) -
2243                 size_round(data.ioc_inllen3);
2244         memset(buf, 0, sizeof(rawbuf));
2245         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2246         if (rc) {
2247                 fprintf(stderr, "error: %s: invalid ioctl\n",
2248                         jt_cmdname(argv[0]));
2249                 return rc;
2250         }
2251
2252         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
2253         if (rc == 0)
2254                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2255         else
2256                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
2257                         strerror(errno));
2258         return rc;
2259 }
2260
2261 int jt_llog_remove(int argc, char **argv)
2262 {
2263         struct obd_ioctl_data data;
2264         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2265         int rc;
2266
2267         if (argc != 3 && argc != 2)
2268                 return CMD_HELP;
2269
2270         memset(&data, 0x00, sizeof(data));
2271         data.ioc_dev = cur_device;
2272         data.ioc_inllen1 = strlen(argv[1]) + 1;
2273         data.ioc_inlbuf1 = argv[1];
2274         if (argc == 3){
2275                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2276                 data.ioc_inlbuf2 = argv[2];
2277         }
2278         memset(buf, 0, sizeof(rawbuf));
2279         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2280         if (rc) {
2281                 fprintf(stderr, "error: %s: invalid ioctl\n",
2282                         jt_cmdname(argv[0]));
2283                 return rc;
2284         }
2285
2286         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
2287         if (rc == 0) {
2288                 if (argc == 3)
2289                         fprintf(stdout, "log %s are removed.\n", argv[2]);
2290                 else
2291                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
2292         } else
2293                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
2294                         strerror(errno));
2295
2296         return rc;
2297 }
2298
2299 /* attach a regular file to virtual block device.
2300  * return vaule:
2301  *  -1: fatal error
2302  *  1: error, it always means the command run failed
2303  *  0: success
2304  */
2305 static int jt_blockdev_run_process(const char *file, char *argv[])
2306 {
2307         pid_t pid;
2308         int rc;
2309
2310         pid = vfork();
2311         if (pid == 0) { /* child process */
2312                 /* don't print error messages */
2313                 close(1), close(2);
2314                 (void)execvp(file, argv);
2315                 exit(-1);
2316         } else if (pid > 0) {
2317                 int status;
2318
2319                 rc = waitpid(pid, &status, 0);
2320                 if (rc < 0 || !WIFEXITED(status))
2321                         return -1;
2322
2323                 return WEXITSTATUS(status);
2324         }
2325
2326         return -1;
2327 }
2328
2329 static int jt_blockdev_find_module(const char *module)
2330 {
2331         FILE *fp;
2332         int found = 0;
2333         char modname[256];
2334
2335         fp = fopen("/proc/modules", "r");
2336         if (fp == NULL)
2337                 return -1;
2338
2339         while (fscanf(fp, "%s %*s %*s %*s %*s %*s", modname) == 1) {
2340                 if (strcmp(module, modname) == 0) {
2341                         found = 1;
2342                         break;
2343                 }
2344         }
2345         fclose(fp);
2346
2347         return found;
2348 }
2349
2350 static int jt_blockdev_probe_module(const char *module)
2351 {
2352         char buf[1024];
2353         char *argv[10];
2354         int c, rc;
2355
2356         if (jt_blockdev_find_module(module) == 1)
2357                 return 0;
2358
2359         /* run modprobe first */
2360         c = 0;
2361         argv[c++] = "/sbin/modprobe";
2362         argv[c++] = "-q";
2363         argv[c++] = (char *)module;
2364         argv[c++] = NULL;
2365         rc = jt_blockdev_run_process("modprobe", argv);
2366         if (rc != 1)
2367                 return rc;
2368
2369         /* cannot find the module in default directory ... */
2370         sprintf(buf, "../llite/%s.ko", module);
2371         c = 0;
2372         argv[c++] = "/sbin/insmod";
2373         argv[c++] = buf;
2374         argv[c++] = NULL;
2375         rc = jt_blockdev_run_process("insmod", argv);
2376         return rc ? -1 : 0;
2377 }
2378
2379 int jt_blockdev_attach(int argc, char **argv)
2380 {
2381         int rc, fd;
2382         struct stat st;
2383         char *filename, *devname;
2384         unsigned long dev;
2385
2386         if (argc != 3)
2387                 return CMD_HELP;
2388
2389         if (jt_blockdev_probe_module("llite_lloop") < 0) {
2390                 fprintf(stderr, "error: cannot find module llite_lloop.(k)o\n");
2391                 return ENOENT;
2392         }
2393
2394         filename = argv[1];
2395         devname = argv[2];
2396
2397         fd = open(filename, O_RDWR);
2398         if (fd < 0) {
2399                 fprintf(stderr, "file %s can't be opened(%s)\n\n",
2400                         filename, strerror(errno));
2401                 return CMD_HELP;
2402         }
2403
2404         rc = ioctl(fd, LL_IOC_LLOOP_ATTACH, &dev);
2405         if (rc < 0) {
2406                 rc = errno;
2407                 fprintf(stderr, "attach error(%s)\n", strerror(rc));
2408                 goto out;
2409         }
2410
2411         rc = stat(devname, &st);
2412         if (rc == 0 && (!S_ISBLK(st.st_mode) || st.st_rdev != dev)) {
2413                 rc = EEXIST;
2414         } else if (rc < 0) {
2415                 if (errno == ENOENT &&
2416                     !mknod(devname, S_IFBLK|S_IRUSR|S_IWUSR, dev))
2417                         rc = 0;
2418                 else
2419                         rc = errno;
2420         }
2421
2422         if (rc) {
2423                 fprintf(stderr, "error: the file %s could be attached to block "
2424                                 "device %X but creating %s failed: %s\n"
2425                                 "now detaching the block device..",
2426                         filename, (int)dev, devname, strerror(rc));
2427
2428                 (void)ioctl(fd, LL_IOC_LLOOP_DETACH_BYDEV, dev);
2429                 fprintf(stderr, "%s\n", strerror(errno));
2430         }
2431 out:
2432         close(fd);
2433         return -rc;
2434 }
2435
2436 int jt_blockdev_detach(int argc, char **argv)
2437 {
2438         char *filename;
2439         int rc, fd;
2440
2441         if (argc != 2)
2442                 return CMD_HELP;
2443
2444         filename = argv[1];
2445         fd = open(filename, O_RDONLY);
2446         if (fd < 0) {
2447                 fprintf(stderr, "cannot open file %s error %s\n",
2448                         filename, strerror(errno));
2449                 return CMD_HELP;
2450         }
2451
2452         rc = ioctl(fd, LL_IOC_LLOOP_DETACH, 0);
2453         if (rc < 0) {
2454                 rc = errno;
2455                 fprintf(stderr, "detach error(%s)\n", strerror(rc));
2456         } else {
2457                 (void)unlink(filename);
2458         }
2459
2460         close(fd);
2461         return -rc;
2462 }
2463
2464 int jt_blockdev_info(int argc, char **argv)
2465 {
2466         char *filename;
2467         int rc, fd;
2468         __u64  ino;
2469
2470         if (argc != 2)
2471                 return CMD_HELP;
2472
2473         filename = argv[1];
2474         fd = open(filename, O_RDONLY);
2475         if (fd < 0) {
2476                 fprintf(stderr, "cannot open file %s error: %s\n",
2477                         filename, strerror(errno));
2478                 return CMD_HELP;
2479         }
2480
2481         rc = ioctl(fd, LL_IOC_LLOOP_INFO, &ino);
2482         if (rc < 0) {
2483                 rc = errno;
2484                 fprintf(stderr, "error: %s\n", strerror(errno));
2485                 goto out;
2486         }
2487         fprintf(stdout, "lloop device info: ");
2488         if (ino == 0ULL)
2489                 fprintf(stdout, "Not attached\n");
2490         else
2491                 fprintf(stdout, "attached to inode "LPU64"\n", ino);
2492 out:
2493         close(fd);
2494         return -rc;
2495 }
2496
2497 static void signal_server(int sig)
2498 {
2499         if (sig == SIGINT) {
2500                 do_disconnect("sigint", 1);
2501                 exit(1);
2502         } else
2503                 fprintf(stderr, "%s: got signal %d\n", jt_cmdname("sigint"), sig);
2504 }
2505
2506 int obd_initialize(int argc, char **argv)
2507 {
2508         int i;
2509
2510         for (i = 0; i < MAX_STRIPES; i++)
2511                 lsm_buffer.lsm.lsm_oinfo[i] = lov_oinfos + i;
2512
2513         shmem_setup();
2514         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH,
2515                          OBD_DEV_MAJOR, OBD_DEV_MINOR);
2516
2517         return 0;
2518 }
2519
2520 void obd_finalize(int argc, char **argv)
2521 {
2522         struct sigaction sigact;
2523
2524         sigact.sa_handler = signal_server;
2525         sigfillset(&sigact.sa_mask);
2526         sigact.sa_flags = SA_RESTART;
2527         sigaction(SIGINT, &sigact, NULL);
2528
2529         shmem_stop();
2530         do_disconnect(argv[0], 1);
2531 }
2532
2533 static int check_pool_cmd(enum lcfg_command_type cmd,
2534                           char *fsname, char *poolname,
2535                           char *ostname)
2536 {
2537         int rc;
2538
2539         rc = llapi_search_ost(fsname, poolname, ostname);
2540         if (rc < 0 && (cmd != LCFG_POOL_NEW)) {
2541                 fprintf(stderr, "Pool %s.%s not found\n",
2542                         fsname, poolname);
2543                 return rc;
2544         }
2545
2546         switch (cmd) {
2547         case LCFG_POOL_NEW: {
2548                 LASSERT(ostname == NULL);
2549                 if (rc >= 0) {
2550                         fprintf(stderr, "Pool %s.%s already exists\n",
2551                                 fsname, poolname);
2552                         return -EEXIST;
2553                 }
2554                 return 0;
2555         }
2556         case LCFG_POOL_DEL: {
2557                 LASSERT(ostname == NULL);
2558                 if (rc == 1) {
2559                         fprintf(stderr, "Pool %s.%s not empty, "
2560                                 "please remove all members\n",
2561                                 fsname, poolname);
2562                         return -ENOTEMPTY;
2563                 }
2564                 return 0;
2565         }
2566         case LCFG_POOL_ADD: {
2567                 if (rc == 1) {
2568                         fprintf(stderr, "OST %s is already in pool %s.%s\n",
2569                                 ostname, fsname, poolname);
2570                         return -EEXIST;
2571                 }
2572                 rc = llapi_search_ost(fsname, NULL, ostname);
2573                 if (rc == 0) {
2574                         fprintf(stderr, "OST %s is not part of the '%s' fs.\n",
2575                                 ostname, fsname);
2576                         return -ENOENT;
2577                 }
2578                 return 0;
2579         }
2580         case LCFG_POOL_REM: {
2581                 if (rc == 0) {
2582                         fprintf(stderr, "OST %s not found in pool %s.%s\n",
2583                                 ostname, fsname, poolname);
2584                         return -ENOENT;
2585                 }
2586                 return 0;
2587         }
2588         default:
2589                 break;
2590         } /* switch */
2591         return -EINVAL;
2592 }
2593
2594 /* This check only verifies that the changes have been "pushed out" to
2595    the client successfully.  This involves waiting for a config update,
2596    and so may fail because of problems in that code or post-command
2597    network loss. So reporting a warning is appropriate, but not a failure.
2598 */
2599 static int check_pool_cmd_result(enum lcfg_command_type cmd,
2600                                  char *fsname, char *poolname,
2601                                  char *ostname)
2602 {
2603         int cpt = 10;
2604         int rc = 0;
2605
2606         switch (cmd) {
2607         case LCFG_POOL_NEW: {
2608                 do {
2609                         rc = llapi_search_ost(fsname, poolname, NULL);
2610                         if (rc == -ENODEV)
2611                                 return rc;
2612                         if (rc < 0)
2613                                 sleep(2);
2614                         cpt--;
2615                 } while ((rc < 0) && (cpt > 0));
2616                 if (rc >= 0) {
2617                         fprintf(stderr, "Pool %s.%s created\n",
2618                                 fsname, poolname);
2619                         return 0;
2620                 } else {
2621                         fprintf(stderr, "Warning, pool %s.%s not found\n",
2622                                 fsname, poolname);
2623                         return -ENOENT;
2624                 }
2625         }
2626         case LCFG_POOL_DEL: {
2627                 do {
2628                         rc = llapi_search_ost(fsname, poolname, NULL);
2629                         if (rc == -ENODEV)
2630                                 return rc;
2631                         if (rc >= 0)
2632                                 sleep(2);
2633                         cpt--;
2634                 } while ((rc >= 0) && (cpt > 0));
2635                 if (rc < 0) {
2636                         fprintf(stderr, "Pool %s.%s destroyed\n",
2637                                 fsname, poolname);
2638                         return 0;
2639                 } else {
2640                         fprintf(stderr, "Warning, pool %s.%s still found\n",
2641                                 fsname, poolname);
2642                         return -EEXIST;
2643                 }
2644         }
2645         case LCFG_POOL_ADD: {
2646                 do {
2647                         rc = llapi_search_ost(fsname, poolname, ostname);
2648                         if (rc == -ENODEV)
2649                                 return rc;
2650                         if (rc != 1)
2651                                 sleep(2);
2652                         cpt--;
2653                 } while ((rc != 1) && (cpt > 0));
2654                 if (rc == 1) {
2655                         fprintf(stderr, "OST %s added to pool %s.%s\n",
2656                                 ostname, fsname, poolname);
2657                         return 0;
2658                 } else {
2659                         fprintf(stderr, "Warning, OST %s not found in pool %s.%s\n",
2660                                 ostname, fsname, poolname);
2661                         return -ENOENT;
2662                 }
2663         }
2664         case LCFG_POOL_REM: {
2665                 do {
2666                         rc = llapi_search_ost(fsname, poolname, ostname);
2667                         if (rc == -ENODEV)
2668                                 return rc;
2669                         if (rc == 1)
2670                                 sleep(2);
2671                         cpt--;
2672                 } while ((rc == 1) && (cpt > 0));
2673                 if (rc != 1) {
2674                         fprintf(stderr, "OST %s removed from pool %s.%s\n",
2675                                 ostname, fsname, poolname);
2676                         return 0;
2677                 } else {
2678                         fprintf(stderr, "Warning, OST %s still found in pool %s.%s\n",
2679                                 ostname, fsname, poolname);
2680                         return -EEXIST;
2681                 }
2682         }
2683         default:
2684                 break;
2685         }
2686         return -EINVAL;
2687 }
2688
2689 static int check_and_complete_ostname(char *fsname, char *ostname)
2690 {
2691         char *ptr;
2692         char real_ostname[MAX_OBD_NAME + 1];
2693         char i;
2694
2695         /* if OST name does not start with fsname, we add it */
2696         /* if not check if the fsname is the right one */
2697         ptr = strchr(ostname, '-');
2698         if (ptr == NULL) {
2699                 sprintf(real_ostname, "%s-%s", fsname, ostname);
2700         } else if (strncmp(ostname, fsname, strlen(fsname)) != 0) {
2701                 fprintf(stderr, "%s does not start with fsname %s\n",
2702                         ostname, fsname);
2703                 return -EINVAL;
2704         } else {
2705              strcpy(real_ostname, ostname);
2706         }
2707         /* real_ostname is fsname-????? */
2708         ptr = real_ostname + strlen(fsname) + 1;
2709         if (strncmp(ptr, "OST", 3) != 0) {
2710                 fprintf(stderr, "%s does not start by %s-OST nor OST\n",
2711                         ostname, fsname);
2712                 return -EINVAL;
2713         }
2714         /* real_ostname is fsname-OST????? */
2715         ptr += 3;
2716         for (i = 0; i < 4; i++) {
2717                 if (!isxdigit(*ptr)) {
2718                         fprintf(stderr,
2719                                 "ost's index in %s is not an hexa number\n",
2720                                 ostname);
2721                         return -EINVAL;
2722                 }
2723                 ptr++;
2724         }
2725         /* real_ostname is fsname-OSTXXXX????? */
2726         /* if OST name does not end with _UUID, we add it */
2727         if (*ptr == '\0') {
2728                 strcat(real_ostname, "_UUID");
2729         } else if (strcmp(ptr, "_UUID") != 0) {
2730                 fprintf(stderr,
2731                         "ostname %s does not end with _UUID\n", ostname);
2732                 return -EINVAL;
2733         }
2734         /* real_ostname is fsname-OSTXXXX_UUID */
2735         strcpy(ostname, real_ostname);
2736         return 0;
2737 }
2738
2739 /* returns 0 or -errno */
2740 static int pool_cmd(enum lcfg_command_type cmd,
2741                     char *cmdname, char *fullpoolname,
2742                     char *fsname, char *poolname, char *ostname)
2743 {
2744         int rc = 0;
2745         struct obd_ioctl_data data;
2746         struct lustre_cfg_bufs bufs;
2747         struct lustre_cfg *lcfg;
2748         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
2749
2750         rc = check_pool_cmd(cmd, fsname, poolname, ostname);
2751         if (rc == -ENODEV)
2752                 fprintf(stderr, "Can't verify pool command since there "
2753                         "is no local MDT or client, proceeding anyhow...\n");
2754         else if (rc)
2755                 return rc;
2756
2757         lustre_cfg_bufs_reset(&bufs, NULL);
2758         lustre_cfg_bufs_set_string(&bufs, 0, cmdname);
2759         lustre_cfg_bufs_set_string(&bufs, 1, fullpoolname);
2760         if (ostname != NULL)
2761                 lustre_cfg_bufs_set_string(&bufs, 2, ostname);
2762
2763         lcfg = lustre_cfg_new(cmd, &bufs);
2764         if (IS_ERR(lcfg)) {
2765                 rc = PTR_ERR(lcfg);
2766                 return rc;
2767         }
2768
2769         memset(&data, 0x00, sizeof(data));
2770         rc = data.ioc_dev = get_mgs_device();
2771         if (rc < 0)
2772                 goto out;
2773
2774         data.ioc_type = LUSTRE_CFG_TYPE;
2775         data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount,
2776                                         lcfg->lcfg_buflens);
2777         data.ioc_pbuf1 = (void *)lcfg;
2778
2779         memset(buf, 0, sizeof(rawbuf));
2780         rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
2781         if (rc) {
2782                 fprintf(stderr, "error: %s: invalid ioctl\n",
2783                         jt_cmdname(cmdname));
2784                 return rc;
2785         }
2786         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_POOL, buf);
2787 out:
2788         if (rc)
2789                 rc = -errno;
2790         lustre_cfg_free(lcfg);
2791         return rc;
2792 }
2793
2794 /*
2795  * this function tranforms a rule [start-end/step] into an array
2796  * of matching numbers
2797  * supported forms are:
2798  * [start]                : just this number
2799  * [start-end]            : all numbers from start to end
2800  * [start-end/step]       : numbers from start to end with increment of step
2801  * on return, format contains a printf format string which can be used
2802  * to generate all the strings
2803  */
2804 static int get_array_idx(char *rule, char *format, int **array)
2805 {
2806         char *start, *end, *ptr;
2807         unsigned int lo, hi, step;
2808         int array_sz = 0;
2809         int i, array_idx;
2810         int rc;
2811
2812         start = strchr(rule, '[');
2813         end = strchr(rule, ']');
2814         if ((start == NULL) || (end == NULL)) {
2815                 *array = malloc(sizeof(int));
2816                 if (*array == NULL)
2817                         return 0;
2818                 strcpy(format, rule);
2819                 array_sz = 1;
2820                 return array_sz;
2821         }
2822         *start = '\0';
2823         *end = '\0';
2824         end++;
2825         start++;
2826         /* put in format the printf format (the rule without the range) */
2827         sprintf(format, "%s%%.4x%s", rule, end);
2828
2829         array_idx = 0;
2830         array_sz = 0;
2831         *array = NULL;
2832         /* loop on , separator */
2833         do {
2834                 /* extract the 3 fields */
2835                 rc = sscanf(start, "%x-%x/%u", &lo, &hi, &step);
2836                 switch (rc) {
2837                 case 0: {
2838                         return 0;
2839                 }
2840                 case 1: {
2841                         array_sz++;
2842                         *array = realloc(*array, array_sz * sizeof(int));
2843                         if (*array == NULL)
2844                                 return 0;
2845                         (*array)[array_idx] = lo;
2846                         array_idx++;
2847                         break;
2848                 }
2849                 case 2: {
2850                         step = 1;
2851                         /* do not break to share code with case 3: */
2852                 }
2853                 case 3: {
2854                         if ((hi < lo) || (step == 0))
2855                                 return 0;
2856                         array_sz += (hi - lo) / step + 1;
2857                         *array = realloc(*array, sizeof(int) * array_sz);
2858                         if (*array == NULL)
2859                                 return 0;
2860                         for (i = lo; i <= hi; i+=step, array_idx++)
2861                                 (*array)[array_idx] = i;
2862                         break;
2863                 }
2864                 }
2865                 ptr = strchr(start, ',');
2866                 if (ptr != NULL)
2867                         start = ptr + 1;
2868
2869         } while (ptr != NULL);
2870         return array_sz;
2871 }
2872
2873 static int extract_fsname_poolname(char *arg, char *fsname, char *poolname)
2874 {
2875         char *ptr;
2876         int len;
2877         int rc;
2878
2879         strcpy(fsname, arg);
2880         ptr = strchr(fsname, '.');
2881         if (ptr == NULL) {
2882                 fprintf(stderr, ". is missing in %s\n", fsname);
2883                 rc = -EINVAL;
2884                 goto err;
2885         }
2886
2887         len = ptr - fsname;
2888         if (len == 0) {
2889                 fprintf(stderr, "fsname is empty\n");
2890                 rc = -EINVAL;
2891                 goto err;
2892         }
2893
2894         len = strlen(ptr + 1);
2895         if (len == 0) {
2896                 fprintf(stderr, "poolname is empty\n");
2897                 rc = -EINVAL;
2898                 goto err;
2899         }
2900         if (len > LOV_MAXPOOLNAME) {
2901                 fprintf(stderr,
2902                         "poolname %s is too long (length is %d max is %d)\n",
2903                         ptr + 1, len, LOV_MAXPOOLNAME);
2904                 rc = -ENAMETOOLONG;
2905                 goto err;
2906         }
2907         strncpy(poolname, ptr + 1, LOV_MAXPOOLNAME);
2908         poolname[LOV_MAXPOOLNAME] = '\0';
2909         *ptr = '\0';
2910         return 0;
2911
2912 err:
2913         fprintf(stderr, "argument %s must be <fsname>.<poolname>\n", arg);
2914         return rc;
2915 }
2916
2917 int jt_pool_cmd(int argc, char **argv)
2918 {
2919         enum lcfg_command_type cmd;
2920         char fsname[PATH_MAX + 1];
2921         char poolname[LOV_MAXPOOLNAME + 1];
2922         char *ostnames_buf = NULL;
2923         int i, rc;
2924         int *array = NULL, array_sz;
2925         struct {
2926                 int     rc;
2927                 char   *ostname;
2928         } *cmds = NULL;
2929
2930         switch (argc) {
2931         case 0:
2932         case 1: return CMD_HELP;
2933         case 2: {
2934                 if (strcmp("pool_new", argv[0]) == 0)
2935                         cmd = LCFG_POOL_NEW;
2936                 else if (strcmp("pool_destroy", argv[0]) == 0)
2937                         cmd = LCFG_POOL_DEL;
2938                 else if (strcmp("pool_list", argv[0]) == 0)
2939                          return llapi_poollist(argv[1]);
2940                 else return CMD_HELP;
2941
2942                 rc = extract_fsname_poolname(argv[1], fsname, poolname);
2943                 if (rc)
2944                         break;
2945
2946                 rc = pool_cmd(cmd, argv[0], argv[1], fsname, poolname, NULL);
2947                 if (rc)
2948                         break;
2949
2950                 check_pool_cmd_result(cmd, fsname, poolname, NULL);
2951                 break;
2952         }
2953         default: {
2954                 char format[2*MAX_OBD_NAME];
2955
2956                 if (strcmp("pool_remove", argv[0]) == 0) {
2957                         cmd = LCFG_POOL_REM;
2958                 } else if (strcmp("pool_add", argv[0]) == 0) {
2959                         cmd = LCFG_POOL_ADD;
2960                 } else {
2961                         return CMD_HELP;
2962                 }
2963
2964                 rc = extract_fsname_poolname(argv[1], fsname, poolname);
2965                 if (rc)
2966                         break;
2967
2968                 for (i = 2; i < argc; i++) {
2969                         int j;
2970
2971                         array_sz = get_array_idx(argv[i], format, &array);
2972                         if (array_sz == 0)
2973                                 return CMD_HELP;
2974
2975                         cmds = malloc(array_sz * sizeof(cmds[0]));
2976                         if (cmds != NULL) {
2977                                 ostnames_buf = malloc(array_sz *
2978                                                       (MAX_OBD_NAME + 1));
2979                         } else {
2980                                 free(array);
2981                                 rc = -ENOMEM;
2982                                 goto out;
2983                         }
2984
2985                         for (j = 0; j < array_sz; j++) {
2986                                 char ostname[MAX_OBD_NAME + 1];
2987
2988                                 snprintf(ostname, MAX_OBD_NAME, format,
2989                                          array[j]);
2990                                 ostname[MAX_OBD_NAME] = '\0';
2991
2992                                 rc = check_and_complete_ostname(fsname,ostname);
2993                                 if (rc) {
2994                                         free(array);
2995                                         free(cmds);
2996                                         if (ostnames_buf)
2997                                                 free(ostnames_buf);
2998                                         goto out;
2999                                 }
3000                                 if (ostnames_buf != NULL) {
3001                                         cmds[j].ostname =
3002                                           &ostnames_buf[(MAX_OBD_NAME + 1) * j];
3003                                         strcpy(cmds[j].ostname, ostname);
3004                                 } else {
3005                                         cmds[j].ostname = NULL;
3006                                 }
3007                                 cmds[j].rc = pool_cmd(cmd, argv[0], argv[1],
3008                                                       fsname, poolname,
3009                                                       ostname);
3010                                 /* Return an err if any of the add/dels fail */
3011                                 if (!rc)
3012                                         rc = cmds[j].rc;
3013                         }
3014                         for (j = 0; j < array_sz; j++) {
3015                                 if (!cmds[j].rc) {
3016                                         char ostname[MAX_OBD_NAME + 1];
3017
3018                                         if (!cmds[j].ostname) {
3019                                                 snprintf(ostname, MAX_OBD_NAME,
3020                                                          format, array[j]);
3021                                                 ostname[MAX_OBD_NAME] = '\0';
3022                                                 check_and_complete_ostname(
3023                                                         fsname, ostname);
3024                                         } else {
3025                                                 strcpy(ostname,
3026                                                        cmds[j].ostname);
3027                                         }
3028                                         check_pool_cmd_result(cmd, fsname,
3029                                                               poolname,ostname);
3030                                 }
3031                         }
3032                         if (array_sz > 0)
3033                                 free(array);
3034                         if (cmds)
3035                                 free(cmds);
3036                         if (ostnames_buf);
3037                                 free(ostnames_buf);
3038                 }
3039                 /* fall through */
3040         }
3041         } /* switch */
3042
3043 out:
3044         if (rc != 0) {
3045                 errno = -rc;
3046                 perror(argv[0]);
3047         }
3048
3049         return rc;
3050 }
3051
3052 int jt_get_obj_version(int argc, char **argv)
3053 {
3054         struct ll_fid fid;
3055         struct obd_ioctl_data data;
3056         __u64 version;
3057         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf, *fidstr;
3058         struct lu_fid f;
3059         int rc;
3060
3061         if (argc != 2)
3062                 return CMD_HELP;
3063
3064         fidstr = argv[1];
3065         while (*fidstr == '[')
3066                 fidstr++;
3067         sscanf(fidstr, SFID, RFID(&f));
3068         /*
3069          * fid_is_sane is not suitable here.  We rely on
3070          * mds_fid2locked_dentry to report on insane FIDs.
3071          */
3072         fid.id = f.f_seq;
3073         fid.generation = f.f_oid;
3074         fid.f_type = f.f_ver;
3075
3076         memset(&data, 0, sizeof data);
3077         data.ioc_dev = cur_device;
3078         data.ioc_inlbuf1 = (char *) &fid;
3079         data.ioc_inllen1 = sizeof fid;
3080         data.ioc_inlbuf2 = (char *) &version;
3081         data.ioc_inllen2 = sizeof version;
3082
3083         memset(buf, 0, sizeof *buf);
3084         rc = obd_ioctl_pack(&data, &buf, sizeof rawbuf);
3085         if (rc) {
3086                 fprintf(stderr, "error: %s: packing ioctl arguments: %s\n",
3087                         jt_cmdname(argv[0]), strerror(-rc));
3088                 return rc;
3089         }
3090
3091         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_GET_OBJ_VERSION, buf);
3092         if (rc == -1) {
3093                 fprintf(stderr, "error: %s: ioctl: %s\n",
3094                         jt_cmdname(argv[0]), strerror(errno));
3095                 return -errno;
3096         }
3097
3098         obd_ioctl_unpack(&data, buf, sizeof rawbuf);
3099         printf(LPX64"\n", version);
3100         return 0;
3101 }
3102
3103 void  llapi_ping_target(char *obd_type, char *obd_name,
3104                         char *obd_uuid, void *args)
3105 {
3106         int  rc;
3107         struct obd_ioctl_data data;
3108         char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
3109
3110         memset(&data, 0, sizeof(data));
3111         data.ioc_inlbuf4 = obd_name;
3112         data.ioc_inllen4 = strlen(obd_name) + 1;
3113         data.ioc_dev = OBD_DEV_BY_DEVNAME;
3114         memset(buf, 0, sizeof(rawbuf));
3115         if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) {
3116                 fprintf(stderr, "error: invalid ioctl\n");
3117                 return;
3118         }
3119         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PING_TARGET, buf);
3120         if (rc)
3121                 rc = errno;
3122         if (rc == ENOTCONN || rc == ESHUTDOWN) {
3123                 printf("%s: INACTIVE\n", obd_name);
3124         } else if (rc) {
3125                 printf("%s: check error: %s\n",
3126                         obd_name, strerror(errno));
3127         } else {
3128                 printf("%s: active\n", obd_name);
3129         }
3130
3131 }