Whamcloud - gitweb
- Added lctl.c which is basically ptlctl/obdctl/debugctl all
[fs/lustre-release.git] / lustre / utils / obdctl.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  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
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 #include <linux/lustre_lib.h>
39 #include <linux/lustre_idl.h>
40 #include <linux/lustre_dlm.h>
41
42 #include <libxml/xmlmemory.h>
43 #include <libxml/parser.h>
44
45 #include <unistd.h>
46 #include <sys/un.h>
47 #include <time.h>
48 #include <sys/time.h>
49 #include <netinet/in.h>
50 #include <errno.h>
51 #include <string.h>
52
53 #include <asm/page.h>   /* needed for PAGE_SIZE - rread*/ 
54
55 #define __KERNEL__
56 #include <linux/list.h>
57 #undef __KERNEL__
58
59 #include "parser.h"
60 #include <stdio.h>
61
62 static int jt_newdev(int argc, char **argv);
63 static int jt_attach(int argc, char **argv);
64 static int jt_setup(int argc, char **argv);
65
66
67 int fd = -1;
68 uint64_t conn_addr = -1;
69 uint64_t conn_cookie;
70 char rawbuf[8192];
71 char *buf = rawbuf;
72 int max = 8192;
73 int thread;
74 int rc = 0;
75
76 #define IOCINIT(data)                                                   \
77 do {                                                                    \
78         memset(&data, 0, sizeof(data));                                 \
79         data.ioc_version = OBD_IOCTL_VERSION;                           \
80         data.ioc_addr = conn_addr;                                      \
81         data.ioc_cookie = conn_cookie;                                  \
82         data.ioc_len = sizeof(data);                                    \
83         if (fd < 0) {                                                   \
84                 fprintf(stderr, "No device open, use device\n");        \
85                 return 1;                                               \
86         }                                                               \
87 } while (0)
88
89 /*
90     pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L",
91     $obdo->{id}, 0,
92     $obdo->{gr}, 0,
93     $obdo->{atime}, 0,
94     $obdo->{mtime}, 0 ,
95     $obdo->{ctime}, 0,
96     $obdo->{size}, 0,
97     $obdo->{blocks}, 0,
98     $obdo->{blksize},
99     $obdo->{mode},
100     $obdo->{uid},
101     $obdo->{gid},
102     $obdo->{flags},
103     $obdo->{obdflags},
104     $obdo->{nlink},
105     $obdo->{generation},
106     $obdo->{valid},
107     $obdo->{inline},
108     $obdo->{obdmd},
109     0, 0, # struct list_head
110     0;  #  struct obd_ops
111 }
112
113 */
114
115 char * obdo_print(struct obdo *obd)
116 {
117         char buf[1024];
118
119         sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\n"
120                 "size: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\n"
121                 "gid: %d\nflags: %x\nobdflags: %x\nnlink: %d,\nvalid %x\n",
122                 obd->o_id,
123                 obd->o_gr,
124                 obd->o_atime,
125                 obd->o_mtime,
126                 obd->o_ctime,
127                 obd->o_size,
128                 obd->o_blocks,
129                 obd->o_blksize,
130                 obd->o_mode,
131                 obd->o_uid,
132                 obd->o_gid,
133                 obd->o_flags,
134                 obd->o_obdflags,
135                 obd->o_nlink,
136                 obd->o_valid);
137         return strdup(buf);
138 }
139
140 static char *cmdname(char *func)
141 {
142         static char buf[512];
143
144         if (thread) {
145                 sprintf(buf, "%s-%d", func, thread);
146                 return buf;
147         }
148
149         return func;
150 }
151
152 int getfd(char *func)
153 {
154         if (fd == -1)
155                 fd = open("/dev/obd", O_RDWR);
156         if (fd == -1) {
157                 fprintf(stderr, "error: %s: opening /dev/obd: %s\n",
158                         cmdname(func), strerror(errno));
159                 return -1;
160         }
161         return 0;
162 }
163
164 #define difftime(a, b)                                          \
165         ((double)(a)->tv_sec - (b)->tv_sec +                    \
166          ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
167
168 static int be_verbose(int verbose, struct timeval *next_time,
169                       int num, int *next_num, int num_total)
170 {
171         struct timeval now;
172
173         if (!verbose)
174                 return 0;
175
176         if (next_time != NULL)
177                 gettimeofday(&now, NULL);
178
179         /* A positive verbosity means to print every X iterations */
180         if (verbose > 0 &&
181             (next_num == NULL || num >= *next_num || num >= num_total)) {
182                 *next_num += verbose;
183                 if (next_time) {
184                         next_time->tv_sec = now.tv_sec - verbose;
185                         next_time->tv_usec = now.tv_usec;
186                 }
187                 return 1;
188         }
189
190         /* A negative verbosity means to print at most each X seconds */
191         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
192                 next_time->tv_sec = now.tv_sec - verbose;
193                 next_time->tv_usec = now.tv_usec;
194                 if (next_num)
195                         *next_num = num;
196                 return 1;
197         }
198
199         return 0;
200 }
201
202 static int get_verbose(const char *arg)
203 {
204         int verbose;
205
206         if (!arg || arg[0] == 'v')
207                 verbose = 1;
208         else if (arg[0] == 's' || arg[0] == 'q')
209                 verbose = 0;
210         else
211                 verbose = (int) strtoul(arg, NULL, 0);
212
213         if (verbose < 0)
214                 printf("Print status every %d seconds\n", -verbose);
215         else if (verbose == 1)
216                 printf("Print status every operation\n");
217         else if (verbose > 1)
218                 printf("Print status every %d operations\n", verbose);
219
220         return verbose;
221 }
222
223 static int do_disconnect(char *func, int verbose)
224 {
225         struct obd_ioctl_data data;
226
227         if (conn_addr == -1) 
228                 return 0; 
229
230         IOCINIT(data);
231
232         rc = ioctl(fd, OBD_IOC_DISCONNECT , &data);
233         if (rc < 0) {
234                 fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
235                         OBD_IOC_DISCONNECT, strerror(errno));
236         } else {
237                 if (verbose)
238                         printf("%s: disconnected conn %Lx\n", cmdname(func),
239                                conn_addr);
240                 conn_addr = -1;
241         }
242
243         return rc;
244 }
245
246 extern command_t cmdlist[];
247
248 static int xml_command(char *cmd, ...) {
249         va_list args;
250         char *arg, *cmds[8];
251         int i = 1, j;
252        
253         cmds[0] = cmd; 
254         va_start(args, cmd);
255
256         while (((arg = va_arg(args, char *)) != NULL) && (i < 8)) {
257                 cmds[i] = arg;
258                 i++;
259         }
260
261         va_end(args);
262
263         printf("obdctl > ");
264         for (j = 0; j < i; j++)
265           printf("%s ", cmds[j]);
266
267         printf("\n");
268
269         return Parser_execarg(i, cmds, cmdlist);
270 }
271
272 static network_t *xml_network(xmlDocPtr doc, xmlNodePtr root) {
273         xmlNodePtr cur = root->xmlChildrenNode;
274         network_t *net;
275         
276         if ((net = (network_t *)calloc(1, sizeof(network_t))) == NULL) {
277                 printf("error: unable to malloc network_t\n");
278                 return NULL;
279         }
280         
281         net->type = xmlGetProp(root, "type");
282         if (net->type == NULL) {
283                 printf("error: type attrib required (tcp, elan, myrinet)\n");
284                 free(net);
285                 return NULL;
286         }
287
288         while (cur != NULL) {
289                 if (!xmlStrcmp(cur->name, "server"))
290                         net->server = xmlNodeGetContent(cur);
291
292                 if (!xmlStrcmp(cur->name, "port"))
293                         net->port = atoi(xmlNodeGetContent(cur));
294
295                 cur = cur->next;
296         } 
297
298         if (net->server == NULL) {
299                 printf("error: <server> tag required\n");
300                 free(net);
301                 return NULL;
302         }
303         
304         return net;
305 }
306
307 static int xml_mds(xmlDocPtr doc, xmlNodePtr root, 
308                    char *serv_name, char *serv_uuid) {
309         xmlNodePtr cur = root->xmlChildrenNode;
310         char *fstype = NULL, *device = NULL;
311         int rc;
312
313         printf("--- Setting up MDS ---\n");
314         while (cur != NULL) {
315                 if (!xmlStrcmp(cur->name, "fstype"))
316                         fstype = xmlNodeGetContent(cur);
317
318                 if (!xmlStrcmp(cur->name, "device"))
319                         device = xmlNodeGetContent(cur);
320  
321                 /* FIXME: Parse the network bits
322                  * if (!xmlStrcmp(cur->name, "network")) {
323                  *       net = xml_network(doc, cur);
324                  *       if (net == NULL)
325                  *               return -1;
326                  * }
327                  * free(net);
328                  */
329                 cur = cur->next;
330         } 
331
332         if ((fstype == NULL) || (device == NULL)) {
333                 printf("error: <fstype> and <device> tags required\n");
334                 return -1;
335         }
336
337         if ((rc = xml_command("newdev", NULL)) != 0)
338                 return rc;
339
340         if ((rc = xml_command("attach","mds",serv_name,serv_uuid,NULL)) != 0)
341                 return rc;
342
343         if ((rc = xml_command("setup", device, fstype, NULL)) != 0)
344                 return rc;
345
346         return 0;
347 }
348         
349 static int xml_obd(xmlDocPtr doc, xmlNodePtr root, 
350                    char *serv_name, char *serv_uuid) {
351         char *obdtype, *format = NULL, *fstype = NULL, *device = NULL;
352         xmlNodePtr cur = root->xmlChildrenNode;
353         int rc;
354
355         obdtype = xmlGetProp(root, "type");
356         printf("--- Setting up OBD ---\n");
357
358         while (cur != NULL) {
359                 if (!xmlStrcmp(cur->name, "fstype"))
360                         fstype = xmlNodeGetContent(cur);
361
362                 if (!xmlStrcmp(cur->name, "device"))
363                         device = xmlNodeGetContent(cur);
364  
365                 if (!xmlStrcmp(cur->name, "autoformat"))
366                         format = xmlNodeGetContent(cur);
367
368                 cur = cur->next;
369         } 
370
371         if ((obdtype == NULL) || (fstype == NULL) || (device == NULL)) {
372                 printf("error: 'type' attrib and <fstype> "
373                        "and <device> tags required\n");
374                 return -1;
375         }
376
377         /* FIXME: Building and configuring loopback devices should go here
378          * but is currently unsupported.  You'll have to use the scripts
379          * for now until support is added, or specify a real device.
380          */
381         
382         if ((rc = xml_command("newdev", NULL)) != 0)
383                 return rc;
384
385         if ((rc = xml_command("attach", obdtype,
386             serv_name,serv_uuid, NULL)) != 0)
387                 return rc;
388
389         if ((rc = xml_command("setup", device, fstype, NULL)) != 0)
390                 return rc;
391
392         return 0;
393 }
394
395 static int xml_ost(xmlDocPtr doc, xmlNodePtr root, 
396                    char *serv_name, char *serv_uuid) {
397         char *server_name = NULL, *server_uuid = NULL;
398         char *failover_name = NULL, *failover_uuid = NULL;
399         xmlNodePtr cur = root->xmlChildrenNode;
400         int server_num, failover_num, rc;
401
402         printf("--- Setting up OST ---\n");
403         while (cur != NULL) {
404                 if (!xmlStrcmp(cur->name, "server_id")) {
405                         server_num = atoi(xmlGetProp(cur, "num"));
406                         server_name = xmlGetProp(cur, "name");
407                         server_uuid = xmlGetProp(cur, "uuid");
408                 }
409
410                 /* FIXME: Properly handle multiple failover servers */
411                 if (!xmlStrcmp(cur->name, "failover_id")) {
412                         failover_num = atoi(xmlGetProp(cur, "num"));
413                         failover_name = xmlGetProp(cur, "name");
414                         failover_uuid = xmlGetProp(cur, "uuid");
415                 }
416
417                 cur = cur->next;
418         } 
419
420         if ((server_name == NULL) || (server_uuid == NULL)) {
421                 printf("error: atleast the <server_id> tag is required\n");
422                 return -1;
423         }
424         
425         if ((rc = xml_command("newdev", NULL)) != 0)
426                 return rc;
427
428         if ((rc = xml_command("attach","ost",serv_name,serv_uuid,NULL)) != 0)
429                 return rc;
430
431         if ((rc = xml_command("setup", server_name, NULL)) != 0)
432                 return rc;
433
434         return 0;
435 }
436
437 static int xml_osc(xmlDocPtr doc, xmlNodePtr root, 
438                    char *serv_name, char *serv_uuid) {
439         char *ost_name = NULL, *ost_uuid = NULL;
440         xmlNodePtr cur = root->xmlChildrenNode;
441         int ost_num, rc = 0;
442
443         printf("--- Setting up OSC ---\n");
444         while (cur != NULL) {
445                 if (!xmlStrcmp(cur->name, "service_id")) {
446                         ost_num = atoi(xmlGetProp(cur, "num"));
447                         ost_name = xmlGetProp(cur, "name");
448                         ost_uuid = xmlGetProp(cur, "uuid");
449                 }
450
451                 cur = cur->next;
452         } 
453
454         if ((ost_name == NULL) || (ost_uuid == NULL)) {
455                 printf("error: atleast the <service_id> tag is required\n");
456                 return -1;
457         }
458
459         if ((rc = xml_command("newdev", NULL)) != 0)
460                 return rc;
461
462         if ((rc = xml_command("attach","osc",serv_name,serv_uuid,NULL)) != 0)
463                 return rc;
464
465         if ((rc = xml_command("setup", ost_uuid, "localhost", NULL)) != 0)
466                 return rc;
467
468         return 0;
469 }
470
471 static int xml_mdc(xmlDocPtr doc, xmlNodePtr root, 
472                    char *serv_name, char *serv_uuid) {
473         char *mds_name = NULL, *mds_uuid = NULL;
474         xmlNodePtr cur = root->xmlChildrenNode;
475         int mds_num, rc = 0;
476
477         printf("--- Setting up MDC ---\n");
478         while (cur != NULL) {
479                 if (!xmlStrcmp(cur->name, "service_id")) {
480                         mds_num = atoi(xmlGetProp(cur, "num"));
481                         mds_name = xmlGetProp(cur, "name");
482                         mds_uuid = xmlGetProp(cur, "uuid");
483                 }
484
485                 cur = cur->next;
486         } 
487
488         if ((mds_name == NULL) || (mds_uuid == NULL)) {
489                 printf("error: atleast the <service_id> tag is required\n");
490                 return -1;
491         }
492
493         if ((rc = xml_command("newdev", NULL)) != 0) 
494                 return rc;
495
496         if ((rc = xml_command("attach","mdc",serv_name,serv_uuid,NULL)) != 0)
497                 return rc;
498
499         if ((rc = xml_command("setup", mds_uuid, "localhost", NULL)) != 0)
500                 return rc;
501                 
502         return 0;
503 }
504
505 static int xml_lov(xmlDocPtr doc, xmlNodePtr root, 
506                    char *serv_name, char *serv_uuid) {
507         printf("--- Setting up LOV ---\n");
508         return 0;
509 }
510
511 static int xml_router(xmlDocPtr doc, xmlNodePtr root, 
512                    char *serv_name, char *serv_uuid) {
513         printf("--- Setting up ROUTER ---\n");
514         return 0;
515 }
516
517 static int xml_ldlm(xmlDocPtr doc, xmlNodePtr root, 
518                    char *serv_name, char *serv_uuid) {
519         int rc;
520
521         printf("--- Setting up LDLM ---\n");
522         if ((rc = xml_command("newdev", NULL)) != 0)
523                 return rc;
524
525         if ((rc = xml_command("attach","ldlm",serv_name,serv_uuid,NULL)) != 0)
526                 return rc;
527
528         if ((rc = xml_command("setup", NULL)) != 0)
529                 return rc;
530
531         return 0;
532 }
533
534 static int xml_service(xmlDocPtr doc, xmlNodePtr root, 
535                        int serv_num, char *serv_name, char *serv_uuid) {
536         xmlNodePtr cur = root;
537         char *name, *uuid;
538
539         while (cur != NULL) {
540                 name = xmlGetProp(cur, "name");
541                 uuid = xmlGetProp(cur, "uuid");
542
543                 if (xmlStrcmp(name, serv_name) ||
544                     xmlStrcmp(uuid, serv_uuid)) {
545                         cur = cur->next;
546                         continue;
547                 }
548
549                 if (!xmlStrcmp(cur->name, "mds"))
550                         return xml_mds(doc, cur, name, uuid);
551                 else if (!xmlStrcmp(cur->name, "obd"))
552                         return xml_obd(doc, cur, name, uuid);
553                 else if (!xmlStrcmp(cur->name, "ost"))
554                         return xml_ost(doc, cur, name, uuid);
555                 else if (!xmlStrcmp(cur->name, "osc"))
556                         return xml_osc(doc, cur, name, uuid);
557                 else if (!xmlStrcmp(cur->name, "mdc"))
558                         return xml_mdc(doc, cur, name, uuid);
559                 else if (!xmlStrcmp(cur->name, "lov"))
560                         return xml_lov(doc, cur, name, uuid);
561                 else if (!xmlStrcmp(cur->name, "router"))
562                         return xml_router(doc, cur, name, uuid);
563                 else if (!xmlStrcmp(cur->name, "ldlm"))
564                         return xml_ldlm(doc, cur, name, uuid);
565                 else
566                         return -1;        
567
568                 cur = cur->next;
569         }
570
571         printf("error: No XML config branch for name=%s uuid=%s\n",
572                 serv_name, serv_uuid); 
573         return -1; 
574 }
575
576 static int xml_profile(xmlDocPtr doc, xmlNodePtr root, 
577                        int prof_num, char *prof_name, char *prof_uuid) {
578         xmlNodePtr parent, cur = root;
579         char *name, *uuid, *srv_name, *srv_uuid;
580         int rc = 0, num;
581
582         while (cur != NULL) {
583                 name = xmlGetProp(cur, "name");
584                 uuid = xmlGetProp(cur, "uuid");
585
586                 if (xmlStrcmp(cur->name, "profile") || 
587                     xmlStrcmp(name, prof_name)          ||
588                     xmlStrcmp(uuid, prof_uuid)) {
589                         cur = cur->next;
590                         continue;
591                 }
592
593                 /* FIXME: Doesn't understand mountpoints yet
594                  *        xml_mountpoint(doc, root, ...);
595                  */    
596
597                 /* Setup each service in turn
598                  * FIXME: Should be sorted by "num" attr, we shouldn't
599                  *        assume they're in order in the XML document.
600                  */
601                 parent = cur;
602                 cur = cur->xmlChildrenNode;
603                 while (cur != NULL) {
604                         if (!xmlStrcmp(cur->name, "service_id")) {
605                                 num = atoi(xmlGetProp(cur, "num"));
606                                 rc = xml_service(doc, root, num,
607                                         srv_name = xmlGetProp(cur, "name"),
608                                         srv_uuid = xmlGetProp(cur, "uuid"));
609                                 if (rc != 0) {
610                                         printf("error: service config\n");
611                                         return rc;
612                                 }
613                         }
614
615                         cur = cur->next;
616                 }
617
618                 cur = parent->next;
619         }
620
621         return rc; 
622 }
623
624 static int xml_node(xmlDocPtr doc, xmlNodePtr root) {
625         xmlNodePtr parent, cur = root;
626         char *name, *uuid;
627         int rc = 0, num;
628         
629         /* Walk the node tags looking for ours */
630         while (cur != NULL) {
631                 if (xmlStrcmp(cur->name, "node")) {
632                         cur = cur->next;
633                         continue;
634                 }
635
636                 name = xmlGetProp(cur, "name");
637                 if (name == NULL)
638                         return -1;
639
640                 uuid = xmlGetProp(cur, "uuid");
641                 if (uuid == NULL)
642                         return -1;
643
644                 /* FIXME: Verify our NAME and UUID against /etc/lustre/id
645                  *        so we're sure we are who we think we are.
646                  */
647
648                 /* Setup each profile in turn
649                  * FIXME: Should be sorted by "num" attr, we shouldn't
650                  *        assume they're in order in the XML document.
651                  */
652                 parent = cur;
653                 cur = cur->xmlChildrenNode;
654                 while (cur != NULL) {
655                         if (!xmlStrcmp(cur->name, "profile_id")) {
656                                 num = atoi(xmlGetProp(cur, "num"));
657                                 rc = xml_profile(doc, root, num,
658                                                  xmlGetProp(cur, "name"),
659                                                  xmlGetProp(cur, "uuid"));
660                                 if (rc != 0)
661                                         return rc;
662                         }
663
664                         cur = cur->next;
665                 }
666
667                 cur = parent->next;
668         }
669
670         return rc;
671 }
672
673 static int do_xml(char *func, char *file)
674 {
675         xmlDocPtr doc;
676         xmlNodePtr cur;
677         int rc;
678
679         doc = xmlParseFile(file);
680         if (doc == NULL) {
681                 fprintf(stderr, "error: Unable to parse XML\n");
682                 return -1; 
683         }
684
685         cur = xmlDocGetRootElement(doc);
686         if (cur == NULL) {
687                 fprintf(stderr, "error: Empty XML\n");
688                 xmlFreeDoc(doc);
689                 return -1;
690         }
691         
692         if (xmlStrcmp(cur->name, (const xmlChar *)"lustre")) {
693                 fprintf(stderr, "error: Root node != <lustre>\n");
694                 xmlFreeDoc(doc);
695                 return -1;
696         }
697
698         /* FIXME: Validate the XML against the DTD here */
699     
700         /* FIXME: Merge all the text nodes under each branch and 
701          *        prune empty nodes.  Just to make the parsing more
702          *        tolerant, the exact location of nested tags isn't
703          *        critical for this.
704          */
705         
706         rc = xml_node(doc, cur->xmlChildrenNode);
707         xmlFreeDoc(doc);
708
709         return rc;
710 }
711
712 static int do_device(char *func, int dev)
713 {
714         struct obd_ioctl_data data;
715
716         memset(&data, 0, sizeof(data));
717
718         data.ioc_dev = dev;
719
720         if (getfd(func))
721                 return -1;
722
723         if (obd_ioctl_pack(&data, &buf, max)) {
724                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
725                 return -2;
726         }
727
728         return ioctl(fd, OBD_IOC_DEVICE , buf);
729 }
730
731 static int jt_device(int argc, char **argv)
732 {
733         do_disconnect(argv[0], 1);
734
735         if (argc != 2) {
736                 fprintf(stderr, "usage: %s devno\n", cmdname(argv[0]));
737                 return -1;
738         }
739
740         rc = do_device(argv[0], strtoul(argv[1], NULL, 0));
741
742         if (rc < 0)
743                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
744                         strerror(rc = errno));
745
746         return rc;
747 }
748
749 static int jt_connect(int argc, char **argv)
750 {
751         struct obd_ioctl_data data;
752
753         IOCINIT(data);
754
755         do_disconnect(argv[0], 1);
756
757         if (argc != 1) {
758                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
759                 return -1;
760         }
761
762         rc = ioctl(fd, OBD_IOC_CONNECT , &data);
763         if (rc < 0)
764                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
765                         OBD_IOC_CONNECT, strerror(rc = errno));
766         else
767                 conn_addr = data.ioc_addr;
768                 conn_cookie = data.ioc_cookie;
769         return rc;
770 }
771
772 static int jt_disconnect(int argc, char **argv)
773 {
774         if (argc != 1) {
775                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
776                 return -1;
777         }
778
779         if (conn_addr == -1)
780                 return 0;
781
782         return do_disconnect(argv[0], 0);
783 }
784
785 static int jt__xml(int argc, char **argv)
786 {
787         if (argc < 2) {
788                 fprintf(stderr, "usage: %s <xml file> <command [args ...]>\n",
789                         cmdname(argv[0]));
790                 return -1;
791         }
792
793         return do_xml("xml", argv[1]);
794 }
795
796 static int jt__device(int argc, char **argv)
797 {
798         char *arg2[3];
799         int ret;
800
801         if (argc < 3) {
802                 fprintf(stderr, "usage: %s devno <command [args ...]>\n",
803                         cmdname(argv[0]));
804                 return -1;
805         }
806
807         rc = do_device("device", strtoul(argv[1], NULL, 0));
808
809         if (!rc) {
810                 arg2[0] = "connect";
811                 arg2[1] = NULL;
812                 rc = jt_connect(1, arg2);
813         }
814
815         if (!rc)
816                 rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
817
818         ret = do_disconnect(argv[0], 0);
819         if (!rc)
820                 rc = ret;
821
822         return rc;
823 }
824
825 static int jt__threads(int argc, char **argv)
826 {
827         int threads, next_thread;
828         int verbose;
829         int i, j;
830
831         if (argc < 5) {
832                 fprintf(stderr,
833                         "usage: %s numthreads verbose devno <cmd [args ...]>\n",
834                         argv[0]);
835                 return -1;
836         }
837
838         threads = strtoul(argv[1], NULL, 0);
839
840         verbose = get_verbose(argv[2]);
841
842         printf("%s: starting %d threads on device %s running %s\n",
843                argv[0], threads, argv[3], argv[4]);
844
845         for (i = 1, next_thread = verbose; i <= threads; i++) {
846                 rc = fork();
847                 if (rc < 0) {
848                         fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
849                                 strerror(rc = errno));
850                         break;
851                 } else if (rc == 0) {
852                         thread = i;
853                         argv[2] = "--device";
854                         return jt__device(argc - 2, argv + 2);
855                 } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
856                         printf("%s: thread #%d (PID %d) started\n",
857                                argv[0], i, rc);
858                 rc = 0;
859         }
860
861         if (!thread) { /* parent process */
862                 if (!verbose)
863                         printf("%s: started %d threads\n\n", argv[0], i - 1);
864                 else
865                         printf("\n");
866
867                 for (j = 1; j < i; j++) {
868                         int status;
869                         int ret = wait(&status);
870
871                         if (ret < 0) {
872                                 fprintf(stderr, "error: %s: wait - %s\n",
873                                         argv[0], strerror(errno));
874                                 if (!rc)
875                                         rc = errno;
876                         } else {
877                                 /*
878                                  * This is a hack.  We _should_ be able to use
879                                  * WIFEXITED(status) to see if there was an
880                                  * error, but it appears to be broken and it
881                                  * always returns 1 (OK).  See wait(2).
882                                  */
883                                 int err = WEXITSTATUS(status);
884                                 if (err)
885                                         fprintf(stderr,
886                                                 "%s: PID %d had rc=%d\n",
887                                                 argv[0], ret, err);
888                                 if (!rc)
889                                         rc = err;
890                         }
891                 }
892         }
893
894         return rc;
895 }
896
897 static int jt_detach(int argc, char **argv)
898 {
899         struct obd_ioctl_data data;
900
901         IOCINIT(data);
902
903         if (argc != 1) {
904                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
905                 return -1;
906         }
907
908         if (obd_ioctl_pack(&data, &buf, max)) {
909                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
910                 return -2;
911         }
912
913         rc = ioctl(fd, OBD_IOC_DETACH , buf);
914         if (rc < 0)
915                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
916                         strerror(rc=errno));
917
918         return rc;
919 }
920
921 static int jt_cleanup(int argc, char **argv)
922 {
923         struct obd_ioctl_data data;
924
925         IOCINIT(data);
926
927         if (argc != 1) {
928                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
929                 return -1;
930         }
931
932         rc = ioctl(fd, OBD_IOC_CLEANUP , &data);
933         if (rc < 0)
934                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
935                         strerror(rc=errno));
936
937         return rc;
938 }
939
940 static int jt_newdev(int argc, char **argv)
941 {
942         struct obd_ioctl_data data;
943
944         if (getfd(argv[0]))
945                 return -1;
946
947         IOCINIT(data);
948
949         if (argc != 1) {
950                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
951                 return -1;
952         }
953
954         rc = ioctl(fd, OBD_IOC_NEWDEV , &data);
955         if (rc < 0)
956                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
957                         strerror(rc=errno));
958         else {
959                 printf("Current device set to %d\n", data.ioc_dev);
960         }
961
962         return rc;
963 }
964
965 static int jt_list(int argc, char **argv)
966 {
967         char buf[1024];
968         struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
969
970         if (getfd(argv[0]))
971                 return -1;
972
973         memset(buf, 0, sizeof(buf));
974         data->ioc_version = OBD_IOCTL_VERSION;
975         data->ioc_addr = conn_addr;
976         data->ioc_cookie = conn_addr;
977         data->ioc_len = sizeof(buf);
978         data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
979
980         if (argc != 1) {
981                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
982                 return -1;
983         }
984
985         rc = ioctl(fd, OBD_IOC_LIST , data);
986         if (rc < 0)
987                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
988                         strerror(rc=errno));
989         else {
990                 printf("%s", data->ioc_bulk);
991         }
992
993         return rc;
994 }
995
996 static int jt_attach(int argc, char **argv)
997 {
998         struct obd_ioctl_data data;
999
1000         IOCINIT(data);
1001
1002         if (argc != 2 && argc != 3 && argc != 4) {
1003                 fprintf(stderr, "usage: %s type [name [uuid]]\n",
1004                         cmdname(argv[0]));
1005                 return -1;
1006         }
1007
1008         data.ioc_inllen1 =  strlen(argv[1]) + 1;
1009         data.ioc_inlbuf1 = argv[1];
1010         if (argc >= 3) {
1011                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1012                 data.ioc_inlbuf2 = argv[2];
1013         }
1014
1015         if (argc == 4) {
1016                 data.ioc_inllen3 = strlen(argv[3]) + 1;
1017                 data.ioc_inlbuf3 = argv[3];
1018         }
1019
1020         if (obd_ioctl_pack(&data, &buf, max)) {
1021                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1022                 return -2;
1023         }
1024
1025         rc = ioctl(fd, OBD_IOC_ATTACH , buf);
1026         if (rc < 0)
1027                 fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
1028                         OBD_IOC_ATTACH, strerror(rc = errno));
1029         else if (argc == 3) {
1030                 char name[1024];
1031                 if (strlen(argv[2]) > 128) {
1032                         printf("Name too long to set environment\n");
1033                         return -EINVAL;
1034                 }
1035                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
1036                 rc = setenv(name, argv[1], 1);
1037                 if (rc) {
1038                         printf("error setting env variable %s\n", name);
1039                 }
1040         }
1041
1042         return rc;
1043 }
1044
1045 #define N2D_OFF 0x100    /* So we can tell between error codes and devices */
1046
1047 static int do_name2dev(char *func, char *name)
1048 {
1049         struct obd_ioctl_data data;
1050
1051         if (getfd(func))
1052                 return -1;
1053
1054         IOCINIT(data);
1055
1056         data.ioc_inllen1 = strlen(name) + 1;
1057         data.ioc_inlbuf1 = name;
1058
1059         if (obd_ioctl_pack(&data, &buf, max)) {
1060                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
1061                 return -2;
1062         }
1063         rc = ioctl(fd, OBD_IOC_NAME2DEV , buf);
1064         if (rc < 0) {
1065                 fprintf(stderr, "error: %s: %s - %s\n", cmdname(func),
1066                         name, strerror(rc = errno));
1067                 return rc;
1068         }
1069
1070         memcpy((char *)(&data), buf, sizeof(data));
1071
1072         return data.ioc_dev + N2D_OFF;
1073 }
1074
1075 static int jt_name2dev(int argc, char **argv)
1076 {
1077         if (argc != 2) {
1078                 fprintf(stderr, "usage: %s name\n", cmdname(argv[0]));
1079                 return -1;
1080         }
1081
1082         rc = do_name2dev(argv[0], argv[1]);
1083         if (rc >= N2D_OFF) {
1084                 int dev = rc - N2D_OFF;
1085                 rc = do_device(argv[0], dev);
1086                 if (rc == 0)
1087                         printf("%d\n", dev);
1088         }
1089         return rc;
1090 }
1091
1092 static int jt_setup(int argc, char **argv)
1093 {
1094         struct obd_ioctl_data data;
1095
1096         IOCINIT(data);
1097
1098         if ( argc > 3) {
1099                 fprintf(stderr, "usage: %s [device] [fstype]\n",
1100                         cmdname(argv[0]));
1101                 return -1;
1102         }
1103
1104         data.ioc_dev = -1;
1105         if (argc > 1) {
1106                 if (argv[1][0] == '$') {
1107                         rc = do_name2dev(argv[0], argv[1] + 1);
1108                         if (rc >= N2D_OFF) {
1109                                 printf("%s is device %d\n", argv[1],
1110                                        rc - N2D_OFF);
1111                                 data.ioc_dev = rc - N2D_OFF;
1112                         }
1113                 } else
1114                         data.ioc_dev = strtoul(argv[1], NULL, 0);
1115                 data.ioc_inllen1 = strlen(argv[1]) + 1;
1116                 data.ioc_inlbuf1 = argv[1];
1117         }
1118         if ( argc == 3 ) {
1119                 data.ioc_inllen2 = strlen(argv[2]) + 1;
1120                 data.ioc_inlbuf2 = argv[2];
1121         }
1122
1123         if (obd_ioctl_pack(&data, &buf, max)) {
1124                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1125                 return -2;
1126         }
1127         rc = ioctl(fd, OBD_IOC_SETUP , buf);
1128         if (rc < 0)
1129                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1130                         strerror(rc = errno));
1131
1132         return rc;
1133 }
1134
1135
1136 static int jt_create(int argc, char **argv)
1137 {
1138         struct obd_ioctl_data data;
1139         struct timeval next_time;
1140         int count = 1, next_count;
1141         int verbose;
1142         int i;
1143
1144         IOCINIT(data);
1145         if (argc < 2 || argc > 4) {
1146                 fprintf(stderr, "usage: %s num [mode] [verbose]\n",
1147                         cmdname(argv[0]));
1148                 return -1;
1149         }
1150         count = strtoul(argv[1], NULL, 0);
1151
1152         if (argc > 2)
1153                 data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0);
1154         else
1155                 data.ioc_obdo1.o_mode = 0100644;
1156         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
1157
1158         verbose = get_verbose(argv[3]);
1159
1160         printf("%s: %d obdos\n", cmdname(argv[0]), count);
1161         gettimeofday(&next_time, NULL);
1162         next_time.tv_sec -= verbose;
1163
1164         for (i = 1, next_count = verbose; i <= count ; i++) {
1165                 rc = ioctl(fd, OBD_IOC_CREATE , &data);
1166                 if (rc < 0) {
1167                         fprintf(stderr, "error: %s: #%d - %s\n",
1168                                 cmdname(argv[0]), i, strerror(rc = errno));
1169                         break;
1170                 }
1171                 if (be_verbose(verbose, &next_time, i, &next_count, count))
1172                         printf("%s: #%d is object id %Ld\n", cmdname(argv[0]),
1173                                i, data.ioc_obdo1.o_id);
1174         }
1175         return rc;
1176 }
1177
1178 static int jt_setattr(int argc, char **argv)
1179 {
1180         struct obd_ioctl_data data;
1181
1182         IOCINIT(data);
1183         if (argc != 2) {
1184                 fprintf(stderr, "usage: %s id mode\n", cmdname(argv[0]));
1185                 return -1;
1186         }
1187
1188         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
1189         data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], NULL, 0);
1190         data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
1191
1192         rc = ioctl(fd, OBD_IOC_SETATTR , &data);
1193         if (rc < 0)
1194                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1195                         strerror(rc = errno));
1196
1197         return rc;
1198 }
1199
1200 static int jt_destroy(int argc, char **argv)
1201 {
1202         struct obd_ioctl_data data;
1203
1204         IOCINIT(data);
1205         if (argc != 2) {
1206                 fprintf(stderr, "usage: %s id\n", cmdname(argv[0]));
1207                 return -1;
1208         }
1209
1210         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
1211         data.ioc_obdo1.o_mode = S_IFREG|0644;
1212
1213         rc = ioctl(fd, OBD_IOC_DESTROY , &data);
1214         if (rc < 0)
1215                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1216                         strerror(rc = errno));
1217
1218         return rc;
1219 }
1220
1221 static int jt_getattr(int argc, char **argv)
1222 {
1223         struct obd_ioctl_data data;
1224
1225         if (argc != 2) {
1226                 fprintf(stderr, "usage: %s id\n", cmdname(argv[0]));
1227                 return -1;
1228         }
1229
1230         IOCINIT(data);
1231         data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
1232         /* to help obd filter */
1233         data.ioc_obdo1.o_mode = 0100644;
1234         data.ioc_obdo1.o_valid = 0xffffffff;
1235         printf("%s: object id %Ld\n", cmdname(argv[0]), data.ioc_obdo1.o_id);
1236
1237         rc = ioctl(fd, OBD_IOC_GETATTR , &data);
1238         if (rc) {
1239                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1240                         strerror(rc=errno));
1241         } else {
1242                 printf("%s: object id %Ld, mode %o\n", cmdname(argv[0]),
1243                        data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
1244         }
1245         return rc;
1246 }
1247
1248 static int jt_test_getattr(int argc, char **argv)
1249 {
1250         struct obd_ioctl_data data;
1251         struct timeval start, next_time;
1252         int i, count, next_count;
1253         int verbose;
1254
1255         if (argc != 2 && argc != 3) {
1256                 fprintf(stderr, "usage: %s count [verbose]\n",cmdname(argv[0]));
1257                 return -1;
1258         }
1259
1260         IOCINIT(data);
1261         count = strtoul(argv[1], NULL, 0);
1262
1263         if (argc == 3)
1264                 verbose = get_verbose(argv[2]);
1265         else
1266                 verbose = 1;
1267
1268         data.ioc_obdo1.o_valid = 0xffffffff;
1269         data.ioc_obdo1.o_id = 2;
1270         gettimeofday(&start, NULL);
1271         next_time.tv_sec = start.tv_sec - verbose;
1272         next_time.tv_usec = start.tv_usec;
1273         printf("%s: getting %d attrs (testing only): %s", cmdname(argv[0]),
1274                count, ctime(&start.tv_sec));
1275
1276         for (i = 1, next_count = verbose; i <= count; i++) {
1277                 rc = ioctl(fd, OBD_IOC_GETATTR , &data);
1278                 if (rc < 0) {
1279                         fprintf(stderr, "error: %s: #%d - %s\n",
1280                                 cmdname(argv[0]), i, strerror(rc = errno));
1281                         break;
1282                 } else {
1283                         if (be_verbose(verbose, &next_time, i,&next_count,count))
1284                         printf("%s: got attr #%d\n", cmdname(argv[0]), i);
1285                 }
1286         }
1287
1288         if (!rc) {
1289                 struct timeval end;
1290                 double diff;
1291
1292                 gettimeofday(&end, NULL);
1293
1294                 diff = difftime(&end, &start);
1295
1296                 --i;
1297                 printf("%s: %d attrs in %.4gs (%.4g attr/s): %s",
1298                        cmdname(argv[0]), i, diff, (double)i / diff,
1299                        ctime(&end.tv_sec));
1300         }
1301         return rc;
1302 }
1303
1304 static int jt_test_brw(int argc, char **argv)
1305 {
1306         struct obd_ioctl_data data;
1307         struct timeval start, next_time;
1308         char *bulk, *b;
1309         int pages = 1, obdos = 1, count, next_count;
1310         int verbose = 1, write = 0, rw;
1311         int i, o, p;
1312         int len;
1313
1314         if (argc < 2 || argc > 6) {
1315                 fprintf(stderr,
1316                         "usage: %s count [write [verbose [pages [obdos]]]]\n",
1317                         cmdname(argv[0]));
1318                 return -1;
1319         }
1320
1321         count = strtoul(argv[1], NULL, 0);
1322
1323         if (argc >= 3) {
1324                 if (argv[2][0] == 'w' || argv[2][0] == '1')
1325                         write = 1;
1326                 else if (argv[2][0] == 'r' || argv[2][0] == '0')
1327                         write = 0;
1328
1329                 verbose = get_verbose(argv[3]);
1330         }
1331
1332         if (argc >= 5)
1333                 pages = strtoul(argv[4], NULL, 0);
1334         if (argc >= 6)
1335                 obdos = strtoul(argv[5], NULL, 0);
1336
1337         if (obdos != 1 && obdos != 2) {
1338                 fprintf(stderr, "error: %s: only 1 or 2 obdos supported\n",
1339                         cmdname(argv[0]));
1340                 return -2;
1341         }
1342
1343         len = pages * PAGE_SIZE;
1344
1345         bulk = calloc(obdos, len);
1346         if (!bulk) {
1347                 fprintf(stderr, "error: %s: no memory allocating %dx%d pages\n",
1348                         cmdname(argv[0]), obdos, pages);
1349                 return -2;
1350         }
1351         IOCINIT(data);
1352         data.ioc_obdo1.o_id = 2;
1353         data.ioc_count = len;
1354         data.ioc_offset = 0;
1355         data.ioc_plen1 = len;
1356         data.ioc_pbuf1 = bulk;
1357         if (obdos > 1) {
1358                 data.ioc_obdo2.o_id = 3;
1359                 data.ioc_plen2 = len;
1360                 data.ioc_pbuf2 = bulk + len;
1361         }
1362
1363         gettimeofday(&start, NULL);
1364         next_time.tv_sec = start.tv_sec - verbose;
1365         next_time.tv_usec = start.tv_usec;
1366
1367         printf("%s: %s %d (%dx%d pages) (testing only): %s",
1368                cmdname(argv[0]), write ? "writing" : "reading",
1369                count, obdos, pages, ctime(&start.tv_sec));
1370
1371         /*
1372          * We will put in the start time (and loop count inside the loop)
1373          * at the beginning of each page so that we will be able to validate
1374          * (at some later time) whether the data actually made it or not.
1375          *
1376          * XXX we do not currently use any of this memory in OBD_IOC_BRW_*
1377          *     just to avoid the overhead of the copy_{to,from}_user.  It
1378          *     can be fixed if we ever need to send real data around.
1379          */
1380         for (o = 0, b = bulk; o < obdos; o++)
1381                 for (p = 0; p < pages; p++, b += PAGE_SIZE)
1382                         memcpy(b, &start, sizeof(start));
1383
1384         rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
1385         for (i = 1, next_count = verbose; i <= count; i++) {
1386                 if (write) {
1387                         b = bulk + sizeof(struct timeval);
1388                         for (o = 0; o < obdos; o++)
1389                                 for (p = 0; p < pages; p++, b += PAGE_SIZE)
1390                                         memcpy(b, &count, sizeof(count));
1391                 }
1392
1393                 rc = ioctl(fd, rw, &data);
1394                 if (rc) {
1395                         fprintf(stderr, "error: %s: #%d - %s on %s\n",
1396                                 cmdname(argv[0]), i, strerror(rc = errno),
1397                                 write ? "write" : "read");
1398                         break;
1399                 } else if (be_verbose(verbose, &next_time, i,&next_count,count))
1400                         printf("%s: %s number %d\n", cmdname(argv[0]),
1401                                write ? "write" : "read", i);
1402         }
1403
1404         free(bulk);
1405
1406         if (!rc) {
1407                 struct timeval end;
1408                 double diff;
1409
1410                 gettimeofday(&end, NULL);
1411
1412                 diff = difftime(&end, &start);
1413
1414                 --i;
1415                 printf("%s: %s %dx%dx%d pages in %.4gs (%.4g pg/s): %s",
1416                        cmdname(argv[0]), write ? "wrote" : "read", obdos,
1417                        pages, i, diff, (double)obdos * i * pages / diff,
1418                        ctime(&end.tv_sec));
1419         }
1420         return rc;
1421 }
1422
1423 static int jt_lov_config(int argc, char **argv)
1424 {
1425         struct obd_ioctl_data data;
1426         struct lov_desc desc; 
1427         uuid_t *uuidarray;
1428         int size, i;
1429         IOCINIT(data);
1430
1431         if (argc <= 5 ){
1432                 Parser_printhelp("lovconfig"); 
1433                 return -1;
1434         }
1435
1436         if (strlen(argv[1]) > sizeof(uuid_t) - 1) { 
1437                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", 
1438                         size);
1439                 return -ENOMEM;
1440         }
1441             
1442         memset(&desc, 0, sizeof(desc)); 
1443         strcpy(desc.ld_uuid, argv[1]); 
1444         desc.ld_default_stripecount = strtoul(argv[2], NULL, 0); 
1445         desc.ld_default_stripesize = strtoul(argv[3], NULL, 0); 
1446         desc.ld_pattern = strtoul(argv[4], NULL, 0); 
1447         desc.ld_tgt_count = argc - 5;
1448
1449
1450         size = sizeof(uuid_t) * desc.ld_tgt_count;
1451         uuidarray = malloc(size);
1452         if (!uuidarray) { 
1453                 fprintf(stderr, "lov_config: no %dB memory for uuid's\n", 
1454                         size);
1455                 return -ENOMEM;
1456         }
1457         memset(uuidarray, 0, size); 
1458         for (i=5 ; i < argc ; i++) { 
1459                 char *buf = (char *) (uuidarray + i -5 );
1460                 if (strlen(argv[i]) >= sizeof(uuid_t)) { 
1461                         fprintf(stderr, "lov_config: arg %d (%s) too long\n",  
1462                                 i, argv[i]);
1463                         free(uuidarray);
1464                         return -EINVAL;
1465                 }
1466                 strcpy(buf, argv[i]); 
1467         }
1468
1469         data.ioc_inllen1 = sizeof(desc); 
1470         data.ioc_inlbuf1 = (char *)&desc;
1471         data.ioc_inllen2 = size;
1472         data.ioc_inlbuf2 = (char *)uuidarray;
1473
1474         if (obd_ioctl_pack(&data, &buf, max)) {
1475                 fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
1476                 return -EINVAL;
1477         }
1478
1479         rc = ioctl(fd, OBD_IOC_LOV_CONFIG , buf);
1480         if (rc < 0)
1481                 fprintf(stderr, "lov_config: error: %s: %s\n", 
1482                         cmdname(argv[0]),strerror(rc = errno));
1483         free(uuidarray);
1484         return rc;
1485 }
1486
1487
1488 static int jt_test_ldlm(int argc, char **argv)
1489 {
1490         struct obd_ioctl_data data;
1491
1492         IOCINIT(data);
1493         if (argc != 1) {
1494                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
1495                 return 1;
1496         }
1497
1498         rc = ioctl(fd, IOC_LDLM_TEST, &data);
1499         if (rc)
1500                 fprintf(stderr, "error: %s: test failed: %s\n",
1501                         cmdname(argv[0]), strerror(rc = errno));
1502         return rc;
1503 }
1504
1505 static int jt_newconn(int argc, char **argv)
1506 {
1507         struct obd_ioctl_data data;
1508
1509         IOCINIT(data);
1510         if (argc != 1) {
1511                 fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
1512                 return -1;
1513         }
1514
1515         rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN , &data);
1516         if (rc < 0)
1517                 fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
1518                         strerror(rc = errno));
1519
1520         return rc;
1521 }
1522
1523 static int jt_quit(int argc, char **argv)
1524 {
1525         Parser_quit(argc, argv);
1526
1527         return rc;
1528 }
1529
1530 command_t cmdlist[] = {
1531         /* Metacommands */
1532         {"--xml", jt__xml, 0, "--xml <xml file> <command [args ...]>"},
1533         {"--device", jt__device, 0, "--device <devno> <command [args ...]>"},
1534         {"--threads", jt__threads, 0,
1535                 "--threads <threads> <devno> <command [args ...]>"},
1536
1537         /* Device configuration commands */
1538         {"lovconfig", jt_lov_config, 0, "configure lov data on MDS "
1539          "(usage: lov-uuid stripecount, stripesize, pattern, UUID1, [UUID2, ...])"}, 
1540         {"list", jt_list, 0, "list the devices (no args)"},
1541         {"newdev", jt_newdev, 0, "set device to a new unused obd (no args)"},
1542         {"device", jt_device, 0, "set current device (args device_no name)"},
1543         {"name2dev", jt_name2dev, 0, "set device by name (args name)"},
1544         {"attach", jt_attach, 0, "name the type of device (args: type data"},
1545         {"setup", jt_setup, 0, "setup device (args: <blkdev> [data]"},
1546         {"detach", jt_detach, 0, "detach the current device (arg: )"},
1547         {"cleanup", jt_cleanup, 0, "cleanup the current device (arg: )"},
1548
1549         /* Session commands */
1550         {"connect", jt_connect, 0, "connect - get a connection to device"},
1551         {"disconnect", jt_disconnect, 0,
1552                 "disconnect - break connection to device"},
1553
1554         /* Session operations */
1555         {"create", jt_create, 0, "create [count [mode [verbose]]]"},
1556         {"destroy", jt_destroy, 0, "destroy <id>"},
1557         {"getattr", jt_getattr, 0, "getattr <id>"},
1558         {"setattr", jt_setattr, 0, "setattr <id> <mode>"},
1559         {"newconn", jt_newconn, 0, "newconn [newuuid]"},
1560         {"test_getattr", jt_test_getattr, 0, "test_getattr <count> [verbose]"},
1561         {"test_brw", jt_test_brw, 0, "test_brw <count> [write [verbose]]"},
1562         {"test_ldlm", jt_test_ldlm, 0, "test lock manager (no args)"},
1563
1564         /* User interface commands */
1565         {"help", Parser_help, 0, "help"},
1566         {"exit", jt_quit, 0, "quit"},
1567         {"quit", jt_quit, 0, "quit"},
1568         { 0, 0, 0, NULL }
1569 };
1570
1571
1572 static void signal_server(int sig)
1573 {
1574         if (sig == SIGINT) {
1575                 do_disconnect("sigint", 1);
1576                 exit(1);
1577         } else {
1578                 fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
1579         }
1580 }
1581
1582 int main(int argc, char **argv)
1583 {
1584         struct sigaction sigact;
1585
1586         sigact.sa_handler = signal_server;
1587         sigfillset(&sigact.sa_mask);
1588         sigact.sa_flags = SA_RESTART;
1589         sigaction(SIGINT, &sigact, NULL);
1590
1591
1592         if (argc > 1) {
1593                 rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
1594         } else {
1595                 Parser_init("obdctl > ", cmdlist);
1596                 rc = Parser_commands();
1597         }
1598
1599         do_disconnect(argv[0], 1);
1600         return rc;
1601 }
1602