Whamcloud - gitweb
- use llmodules.sh to load modules now
[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
66 #if 0
67 static int thread;
68 #endif
69
70 int device_setup(int argc, char **argv) {
71         return 0;
72 }
73
74 /* Misc support functions */
75 static int do_name2dev(char *func, char *name) {
76         struct obd_ioctl_data data;
77         int rc;
78
79         LUSTRE_CONNECT(func);
80         IOCINIT(data);
81
82         data.ioc_inllen1 = strlen(name) + 1;
83         data.ioc_inlbuf1 = name;
84
85         if (obd_ioctl_pack(&data, &buf, max)) {
86                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
87                 return -2;
88         }
89         rc = ioctl(fd, OBD_IOC_NAME2DEV , buf);
90         if (rc < 0) {
91                 fprintf(stderr, "error: %s: %s - %s\n", cmdname(func),
92                         name, strerror(rc = errno));
93                 return rc;
94         }
95
96         memcpy((char *)(&data), buf, sizeof(data));
97
98         return data.ioc_dev + N2D_OFF;
99 }
100
101 /* 
102  * resolve a device name to a device number.
103  * supports a number or name.  
104  * FIXME: support UUID 
105  */
106 static int parse_devname(char * func, char *name) 
107 {
108         int rc;
109         int ret = -1;
110
111         if (!name) 
112                 return ret;
113         if (name[0] == '$') {
114                 rc = do_name2dev(func, name + 1);
115                 if (rc >= N2D_OFF) {
116                         ret = rc - N2D_OFF;
117                         printf("%s is device %d\n", name,
118                                ret);
119                 } else {
120                         fprintf(stderr, "error: %s: %s: %s\n", cmdname(func),
121                                 name, "device not found");
122                 }
123                         
124         } else
125                 ret = strtoul(name, NULL, 0);
126         return ret;
127 }
128
129
130 #if 0
131 /* pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L" */
132 static char * obdo_print(struct obdo *obd)
133 {
134         char buf[1024];
135
136         sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\n"
137                 "size: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\n"
138                 "gid: %d\nflags: %x\nobdflags: %x\nnlink: %d,\nvalid %x\n",
139                 obd->o_id,
140                 obd->o_gr,
141                 obd->o_atime,
142                 obd->o_mtime,
143                 obd->o_ctime,
144                 obd->o_size,
145                 obd->o_blocks,
146                 obd->o_blksize,
147                 obd->o_mode,
148                 obd->o_uid,
149                 obd->o_gid,
150                 obd->o_flags,
151                 obd->o_obdflags,
152                 obd->o_nlink,
153                 obd->o_valid);
154         return strdup(buf);
155 }
156 #endif
157
158 /* Device selection commands */
159 int jt_dev_newdev(int argc, char **argv) 
160 {
161         int rc;
162         struct obd_ioctl_data data;
163
164         LUSTRE_CONNECT(argv[0]);
165         IOCINIT(data);
166
167         if (argc != 1)
168                 return CMD_HELP;
169
170         rc = ioctl(fd, OBD_IOC_NEWDEV , &data);
171         if (rc < 0)
172                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
173                         strerror(rc=errno));
174         else {
175                 printf("Current device set to %d\n", data.ioc_dev);
176         }
177
178         return rc;
179 }
180
181 static int do_device(char *func, int dev) {
182         struct obd_ioctl_data data;
183
184         memset(&data, 0, sizeof(data));
185         data.ioc_dev = dev;
186         LUSTRE_CONNECT(func);
187
188         if (obd_ioctl_pack(&data, &buf, max)) {
189                 CERROR("error: %s: invalid ioctl\n", cmdname(func));
190                 return -2;
191         }
192
193         return ioctl(fd, OBD_IOC_DEVICE , buf);
194 }
195
196 int jt_dev_device(int argc, char **argv) 
197 {
198         int rc, dev;
199         do_disconnect(argv[0], 1);
200
201         if (argc != 2)
202                 return CMD_HELP;
203         dev = parse_devname(argv[0], argv[1]);
204         if (dev < 0) {
205                 return -1; 
206         }
207         rc = do_device(argv[0], dev);
208         if (rc < 0)
209                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
210                         strerror(rc = errno));
211
212         return rc;
213 }
214
215 static int do_uuid2dev(char *func, char *name) {
216         return 0;
217 }
218
219 int jt_dev_uuid2dev(int argc, char **argv) 
220 {
221         do_uuid2dev(NULL, NULL);
222         return 0;
223 }
224
225 int jt_dev_name2dev(int argc, char **argv) 
226 {
227         int rc;
228         if (argc != 2)
229                 return CMD_HELP;
230
231         rc = do_name2dev(argv[0], argv[1]);
232         if (rc >= N2D_OFF) {
233                 int dev = rc - N2D_OFF;
234                 rc = do_device(argv[0], dev);
235                 if (rc == 0)
236                         printf("%d\n", dev);
237         }
238         return rc;
239 }
240
241 int jt_dev_list(int argc, char **argv) 
242 {
243         int rc;
244         char buf[1024];
245         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
246
247         LUSTRE_CONNECT(argv[0]);
248         memset(buf, 0, sizeof(buf));
249         data->ioc_version = OBD_IOCTL_VERSION;
250         data->ioc_addr = conn_addr;
251         data->ioc_cookie = conn_addr;
252         data->ioc_len = sizeof(buf);
253         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
254
255         if (argc != 1)
256                 return CMD_HELP;
257                 
258         rc = ioctl(fd, OBD_IOC_LIST , data);
259         if (rc < 0)
260                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
261                         strerror(rc=errno));
262         else {
263                 printf("%s", data->ioc_bulk);
264         }
265
266         return rc;
267 }
268
269 /* Device configuration commands */
270 int do_disconnect(char *func, int verbose) 
271 {
272         int rc;
273         struct obd_ioctl_data data;
274
275         if (conn_addr == -1) 
276                 return 0; 
277
278         IOCINIT(data);
279
280         rc = ioctl(fd, OBD_IOC_DISCONNECT , &data);
281         if (rc < 0) {
282                 fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
283                         OBD_IOC_DISCONNECT, strerror(errno));
284         } else {
285                 if (verbose)
286                         printf("%s: disconnected conn %Lx\n", cmdname(func),
287                                conn_addr);
288                 conn_addr = -1;
289         }
290
291         return rc;
292 }
293
294 #if 0
295 static int jt_dev_newconn(int argc, char **argv)
296 {
297         int rc;a
298         struct obd_ioctl_data data;
299
300         IOCINIT(data);
301         if (argc != 1) {
302                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
303                 return -1;
304         }
305
306         rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN , &data);
307         if (rc < 0)
308                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
309                         strerror(rc = errno));
310
311         return rc;
312 }
313 #endif
314
315 int jt_dev_probe(int argc, char **argv) 
316 {
317         int rc;
318         struct obd_ioctl_data data;
319
320         IOCINIT(data);
321         do_disconnect(argv[0], 1);
322
323         if (argc != 1)
324                 return CMD_HELP;
325
326         rc = ioctl(fd, OBD_IOC_CONNECT , &data);
327         if (rc < 0)
328                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
329                         OBD_IOC_CONNECT, strerror(rc = errno));
330         else
331                 conn_addr = data.ioc_addr;
332                 conn_cookie = data.ioc_cookie;
333         return rc;
334 }
335
336 int jt_dev_close(int argc, char **argv) 
337 {
338         if (argc != 1)
339                 return CMD_HELP;
340
341         if (conn_addr == -1)
342                 return 0;
343
344         return do_disconnect(argv[0], 0);
345 }
346
347 int jt_opt_device(int argc, char **argv)
348 {
349         char *arg2[3];
350         int ret;
351         int rc;
352
353         if (argc < 3) {
354                 fprintf(stderr, "usage: %s devno <command [args ...]>\n",
355                         cmdname(argv[0]));
356                 return -1;
357         }
358
359         rc = do_device("device", parse_devname(argv[0], argv[1]));
360
361         if (!rc) {
362                 arg2[0] = "connect";
363                 arg2[1] = NULL;
364                 rc = jt_dev_probe(1, arg2);
365         }
366
367         if (!rc)
368                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
369         ret = do_disconnect(argv[0], 0);
370         if (!rc)
371                 rc = ret;
372
373         return rc;
374 }
375
376
377 int jt_dev_attach(int argc, char **argv) 
378 {
379         int rc;
380         struct obd_ioctl_data data;
381
382         IOCINIT(data);
383         if (argc != 2 && argc != 3 && argc != 4)
384                 return CMD_HELP;
385
386         data.ioc_inllen1 =  strlen(argv[1]) + 1;
387         data.ioc_inlbuf1 = argv[1];
388         if (argc >= 3) {
389                 data.ioc_inllen2 = strlen(argv[2]) + 1;
390                 data.ioc_inlbuf2 = argv[2];
391         }
392
393         if (argc == 4) {
394                 data.ioc_inllen3 = strlen(argv[3]) + 1;
395                 data.ioc_inlbuf3 = argv[3];
396         }
397
398         if (obd_ioctl_pack(&data, &buf, max)) {
399                 fprintf(stderr, "error: %s: invalid ioctl\n",cmdname(argv[0]));
400                 return -2;
401         }
402
403         rc = ioctl(fd, OBD_IOC_ATTACH , buf);
404         if (rc < 0)
405                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
406                         OBD_IOC_ATTACH, strerror(rc = errno));
407         else if (argc == 3) {
408                 char name[1024];
409                 if (strlen(argv[2]) > 128) {
410                         printf("Name too long to set environment\n");
411                         return -EINVAL;
412                 }
413                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
414                 rc = setenv(name, argv[1], 1);
415                 if (rc) {
416                         printf("error setting env variable %s\n", name);
417                 }
418         }
419
420         return rc;
421 }
422
423 int jt_dev_setup(int argc, char **argv) 
424 {
425         int rc;
426         struct obd_ioctl_data data;
427
428         IOCINIT(data);
429         if (argc > 3)
430                 return CMD_HELP;
431                 
432         data.ioc_dev = -1;
433         if (argc > 1) {
434                 data.ioc_dev = parse_devname(argv[0], argv[1]);
435                 if (data.ioc_dev < 0) 
436                         return rc = -1;
437
438                 data.ioc_inllen1 = strlen(argv[1]) + 1;
439                 data.ioc_inlbuf1 = argv[1];
440         }
441         if ( argc == 3 ) {
442                 data.ioc_inllen2 = strlen(argv[2]) + 1;
443                 data.ioc_inlbuf2 = argv[2];
444         }
445
446         if (obd_ioctl_pack(&data, &buf, max)) {
447                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
448                 return -2;
449         }
450         rc = ioctl(fd, OBD_IOC_SETUP , buf);
451         if (rc < 0)
452                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
453                         strerror(rc = errno));
454
455         return rc;
456 }
457
458 int jt_dev_detach(int argc, char **argv) 
459 {
460         int rc;
461         struct obd_ioctl_data data;
462
463         IOCINIT(data);
464         if (argc != 1)
465                 return CMD_HELP;
466
467         if (obd_ioctl_pack(&data, &buf, max)) {
468                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
469                 return -2;
470         }
471
472         rc = ioctl(fd, OBD_IOC_DETACH , buf);
473         if (rc < 0)
474                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
475                         strerror(rc=errno));
476
477         return rc;
478 }
479
480 int jt_dev_cleanup(int argc, char **argv) 
481 {
482         int rc;
483         struct obd_ioctl_data data;
484
485         IOCINIT(data);
486         if (argc != 1)
487                 return CMD_HELP;
488
489         rc = ioctl(fd, OBD_IOC_CLEANUP , &data);
490         if (rc < 0)
491                 CERROR("error: %s: %s\n", cmdname(argv[0]),
492                         strerror(rc=errno));
493         return rc;
494 }
495
496 int jt_dev_lov_config(int argc, char **argv) 
497 {
498         struct obd_ioctl_data data;
499         struct lov_desc desc; 
500         uuid_t *uuidarray;
501         int rc, size, i;
502
503         IOCINIT(data);
504         if (argc <= 5)
505                 return CMD_HELP;
506
507         if (strlen(argv[1]) > sizeof(uuid_t) - 1) { 
508                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", 
509                         strlen(argv[1]));
510                 return -ENOMEM;
511         }
512             
513         memset(&desc, 0, sizeof(desc)); 
514         strcpy(desc.ld_uuid, argv[1]); 
515         desc.ld_default_stripecount = strtoul(argv[2], NULL, 0); 
516         desc.ld_default_stripesize = strtoul(argv[3], NULL, 0); 
517         desc.ld_pattern = strtoul(argv[4], NULL, 0); 
518         desc.ld_tgt_count = argc - 5;
519
520
521         size = sizeof(uuid_t) * desc.ld_tgt_count;
522         uuidarray = malloc(size);
523         if (!uuidarray) { 
524                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", 
525                         size);
526                 return -ENOMEM;
527         }
528         memset(uuidarray, 0, size); 
529         for (i=5 ; i < argc ; i++) { 
530                 char *buf = (char *) (uuidarray + i -5 );
531                 if (strlen(argv[i]) >= sizeof(uuid_t)) { 
532                         fprintf(stderr, "lov_config: arg %d (%s) too long\n",  
533                                 i, argv[i]);
534                         free(uuidarray);
535                         return -EINVAL;
536                 }
537                 strcpy(buf, argv[i]); 
538         }
539
540         data.ioc_inllen1 = sizeof(desc); 
541         data.ioc_inlbuf1 = (char *)&desc;
542         data.ioc_inllen2 = size;
543         data.ioc_inlbuf2 = (char *)uuidarray;
544
545         if (obd_ioctl_pack(&data, &buf, max)) {
546                 fprintf(stderr, "error: %s: invalid ioctl\n",cmdname(argv[0]));
547                 return -EINVAL;
548         }
549
550         rc = ioctl(fd, OBD_IOC_LOV_CONFIG , buf);
551         if (rc < 0)
552                 fprintf(stderr, "lov_config: error: %s: %s\n", 
553                         cmdname(argv[0]),strerror(rc = errno));
554         free(uuidarray);
555         return rc;
556 }
557
558 #if 0
559 int jt_dev_create(int argc, char **argv) {
560         struct obd_ioctl_data data;
561         struct timeval next_time;
562         int count = 1, next_count;
563         int verbose;
564         int i;
565
566         IOCINIT(data);
567         if (argc < 2 || argc > 4)
568                 return CMD_HELP;
569
570         count = strtoul(argv[1], NULL, 0);
571
572         if (argc > 2)
573                 data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0);
574         else
575                 data.ioc_obdo1.o_mode = 0100644;
576         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
577
578         verbose = get_verbose(argv[3]);
579
580         printf("%s: %d obdos\n", cmdname(argv[0]), count);
581         gettimeofday(&next_time, NULL);
582         next_time.tv_sec -= verbose;
583
584         for (i = 1, next_count = verbose; i <= count ; i++) {
585                 rc = ioctl(fd, OBD_IOC_CREATE , &data);
586                 if (rc < 0) {
587                         fprintf(stderr, "error: %s: #%d - %s\n",
588                                 cmdname(argv[0]), i, strerror(rc = errno));
589                         break;
590                 }
591                 if (be_verbose(verbose, &next_time, i, &next_count, count))
592                         printf("%s: #%d is object id %Ld\n", cmdname(argv[0]),
593                                i, data.ioc_obdo1.o_id);
594         }
595         return rc;
596 }
597
598 int jt_dev_destroy(int argc, char **argv) {
599         struct obd_ioctl_data data;
600
601         IOCINIT(data);
602         if (argc != 2) {
603                 fprintf(stderr, "usage: %s id\n", cmdname(argv[0]));
604                 return -1;
605         }
606
607         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
608         data.ioc_obdo1.o_mode = S_IFREG|0644;
609
610         rc = ioctl(fd, OBD_IOC_DESTROY , &data);
611         if (rc < 0)
612                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
613                         strerror(rc = errno));
614
615         return rc;
616 }
617 #endif
618
619 /* Device configuration commands */
620 int jt_dev_setattr(int argc, char **argv) 
621 {
622         int rc;
623         struct obd_ioctl_data data;
624
625         IOCINIT(data);
626         if (argc != 2)
627                 return CMD_HELP;
628                 
629         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
630         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], NULL, 0);
631         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
632
633         rc = ioctl(fd, OBD_IOC_SETATTR , &data);
634         if (rc < 0)
635                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
636                         strerror(rc = errno));
637
638         return rc;
639 }
640
641 int jt_dev_getattr(int argc, char **argv) 
642 {
643         int rc;
644         struct obd_ioctl_data data;
645
646         if (argc != 2)
647                 return CMD_HELP;
648
649         IOCINIT(data);
650         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
651         /* to help obd filter */
652         data.ioc_obdo1.o_mode = 0100644;
653         data.ioc_obdo1.o_valid = 0xffffffff;
654         printf("%s: object id %Ld\n", cmdname(argv[0]), data.ioc_obdo1.o_id);
655
656         rc = ioctl(fd, OBD_IOC_GETATTR , &data);
657         if (rc) {
658                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
659                         strerror(rc=errno));
660         } else {
661                 printf("%s: object id %Ld, mode %o\n", cmdname(argv[0]),
662                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
663         }
664         return rc;
665 }
666
667 int jt_dev_test_getattr(int argc, char **argv) 
668 {
669         int rc = 0;
670         struct obd_ioctl_data data;
671         struct timeval start, next_time;
672         int i, count, next_count;
673         int verbose;
674
675         if (argc != 2 && argc != 3)
676                 return CMD_HELP;
677
678         IOCINIT(data);
679         count = strtoul(argv[1], NULL, 0);
680
681         if (argc == 3)
682                 verbose = get_verbose(argv[2]);
683         else
684                 verbose = 1;
685
686         data.ioc_obdo1.o_valid = 0xffffffff;
687         data.ioc_obdo1.o_id = 2;
688         gettimeofday(&start, NULL);
689         next_time.tv_sec = start.tv_sec - verbose;
690         next_time.tv_usec = start.tv_usec;
691         printf("%s: getting %d attrs (testing only): %s", cmdname(argv[0]),
692                count, ctime(&start.tv_sec));
693
694         for (i = 1, next_count = verbose; i <= count; i++) {
695                 rc = ioctl(fd, OBD_IOC_GETATTR , &data);
696                 if (rc < 0) {
697                         fprintf(stderr, "error: %s: #%d - %s\n",
698                                 cmdname(argv[0]), i, strerror(rc = errno));
699                         break;
700                 } else {
701                         if (be_verbose(verbose, &next_time, i,&next_count,count))
702                         printf("%s: got attr #%d\n", cmdname(argv[0]), i);
703                 }
704         }
705
706         if (!rc) {
707                 struct timeval end;
708                 double diff;
709
710                 gettimeofday(&end, NULL);
711
712                 diff = difftime(&end, &start);
713
714                 --i;
715                 printf("%s: %d attrs in %.4gs (%.4g attr/s): %s",
716                        cmdname(argv[0]), i, diff, (double)i / diff,
717                        ctime(&end.tv_sec));
718         }
719         return rc;
720 }
721
722 int jt_dev_test_brw(int argc, char **argv) 
723 {
724         int rc = 0;
725         struct obd_ioctl_data data;
726         struct timeval start, next_time;
727         char *bulk, *b;
728         int pages = 1, obdos = 1, count, next_count;
729         int verbose = 1, write = 0, rw;
730         int i, o, p;
731         int len;
732
733         if (argc < 2 || argc > 6)
734                 return CMD_HELP;
735
736         count = strtoul(argv[1], NULL, 0);
737
738         if (argc >= 3) {
739                 if (argv[2][0] == 'w' || argv[2][0] == '1')
740                         write = 1;
741                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
742                         write = 0;
743
744                 verbose = get_verbose(argv[3]);
745         }
746
747         if (argc >= 5)
748                 pages = strtoul(argv[4], NULL, 0);
749         if (argc >= 6)
750                 obdos = strtoul(argv[5], NULL, 0);
751
752         if (obdos != 1 && obdos != 2) {
753                 fprintf(stderr, "error: %s: only 1 or 2 obdos supported\n",
754                         cmdname(argv[0]));
755                 return -2;
756         }
757
758         len = pages * PAGE_SIZE;
759
760         bulk = calloc(obdos, len);
761         if (!bulk) {
762                 fprintf(stderr,"error: %s: no memory allocating %dx%d pages\n",
763                         cmdname(argv[0]), obdos, pages);
764                 return -2;
765         }
766         IOCINIT(data);
767         data.ioc_obdo1.o_id = 2;
768         data.ioc_count = len;
769         data.ioc_offset = 0;
770         data.ioc_plen1 = len;
771         data.ioc_pbuf1 = bulk;
772         if (obdos > 1) {
773                 data.ioc_obdo2.o_id = 3;
774                 data.ioc_plen2 = len;
775                 data.ioc_pbuf2 = bulk + len;
776         }
777
778         gettimeofday(&start, NULL);
779         next_time.tv_sec = start.tv_sec - verbose;
780         next_time.tv_usec = start.tv_usec;
781
782         printf("%s: %s %d (%dx%d pages) (testing only): %s",
783                cmdname(argv[0]), write ? "writing" : "reading",
784                count, obdos, pages, ctime(&start.tv_sec));
785
786         /*
787          * We will put in the start time (and loop count inside the loop)
788          * at the beginning of each page so that we will be able to validate
789          * (at some later time) whether the data actually made it or not.
790          *
791          * XXX we do not currently use any of this memory in OBD_IOC_BRW_*
792          *     just to avoid the overhead of the copy_{to,from}_user.  It
793          *     can be fixed if we ever need to send real data around.
794          */
795         for (o = 0, b = bulk; o < obdos; o++)
796                 for (p = 0; p < pages; p++, b += PAGE_SIZE)
797                         memcpy(b, &start, sizeof(start));
798
799         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
800         for (i = 1, next_count = verbose; i <= count; i++) {
801                 if (write) {
802                         b = bulk + sizeof(struct timeval);
803                         for (o = 0; o < obdos; o++)
804                                 for (p = 0; p < pages; p++, b += PAGE_SIZE)
805                                         memcpy(b, &count, sizeof(count));
806                 }
807
808                 rc = ioctl(fd, rw, &data);
809                 if (rc) {
810                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
811                                 cmdname(argv[0]), i, strerror(rc = errno),
812                                 write ? "write" : "read");
813                         break;
814                 } else if (be_verbose(verbose,&next_time,i,&next_count,count))
815                         printf("%s: %s number %d\n", cmdname(argv[0]),
816                                write ? "write" : "read", i);
817         }
818
819         free(bulk);
820
821         if (!rc) {
822                 struct timeval end;
823                 double diff;
824
825                 gettimeofday(&end, NULL);
826
827                 diff = difftime(&end, &start);
828
829                 --i;
830                 printf("%s: %s %dx%dx%d pages in %.4gs (%.4g pg/s): %s",
831                        cmdname(argv[0]), write ? "wrote" : "read", obdos,
832                        pages, i, diff, (double)obdos * i * pages / diff,
833                        ctime(&end.tv_sec));
834         }
835         return rc;
836 }
837
838 int jt_dev_test_ldlm(int argc, char **argv) 
839 {
840         int rc;
841         struct obd_ioctl_data data;
842
843         IOCINIT(data);
844         if (argc != 1)
845                 return CMD_HELP;
846
847         rc = ioctl(fd, IOC_LDLM_TEST, &data);
848         if (rc)
849                 fprintf(stderr, "error: %s: test failed: %s\n",
850                         cmdname(argv[0]), strerror(rc = errno));
851         return rc;
852 }
853