From: behlendo Date: Thu, 4 Jul 2002 00:12:30 +0000 (+0000) Subject: - Added lctl.c which is basically ptlctl/obdctl/debugctl all X-Git-Tag: v1_7_100~5377 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=67d9629b694bdac2e62c67cf97de3671926cb9ba - Added lctl.c which is basically ptlctl/obdctl/debugctl all frankensteined together. It should be possible to configure all of portals/lustre through it. - network.c contains the portals bits device.c contains the device bits debug.c contains the debug bits - Some functionality has been consolidated when it was redundant, there's still more of that to do! - The thread handling that was in obdctl is broken for a little bit. - All the original *ctl tools are uneffected. - Several commands have been slightly renamed do to name collisions, for instance the obdctl list command is now device_list, so as not to conflict with debug_list or route_list. It'll be pretty obvious. --- diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index b62d520..a70fa9e 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -1,12 +1,13 @@ DEFS:= -EXTRA_DIST = parser.h +EXTRA_DIST = parser.h lctl.h CFLAGS:=-g -I. -I/usr/include/libxml2 -I/usr/include/glib-1.2 -I$(PORTALS)/include \ -I/usr/lib/glib/include -I$(srcdir)/../include -Wall KFLAGS:= CPPFLAGS := LDADD := -lreadline -lncurses -lxml2 # -lefence -bin_PROGRAMS = obdctl +bin_PROGRAMS = obdctl lctl obdctl_SOURCES = parser.c obdctl.c +lctl_SOURCES = parser.c network.c device.c debug.c lctl.c include $(top_srcdir)/Rules diff --git a/lustre/utils/debug.c b/lustre/utils/debug.c new file mode 100644 index 0000000..45c9583 --- /dev/null +++ b/lustre/utils/debug.c @@ -0,0 +1,433 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001, 2002 Cluster File Systems, Inc. + * + * This file is part of Portals, http://www.sf.net/projects/lustre/ + * + * Portals is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Portals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Portals; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Some day I'll split all of this functionality into a cfs_debug module + * of its own. That day is not today. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lctl.h" + +static char rawbuf[8192]; +static char *buf = rawbuf; +static int max = 8192; +static int g_pfd = -1; +static int subsystem_array[1 << 8]; +static int debug_mask = ~0; + +static const char *portal_debug_subsystems[] = + {"undefined", "mdc", "mds", "osc", "ost", "class", "obdfs", "llite", + "rpc", "ext2obd", "portals", "socknal", "qswnal", "pinger", "filter", + "obdtrace", "echo", "ldlm", "lov", "gmnal", "router", NULL}; +static const char *portal_debug_masks[] = + {"trace", "inode", "super", "ext2", "malloc", "cache", "info", "ioctl", + "blocks", "net", "warning", "buffs", "other", "dentry", "portals", + "page", "dlmtrace", NULL}; + +int debug_setup(int argc, char **argv) { + memset(subsystem_array, 1, sizeof(subsystem_array)); + return 0; +} + +static int do_debug_mask(char *name, int enable) { + int found = 0, i; + + for (i = 0; portal_debug_subsystems[i] != NULL; i++) { + if (strcasecmp(name, portal_debug_subsystems[i]) == 0 || + strcasecmp(name, "all_subs") == 0) { + fprintf(stderr, "%s output from subsystem \"%s\"\n", + enable ? "Enabling" : "Disabling", + portal_debug_subsystems[i]); + subsystem_array[i] = enable; + found = 1; + } + } + for (i = 0; portal_debug_masks[i] != NULL; i++) { + if (strcasecmp(name, portal_debug_masks[i]) == 0 || + strcasecmp(name, "all_types") == 0) { + fprintf(stderr, "%s output of type \"%s\"\n", + enable ? "Enabling" : "Disabling", + portal_debug_masks[i]); + if (enable) + debug_mask |= (1 << i); + else + debug_mask &= ~(1 << i); + found = 1; + } + } + + return found; +} + +/* if 'raw' is true, don't strip the debug information from the + * front of the lines */ +static void dump_buffer(FILE *fd, char *buf, int size, int raw) { + char *p, *z; + unsigned long subsystem, debug, dropped = 0, kept = 0; + int max_sub, max_type; + + for (max_sub = 0; portal_debug_subsystems[max_sub] != NULL; max_sub++) + ; + for (max_type = 0; portal_debug_masks[max_type] != NULL; max_type++) + ; + + while (size) { + p = memchr(buf, '\n', size); + if (!p) + break; + subsystem = strtoul(buf, &z, 16); + debug = strtoul(z + 1, &z, 16); + + z++; + /* for some reason %*s isn't working. */ + *p = '\0'; + if (subsystem < max_sub && + subsystem_array[subsystem] && + (!debug || (debug_mask & debug))) { + if (raw) + fprintf(fd, "%s\n", buf); + else + fprintf(fd, "%s\n", z); + //printf("%s\n", buf); + kept++; + } else { + //fprintf(stderr, "dropping line (%lx:%lx): %s\n", subsystem, debug, buf); + dropped++; + } + *p = '\n'; + p++; + size -= (p - buf); + buf = p; + } + + fprintf(stderr, "Debug log: %lu lines, %lu kept, %lu dropped.\n", + dropped + kept, kept, dropped); +} + +int jt_debug_kernel(int argc, char **argv) { + int rc, raw = 0; + FILE *fd = stdout; + const int databuf_size = (6 << 20); + struct portal_ioctl_data data, *newdata; + char *databuf = NULL; + + PORTALS_CONNECT; + + if (argc > 3) + return CMD_HELP; + + if (argc > 1) { + fd = fopen(argv[1], "w"); + if (fd == NULL) { + fprintf(stderr, "fopen(%s) failed: %s\n", argv[1], + strerror(errno)); + return -1; + } + } + if (argc > 2) + raw = atoi(argv[2]); + + databuf = malloc(databuf_size); + if (!databuf) { + fprintf(stderr, "No memory for buffer.\n"); + goto out; + } + + memset(&data, 0, sizeof(data)); + data.ioc_plen1 = databuf_size; + data.ioc_pbuf1 = databuf; + + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + goto out; + } + + rc = ioctl(g_pfd, IOC_PORTAL_GET_DEBUG, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_GET_DEBUG failed: %s\n", + strerror(errno)); + goto out; + } + + newdata = (struct portal_ioctl_data *)buf; + if (newdata->ioc_size > 0) + dump_buffer(fd, databuf, newdata->ioc_size, raw); + else + fprintf(stderr, "No data in the debug buffer.\n"); + +out: + if (databuf) + free(databuf); + if (fd != stdout) + fclose(fd); + return 0; +} + +int jt_debug_file(int argc, char **argv) { + int rc, fd = -1, raw = 0; + FILE *output = stdout; + char *databuf = NULL; + struct stat statbuf; + + if (argc > 4 || argc < 2) + return CMD_HELP; + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fopen(%s) failed: %s\n", argv[1], + strerror(errno)); + return -1; + } + rc = fstat(fd, &statbuf); + if (rc < 0) { + fprintf(stderr, "fstat failed: %s\n", strerror(errno)); + goto out; + } + + if (argc == 3) { + output = fopen(argv[2], "w"); + if (output == NULL) { + fprintf(stderr, "fopen(%s) failed: %s\n", argv[2], + strerror(errno)); + goto out; + } + } + + if (argc == 4) + raw = atoi(argv[3]); + + databuf = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0); + if (databuf == NULL) { + fprintf(stderr, "mmap failed: %s\n", strerror(errno)); + goto out; + } + + dump_buffer(output, databuf, statbuf.st_size, raw); + +out: + if (databuf) + munmap(databuf, statbuf.st_size); + if (output != stdout) + fclose(output); + if (fd > 0) + close(fd); + return 0; +} + +int jt_debug_clear(int argc, char **argv) { + int rc; + struct portal_ioctl_data data; + + PORTALS_CONNECT; + if (argc != 1) + return CMD_HELP; + + memset(&data, 0, sizeof(data)); + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + return -1; + } + + rc = ioctl(g_pfd, IOC_PORTAL_CLEAR_DEBUG, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_CLEAR_DEBUG failed: %s\n", + strerror(errno)); + return -1; + } + return 0; +} + +int jt_debug_mark(int argc, char **argv) { + int rc; + struct portal_ioctl_data data; + char *text; + time_t now = time(NULL); + + PORTALS_CONNECT; + if (argc > 2) + return CMD_HELP; + + if (argc == 2) { + text = argv[1]; + } else { + text = ctime(&now); + text[strlen(text) - 1] = '\0'; /* stupid \n */ + } + + memset(&data, 0, sizeof(data)); + data.ioc_inllen1 = strlen(text) + 1; + data.ioc_inlbuf1 = text; + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + return -1; + } + + rc = ioctl(g_pfd, IOC_PORTAL_MARK_DEBUG, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_MARK_DEBUG failed: %s\n", + strerror(errno)); + return -1; + } + return 0; +} + +int jt_debug_filter(int argc, char **argv) { + int i; + + if (argc < 2) + return CMD_HELP; + + for (i = 1; i < argc; i++) + if (!do_debug_mask(argv[i], 0)) + fprintf(stderr, "Unknown subsystem or " + "debug type: %s\n", argv[i]); + return 0; +} + +int jt_debug_show(int argc, char **argv) { + int i; + + if (argc < 2) + return CMD_HELP; + + for (i = 1; i < argc; i++) + if (!do_debug_mask(argv[i], 1)) + fprintf(stderr, "Unknown subsystem or " + "debug type: %s\n", argv[i]); + + return 0; +} + +int jt_debug_list(int argc, char **argv) { + int i; + + if (argc != 2) + return CMD_HELP; + + if (strcasecmp(argv[1], "subs") == 0) { + printf("Subsystems: all_subs"); + for (i = 0; portal_debug_subsystems[i] != NULL; i++) + printf(", %s", portal_debug_subsystems[i]); + printf("\n"); + } else if (strcasecmp(argv[1], "types") == 0) { + printf("Types: all_types"); + for (i = 0; portal_debug_masks[i] != NULL; i++) + printf(", %s", portal_debug_masks[i]); + printf("\n"); + } + return 0; +} + +int jt_debug_modules(int argc, char **argv) { + char *modules[] = {"portals", "ksocknal", "obdclass", "ptlrpc", + "obdext2", "ost", "osc", "mds", "mdc", "llite", + "obdecho", "ldlm", "obdfilter", "extN", "lov", + "mds_ext2", "mds_ext3", "mds_extN", NULL}; + char *paths[] = {"portals/linux/oslib", "portals/linux/socknal", + "lustre/obdclass", "lustre/ptlrpc", "lustre/obdext2", + "lustre/ost", "lustre/osc", "lustre/mds", "lustre/mdc", + "lustre/llite", "lustre/obdecho", "lustre/ldlm", + "lustre/obdfilter", "lustre/extN", "lustre/lov", + "lustre/mds", "lustre/mds", "lustre/mds", NULL}; + char *path = ".."; + char *kernel = "linux"; + int i; + + if (argc >= 2) + path = argv[1]; + if (argc == 3) + kernel = argv[2]; + if (argc > 3) { + printf("%s [path] [kernel]\n", argv[0]); + return 0; + } + + printf("set height 1000\n" + "symbol-file\n" + "delete\n" + "symbol-file %s\n" + "b panic\n" + "b stop\n", kernel); + + for (i = 0; modules[i] != NULL; i++) { + struct module_info info; + int rc; + size_t crap; + int query_module(const char *name, int which, void *buf, + size_t bufsize, size_t *ret); + + rc = query_module(modules[i], QM_INFO, &info, sizeof(info), + &crap); + if (rc < 0) { + if (errno != ENOENT) + printf("query_module(%s) failed: %s\n", + modules[i], strerror(errno)); + } else { + printf("add-symbol-file %s/%s/%s.o 0x%0lx\n", path, + paths[i], modules[i], + info.addr + sizeof(struct module)); + } + } + printf("set height 24\n"); + + return 0; +} + +int jt_debug_panic(int argc, char **argv) { + int rc; + struct portal_ioctl_data data; + + PORTALS_CONNECT; + if (argc != 1) + return CMD_HELP; + + memset(&data, 0, sizeof(data)); + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + return -1; + } + + rc = ioctl(g_pfd, IOC_PORTAL_PANIC, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_PANIC failed: %s\n", + strerror(errno)); + return -1; + } + return 0; +} diff --git a/lustre/utils/device.c b/lustre/utils/device.c new file mode 100644 index 0000000..59ba760 --- /dev/null +++ b/lustre/utils/device.c @@ -0,0 +1,919 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2002 Cluster File Systems, Inc. + * Author: Peter J. Braam + * Author: Phil Schwan + * Author: Brian Behlendorf + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define printk printf + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include /* needed for PAGE_SIZE - rread*/ + +#include "parser.h" +#include "lctl.h" + +#define __KERNEL__ +#include +#undef __KERNEL__ + +static int fd = -1; +static uint64_t conn_addr = -1; +static uint64_t conn_cookie; +static char rawbuf[8192]; +static char *buf = rawbuf; +static int max = 8192; +static int rc = 0; + +#if 0 +static int thread; +#endif + +int device_setup(int argc, char **argv) { + return 0; +} + +/* Misc support functions */ +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; +} + +#if 0 +/* pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L" */ +static 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); +} +#endif + +/* Device selection commands */ +int jt_dev_newdev(int argc, char **argv) { + struct obd_ioctl_data data; + + LUSTRE_CONNECT(argv[0]); + IOCINIT(data); + + if (argc != 1) + return CMD_HELP; + + 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 do_device(char *func, int dev) { + struct obd_ioctl_data data; + + memset(&data, 0, sizeof(data)); + data.ioc_dev = dev; + LUSTRE_CONNECT(func); + + 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); +} + +int jt_dev_device(int argc, char **argv) { + do_disconnect(argv[0], 1); + + if (argc != 2) + return CMD_HELP; + + 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 do_uuid2dev(char *func, char *name) { + return 0; +} + +int jt_dev_uuid2dev(int argc, char **argv) { + do_uuid2dev(NULL, NULL); + return 0; +} + +static int do_name2dev(char *func, char *name) { + struct obd_ioctl_data data; + + LUSTRE_CONNECT(func); + 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; +} + +int jt_dev_name2dev(int argc, char **argv) { + + if (argc != 2) + return CMD_HELP; + + 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; +} + +int jt_dev_list(int argc, char **argv) { + char buf[1024]; + struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf; + + LUSTRE_CONNECT(argv[0]); + 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) + return CMD_HELP; + + 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; +} + +/* Device configuration commands */ +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; +} + +#if 0 +static int jt_dev_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; +} +#endif + +int jt_dev_probe(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + do_disconnect(argv[0], 1); + + if (argc != 1) + return CMD_HELP; + + 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; +} + +int jt_dev_close(int argc, char **argv) { + if (argc != 1) + return CMD_HELP; + + if (conn_addr == -1) + return 0; + + return do_disconnect(argv[0], 0); +} + +#if 0 +static int jt__device(int argc, char **argv) +{ + char *arg2[3]; + int ret; + + if (argc < 3) { + fprintf(stderr, "usage: %s devno \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); + } + + if (!rc) + rc = Parser_execarg(argc - 2, argv + 2, cmdlist); + + ret = do_disconnect(argv[0], 0); + if (!rc) + rc = ret; + + return rc; +} + +static int jt__threads(int argc, char **argv) +{ + int threads, next_thread; + int verbose; + int i, j; + + if (argc < 5) { + fprintf(stderr, + "usage: %s numthreads verbose devno \n", + argv[0]); + return -1; + } + + threads = strtoul(argv[1], 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]); + + for (i = 1, next_thread = verbose; i <= threads; i++) { + rc = fork(); + if (rc < 0) { + fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i, + strerror(rc = errno)); + break; + } else if (rc == 0) { + thread = i; + argv[2] = "--device"; + return jt__device(argc - 2, argv + 2); + } else if (be_verbose(verbose, NULL, i, &next_thread, threads)) + printf("%s: thread #%d (PID %d) started\n", + argv[0], i, rc); + rc = 0; + } + + if (!thread) { /* parent process */ + if (!verbose) + printf("%s: started %d threads\n\n", argv[0], i - 1); + else + printf("\n"); + + for (j = 1; j < i; j++) { + int status; + int ret = wait(&status); + + if (ret < 0) { + fprintf(stderr, "error: %s: wait - %s\n", + argv[0], strerror(errno)); + if (!rc) + rc = errno; + } 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; + } + } + } + + return rc; +} +#endif + +int jt_dev_attach(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 2 && argc != 3 && argc != 4) + return CMD_HELP; + + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + if (argc >= 3) { + data.ioc_inllen2 = strlen(argv[2]) + 1; + data.ioc_inlbuf2 = argv[2]; + } + + 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; + } + + 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; +} + +int jt_dev_setup(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc > 3) + return CMD_HELP; + + data.ioc_dev = -1; + if (argc > 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]; + } + if ( argc == 3 ) { + data.ioc_inllen2 = strlen(argv[2]) + 1; + data.ioc_inlbuf2 = argv[2]; + } + + if (obd_ioctl_pack(&data, &buf, max)) { + fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0])); + return -2; + } + rc = ioctl(fd, OBD_IOC_SETUP , buf); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} + +int jt_dev_detach(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 1) + return CMD_HELP; + + if (obd_ioctl_pack(&data, &buf, max)) { + fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0])); + return -2; + } + + rc = ioctl(fd, OBD_IOC_DETACH , buf); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc=errno)); + + return rc; +} + +int jt_dev_cleanup(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 1) + return CMD_HELP; + + rc = ioctl(fd, OBD_IOC_CLEANUP , &data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc=errno)); + + return rc; +} + +int jt_dev_lov_config(int argc, char **argv) { + struct obd_ioctl_data data; + struct lov_desc desc; + uuid_t *uuidarray; + int size, i; + + IOCINIT(data); + if (argc <= 5) + return CMD_HELP; + + if (strlen(argv[1]) > sizeof(uuid_t) - 1) { + fprintf(stderr, "lov_config: no %dB memory for uuid's\n", + size); + return -ENOMEM; + } + + memset(&desc, 0, sizeof(desc)); + strcpy(desc.ld_uuid, argv[1]); + desc.ld_default_stripecount = strtoul(argv[2], NULL, 0); + desc.ld_default_stripesize = strtoul(argv[3], NULL, 0); + desc.ld_pattern = strtoul(argv[4], NULL, 0); + desc.ld_tgt_count = argc - 5; + + + size = sizeof(uuid_t) * desc.ld_tgt_count; + uuidarray = malloc(size); + if (!uuidarray) { + fprintf(stderr, "lov_config: no %dB memory for uuid's\n", + size); + return -ENOMEM; + } + memset(uuidarray, 0, size); + for (i=5 ; i < argc ; i++) { + char *buf = (char *) (uuidarray + i -5 ); + if (strlen(argv[i]) >= sizeof(uuid_t)) { + fprintf(stderr, "lov_config: arg %d (%s) too long\n", + i, argv[i]); + free(uuidarray); + return -EINVAL; + } + strcpy(buf, argv[i]); + } + + data.ioc_inllen1 = sizeof(desc); + data.ioc_inlbuf1 = (char *)&desc; + data.ioc_inllen2 = size; + data.ioc_inlbuf2 = (char *)uuidarray; + + if (obd_ioctl_pack(&data, &buf, max)) { + fprintf(stderr, "error: %s: invalid ioctl\n",cmdname(argv[0])); + return -EINVAL; + } + + rc = ioctl(fd, OBD_IOC_LOV_CONFIG , buf); + if (rc < 0) + fprintf(stderr, "lov_config: error: %s: %s\n", + cmdname(argv[0]),strerror(rc = errno)); + free(uuidarray); + return rc; +} + +#if 0 +int jt_dev_create(int argc, char **argv) { + struct obd_ioctl_data data; + struct timeval next_time; + int count = 1, next_count; + int verbose; + int i; + + IOCINIT(data); + if (argc < 2 || argc > 4) + return CMD_HELP; + + count = strtoul(argv[1], NULL, 0); + + if (argc > 2) + data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0); + else + data.ioc_obdo1.o_mode = 0100644; + data.ioc_obdo1.o_valid = OBD_MD_FLMODE; + + verbose = get_verbose(argv[3]); + + printf("%s: %d obdos\n", cmdname(argv[0]), count); + gettimeofday(&next_time, NULL); + next_time.tv_sec -= verbose; + + for (i = 1, next_count = verbose; i <= count ; i++) { + rc = ioctl(fd, OBD_IOC_CREATE , &data); + if (rc < 0) { + fprintf(stderr, "error: %s: #%d - %s\n", + cmdname(argv[0]), i, strerror(rc = errno)); + break; + } + if (be_verbose(verbose, &next_time, i, &next_count, count)) + printf("%s: #%d is object id %Ld\n", cmdname(argv[0]), + i, data.ioc_obdo1.o_id); + } + return rc; +} + +int jt_dev_destroy(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 2) { + fprintf(stderr, "usage: %s id\n", cmdname(argv[0])); + return -1; + } + + data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0); + data.ioc_obdo1.o_mode = S_IFREG|0644; + + rc = ioctl(fd, OBD_IOC_DESTROY , &data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} +#endif + +/* Device configuration commands */ +int jt_dev_setattr(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 2) + return CMD_HELP; + + 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; + + rc = ioctl(fd, OBD_IOC_SETATTR , &data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} + +int jt_dev_getattr(int argc, char **argv) { + struct obd_ioctl_data data; + + if (argc != 2) + return CMD_HELP; + + IOCINIT(data); + data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0); + /* 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); + + rc = ioctl(fd, OBD_IOC_GETATTR , &data); + if (rc) { + fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]), + strerror(rc=errno)); + } else { + printf("%s: object id %Ld, mode %o\n", cmdname(argv[0]), + data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode); + } + return rc; +} + +int jt_dev_test_getattr(int argc, char **argv) { + struct obd_ioctl_data data; + struct timeval start, next_time; + int i, count, next_count; + int verbose; + + if (argc != 2 && argc != 3) + return CMD_HELP; + + IOCINIT(data); + count = strtoul(argv[1], 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); + next_time.tv_sec = start.tv_sec - verbose; + next_time.tv_usec = start.tv_usec; + printf("%s: getting %d attrs (testing only): %s", cmdname(argv[0]), + count, ctime(&start.tv_sec)); + + for (i = 1, next_count = verbose; i <= count; i++) { + rc = ioctl(fd, OBD_IOC_GETATTR , &data); + 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)) + printf("%s: got attr #%d\n", cmdname(argv[0]), i); + } + } + + if (!rc) { + struct timeval end; + double diff; + + gettimeofday(&end, NULL); + + diff = difftime(&end, &start); + + --i; + printf("%s: %d attrs in %.4gs (%.4g attr/s): %s", + cmdname(argv[0]), i, diff, (double)i / diff, + ctime(&end.tv_sec)); + } + return rc; +} + +int jt_dev_test_brw(int argc, char **argv) { + struct obd_ioctl_data data; + struct timeval start, next_time; + char *bulk, *b; + int pages = 1, obdos = 1, count, next_count; + int verbose = 1, write = 0, rw; + int i, o, p; + int len; + + if (argc < 2 || argc > 6) + return CMD_HELP; + + count = strtoul(argv[1], NULL, 0); + + if (argc >= 3) { + if (argv[2][0] == 'w' || argv[2][0] == '1') + write = 1; + else if (argv[2][0] == 'r' || argv[2][0] == '0') + write = 0; + + verbose = get_verbose(argv[3]); + } + + if (argc >= 5) + pages = strtoul(argv[4], NULL, 0); + if (argc >= 6) + obdos = strtoul(argv[5], NULL, 0); + + if (obdos != 1 && obdos != 2) { + fprintf(stderr, "error: %s: only 1 or 2 obdos supported\n", + cmdname(argv[0])); + return -2; + } + + len = pages * PAGE_SIZE; + + bulk = calloc(obdos, len); + if (!bulk) { + fprintf(stderr,"error: %s: no memory allocating %dx%d pages\n", + cmdname(argv[0]), obdos, pages); + return -2; + } + IOCINIT(data); + 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 = 3; + data.ioc_plen2 = len; + data.ioc_pbuf2 = bulk + len; + } + + gettimeofday(&start, NULL); + next_time.tv_sec = start.tv_sec - verbose; + next_time.tv_usec = start.tv_usec; + + printf("%s: %s %d (%dx%d pages) (testing only): %s", + cmdname(argv[0]), write ? "writing" : "reading", + count, obdos, pages, ctime(&start.tv_sec)); + + /* + * 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) + memcpy(b, &start, sizeof(start)); + + rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ; + for (i = 1, next_count = verbose; i <= count; i++) { + if (write) { + b = bulk + sizeof(struct timeval); + for (o = 0; o < obdos; o++) + for (p = 0; p < pages; p++, b += PAGE_SIZE) + memcpy(b, &count, sizeof(count)); + } + + rc = ioctl(fd, rw, &data); + if (rc) { + fprintf(stderr, "error: %s: #%d - %s on %s\n", + cmdname(argv[0]), i, strerror(rc = errno), + write ? "write" : "read"); + break; + } else if (be_verbose(verbose,&next_time,i,&next_count,count)) + printf("%s: %s number %d\n", cmdname(argv[0]), + write ? "write" : "read", i); + } + + free(bulk); + + if (!rc) { + struct timeval end; + double diff; + + gettimeofday(&end, NULL); + + diff = difftime(&end, &start); + + --i; + printf("%s: %s %dx%dx%d pages in %.4gs (%.4g pg/s): %s", + cmdname(argv[0]), write ? "wrote" : "read", obdos, + pages, i, diff, (double)obdos * i * pages / diff, + ctime(&end.tv_sec)); + } + return rc; +} + +int jt_dev_test_ldlm(int argc, char **argv) { + struct obd_ioctl_data data; + + IOCINIT(data); + if (argc != 1) + return CMD_HELP; + + rc = ioctl(fd, IOC_LDLM_TEST, &data); + if (rc) + fprintf(stderr, "error: %s: test failed: %s\n", + cmdname(argv[0]), strerror(rc = errno)); + return rc; +} diff --git a/lustre/utils/lctl.h b/lustre/utils/lctl.h new file mode 100644 index 0000000..0de7fe9 --- /dev/null +++ b/lustre/utils/lctl.h @@ -0,0 +1,127 @@ +#ifndef _LCTL_H_ +#define _LCTL_H_ + +#include "parser.h" +extern command_t cmdlist[]; + +/* Network configuration commands */ +int jt_net_network(int argc, char **argv); +int jt_net_connect(int argc, char **argv); +int jt_net_disconnect(int argc, char **argv); +int jt_net_add_uuid(int argc, char **argv); +int jt_net_del_uuid(int argc, char **argv); +int jt_net_mynid(int argc, char **argv); +int jt_net_add_route(int argc, char **argv); +int jt_net_del_route(int argc, char **argv); +int jt_net_route_list(int argc, char **argv); +int jt_net_recv_mem(int argc, char **argv); +int jt_net_send_mem(int argc, char **argv); +int jt_net_nagle(int argc, char **argv); + +/* Device selection commands */ +int jt_dev_newdev(int argc, char **argv); +int jt_dev_uuid2dev(int argc, char **argv); +int jt_dev_name2dev(int argc, char **argv); +int jt_dev_device(int argc, char **argv); +int jt_dev_list(int argc, char **argv); + +/* Device configuration commands */ +int jt_dev_attach(int argc, char **argv); +int jt_dev_setup(int argc, char **argv); +int jt_dev_cleanup(int argc, char **argv); +int jt_dev_detach(int argc, char **argv); +int jt_dev_lov_config(int argc, char **argv); + +/* Device operations */ +int jt_dev_probe(int argc, char **argv); +int jt_dev_close(int argc, char **argv); +int jt_dev_getattr(int argc, char **argv); +int jt_dev_setattr(int argc, char **argv); +int jt_dev_test_getattr(int argc, char **argv); +int jt_dev_test_brw(int argc, char **argv); +int jt_dev_test_ldlm(int argc, char **argv); + +/* Debug commands */ +int jt_debug_kernel(int argc, char **argv); +int jt_debug_file(int argc, char **argv); +int jt_debug_clear(int argc, char **argv); +int jt_debug_mark(int argc, char **argv); +int jt_debug_filter(int argc, char **argv); +int jt_debug_show(int argc, char **argv); +int jt_debug_list(int argc, char **argv); +int jt_debug_modules(int argc, char **argv); +int jt_debug_panic(int argc, char **argv); + +int do_disconnect(char *func, int verbose); +int network_setup(int argc, char **argv); +int device_setup(int argc, char **argv); +int debug_setup(int argc, char **argv); + + +/* So we can tell between error codes and devices */ +#define N2D_OFF 0x100 + +#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) + +#define PORTALS_CONNECT \ +do { \ + if (g_pfd != -1) \ + break; \ + \ + g_pfd = open("/dev/portals", O_RDWR); \ + if (g_pfd < 0) { \ + fprintf(stderr, "error: failed to open /dev/portals: %s\n" \ + "hint: the portals module may not be loaded\n", \ + strerror(errno)); \ + return -1; \ + } \ +} while(0) + +#define LUSTRE_CONNECT(func) \ +do { \ + if (fd != -1) \ + break; \ + \ + fd = open("/dev/obd", O_RDWR); \ + if (fd < 0) { \ + fprintf(stderr, "error: %s failed to open /dev/obd: %s\n" \ + "hint: the lustre modules may not be loaded\n", \ + cmdname(func), strerror(errno)); \ + return -1; \ + } \ +} while(0) + +#define difftime(a, b) \ + ((double)((a)->tv_sec - (b)->tv_sec) + \ + ((double)((a)->tv_usec - (b)->tv_usec) / 1000000)) + +static inline char *cmdname(char *func) { + static char buf[512]; + int thread = 0; + + if (thread) { + sprintf(buf, "%s-%d", func, thread); + return buf; + } + + return func; +} + +typedef struct { + char *name; + int num; +} name2num_t; + +#endif + diff --git a/lustre/utils/network.c b/lustre/utils/network.c new file mode 100644 index 0000000..5639197 --- /dev/null +++ b/lustre/utils/network.c @@ -0,0 +1,729 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001, 2002 Cluster File Systems, Inc. + * + * This file is a modified version of the ptlctl tool which is + * part of Portals, http://www.sf.net/projects/lustre/ + * + * Portals is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Portals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Portals; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lctl.h" + +static char rawbuf[8192]; +static char *buf = rawbuf; +static int max = 8192; + +static unsigned int g_nid = 0; +static unsigned int g_nal = 0; +static unsigned short g_port = 0; +static int g_pfd = -1; + +static int g_socket_txmem = 0; +static int g_socket_rxmem = 0; +static int g_socket_nonagle = 1; + +static name2num_t nalnames[] = { + {"tcp", SOCKNAL}, + {"elan", QSWNAL}, + {"gm", GMNAL}, + {NULL, -1} +}; + +int network_setup(int argc, char **argv) { + PORTALS_CONNECT; + return 0; +} + +static name2num_t *name2num_lookup_name(name2num_t *table, char *str) { + while (table->name != NULL) + if (!strcmp (str, table->name)) + return (table); + else + table++; + return (NULL); +} + +static name2num_t *name2num_lookup_num(name2num_t *table, int num) { + while (table->name != NULL) + if (num == table->num) + return (table); + else + table++; + return (NULL); +} + +static int name2nal(char *str) { + name2num_t *e = name2num_lookup_name (nalnames, str); + + return ((e == NULL) ? 0 : e->num); +} + +static char *nal2name (int nal) { + name2num_t *e = name2num_lookup_num (nalnames, nal); + + return ((e == NULL) ? "???" : e->name); +} + +static int nid2nal(ptl_nid_t nid) { + /* BIG pragmatic assumption */ + return ((((__u32)nid) & 0xffff0000) != 0 ? SOCKNAL : QSWNAL); +} + +static int parse_nid(ptl_nid_t *nidp, char *str) { + struct hostent *he; + int a; + int b; + int c; + int d; + + if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && + (a & ~0xff) == 0 && (b & ~0xff) == 0 && + (c & ~0xff) == 0 && (d & ~0xff) == 0) { + __u32 addr = (a<<24)|(b<<16)|(c<<8)|d; + *nidp = (ptl_nid_t)addr; + return (0); + } + + if ((('a' <= str[0] && str[0] <= 'z') || + ('A' <= str[0] && str[0] <= 'Z')) && + (he = gethostbyname (str)) != NULL) { + __u32 addr = *(__u32 *)he->h_addr; + *nidp = (ptl_nid_t)ntohl(addr); /* HOST byte order */ + return (0); + } + + if (sscanf (str, "%i", &a) == 1) { + *nidp = (ptl_nid_t)a; + return (0); + } + + return (-1); +} + +static char *nid2str (char *buffer, ptl_nid_t nid) { + switch (nid2nal(nid)) { + case QSWNAL: + sprintf (buffer, "%Ld", nid); + return (buffer); + + case SOCKNAL: { + __u32 addr = htonl((__u32)nid); /* back to NETWORK byte order*/ + struct hostent *he = gethostbyaddr ((const char *)&addr, + sizeof(addr), AF_INET); + + if (he != NULL) { + strcpy (buffer, he->h_name); + } else { + addr = (__u32)nid; + sprintf(buffer, "%d.%d.%d.%d", (addr>>24)&0xff, + (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff); + } + return (buffer); + } + + default: + sprintf (buffer, "nid2nal broken"); + return (buffer); + } +} + +int jt_net_network(int argc, char **argv) { + int nal; + + if (argc != 2 || (nal = name2nal (argv[1])) == 0) + return CMD_HELP; + + g_nal = nal; + return (0); +} + +int jt_net_connect(int argc, char **argv) { + if (argc < 2) + return CMD_HELP; + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + if (g_nal == SOCKNAL) { + struct hostent *he; + struct portal_ioctl_data data; + struct sockaddr_in srvaddr; + int fd, rc; + int nonagle = 0; + int rxmem = 0; + int txmem = 0; + int o; + int olen; + + if (argc != 3) + return CMD_HELP; + + he = gethostbyname(argv[1]); + if (!he) { + fprintf(stderr, "gethostbyname error: %s\n", + strerror(errno)); + return -1; + } + + g_port = atol(argv[2]); + + memset(&srvaddr, 0, sizeof(srvaddr)); + srvaddr.sin_family = AF_INET; + srvaddr.sin_port = htons(g_port); + srvaddr.sin_addr.s_addr = *(__u32 *)he->h_addr; + + fd = socket(PF_INET, SOCK_STREAM, 0); + if ( fd < 0 ) { + fprintf(stderr, "socket() failed: %s\n", + strerror(errno)); + return -1; + } + + if (g_socket_nonagle) { + o = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, + &o, sizeof (o)) != 0) { + fprintf(stderr, "cannot disable nagle: %s\n", + strerror(errno)); + return (-1); + } + } + + if (g_socket_rxmem != 0) { + o = g_socket_rxmem; + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, + &o, sizeof (o)) != 0) { + fprintf(stderr, "cannot set receive buffer " + "size: %s\n", strerror(errno)); + return (-1); + } + } + + if (g_socket_txmem != 0) { + o = g_socket_txmem; + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, + &o, sizeof (o)) != 0) { + fprintf(stderr, "cannot set send buffer " + "size: %s\n", strerror(errno)); + return (-1); + } + } + + rc = connect(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)); + if ( rc == -1 ) { + fprintf(stderr, "connect() failed: %s\n", + strerror(errno)); + return -1; + } + + olen = sizeof (txmem); + if (getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, &olen) != 0) + fprintf(stderr, "Can't get send buffer size: %s\n", + strerror(errno)); + olen = sizeof (rxmem); + if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, &olen) != 0) + fprintf(stderr, "Can't get receive buffer size: %s\n", + strerror(errno)); + olen = sizeof (nonagle); + if (getsockopt(fd,IPPROTO_TCP,TCP_NODELAY,&nonagle,&olen) != 0) + fprintf(stderr, "Can't get nagle: %s\n", + strerror(errno)); + + fprintf(stderr, "Connected to %s (snd %d, rcv %d, nagle %s)\n", + argv[1],txmem,rxmem,nonagle ? "Disabled" : "Enabled"); + + PORTAL_IOC_INIT(data); + data.ioc_fd = fd; + /* HOST byte order */ + data.ioc_nid = ntohl(srvaddr.sin_addr.s_addr); + + rc = ioctl(g_pfd, IOC_PORTAL_REGISTER_CLIENT_FD, &data); + if (rc) { + fprintf(stderr, "failed to register fd with portals: " + "%s\n", strerror(errno)); + return -1; + } + + g_nid = ntohl (srvaddr.sin_addr.s_addr); /* HOST byte order */ + fprintf(stderr, "Connection to 0x%x registered with socknal\n", + g_nid); + + rc = close(fd); + if (rc) { + fprintf(stderr, "close failed: %d\n", rc); + } + } else if (g_nal == QSWNAL) { + g_nid = atoi(argv[1]); + } else if (g_nal == GMNAL) { + g_nid = atoi(argv[1]); + } else { + fprintf(stderr, "This should never happen. Also it is very " + "bad.\n"); + } + + return 0; +} + +int jt_net_disconnect(int argc, char **argv) { + if (argc > 2) + return CMD_HELP; + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + if (g_nal == SOCKNAL) { + struct hostent *he; + struct portal_ioctl_data data; + int rc; + + PORTAL_IOC_INIT(data); + if (argc == 2) { + he = gethostbyname(argv[1]); + if (!he) { + fprintf(stderr, "gethostbyname error: %s\n", + strerror(errno)); + return -1; + } + + /* HOST byte order */ + data.ioc_nid = ntohl (*(__u32 *)he->h_addr); + + } else { + fprintf(stderr, "Disconnecting ALL connections.\n"); + /* leave ioc_nid zeroed == disconnect all */ + } + rc = ioctl(g_pfd, IOC_PORTAL_CLOSE_CONNECTION, &data); + if (rc) { + fprintf(stderr, "failed to remove connection: %s\n", + strerror(errno)); + return -1; + } + } else if (g_nal == QSWNAL) { + fprintf(stderr, "'disconnect' doesn't make any sense for " + "elan.\n"); + } else if (g_nal == GMNAL) { + fprintf(stderr, "'disconnect' doesn't make any sense for " + "GM.\n"); + } else { + fprintf(stderr, "This should never happen. Also it is very " + "bad.\n"); + } + + return 0; +} + +/* +int jt_net_ping(int argc, char **argv) { + int rc; + ptl_nid_t nid; + long count = 1; + long size = 4; + long timeout = 1; + struct portal_ioctl_data data; + + if (argc < 2) { + fprintf(stderr, "usage: %s nid [count] [size] [timeout " + (secs)]\n", argv[0]); + return 0; + } + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + if (parse_nid (&nid, argv[1]) != 0) { + fprintf (stderr, "Can\'t parse nid \"%s\"\n", argv[1]); + return (-1); + } + + if (argc > 2) { + count = atol(argv[2]); + + if (count < 0 || count > 20000) { + fprintf(stderr, "are you insane? " + "%ld is a crazy count.\n", count); + return -1; + } + } + + if (argc > 3) + size= atol(argv[3]); + + if (argc > 4) + timeout = atol (argv[4]); + + PORTAL_IOC_INIT (data); + data.ioc_count = count; + data.ioc_size = size; + data.ioc_nid = (__u32)nid; + data.ioc_nal = g_nal; + data.ioc_timeout = timeout; + + rc = ioctl(g_pfd, IOC_PORTAL_PING, &data); + if (rc) { + fprintf(stderr, "failed to start pinger: %s\n", + strerror(errno)); + return -1; + } + fprintf(stderr, "Pinger started, take cover...\n"); + return 0; +} +*/ + +int jt_net_mynid(int argc, char **argv) { + int rc; + struct hostent *h; + char buf[1024], *hostname; + struct portal_ioctl_data data; + ptl_nid_t mynid; + + if (argc > 2) + return CMD_HELP; + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + if (g_nal == QSWNAL) { + fprintf(stderr, "'mynid' doesn't make any sense for elan.\n"); + return -1; + } else if (g_nal == GMNAL) { + fprintf(stderr, "'mynid' doesn't make any sense for GM.\n"); + return -1; + } + + if (g_nal != SOCKNAL) { + fprintf(stderr, "This should never happen. Also it is very " + "bad.\n"); + return -1; + } + + if (argc == 1) { + if (gethostname(buf, sizeof(buf)) != 0) { + fprintf(stderr, "gethostname failed: %s\n", + strerror(errno)); + return -1; + } + hostname = buf; + } else { + hostname = argv[1]; + } + + h = gethostbyname(hostname); + + if (!h) { + fprintf(stderr, "cannot get address for host '%s': %d\n", + hostname, h_errno); + return -1; + } + mynid = (ptl_nid_t)ntohl (*(__u32 *)h->h_addr); /* HOST byte order */ + + PORTAL_IOC_INIT(data); + data.ioc_nid = (__u32)mynid; + + rc = ioctl(g_pfd, IOC_PORTAL_REGISTER_MYNID, &data); + if (rc < 0) + fprintf(stderr, "IOC_PORTAL_REGISTER_MYNID failed: %s\n", + strerror(errno)); + else + fprintf(stderr, "registered my nid 0x%Lx (%s)\n", + mynid, hostname); + return 0; +} + +int jt_net_add_uuid(int argc, char **argv) { + char tmp[64]; + int rc; + struct portal_ioctl_data data; + ptl_nid_t nid = g_nid; + + if (argc != 3) + return CMD_HELP; + + if (parse_nid(&nid, argv[2]) != 0) { + fprintf (stderr, "Can't parse NID %s\n", argv[2]); + return (-1); + } + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + memset(&data, 0, sizeof(data)); + data.ioc_nid = nid; + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + data.ioc_nal = g_nal; + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + return -1; + } + + rc = ioctl(g_pfd, IOC_PORTAL_ADD_UUID, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n", + strerror(errno)); + return -1; + } + + fprintf (stderr, "Added uuid %s: %s\n", argv[1], nid2str (tmp, nid)); + return 0; +} + +#if 0 +static int jt_close_uuid(int argc, char **argv) +{ + int rc; + struct portal_ioctl_data data; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 0; + } + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + memset(&data, 0, sizeof(data)); + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + data.ioc_nal = g_nal; + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + return -1; + } + + rc = ioctl(g_pfd, IOC_PORTAL_CLOSE_UUID, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n", + strerror(errno)); + return -1; + } + return 0; +} +#endif + +int jt_net_del_uuid(int argc, char **argv) { + int rc; + struct portal_ioctl_data data; + + if (argc != 2) + return CMD_HELP; + + if (g_nal == 0) { + fprintf(stderr, "Error: you must run the 'setup' command " + "first.\n"); + return -1; + } + + memset(&data, 0, sizeof(data)); + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + data.ioc_nal = g_nal; + if (portal_ioctl_pack(&data, &buf, max) != 0) { + fprintf(stderr, "portal_ioctl_pack failed.\n"); + return -1; + } + + rc = ioctl(g_pfd, IOC_PORTAL_DEL_UUID, buf); + if (rc) { + fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n", + strerror(errno)); + return -1; + } + return 0; +} + +int jt_net_add_route (int argc, char **argv) { + struct portal_ioctl_data data; + ptl_nid_t nid1; + ptl_nid_t nid2; + ptl_nid_t gateway_nid; + int gateway_nal; + int rc; + + if (argc < 3) + return CMD_HELP; + + if (parse_nid (&gateway_nid, argv[1]) != 0) { + fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]); + return (-1); + } + + gateway_nal = nid2nal (gateway_nid); + if (parse_nid (&nid1, argv[2]) != 0) { + fprintf(stderr, "Can't parse first target NID \"%s\"\n", + argv[2]); + return (-1); + } + + if (argc < 4) { + nid2 = nid1; + } else if (parse_nid (&nid2, argv[3]) != 0) { + fprintf(stderr, "Can't parse second target NID \"%s\"\n", + argv[4]); + return (-1); + } + + PORTAL_IOC_INIT(data); + data.ioc_nid = gateway_nid; + data.ioc_nal = gateway_nal; + data.ioc_nid2 = MIN (nid1, nid2); + data.ioc_nid3 = MAX (nid1, nid2); + + rc = ioctl (g_pfd, IOC_PORTAL_ADD_ROUTE, &data); + if (rc != 0) { + fprintf(stderr, "IOC_PORTAL_ADD_ROUTE failed: %s\n", + strerror (errno)); + return (-1); + } + + return (0); +} + +int jt_net_del_route(int argc, char **argv) { + struct portal_ioctl_data data; + ptl_nid_t nid; + int rc; + + if (argc < 2) + return CMD_HELP; + + if (parse_nid (&nid, argv[1]) != 0) { + fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]); + return (-1); + } + + PORTAL_IOC_INIT(data); + data.ioc_nid = nid; + + rc = ioctl (g_pfd, IOC_PORTAL_DEL_ROUTE, &data); + if (rc != 0) { + fprintf(stderr, "IOC_PORTAL_DEL_ROUTE (0x%Lx) failed: %s\n", + nid, strerror (errno)); + return (-1); + } + + return (0); +} + +int jt_net_route_list(int argc, char **argv) { + char buffer[3][128]; + struct portal_ioctl_data data; + int rc; + int index; + int gateway_nal; + ptl_nid_t gateway_nid; + ptl_nid_t nid1; + ptl_nid_t nid2; + + for (index = 0;;index++) { + PORTAL_IOC_INIT(data); + data.ioc_count = index; + + rc = ioctl (g_pfd, IOC_PORTAL_GET_ROUTE, &data); + if (rc != 0) + break; + + gateway_nal = data.ioc_nal; + gateway_nid = data.ioc_nid; + nid1 = data.ioc_nid2; + nid2 = data.ioc_nid3; + + printf ("%8s %18s : %s - %s\n", + nal2name (gateway_nal), + nid2str (buffer[0], gateway_nid), + nid2str (buffer[1], nid1), + nid2str (buffer[2], nid2)); + } + return (0); +} + +int jt_net_recv_mem(int argc, char **argv) { + int size; + + if (argc > 1) { + if (Parser_size (&size, argv[1]) != 0 || size < 0) { + fprintf (stderr, "Can't parse size %s\n", argv[1]); + return (0); + } + + g_socket_rxmem = size; + } + + printf ("Socket rxmem = %d\n", g_socket_rxmem); + return (0); +} + +int jt_net_send_mem(int argc, char **argv) { + int size; + + if (argc > 1) { + if (Parser_size (&size, argv[1]) != 0 || size < 0) { + fprintf (stderr, "Can't parse size %s\n", argv[1]); + return (0); + } + g_socket_txmem = size; + } + + printf ("Socket txmem = %d\n", g_socket_txmem); + return (0); +} + +int jt_net_nagle(int argc, char **argv) { + int enable; + + if (argc > 1) { + if (Parser_bool (&enable, argv[1]) != 0) { + fprintf (stderr, "Can't parse boolean %s\n", argv[1]); + return (0); + } + g_socket_nonagle = !enable; + } + + printf ("Nagle %s\n", g_socket_nonagle ? "disabled" : "enabled"); + return (0); +} diff --git a/lustre/utils/parser.c b/lustre/utils/parser.c index b06f624..8e8fd04 100644 --- a/lustre/utils/parser.c +++ b/lustre/utils/parser.c @@ -36,10 +36,6 @@ extern void stifle_history(int); extern void add_history(char *); #include "parser.h" -#define CMD_COMPLETE 0 -#define CMD_INCOMPLETE 1 -#define CMD_NONE 2 -#define CMD_AMBIG 3 static command_t * top_level; /* Top level of commands, initialized by * InitParser */ @@ -264,6 +260,10 @@ int execute_line(char * line) case CMD_COMPLETE: i = line2args(line, argv, MAXARGS); rc = (cmd->pc_func)(i, argv); + + if (rc == CMD_HELP) + fprintf(stderr, "%s\n", cmd->pc_help); + break; } @@ -589,6 +589,66 @@ int Parser_arg2int(const char *inp, long *result, int base) return 1; } +/* Convert human readable size string to and int; "1k" -> 1000 */ +int Parser_size (int *sizep, char *str) { + int size; + char mod[32]; + + switch (sscanf (str, "%d%1[gGmMkK]", &size, mod)) { + default: + return (-1); + + case 1: + *sizep = size; + return (0); + + case 2: + switch (*mod) { + case 'g': + case 'G': + *sizep = size << 30; + return (0); + + case 'm': + case 'M': + *sizep = size << 20; + return (0); + + case 'k': + case 'K': + *sizep = size << 10; + return (0); + + default: + *sizep = size; + return (0); + } + } +} + +/* Convert a string boolean to an int; "enable" -> 1 */ +int Parser_bool (int *b, char *str) { + if (strcasecmp (str, "no") || + strcasecmp (str, "n") || + strcasecmp (str, "off") || + strcasecmp (str, "disable")) + { + *b = 0; + return (0); + } + + if (strcasecmp (str, "yes") || + strcasecmp (str, "y") || + strcasecmp (str, "on") || + strcasecmp (str, "enable")) + { + *b = 1; + return (0); + } + + return (-1); +} + int Parser_quit(int argc, char **argv) { argc = argc; diff --git a/lustre/utils/parser.h b/lustre/utils/parser.h index 8f22505..dead9f5 100644 --- a/lustre/utils/parser.h +++ b/lustre/utils/parser.h @@ -4,6 +4,12 @@ #define HISTORY 100 /* Don't let history grow unbounded */ #define MAXARGS 100 +#define CMD_COMPLETE 0 +#define CMD_INCOMPLETE 1 +#define CMD_NONE 2 +#define CMD_AMBIG 3 +#define CMD_HELP 4 + typedef struct parser_cmd { char *pc_name; int (* pc_func)(int, char **); @@ -58,5 +64,10 @@ char *Parser_strarg(char *inp, const char *prompt, const char *deft, /* Extracts an integer from a string with a base */ int Parser_arg2int(const char *inp, long *result, int base); +/* Convert human readable size string to and int; "1k" -> 1000 */ +int Parser_size(int *sizep, char *str); + +/* Convert a string boolean to an int; "enable" -> 1 */ +int Parser_bool(int *b, char *str); #endif