-#include <stdio.h>
-
-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;
-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_addr = conn_addr; \
- data.ioc_cookie = conn_cookie; \
- data.ioc_len = sizeof(data); \
- if (fd < 0) { \
- fprintf(stderr, "No device open, use device\n"); \
- return 1; \
- } \
-} while (0)
-
-/*
- pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L",
- $obdo->{id}, 0,
- $obdo->{gr}, 0,
- $obdo->{atime}, 0,
- $obdo->{mtime}, 0 ,
- $obdo->{ctime}, 0,
- $obdo->{size}, 0,
- $obdo->{blocks}, 0,
- $obdo->{blksize},
- $obdo->{mode},
- $obdo->{uid},
- $obdo->{gid},
- $obdo->{flags},
- $obdo->{obdflags},
- $obdo->{nlink},
- $obdo->{generation},
- $obdo->{valid},
- $obdo->{inline},
- $obdo->{obdmd},
- 0, 0, # struct list_head
- 0; # struct obd_ops
-}
-
-*/
-
-char * obdo_print(struct obdo *obd)
-{
- char buf[1024];
-
- sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\n"
- "size: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\n"
- "gid: %d\nflags: %x\nobdflags: %x\nnlink: %d,\nvalid %x\n",
- obd->o_id,
- obd->o_gr,
- obd->o_atime,
- obd->o_mtime,
- obd->o_ctime,
- obd->o_size,
- obd->o_blocks,
- obd->o_blksize,
- obd->o_mode,
- obd->o_uid,
- obd->o_gid,
- obd->o_flags,
- obd->o_obdflags,
- obd->o_nlink,
- obd->o_valid);
- return strdup(buf);
-}
-
-static char *cmdname(char *func)
-{
- static char buf[512];
-
- if (thread) {
- sprintf(buf, "%s-%d", func, thread);
- return buf;
- }
-
- return func;
-}
-
-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))
-
-static int be_verbose(int verbose, struct timeval *next_time,
- int num, int *next_num, int num_total)
-{
- struct timeval now;
-
- 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;
- if (next_time) {
- next_time->tv_sec = now.tv_sec - verbose;
- next_time->tv_usec = now.tv_usec;
- }
- 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;
-
- if (conn_addr == -1)
- return 0;
-
- IOCINIT(data);
-
- rc = ioctl(fd, OBD_IOC_DISCONNECT , &data);
- if (rc < 0) {
- fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
- OBD_IOC_DISCONNECT, strerror(errno));
- } else {
- if (verbose)
- printf("%s: disconnected conn %Lx\n", cmdname(func),
- conn_addr);
- conn_addr = -1;
- }
-
- return rc;
-}
-
-extern command_t cmdlist[];
-
-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: <server> 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: <fstype> and <device> 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 <fstype> "
- "and <device> 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 <server_id> 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 <service_id> 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 <service_id> 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)
-{
- xmlDocPtr doc;
- xmlNodePtr cur;
- int rc;
-
- doc = xmlParseFile(file);
- if (doc == NULL) {
- fprintf(stderr, "error: Unable to parse XML\n");
- return -1;
- }
-
- 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 != <lustre>\n");
- xmlFreeDoc(doc);
- return -1;
- }
-
- /* 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(func));
- return -2;
- }
-
- 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 = do_device(argv[0], strtoul(argv[1], NULL, 0));
-
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-static int jt_connect(int argc, char **argv)
-{
- struct obd_ioctl_data data;
-
- IOCINIT(data);
-
- do_disconnect(argv[0], 1);
-
- if (argc != 1) {
- fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
- return -1;
- }
-
- rc = ioctl(fd, OBD_IOC_CONNECT , &data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
- OBD_IOC_CONNECT, strerror(rc = errno));
- else
- conn_addr = data.ioc_addr;
- conn_cookie = data.ioc_cookie;
- return rc;
-}
-
-static int jt_disconnect(int argc, char **argv)
-{
- if (argc != 1) {
- fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
- 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 <xml file> <command [args ...]>\n",
- cmdname(argv[0]));
- return -1;
- }
-
- return do_xml("xml", argv[1]);
-}
-
-static int jt__device(int argc, char **argv)
-{
- char *arg2[3];
- int ret;
-
- if (argc < 3) {
- fprintf(stderr, "usage: %s devno <command [args ...]>\n",
- cmdname(argv[0]));
- return -1;
- }
-
- rc = do_device("device", strtoul(argv[1], NULL, 0));
-
- if (!rc) {
- arg2[0] = "connect";
- arg2[1] = NULL;
- rc = jt_connect(1, arg2);
- }