Whamcloud - gitweb
make sure libsysio is always disted
[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  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Andreas Dilger <adilger@clusterfs.com>
8  *   Author: Robert Read <rread@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28 #include <stdlib.h>
29 #include <sys/ioctl.h>
30 #include <fcntl.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/stat.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <signal.h>
38 #include <ctype.h>
39 #include <pwd.h>
40 #include <grp.h>
41 #include "obdctl.h"
42
43 #include <linux/obd.h>          /* for struct lov_stripe_md */
44 #include <linux/lustre_build_version.h>
45
46 #include <unistd.h>
47 #include <sys/un.h>
48 #include <time.h>
49 #include <sys/time.h>
50 #include <errno.h>
51 #include <string.h>
52
53 #include <asm/page.h>           /* needed for PAGE_SIZE - rread */
54
55 #define __KERNEL__
56 #include <linux/list.h>
57 #undef __KERNEL__
58
59 #include <linux/obd_class.h>
60 #include <portals/ptlctl.h>
61 #include "parser.h"
62 #include <stdio.h>
63
64 #include <sys/ipc.h>
65 #include <sys/shm.h>
66 #include <pthread.h>
67
68
69 #define MAX_STRING_SIZE 128
70 #define DEVICES_LIST "/proc/fs/lustre/devices"
71
72 #define MAX_THREADS 1024
73 struct shared_data {
74         __u64 counters[MAX_THREADS];
75         __u64 offsets[MAX_THREADS];
76         int   running;
77         int   barrier;
78         pthread_mutex_t mutex;
79         pthread_cond_t  cond;
80 };
81 static struct shared_data *shared_data;
82 static __u64 counter_snapshot[2][MAX_THREADS];
83 static int prev_valid;
84 struct timeval prev_time;
85
86 static int jt_recording;
87 static char rawbuf[8192];
88 static char *buf = rawbuf;
89 static int max = sizeof(rawbuf);
90
91 static int thread;
92 static int nthreads;
93
94 static uint32_t cur_device = MAX_OBD_DEVICES;
95
96 union lsm_buffer {
97         char                 space [4096];
98         struct lov_stripe_md lsm;
99 } lsm_buffer;
100
101 static int l2_ioctl(int dev_id, int opc, void *buf)
102 {
103         return l_ioctl(dev_id, opc, buf);
104 }
105
106 #define IOC_INIT(data)                                                  \
107 do {                                                                    \
108         memset(&data, 0, sizeof(data));                                 \
109         data.ioc_dev = cur_device;                                      \
110 } while (0)
111
112 #define IOC_PACK(func, data)                                            \
113 do {                                                                    \
114         memset(buf, 0, sizeof(rawbuf));                                 \
115         if (obd_ioctl_pack(&data, &buf, max)) {                         \
116                 fprintf(stderr, "error: %s: invalid ioctl\n",           \
117                         jt_cmdname(func));                                 \
118                 return -2;                                              \
119         }                                                               \
120 } while (0)
121
122 #define IOC_UNPACK(func, data)                                          \
123 do {                                                                    \
124         if (obd_ioctl_unpack(&data, buf, max)) {                        \
125                 fprintf(stderr, "error: %s: invalid reply\n",           \
126                         jt_cmdname(func));                                 \
127                 return -2;                                              \
128         }                                                               \
129 } while (0)
130
131 int obd_record(enum cfg_record_type type, int len, void *ptr)
132 {
133         struct obd_ioctl_data data;
134
135         IOC_INIT(data);
136         data.ioc_type = type;
137         data.ioc_plen1 = len;
138         data.ioc_pbuf1 = ptr;
139         IOC_PACK("obd_record", data);
140
141         return  l_ioctl(OBD_DEV_ID, OBD_IOC_DORECORD, &data);
142 }
143
144 int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg)
145 {
146         int opc;
147         char lcfg_rawbuf[8192];
148         char * lcfg_buf= lcfg_rawbuf;
149         struct obd_ioctl_data data;
150         int len;
151         int rc;
152
153         memset(lcfg_buf, 0, sizeof(lcfg_rawbuf));
154         if (lustre_cfg_pack(lcfg, &lcfg_buf, sizeof(lcfg_rawbuf), &len)) {
155                 fprintf(stderr, "error: %s: invalid ioctl\n",
156                         jt_cmdname(func));
157                 return -2;
158         }
159
160         IOC_INIT(data);
161         data.ioc_type = LUSTRE_CFG_TYPE;
162         data.ioc_plen1 = len;
163         data.ioc_pbuf1 = lcfg_buf;
164         IOC_PACK(func, data);
165
166         if (jt_recording)
167                 opc = OBD_IOC_DORECORD;
168         else
169                 opc = OBD_IOC_PROCESS_CFG;
170
171         rc =  l_ioctl(dev_id, opc, buf);
172         if (rc == 0)
173                 rc = lustre_cfg_unpack(lcfg, lcfg_buf, sizeof(lcfg_rawbuf));
174
175         return rc;
176 }
177
178 char *obdo_print(struct obdo *obd)
179 {
180         char buf[1024];
181
182         sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
183                 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
184                 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
185                 "misc: %x\nnlink: %d,\nvalid "LPX64"\n",
186                 obd->o_id, obd->o_gr, obd->o_atime, obd->o_mtime, obd->o_ctime,
187                 obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
188                 obd->o_uid, obd->o_gid, obd->o_flags, obd->o_misc,
189                 obd->o_nlink, obd->o_valid);
190         return strdup(buf);
191 }
192
193
194 #define BAD_VERBOSE (-999999999)
195
196 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
197
198 static int do_name2dev(char *func, char *name)
199 {
200         struct obd_ioctl_data data;
201         int rc;
202
203         IOC_INIT(data);
204
205         data.ioc_inllen1 = strlen(name) + 1;
206         data.ioc_inlbuf1 = name;
207
208         IOC_PACK(func, data);
209         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
210         if (rc < 0)
211                 return errno;
212         IOC_UNPACK(func, data);
213
214         return data.ioc_dev + N2D_OFF;
215 }
216
217 /*
218  * resolve a device name to a device number.
219  * supports a number, $name or %uuid.
220  */
221 int parse_devname(char *func, char *name)
222 {
223         int rc;
224         int ret = -1;
225
226         if (!name)
227                 return ret;
228         if (name[0] == '$' || name[0] == '%') {
229                 name++;
230                 rc = do_name2dev(func, name);
231                 if (rc >= N2D_OFF) {
232                         ret = rc - N2D_OFF;
233                         printf("Name %s is device %d\n", name, ret);
234                 } else {
235                         printf("No device found for name %s: %s\n",
236                                name, strerror(rc));
237                 }
238         } else {
239                 /* Assume it's a number.  This means that bogus strings become
240                  * 0.  I might care about that some day. */
241                 ret = strtoul(name, NULL, 0);
242                 //printf("Selected device %d\n", ret);
243         }
244
245         return ret;
246 }
247
248 static char *
249 lsm_string (struct lov_stripe_md *lsm)
250 {
251         static char buffer[4096];
252         char       *p = buffer;
253         int         space = sizeof (buffer);
254         int         i;
255         int         nob;
256
257         *p = 0;
258         space--;
259
260         nob = snprintf(p, space, LPX64, lsm->lsm_object_id);
261         p += nob;
262         space -= nob;
263
264         if (lsm->lsm_stripe_count != 0) {
265                 nob = snprintf (p, space, "=%u#%u",
266                                 lsm->lsm_stripe_size,
267                                 lsm->lsm_stripe_count);
268                 p += nob;
269                 space -= nob;
270
271                 for (i = 0; i < lsm->lsm_stripe_count; i++) {
272                         nob = snprintf (p, space, "@%u:"LPX64,
273                                         lsm->lsm_oinfo[i].loi_ost_idx,
274                                         lsm->lsm_oinfo[i].loi_id);
275                         p += nob;
276                         space -= nob;
277                 }
278         }
279
280         if (space == 0) {                       /* probable overflow */
281                 fprintf (stderr, "lsm_string() overflowed buffer\n");
282                 abort ();
283         }
284
285         return (buffer);
286 }
287
288 static void
289 reset_lsmb (union lsm_buffer *lsmb)
290 {
291         memset (lsmb->space, 0, sizeof (lsmb->space));
292         lsmb->lsm.lsm_magic = LOV_MAGIC;
293 }
294
295 static int
296 parse_lsm (union lsm_buffer *lsmb, char *string)
297 {
298         struct lov_stripe_md *lsm = &lsmb->lsm;
299         char                 *end;
300         int                   i;
301
302         /*
303          * object_id[=size#count[@offset:id]*]
304          */
305
306         reset_lsmb (lsmb);
307
308         lsm->lsm_object_id = strtoull (string, &end, 0);
309         if (end == string)
310                 return (-1);
311         string = end;
312
313         if (*string == 0)
314                 return (0);
315
316         if (*string != '=')
317                 return (-1);
318         string++;
319
320         lsm->lsm_stripe_size = strtoul (string, &end, 0);
321         if (end == string)
322                 return (-1);
323         string = end;
324
325         if (*string != '#')
326                 return (-1);
327         string++;
328
329         lsm->lsm_stripe_count = strtoul (string, &end, 0);
330         if (end == string)
331                 return (-1);
332         string = end;
333
334         if (*string == 0)               /* don't have to specify obj ids */
335                 return (0);
336
337         for (i = 0; i < lsm->lsm_stripe_count; i++) {
338                 if (*string != '@')
339                         return (-1);
340                 string++;
341                 lsm->lsm_oinfo[i].loi_ost_idx = strtoul(string, &end, 0);
342                 if (*end != ':')
343                         return (-1);
344                 string = end + 1;
345                 lsm->lsm_oinfo[i].loi_id = strtoull(string, &end, 0);
346                 string = end;
347         }
348
349         if (*string != 0)
350                 return (-1);
351
352         return (0);
353 }
354
355 char *jt_cmdname(char *func)
356 {
357         static char buf[512];
358
359         if (thread) {
360                 sprintf(buf, "%s-%d", func, thread);
361                 return buf;
362         }
363
364         return func;
365 }
366
367 #define difftime(a, b)                                  \
368         ((a)->tv_sec - (b)->tv_sec +                    \
369          ((a)->tv_usec - (b)->tv_usec) / 1000000.0)
370
371 static int be_verbose(int verbose, struct timeval *next_time,
372                       __u64 num, __u64 *next_num, int num_total)
373 {
374         struct timeval now;
375
376         if (!verbose)
377                 return 0;
378
379         if (next_time != NULL)
380                 gettimeofday(&now, NULL);
381
382         /* A positive verbosity means to print every X iterations */
383         if (verbose > 0 &&
384             (next_num == NULL || num >= *next_num || num >= num_total)) {
385                 *next_num += verbose;
386                 if (next_time) {
387                         next_time->tv_sec = now.tv_sec - verbose;
388                         next_time->tv_usec = now.tv_usec;
389                 }
390                 return 1;
391         }
392
393         /* A negative verbosity means to print at most each X seconds */
394         if (verbose < 0 && next_time != NULL &&
395             difftime(&now, next_time) >= 0.0){
396                 next_time->tv_sec = now.tv_sec - verbose;
397                 next_time->tv_usec = now.tv_usec;
398                 if (next_num)
399                         *next_num = num;
400                 return 1;
401         }
402
403         return 0;
404 }
405
406 static int get_verbose(char *func, const char *arg)
407 {
408         int verbose;
409         char *end;
410
411         if (!arg || arg[0] == 'v')
412                 verbose = 1;
413         else if (arg[0] == 's' || arg[0] == 'q')
414                 verbose = 0;
415         else {
416                 verbose = (int)strtoul(arg, &end, 0);
417                 if (*end) {
418                         fprintf(stderr, "error: %s: bad verbose option '%s'\n",
419                                 jt_cmdname(func), arg);
420                         return BAD_VERBOSE;
421                 }
422         }
423
424         if (verbose < 0)
425                 printf("Print status every %d seconds\n", -verbose);
426         else if (verbose == 1)
427                 printf("Print status every operation\n");
428         else if (verbose > 1)
429                 printf("Print status every %d operations\n", verbose);
430
431         return verbose;
432 }
433
434 int do_disconnect(char *func, int verbose)
435 {
436         cur_device = MAX_OBD_DEVICES;
437         return 0;
438 }
439
440 static void shmem_setup(void)
441 {
442         /* Create new segment */
443         int shmid = shmget(IPC_PRIVATE, sizeof(*shared_data), 0600);
444
445         if (shmid == -1) {
446                 fprintf(stderr, "Can't create shared data: %s\n",
447                         strerror(errno));
448                 return;
449         }
450
451         /* Attatch to new segment */
452         shared_data = (struct shared_data *)shmat(shmid, NULL, 0);
453         
454         if (shared_data == (struct shared_data *)(-1)) {
455                 fprintf(stderr, "Can't attach shared data: %s\n",
456                         strerror(errno));
457                 shared_data = NULL;
458                 return;
459         }
460
461         /* Mark segment as destroyed, so it will disappear when we exit.
462          * Forks will inherit attached segments, so we should be OK.
463          */
464         if (shmctl(shmid, IPC_RMID, NULL) == -1) {
465                 fprintf(stderr, "Can't destroy shared data: %s\n",
466                         strerror(errno));
467         }
468 }
469
470 static inline void shmem_reset(int total_threads)
471 {
472         if (shared_data == NULL)
473                 return;
474
475         memset(shared_data, 0, sizeof(*shared_data));
476         pthread_mutex_init(&shared_data->mutex, NULL);
477         pthread_cond_init(&shared_data->cond, NULL);
478
479         memset(counter_snapshot, 0, sizeof(counter_snapshot));
480         prev_valid = 0;
481         shared_data->barrier = total_threads;
482 }
483
484 static inline void shmem_bump(void)
485 {
486         static int bumped_running;
487
488         if (shared_data == NULL || thread <= 0 || thread > MAX_THREADS)
489                 return;
490         pthread_mutex_lock(&shared_data->mutex);
491         shared_data->counters[thread - 1]++;
492         if (!bumped_running)
493                 shared_data->running++;
494         pthread_mutex_unlock(&shared_data->mutex);
495         bumped_running = 1;
496 }
497
498 static void shmem_snap(int total_threads, int live_threads)
499 {
500         struct timeval this_time;
501         int non_zero = 0;
502         __u64 total = 0;
503         double secs;
504         int running;
505         int i;
506
507         if (shared_data == NULL || total_threads > MAX_THREADS)
508                 return;
509         
510         pthread_mutex_lock(&shared_data->mutex);
511         memcpy(counter_snapshot[0], shared_data->counters,
512                total_threads * sizeof(counter_snapshot[0][0]));
513         running = shared_data->running;
514         pthread_mutex_unlock(&shared_data->mutex);
515
516         gettimeofday(&this_time, NULL);
517
518         for (i = 0; i < total_threads; i++) {
519                 long long this_count =
520                         counter_snapshot[0][i] - counter_snapshot[1][i];
521
522                 if (this_count != 0) {
523                         non_zero++;
524                         total += this_count;
525                 }
526         }
527
528         secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
529                 (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
530
531         if (prev_valid &&
532             live_threads == total_threads &&
533             secs > 0.0)                    /* someone screwed with the time? */
534                 printf("%d/%d Total: %f/second\n", non_zero, total_threads, total / secs);
535                                                                                                                                                                                                      
536         memcpy(counter_snapshot[1], counter_snapshot[0],
537                total_threads * sizeof(counter_snapshot[0][0]));
538         prev_time = this_time;
539         if (!prev_valid &&
540             running == total_threads)
541                 prev_valid = 1;
542 }
543
544 extern command_t cmdlist[];
545
546 static int do_device(char *func, char *devname)
547 {
548         struct obd_ioctl_data data;
549         int dev;
550
551         memset(&data, 0, sizeof(data));
552
553         dev = parse_devname(func, devname);
554         if (dev < 0)
555                 return -1;
556
557         cur_device = dev;
558         return 0;
559 }
560
561 int jt_obd_device(int argc, char **argv)
562 {
563         int rc;
564         do_disconnect(argv[0], 1);
565
566         if (argc != 2)
567                 return CMD_HELP;
568
569         rc = do_device(argv[0], argv[1]);
570         return rc;
571 }
572
573 int jt_obd_connect(int argc, char **argv)
574 {
575         return 0;
576 }
577
578 int jt_obd_disconnect(int argc, char **argv)
579 {
580         if (argc != 1)
581                 return CMD_HELP;
582
583         return do_disconnect(argv[0], 0);
584 }
585
586 int jt_opt_device(int argc, char **argv)
587 {
588         int ret;
589         int rc;
590
591         if (argc < 3)
592                 return CMD_HELP;
593
594         rc = do_device("device", argv[1]);
595
596         if (!rc)
597                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
598
599         ret = do_disconnect(argv[0], 0);
600         if (!rc)
601                 rc = ret;
602
603         return rc;
604 }
605
606 static void parent_sighandler (int sig)
607 {
608         return;
609 }
610
611 int jt_opt_threads(int argc, char **argv)
612 {
613         sigset_t         saveset;
614         sigset_t         sigset;
615         struct sigaction sigact;
616         struct sigaction saveact1;
617         struct sigaction saveact2;
618         __u64 threads, next_thread;
619         int verbose;
620         int rc = 0;
621         char *end;
622         int i;
623
624         if (argc < 5)
625                 return CMD_HELP;
626
627         threads = strtoull(argv[1], &end, 0);
628         if (*end || threads > MAX_THREADS) {
629                 fprintf(stderr, "error: %s: invalid thread count '%s'\n",
630                         jt_cmdname(argv[0]), argv[1]);
631                 return CMD_HELP;
632         }
633
634         verbose = get_verbose(argv[0], argv[2]);
635         if (verbose == BAD_VERBOSE)
636                 return CMD_HELP;
637
638         if (verbose != 0)
639                 printf("%s: starting "LPD64" threads on device %s running %s\n",
640                        argv[0], threads, argv[3], argv[4]);
641
642         shmem_reset(threads);
643
644         sigemptyset(&sigset);
645         sigaddset(&sigset, SIGALRM);
646         sigaddset(&sigset, SIGCHLD);
647         sigprocmask(SIG_BLOCK, &sigset, &saveset);
648
649         nthreads = threads;
650
651
652         for (i = 1, next_thread = verbose; i <= threads; i++) {
653                 rc = fork();
654                 if (rc < 0) {
655                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
656                                 strerror(rc = errno));
657                         break;
658                 } else if (rc == 0) {
659                         sigprocmask(SIG_SETMASK, &saveset, NULL);
660                         thread = i;
661                         argv[2] = "--device";
662                         return jt_opt_device(argc - 2, argv + 2);
663                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
664                         printf("%s: thread #%d (PID %d) started\n",
665                                argv[0], i, rc);
666                 rc = 0;
667         }
668
669         if (!thread) {          /* parent process */
670                 int live_threads = threads;
671
672                 sigemptyset(&sigset);
673                 sigemptyset(&sigact.sa_mask);
674                 sigact.sa_handler = parent_sighandler;
675                 sigact.sa_flags = 0;
676
677                 sigaction(SIGALRM, &sigact, &saveact1);
678                 sigaction(SIGCHLD, &sigact, &saveact2);
679
680                 while (live_threads > 0) {
681                         int status;
682                         pid_t ret;
683
684                         if (verbose < 0)        /* periodic stats */
685                                 alarm(-verbose);
686
687                         sigsuspend(&sigset);
688                         alarm(0);
689
690                         while (live_threads > 0) {
691                                 ret = waitpid(0, &status, WNOHANG);
692                                 if (ret == 0)
693                                         break;
694
695                                 if (ret < 0) {
696                                         fprintf(stderr, "error: %s: wait - %s\n",
697                                                 argv[0], strerror(errno));
698                                         if (!rc)
699                                                 rc = errno;
700                                         continue;
701                                 } else {
702                                         /*
703                                          * This is a hack.  We _should_ be able
704                                          * to use WIFEXITED(status) to see if
705                                          * there was an error, but it appears
706                                          * to be broken and it always returns 1
707                                          * (OK).  See wait(2).
708                                          */
709                                         int err = WEXITSTATUS(status);
710                                         if (err || WIFSIGNALED(status))
711                                                 fprintf(stderr,
712                                                         "%s: PID %d had rc=%d\n",
713                                                         argv[0], ret, err);
714                                         if (!rc)
715                                                 rc = err;
716                                         live_threads--;
717                                 }
718                         }
719                         /* Show stats while all threads running */
720                         if (verbose < 0)
721                                 shmem_snap(threads, live_threads);
722                 }
723                 sigaction(SIGCHLD, &saveact2, NULL);
724                 sigaction(SIGALRM, &saveact1, NULL);
725         }
726         sigprocmask(SIG_SETMASK, &saveset, NULL);
727         return rc;
728 }
729
730 int jt_opt_net(int argc, char **argv)
731 {
732         char *arg2[3];
733         int rc;
734
735         if (argc < 3)
736                 return CMD_HELP;
737
738         arg2[0] = argv[0];
739         arg2[1] = argv[1];
740         arg2[2] = NULL;
741         rc = jt_ptl_network (2, arg2);
742
743         if (!rc)
744                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
745
746         return rc;
747 }
748
749 int jt_obd_no_transno(int argc, char **argv)
750 {
751         struct obd_ioctl_data data;
752         int rc;
753
754         IOC_INIT(data);
755
756         if (argc != 1)
757                 return CMD_HELP;
758
759         IOC_PACK(argv[0], data);
760         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf);
761         if (rc < 0)
762                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
763                         strerror(rc = errno));
764
765         return rc;
766 }
767
768 int jt_obd_set_readonly(int argc, char **argv)
769 {
770         struct obd_ioctl_data data;
771         int rc;
772
773         IOC_INIT(data);
774
775         if (argc != 1)
776                 return CMD_HELP;
777
778         IOC_PACK(argv[0], data);
779         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf);
780         if (rc < 0)
781                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
782                         strerror(rc = errno));
783
784         return rc;
785 }
786
787 int jt_obd_abort_recovery(int argc, char **argv)
788 {
789         struct obd_ioctl_data data;
790         int rc;
791
792         IOC_INIT(data);
793
794         if (argc != 1)
795                 return CMD_HELP;
796
797         IOC_PACK(argv[0], data);
798         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf);
799         if (rc < 0)
800                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
801                         strerror(rc = errno));
802
803         return rc;
804 }
805 static int is_number(char *str)
806 {
807         int i, len;
808
809         if (*str == '-' || *str == '+')
810                 str++;
811
812         if (!strncmp(str, "0x", 2))
813                 str += 2;
814
815         len = strlen(str);
816         if (!len)
817                 return 0;
818
819         for (i = 0; i < len; i++)
820                 if (!isdigit(str[i]))
821                         return 0;
822         return 1;
823 }
824
825 static int str2ugid(char *str, uint32_t *uid, uint32_t *gid)
826 {
827         struct passwd *pwd;
828         struct group  *grp;
829         char *p;
830
831         p = strchr(str, ':');
832         if (!p)
833                 return -1;
834         *p++ = 0;
835
836         pwd = getpwnam(str);
837         if (pwd)
838                 *uid = pwd->pw_uid;
839         else {
840                 if (!is_number(str))
841                         return -1;
842                 *uid = atoi(str);
843         }
844
845         grp = getgrnam(p);
846         if (grp)
847                 *gid = grp->gr_gid;
848         else {
849                 if (!is_number(p))
850                         return -1;
851                 *gid = atoi(p);
852         }
853         return 0;
854 }
855
856 static void ugid2str(char *uidname, char *gidname, uint32_t uid, uint32_t gid)
857 {
858         struct passwd *pwd;
859         struct group  *grp;
860
861         pwd = getpwuid(uid);
862         if (pwd)
863                 snprintf(uidname, 128, "%s", pwd->pw_name);
864         else
865                 snprintf(uidname, 128, "%d", uid);
866
867         grp = getgrgid(gid);
868         if (grp)
869                 snprintf(gidname, 128, "%s", grp->gr_name);
870         else
871                 snprintf(uidname, 128, "%d", gid);
872 }
873
874 #define SQUASH_IOC_SIZE (4 * 4 + sizeof(ptl_nid_t))
875 int jt_obd_root_squash(int argc, char **argv)
876 {
877         struct obd_ioctl_data   data;
878         char                    mybuf[SQUASH_IOC_SIZE];
879         uint32_t                *dir, *uid, *gid;
880         ptl_nid_t               *nid;
881         int                     rc;
882
883         IOC_INIT(data);
884
885         if (argc > 3)
886                 return CMD_HELP;
887
888         memset(mybuf, 0, sizeof(mybuf));
889         dir = (uint32_t *) mybuf;
890         uid = dir + 2;
891         gid = dir + 3;
892         nid = (ptl_nid_t *) (dir + 4);
893
894         if (argc == 1) {
895                 *dir = 0;
896         } else {
897                 *dir = 1;
898                 if (str2ugid(argv[1], uid, gid)) {
899                         fprintf(stderr, "error: %s: can't parse ugid %s\n",
900                                 jt_cmdname(argv[0]), argv[1]);
901                         return -1;
902                 }
903                 if (argc == 3) {
904                         if (ptl_parse_nid(nid, argv[2])) {
905                                 fprintf(stderr,
906                                         "error: %s: can't parse nid %s\n",
907                                         jt_cmdname(argv[0]), argv[2]);
908                                 return -1;
909                         }
910                 } else
911                         *nid = 0;
912         }
913
914         data.ioc_inllen1= SQUASH_IOC_SIZE;
915         data.ioc_inlbuf1 = mybuf;
916
917         IOC_PACK(argv[0], data);
918         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ROOT_SQUASH, buf);
919         IOC_UNPACK(argv[0], data);
920         if (rc < 0)
921                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
922                         strerror(rc = errno));
923         else if (argc == 1) {
924                 char uidname[128], gidname[128];
925                 char nidstr[256] = {0, };
926
927                 ugid2str(uidname, gidname, *uid, *gid);
928                 ptl_nid2str(nidstr, *nid);
929                 printf("squash (root:root) => (%s:%s), except nid %s\n",
930                         uidname, gidname, nidstr);
931         }
932
933         return rc;
934 }
935
936 int jt_get_version(int argc, char **argv)
937 {
938         int rc;
939         char buf[8192];
940         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
941
942         if (argc != 1)
943                 return CMD_HELP;
944
945         memset(buf, 0, sizeof(buf));
946         data->ioc_version = OBD_IOCTL_VERSION;
947         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
948         data->ioc_len = obd_ioctl_packlen(data);
949
950         rc = l2_ioctl(OBD_DEV_ID, OBD_GET_VERSION, buf);
951         if (rc < 0)
952                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
953                         strerror(rc = errno));
954         else {
955                 printf("Lustre version: %s\n", data->ioc_bulk);
956         }
957
958         printf("lctl   version: %s\n", BUILD_VERSION);
959         return rc;
960 }
961
962 int jt_obd_list(int argc, char **argv)
963 {
964         int rc;
965         char buf[MAX_STRING_SIZE];
966         FILE *fp = fopen(DEVICES_LIST, "r");
967
968         if (fp == NULL) {
969                 fprintf(stderr, "error: %s: %s could not open file "
970                         DEVICES_LIST " .\n",
971                         jt_cmdname(argv[0]), strerror(rc =  errno));
972                 return rc;
973         }
974
975         if (argc != 1)
976                 return CMD_HELP;
977
978         while (fgets(buf, sizeof(buf), fp) != NULL)
979                 printf("%s", buf);
980
981         fclose(fp);
982
983         return 0;
984 }
985
986 /* Get echo client's stripe meta-data for the given object
987  */
988 int jt_obd_get_stripe (int argc, char **argv)
989 {
990         struct obd_ioctl_data data;
991         __u64 id;
992         int   rc;
993         char *end;
994
995         if (argc != 2)
996                 return (CMD_HELP);
997
998         id = strtoull (argv[1], &end, 0);
999         if (*end) {
1000                 fprintf (stderr, "Error: %s: invalid object id '%s'\n",
1001                          jt_cmdname (argv[0]), argv[1]);
1002                 return (CMD_HELP);
1003         }
1004
1005         memset (&lsm_buffer, 0, sizeof (lsm_buffer));
1006
1007         IOC_INIT (data);
1008         data.ioc_obdo1.o_id = id;
1009         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1010         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1011         data.ioc_pbuf1 = (char *)&lsm_buffer;
1012         data.ioc_plen1 = sizeof (lsm_buffer);
1013
1014         IOC_PACK(argv[0], data);
1015         rc = l2_ioctl(OBD_DEV_ID, ECHO_IOC_GET_STRIPE, buf);
1016         IOC_UNPACK(argv[0], data);
1017
1018         if (rc != 0) {
1019                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1020                          jt_cmdname (argv[0]), rc, strerror (errno));
1021                 return (rc);
1022         }
1023
1024         printf ("%s\n", lsm_string (&lsm_buffer.lsm));
1025
1026         return (rc);
1027 }
1028
1029 /* Set stripe meta-data for 1 or more objects.  Object must be new to
1030  * this echo client instance.
1031  */
1032 int jt_obd_set_stripe (int argc, char **argv)
1033 {
1034         struct obd_ioctl_data data;
1035         char *end;
1036         int count = 1;
1037         int i;
1038         int rc;
1039
1040         if (argc < 2 || argc > 3)
1041                 return CMD_HELP;
1042
1043         rc = parse_lsm (&lsm_buffer, argv[1]);
1044         if (rc != 0) {
1045                 fprintf (stderr, "error: %s: invalid object '%s'\n",
1046                          jt_cmdname (argv[0]), argv[1]);
1047                 return CMD_HELP;
1048         }
1049
1050         if (argc > 2) {
1051                 count = strtol (argv[2], &end, 0);
1052                 if (*end != 0) {
1053                         fprintf (stderr, "error: %s: invalid count '%s'\n",
1054                                  jt_cmdname (argv[0]), argv[1]);
1055                         return CMD_HELP;
1056                 }
1057         }
1058
1059         for (i = 0; i < count; i++) {
1060                 IOC_INIT (data);
1061                 data.ioc_obdo1.o_id = lsm_buffer.lsm.lsm_object_id + i;
1062                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1063                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1064                 data.ioc_pbuf1 = (char *)&lsm_buffer;
1065                 data.ioc_plen1 = sizeof (lsm_buffer);
1066
1067                 IOC_PACK (argv[0], data);
1068                 rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1069                 IOC_UNPACK (argv[0], data);
1070
1071                 if (rc != 0) {
1072                         fprintf (stderr, "Error: %s: rc %d(%s)\n",
1073                                  jt_cmdname (argv[0]), rc, strerror (errno));
1074                         return (rc);
1075                 }
1076         }
1077
1078         return (0);
1079 }
1080
1081 /* Clear stripe meta-data info for an object on this echo-client instance
1082  */
1083 int jt_obd_unset_stripe (int argc, char **argv)
1084 {
1085         struct obd_ioctl_data data;
1086         char *end;
1087         obd_id id;
1088         int rc;
1089
1090         if (argc != 2)
1091                 return CMD_HELP;
1092
1093         id = strtoull (argv[1], &end, 0);
1094         if (*end != 0) {
1095                 fprintf (stderr, "error: %s: invalid object id '%s'\n",
1096                          jt_cmdname (argv[0]), argv[1]);
1097                 return CMD_HELP;
1098         }
1099
1100         IOC_INIT (data);
1101         data.ioc_obdo1.o_id = id;
1102         data.ioc_obdo1.o_mode = S_IFREG | 0644;
1103         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1104
1105         IOC_PACK (argv[0], data);
1106         rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf);
1107         IOC_UNPACK (argv[0], data);
1108
1109         if (rc != 0)
1110                 fprintf (stderr, "Error: %s: rc %d(%s)\n",
1111                          jt_cmdname (argv[0]), rc, strerror (errno));
1112
1113         return (0);
1114 }
1115
1116 /* Create one or more objects, arg[4] may describe stripe meta-data.  If
1117  * not, defaults assumed.  This echo-client instance stashes the stripe
1118  * object ids.  Use get_stripe on this node to print full lsm and
1119  * set_stripe on another node to cut/paste between nodes.
1120  */
1121 int jt_obd_create(int argc, char **argv)
1122 {
1123         struct obd_ioctl_data data;
1124         struct timeval next_time;
1125         __u64 count = 1, next_count, base_id = 0;
1126         int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0;
1127         char *end;
1128
1129         IOC_INIT(data);
1130         if (argc < 2 || argc > 5)
1131                 return CMD_HELP;
1132
1133         count = strtoull(argv[1], &end, 0);
1134         if (*end) {
1135                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1136                         jt_cmdname(argv[0]), argv[1]);
1137                 return CMD_HELP;
1138         }
1139
1140         if (argc > 2) {
1141                 mode = strtoul(argv[2], &end, 0);
1142                 if (*end) {
1143                         fprintf(stderr, "error: %s: invalid mode '%s'\n",
1144                                 jt_cmdname(argv[0]), argv[2]);
1145                         return CMD_HELP;
1146                 }
1147                 if (!(mode & S_IFMT))
1148                         mode |= S_IFREG;
1149         }
1150
1151         if (argc > 3) {
1152                 verbose = get_verbose(argv[0], argv[3]);
1153                 if (verbose == BAD_VERBOSE)
1154                         return CMD_HELP;
1155         }
1156
1157         if (argc < 5)
1158                 reset_lsmb (&lsm_buffer);       /* will set default */
1159         else {
1160                 rc = parse_lsm (&lsm_buffer, argv[4]);
1161                 if (rc != 0) {
1162                         fprintf(stderr, "error: %s: invalid lsm '%s'\n",
1163                                 jt_cmdname(argv[0]), argv[4]);
1164                         return CMD_HELP;
1165                 }
1166                 base_id = lsm_buffer.lsm.lsm_object_id;
1167                 valid_lsm = 1;
1168         }
1169
1170         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1171         gettimeofday(&next_time, NULL);
1172         next_time.tv_sec -= verbose;
1173
1174         for (i = 1, next_count = verbose; i <= count; i++) {
1175                 data.ioc_obdo1.o_mode = mode;
1176                 data.ioc_obdo1.o_id = base_id;
1177                 data.ioc_obdo1.o_uid = 0;
1178                 data.ioc_obdo1.o_gid = 0;
1179                 data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
1180                         OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
1181
1182                 if (valid_lsm) {
1183                         data.ioc_plen1 = sizeof lsm_buffer;
1184                         data.ioc_pbuf1 = (char *)&lsm_buffer;
1185                 }
1186
1187                 IOC_PACK(argv[0], data);
1188                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf);
1189                 IOC_UNPACK(argv[0], data);
1190                 shmem_bump();
1191                 if (rc < 0) {
1192                         fprintf(stderr, "error: %s: #%d - %s\n",
1193                                 jt_cmdname(argv[0]), i, strerror(rc = errno));
1194                         break;
1195                 }
1196                 if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
1197                         fprintf(stderr, "error: %s: objid not valid #%d:"LPX64"\n",
1198                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
1199                         rc = EINVAL;
1200                         break;
1201                 }
1202
1203                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1204                         printf("%s: #%d is object id "LPX64"\n",
1205                                 jt_cmdname(argv[0]), i, data.ioc_obdo1.o_id);
1206         }
1207         return rc;
1208 }
1209
1210 int jt_obd_setattr(int argc, char **argv)
1211 {
1212         struct obd_ioctl_data data;
1213         char *end;
1214         int rc;
1215
1216         IOC_INIT(data);
1217         if (argc != 2)
1218                 return CMD_HELP;
1219
1220         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1221         if (*end) {
1222                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1223                         jt_cmdname(argv[0]), argv[1]);
1224                 return CMD_HELP;
1225         }
1226         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
1227         if (*end) {
1228                 fprintf(stderr, "error: %s: invalid mode '%s'\n",
1229                         jt_cmdname(argv[0]), argv[2]);
1230                 return CMD_HELP;
1231         }
1232         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1233
1234         IOC_PACK(argv[0], data);
1235         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf);
1236         if (rc < 0)
1237                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1238                         strerror(rc = errno));
1239
1240         return rc;
1241 }
1242
1243 int jt_obd_test_setattr(int argc, char **argv)
1244 {
1245         struct obd_ioctl_data data;
1246         struct timeval start, next_time;
1247         __u64 i, count, next_count;
1248         int verbose = 1;
1249         obd_id objid = 3;
1250         char *end;
1251         int rc = 0;
1252
1253         if (argc < 2 && argc > 4)
1254                 return CMD_HELP;
1255
1256         IOC_INIT(data);
1257         count = strtoull(argv[1], &end, 0);
1258         if (*end) {
1259                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1260                         jt_cmdname(argv[0]), argv[1]);
1261                 return CMD_HELP;
1262         }
1263
1264         if (argc >= 3) {
1265                 verbose = get_verbose(argv[0], argv[2]);
1266                 if (verbose == BAD_VERBOSE)
1267                         return CMD_HELP;
1268         }
1269
1270         if (argc >= 4) {
1271                 if (argv[3][0] == 't') {
1272                         objid = strtoull(argv[3] + 1, &end, 0);
1273                         if (thread)
1274                                 objid += thread - 1;
1275                 } else
1276                         objid = strtoull(argv[3], &end, 0);
1277                 if (*end) {
1278                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1279                                 jt_cmdname(argv[0]), argv[3]);
1280                         return CMD_HELP;
1281                 }
1282         }
1283
1284         gettimeofday(&start, NULL);
1285         next_time.tv_sec = start.tv_sec - verbose;
1286         next_time.tv_usec = start.tv_usec;
1287         if (verbose != 0)
1288                 printf("%s: setting "LPD64" attrs (objid "LPX64"): %s",
1289                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1290
1291         for (i = 1, next_count = verbose; i <= count; i++) {
1292                 data.ioc_obdo1.o_id = objid;
1293                 data.ioc_obdo1.o_mode = S_IFREG;
1294                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
1295                 IOC_PACK(argv[0], data);
1296                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data);
1297                 shmem_bump();
1298                 if (rc < 0) {
1299                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1300                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1301                         break;
1302                 } else {
1303                         if (be_verbose
1304                             (verbose, &next_time, i, &next_count, count))
1305                                 printf("%s: set attr #"LPD64"\n",
1306                                        jt_cmdname(argv[0]), i);
1307                 }
1308         }
1309
1310         if (!rc) {
1311                 struct timeval end;
1312                 double diff;
1313
1314                 gettimeofday(&end, NULL);
1315
1316                 diff = difftime(&end, &start);
1317
1318                 --i;
1319                 if (verbose != 0)
1320                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1321                                jt_cmdname(argv[0]), i, diff, i / diff,
1322                                ctime(&end.tv_sec));
1323         }
1324         return rc;
1325 }
1326
1327
1328 int jt_obd_destroy(int argc, char **argv)
1329 {
1330         struct obd_ioctl_data data;
1331         struct timeval next_time;
1332         __u64 count = 1, next_count;
1333         int verbose = 1;
1334         __u64 id;
1335         char *end;
1336         int rc = 0, i;
1337
1338         IOC_INIT(data);
1339         if (argc < 2 || argc > 4)
1340                 return CMD_HELP;
1341
1342         id = strtoull(argv[1], &end, 0);
1343         if (*end) {
1344                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1345                         jt_cmdname(argv[0]), argv[1]);
1346                 return CMD_HELP;
1347         }
1348         if (argc > 2) {
1349                 count = strtoull(argv[2], &end, 0);
1350                 if (*end) {
1351                         fprintf(stderr,
1352                                 "error: %s: invalid iteration count '%s'\n",
1353                                 jt_cmdname(argv[0]), argv[2]);
1354                         return CMD_HELP;
1355                 }
1356         }
1357
1358         if (argc > 3) {
1359                 verbose = get_verbose(argv[0], argv[3]);
1360                 if (verbose == BAD_VERBOSE)
1361                         return CMD_HELP;
1362         }
1363
1364         printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count);
1365         gettimeofday(&next_time, NULL);
1366         next_time.tv_sec -= verbose;
1367
1368         for (i = 1, next_count = verbose; i <= count; i++, id++) {
1369                 data.ioc_obdo1.o_id = id;
1370                 data.ioc_obdo1.o_mode = S_IFREG | 0644;
1371                 data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
1372
1373                 IOC_PACK(argv[0], data);
1374                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf);
1375                 IOC_UNPACK(argv[0], data);
1376                 shmem_bump();
1377                 if (rc < 0) {
1378                         fprintf(stderr, "error: %s: objid "LPX64": %s\n",
1379                                 jt_cmdname(argv[0]), id, strerror(rc = errno));
1380                         break;
1381                 }
1382
1383                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1384                         printf("%s: #%d is object id "LPX64"\n",
1385                                jt_cmdname(argv[0]), i, id);
1386         }
1387
1388         return rc;
1389 }
1390
1391 int jt_obd_getattr(int argc, char **argv)
1392 {
1393         struct obd_ioctl_data data;
1394         char *end;
1395         int rc;
1396
1397         if (argc != 2)
1398                 return CMD_HELP;
1399
1400         IOC_INIT(data);
1401         data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
1402         if (*end) {
1403                 fprintf(stderr, "error: %s: invalid objid '%s'\n",
1404                         jt_cmdname(argv[0]), argv[1]);
1405                 return CMD_HELP;
1406         }
1407         /* to help obd filter */
1408         data.ioc_obdo1.o_mode = 0100644;
1409         data.ioc_obdo1.o_valid = (obd_valid)~0ULL;
1410         printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id);
1411
1412         IOC_PACK(argv[0], data);
1413         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf);
1414         IOC_UNPACK(argv[0], data);
1415         if (rc) {
1416                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1417                         strerror(rc = errno));
1418         } else {
1419                 printf("%s: object id "LPX64", mode %o\n", jt_cmdname(argv[0]),
1420                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1421         }
1422         return rc;
1423 }
1424
1425 int jt_obd_test_getattr(int argc, char **argv)
1426 {
1427         struct obd_ioctl_data data;
1428         struct timeval start, next_time;
1429         __u64 i, count, next_count;
1430         int verbose = 1;
1431         obd_id objid = 3;
1432         char *end;
1433         int rc = 0;
1434
1435         if (argc < 2 || argc > 4)
1436                 return CMD_HELP;
1437
1438         IOC_INIT(data);
1439         count = strtoull(argv[1], &end, 0);
1440         if (*end) {
1441                 fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
1442                         jt_cmdname(argv[0]), argv[1]);
1443                 return CMD_HELP;
1444         }
1445
1446         if (argc >= 3) {
1447                 verbose = get_verbose(argv[0], argv[2]);
1448                 if (verbose == BAD_VERBOSE)
1449                         return CMD_HELP;
1450         }
1451
1452         if (argc >= 4) {
1453                 if (argv[3][0] == 't') {
1454                         objid = strtoull(argv[3] + 1, &end, 0);
1455                         if (thread)
1456                                 objid += thread - 1;
1457                 } else
1458                         objid = strtoull(argv[3], &end, 0);
1459                 if (*end) {
1460                         fprintf(stderr, "error: %s: invalid objid '%s'\n",
1461                                 jt_cmdname(argv[0]), argv[3]);
1462                         return CMD_HELP;
1463                 }
1464         }
1465
1466         gettimeofday(&start, NULL);
1467         next_time.tv_sec = start.tv_sec - verbose;
1468         next_time.tv_usec = start.tv_usec;
1469         if (verbose != 0)
1470                 printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
1471                        jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
1472
1473         for (i = 1, next_count = verbose; i <= count; i++) {
1474                 data.ioc_obdo1.o_id = objid;
1475                 data.ioc_obdo1.o_mode = S_IFREG;
1476                 data.ioc_obdo1.o_valid = (obd_valid)~0ULL;
1477                 IOC_PACK(argv[0], data);
1478                 rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data);
1479                 shmem_bump();
1480                 if (rc < 0) {
1481                         fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
1482                                 jt_cmdname(argv[0]), i, errno, strerror(rc = errno));
1483                         break;
1484                 } else {
1485                         if (be_verbose
1486                             (verbose, &next_time, i, &next_count, count))
1487                                 printf("%s: got attr #"LPD64"\n",
1488                                        jt_cmdname(argv[0]), i);
1489                 }
1490         }
1491
1492         if (!rc) {
1493                 struct timeval end;
1494                 double diff;
1495
1496                 gettimeofday(&end, NULL);
1497
1498                 diff = difftime(&end, &start);
1499
1500                 --i;
1501                 if (verbose != 0)
1502                         printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s",
1503                                jt_cmdname(argv[0]), i, diff, i / diff,
1504                                ctime(&end.tv_sec));
1505         }
1506         return rc;
1507 }
1508
1509 int jt_obd_test_brw(int argc, char **argv)
1510 {
1511         struct obd_ioctl_data data;
1512         struct timeval start, next_time;
1513         __u64 count, next_count, len, stride, thr_offset = 0, objid = 3;
1514         int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1;
1515         long n;
1516         int repeat_offset = 0;
1517         unsigned long long ull;
1518         int  nthr_per_obj = 0;
1519         int  verify = 1;
1520         int  obj_idx = 0;
1521         char *end;
1522
1523         if (argc < 2 || argc > 7) {
1524                 fprintf(stderr, "error: %s: bad number of arguments: %d\n",
1525                         jt_cmdname(argv[0]), argc);
1526                 return CMD_HELP;
1527         }
1528
1529         /* make each thread write to a different offset */
1530         count = strtoull(argv[1], &end, 0);
1531  
1532         if (*end) {
1533                 fprintf(stderr, "error: %s: bad iteration count '%s'\n",
1534                         jt_cmdname(argv[0]), argv[1]);
1535                 return CMD_HELP;
1536         }
1537
1538         if (argc >= 3) {
1539                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1540                         write = 1;
1541                 /* else it's a read */
1542                 if (argv[2][0] != 0)
1543                         for (i = 1; argv[2][i] != 0; i++)
1544                                 switch (argv[2][i]) {
1545                                 case 'r':
1546                                         repeat_offset = 1;
1547                                         break;
1548
1549                                 case 'x':
1550                                         verify = 0;
1551                                         break;
1552
1553                                 default:
1554                                         fprintf (stderr, "Can't parse cmd '%s'\n",
1555                                                  argv[2]);
1556                                         return CMD_HELP;
1557                                 }
1558         }
1559
1560         if (argc >= 4) {
1561                 verbose = get_verbose(argv[0], argv[3]);
1562                 if (verbose == BAD_VERBOSE)
1563                         return CMD_HELP;
1564         }
1565
1566         if (argc >= 5) {
1567                 pages = strtoul(argv[4], &end, 0);
1568                 if (*end) {
1569                         fprintf(stderr, "error: %s: bad page count '%s'\n",
1570                                 jt_cmdname(argv[0]), argv[4]);
1571                         return CMD_HELP;
1572                 }
1573         }
1574         if (argc >= 6) {
1575                 if (thread &&
1576                     (n = strtol(argv[5], &end, 0)) > 0 &&
1577                     *end == 't' &&
1578                     (ull = strtoull(end + 1, &end, 0)) > 0 &&
1579                     *end == 0) {
1580                         nthr_per_obj = n;
1581                         objid = ull;
1582                 } else if (thread &&
1583                            argv[5][0] == 't') {
1584                         nthr_per_obj = 1;
1585                         objid = strtoull(argv[5] + 1, &end, 0);
1586                 } else {
1587                         nthr_per_obj = 0;
1588                         objid = strtoull(argv[5], &end, 0);
1589                 }
1590                 if (*end) {
1591                         fprintf(stderr, "error: %s: bad objid '%s'\n",
1592                                 jt_cmdname(argv[0]), argv[5]);
1593                         return CMD_HELP;
1594                 }
1595         }
1596
1597         IOC_INIT(data);
1598
1599         /* communicate the 'type' of brw test and batching to echo_client.
1600          * don't start.  we'd love to refactor this lctl->echo_client
1601          * interface */
1602         data.ioc_pbuf1 = (void *)1;
1603         data.ioc_plen1 = 1;
1604
1605         if (argc >= 7) {
1606                 switch(argv[6][0]) {
1607                         case 'g': /* plug and unplug */
1608                                 data.ioc_pbuf1 = (void *)2;
1609                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1610                                                           0);
1611                                 break;
1612                         case 'p': /* prep and commit */
1613                                 data.ioc_pbuf1 = (void *)3;
1614                                 data.ioc_plen1 = strtoull(argv[6] + 1, &end,
1615                                                           0);
1616                                 break;
1617                         default:
1618                                 fprintf(stderr, "error: %s: batching '%s' "
1619                                         "needs to specify 'p' or 'g'\n",
1620                                         jt_cmdname(argv[0]), argv[6]);
1621                                 return CMD_HELP;
1622                 }
1623
1624                 if (*end) {
1625                         fprintf(stderr, "error: %s: bad batching '%s'\n",
1626                                 jt_cmdname(argv[0]), argv[6]);
1627                         return CMD_HELP;
1628                 }
1629                 data.ioc_plen1 *= PAGE_SIZE;
1630         }
1631
1632         len = pages * PAGE_SIZE;
1633         stride = len;
1634
1635         if (thread) {
1636                 pthread_mutex_lock (&shared_data->mutex);
1637                 if (nthr_per_obj != 0) {
1638                         /* threads interleave */
1639                         obj_idx = (thread - 1)/nthr_per_obj;
1640                         objid += obj_idx;
1641                         stride *= nthr_per_obj;
1642                         thr_offset = ((thread - 1) % nthr_per_obj) * len;
1643                         if (thr_offset == 0)
1644                                 shared_data->offsets[obj_idx] = stride;
1645                 } else {
1646                         /* threads disjoint */
1647                         thr_offset = (thread - 1) * len;
1648                 }
1649
1650                 shared_data->barrier--;
1651                 if (shared_data->barrier == 0)
1652                         pthread_cond_broadcast(&shared_data->cond);
1653                 else
1654                         pthread_cond_wait(&shared_data->cond,
1655                                           &shared_data->mutex);
1656
1657                 pthread_mutex_unlock (&shared_data->mutex);
1658         }
1659
1660
1661         data.ioc_obdo1.o_id = objid;
1662         data.ioc_obdo1.o_mode = S_IFREG;
1663         data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS;
1664         data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0);
1665
1666         data.ioc_count = len;
1667         data.ioc_offset = (repeat_offset ? 0 : thr_offset);
1668
1669         gettimeofday(&start, NULL);
1670         next_time.tv_sec = start.tv_sec - verbose;
1671         next_time.tv_usec = start.tv_usec;
1672
1673         if (verbose != 0)
1674                 printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
1675                        jt_cmdname(argv[0]), write ? "writing" : "reading", count,
1676                        pages, objid, data.ioc_offset, ctime(&start.tv_sec));
1677
1678         cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1679         for (i = 1, next_count = verbose; i <= count; i++) {
1680                 data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT);
1681                 IOC_PACK(argv[0], data);
1682                 rc = l2_ioctl(OBD_DEV_ID, cmd, buf);
1683                 shmem_bump();
1684                 if (rc) {
1685                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1686                                 jt_cmdname(argv[0]), i, strerror(rc = errno),
1687                                 write ? "write" : "read");
1688                         break;
1689                 } else if (be_verbose(verbose, &next_time,i, &next_count,count))
1690                         printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n",
1691                                jt_cmdname(argv[0]), write ? "write" : "read", i,
1692                                data.ioc_obdo1.o_id, data.ioc_offset,
1693                                (int)(pages * PAGE_SIZE));
1694
1695                 if (!repeat_offset) {
1696                         if (stride == len) {
1697                                 data.ioc_offset += stride;
1698                         } else if (i < count) {
1699                                 pthread_mutex_lock (&shared_data->mutex);
1700                                 data.ioc_offset = shared_data->offsets[obj_idx];
1701                                 shared_data->offsets[obj_idx] += len;
1702                                 pthread_mutex_unlock (&shared_data->mutex);
1703                         }
1704                 }
1705
1706         }
1707
1708         if (!rc) {
1709                 struct timeval end;
1710                 double diff;
1711
1712                 gettimeofday(&end, NULL);
1713
1714                 diff = difftime(&end, &start);
1715
1716                 --i;
1717                 if (verbose != 0)
1718                         printf("%s: %s %dx%d pages in %.3fs (%.3f MB/s): %s",
1719                                jt_cmdname(argv[0]), write ? "wrote" : "read",
1720                                i, pages, diff,
1721                                ((double)i * pages * getpagesize()) /
1722                                (diff * 1048576.0),
1723                                ctime(&end.tv_sec));
1724         }
1725
1726         return rc;
1727 }
1728
1729 int jt_obd_lov_getconfig(int argc, char **argv)
1730 {
1731         struct obd_ioctl_data data;
1732         struct lov_desc desc;
1733         struct obd_uuid *uuidarray;
1734         __u32 *obdgens;
1735         char *path;
1736         int rc, fd;
1737
1738         IOC_INIT(data);
1739
1740         if (argc != 2)
1741                 return CMD_HELP;
1742
1743         path = argv[1];
1744         fd = open(path, O_RDONLY);
1745         if (fd < 0) {
1746                 fprintf(stderr, "open \"%s\" failed: %s\n", path,
1747                         strerror(errno));
1748                 return -errno;
1749         }
1750
1751         memset(&desc, 0, sizeof(desc));
1752         obd_str2uuid(&desc.ld_uuid, argv[1]);
1753         desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) /
1754                              (sizeof(*uuidarray) + sizeof(*obdgens)));
1755
1756 repeat:
1757         uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
1758         if (!uuidarray) {
1759                 fprintf(stderr, "error: %s: no memory for %d uuid's\n",
1760                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1761                 rc = -ENOMEM;
1762                 goto out;
1763         }
1764         obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens));
1765         if (!obdgens) {
1766                 fprintf(stderr, "error: %s: no memory for %d generation #'s\n",
1767                         jt_cmdname(argv[0]), desc.ld_tgt_count);
1768                 rc = -ENOMEM;
1769                 goto out_uuidarray;
1770         }
1771
1772         data.ioc_inllen1 = sizeof(desc);
1773         data.ioc_inlbuf1 = (char *)&desc;
1774         data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
1775         data.ioc_inlbuf2 = (char *)uuidarray;
1776         data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens);
1777         data.ioc_inlbuf3 = (char *)obdgens;
1778
1779         if (obd_ioctl_pack(&data, &buf, max)) {
1780                 fprintf(stderr, "error: %s: invalid ioctl\n",
1781                         jt_cmdname(argv[0]));
1782                 rc = -EINVAL;
1783                 goto out_obdgens;
1784         }
1785         rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
1786         if (rc == -ENOSPC) {
1787                 free(uuidarray);
1788                 free(obdgens);
1789                 goto repeat;
1790         } else if (rc) {
1791                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1792                         jt_cmdname(argv[0]), strerror(rc = errno));
1793         } else {
1794                 struct obd_uuid *uuidp;
1795                 __u32 *genp;
1796                 int i;
1797
1798                 if (obd_ioctl_unpack(&data, buf, max)) {
1799                         fprintf(stderr, "error: %s: invalid reply\n",
1800                                 jt_cmdname(argv[0]));
1801                         rc = -EINVAL;
1802                         goto out;
1803                 }
1804                 printf("default_stripe_count: %u\n",
1805                        desc.ld_default_stripe_count);
1806                 printf("default_stripe_size: "LPU64"\n",
1807                        desc.ld_default_stripe_size);
1808                 printf("default_stripe_offset: "LPU64"\n",
1809                        desc.ld_default_stripe_offset);
1810                 printf("default_stripe_pattern: %u\n", desc.ld_pattern);
1811                 printf("obd_count: %u\n", desc.ld_tgt_count);
1812                 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
1813                 uuidp = uuidarray;
1814                 genp = obdgens;
1815                 for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++)
1816                         printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp);
1817         }
1818 out_obdgens:
1819         free(obdgens);
1820 out_uuidarray:
1821         free(uuidarray);
1822 out:
1823         close(fd);
1824         return rc;
1825 }
1826
1827 int jt_obd_test_ldlm(int argc, char **argv)
1828 {
1829         struct obd_ioctl_data data;
1830         int rc;
1831
1832         IOC_INIT(data);
1833         if (argc != 1)
1834                 return CMD_HELP;
1835
1836         IOC_PACK(argv[0], data);
1837         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_TEST, buf);
1838         if (rc)
1839                 fprintf(stderr, "error: %s: test failed: %s\n",
1840                         jt_cmdname(argv[0]), strerror(rc = errno));
1841         return rc;
1842 }
1843
1844 int jt_obd_dump_ldlm(int argc, char **argv)
1845 {
1846         struct obd_ioctl_data data;
1847         int rc;
1848
1849         IOC_INIT(data);
1850         if (argc != 1)
1851                 return CMD_HELP;
1852
1853         IOC_PACK(argv[0], data);
1854         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf);
1855         if (rc)
1856                 fprintf(stderr, "error: %s failed: %s\n",
1857                         jt_cmdname(argv[0]), strerror(rc = errno));
1858         return rc;
1859 }
1860
1861 int jt_obd_ldlm_regress_start(int argc, char **argv)
1862 {
1863         int rc;
1864         struct obd_ioctl_data data;
1865         char argstring[200];
1866         int i, count = sizeof(argstring) - 1;
1867
1868         IOC_INIT(data);
1869         if (argc > 5)
1870                 return CMD_HELP;
1871
1872         argstring[0] = '\0';
1873         for (i = 1; i < argc; i++) {
1874                 strncat(argstring, " ", count);
1875                 count--;
1876                 strncat(argstring, argv[i], count);
1877                 count -= strlen(argv[i]);
1878         }
1879
1880         if (strlen(argstring)) {
1881                 data.ioc_inlbuf1 = argstring;
1882                 data.ioc_inllen1 = strlen(argstring) + 1;
1883         }
1884
1885         IOC_PACK(argv[0], data);
1886         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf);
1887         if (rc)
1888                 fprintf(stderr, "error: %s: test failed: %s\n",
1889                         jt_cmdname(argv[0]), strerror(rc = errno));
1890
1891         return rc;
1892 }
1893
1894 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1895 {
1896         int rc;
1897         struct obd_ioctl_data data;
1898         IOC_INIT(data);
1899
1900         if (argc != 1)
1901                 return CMD_HELP;
1902
1903         IOC_PACK(argv[0], data);
1904         rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf);
1905
1906         if (rc)
1907                 fprintf(stderr, "error: %s: test failed: %s\n",
1908                         jt_cmdname(argv[0]), strerror(rc = errno));
1909         return rc;
1910 }
1911
1912 static int do_activate(int argc, char **argv, int flag)
1913 {
1914         struct obd_ioctl_data data;
1915         int rc;
1916
1917         IOC_INIT(data);
1918         if (argc != 1)
1919                 return CMD_HELP;
1920
1921         /* reuse offset for 'active' */
1922         data.ioc_offset = flag;
1923
1924         IOC_PACK(argv[0], data);
1925         rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf);
1926         if (rc)
1927                 fprintf(stderr, "error: %s: failed: %s\n",
1928                         jt_cmdname(argv[0]), strerror(rc = errno));
1929
1930         return rc;
1931 }
1932
1933 int jt_obd_deactivate(int argc, char **argv)
1934 {
1935         return do_activate(argc, argv, 0);
1936 }
1937
1938 int jt_obd_activate(int argc, char **argv)
1939 {
1940         return do_activate(argc, argv, 1);
1941 }
1942
1943 int jt_obd_recover(int argc, char **argv)
1944 {
1945         int rc;
1946         struct obd_ioctl_data data;
1947
1948         IOC_INIT(data);
1949         if (argc > 2)
1950                 return CMD_HELP;
1951
1952         if (argc == 2) {
1953                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1954                 data.ioc_inlbuf1 = argv[1];
1955         }
1956
1957         IOC_PACK(argv[0], data);
1958         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf);
1959         if (rc < 0) {
1960                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
1961                         strerror(rc = errno));
1962         }
1963
1964         return rc;
1965 }
1966
1967 int jt_obd_mdc_lookup(int argc, char **argv)
1968 {
1969         struct obd_ioctl_data data;
1970         char *parent, *child;
1971         int rc, fd, verbose = 1;
1972
1973         if (argc < 3 || argc > 4)
1974                 return CMD_HELP;
1975
1976         parent = argv[1];
1977         child = argv[2];
1978         if (argc == 4)
1979                 verbose = get_verbose(argv[0], argv[3]);
1980
1981         IOC_INIT(data);
1982
1983         data.ioc_inllen1 = strlen(child) + 1;
1984         data.ioc_inlbuf1 = child;
1985
1986         IOC_PACK(argv[0], data);
1987
1988         fd = open(parent, O_RDONLY);
1989         if (fd < 0) {
1990                 fprintf(stderr, "open \"%s\" failed: %s\n", parent,
1991                         strerror(errno));
1992                 return -1;
1993         }
1994
1995         rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
1996         if (rc < 0) {
1997                 fprintf(stderr, "error: %s: ioctl error: %s\n",
1998                         jt_cmdname(argv[0]), strerror(rc = errno));
1999         }
2000         close(fd);
2001
2002         if (verbose) {
2003                 IOC_UNPACK(argv[0], data);
2004                 printf("%s: mode %o uid %d gid %d\n", child,
2005                        data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid,
2006                        data.ioc_obdo1.o_gid);
2007         }
2008
2009         return rc;
2010 }
2011
2012 int jt_obd_finish_gns(int argc, char **argv)
2013 {
2014         char *mtpt;
2015         int rc, fd;
2016         struct obd_ioctl_data data;
2017
2018         if (argc != 2)
2019                 return CMD_HELP;
2020
2021         mtpt = argv[1];
2022
2023         fd = open(mtpt, O_RDONLY);
2024         if (fd < 0) {
2025                 fprintf(stderr, "open \"%s\" failed: %s\n", mtpt,
2026                         strerror(errno));
2027                 return -1;
2028         }
2029
2030         IOC_INIT(data);
2031         IOC_PACK(argv[0], data);
2032         rc = ioctl(fd, IOC_MDC_FINISH_GNS, buf);
2033         if (rc < 0) {
2034                 fprintf(stderr, "error: %s(%s) ioctl error: %s\n",
2035                         jt_cmdname(argv[0]), mtpt, strerror(rc = errno));
2036         }
2037         close(fd);
2038
2039         return rc;
2040 }
2041
2042 int jt_obd_close_uuid(int argc, char **argv)
2043 {
2044         int rc, nal;
2045         struct obd_ioctl_data data;
2046
2047         if (argc != 3) {
2048                 fprintf(stderr, "usage: %s <uuid> <net-type>\n", argv[0]);
2049                 return 0;
2050         }
2051
2052         nal = ptl_name2nal(argv[2]);
2053
2054         if (nal <= 0) {
2055                 fprintf (stderr, "Can't parse NAL %s\n", argv[2]);
2056                 return -1;
2057         }
2058
2059         IOC_INIT(data);
2060         data.ioc_inllen1 = strlen(argv[1]) + 1;
2061         data.ioc_inlbuf1 = argv[1];
2062         data.ioc_nal = nal;
2063
2064         IOC_PACK(argv[0], data);
2065         rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf);
2066         if (rc) {
2067                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
2068                         strerror(errno));
2069                 return -1;
2070         }
2071         return 0;
2072 }
2073
2074
2075 int jt_cfg_record(int argc, char **argv)
2076 {
2077         struct obd_ioctl_data data;
2078         int rc;
2079
2080         IOC_INIT(data);
2081
2082         if (argc != 2)
2083                 return CMD_HELP;
2084
2085         data.ioc_inllen1 = strlen(argv[1]) + 1;
2086         data.ioc_inlbuf1 = argv[1];
2087
2088         IOC_PACK(argv[0], data);
2089         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_RECORD, buf);
2090         if (rc == 0) {
2091                 jt_recording = 1;
2092                 ptl_set_cfg_record_cb(obd_record);
2093         } else {
2094                 fprintf(stderr, "OBD_IOC_RECORD failed: %s\n",
2095                         strerror(errno));
2096         }
2097
2098         return rc;
2099 }
2100
2101 int jt_cfg_parse(int argc, char **argv)
2102 {
2103         struct obd_ioctl_data data;
2104         int rc;
2105
2106         IOC_INIT(data);
2107
2108         if (argc != 2)
2109                 return CMD_HELP;
2110
2111         data.ioc_inllen1 = strlen(argv[1]) + 1;
2112         data.ioc_inlbuf1 = argv[1];
2113
2114         IOC_PACK(argv[0], data);
2115         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PARSE, buf);
2116         if (rc < 0)
2117                 fprintf(stderr, "OBD_IOC_PARSE failed: %s\n",
2118                         strerror(errno));
2119
2120         return rc;
2121 }
2122
2123
2124 int jt_cfg_dump_log(int argc, char **argv)
2125 {
2126         struct obd_ioctl_data data;
2127         int rc;
2128
2129         IOC_INIT(data);
2130
2131         if (argc != 2)
2132                 return CMD_HELP;
2133
2134         data.ioc_inllen1 = strlen(argv[1]) + 1;
2135         data.ioc_inlbuf1 = argv[1];
2136
2137         IOC_PACK(argv[0], data);
2138         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf);
2139         if (rc < 0)
2140                 fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n",
2141                         strerror(errno));
2142
2143         return rc;
2144 }
2145
2146 int jt_cfg_clear_log(int argc, char **argv)
2147 {
2148         struct obd_ioctl_data data;
2149         int rc;
2150
2151         IOC_INIT(data);
2152
2153         if (argc != 2)
2154                 return CMD_HELP;
2155
2156         data.ioc_inllen1 = strlen(argv[1]) + 1;
2157         data.ioc_inlbuf1 = argv[1];
2158
2159         IOC_PACK(argv[0], data);
2160         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CLEAR_LOG, buf);
2161         if (rc < 0)
2162                 fprintf(stderr, "OBD_IOC_CLEAR_LOG failed: %s\n",
2163                         strerror(errno));
2164
2165         return rc;
2166 }
2167
2168
2169
2170 int jt_cfg_endrecord(int argc, char **argv)
2171 {
2172         struct obd_ioctl_data data;
2173         int rc;
2174
2175         IOC_INIT(data);
2176
2177         if (argc != 1)
2178                 return CMD_HELP;
2179
2180         if (!jt_recording) {
2181                 fprintf(stderr, "Not recording, so endrecord doesn't make "
2182                         "sense.\n");
2183                 return 0;
2184         }
2185
2186         IOC_PACK(argv[0], data);
2187         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ENDRECORD, buf);
2188         if (rc == 0) {
2189                 jt_recording = 0;
2190                 ptl_set_cfg_record_cb(NULL);
2191         } else {
2192                 fprintf(stderr, "OBD_IOC_ENDRECORD failed: %s\n",
2193                         strerror(errno));
2194         }
2195         return rc;
2196 }
2197
2198 int jt_llog_catlist(int argc, char **argv)
2199 {
2200         struct obd_ioctl_data data;
2201         int rc;
2202
2203         if (argc != 1)
2204                 return CMD_HELP;
2205
2206         IOC_INIT(data);
2207         data.ioc_inllen1 = max - size_round(sizeof(data));
2208         IOC_PACK(argv[0], data);
2209
2210         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf);
2211         if (rc == 0)
2212                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2213         else
2214                 fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n",
2215                         strerror(errno));
2216
2217         return rc;
2218 }
2219
2220 int jt_llog_info(int argc, char **argv)
2221 {
2222         struct obd_ioctl_data data;
2223         int rc;
2224
2225         if (argc != 2)
2226                 return CMD_HELP;
2227
2228         IOC_INIT(data);
2229         data.ioc_inllen1 = strlen(argv[1]) + 1;
2230         data.ioc_inlbuf1 = argv[1];
2231         data.ioc_inllen2 = max - size_round(sizeof(data)) -
2232                 size_round(data.ioc_inllen1);
2233         IOC_PACK(argv[0], data);
2234
2235         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf);
2236         if (rc == 0)
2237                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2238         else
2239                 fprintf(stderr, "OBD_IOC_LLOG_INFO failed: %s\n",
2240                         strerror(errno));
2241
2242         return rc;
2243 }
2244
2245 int jt_llog_print(int argc, char **argv)
2246 {
2247         struct obd_ioctl_data data;
2248         int rc;
2249
2250         if (argc != 2 && argc != 4)
2251                 return CMD_HELP;
2252
2253         IOC_INIT(data);
2254         data.ioc_inllen1 = strlen(argv[1]) + 1;
2255         data.ioc_inlbuf1 = argv[1];
2256         if (argc == 4) {
2257                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2258                 data.ioc_inlbuf2 = argv[2];
2259                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2260                 data.ioc_inlbuf3 = argv[3];
2261         } else {
2262                 char from[2] = "1", to[3] = "-1";
2263                 data.ioc_inllen2 = strlen(from) + 1;
2264                 data.ioc_inlbuf2 = from;
2265                 data.ioc_inllen3 = strlen(to) + 1;
2266                 data.ioc_inlbuf3 = to;
2267         }
2268         data.ioc_inllen4 = max - size_round(sizeof(data)) -
2269                 size_round(data.ioc_inllen1) -
2270                 size_round(data.ioc_inllen2) -
2271                 size_round(data.ioc_inllen3);
2272         IOC_PACK(argv[0], data);
2273
2274         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf);
2275         if (rc == 0)
2276                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2277         else
2278                 fprintf(stderr, "OBD_IOC_LLOG_PRINT failed: %s\n",
2279                         strerror(errno));
2280
2281         return rc;
2282 }
2283
2284 int jt_llog_cancel(int argc, char **argv)
2285 {
2286         struct obd_ioctl_data data;
2287         int rc;
2288
2289         if (argc != 4)
2290                 return CMD_HELP;
2291
2292         IOC_INIT(data);
2293         data.ioc_inllen1 = strlen(argv[1]) + 1;
2294         data.ioc_inlbuf1 = argv[1];
2295         data.ioc_inllen2 = strlen(argv[2]) + 1;
2296         data.ioc_inlbuf2 = argv[2];
2297         data.ioc_inllen3 = strlen(argv[3]) + 1;
2298         data.ioc_inlbuf3 = argv[3];
2299         IOC_PACK(argv[0], data);
2300
2301         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
2302         if (rc == 0)
2303                 fprintf(stdout, "index %s be canceled.\n", argv[3]);
2304         else
2305                 fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n",
2306                         strerror(errno));
2307
2308         return rc;
2309
2310 }
2311 int jt_llog_check(int argc, char **argv)
2312 {
2313         struct obd_ioctl_data data;
2314         int rc;
2315
2316         if (argc != 2 && argc != 4)
2317                 return CMD_HELP;
2318
2319         IOC_INIT(data);
2320         data.ioc_inllen1 = strlen(argv[1]) + 1;
2321         data.ioc_inlbuf1 = argv[1];
2322         if (argc == 4) {
2323                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2324                 data.ioc_inlbuf2 = argv[2];
2325                 data.ioc_inllen3 = strlen(argv[3]) + 1;
2326                 data.ioc_inlbuf3 = argv[3];
2327         } else {
2328                 char from[2] = "1", to[3] = "-1";
2329                 data.ioc_inllen2 = strlen(from) + 1;
2330                 data.ioc_inlbuf2 = from;
2331                 data.ioc_inllen3 = strlen(to) + 1;
2332                 data.ioc_inlbuf3 = to;
2333         }
2334         data.ioc_inllen4 = max - size_round(sizeof(data)) -
2335                 size_round(data.ioc_inllen1) -
2336                 size_round(data.ioc_inllen2) -
2337                 size_round(data.ioc_inllen3);
2338         IOC_PACK(argv[0], data);
2339
2340         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf);
2341         if (rc == 0)
2342                 fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk);
2343         else
2344                 fprintf(stderr, "OBD_IOC_LLOG_CHECK failed: %s\n",
2345                         strerror(errno));
2346         return rc;
2347 }
2348
2349 int jt_llog_remove(int argc, char **argv)
2350 {
2351         struct obd_ioctl_data data;
2352         int rc;
2353
2354         if (argc != 3 && argc != 2)
2355                 return CMD_HELP;
2356
2357         IOC_INIT(data);
2358         data.ioc_inllen1 = strlen(argv[1]) + 1;
2359         data.ioc_inlbuf1 = argv[1];
2360         if (argc == 3){
2361                 data.ioc_inllen2 = strlen(argv[2]) + 1;
2362                 data.ioc_inlbuf2 = argv[2];
2363         }
2364         IOC_PACK(argv[0], data);
2365
2366         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf);
2367         if (rc == 0) {
2368                 if (argc == 3)
2369                         fprintf(stdout, "log %s are removed.\n", argv[2]);
2370                 else
2371                         fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
2372         } else
2373                 fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
2374                         strerror(errno));
2375
2376         return rc;
2377 }
2378 int jt_obd_reint_sync(int argc, char **argv)
2379 {
2380         struct obd_ioctl_data data;
2381         int rc = 0;
2382       
2383         IOC_INIT(data);
2384         if (argc != 1)
2385                return CMD_HELP; 
2386         IOC_PACK(argv[0], data);
2387         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CMOBD_SYNC, buf);
2388        
2389         if (rc) {
2390                 fprintf(stderr, "OBD_IOC_CMOBD_SYNC failed: %s\n",
2391                         strerror(errno));
2392         }
2393         return rc;  
2394                
2395 }
2396
2397 int jt_obd_cache_on(int argc, char **argv)
2398 {
2399         struct obd_ioctl_data data;
2400         int rc = 0;
2401       
2402         IOC_INIT(data);
2403         if (argc != 1)
2404                return CMD_HELP; 
2405         IOC_PACK(argv[0], data);
2406         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_COBD_CON, buf);
2407        
2408         if (rc) {
2409                 fprintf(stderr, "OBD_IOC_COBD_CON failed: %s\n",
2410                         strerror(errno));
2411         }
2412         return rc;  
2413                
2414 }
2415 int jt_obd_cache_off(int argc, char **argv)
2416 {
2417         struct obd_ioctl_data data;
2418         int rc = 0;
2419       
2420         IOC_INIT(data);
2421         if (argc != 1)
2422                return CMD_HELP; 
2423         IOC_PACK(argv[0], data);
2424         rc = l_ioctl(OBD_DEV_ID, OBD_IOC_COBD_COFF, buf);
2425         if (rc) {
2426                 fprintf(stderr, "OBD_IOC_COBD_COFF failed: %s\n",
2427                         strerror(errno));
2428         }
2429         return rc;  
2430 }
2431 int jt_obd_snap_add(int argc, char **argv)
2432 {
2433         struct obd_ioctl_data data;
2434         int rc = 0;
2435       
2436         if (argc != 3)
2437                return CMD_HELP;
2438
2439         shmem_setup();   
2440         register_ioc_dev(SMFS_DEV_ID, SMFS_DEV_PATH);
2441         
2442         IOC_INIT(data);
2443         
2444         data.ioc_inllen1 = strlen(argv[1]) + 1;
2445         data.ioc_inlbuf1 = argv[1];
2446         data.ioc_inllen2 = strlen(argv[2]) + 2;
2447         data.ioc_inlbuf2 = argv[2];
2448
2449         IOC_PACK(argv[0], data);
2450        
2451         rc = l_ioctl(SMFS_DEV_ID, OBD_IOC_SMFS_SNAP_ADD, buf);
2452         
2453         unregister_ioc_dev(SMFS_DEV_ID);       
2454         if (rc) {
2455                 fprintf(stderr, "OBD_IOC_SNAP_ADD failed: rc=%s\n", 
2456                         strerror(errno));
2457         }
2458  
2459         return rc;
2460 }
2461 static void signal_server(int sig)
2462 {
2463         if (sig == SIGINT) {
2464                 do_disconnect("sigint", 1);
2465                 exit(1);
2466         } else
2467                 fprintf(stderr, "%s: got signal %d\n", 
2468                         jt_cmdname("sigint"), sig);
2469 }
2470
2471 int obd_initialize(int argc, char **argv)
2472 {
2473         shmem_setup();
2474         register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH);
2475
2476         return 0;
2477 }
2478
2479
2480 void obd_finalize(int argc, char **argv)
2481 {
2482         struct sigaction sigact;
2483
2484         sigact.sa_handler = signal_server;
2485         sigfillset(&sigact.sa_mask);
2486         sigact.sa_flags = SA_RESTART;
2487         sigaction(SIGINT, &sigact, NULL);
2488
2489         if (jt_recording) {
2490                 printf("END RECORD\n");
2491                 jt_cfg_endrecord(argc, argv);
2492         }
2493
2494         do_disconnect(argv[0], 1);
2495 }