Whamcloud - gitweb
- Add create and destroy operations to lctl.
[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 #define printk printf
39
40 #include <linux/lustre_lib.h>
41 #include <linux/lustre_idl.h>
42 #include <linux/lustre_dlm.h>
43
44 #include <unistd.h>
45 #include <sys/un.h>
46 #include <time.h>
47 #include <sys/time.h>
48 #include <netinet/in.h>
49 #include <errno.h>
50 #include <string.h>
51
52 #include <asm/page.h>           /* needed for PAGE_SIZE - rread */
53
54 #define __KERNEL__
55 #include <linux/list.h>
56 #undef __KERNEL__
57
58 #include "obdctl.h"
59 #include "parser.h"
60 #include <stdio.h>
61
62 #define SHMEM_STATS 1
63 #if SHMEM_STATS
64 # include <sys/ipc.h>
65 # include <sys/shm.h>
66
67 # define MAX_SHMEM_COUNT 1024
68 static long long *shared_counters;
69 static long long counter_snapshot[2][MAX_SHMEM_COUNT];
70 struct timeval prev_time;
71 #endif
72
73 int fd = -1;
74 uint64_t conn_addr = -1;
75 uint64_t conn_cookie;
76 char rawbuf[8192];
77 char *buf = rawbuf;
78 int max = 8192;
79
80 static int thread;
81
82 static int getfd(char *func);
83 static char *cmdname(char *func);
84
85 #define IOCINIT(data)                                                   \
86 do {                                                                    \
87         memset(&data, 0, sizeof(data));                                 \
88         data.ioc_version = OBD_IOCTL_VERSION;                           \
89         data.ioc_addr = conn_addr;                                      \
90         data.ioc_cookie = conn_cookie;                                  \
91         data.ioc_len = sizeof(data);                                    \
92         if (fd < 0) {                                                   \
93                 fprintf(stderr, "No device open, use device\n");        \
94                 return 1;                                               \
95         }                                                               \
96 } while (0)
97
98 /*
99     pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L",
100     $obdo->{id}, 0,
101     $obdo->{gr}, 0,
102     $obdo->{atime}, 0,
103     $obdo->{mtime}, 0 ,
104     $obdo->{ctime}, 0,
105     $obdo->{size}, 0,
106     $obdo->{blocks}, 0,
107     $obdo->{blksize},
108     $obdo->{mode},
109     $obdo->{uid},
110     $obdo->{gid},
111     $obdo->{flags},
112     $obdo->{obdflags},
113     $obdo->{nlink},
114     $obdo->{generation},
115     $obdo->{valid},
116     $obdo->{inline},
117     $obdo->{obdmd},
118     0, 0, # struct list_head
119     0;  #  struct obd_ops
120 }
121
122 */
123
124 char *obdo_print(struct obdo *obd)
125 {
126         char buf[1024];
127
128         sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\n"
129                 "size: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\n"
130                 "gid: %d\nflags: %x\nobdflags: %x\nnlink: %d,\nvalid %x\n",
131                 obd->o_id,
132                 obd->o_gr,
133                 obd->o_atime,
134                 obd->o_mtime,
135                 obd->o_ctime,
136                 obd->o_size,
137                 obd->o_blocks,
138                 obd->o_blksize,
139                 obd->o_mode,
140                 obd->o_uid,
141                 obd->o_gid,
142                 obd->o_flags, obd->o_obdflags, obd->o_nlink, obd->o_valid);
143         return strdup(buf);
144 }
145
146
147
148 #define N2D_OFF 0x100      /* So we can tell between error codes and devices */
149
150 static int do_name2dev(char *func, char *name)
151 {
152         struct obd_ioctl_data data;
153         int rc;
154
155         if (getfd(func))
156                 return -1;
157
158         IOCINIT(data);
159
160         data.ioc_inllen1 = strlen(name) + 1;
161         data.ioc_inlbuf1 = name;
162
163         if (obd_ioctl_pack(&data, &buf, max)) {
164                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
165                 return -2;
166         }
167         rc = ioctl(fd, OBD_IOC_NAME2DEV, buf);
168         if (rc < 0) {
169                 fprintf(stderr, "error: %s: %s - %s\n", cmdname(func),
170                         name, strerror(rc = errno));
171                 return rc;
172         }
173
174         memcpy((char *)(&data), buf, sizeof(data));
175
176         return data.ioc_dev + N2D_OFF;
177 }
178
179 /*
180  * resolve a device name to a device number.
181  * supports a number or name.
182  * FIXME: support UUID
183  */
184 static int parse_devname(char * func, char *name)
185 {
186         int rc;
187         int ret = -1;
188
189         if (!name)
190                 return ret;
191         if (name[0] == '$') {
192                 rc = do_name2dev(func, name + 1);
193                 if (rc >= N2D_OFF) {
194                         ret = rc - N2D_OFF;
195                         printf("%s is device %d\n", name,
196                                ret);
197                 } else {
198                         fprintf(stderr, "error: %s: %s: %s\n", cmdname(func),
199                                 name, "device not found");
200                 }
201         } else
202                 ret = strtoul(name, NULL, 0);
203
204         return ret;
205 }
206
207 static char *cmdname(char *func)
208 {
209         static char buf[512];
210
211         if (thread) {
212                 sprintf(buf, "%s-%d", func, thread);
213                 return buf;
214         }
215
216         return func;
217 }
218
219 static int getfd(char *func)
220 {
221         if (fd == -1)
222                 fd = open("/dev/obd", O_RDWR);
223         if (fd == -1) {
224                 fprintf(stderr, "error: %s: opening /dev/obd: %s\n"
225                         "hint: lustre kernel modules may not be loaded.\n",
226                         cmdname(func), strerror(errno));
227                 return -1;
228         }
229         return 0;
230 }
231
232 #define difftime(a, b)                                          \
233         ((double)(a)->tv_sec - (b)->tv_sec +                    \
234          ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
235
236 static int be_verbose(int verbose, struct timeval *next_time,
237                       int num, int *next_num, int num_total)
238 {
239         struct timeval now;
240
241         if (!verbose)
242                 return 0;
243
244         if (next_time != NULL)
245                 gettimeofday(&now, NULL);
246
247         /* A positive verbosity means to print every X iterations */
248         if (verbose > 0 &&
249             (next_num == NULL || num >= *next_num || num >= num_total)) {
250                 *next_num += verbose;
251                 if (next_time) {
252                         next_time->tv_sec = now.tv_sec - verbose;
253                         next_time->tv_usec = now.tv_usec;
254                 }
255                 return 1;
256         }
257
258         /* A negative verbosity means to print at most each X seconds */
259         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0) {
260                 next_time->tv_sec = now.tv_sec - verbose;
261                 next_time->tv_usec = now.tv_usec;
262                 if (next_num)
263                         *next_num = num;
264                 return 1;
265         }
266
267         return 0;
268 }
269
270 static int get_verbose(const char *arg)
271 {
272         int verbose;
273
274         if (!arg || arg[0] == 'v')
275                 verbose = 1;
276         else if (arg[0] == 's' || arg[0] == 'q')
277                 verbose = 0;
278         else
279                 verbose = (int)strtoul(arg, NULL, 0);
280
281         if (verbose < 0)
282                 printf("Print status every %d seconds\n", -verbose);
283         else if (verbose == 1)
284                 printf("Print status every operation\n");
285         else if (verbose > 1)
286                 printf("Print status every %d operations\n", verbose);
287
288         return verbose;
289 }
290
291 int do_disconnect(char *func, int verbose)
292 {
293         int rc;
294         struct obd_ioctl_data data;
295
296         if (conn_addr == -1)
297                 return 0;
298
299         IOCINIT(data);
300
301         rc = ioctl(fd, OBD_IOC_DISCONNECT, &data);
302         if (rc < 0) {
303                 fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
304                         OBD_IOC_DISCONNECT, strerror(errno));
305         } else {
306                 if (verbose)
307                         printf("%s: disconnected conn %Lx\n", cmdname(func),
308                                conn_addr);
309                 conn_addr = -1;
310         }
311
312         return rc;
313 }
314
315 #if SHMEM_STATS
316 static void shmem_setup(void)
317 {
318         int shmid = shmget(IPC_PRIVATE, sizeof(counter_snapshot[0]), 0600);
319
320         if (shmid == -1) {
321                 fprintf(stderr, "Can't create shared memory counters: %s\n",
322                         strerror(errno));
323                 return;
324         }
325
326         shared_counters = (long long *)shmat(shmid, NULL, 0);
327
328         if (shared_counters == (long long *)(-1)) {
329                 fprintf(stderr, "Can't attach shared memory counters: %s\n",
330                         strerror(errno));
331                 shared_counters = NULL;
332                 return;
333         }
334 }
335
336 static inline void shmem_reset(void)
337 {
338         if (shared_counters == NULL)
339                 return;
340
341         memset(shared_counters, 0, sizeof(counter_snapshot[0]));
342         memset(counter_snapshot, 0, sizeof(counter_snapshot));
343         gettimeofday(&prev_time, NULL);
344 }
345
346 static inline void shmem_bump(void)
347 {
348         if (shared_counters == NULL || thread <= 0 || thread > MAX_SHMEM_COUNT)
349                 return;
350
351         shared_counters[thread - 1]++;
352 }
353
354 static void shmem_snap(int n)
355 {
356         struct timeval this_time;
357         int non_zero = 0;
358         long long total = 0;
359         double secs;
360         int i;
361
362         if (shared_counters == NULL || n > MAX_SHMEM_COUNT)
363                 return;
364
365         memcpy(counter_snapshot[1], counter_snapshot[0],
366                n * sizeof(counter_snapshot[0][0]));
367         memcpy(counter_snapshot[0], shared_counters,
368                n * sizeof(counter_snapshot[0][0]));
369         gettimeofday(&this_time, NULL);
370
371         for (i = 0; i < n; i++) {
372                 long long this_count =
373                         counter_snapshot[0][i] - counter_snapshot[1][i];
374
375                 if (this_count != 0) {
376                         non_zero++;
377                         total += this_count;
378                 }
379         }
380
381         secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
382                 (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
383
384         printf("%d/%d Total: %f/second\n", non_zero, n, total / secs);
385
386         prev_time = this_time;
387 }
388
389 #define SHMEM_SETUP()   shmem_setup()
390 #define SHMEM_RESET()   shmem_reset()
391 #define SHMEM_BUMP()    shmem_bump()
392 #define SHMEM_SNAP(n)   shmem_snap(n)
393 #else
394 #define SHMEM_SETUP()
395 #define SHMEM_RESET()
396 #define SHMEM_BUMP()
397 #define SHMEM_SNAP(n)
398 #endif
399
400 extern command_t cmdlist[];
401
402 static int do_device(char *func, int dev)
403 {
404         struct obd_ioctl_data data;
405
406         memset(&data, 0, sizeof(data));
407
408         data.ioc_dev = dev;
409
410         if (getfd(func))
411                 return -1;
412
413         if (obd_ioctl_pack(&data, &buf, max)) {
414                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
415                 return -2;
416         }
417
418         return ioctl(fd, OBD_IOC_DEVICE, buf);
419 }
420
421 int jt_obd_device(int argc, char **argv)
422 {
423         int rc, dev;
424         do_disconnect(argv[0], 1);
425
426         if (argc != 2)
427                 return CMD_HELP;
428
429         dev = parse_devname(argv[0], argv[1]);
430         if (dev < 0)
431                 return -1;
432
433         rc = do_device(argv[0], dev);
434         if (rc < 0)
435                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
436                         strerror(rc = errno));
437
438         return rc;
439 }
440
441 int jt_obd_connect(int argc, char **argv)
442 {
443         struct obd_ioctl_data data;
444         int rc;
445
446         IOCINIT(data);
447
448         do_disconnect(argv[0], 1);
449
450 #warning Robert: implement timeout per lctl usage for probe
451         if (argc != 1)
452                 return CMD_HELP;
453
454         rc = ioctl(fd, OBD_IOC_CONNECT, &data);
455         if (rc < 0)
456                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
457                         OBD_IOC_CONNECT, strerror(rc = errno));
458         else {
459                 conn_addr = data.ioc_addr;
460                 conn_cookie = data.ioc_cookie;
461         }
462         return rc;
463 }
464
465 int jt_obd_disconnect(int argc, char **argv)
466 {
467         if (argc != 1)
468                 return CMD_HELP;
469
470         if (conn_addr == -1)
471                 return 0;
472
473         return do_disconnect(argv[0], 0);
474 }
475
476 int jt_opt_device(int argc, char **argv)
477 {
478         char *arg2[3];
479         int ret;
480         int rc;
481
482         if (argc < 3) {
483                 fprintf(stderr, "usage: %s devno <command [args ...]>\n",
484                         cmdname(argv[0]));
485                 return -1;
486         }
487
488         rc = do_device("device", parse_devname(argv[0], argv[1]));
489
490         if (!rc) {
491                 arg2[0] = "connect";
492                 arg2[1] = NULL;
493                 rc = jt_obd_connect(1, arg2);
494         }
495
496         if (!rc)
497                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
498
499         ret = do_disconnect(argv[0], 0);
500         if (!rc)
501                 rc = ret;
502
503         return rc;
504 }
505
506 int jt_opt_threads(int argc, char **argv)
507 {
508         int threads, next_thread;
509         int verbose;
510         int rc = 0;
511         int i;
512
513         if (argc < 5) {
514                 fprintf(stderr,
515                         "usage: %s numthreads verbose devno <cmd [args ...]>\n",
516                         argv[0]);
517                 return -1;
518         }
519
520         threads = strtoul(argv[1], NULL, 0);
521
522         verbose = get_verbose(argv[2]);
523
524         if (verbose != 0)
525                 printf("%s: starting %d threads on device %s running %s\n",
526                        argv[0], threads, argv[3], argv[4]);
527
528         SHMEM_RESET();
529
530         for (i = 1, next_thread = verbose; i <= threads; i++) {
531                 rc = fork();
532                 if (rc < 0) {
533                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
534                                 strerror(rc = errno));
535                         break;
536                 } else if (rc == 0) {
537                         thread = i;
538                         argv[2] = "--device";
539                         return jt_opt_device(argc - 2, argv + 2);
540                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
541                         printf("%s: thread #%d (PID %d) started\n",
542                                argv[0], i, rc);
543                 rc = 0;
544         }
545
546         if (!thread) {          /* parent process */
547                 int live_threads = threads;
548
549                 while (live_threads > 0) {
550                         int status;
551                         pid_t ret;
552
553                         ret = waitpid(0, &status, verbose < 0 ? WNOHANG : 0);
554                         if (ret == 0) {
555                                 if (verbose >= 0)
556                                         abort();
557
558                                 sleep(-verbose);
559                                 SHMEM_SNAP(threads);
560                                 continue;
561                         }
562
563                         if (ret < 0) {
564                                 fprintf(stderr, "error: %s: wait - %s\n",
565                                         argv[0], strerror(errno));
566                                 if (!rc)
567                                         rc = errno;
568                         } else {
569                                 /*
570                                  * This is a hack.  We _should_ be able to use
571                                  * WIFEXITED(status) to see if there was an
572                                  * error, but it appears to be broken and it
573                                  * always returns 1 (OK).  See wait(2).
574                                  */
575                                 int err = WEXITSTATUS(status);
576                                 if (err)
577                                         fprintf(stderr,
578                                                 "%s: PID %d had rc=%d\n",
579                                                 argv[0], ret, err);
580                                 if (!rc)
581                                         rc = err;
582
583                                 live_threads--;
584                         }
585                 }
586         }
587
588         return rc;
589 }
590
591 int jt_obd_detach(int argc, char **argv)
592 {
593         struct obd_ioctl_data data;
594         int rc;
595
596         IOCINIT(data);
597
598         if (argc != 1)
599                 return CMD_HELP;
600
601         if (obd_ioctl_pack(&data, &buf, max)) {
602                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
603                 return -2;
604         }
605
606         rc = ioctl(fd, OBD_IOC_DETACH, buf);
607         if (rc < 0)
608                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
609                         strerror(rc = errno));
610
611         return rc;
612 }
613
614 int jt_obd_cleanup(int argc, char **argv)
615 {
616         struct obd_ioctl_data data;
617         int rc;
618
619         IOCINIT(data);
620
621         if (argc != 1)
622                 return CMD_HELP;
623
624         rc = ioctl(fd, OBD_IOC_CLEANUP, &data);
625         if (rc < 0)
626                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
627                         strerror(rc = errno));
628
629         return rc;
630 }
631
632 int jt_obd_newdev(int argc, char **argv)
633 {
634         int rc;
635         struct obd_ioctl_data data;
636
637         if (getfd(argv[0]))
638                 return -1;
639
640         IOCINIT(data);
641
642         if (argc != 1)
643                 return CMD_HELP;
644
645         rc = ioctl(fd, OBD_IOC_NEWDEV, &data);
646         if (rc < 0)
647                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
648                         strerror(rc = errno));
649         else {
650                 printf("Current device set to %d\n", data.ioc_dev);
651         }
652
653         return rc;
654 }
655
656 int jt_obd_list(int argc, char **argv)
657 {
658         int rc;
659         char buf[1024];
660         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
661
662         if (getfd(argv[0]))
663                 return -1;
664
665         memset(buf, 0, sizeof(buf));
666         data->ioc_version = OBD_IOCTL_VERSION;
667         data->ioc_addr = conn_addr;
668         data->ioc_cookie = conn_addr;
669         data->ioc_len = sizeof(buf);
670         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
671
672         if (argc != 1)
673                 return CMD_HELP;
674
675         rc = ioctl(fd, OBD_IOC_LIST, data);
676         if (rc < 0)
677                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
678                         strerror(rc = errno));
679         else {
680                 printf("%s", data->ioc_bulk);
681         }
682
683         return rc;
684 }
685
686 int jt_obd_attach(int argc, char **argv)
687 {
688         struct obd_ioctl_data data;
689         int rc;
690
691         IOCINIT(data);
692
693         if (argc != 2 && argc != 3 && argc != 4)
694                 return CMD_HELP;
695
696         data.ioc_inllen1 = strlen(argv[1]) + 1;
697         data.ioc_inlbuf1 = argv[1];
698         if (argc >= 3) {
699                 data.ioc_inllen2 = strlen(argv[2]) + 1;
700                 data.ioc_inlbuf2 = argv[2];
701         }
702
703         if (argc == 4) {
704                 data.ioc_inllen3 = strlen(argv[3]) + 1;
705                 data.ioc_inlbuf3 = argv[3];
706         }
707
708         if (obd_ioctl_pack(&data, &buf, max)) {
709                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
710                 return -2;
711         }
712
713         rc = ioctl(fd, OBD_IOC_ATTACH, buf);
714         if (rc < 0)
715                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
716                         OBD_IOC_ATTACH, strerror(rc = errno));
717         else if (argc == 3) {
718                 char name[1024];
719                 if (strlen(argv[2]) > 128) {
720                         printf("Name too long to set environment\n");
721                         return -EINVAL;
722                 }
723                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
724                 rc = setenv(name, argv[1], 1);
725                 if (rc) {
726                         printf("error setting env variable %s\n", name);
727                 }
728         }
729
730         return rc;
731 }
732
733 int jt_obd_name2dev(int argc, char **argv)
734 {
735         int rc;
736
737         if (argc != 2)
738                 return CMD_HELP;
739
740         rc = do_name2dev(argv[0], argv[1]);
741         if (rc >= N2D_OFF) {
742                 int dev = rc - N2D_OFF;
743                 rc = do_device(argv[0], dev);
744                 if (rc == 0)
745                         printf("%d\n", dev);
746         }
747         return rc;
748 }
749
750 int jt_obd_setup(int argc, char **argv)
751 {
752         struct obd_ioctl_data data;
753         int rc;
754
755         IOCINIT(data);
756
757         if (argc > 3)
758                 return CMD_HELP;
759
760         data.ioc_dev = -1;
761         if (argc > 1) {
762                 data.ioc_dev = parse_devname(argv[0], argv[1]);
763                 if (data.ioc_dev < 0)
764                         return -1;
765                 data.ioc_inllen1 = strlen(argv[1]) + 1;
766                 data.ioc_inlbuf1 = argv[1];
767         }
768         if (argc == 3) {
769                 data.ioc_inllen2 = strlen(argv[2]) + 1;
770                 data.ioc_inlbuf2 = argv[2];
771         }
772
773         if (obd_ioctl_pack(&data, &buf, max)) {
774                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
775                 return -2;
776         }
777         rc = ioctl(fd, OBD_IOC_SETUP, buf);
778         if (rc < 0)
779                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
780                         strerror(rc = errno));
781
782         return rc;
783 }
784
785
786 int jt_obd_create(int argc, char **argv)
787 {
788         struct obd_ioctl_data data;
789         struct timeval next_time;
790         int count = 1, next_count;
791         int verbose = 1;
792         int rc = 0, i;
793
794         IOCINIT(data);
795         if (argc < 2 || argc > 4)
796                 return CMD_HELP;
797
798         count = strtoul(argv[1], NULL, 0);
799
800         if (argc > 2)
801                 data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0);
802         else
803                 data.ioc_obdo1.o_mode = 0100644;
804         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
805
806         if (argc > 3)
807                 verbose = get_verbose(argv[3]);
808
809         printf("%s: %d objects\n", cmdname(argv[0]), count);
810         gettimeofday(&next_time, NULL);
811         next_time.tv_sec -= verbose;
812
813         for (i = 1, next_count = verbose; i <= count; i++) {
814                 rc = ioctl(fd, OBD_IOC_CREATE, &data);
815                 SHMEM_BUMP();
816                 if (rc < 0) {
817                         fprintf(stderr, "error: %s: #%d - %s\n",
818                                 cmdname(argv[0]), i, strerror(rc = errno));
819                         break;
820                 }
821                 if (be_verbose(verbose, &next_time, i, &next_count, count))
822                         printf("%s: #%d is object id %Ld\n", cmdname(argv[0]),
823                                i, data.ioc_obdo1.o_id);
824         }
825         return rc;
826 }
827
828 int jt_obd_setattr(int argc, char **argv)
829 {
830         struct obd_ioctl_data data;
831         int rc;
832
833         IOCINIT(data);
834         if (argc != 2)
835                 return CMD_HELP;
836
837         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
838         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], NULL, 0);
839         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
840
841         rc = ioctl(fd, OBD_IOC_SETATTR, &data);
842         if (rc < 0)
843                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
844                         strerror(rc = errno));
845
846         return rc;
847 }
848
849 int jt_obd_destroy(int argc, char **argv)
850 {
851         struct obd_ioctl_data data;
852         int rc;
853
854         IOCINIT(data);
855         if (argc != 2)
856                 return CMD_HELP;
857
858         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
859         data.ioc_obdo1.o_mode = S_IFREG | 0644;
860
861         rc = ioctl(fd, OBD_IOC_DESTROY, &data);
862         if (rc < 0)
863                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
864                         strerror(rc = errno));
865
866         return rc;
867 }
868
869 int jt_obd_getattr(int argc, char **argv)
870 {
871         struct obd_ioctl_data data;
872         int rc;
873
874         if (argc != 2)
875                 return CMD_HELP;
876
877         IOCINIT(data);
878         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
879         /* to help obd filter */
880         data.ioc_obdo1.o_mode = 0100644;
881         data.ioc_obdo1.o_valid = 0xffffffff;
882         printf("%s: object id %Ld\n", cmdname(argv[0]), data.ioc_obdo1.o_id);
883
884         rc = ioctl(fd, OBD_IOC_GETATTR, &data);
885         if (rc) {
886                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
887                         strerror(rc = errno));
888         } else {
889                 printf("%s: object id %Ld, mode %o\n", cmdname(argv[0]),
890                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
891         }
892         return rc;
893 }
894
895 int jt_obd_test_getattr(int argc, char **argv)
896 {
897         struct obd_ioctl_data data;
898         struct timeval start, next_time;
899         int i, count, next_count;
900         int verbose;
901         int rc = 0;
902
903         if (argc != 2 && argc != 3)
904                 return CMD_HELP;
905
906         IOCINIT(data);
907         count = strtoul(argv[1], NULL, 0);
908
909         if (argc == 3)
910                 verbose = get_verbose(argv[2]);
911         else
912                 verbose = 1;
913
914         data.ioc_obdo1.o_valid = 0xffffffff;
915         data.ioc_obdo1.o_id = 2;
916         gettimeofday(&start, NULL);
917         next_time.tv_sec = start.tv_sec - verbose;
918         next_time.tv_usec = start.tv_usec;
919         if (verbose != 0)
920                 printf("%s: getting %d attrs (testing only): %s",
921                        cmdname(argv[0]), count, ctime(&start.tv_sec));
922
923         for (i = 1, next_count = verbose; i <= count; i++) {
924                 rc = ioctl(fd, OBD_IOC_GETATTR, &data);
925                 SHMEM_BUMP();
926                 if (rc < 0) {
927                         fprintf(stderr, "error: %s: #%d - %s\n",
928                                 cmdname(argv[0]), i, strerror(rc = errno));
929                         break;
930                 } else {
931                         if (be_verbose
932                             (verbose, &next_time, i, &next_count, count))
933                                 printf("%s: got attr #%d\n", cmdname(argv[0]),
934                                        i);
935                 }
936         }
937
938         if (!rc) {
939                 struct timeval end;
940                 double diff;
941
942                 gettimeofday(&end, NULL);
943
944                 diff = difftime(&end, &start);
945
946                 --i;
947                 if (verbose != 0)
948                         printf("%s: %d attrs in %.4gs (%.4g attr/s): %s",
949                                cmdname(argv[0]), i, diff, (double)i / diff,
950                                ctime(&end.tv_sec));
951         }
952         return rc;
953 }
954
955 int jt_obd_test_brw(int argc, char **argv)
956 {
957         struct obd_ioctl_data data;
958         struct timeval start, next_time;
959         int pages = 1, objid = 3, count, next_count;
960         int verbose = 1, write = 0, rw;
961         long long offset;
962         int i;
963         int len;
964         int rc = 0;
965
966         if (argc < 2 || argc > 6)
967                 return CMD_HELP;
968
969         count = strtoul(argv[1], NULL, 0);
970
971         if (argc >= 3) {
972                 if (argv[2][0] == 'w' || argv[2][0] == '1')
973                         write = 1;
974                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
975                         write = 0;
976
977                 verbose = get_verbose(argv[3]);
978         }
979
980         if (argc >= 5)
981                 pages = strtoul(argv[4], NULL, 0);
982         if (argc >= 6)
983                 objid = strtoul(argv[5], NULL, 0);
984
985         len = pages * PAGE_SIZE;
986
987         IOCINIT(data);
988         data.ioc_obdo1.o_id = objid;
989         data.ioc_count = len;
990         data.ioc_offset = 0;
991
992         gettimeofday(&start, NULL);
993         next_time.tv_sec = start.tv_sec - verbose;
994         next_time.tv_usec = start.tv_usec;
995
996         if (verbose != 0)
997                 printf("%s: %s %dx%d pages (testing only): %s",
998                        cmdname(argv[0]), write ? "writing" : "reading",
999                        count, pages, ctime(&start.tv_sec));
1000
1001         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1002         for (i = 1, next_count = verbose, offset = 0; i <= count; i++) {
1003                 rc = ioctl(fd, rw, &data);
1004                 SHMEM_BUMP();
1005                 if (rc) {
1006                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1007                                 cmdname(argv[0]), i, strerror(rc = errno),
1008                                 write ? "write" : "read");
1009                         break;
1010                 } else if (be_verbose
1011                            (verbose, &next_time, i, &next_count, count))
1012                         printf("%s: %s number %d\n", cmdname(argv[0]),
1013                                write ? "write" : "read", i);
1014
1015                 data.ioc_offset += len;
1016         }
1017
1018         if (!rc) {
1019                 struct timeval end;
1020                 double diff;
1021
1022                 gettimeofday(&end, NULL);
1023
1024                 diff = difftime(&end, &start);
1025
1026                 --i;
1027                 if (verbose != 0)
1028                         printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s",
1029                                cmdname(argv[0]), write ? "wrote" : "read",
1030                                i, pages, diff, (double)i * pages / diff,
1031                                ctime(&end.tv_sec));
1032         }
1033         return rc;
1034 }
1035
1036 int jt_obd_lov_config(int argc, char **argv)
1037 {
1038         struct obd_ioctl_data data;
1039         struct lov_desc desc;
1040         uuid_t *uuidarray;
1041         int rc, size, i;
1042         IOCINIT(data);
1043
1044         if (argc <= 6)
1045                 return CMD_HELP;
1046
1047         if (strlen(argv[1]) > sizeof(uuid_t) - 1) {
1048                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n",
1049                         strlen(argv[1]));
1050                 return -ENOMEM;
1051         }
1052
1053         memset(&desc, 0, sizeof(desc));
1054         strcpy(desc.ld_uuid, argv[1]);
1055         desc.ld_default_stripe_count = strtoul(argv[2], NULL, 0);
1056         desc.ld_default_stripe_size = strtoul(argv[3], NULL, 0);
1057         desc.ld_default_stripe_offset = (__u64) strtoul(argv[4], NULL, 0);
1058         desc.ld_pattern = strtoul(argv[5], NULL, 0);
1059         desc.ld_tgt_count = argc - 6;
1060
1061
1062         size = sizeof(uuid_t) * desc.ld_tgt_count;
1063         uuidarray = malloc(size);
1064         if (!uuidarray) {
1065                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", size);
1066                 return -ENOMEM;
1067         }
1068         memset(uuidarray, 0, size);
1069         for (i = 6; i < argc; i++) {
1070                 char *buf = (char *)(uuidarray + i - 6);
1071                 if (strlen(argv[i]) >= sizeof(uuid_t)) {
1072                         fprintf(stderr, "lov_config: arg %d (%s) too long\n",
1073                                 i, argv[i]);
1074                         free(uuidarray);
1075                         return -EINVAL;
1076                 }
1077                 strcpy(buf, argv[i]);
1078         }
1079
1080         data.ioc_inllen1 = sizeof(desc);
1081         data.ioc_inlbuf1 = (char *)&desc;
1082         data.ioc_inllen2 = size;
1083         data.ioc_inlbuf2 = (char *)uuidarray;
1084
1085         if (obd_ioctl_pack(&data, &buf, max)) {
1086                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1087                 return -EINVAL;
1088         }
1089
1090         rc = ioctl(fd, OBD_IOC_LOV_CONFIG, buf);
1091         if (rc)
1092                 fprintf(stderr, "lov_config: error: %s: %s\n",
1093                         cmdname(argv[0]), strerror(rc = errno));
1094         free(uuidarray);
1095         return rc;
1096 }
1097
1098 int jt_obd_test_ldlm(int argc, char **argv)
1099 {
1100         struct obd_ioctl_data data;
1101         int rc;
1102
1103         IOCINIT(data);
1104         if (argc != 1)
1105                 return CMD_HELP;
1106
1107         rc = ioctl(fd, IOC_LDLM_TEST, &data);
1108         if (rc)
1109                 fprintf(stderr, "error: %s: test failed: %s\n",
1110                         cmdname(argv[0]), strerror(rc = errno));
1111         return rc;
1112 }
1113
1114 int jt_obd_dump_ldlm(int argc, char **argv)
1115 {
1116         struct obd_ioctl_data data;
1117         int rc;
1118
1119         IOCINIT(data);
1120         if (argc != 1)
1121                 return CMD_HELP;
1122
1123         rc = ioctl(fd, IOC_LDLM_DUMP, &data);
1124         if (rc)
1125                 fprintf(stderr, "error: %s failed: %s\n",
1126                         cmdname(argv[0]), strerror(rc = errno));
1127         return rc;
1128 }
1129
1130 int jt_obd_ldlm_regress_start(int argc, char **argv)
1131 {
1132         int rc;
1133         struct obd_ioctl_data data;
1134
1135         IOCINIT(data);
1136
1137         if (argc > 2)
1138                 return CMD_HELP;
1139
1140         if (argc == 2) {
1141                 data.ioc_inllen1 =  strlen(argv[1]) + 1;
1142                 data.ioc_inlbuf1 = argv[1];
1143         } else {
1144                 data.ioc_inllen1 = 0;
1145         }
1146
1147         if (obd_ioctl_pack(&data, &buf, max)) {
1148                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1149                 return -2;
1150         }
1151
1152         rc = ioctl(fd, IOC_LDLM_REGRESS_START, buf);
1153
1154         if (rc)
1155                 fprintf(stderr, "error: %s: test failed: %s\n",
1156                         cmdname(argv[0]), strerror(rc = errno));
1157
1158         return rc;
1159 }
1160
1161 int jt_obd_ldlm_regress_stop(int argc, char **argv)
1162 {
1163         int rc;
1164         struct obd_ioctl_data data;
1165         IOCINIT(data);
1166
1167         if (argc != 1)
1168                 return CMD_HELP;
1169
1170         rc = ioctl(fd, IOC_LDLM_REGRESS_STOP, &data);
1171
1172         if (rc)
1173                 fprintf(stderr, "error: %s: test failed: %s\n",
1174                         cmdname(argv[0]), strerror(rc = errno));
1175         return rc;
1176 }
1177
1178 int jt_obd_newconn(int argc, char **argv)
1179 {
1180         int rc;
1181         struct obd_ioctl_data data;
1182
1183         IOCINIT(data);
1184         if (argc != 1)
1185                 return CMD_HELP;
1186
1187         rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN, &data);
1188         if (rc < 0)
1189                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1190                         strerror(rc = errno));
1191
1192         return rc;
1193 }
1194
1195 static void signal_server(int sig)
1196 {
1197         if (sig == SIGINT) {
1198                 do_disconnect("sigint", 1);
1199                 exit(1);
1200         } else
1201                 fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
1202 }
1203
1204 int obd_initialize(int argc, char **argv)
1205 {
1206         SHMEM_SETUP();
1207         return 0;
1208 }
1209
1210
1211 void obd_cleanup(int argc, char **argv)
1212 {
1213         struct sigaction sigact;
1214
1215         sigact.sa_handler = signal_server;
1216         sigfillset(&sigact.sa_mask);
1217         sigact.sa_flags = SA_RESTART;
1218         sigaction(SIGINT, &sigact, NULL);
1219
1220         do_disconnect(argv[0], 1);
1221 }