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