X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fobdctl.c;h=6bcc0d0db2a9afa89c2e767e2b5c29400ad74eb3;hp=29e40f151f6ab37b648073a219ce4e6aeddfb65d;hb=ce6fead2306cbfc7c6184eb232dddc26c98fac2e;hpb=175077343bd583286e167cfe729fc4925cbfd97a diff --git a/lustre/utils/obdctl.c b/lustre/utils/obdctl.c index 29e40f1..6bcc0d0 100644 --- a/lustre/utils/obdctl.c +++ b/lustre/utils/obdctl.c @@ -22,6 +22,7 @@ * */ + #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #define printk printf @@ -37,6 +39,9 @@ #include #include +#include +#include + #include #include #include @@ -52,18 +57,26 @@ #include "parser.h" #include +static int jt_newdev(int argc, char **argv); +static int jt_attach(int argc, char **argv); +static int jt_setup(int argc, char **argv); + + int fd = -1; -int connid = -1; +uint64_t conn_addr = -1; +uint64_t conn_cookie; char rawbuf[8192]; char *buf = rawbuf; int max = 8192; int thread; +int rc = 0; #define IOCINIT(data) \ do { \ memset(&data, 0, sizeof(data)); \ data.ioc_version = OBD_IOCTL_VERSION; \ - data.ioc_conn1 = connid; \ + data.ioc_addr = conn_addr; \ + data.ioc_cookie = conn_cookie; \ data.ioc_len = sizeof(data); \ if (fd < 0) { \ fprintf(stderr, "No device open, use device\n"); \ @@ -134,7 +147,19 @@ static char *cmdname(char *func) return func; } -#define difftime(a, b) \ +int getfd(char *func) +{ + if (fd == -1) + fd = open("/dev/obd", O_RDWR); + if (fd == -1) { + fprintf(stderr, "error: %s: opening /dev/obd: %s\n", + cmdname(func), strerror(errno)); + return -1; + } + return 0; +} + +#define difftime(a, b) \ ((double)(a)->tv_sec - (b)->tv_sec + \ ((double)((a)->tv_usec - (b)->tv_usec) / 1000000)) @@ -146,33 +171,59 @@ static int be_verbose(int verbose, struct timeval *next_time, if (!verbose) return 0; + if (next_time != NULL) + gettimeofday(&now, NULL); + /* A positive verbosity means to print every X iterations */ if (verbose > 0 && (next_num == NULL || num >= *next_num || num >= num_total)) { *next_num += verbose; - return 1; - } - - if (verbose < 0 && next_time != NULL) { - /* A negative verbosity means to print at most each X seconds */ - gettimeofday(&now, NULL); - if (difftime(&now, next_time) >= 0) { + if (next_time) { next_time->tv_sec = now.tv_sec - verbose; next_time->tv_usec = now.tv_usec; - return 1; } + return 1; + } + + /* A negative verbosity means to print at most each X seconds */ + if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){ + next_time->tv_sec = now.tv_sec - verbose; + next_time->tv_usec = now.tv_usec; + if (next_num) + *next_num = num; + return 1; } return 0; } +static int get_verbose(const char *arg) +{ + int verbose; + + if (!arg || arg[0] == 'v') + verbose = 1; + else if (arg[0] == 's' || arg[0] == 'q') + verbose = 0; + else + verbose = (int) strtoul(arg, NULL, 0); + + if (verbose < 0) + printf("Print status every %d seconds\n", -verbose); + else if (verbose == 1) + printf("Print status every operation\n"); + else if (verbose > 1) + printf("Print status every %d operations\n", verbose); + + return verbose; +} + static int do_disconnect(char *func, int verbose) { struct obd_ioctl_data data; - int rc; - if (connid == -1) - return 0; + if (conn_addr == -1) + return 0; IOCINIT(data); @@ -182,9 +233,9 @@ static int do_disconnect(char *func, int verbose) OBD_IOC_DISCONNECT, strerror(errno)); } else { if (verbose) - printf("%s: disconnected connid %d\n", cmdname(func), - connid); - connid = -1; + printf("%s: disconnected conn %Lx\n", cmdname(func), + conn_addr); + conn_addr = -1; } return rc; @@ -192,38 +243,503 @@ static int do_disconnect(char *func, int verbose) extern command_t cmdlist[]; -static int jt_device(int argc, char **argv) +static int xml_command(char *cmd, ...) { + va_list args; + char *arg, *cmds[8]; + int i = 1, j; + + cmds[0] = cmd; + va_start(args, cmd); + + while (((arg = va_arg(args, char *)) != NULL) && (i < 8)) { + cmds[i] = arg; + i++; + } + + va_end(args); + + printf("obdctl > "); + for (j = 0; j < i; j++) + printf("%s ", cmds[j]); + + printf("\n"); + + return Parser_execarg(i, cmds, cmdlist); +} + +static network_t *xml_network(xmlDocPtr doc, xmlNodePtr root) { + xmlNodePtr cur = root->xmlChildrenNode; + network_t *net; + + if ((net = (network_t *)calloc(1, sizeof(network_t))) == NULL) { + printf("error: unable to malloc network_t\n"); + return NULL; + } + + net->type = xmlGetProp(root, "type"); + if (net->type == NULL) { + printf("error: type attrib required (tcp, elan, myrinet)\n"); + free(net); + return NULL; + } + + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "server")) + net->server = xmlNodeGetContent(cur); + + if (!xmlStrcmp(cur->name, "port")) + net->port = atoi(xmlNodeGetContent(cur)); + + cur = cur->next; + } + + if (net->server == NULL) { + printf("error: tag required\n"); + free(net); + return NULL; + } + + return net; +} + +static int xml_mds(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + xmlNodePtr cur = root->xmlChildrenNode; + char *fstype = NULL, *device = NULL; + int rc; + + printf("--- Setting up MDS ---\n"); + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "fstype")) + fstype = xmlNodeGetContent(cur); + + if (!xmlStrcmp(cur->name, "device")) + device = xmlNodeGetContent(cur); + + /* FIXME: Parse the network bits + * if (!xmlStrcmp(cur->name, "network")) { + * net = xml_network(doc, cur); + * if (net == NULL) + * return -1; + * } + * free(net); + */ + cur = cur->next; + } + + if ((fstype == NULL) || (device == NULL)) { + printf("error: and tags required\n"); + return -1; + } + + if ((rc = xml_command("newdev", NULL)) != 0) + return rc; + + if ((rc = xml_command("attach","mds",serv_name,serv_uuid,NULL)) != 0) + return rc; + + if ((rc = xml_command("setup", device, fstype, NULL)) != 0) + return rc; + + return 0; +} + +static int xml_obd(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + char *obdtype, *format = NULL, *fstype = NULL, *device = NULL; + xmlNodePtr cur = root->xmlChildrenNode; + int rc; + + obdtype = xmlGetProp(root, "type"); + printf("--- Setting up OBD ---\n"); + + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "fstype")) + fstype = xmlNodeGetContent(cur); + + if (!xmlStrcmp(cur->name, "device")) + device = xmlNodeGetContent(cur); + + if (!xmlStrcmp(cur->name, "autoformat")) + format = xmlNodeGetContent(cur); + + cur = cur->next; + } + + if ((obdtype == NULL) || (fstype == NULL) || (device == NULL)) { + printf("error: 'type' attrib and " + "and tags required\n"); + return -1; + } + + /* FIXME: Building and configuring loopback devices should go here + * but is currently unsupported. You'll have to use the scripts + * for now until support is added, or specify a real device. + */ + + if ((rc = xml_command("newdev", NULL)) != 0) + return rc; + + if ((rc = xml_command("attach", obdtype, + serv_name,serv_uuid, NULL)) != 0) + return rc; + + if ((rc = xml_command("setup", device, fstype, NULL)) != 0) + return rc; + + return 0; +} + +static int xml_ost(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + char *server_name = NULL, *server_uuid = NULL; + char *failover_name = NULL, *failover_uuid = NULL; + xmlNodePtr cur = root->xmlChildrenNode; + int server_num, failover_num, rc; + + printf("--- Setting up OST ---\n"); + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "server_id")) { + server_num = atoi(xmlGetProp(cur, "num")); + server_name = xmlGetProp(cur, "name"); + server_uuid = xmlGetProp(cur, "uuid"); + } + + /* FIXME: Properly handle multiple failover servers */ + if (!xmlStrcmp(cur->name, "failover_id")) { + failover_num = atoi(xmlGetProp(cur, "num")); + failover_name = xmlGetProp(cur, "name"); + failover_uuid = xmlGetProp(cur, "uuid"); + } + + cur = cur->next; + } + + if ((server_name == NULL) || (server_uuid == NULL)) { + printf("error: atleast the tag is required\n"); + return -1; + } + + if ((rc = xml_command("newdev", NULL)) != 0) + return rc; + + if ((rc = xml_command("attach","ost",serv_name,serv_uuid,NULL)) != 0) + return rc; + + if ((rc = xml_command("setup", server_name, NULL)) != 0) + return rc; + + return 0; +} + +static int xml_osc(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + char *ost_name = NULL, *ost_uuid = NULL; + xmlNodePtr cur = root->xmlChildrenNode; + int ost_num, rc = 0; + + printf("--- Setting up OSC ---\n"); + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "service_id")) { + ost_num = atoi(xmlGetProp(cur, "num")); + ost_name = xmlGetProp(cur, "name"); + ost_uuid = xmlGetProp(cur, "uuid"); + } + + cur = cur->next; + } + + if ((ost_name == NULL) || (ost_uuid == NULL)) { + printf("error: atleast the tag is required\n"); + return -1; + } + + if ((rc = xml_command("newdev", NULL)) != 0) + return rc; + + if ((rc = xml_command("attach","osc",serv_name,serv_uuid,NULL)) != 0) + return rc; + + if ((rc = xml_command("setup", ost_uuid, "localhost", NULL)) != 0) + return rc; + + return 0; +} + +static int xml_mdc(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + char *mds_name = NULL, *mds_uuid = NULL; + xmlNodePtr cur = root->xmlChildrenNode; + int mds_num, rc = 0; + + printf("--- Setting up MDC ---\n"); + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "service_id")) { + mds_num = atoi(xmlGetProp(cur, "num")); + mds_name = xmlGetProp(cur, "name"); + mds_uuid = xmlGetProp(cur, "uuid"); + } + + cur = cur->next; + } + + if ((mds_name == NULL) || (mds_uuid == NULL)) { + printf("error: atleast the tag is required\n"); + return -1; + } + + if ((rc = xml_command("newdev", NULL)) != 0) + return rc; + + if ((rc = xml_command("attach","mdc",serv_name,serv_uuid,NULL)) != 0) + return rc; + + if ((rc = xml_command("setup", mds_uuid, "localhost", NULL)) != 0) + return rc; + + return 0; +} + +static int xml_lov(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + printf("--- Setting up LOV ---\n"); + return 0; +} + +static int xml_router(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + printf("--- Setting up ROUTER ---\n"); + return 0; +} + +static int xml_ldlm(xmlDocPtr doc, xmlNodePtr root, + char *serv_name, char *serv_uuid) { + int rc; + + printf("--- Setting up LDLM ---\n"); + if ((rc = xml_command("newdev", NULL)) != 0) + return rc; + + if ((rc = xml_command("attach","ldlm",serv_name,serv_uuid,NULL)) != 0) + return rc; + + if ((rc = xml_command("setup", NULL)) != 0) + return rc; + + return 0; +} + +static int xml_service(xmlDocPtr doc, xmlNodePtr root, + int serv_num, char *serv_name, char *serv_uuid) { + xmlNodePtr cur = root; + char *name, *uuid; + + while (cur != NULL) { + name = xmlGetProp(cur, "name"); + uuid = xmlGetProp(cur, "uuid"); + + if (xmlStrcmp(name, serv_name) || + xmlStrcmp(uuid, serv_uuid)) { + cur = cur->next; + continue; + } + + if (!xmlStrcmp(cur->name, "mds")) + return xml_mds(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "obd")) + return xml_obd(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "ost")) + return xml_ost(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "osc")) + return xml_osc(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "mdc")) + return xml_mdc(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "lov")) + return xml_lov(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "router")) + return xml_router(doc, cur, name, uuid); + else if (!xmlStrcmp(cur->name, "ldlm")) + return xml_ldlm(doc, cur, name, uuid); + else + return -1; + + cur = cur->next; + } + + printf("error: No XML config branch for name=%s uuid=%s\n", + serv_name, serv_uuid); + return -1; +} + +static int xml_profile(xmlDocPtr doc, xmlNodePtr root, + int prof_num, char *prof_name, char *prof_uuid) { + xmlNodePtr parent, cur = root; + char *name, *uuid, *srv_name, *srv_uuid; + int rc = 0, num; + + while (cur != NULL) { + name = xmlGetProp(cur, "name"); + uuid = xmlGetProp(cur, "uuid"); + + if (xmlStrcmp(cur->name, "profile") || + xmlStrcmp(name, prof_name) || + xmlStrcmp(uuid, prof_uuid)) { + cur = cur->next; + continue; + } + + /* FIXME: Doesn't understand mountpoints yet + * xml_mountpoint(doc, root, ...); + */ + + /* Setup each service in turn + * FIXME: Should be sorted by "num" attr, we shouldn't + * assume they're in order in the XML document. + */ + parent = cur; + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "service_id")) { + num = atoi(xmlGetProp(cur, "num")); + rc = xml_service(doc, root, num, + srv_name = xmlGetProp(cur, "name"), + srv_uuid = xmlGetProp(cur, "uuid")); + if (rc != 0) { + printf("error: service config\n"); + return rc; + } + } + + cur = cur->next; + } + + cur = parent->next; + } + + return rc; +} + +static int xml_node(xmlDocPtr doc, xmlNodePtr root) { + xmlNodePtr parent, cur = root; + char *name, *uuid; + int rc = 0, num; + + /* Walk the node tags looking for ours */ + while (cur != NULL) { + if (xmlStrcmp(cur->name, "node")) { + cur = cur->next; + continue; + } + + name = xmlGetProp(cur, "name"); + if (name == NULL) + return -1; + + uuid = xmlGetProp(cur, "uuid"); + if (uuid == NULL) + return -1; + + /* FIXME: Verify our NAME and UUID against /etc/lustre/id + * so we're sure we are who we think we are. + */ + + /* Setup each profile in turn + * FIXME: Should be sorted by "num" attr, we shouldn't + * assume they're in order in the XML document. + */ + parent = cur; + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, "profile_id")) { + num = atoi(xmlGetProp(cur, "num")); + rc = xml_profile(doc, root, num, + xmlGetProp(cur, "name"), + xmlGetProp(cur, "uuid")); + if (rc != 0) + return rc; + } + + cur = cur->next; + } + + cur = parent->next; + } + + return rc; +} + +static int do_xml(char *func, char *file) { - struct obd_ioctl_data data; + xmlDocPtr doc; + xmlNodePtr cur; int rc; - do_disconnect(argv[0], 1); + doc = xmlParseFile(file); + if (doc == NULL) { + fprintf(stderr, "error: Unable to parse XML\n"); + return -1; + } - memset(&data, 0, sizeof(data)); - if ( argc != 2 ) { - fprintf(stderr, "usage: %s devno\n", cmdname(argv[0])); + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + fprintf(stderr, "error: Empty XML\n"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)"lustre")) { + fprintf(stderr, "error: Root node != \n"); + xmlFreeDoc(doc); return -1; } - data.ioc_dev = strtoul(argv[1], NULL, 0); + /* FIXME: Validate the XML against the DTD here */ + + /* FIXME: Merge all the text nodes under each branch and + * prune empty nodes. Just to make the parsing more + * tolerant, the exact location of nested tags isn't + * critical for this. + */ + + rc = xml_node(doc, cur->xmlChildrenNode); + xmlFreeDoc(doc); + + return rc; +} + +static int do_device(char *func, int dev) +{ + struct obd_ioctl_data data; + + memset(&data, 0, sizeof(data)); + + data.ioc_dev = dev; + + if (getfd(func)) + return -1; if (obd_ioctl_pack(&data, &buf, max)) { - fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0])); + fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func)); return -2; } - if (fd == -1) - fd = open("/dev/obd", O_RDWR); - if (fd == -1) { - fprintf(stderr, "error: %s: opening /dev/obd: %s\n", - cmdname(argv[0]), strerror(errno)); - return errno; + return ioctl(fd, OBD_IOC_DEVICE , buf); +} + +static int jt_device(int argc, char **argv) +{ + do_disconnect(argv[0], 1); + + if (argc != 2) { + fprintf(stderr, "usage: %s devno\n", cmdname(argv[0])); + return -1; } - rc = ioctl(fd, OBD_IOC_DEVICE , buf); + rc = do_device(argv[0], strtoul(argv[1], NULL, 0)); + if (rc < 0) - fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]), - OBD_IOC_DEVICE, strerror(rc = errno)); + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc = errno)); return rc; } @@ -231,7 +747,6 @@ static int jt_device(int argc, char **argv) static int jt_connect(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); @@ -247,8 +762,8 @@ static int jt_connect(int argc, char **argv) fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]), OBD_IOC_CONNECT, strerror(rc = errno)); else - connid = data.ioc_conn1; - + conn_addr = data.ioc_addr; + conn_cookie = data.ioc_cookie; return rc; } @@ -259,13 +774,27 @@ static int jt_disconnect(int argc, char **argv) return -1; } + if (conn_addr == -1) + return 0; + return do_disconnect(argv[0], 0); } +static int jt__xml(int argc, char **argv) +{ + if (argc < 2) { + fprintf(stderr, "usage: %s \n", + cmdname(argv[0])); + return -1; + } + + return do_xml("xml", argv[1]); +} + static int jt__device(int argc, char **argv) { char *arg2[3]; - int rc, ret; + int ret; if (argc < 3) { fprintf(stderr, "usage: %s devno \n", @@ -273,10 +802,7 @@ static int jt__device(int argc, char **argv) return -1; } - arg2[0] = "device"; - arg2[1] = argv[1]; - arg2[2] = NULL; - rc = jt_device(2, arg2); + rc = do_device("device", strtoul(argv[1], NULL, 0)); if (!rc) { arg2[0] = "connect"; @@ -297,9 +823,8 @@ static int jt__device(int argc, char **argv) static int jt__threads(int argc, char **argv) { int threads, next_thread; - int verbose = 1; + int verbose; int i, j; - int rc; if (argc < 5) { fprintf(stderr, @@ -310,12 +835,7 @@ static int jt__threads(int argc, char **argv) threads = strtoul(argv[1], NULL, 0); - if (argv[2][0] == 's' || argv[2][0] == 'q') - verbose = 0; - else if (argv[2][0] == 'v') - verbose = 1; - else - verbose = strtoul(argv[2], NULL, 0); + verbose = get_verbose(argv[2]); printf("%s: starting %d threads on device %s running %s\n", argv[0], threads, argv[3], argv[4]); @@ -349,13 +869,22 @@ static int jt__threads(int argc, char **argv) if (ret < 0) { fprintf(stderr, "error: %s: wait - %s\n", argv[0], strerror(errno)); - if (rc == 0) + if (!rc) rc = errno; - } else if (WIFEXITED(status) == 0) { - fprintf(stderr, "%s: PID %d had rc=%d\n", - argv[0], ret, WEXITSTATUS(status)); - if (rc == 0) - rc = WEXITSTATUS(status); + } else { + /* + * This is a hack. We _should_ be able to use + * WIFEXITED(status) to see if there was an + * error, but it appears to be broken and it + * always returns 1 (OK). See wait(2). + */ + int err = WEXITSTATUS(status); + if (err) + fprintf(stderr, + "%s: PID %d had rc=%d\n", + argv[0], ret, err); + if (!rc) + rc = err; } } } @@ -366,7 +895,6 @@ static int jt__threads(int argc, char **argv) static int jt_detach(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); @@ -391,7 +919,6 @@ static int jt_detach(int argc, char **argv) static int jt_cleanup(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); @@ -408,49 +935,161 @@ static int jt_cleanup(int argc, char **argv) return rc; } +static int jt_newdev(int argc, char **argv) +{ + struct obd_ioctl_data data; + + if (getfd(argv[0])) + return -1; + + IOCINIT(data); + + if (argc != 1) { + fprintf(stderr, "usage: %s\n", cmdname(argv[0])); + return -1; + } + + rc = ioctl(fd, OBD_IOC_NEWDEV , &data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc=errno)); + else { + printf("Current device set to %d\n", data.ioc_dev); + } + + return rc; +} + +static int jt_list(int argc, char **argv) +{ + char buf[1024]; + struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf; + + if (getfd(argv[0])) + return -1; + + memset(buf, 0, sizeof(buf)); + data->ioc_version = OBD_IOCTL_VERSION; + data->ioc_addr = conn_addr; + data->ioc_cookie = conn_addr; + data->ioc_len = sizeof(buf); + data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data)); + + if (argc != 1) { + fprintf(stderr, "usage: %s\n", cmdname(argv[0])); + return -1; + } + + rc = ioctl(fd, OBD_IOC_LIST , data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc=errno)); + else { + printf("%s", data->ioc_bulk); + } + + return rc; +} + static int jt_attach(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); - if (argc != 2 && argc != 3) { - fprintf(stderr, "usage: %s type [data]\n", cmdname(argv[0])); + if (argc != 2 && argc != 3 && argc != 4) { + fprintf(stderr, "usage: %s type [name [uuid]]\n", + cmdname(argv[0])); return -1; } data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; - if (argc == 3) { + if (argc >= 3) { data.ioc_inllen2 = strlen(argv[2]) + 1; data.ioc_inlbuf2 = argv[2]; } - printf("%s: len %d addr %p type %s data %s\n", - cmdname(argv[0]), data.ioc_len, buf, - MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2)); + if (argc == 4) { + data.ioc_inllen3 = strlen(argv[3]) + 1; + data.ioc_inlbuf3 = argv[3]; + } if (obd_ioctl_pack(&data, &buf, max)) { fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0])); return -2; } - printf("%s: len %d addr %p raw %p type %s data %s and %s\n", - cmdname(argv[0]), data.ioc_len, buf, rawbuf, - MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2), &buf[516]); rc = ioctl(fd, OBD_IOC_ATTACH , buf); if (rc < 0) fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]), OBD_IOC_ATTACH, strerror(rc = errno)); + else if (argc == 3) { + char name[1024]; + if (strlen(argv[2]) > 128) { + printf("Name too long to set environment\n"); + return -EINVAL; + } + snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]); + rc = setenv(name, argv[1], 1); + if (rc) { + printf("error setting env variable %s\n", name); + } + } + + return rc; +} + +#define N2D_OFF 0x100 /* So we can tell between error codes and devices */ + +static int do_name2dev(char *func, char *name) +{ + struct obd_ioctl_data data; + + if (getfd(func)) + return -1; + + IOCINIT(data); + + data.ioc_inllen1 = strlen(name) + 1; + data.ioc_inlbuf1 = name; + + if (obd_ioctl_pack(&data, &buf, max)) { + fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func)); + return -2; + } + rc = ioctl(fd, OBD_IOC_NAME2DEV , buf); + if (rc < 0) { + fprintf(stderr, "error: %s: %s - %s\n", cmdname(func), + name, strerror(rc = errno)); + return rc; + } + + memcpy((char *)(&data), buf, sizeof(data)); + return data.ioc_dev + N2D_OFF; +} + +static int jt_name2dev(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "usage: %s name\n", cmdname(argv[0])); + return -1; + } + + rc = do_name2dev(argv[0], argv[1]); + if (rc >= N2D_OFF) { + int dev = rc - N2D_OFF; + rc = do_device(argv[0], dev); + if (rc == 0) + printf("%d\n", dev); + } return rc; } static int jt_setup(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); @@ -460,30 +1099,29 @@ static int jt_setup(int argc, char **argv) return -1; } + data.ioc_dev = -1; if (argc > 1) { - data.ioc_inllen1 = strlen(argv[1]) + 1; + if (argv[1][0] == '$') { + rc = do_name2dev(argv[0], argv[1] + 1); + if (rc >= N2D_OFF) { + printf("%s is device %d\n", argv[1], + rc - N2D_OFF); + data.ioc_dev = rc - N2D_OFF; + } + } else + data.ioc_dev = strtoul(argv[1], NULL, 0); + data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; - data.ioc_dev = strtoul(argv[1], NULL, 0); - } else { - data.ioc_dev = -1; } if ( argc == 3 ) { data.ioc_inllen2 = strlen(argv[2]) + 1; data.ioc_inlbuf2 = argv[2]; } - printf("%s: len %d addr %p device %s type %s\n", - cmdname(argv[0]), data.ioc_len, buf, - MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2)); - if (obd_ioctl_pack(&data, &buf, max)) { fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0])); return -2; } - printf("%s: len %d addr %p raw %p device %s type %s\n", - cmdname(argv[0]), data.ioc_len, buf, rawbuf, - MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2)); - rc = ioctl(fd, OBD_IOC_SETUP , buf); if (rc < 0) fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), @@ -498,9 +1136,8 @@ static int jt_create(int argc, char **argv) struct obd_ioctl_data data; struct timeval next_time; int count = 1, next_count; - int verbose = 1; + int verbose; int i; - int rc; IOCINIT(data); if (argc < 2 || argc > 4) { @@ -516,14 +1153,7 @@ static int jt_create(int argc, char **argv) data.ioc_obdo1.o_mode = 0100644; data.ioc_obdo1.o_valid = OBD_MD_FLMODE; - if (argc > 3) { - if (argv[3][0] == 's' || argv[3][0] == 'q') - verbose = 0; - else if (argv[3][0] == 'v') - verbose = 1; - else - verbose = strtoul(argv[3], NULL, 0); - } + verbose = get_verbose(argv[3]); printf("%s: %d obdos\n", cmdname(argv[0]), count); gettimeofday(&next_time, NULL); @@ -546,7 +1176,6 @@ static int jt_create(int argc, char **argv) static int jt_setattr(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); if (argc != 2) { @@ -556,7 +1185,7 @@ static int jt_setattr(int argc, char **argv) data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0); data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], NULL, 0); - data.ioc_obdo1.o_valid = OBD_MD_FLMODE; + data.ioc_obdo1.o_valid = OBD_MD_FLMODE; rc = ioctl(fd, OBD_IOC_SETATTR , &data); if (rc < 0) @@ -569,7 +1198,6 @@ static int jt_setattr(int argc, char **argv) static int jt_destroy(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); if (argc != 2) { @@ -591,7 +1219,6 @@ static int jt_destroy(int argc, char **argv) static int jt_getattr(int argc, char **argv) { struct obd_ioctl_data data; - int rc; if (argc != 2) { fprintf(stderr, "usage: %s id\n", cmdname(argv[0])); @@ -600,7 +1227,7 @@ static int jt_getattr(int argc, char **argv) IOCINIT(data); data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0); - /* to help obd filter */ + /* to help obd filter */ data.ioc_obdo1.o_mode = 0100644; data.ioc_obdo1.o_valid = 0xffffffff; printf("%s: object id %Ld\n", cmdname(argv[0]), data.ioc_obdo1.o_id); @@ -621,8 +1248,7 @@ static int jt_test_getattr(int argc, char **argv) struct obd_ioctl_data data; struct timeval start, next_time; int i, count, next_count; - int verbose = 1; - int rc; + int verbose; if (argc != 2 && argc != 3) { fprintf(stderr, "usage: %s count [verbose]\n",cmdname(argv[0])); @@ -632,14 +1258,11 @@ static int jt_test_getattr(int argc, char **argv) IOCINIT(data); count = strtoul(argv[1], NULL, 0); - if (argc == 3) { - if (argv[2][0] == 's' || argv[2][0] == 'q') - verbose = 0; - else if (argv[2][0] == 'v') - verbose = 1; - else - verbose = strtoul(argv[2], NULL, 0); - } + if (argc == 3) + verbose = get_verbose(argv[2]); + else + verbose = 1; + data.ioc_obdo1.o_valid = 0xffffffff; data.ioc_obdo1.o_id = 2; gettimeofday(&start, NULL); @@ -650,13 +1273,15 @@ static int jt_test_getattr(int argc, char **argv) for (i = 1, next_count = verbose; i <= count; i++) { rc = ioctl(fd, OBD_IOC_GETATTR , &data); - if (rc) { + if (rc < 0) { fprintf(stderr, "error: %s: #%d - %s\n", cmdname(argv[0]), i, strerror(rc = errno)); break; - } else if (be_verbose(verbose, &next_time, i,&next_count,count)) + } else { + if (be_verbose(verbose, &next_time, i,&next_count,count)) printf("%s: got attr #%d\n", cmdname(argv[0]), i); - } + } + } if (!rc) { struct timeval end; @@ -683,7 +1308,6 @@ static int jt_test_brw(int argc, char **argv) int verbose = 1, write = 0, rw; int i, o, p; int len; - int rc; if (argc < 2 || argc > 6) { fprintf(stderr, @@ -699,15 +1323,10 @@ static int jt_test_brw(int argc, char **argv) write = 1; else if (argv[2][0] == 'r' || argv[2][0] == '0') write = 0; + + verbose = get_verbose(argv[3]); } - if (argc >= 4) { - if (argv[3][0] == 's' || argv[3][0] == 'q') - verbose = 0; - else if (argv[3][0] == 'v') - verbose = 1; - else - verbose = strtoul(argv[3], NULL, 0); - } + if (argc >= 5) pages = strtoul(argv[4], NULL, 0); if (argc >= 6) @@ -728,14 +1347,13 @@ static int jt_test_brw(int argc, char **argv) return -2; } IOCINIT(data); - data.ioc_conn2 = connid; data.ioc_obdo1.o_id = 2; data.ioc_count = len; data.ioc_offset = 0; data.ioc_plen1 = len; data.ioc_pbuf1 = bulk; if (obdos > 1) { - data.ioc_obdo2.o_id = 2; + data.ioc_obdo2.o_id = 3; data.ioc_plen2 = len; data.ioc_pbuf2 = bulk + len; } @@ -752,6 +1370,10 @@ static int jt_test_brw(int argc, char **argv) * We will put in the start time (and loop count inside the loop) * at the beginning of each page so that we will be able to validate * (at some later time) whether the data actually made it or not. + * + * XXX we do not currently use any of this memory in OBD_IOC_BRW_* + * just to avoid the overhead of the copy_{to,from}_user. It + * can be fixed if we ever need to send real data around. */ for (o = 0, b = bulk; o < obdos; o++) for (p = 0; p < pages; p++, b += PAGE_SIZE) @@ -799,7 +1421,6 @@ static int jt_test_brw(int argc, char **argv) static int jt_test_ldlm(int argc, char **argv) { struct obd_ioctl_data data; - int rc; IOCINIT(data); if (argc != 1) { @@ -814,14 +1435,43 @@ static int jt_test_ldlm(int argc, char **argv) return rc; } +static int jt_newconn(int argc, char **argv) +{ + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 1) { + fprintf(stderr, "usage: %s\n", cmdname(argv[0])); + return -1; + } + + rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN , &data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} + +static int jt_quit(int argc, char **argv) +{ + Parser_quit(argc, argv); + + return rc; +} + command_t cmdlist[] = { /* Metacommands */ + {"--xml", jt__xml, 0, "--xml "}, {"--device", jt__device, 0, "--device "}, {"--threads", jt__threads, 0, "--threads "}, /* Device configuration commands */ - {"device", jt_device, 0, "set current device (args device no)"}, + {"list", jt_list, 0, "list the devices (no args)"}, + {"newdev", jt_newdev, 0, "set device to a new unused obd (no args)"}, + {"device", jt_device, 0, "set current device (args device_no name)"}, + {"name2dev", jt_name2dev, 0, "set device by name (args name)"}, {"attach", jt_attach, 0, "name the type of device (args: type data"}, {"setup", jt_setup, 0, "setup device (args: [data]"}, {"detach", jt_detach, 0, "detach the current device (arg: )"}, @@ -837,21 +1487,22 @@ command_t cmdlist[] = { {"destroy", jt_destroy, 0, "destroy "}, {"getattr", jt_getattr, 0, "getattr "}, {"setattr", jt_setattr, 0, "setattr "}, + {"newconn", jt_newconn, 0, "newconn [newuuid]"}, {"test_getattr", jt_test_getattr, 0, "test_getattr [verbose]"}, {"test_brw", jt_test_brw, 0, "test_brw [write [verbose]]"}, {"test_ldlm", jt_test_ldlm, 0, "test lock manager (no args)"}, /* User interface commands */ {"help", Parser_help, 0, "help"}, - {"exit", Parser_quit, 0, "quit"}, - {"quit", Parser_quit, 0, "quit"}, + {"exit", jt_quit, 0, "quit"}, + {"quit", jt_quit, 0, "quit"}, { 0, 0, 0, NULL } }; static void signal_server(int sig) { - if (sig == SIGINT) { + if (sig == SIGINT) { do_disconnect("sigint", 1); exit(1); } else { @@ -862,7 +1513,6 @@ static void signal_server(int sig) int main(int argc, char **argv) { struct sigaction sigact; - int rc = 0; sigact.sa_handler = signal_server; sigfillset(&sigact.sa_mask); @@ -874,7 +1524,7 @@ int main(int argc, char **argv) rc = Parser_execarg(argc - 1, argv + 1, cmdlist); } else { Parser_init("obdctl > ", cmdlist); - Parser_commands(); + rc = Parser_commands(); } do_disconnect(argv[0], 1);