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