Whamcloud - gitweb
- Make now correctly rebuilds
[fs/lustre-release.git] / lustre / utils / device.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: Brian Behlendorf <behlendorf1@llnl.gov> 
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26 #include <stdlib.h>
27 #include <sys/ioctl.h>
28 #include <fcntl.h>
29 #include <sys/socket.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <sys/stat.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <signal.h>
36 #define printk printf
37
38
39 #include <linux/lustre_lib.h>
40 #include <linux/lustre_idl.h>
41 #include <linux/lustre_dlm.h>
42
43 #include <unistd.h>
44 #include <sys/un.h>
45 #include <time.h>
46 #include <sys/time.h>
47 #include <netinet/in.h>
48 #include <errno.h>
49 #include <string.h>
50 #include <asm/page.h>   /* needed for PAGE_SIZE - rread*/ 
51
52 #include "parser.h"
53 #include "lctl.h"
54
55 #define __KERNEL__
56 #include <linux/list.h>
57 #undef __KERNEL__
58
59 static int fd = -1;
60 static uint64_t conn_addr = -1;
61 static uint64_t conn_cookie;
62 static char rawbuf[8192];
63 static char *buf = rawbuf;
64 static int max = 8192;
65 static int rc = 0;
66
67 #if 0
68 static int thread;
69 #endif
70
71 int device_setup(int argc, char **argv) {
72         return 0;
73 }
74
75 /* Misc support functions */
76 static int be_verbose(int verbose, struct timeval *next_time,
77                       int num, int *next_num, int num_total) {
78         struct timeval now;
79
80         if (!verbose)
81                 return 0;
82
83         if (next_time != NULL)
84                 gettimeofday(&now, NULL);
85
86         /* A positive verbosity means to print every X iterations */
87         if (verbose > 0 &&
88             (next_num == NULL || num >= *next_num || num >= num_total)) {
89                 *next_num += verbose;
90                 if (next_time) {
91                         next_time->tv_sec = now.tv_sec - verbose;
92                         next_time->tv_usec = now.tv_usec;
93                 }
94                 return 1;
95         }
96
97         /* A negative verbosity means to print at most each X seconds */
98         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
99                 next_time->tv_sec = now.tv_sec - verbose;
100                 next_time->tv_usec = now.tv_usec;
101                 if (next_num)
102                         *next_num = num;
103                 return 1;
104         }
105
106         return 0;
107 }
108
109 static int get_verbose(const char *arg) {
110         int verbose;
111
112         if (!arg || arg[0] == 'v')
113                 verbose = 1;
114         else if (arg[0] == 's' || arg[0] == 'q')
115                 verbose = 0;
116         else
117                 verbose = (int) strtoul(arg, NULL, 0);
118
119         if (verbose < 0)
120                 printf("Print status every %d seconds\n", -verbose);
121         else if (verbose == 1)
122                 printf("Print status every operation\n");
123         else if (verbose > 1)
124                 printf("Print status every %d operations\n", verbose);
125
126         return verbose;
127 }
128
129 #if 0
130 /* pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L" */
131 static char * obdo_print(struct obdo *obd)
132 {
133         char buf[1024];
134
135         sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\n"
136                 "size: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\n"
137                 "gid: %d\nflags: %x\nobdflags: %x\nnlink: %d,\nvalid %x\n",
138                 obd->o_id,
139                 obd->o_gr,
140                 obd->o_atime,
141                 obd->o_mtime,
142                 obd->o_ctime,
143                 obd->o_size,
144                 obd->o_blocks,
145                 obd->o_blksize,
146                 obd->o_mode,
147                 obd->o_uid,
148                 obd->o_gid,
149                 obd->o_flags,
150                 obd->o_obdflags,
151                 obd->o_nlink,
152                 obd->o_valid);
153         return strdup(buf);
154 }
155 #endif
156
157 /* Device selection commands */
158 int jt_dev_newdev(int argc, char **argv) {
159         struct obd_ioctl_data data;
160
161         LUSTRE_CONNECT(argv[0]);
162         IOCINIT(data);
163
164         if (argc != 1)
165                 return CMD_HELP;
166
167         rc = ioctl(fd, OBD_IOC_NEWDEV , &data);
168         if (rc < 0)
169                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
170                         strerror(rc=errno));
171         else {
172                 printf("Current device set to %d\n", data.ioc_dev);
173         }
174
175         return rc;
176 }
177
178 static int do_device(char *func, int dev) {
179         struct obd_ioctl_data data;
180
181         memset(&data, 0, sizeof(data));
182         data.ioc_dev = dev;
183         LUSTRE_CONNECT(func);
184
185         if (obd_ioctl_pack(&data, &buf, max)) {
186                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
187                 return -2;
188         }
189
190         return ioctl(fd, OBD_IOC_DEVICE , buf);
191 }
192
193 int jt_dev_device(int argc, char **argv) {
194         do_disconnect(argv[0], 1);
195
196         if (argc != 2)
197                 return CMD_HELP;
198
199         rc = do_device(argv[0], strtoul(argv[1], NULL, 0));
200         if (rc < 0)
201                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
202                         strerror(rc = errno));
203
204         return rc;
205 }
206
207 static int do_uuid2dev(char *func, char *name) {
208         return 0;
209 }
210
211 int jt_dev_uuid2dev(int argc, char **argv) {
212         do_uuid2dev(NULL, NULL);
213         return 0;
214 }
215
216 static int do_name2dev(char *func, char *name) {
217         struct obd_ioctl_data data;
218
219         LUSTRE_CONNECT(func);
220         IOCINIT(data);
221
222         data.ioc_inllen1 = strlen(name) + 1;
223         data.ioc_inlbuf1 = name;
224
225         if (obd_ioctl_pack(&data, &buf, max)) {
226                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
227                 return -2;
228         }
229         rc = ioctl(fd, OBD_IOC_NAME2DEV , buf);
230         if (rc < 0) {
231                 fprintf(stderr, "error: %s: %s - %s\n", cmdname(func),
232                         name, strerror(rc = errno));
233                 return rc;
234         }
235
236         memcpy((char *)(&data), buf, sizeof(data));
237
238         return data.ioc_dev + N2D_OFF;
239 }
240
241 int jt_dev_name2dev(int argc, char **argv) {
242
243         if (argc != 2)
244                 return CMD_HELP;
245
246         rc = do_name2dev(argv[0], argv[1]);
247         if (rc >= N2D_OFF) {
248                 int dev = rc - N2D_OFF;
249                 rc = do_device(argv[0], dev);
250                 if (rc == 0)
251                         printf("%d\n", dev);
252         }
253         return rc;
254 }
255
256 int jt_dev_list(int argc, char **argv) {
257         char buf[1024];
258         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
259
260         LUSTRE_CONNECT(argv[0]);
261         memset(buf, 0, sizeof(buf));
262         data->ioc_version = OBD_IOCTL_VERSION;
263         data->ioc_addr = conn_addr;
264         data->ioc_cookie = conn_addr;
265         data->ioc_len = sizeof(buf);
266         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
267
268         if (argc != 1)
269                 return CMD_HELP;
270                 
271         rc = ioctl(fd, OBD_IOC_LIST , data);
272         if (rc < 0)
273                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
274                         strerror(rc=errno));
275         else {
276                 printf("%s", data->ioc_bulk);
277         }
278
279         return rc;
280 }
281
282 /* Device configuration commands */
283 int do_disconnect(char *func, int verbose) {
284         struct obd_ioctl_data data;
285
286         if (conn_addr == -1) 
287                 return 0; 
288
289         IOCINIT(data);
290
291         rc = ioctl(fd, OBD_IOC_DISCONNECT , &data);
292         if (rc < 0) {
293                 fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
294                         OBD_IOC_DISCONNECT, strerror(errno));
295         } else {
296                 if (verbose)
297                         printf("%s: disconnected conn %Lx\n", cmdname(func),
298                                conn_addr);
299                 conn_addr = -1;
300         }
301
302         return rc;
303 }
304
305 #if 0
306 static int jt_dev_newconn(int argc, char **argv)
307 {
308         struct obd_ioctl_data data;
309
310         IOCINIT(data);
311         if (argc != 1) {
312                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
313                 return -1;
314         }
315
316         rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN , &data);
317         if (rc < 0)
318                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
319                         strerror(rc = errno));
320
321         return rc;
322 }
323 #endif
324
325 int jt_dev_probe(int argc, char **argv) {
326         struct obd_ioctl_data data;
327
328         IOCINIT(data);
329         do_disconnect(argv[0], 1);
330
331         if (argc != 1)
332                 return CMD_HELP;
333
334         rc = ioctl(fd, OBD_IOC_CONNECT , &data);
335         if (rc < 0)
336                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
337                         OBD_IOC_CONNECT, strerror(rc = errno));
338         else
339                 conn_addr = data.ioc_addr;
340                 conn_cookie = data.ioc_cookie;
341         return rc;
342 }
343
344 int jt_dev_close(int argc, char **argv) {
345         if (argc != 1)
346                 return CMD_HELP;
347
348         if (conn_addr == -1)
349                 return 0;
350
351         return do_disconnect(argv[0], 0);
352 }
353
354 #if 0
355 static int jt__device(int argc, char **argv)
356 {
357         char *arg2[3];
358         int ret;
359
360         if (argc < 3) {
361                 fprintf(stderr, "usage: %s devno <command [args ...]>\n",
362                         cmdname(argv[0]));
363                 return -1;
364         }
365
366         rc = do_device("device", strtoul(argv[1], NULL, 0));
367
368         if (!rc) {
369                 arg2[0] = "connect";
370                 arg2[1] = NULL;
371                 rc = jt_connect(1, arg2);
372         }
373
374         if (!rc)
375                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
376
377         ret = do_disconnect(argv[0], 0);
378         if (!rc)
379                 rc = ret;
380
381         return rc;
382 }
383
384 static int jt__threads(int argc, char **argv)
385 {
386         int threads, next_thread;
387         int verbose;
388         int i, j;
389
390         if (argc < 5) {
391                 fprintf(stderr,
392                         "usage: %s numthreads verbose devno <cmd [args ...]>\n",
393                         argv[0]);
394                 return -1;
395         }
396
397         threads = strtoul(argv[1], NULL, 0);
398
399         verbose = get_verbose(argv[2]);
400
401         printf("%s: starting %d threads on device %s running %s\n",
402                argv[0], threads, argv[3], argv[4]);
403
404         for (i = 1, next_thread = verbose; i <= threads; i++) {
405                 rc = fork();
406                 if (rc < 0) {
407                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
408                                 strerror(rc = errno));
409                         break;
410                 } else if (rc == 0) {
411                         thread = i;
412                         argv[2] = "--device";
413                         return jt__device(argc - 2, argv + 2);
414                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
415                         printf("%s: thread #%d (PID %d) started\n",
416                                argv[0], i, rc);
417                 rc = 0;
418         }
419
420         if (!thread) { /* parent process */
421                 if (!verbose)
422                         printf("%s: started %d threads\n\n", argv[0], i - 1);
423                 else
424                         printf("\n");
425
426                 for (j = 1; j < i; j++) {
427                         int status;
428                         int ret = wait(&status);
429
430                         if (ret < 0) {
431                                 fprintf(stderr, "error: %s: wait - %s\n",
432                                         argv[0], strerror(errno));
433                                 if (!rc)
434                                         rc = errno;
435                         } else {
436                                 /*
437                                  * This is a hack.  We _should_ be able to use
438                                  * WIFEXITED(status) to see if there was an
439                                  * error, but it appears to be broken and it
440                                  * always returns 1 (OK).  See wait(2).
441                                  */
442                                 int err = WEXITSTATUS(status);
443                                 if (err)
444                                         fprintf(stderr,
445                                                 "%s: PID %d had rc=%d\n",
446                                                 argv[0], ret, err);
447                                 if (!rc)
448                                         rc = err;
449                         }
450                 }
451         }
452
453         return rc;
454 }
455 #endif
456
457 int jt_dev_attach(int argc, char **argv) {
458         struct obd_ioctl_data data;
459
460         IOCINIT(data);
461         if (argc != 2 && argc != 3 && argc != 4)
462                 return CMD_HELP;
463
464         data.ioc_inllen1 =  strlen(argv[1]) + 1;
465         data.ioc_inlbuf1 = argv[1];
466         if (argc >= 3) {
467                 data.ioc_inllen2 = strlen(argv[2]) + 1;
468                 data.ioc_inlbuf2 = argv[2];
469         }
470
471         if (argc == 4) {
472                 data.ioc_inllen3 = strlen(argv[3]) + 1;
473                 data.ioc_inlbuf3 = argv[3];
474         }
475
476         if (obd_ioctl_pack(&data, &buf, max)) {
477                 fprintf(stderr, "error: %s: invalid ioctl\n",cmdname(argv[0]));
478                 return -2;
479         }
480
481         rc = ioctl(fd, OBD_IOC_ATTACH , buf);
482         if (rc < 0)
483                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
484                         OBD_IOC_ATTACH, strerror(rc = errno));
485         else if (argc == 3) {
486                 char name[1024];
487                 if (strlen(argv[2]) > 128) {
488                         printf("Name too long to set environment\n");
489                         return -EINVAL;
490                 }
491                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
492                 rc = setenv(name, argv[1], 1);
493                 if (rc) {
494                         printf("error setting env variable %s\n", name);
495                 }
496         }
497
498         return rc;
499 }
500
501 int jt_dev_setup(int argc, char **argv) {
502         struct obd_ioctl_data data;
503
504         IOCINIT(data);
505         if (argc > 3)
506                 return CMD_HELP;
507                 
508         data.ioc_dev = -1;
509         if (argc > 1) {
510                 if (argv[1][0] == '$') {
511                         rc = do_name2dev(argv[0], argv[1] + 1);
512                         if (rc >= N2D_OFF) {
513                                 printf("%s is device %d\n", argv[1],
514                                        rc - N2D_OFF);
515                                 data.ioc_dev = rc - N2D_OFF;
516                         }
517                 } else
518                         data.ioc_dev = strtoul(argv[1], NULL, 0);
519                 data.ioc_inllen1 = strlen(argv[1]) + 1;
520                 data.ioc_inlbuf1 = argv[1];
521         }
522         if ( argc == 3 ) {
523                 data.ioc_inllen2 = strlen(argv[2]) + 1;
524                 data.ioc_inlbuf2 = argv[2];
525         }
526
527         if (obd_ioctl_pack(&data, &buf, max)) {
528                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
529                 return -2;
530         }
531         rc = ioctl(fd, OBD_IOC_SETUP , buf);
532         if (rc < 0)
533                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
534                         strerror(rc = errno));
535
536         return rc;
537 }
538
539 int jt_dev_detach(int argc, char **argv) {
540         struct obd_ioctl_data data;
541
542         IOCINIT(data);
543         if (argc != 1)
544                 return CMD_HELP;
545
546         if (obd_ioctl_pack(&data, &buf, max)) {
547                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
548                 return -2;
549         }
550
551         rc = ioctl(fd, OBD_IOC_DETACH , buf);
552         if (rc < 0)
553                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
554                         strerror(rc=errno));
555
556         return rc;
557 }
558
559 int jt_dev_cleanup(int argc, char **argv) {
560         struct obd_ioctl_data data;
561
562         IOCINIT(data);
563         if (argc != 1)
564                 return CMD_HELP;
565
566         rc = ioctl(fd, OBD_IOC_CLEANUP , &data);
567         if (rc < 0)
568                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
569                         strerror(rc=errno));
570
571         return rc;
572 }
573
574 int jt_dev_lov_config(int argc, char **argv) {
575         struct obd_ioctl_data data;
576         struct lov_desc desc; 
577         uuid_t *uuidarray;
578         int size, i;
579
580         IOCINIT(data);
581         if (argc <= 5)
582                 return CMD_HELP;
583
584         if (strlen(argv[1]) > sizeof(uuid_t) - 1) { 
585                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", 
586                         size);
587                 return -ENOMEM;
588         }
589             
590         memset(&desc, 0, sizeof(desc)); 
591         strcpy(desc.ld_uuid, argv[1]); 
592         desc.ld_default_stripecount = strtoul(argv[2], NULL, 0); 
593         desc.ld_default_stripesize = strtoul(argv[3], NULL, 0); 
594         desc.ld_pattern = strtoul(argv[4], NULL, 0); 
595         desc.ld_tgt_count = argc - 5;
596
597
598         size = sizeof(uuid_t) * desc.ld_tgt_count;
599         uuidarray = malloc(size);
600         if (!uuidarray) { 
601                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", 
602                         size);
603                 return -ENOMEM;
604         }
605         memset(uuidarray, 0, size); 
606         for (i=5 ; i < argc ; i++) { 
607                 char *buf = (char *) (uuidarray + i -5 );
608                 if (strlen(argv[i]) >= sizeof(uuid_t)) { 
609                         fprintf(stderr, "lov_config: arg %d (%s) too long\n",  
610                                 i, argv[i]);
611                         free(uuidarray);
612                         return -EINVAL;
613                 }
614                 strcpy(buf, argv[i]); 
615         }
616
617         data.ioc_inllen1 = sizeof(desc); 
618         data.ioc_inlbuf1 = (char *)&desc;
619         data.ioc_inllen2 = size;
620         data.ioc_inlbuf2 = (char *)uuidarray;
621
622         if (obd_ioctl_pack(&data, &buf, max)) {
623                 fprintf(stderr, "error: %s: invalid ioctl\n",cmdname(argv[0]));
624                 return -EINVAL;
625         }
626
627         rc = ioctl(fd, OBD_IOC_LOV_CONFIG , buf);
628         if (rc < 0)
629                 fprintf(stderr, "lov_config: error: %s: %s\n", 
630                         cmdname(argv[0]),strerror(rc = errno));
631         free(uuidarray);
632         return rc;
633 }
634
635 #if 0
636 int jt_dev_create(int argc, char **argv) {
637         struct obd_ioctl_data data;
638         struct timeval next_time;
639         int count = 1, next_count;
640         int verbose;
641         int i;
642
643         IOCINIT(data);
644         if (argc < 2 || argc > 4)
645                 return CMD_HELP;
646
647         count = strtoul(argv[1], NULL, 0);
648
649         if (argc > 2)
650                 data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0);
651         else
652                 data.ioc_obdo1.o_mode = 0100644;
653         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
654
655         verbose = get_verbose(argv[3]);
656
657         printf("%s: %d obdos\n", cmdname(argv[0]), count);
658         gettimeofday(&next_time, NULL);
659         next_time.tv_sec -= verbose;
660
661         for (i = 1, next_count = verbose; i <= count ; i++) {
662                 rc = ioctl(fd, OBD_IOC_CREATE , &data);
663                 if (rc < 0) {
664                         fprintf(stderr, "error: %s: #%d - %s\n",
665                                 cmdname(argv[0]), i, strerror(rc = errno));
666                         break;
667                 }
668                 if (be_verbose(verbose, &next_time, i, &next_count, count))
669                         printf("%s: #%d is object id %Ld\n", cmdname(argv[0]),
670                                i, data.ioc_obdo1.o_id);
671         }
672         return rc;
673 }
674
675 int jt_dev_destroy(int argc, char **argv) {
676         struct obd_ioctl_data data;
677
678         IOCINIT(data);
679         if (argc != 2) {
680                 fprintf(stderr, "usage: %s id\n", cmdname(argv[0]));
681                 return -1;
682         }
683
684         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
685         data.ioc_obdo1.o_mode = S_IFREG|0644;
686
687         rc = ioctl(fd, OBD_IOC_DESTROY , &data);
688         if (rc < 0)
689                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
690                         strerror(rc = errno));
691
692         return rc;
693 }
694 #endif
695
696 /* Device configuration commands */
697 int jt_dev_setattr(int argc, char **argv) {
698         struct obd_ioctl_data data;
699
700         IOCINIT(data);
701         if (argc != 2)
702                 return CMD_HELP;
703                 
704         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
705         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], NULL, 0);
706         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
707
708         rc = ioctl(fd, OBD_IOC_SETATTR , &data);
709         if (rc < 0)
710                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
711                         strerror(rc = errno));
712
713         return rc;
714 }
715
716 int jt_dev_getattr(int argc, char **argv) {
717         struct obd_ioctl_data data;
718
719         if (argc != 2)
720                 return CMD_HELP;
721
722         IOCINIT(data);
723         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
724         /* to help obd filter */
725         data.ioc_obdo1.o_mode = 0100644;
726         data.ioc_obdo1.o_valid = 0xffffffff;
727         printf("%s: object id %Ld\n", cmdname(argv[0]), data.ioc_obdo1.o_id);
728
729         rc = ioctl(fd, OBD_IOC_GETATTR , &data);
730         if (rc) {
731                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
732                         strerror(rc=errno));
733         } else {
734                 printf("%s: object id %Ld, mode %o\n", cmdname(argv[0]),
735                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
736         }
737         return rc;
738 }
739
740 int jt_dev_test_getattr(int argc, char **argv) {
741         struct obd_ioctl_data data;
742         struct timeval start, next_time;
743         int i, count, next_count;
744         int verbose;
745
746         if (argc != 2 && argc != 3)
747                 return CMD_HELP;
748
749         IOCINIT(data);
750         count = strtoul(argv[1], NULL, 0);
751
752         if (argc == 3)
753                 verbose = get_verbose(argv[2]);
754         else
755                 verbose = 1;
756
757         data.ioc_obdo1.o_valid = 0xffffffff;
758         data.ioc_obdo1.o_id = 2;
759         gettimeofday(&start, NULL);
760         next_time.tv_sec = start.tv_sec - verbose;
761         next_time.tv_usec = start.tv_usec;
762         printf("%s: getting %d attrs (testing only): %s", cmdname(argv[0]),
763                count, ctime(&start.tv_sec));
764
765         for (i = 1, next_count = verbose; i <= count; i++) {
766                 rc = ioctl(fd, OBD_IOC_GETATTR , &data);
767                 if (rc < 0) {
768                         fprintf(stderr, "error: %s: #%d - %s\n",
769                                 cmdname(argv[0]), i, strerror(rc = errno));
770                         break;
771                 } else {
772                         if (be_verbose(verbose, &next_time, i,&next_count,count))
773                         printf("%s: got attr #%d\n", cmdname(argv[0]), i);
774                 }
775         }
776
777         if (!rc) {
778                 struct timeval end;
779                 double diff;
780
781                 gettimeofday(&end, NULL);
782
783                 diff = difftime(&end, &start);
784
785                 --i;
786                 printf("%s: %d attrs in %.4gs (%.4g attr/s): %s",
787                        cmdname(argv[0]), i, diff, (double)i / diff,
788                        ctime(&end.tv_sec));
789         }
790         return rc;
791 }
792
793 int jt_dev_test_brw(int argc, char **argv) {
794         struct obd_ioctl_data data;
795         struct timeval start, next_time;
796         char *bulk, *b;
797         int pages = 1, obdos = 1, count, next_count;
798         int verbose = 1, write = 0, rw;
799         int i, o, p;
800         int len;
801
802         if (argc < 2 || argc > 6)
803                 return CMD_HELP;
804
805         count = strtoul(argv[1], NULL, 0);
806
807         if (argc >= 3) {
808                 if (argv[2][0] == 'w' || argv[2][0] == '1')
809                         write = 1;
810                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
811                         write = 0;
812
813                 verbose = get_verbose(argv[3]);
814         }
815
816         if (argc >= 5)
817                 pages = strtoul(argv[4], NULL, 0);
818         if (argc >= 6)
819                 obdos = strtoul(argv[5], NULL, 0);
820
821         if (obdos != 1 && obdos != 2) {
822                 fprintf(stderr, "error: %s: only 1 or 2 obdos supported\n",
823                         cmdname(argv[0]));
824                 return -2;
825         }
826
827         len = pages * PAGE_SIZE;
828
829         bulk = calloc(obdos, len);
830         if (!bulk) {
831                 fprintf(stderr,"error: %s: no memory allocating %dx%d pages\n",
832                         cmdname(argv[0]), obdos, pages);
833                 return -2;
834         }
835         IOCINIT(data);
836         data.ioc_obdo1.o_id = 2;
837         data.ioc_count = len;
838         data.ioc_offset = 0;
839         data.ioc_plen1 = len;
840         data.ioc_pbuf1 = bulk;
841         if (obdos > 1) {
842                 data.ioc_obdo2.o_id = 3;
843                 data.ioc_plen2 = len;
844                 data.ioc_pbuf2 = bulk + len;
845         }
846
847         gettimeofday(&start, NULL);
848         next_time.tv_sec = start.tv_sec - verbose;
849         next_time.tv_usec = start.tv_usec;
850
851         printf("%s: %s %d (%dx%d pages) (testing only): %s",
852                cmdname(argv[0]), write ? "writing" : "reading",
853                count, obdos, pages, ctime(&start.tv_sec));
854
855         /*
856          * We will put in the start time (and loop count inside the loop)
857          * at the beginning of each page so that we will be able to validate
858          * (at some later time) whether the data actually made it or not.
859          *
860          * XXX we do not currently use any of this memory in OBD_IOC_BRW_*
861          *     just to avoid the overhead of the copy_{to,from}_user.  It
862          *     can be fixed if we ever need to send real data around.
863          */
864         for (o = 0, b = bulk; o < obdos; o++)
865                 for (p = 0; p < pages; p++, b += PAGE_SIZE)
866                         memcpy(b, &start, sizeof(start));
867
868         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
869         for (i = 1, next_count = verbose; i <= count; i++) {
870                 if (write) {
871                         b = bulk + sizeof(struct timeval);
872                         for (o = 0; o < obdos; o++)
873                                 for (p = 0; p < pages; p++, b += PAGE_SIZE)
874                                         memcpy(b, &count, sizeof(count));
875                 }
876
877                 rc = ioctl(fd, rw, &data);
878                 if (rc) {
879                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
880                                 cmdname(argv[0]), i, strerror(rc = errno),
881                                 write ? "write" : "read");
882                         break;
883                 } else if (be_verbose(verbose,&next_time,i,&next_count,count))
884                         printf("%s: %s number %d\n", cmdname(argv[0]),
885                                write ? "write" : "read", i);
886         }
887
888         free(bulk);
889
890         if (!rc) {
891                 struct timeval end;
892                 double diff;
893
894                 gettimeofday(&end, NULL);
895
896                 diff = difftime(&end, &start);
897
898                 --i;
899                 printf("%s: %s %dx%dx%d pages in %.4gs (%.4g pg/s): %s",
900                        cmdname(argv[0]), write ? "wrote" : "read", obdos,
901                        pages, i, diff, (double)obdos * i * pages / diff,
902                        ctime(&end.tv_sec));
903         }
904         return rc;
905 }
906
907 int jt_dev_test_ldlm(int argc, char **argv) {
908         struct obd_ioctl_data data;
909
910         IOCINIT(data);
911         if (argc != 1)
912                 return CMD_HELP;
913
914         rc = ioctl(fd, IOC_LDLM_TEST, &data);
915         if (rc)
916                 fprintf(stderr, "error: %s: test failed: %s\n",
917                         cmdname(argv[0]), strerror(rc = errno));
918         return rc;
919 }