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