X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fobd.c;h=aad4edf50bcc17f26de67c9a202325094f4ba7e3;hp=771918696cf00b3ee663ccc33c04fab82a223821;hb=0f45a4a2bcfa2db8c2524b2138a019c5fc8f2079;hpb=15b0e514725b0c8e0acdbfc0d5382a6302639d58 diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 7719186..aad4edf 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -1,29 +1,45 @@ /* -*- 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: Andreas Dilger - * Author: Robert Read + * GPL HEADER START * - * This file is part of Lustre, http://www.lustre.org. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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. + * This program 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * 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. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/utils/obd.c + * + * Author: Peter J. Braam + * Author: Phil Schwan + * Author: Andreas Dilger + * Author: Robert Read */ - #include #include @@ -35,11 +51,13 @@ #include #include #include +#include +#include #include "obdctl.h" -#include /* for struct lov_stripe_md */ -#include +#include /* for struct lov_stripe_md */ +#include #include #include @@ -48,119 +66,136 @@ #include #include -#include /* needed for PAGE_SIZE - rread */ - -#define __KERNEL__ -#include -#undef __KERNEL__ - -#include -#include "parser.h" +#include +#include +#include #include - -#define SHMEM_STATS 1 -#if SHMEM_STATS -# include -# include - -# define MAX_SHMEM_COUNT 1024 -static long long *shared_counters; -static long long counter_snapshot[2][MAX_SHMEM_COUNT]; -struct timeval prev_time; +#include + +#define MAX_STRING_SIZE 128 +#define DEVICES_LIST "/proc/fs/lustre/devices" + +#if HAVE_LIBPTHREAD +#include +#include +#include + +#define MAX_THREADS 1024 + +struct shared_data { + __u64 counters[MAX_THREADS]; + __u64 offsets[MAX_THREADS]; + int running; + int barrier; + int stop; + l_mutex_t mutex; + l_cond_t cond; +}; + +static struct shared_data *shared_data; +static __u64 counter_snapshot[2][MAX_THREADS]; +static int prev_valid; +static struct timeval prev_time; +static int thread; +static int nthreads; +#else +const int thread = 0; +const int nthreads = 1; #endif -static int jt_recording; -static uint64_t conn_cookie = -1; -static char rawbuf[8192]; -static char *buf = rawbuf; -static int max = sizeof(rawbuf); +#define MAX_IOC_BUFLEN 8192 -static int thread; +static int cur_device = -1; + +#define MAX_STRIPES 170 +struct lov_oinfo lov_oinfos[MAX_STRIPES]; -union lsm_buffer { - char space [4096]; +struct lsm_buffer { struct lov_stripe_md lsm; + struct lov_oinfo *ptrs[MAX_STRIPES]; } lsm_buffer; static int l2_ioctl(int dev_id, int opc, void *buf) { -// if (jt_recording) { -// struct obd_ioctl_data *data = buf; -// data->ioc_command = opc; -// opc = OBD_IOC_DORECORD; -// } return l_ioctl(dev_id, opc, buf); } -#define IOC_INIT(data) \ -do { \ - memset(&data, 0, sizeof(data)); \ - data.ioc_cookie = conn_cookie; \ -} while (0) - -#define IOC_PACK(func, data) \ -do { \ - memset(buf, 0, sizeof(rawbuf)); \ - if (obd_ioctl_pack(&data, &buf, max)) { \ - fprintf(stderr, "error: %s: invalid ioctl\n", \ - jt_cmdname(func)); \ - return -2; \ - } \ -} while (0) - -#define IOC_UNPACK(func, data) \ -do { \ - if (obd_ioctl_unpack(&data, buf, max)) { \ - fprintf(stderr, "error: %s: invalid reply\n", \ - jt_cmdname(func)); \ - return -2; \ - } \ -} while (0) - -int obd_record(enum cfg_record_type type, int len, void *ptr) +int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int rc; + + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; + data.ioc_type = LUSTRE_CFG_TYPE; + data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount, + lcfg->lcfg_buflens); + data.ioc_pbuf1 = (void *)lcfg; + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(func)); + return rc; + } - IOC_INIT(data); - data.ioc_type = type; - data.ioc_plen1 = len; - data.ioc_pbuf1 = ptr; - IOC_PACK("obd_record", data); + rc = l_ioctl(dev_id, OBD_IOC_PROCESS_CFG, buf); - return l_ioctl(OBD_DEV_ID, OBD_IOC_DORECORD, &data); + return rc; } -int lcfg_ioctl(char * func, int dev_id, struct lustre_cfg *lcfg) +static int do_device(char *func, char *devname); + +static int get_mgs_device() +{ + char mgs[] = "$MGS"; + static int mgs_device = -1; + + if (mgs_device == -1) { + int rc; + do_disconnect(NULL, 1); + rc = do_device("mgsioc", mgs); + if (rc) { + fprintf(stderr, + "This command must be run on the MGS.\n"); + errno = ENODEV; + return -1; + } + mgs_device = cur_device; + } + return mgs_device; +} + +/* Returns -1 on error with errno set */ +int lcfg_mgs_ioctl(char *func, int dev_id, struct lustre_cfg *lcfg) { - int opc; - char lcfg_rawbuf[8192]; - char * lcfg_buf= lcfg_rawbuf; struct obd_ioctl_data data; - int len; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; - memset(lcfg_buf, 0, sizeof(lcfg_rawbuf)); - if (lustre_cfg_pack(lcfg, &lcfg_buf, sizeof(lcfg_rawbuf), &len)) { + memset(&data, 0x00, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + goto out; + data.ioc_type = LUSTRE_CFG_TYPE; + data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount, + lcfg->lcfg_buflens); + data.ioc_pbuf1 = (void *)lcfg; + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { fprintf(stderr, "error: %s: invalid ioctl\n", jt_cmdname(func)); - return -2; + return rc; } - IOC_INIT(data); - data.ioc_type = LUSTRE_CFG_TYPE; - data.ioc_plen1 = len; - data.ioc_pbuf1 = lcfg_buf; - IOC_PACK(func, data); - - if (jt_recording) - opc = OBD_IOC_DORECORD; - else - opc = OBD_IOC_PROCESS_CFG; - - rc = l_ioctl(dev_id, opc, buf); - if (rc == 0) - rc = lustre_cfg_unpack(lcfg, lcfg_buf, sizeof(lcfg_rawbuf)); - + rc = l_ioctl(dev_id, OBD_IOC_PARAM, buf); +out: + if (rc) { + if (errno == ENOSYS) + fprintf(stderr, "Make sure cfg_device is set first.\n"); + } return rc; } @@ -171,10 +206,10 @@ char *obdo_print(struct obdo *obd) sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64 "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64 "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n" - "obdflags: %x\nnlink: %d,\nvalid %x\n", + "misc: %x\nnlink: %d,\nvalid "LPX64"\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_uid, obd->o_gid, obd->o_flags, obd->o_misc, obd->o_nlink, obd->o_valid); return strdup(buf); } @@ -187,18 +222,30 @@ char *obdo_print(struct obdo *obd) static int do_name2dev(char *func, char *name) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; - IOC_INIT(data); - + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(name) + 1; data.ioc_inlbuf1 = name; - IOC_PACK(func, data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(func)); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf); if (rc < 0) return errno; - IOC_UNPACK(func, data); + rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid reply\n", + jt_cmdname(func)); + return rc; + } return data.ioc_dev + N2D_OFF; } @@ -214,75 +261,33 @@ int parse_devname(char *func, char *name) if (!name) return ret; - if (name[0] == '$' || name[0] == '%') { - name++; + if (isdigit(name[0])) { + ret = strtoul(name, NULL, 0); + } else { + if (name[0] == '$' || name[0] == '%') + name++; rc = do_name2dev(func, name); if (rc >= N2D_OFF) { ret = rc - N2D_OFF; - printf("Name %s is device %d\n", name, ret); + // printf("Name %s is device %d\n", name, ret); } else { - printf("No device found for name %s: %s\n", - name, strerror(rc)); + fprintf(stderr, "No device found for name %s: %s\n", + name, strerror(rc)); } - } else { - /* Assume it's a number. This means that bogus strings become - * 0. I might care about that some day. */ - ret = strtoul(name, NULL, 0); - printf("Selected device %d\n", ret); } - return ret; } -static char * -lsm_string (struct lov_stripe_md *lsm) -{ - static char buffer[4096]; - char *p = buffer; - int space = sizeof (buffer); - int i; - int nob; - - *p = 0; - space--; - - nob = snprintf(p, space, LPX64, lsm->lsm_object_id); - p += nob; - space -= nob; - - if (lsm->lsm_stripe_count != 0) { - nob = snprintf (p, space, "=%u#%u", - lsm->lsm_stripe_size, - lsm->lsm_stripe_count); - p += nob; - space -= nob; - - for (i = 0; i < lsm->lsm_stripe_count; i++) { - nob = snprintf (p, space, "@%u:"LPX64, - lsm->lsm_oinfo[i].loi_ost_idx, - lsm->lsm_oinfo[i].loi_id); - p += nob; - space -= nob; - } - } - - if (space == 0) { /* probable overflow */ - fprintf (stderr, "lsm_string() overflowed buffer\n"); - abort (); - } - - return (buffer); -} - static void -reset_lsmb (union lsm_buffer *lsmb) +reset_lsmb (struct lsm_buffer *lsmb) { - memset (lsmb->space, 0, sizeof (lsmb->space)); + memset (&lsmb->lsm, 0, sizeof (lsmb->lsm)); + memset(lov_oinfos, 0, sizeof(lov_oinfos)); lsmb->lsm.lsm_magic = LOV_MAGIC; } static int -parse_lsm (union lsm_buffer *lsmb, char *string) +parse_lsm (struct lsm_buffer *lsmb, char *string) { struct lov_stripe_md *lsm = &lsmb->lsm; char *end; @@ -327,11 +332,11 @@ parse_lsm (union lsm_buffer *lsmb, char *string) if (*string != '@') return (-1); string++; - lsm->lsm_oinfo[i].loi_ost_idx = strtoul(string, &end, 0); + lsm->lsm_oinfo[i]->loi_ost_idx = strtoul(string, &end, 0); if (*end != ':') return (-1); string = end + 1; - lsm->lsm_oinfo[i].loi_id = strtoull(string, &end, 0); + lsm->lsm_oinfo[i]->loi_id = strtoull(string, &end, 0); string = end; } @@ -369,8 +374,7 @@ static int be_verbose(int verbose, struct timeval *next_time, gettimeofday(&now, NULL); /* A positive verbosity means to print every X iterations */ - if (verbose > 0 && - (next_num == NULL || num >= *next_num || num >= num_total)) { + if (verbose > 0 && (num >= *next_num || num >= num_total)) { *next_num += verbose; if (next_time) { next_time->tv_sec = now.tv_sec - verbose; @@ -384,8 +388,7 @@ static int be_verbose(int verbose, struct timeval *next_time, difftime(&now, next_time) >= 0.0){ next_time->tv_sec = now.tv_sec - verbose; next_time->tv_usec = now.tv_usec; - if (next_num) - *next_num = num; + *next_num = num; return 1; } @@ -422,28 +425,30 @@ static int get_verbose(char *func, const char *arg) int do_disconnect(char *func, int verbose) { + lcfg_set_devname(NULL); + cur_device = -1; return 0; } -#if SHMEM_STATS +#ifdef MAX_THREADS static void shmem_setup(void) { /* Create new segment */ - int shmid = shmget(IPC_PRIVATE, sizeof(counter_snapshot[0]), 0600); + int shmid = shmget(IPC_PRIVATE, sizeof(*shared_data), 0600); if (shmid == -1) { - fprintf(stderr, "Can't create shared memory counters: %s\n", + fprintf(stderr, "Can't create shared data: %s\n", strerror(errno)); return; } /* Attatch to new segment */ - shared_counters = (long long *)shmat(shmid, NULL, 0); + shared_data = (struct shared_data *)shmat(shmid, NULL, 0); - if (shared_counters == (long long *)(-1)) { - fprintf(stderr, "Can't attach shared memory counters: %s\n", + if (shared_data == (struct shared_data *)(-1)) { + fprintf(stderr, "Can't attach shared data: %s\n", strerror(errno)); - shared_counters = NULL; + shared_data = NULL; return; } @@ -451,47 +456,70 @@ static void shmem_setup(void) * Forks will inherit attached segments, so we should be OK. */ if (shmctl(shmid, IPC_RMID, NULL) == -1) { - fprintf(stderr, "Can't destroy shared memory counters: %s\n", + fprintf(stderr, "Can't destroy shared data: %s\n", strerror(errno)); } } -static inline void shmem_reset(void) +static inline void shmem_lock(void) +{ + l_mutex_lock(&shared_data->mutex); +} + +static inline void shmem_unlock(void) +{ + l_mutex_unlock(&shared_data->mutex); +} + +static inline void shmem_reset(int total_threads) { - if (shared_counters == NULL) + if (shared_data == NULL) return; - memset(shared_counters, 0, sizeof(counter_snapshot[0])); + memset(shared_data, 0, sizeof(*shared_data)); + l_mutex_init(&shared_data->mutex); + l_cond_init(&shared_data->cond); memset(counter_snapshot, 0, sizeof(counter_snapshot)); - gettimeofday(&prev_time, NULL); + prev_valid = 0; + shared_data->barrier = total_threads; } static inline void shmem_bump(void) { - if (shared_counters == NULL || thread <= 0 || thread > MAX_SHMEM_COUNT) + static int bumped_running; + + if (shared_data == NULL || thread <= 0 || thread > MAX_THREADS) return; - shared_counters[thread - 1]++; + shmem_lock(); + shared_data->counters[thread - 1]++; + if (!bumped_running) + shared_data->running++; + shmem_unlock(); + bumped_running = 1; } -static void shmem_snap(int n) +static void shmem_snap(int total_threads, int live_threads) { struct timeval this_time; int non_zero = 0; - long long total = 0; + __u64 total = 0; double secs; + int running; int i; - if (shared_counters == NULL || n > MAX_SHMEM_COUNT) + if (shared_data == NULL || total_threads > MAX_THREADS) return; - memcpy(counter_snapshot[1], counter_snapshot[0], - n * sizeof(counter_snapshot[0][0])); - memcpy(counter_snapshot[0], shared_counters, - n * sizeof(counter_snapshot[0][0])); + shmem_lock(); + memcpy(counter_snapshot[0], shared_data->counters, + total_threads * sizeof(counter_snapshot[0][0])); + running = shared_data->running; + shmem_unlock(); + gettimeofday(&this_time, NULL); - for (i = 0; i < n; i++) { + for (i = 0; i < total_threads; i++) { long long this_count = counter_snapshot[0][i] - counter_snapshot[1][i]; @@ -502,109 +530,109 @@ static void shmem_snap(int n) } secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) - - (prev_time.tv_sec + prev_time.tv_usec / 1000000.0); + (prev_time.tv_sec + prev_time.tv_usec / 1000000.0); - printf("%d/%d Total: %f/second\n", non_zero, n, total / secs); + if (prev_valid && + secs > 1.0) /* someone screwed with the time? */ + printf("%d/%d Total: %f/second\n", non_zero, total_threads, total / secs); + memcpy(counter_snapshot[1], counter_snapshot[0], + total_threads * sizeof(counter_snapshot[0][0])); prev_time = this_time; + if (!prev_valid && + running == total_threads) + prev_valid = 1; +} + +static void shmem_stop(void) +{ + if (shared_data == NULL) + return; + + shared_data->stop = 1; } -#define SHMEM_SETUP() shmem_setup() -#define SHMEM_RESET() shmem_reset() -#define SHMEM_BUMP() shmem_bump() -#define SHMEM_SNAP(n) shmem_snap(n) +static int shmem_running(void) +{ + return (shared_data == NULL || + !shared_data->stop); +} #else -#define SHMEM_SETUP() -#define SHMEM_RESET() -#define SHMEM_BUMP() -#define SHMEM_SNAP(n) -#endif +static void shmem_setup(void) +{ +} -extern command_t cmdlist[]; +static inline void shmem_reset(int total_threads) +{ +} -static int do_device(char *func, int dev) +static inline void shmem_bump(void) { - struct obd_ioctl_data data; +} - memset(&data, 0, sizeof(data)); +static void shmem_lock() +{ +} - data.ioc_dev = dev; +static void shmem_unlock() +{ +} - IOC_PACK(func, data); - return l2_ioctl(OBD_DEV_ID, OBD_IOC_DEVICE, buf); +static void shmem_stop(void) +{ } -int jt_obd_device(int argc, char **argv) +static int shmem_running(void) { - int rc, dev; - do_disconnect(argv[0], 1); + return 1; +} +#endif - if (argc != 2) - return CMD_HELP; +extern command_t cmdlist[]; + +static int do_device(char *func, char *devname) +{ + int dev; - dev = parse_devname(argv[0], argv[1]); + dev = parse_devname(func, devname); if (dev < 0) return -1; - rc = do_device(argv[0], dev); - if (rc < 0) - fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), - strerror(rc = errno)); - - return rc; + lcfg_set_devname(devname); + cur_device = dev; + return 0; } -int jt_obd_connect(int argc, char **argv) +int jt_obd_get_device() { - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - - do_disconnect(argv[0], 1); - - /* XXX TODO: implement timeout per lctl usage for probe */ - if (argc != 1) - return CMD_HELP; - - IOC_PACK(argv[0], data); - rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CONNECT, buf); - IOC_UNPACK(argv[0], data); - if (rc < 0) - fprintf(stderr, "error: %s: OBD_IOC_CONNECT %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); - else - conn_cookie = data.ioc_cookie; - return rc; + return cur_device; } -int jt_obd_disconnect(int argc, char **argv) +int jt_obd_device(int argc, char **argv) { - if (argc != 1) + int rc; + + if (argc > 2) return CMD_HELP; - if (conn_cookie == -1) + if (argc == 1) { + printf("current device is %d - %s\n", + cur_device, lcfg_get_devname() ? : "not set"); return 0; - - return do_disconnect(argv[0], 0); + } + rc = do_device("device", argv[1]); + return rc; } int jt_opt_device(int argc, char **argv) { - char *arg2[3]; int ret; int rc; if (argc < 3) return CMD_HELP; - rc = do_device("device", parse_devname(argv[0], argv[1])); - - if (!rc) { - arg2[0] = "connect"; - arg2[1] = NULL; - rc = jt_obd_connect(1, arg2); - } + rc = do_device("device", argv[1]); if (!rc) rc = Parser_execarg(argc - 2, argv + 2, cmdlist); @@ -616,20 +644,38 @@ int jt_opt_device(int argc, char **argv) return rc; } +#ifdef MAX_THREADS +static void parent_sighandler (int sig) +{ + return; +} + int jt_opt_threads(int argc, char **argv) { - __u64 threads, next_thread; + static char cmdstr[128]; + sigset_t saveset; + sigset_t sigset; + struct sigaction sigact; + struct sigaction saveact1; + struct sigaction saveact2; + unsigned long threads; + __u64 next_thread; int verbose; int rc = 0; + int report_count = -1; char *end; int i; if (argc < 5) return CMD_HELP; - threads = strtoull(argv[1], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: invalid page count '%s'\n", + threads = strtoul(argv[1], &end, 0); + + if (*end == '.') + report_count = strtoul(end + 1, &end, 0); + + if (*end || threads > MAX_THREADS) { + fprintf(stderr, "error: %s: invalid thread count '%s'\n", jt_cmdname(argv[0]), argv[1]); return CMD_HELP; } @@ -638,11 +684,24 @@ int jt_opt_threads(int argc, char **argv) if (verbose == BAD_VERBOSE) return CMD_HELP; - if (verbose != 0) - printf("%s: starting "LPD64" threads on device %s running %s\n", - argv[0], threads, argv[3], argv[4]); + if (verbose != 0) { + snprintf(cmdstr, sizeof(cmdstr), "%s", argv[4]); + for (i = 5; i < argc; i++) + snprintf(cmdstr + strlen(cmdstr), sizeof(cmdstr), + " %s", argv[i]); + + printf("%s: starting %ld threads on device %s running %s\n", + argv[0], threads, argv[3], cmdstr); + } + + shmem_reset(threads); - SHMEM_RESET(); + sigemptyset(&sigset); + sigaddset(&sigset, SIGALRM); + sigaddset(&sigset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sigset, &saveset); + + nthreads = threads; for (i = 1, next_thread = verbose; i <= threads; i++) { rc = fork(); @@ -651,9 +710,11 @@ int jt_opt_threads(int argc, char **argv) strerror(rc = errno)); break; } else if (rc == 0) { + sigprocmask(SIG_SETMASK, &saveset, NULL); + thread = i; argv[2] = "--device"; - return jt_opt_device(argc - 2, argv + 2); + exit(jt_opt_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); @@ -663,47 +724,78 @@ int jt_opt_threads(int argc, char **argv) if (!thread) { /* parent process */ int live_threads = threads; + sigemptyset(&sigset); + sigemptyset(&sigact.sa_mask); + sigact.sa_handler = parent_sighandler; + sigact.sa_flags = 0; + + sigaction(SIGALRM, &sigact, &saveact1); + sigaction(SIGCHLD, &sigact, &saveact2); + while (live_threads > 0) { int status; pid_t ret; - ret = waitpid(0, &status, verbose < 0 ? WNOHANG : 0); - if (ret == 0) { - if (verbose >= 0) - abort(); - - sleep(-verbose); - SHMEM_SNAP(threads); - continue; + if (verbose < 0) /* periodic stats */ + alarm(-verbose); + + sigsuspend(&sigset); + alarm(0); + + while (live_threads > 0) { + ret = waitpid(0, &status, WNOHANG); + if (ret == 0) + break; + + if (ret < 0) { + fprintf(stderr, "error: %s: wait - %s\n", + argv[0], strerror(errno)); + if (!rc) + rc = errno; + continue; + } 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 || WIFSIGNALED(status)) + fprintf(stderr, + "%s: PID %d had rc=%d\n", + argv[0], ret, err); + if (!rc) + rc = err; + + live_threads--; + } } - 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 || WIFSIGNALED(status)) - fprintf(stderr, - "%s: PID %d had rc=%d\n", - argv[0], ret, err); - if (!rc) - rc = err; - - live_threads--; + /* Show stats while all threads running */ + if (verbose < 0) { + shmem_snap(threads, live_threads); + if (report_count > 0 && --report_count == 0) + shmem_stop(); } } + sigaction(SIGCHLD, &saveact2, NULL); + sigaction(SIGALRM, &saveact1, NULL); } + sigprocmask(SIG_SETMASK, &saveset, NULL); + return rc; } +#else +int jt_opt_threads(int argc, char **argv) +{ + fprintf(stderr, "%s not-supported in a single-threaded runtime\n", + jt_cmdname(argv[0])); + return CMD_HELP; +} +#endif int jt_opt_net(int argc, char **argv) { @@ -727,14 +819,22 @@ int jt_opt_net(int argc, char **argv) int jt_obd_no_transno(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 1) return CMD_HELP; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_NO_TRANSNO, buf); if (rc < 0) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), @@ -746,14 +846,22 @@ int jt_obd_no_transno(int argc, char **argv) int jt_obd_set_readonly(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 1) return CMD_HELP; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SET_READONLY, buf); if (rc < 0) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), @@ -765,14 +873,22 @@ int jt_obd_set_readonly(int argc, char **argv) int jt_obd_abort_recovery(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 1) return CMD_HELP; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ABORT_RECOVERY, buf); if (rc < 0) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), @@ -784,16 +900,16 @@ int jt_obd_abort_recovery(int argc, char **argv) int jt_get_version(int argc, char **argv) { int rc; - char buf[8192]; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf; if (argc != 1) return CMD_HELP; - memset(buf, 0, sizeof(buf)); + memset(buf, 0, sizeof(rawbuf)); data->ioc_version = OBD_IOCTL_VERSION; - data->ioc_cookie = conn_cookie; - data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data)); + data->ioc_inllen1 = sizeof(rawbuf) - cfs_size_round(sizeof(*data)); + data->ioc_inlbuf1 = buf + cfs_size_round(sizeof(*data)); data->ioc_len = obd_ioctl_packlen(data); rc = l2_ioctl(OBD_DEV_ID, OBD_GET_VERSION, buf); @@ -808,195 +924,163 @@ int jt_get_version(int argc, char **argv) return rc; } -int jt_obd_list(int argc, char **argv) +/* + * Print an obd device line with the ost_conn_uuid inserted, if the obd + * is an osc. + */ +static void print_obd_line(char *s) { - int rc; - char buf[OBD_MAX_IOCTL_BUFFER]; - struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf; - - if (argc != 1) - return CMD_HELP; + char buf[MAX_STRING_SIZE]; + char obd_name[MAX_OBD_NAME]; + FILE *fp = NULL; + char *ptr; + + if (sscanf(s, " %*d %*s osc %s %*s %*d ", obd_name) == 0) + goto try_mdc; + snprintf(buf, sizeof(buf), + "/proc/fs/lustre/osc/%s/ost_conn_uuid", obd_name); + if ((fp = fopen(buf, "r")) == NULL) + goto try_mdc; + goto got_one; + +try_mdc: + if (sscanf(s, " %*d %*s mdc %s %*s %*d ", obd_name) == 0) + goto fail; + snprintf(buf, sizeof(buf), + "/proc/fs/lustre/mdc/%s/mds_conn_uuid", obd_name); + if ((fp = fopen(buf, "r")) == NULL) + goto fail; + +got_one: + /* should not ignore fgets(3)'s return value */ + if (!fgets(buf, sizeof(buf), fp)) { + fprintf(stderr, "reading from %s: %s", buf, strerror(errno)); + fclose(fp); + return; + } + fclose(fp); - memset(buf, 0, sizeof(buf)); - data->ioc_version = OBD_IOCTL_VERSION; - data->ioc_cookie = conn_cookie; - data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data)); - data->ioc_len = obd_ioctl_packlen(data); + /* trim trailing newlines */ + ptr = strrchr(buf, '\n'); + if (ptr) *ptr = '\0'; + ptr = strrchr(s, '\n'); + if (ptr) *ptr = '\0'; - rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_LIST, data); - if (rc < 0) - fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), - strerror(rc = errno)); - else { - printf("%s", data->ioc_bulk); - } + printf("%s %s\n", s, buf); + return; - return rc; +fail: + printf("%s", s); + return; } -/* Get echo client's stripe meta-data for the given object - */ -int jt_obd_get_stripe (int argc, char **argv) +/* get device list by ioctl */ +int jt_obd_list_ioctl(int argc, char **argv) { - struct obd_ioctl_data data; - __u64 id; - int rc; - char *end; + int rc, index; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf; - if (argc != 2) - return (CMD_HELP); + if (argc > 2) + return CMD_HELP; + /* Just ignore a -t option. Only supported with /proc. */ + else if (argc == 2 && strcmp(argv[1], "-t") != 0) + return CMD_HELP; - id = strtoull (argv[1], &end, 0); - if (*end) { - fprintf (stderr, "Error: %s: invalid object id '%s'\n", - jt_cmdname (argv[0]), argv[1]); - return (CMD_HELP); + for (index = 0;; index++) { + memset(buf, 0, sizeof(rawbuf)); + data->ioc_version = OBD_IOCTL_VERSION; + data->ioc_inllen1 = + sizeof(rawbuf) - cfs_size_round(sizeof(*data)); + data->ioc_inlbuf1 = buf + cfs_size_round(sizeof(*data)); + data->ioc_len = obd_ioctl_packlen(data); + data->ioc_count = index; + + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETDEVICE, buf); + if (rc != 0) + break; + printf("%s\n", (char *)data->ioc_bulk); } + if (rc != 0) { + if (errno == ENOENT) + /* no device or the last device */ + rc = 0; + else + fprintf(stderr, "Error getting device list: %s: " + "check dmesg.\n", strerror(errno)); + } + return rc; +} - memset (&lsm_buffer, 0, sizeof (lsm_buffer)); - - IOC_INIT (data); - data.ioc_obdo1.o_id = id; - data.ioc_obdo1.o_mode = S_IFREG | 0644; - data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE; - data.ioc_pbuf1 = (char *)&lsm_buffer; - data.ioc_plen1 = sizeof (lsm_buffer); +int jt_obd_list(int argc, char **argv) +{ + int rc; + char buf[MAX_STRING_SIZE]; + FILE *fp = NULL; + int print_obd = 0; - IOC_PACK(argv[0], data); - rc = l2_ioctl(OBD_DEV_ID, ECHO_IOC_GET_STRIPE, buf); - IOC_UNPACK(argv[0], data); + if (argc > 2) + return CMD_HELP; + else if (argc == 2) { + if (strcmp(argv[1], "-t") == 0) + print_obd = 1; + else + return CMD_HELP; + } - if (rc != 0) { - fprintf (stderr, "Error: %s: rc %d(%s)\n", - jt_cmdname (argv[0]), rc, strerror (errno)); - return (rc); + fp = fopen(DEVICES_LIST, "r"); + if (fp == NULL) { + fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n", + jt_cmdname(argv[0]), strerror(rc = errno)); + return jt_obd_list_ioctl(argc, argv); } - printf ("%s\n", lsm_string (&lsm_buffer.lsm)); + while (fgets(buf, sizeof(buf), fp) != NULL) + if (print_obd) + print_obd_line(buf); + else + printf("%s", buf); - return (rc); + fclose(fp); + return 0; } -/* Set stripe meta-data for 1 or more objects. Object must be new to - * this echo client instance. +/* Create one or more objects, arg[4] may describe stripe meta-data. If + * not, defaults assumed. This echo-client instance stashes the stripe + * object ids. Use get_stripe on this node to print full lsm and + * set_stripe on another node to cut/paste between nodes. */ -int jt_obd_set_stripe (int argc, char **argv) +/* create [] [q|v|# verbosity] [striping] */ +int jt_obd_create(int argc, char **argv) { + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; struct obd_ioctl_data data; + struct timeval next_time; + __u64 count = 1, next_count, base_id = 0; + int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0; char *end; - int count = 1; - int i; - int rc; - if (argc < 2 || argc > 3) + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; + if (argc < 2 || argc > 5) return CMD_HELP; - rc = parse_lsm (&lsm_buffer, argv[1]); - if (rc != 0) { - fprintf (stderr, "error: %s: invalid object '%s'\n", - jt_cmdname (argv[0]), argv[1]); + count = strtoull(argv[1], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: invalid iteration count '%s'\n", + jt_cmdname(argv[0]), argv[1]); return CMD_HELP; } if (argc > 2) { - count = strtol (argv[2], &end, 0); - if (*end != 0) { - fprintf (stderr, "error: %s: invalid count '%s'\n", - jt_cmdname (argv[0]), argv[1]); + mode = strtoul(argv[2], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: invalid mode '%s'\n", + jt_cmdname(argv[0]), argv[2]); return CMD_HELP; } - } - - for (i = 0; i < count; i++) { - IOC_INIT (data); - data.ioc_obdo1.o_id = lsm_buffer.lsm.lsm_object_id + i; - data.ioc_obdo1.o_mode = S_IFREG | 0644; - data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE; - data.ioc_pbuf1 = (char *)&lsm_buffer; - data.ioc_plen1 = sizeof (lsm_buffer); - - IOC_PACK (argv[0], data); - rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf); - IOC_UNPACK (argv[0], data); - - if (rc != 0) { - fprintf (stderr, "Error: %s: rc %d(%s)\n", - jt_cmdname (argv[0]), rc, strerror (errno)); - return (rc); - } - } - - return (0); -} - -/* Clear stripe meta-data info for an object on this echo-client instance - */ -int jt_obd_unset_stripe (int argc, char **argv) -{ - struct obd_ioctl_data data; - char *end; - obd_id id; - int rc; - - if (argc != 2) - return CMD_HELP; - - id = strtoull (argv[1], &end, 0); - if (*end != 0) { - fprintf (stderr, "error: %s: invalid object id '%s'\n", - jt_cmdname (argv[0]), argv[1]); - return CMD_HELP; - } - - IOC_INIT (data); - data.ioc_obdo1.o_id = id; - data.ioc_obdo1.o_mode = S_IFREG | 0644; - data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE; - - IOC_PACK (argv[0], data); - rc = l2_ioctl (OBD_DEV_ID, ECHO_IOC_SET_STRIPE, buf); - IOC_UNPACK (argv[0], data); - - if (rc != 0) - fprintf (stderr, "Error: %s: rc %d(%s)\n", - jt_cmdname (argv[0]), rc, strerror (errno)); - - return (0); -} - -/* Create one or more objects, arg[4] may describe stripe meta-data. If - * not, defaults assumed. This echo-client instance stashes the stripe - * object ids. Use get_stripe on this node to print full lsm and - * set_stripe on another node to cut/paste between nodes. - */ -int jt_obd_create(int argc, char **argv) -{ - struct obd_ioctl_data data; - struct timeval next_time; - __u64 count = 1, next_count, base_id = 0; - int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0; - char *end; - - IOC_INIT(data); - if (argc < 2 || argc > 5) - return CMD_HELP; - - count = strtoull(argv[1], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: invalid iteration count '%s'\n", - jt_cmdname(argv[0]), argv[1]); - return CMD_HELP; - } - - if (argc > 2) { - mode = strtoul(argv[2], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: invalid mode '%s'\n", - jt_cmdname(argv[0]), argv[2]); - return CMD_HELP; - } - if (!(mode & S_IFMT)) - mode |= S_IFREG; + if (!(mode & S_IFMT)) + mode |= S_IFREG; } if (argc > 3) { @@ -1022,7 +1106,7 @@ int jt_obd_create(int argc, char **argv) gettimeofday(&next_time, NULL); next_time.tv_sec -= verbose; - for (i = 1, next_count = verbose; i <= count; i++) { + for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) { data.ioc_obdo1.o_mode = mode; data.ioc_obdo1.o_id = base_id; data.ioc_obdo1.o_uid = 0; @@ -1035,17 +1119,23 @@ int jt_obd_create(int argc, char **argv) data.ioc_pbuf1 = (char *)&lsm_buffer; } - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CREATE, buf); - IOC_UNPACK(argv[0], data); - SHMEM_BUMP(); + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + shmem_bump(); if (rc < 0) { fprintf(stderr, "error: %s: #%d - %s\n", jt_cmdname(argv[0]), i, strerror(rc = errno)); break; } if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) { - fprintf(stderr, "error: %s: objid not valid #%d:%08x\n", + fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n", jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid); rc = EINVAL; break; @@ -1061,10 +1151,12 @@ int jt_obd_create(int argc, char **argv) int jt_obd_setattr(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; char *end; int rc; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 2) return CMD_HELP; @@ -1082,7 +1174,13 @@ int jt_obd_setattr(int argc, char **argv) } data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, buf); if (rc < 0) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), @@ -1091,22 +1189,116 @@ int jt_obd_setattr(int argc, char **argv) return rc; } +int jt_obd_test_setattr(int argc, char **argv) +{ + struct obd_ioctl_data data; + struct timeval start, next_time; + __u64 i, count, next_count; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int verbose = 1; + obd_id objid = 3; + char *end; + int rc = 0; + + if (argc < 2 || argc > 4) + return CMD_HELP; + + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; + count = strtoull(argv[1], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: invalid iteration count '%s'\n", + jt_cmdname(argv[0]), argv[1]); + return CMD_HELP; + } + + if (argc >= 3) { + verbose = get_verbose(argv[0], argv[2]); + if (verbose == BAD_VERBOSE) + return CMD_HELP; + } + + if (argc >= 4) { + if (argv[3][0] == 't') { + objid = strtoull(argv[3] + 1, &end, 0); + if (thread) + objid += thread - 1; + } else + objid = strtoull(argv[3], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: invalid objid '%s'\n", + jt_cmdname(argv[0]), argv[3]); + return CMD_HELP; + } + } + + gettimeofday(&start, NULL); + next_time.tv_sec = start.tv_sec - verbose; + next_time.tv_usec = start.tv_usec; + if (verbose != 0) + printf("%s: setting "LPD64" attrs (objid "LPX64"): %s", + jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec)); + + for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) { + data.ioc_obdo1.o_id = objid; + data.ioc_obdo1.o_mode = S_IFREG; + data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE; + memset(buf, 0x00, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data); + shmem_bump(); + if (rc < 0) { + fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n", + jt_cmdname(argv[0]), i, errno, strerror(rc = errno)); + break; + } else { + if (be_verbose + (verbose, &next_time, i, &next_count, count)) + printf("%s: set attr #"LPD64"\n", + jt_cmdname(argv[0]), i); + } + } + + if (!rc) { + struct timeval end; + double diff; + + gettimeofday(&end, NULL); + + diff = difftime(&end, &start); + + --i; + if (verbose != 0) + printf("%s: "LPD64" attrs in %.3fs (%.3f attr/s): %s", + jt_cmdname(argv[0]), i, diff, i / diff, + ctime(&end.tv_sec)); + } + return rc; +} + int jt_obd_destroy(int argc, char **argv) { struct obd_ioctl_data data; struct timeval next_time; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; __u64 count = 1, next_count; int verbose = 1; __u64 id; char *end; int rc = 0, i; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc < 2 || argc > 4) return CMD_HELP; id = strtoull(argv[1], &end, 0); - if (*end) { + if (*end || id == 0 || errno != 0) { fprintf(stderr, "error: %s: invalid objid '%s'\n", jt_cmdname(argv[0]), argv[1]); return CMD_HELP; @@ -1131,15 +1323,21 @@ int jt_obd_destroy(int argc, char **argv) gettimeofday(&next_time, NULL); next_time.tv_sec -= verbose; - for (i = 1, next_count = verbose; i <= count; i++, id++) { + for (i = 1, next_count = verbose; i <= count && shmem_running(); i++, id++) { data.ioc_obdo1.o_id = id; data.ioc_obdo1.o_mode = S_IFREG | 0644; data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_DESTROY, buf); - IOC_UNPACK(argv[0], data); - SHMEM_BUMP(); + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + shmem_bump(); if (rc < 0) { fprintf(stderr, "error: %s: objid "LPX64": %s\n", jt_cmdname(argv[0]), id, strerror(rc = errno)); @@ -1157,13 +1355,15 @@ int jt_obd_destroy(int argc, char **argv) int jt_obd_getattr(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; char *end; int rc; if (argc != 2) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0); if (*end) { fprintf(stderr, "error: %s: invalid objid '%s'\n", @@ -1175,9 +1375,15 @@ int jt_obd_getattr(int argc, char **argv) data.ioc_obdo1.o_valid = 0xffffffff; printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]),data.ioc_obdo1.o_id); - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, buf); - IOC_UNPACK(argv[0], data); + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); if (rc) { fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); @@ -1192,16 +1398,18 @@ int jt_obd_test_getattr(int argc, char **argv) { struct obd_ioctl_data data; struct timeval start, next_time; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; __u64 i, count, next_count; int verbose = 1; obd_id objid = 3; char *end; int rc = 0; - if (argc < 2 && argc > 4) + if (argc < 2 || argc > 4) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; count = strtoull(argv[1], &end, 0); if (*end) { fprintf(stderr, "error: %s: invalid iteration count '%s'\n", @@ -1236,13 +1444,19 @@ int jt_obd_test_getattr(int argc, char **argv) printf("%s: getting "LPD64" attrs (objid "LPX64"): %s", jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec)); - for (i = 1, next_count = verbose; i <= count; i++) { + for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) { data.ioc_obdo1.o_id = objid; data.ioc_obdo1.o_mode = S_IFREG; data.ioc_obdo1.o_valid = 0xffffffff; - IOC_PACK(argv[0], data); + memset(buf, 0x00, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data); - SHMEM_BUMP(); + shmem_bump(); if (rc < 0) { fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n", jt_cmdname(argv[0]), i, errno, strerror(rc = errno)); @@ -1272,12 +1486,26 @@ int jt_obd_test_getattr(int argc, char **argv) return rc; } +/* test_brw count + mode + verbosity + blocksize + <[[]t(inc obj by thread#)]obj> object + [p|g] batch */ int jt_obd_test_brw(int argc, char **argv) { struct obd_ioctl_data data; struct timeval start, next_time; - __u64 count, next_count, len, thr_offset = 0, objid = 3; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + __u64 count, next_count, len, stride, thr_offset = 0, objid = 3; int write = 0, verbose = 1, cmd, i, rc = 0, pages = 1; + int offset_pages = 0; + long n; + int repeat_offset = 0; + unsigned long long ull; + int nthr_per_obj = 0; + int verify = 1; + int obj_idx = 0; char *end; if (argc < 2 || argc > 7) { @@ -1286,14 +1514,7 @@ int jt_obd_test_brw(int argc, char **argv) return CMD_HELP; } - /* make each thread write to a different offset */ - if (argv[1][0] == 't') { - count = strtoull(argv[1] + 1, &end, 0); - if (thread) - thr_offset = thread - 1; - } else - count = strtoull(argv[1], &end, 0); - + count = strtoull(argv[1], &end, 0); if (*end) { fprintf(stderr, "error: %s: bad iteration count '%s'\n", jt_cmdname(argv[0]), argv[1]); @@ -1303,8 +1524,24 @@ int jt_obd_test_brw(int argc, char **argv) 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; + /* else it's a read */ + + if (argv[2][0] != 0) + for (i = 1; argv[2][i] != 0; i++) + switch (argv[2][i]) { + case 'r': + repeat_offset = 1; + break; + + case 'x': + verify = 0; + break; + + default: + fprintf (stderr, "Can't parse cmd '%s'\n", + argv[2]); + return CMD_HELP; + } } if (argc >= 4) { @@ -1315,19 +1552,34 @@ int jt_obd_test_brw(int argc, char **argv) if (argc >= 5) { pages = strtoul(argv[4], &end, 0); - if (*end) { - fprintf(stderr, "error: %s: bad page count '%s'\n", + + if (*end == '+') + offset_pages = strtoul(end + 1, &end, 0); + + if (*end != 0 || + offset_pages < 0 || offset_pages >= pages) { + fprintf(stderr, "error: %s: bad npages[+offset] parameter '%s'\n", jt_cmdname(argv[0]), argv[4]); return CMD_HELP; } } + if (argc >= 6) { - if (argv[5][0] == 't') { + if (thread && + (n = strtol(argv[5], &end, 0)) > 0 && + *end == 't' && + (ull = strtoull(end + 1, &end, 0)) > 0 && + *end == 0) { + nthr_per_obj = n; + objid = ull; + } else if (thread && + argv[5][0] == 't') { + nthr_per_obj = 1; objid = strtoull(argv[5] + 1, &end, 0); - if (thread) - objid += thread - 1; - } else + } else { + nthr_per_obj = 0; objid = strtoull(argv[5], &end, 0); + } if (*end) { fprintf(stderr, "error: %s: bad objid '%s'\n", jt_cmdname(argv[0]), argv[5]); @@ -1335,7 +1587,8 @@ int jt_obd_test_brw(int argc, char **argv) } } - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; /* communicate the 'type' of brw test and batching to echo_client. * don't start. we'd love to refactor this lctl->echo_client @@ -1367,16 +1620,46 @@ int jt_obd_test_brw(int argc, char **argv) jt_cmdname(argv[0]), argv[6]); return CMD_HELP; } - data.ioc_plen1 *= PAGE_SIZE; + data.ioc_plen1 *= getpagesize(); } - len = pages * PAGE_SIZE; + len = pages * getpagesize(); + thr_offset = offset_pages * getpagesize(); + stride = len; + +#ifdef MAX_THREADS + if (thread) { + shmem_lock (); + if (nthr_per_obj != 0) { + /* threads interleave */ + obj_idx = (thread - 1)/nthr_per_obj; + objid += obj_idx; + stride *= nthr_per_obj; + if ((thread - 1) % nthr_per_obj == 0) + shared_data->offsets[obj_idx] = stride + thr_offset; + thr_offset += ((thread - 1) % nthr_per_obj) * len; + } else { + /* threads disjoint */ + thr_offset += (thread - 1) * len; + } + + shared_data->barrier--; + if (shared_data->barrier == 0) + l_cond_broadcast(&shared_data->cond); + else + l_cond_wait(&shared_data->cond, + &shared_data->mutex); + + shmem_unlock (); + } +#endif data.ioc_obdo1.o_id = objid; data.ioc_obdo1.o_mode = S_IFREG; - data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE; + data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS; + data.ioc_obdo1.o_flags = (verify ? OBD_FL_DEBUG_CHECK : 0); data.ioc_count = len; - data.ioc_offset = thr_offset * len * count; + data.ioc_offset = (repeat_offset ? 0 : thr_offset); gettimeofday(&start, NULL); next_time.tv_sec = start.tv_sec - verbose; @@ -1388,21 +1671,46 @@ int jt_obd_test_brw(int argc, char **argv) pages, objid, data.ioc_offset, ctime(&start.tv_sec)); cmd = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ; - for (i = 1, next_count = verbose; i <= count; i++) { + for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) { data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT); - IOC_PACK(argv[0], data); + memset(buf, 0x00, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, cmd, buf); - SHMEM_BUMP(); + shmem_bump(); if (rc) { fprintf(stderr, "error: %s: #%d - %s on %s\n", jt_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 %dx%d\n", jt_cmdname(argv[0]), - write ? "write" : "read", i, pages); + } else if (be_verbose(verbose, &next_time,i, &next_count,count)) { + shmem_lock (); + printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n", + jt_cmdname(argv[0]), write ? "write" : "read", i, + data.ioc_obdo1.o_id, data.ioc_offset, + (int)(pages * getpagesize())); + shmem_unlock (); + } - data.ioc_offset += len; + if (!repeat_offset) { +#ifdef MAX_THREADS + if (stride == len) { + data.ioc_offset += stride; + } else if (i < count) { + shmem_lock (); + data.ioc_offset = shared_data->offsets[obj_idx]; + shared_data->offsets[obj_idx] += len; + shmem_unlock (); + } +#else + data.ioc_offset += len; + obj_idx = 0; /* avoids an unused var warning */ +#endif + } } if (!rc) { @@ -1431,10 +1739,13 @@ int jt_obd_lov_getconfig(int argc, char **argv) struct obd_ioctl_data data; struct lov_desc desc; struct obd_uuid *uuidarray; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + __u32 *obdgens; char *path; int rc, fd; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 2) return CMD_HELP; @@ -1444,13 +1755,13 @@ int jt_obd_lov_getconfig(int argc, char **argv) if (fd < 0) { fprintf(stderr, "open \"%s\" failed: %s\n", path, strerror(errno)); - return -1; + return -errno; } memset(&desc, 0, sizeof(desc)); obd_str2uuid(&desc.ld_uuid, argv[1]); desc.ld_tgt_count = ((OBD_MAX_IOCTL_BUFFER-sizeof(data)-sizeof(desc)) / - sizeof(*uuidarray)); + (sizeof(*uuidarray) + sizeof(*obdgens))); repeat: uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray)); @@ -1460,94 +1771,83 @@ repeat: rc = -ENOMEM; goto out; } + obdgens = calloc(desc.ld_tgt_count, sizeof(*obdgens)); + if (!obdgens) { + fprintf(stderr, "error: %s: no memory for %d generation #'s\n", + jt_cmdname(argv[0]), desc.ld_tgt_count); + rc = -ENOMEM; + goto out_uuidarray; + } + memset(buf, 0x00, sizeof(rawbuf)); data.ioc_inllen1 = sizeof(desc); data.ioc_inlbuf1 = (char *)&desc; data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray); data.ioc_inlbuf2 = (char *)uuidarray; + data.ioc_inllen3 = desc.ld_tgt_count * sizeof(*obdgens); + data.ioc_inlbuf3 = (char *)obdgens; - if (obd_ioctl_pack(&data, &buf, max)) { + if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) { fprintf(stderr, "error: %s: invalid ioctl\n", jt_cmdname(argv[0])); rc = -EINVAL; - goto out; + goto out_obdgens; } rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf); if (rc == -ENOSPC) { free(uuidarray); + free(obdgens); goto repeat; } else if (rc) { fprintf(stderr, "error: %s: ioctl error: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); } else { - struct obd_uuid *ptr; + struct obd_uuid *uuidp; + __u32 *genp; int i; - if (obd_ioctl_unpack(&data, buf, max)) { + if (obd_ioctl_unpack(&data, buf, sizeof(rawbuf))) { fprintf(stderr, "error: %s: invalid reply\n", jt_cmdname(argv[0])); rc = -EINVAL; goto out; } - printf("default_stripe_count: %u\n", - desc.ld_default_stripe_count); + if (desc.ld_default_stripe_count == (__u32)-1) + printf("default_stripe_count: %d\n", -1); + else + printf("default_stripe_count: %u\n", + desc.ld_default_stripe_count); printf("default_stripe_size: "LPU64"\n", desc.ld_default_stripe_size); printf("default_stripe_offset: "LPU64"\n", desc.ld_default_stripe_offset); printf("default_stripe_pattern: %u\n", desc.ld_pattern); printf("obd_count: %u\n", desc.ld_tgt_count); - for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++) - printf("%u: %s\n", i, (char *)ptr); - } -out: + printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n"); + uuidp = uuidarray; + genp = obdgens; + for (i = 0; i < desc.ld_tgt_count; i++, uuidp++, genp++) + printf("\t%6u\t%14u\t\t %s\n", i, *genp, (char *)uuidp); + } +out_obdgens: + free(obdgens); +out_uuidarray: free(uuidarray); +out: close(fd); return rc; } -int jt_obd_test_ldlm(int argc, char **argv) -{ - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - if (argc != 1) - return CMD_HELP; - - IOC_PACK(argv[0], data); - rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_TEST, buf); - if (rc) - fprintf(stderr, "error: %s: test failed: %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); - return rc; -} - -int jt_obd_dump_ldlm(int argc, char **argv) -{ - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - if (argc != 1) - return CMD_HELP; - - IOC_PACK(argv[0], data); - rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_DUMP, buf); - if (rc) - fprintf(stderr, "error: %s failed: %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); - return rc; -} - int jt_obd_ldlm_regress_start(int argc, char **argv) { int rc; struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; char argstring[200]; int i, count = sizeof(argstring) - 1; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc > 5) return CMD_HELP; @@ -1564,7 +1864,13 @@ int jt_obd_ldlm_regress_start(int argc, char **argv) data.ioc_inllen1 = strlen(argstring) + 1; } - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_START, buf); if (rc) fprintf(stderr, "error: %s: test failed: %s\n", @@ -1576,13 +1882,22 @@ int jt_obd_ldlm_regress_start(int argc, char **argv) int jt_obd_ldlm_regress_stop(int argc, char **argv) { int rc; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; struct obd_ioctl_data data; - IOC_INIT(data); + + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 1) return CMD_HELP; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, IOC_LDLM_REGRESS_STOP, buf); if (rc) @@ -1594,16 +1909,24 @@ int jt_obd_ldlm_regress_stop(int argc, char **argv) static int do_activate(int argc, char **argv, int flag) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc != 1) return CMD_HELP; /* reuse offset for 'active' */ data.ioc_offset = flag; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, IOC_OSC_SET_ACTIVE, buf); if (rc) fprintf(stderr, "error: %s: failed: %s\n", @@ -1625,9 +1948,11 @@ int jt_obd_activate(int argc, char **argv) int jt_obd_recover(int argc, char **argv) { int rc; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; struct obd_ioctl_data data; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; if (argc > 2) return CMD_HELP; @@ -1636,7 +1961,13 @@ int jt_obd_recover(int argc, char **argv) data.ioc_inlbuf1 = argv[1]; } - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLIENT_RECOVER, buf); if (rc < 0) { fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), @@ -1649,6 +1980,7 @@ int jt_obd_recover(int argc, char **argv) int jt_obd_mdc_lookup(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; char *parent, *child; int rc, fd, verbose = 1; @@ -1660,12 +1992,19 @@ int jt_obd_mdc_lookup(int argc, char **argv) if (argc == 4) verbose = get_verbose(argv[0], argv[3]); - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(child) + 1; data.ioc_inlbuf1 = child; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } fd = open(parent, O_RDONLY); if (fd < 0) { @@ -1682,7 +2021,12 @@ int jt_obd_mdc_lookup(int argc, char **argv) close(fd); if (verbose) { - IOC_UNPACK(argv[0], data); + rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid reply\n", + jt_cmdname(argv[0])); + return rc; + } printf("%s: mode %o uid %d gid %d\n", child, data.ioc_obdo1.o_mode, data.ioc_obdo1.o_uid, data.ioc_obdo1.o_gid); @@ -1691,103 +2035,27 @@ int jt_obd_mdc_lookup(int argc, char **argv) return rc; } - -int jt_obd_close_uuid(int argc, char **argv) +int jt_cfg_dump_log(int argc, char **argv) { - int rc, nal; struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int rc; - if (argc != 3) { - fprintf(stderr, "usage: %s \n", argv[0]); - return 0; - } + if (argc != 2) + return CMD_HELP; - nal = ptl_name2nal(argv[2]); - - if (nal <= 0) { - fprintf (stderr, "Can't parse NAL %s\n", argv[2]); - return -1; - } - - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; - data.ioc_nal = nal; - IOC_PACK(argv[0], data); - rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CLOSE_UUID, buf); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); if (rc) { - fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n", - strerror(errno)); - return -1; - } - return 0; -} - - -int jt_cfg_record(int argc, char **argv) -{ - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - - if (argc != 2) - return CMD_HELP; - - data.ioc_inllen1 = strlen(argv[1]) + 1; - data.ioc_inlbuf1 = argv[1]; - - IOC_PACK(argv[0], data); - rc = l_ioctl(OBD_DEV_ID, OBD_IOC_RECORD, buf); - if (rc == 0) { - jt_recording = 1; - ptl_set_cfg_record_cb(obd_record); - } else { - fprintf(stderr, "OBD_IOC_RECORD failed: %s\n", - strerror(errno)); + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; } - - return rc; -} - -int jt_cfg_parse(int argc, char **argv) -{ - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - - if (argc != 2) - return CMD_HELP; - - data.ioc_inllen1 = strlen(argv[1]) + 1; - data.ioc_inlbuf1 = argv[1]; - - IOC_PACK(argv[0], data); - rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PARSE, buf); - if (rc < 0) - fprintf(stderr, "OBD_IOC_PARSE failed: %s\n", - strerror(errno)); - - return rc; -} - - -int jt_cfg_dump_log(int argc, char **argv) -{ - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - - if (argc != 2) - return CMD_HELP; - - data.ioc_inllen1 = strlen(argv[1]) + 1; - data.ioc_inlbuf1 = argv[1]; - - IOC_PACK(argv[0], data); rc = l_ioctl(OBD_DEV_ID, OBD_IOC_DUMP_LOG, buf); if (rc < 0) fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n", @@ -1796,70 +2064,57 @@ int jt_cfg_dump_log(int argc, char **argv) return rc; } - -int jt_cfg_endrecord(int argc, char **argv) -{ - struct obd_ioctl_data data; - int rc; - - IOC_INIT(data); - - if (argc != 1) - return CMD_HELP; - - if (!jt_recording) { - fprintf(stderr, "Not recording, so endrecord doesn't make sense.\n"); - return 0; - } - - IOC_PACK(argv[0], data); - rc = l_ioctl(OBD_DEV_ID, OBD_IOC_ENDRECORD, buf); - if (rc == 0) { - jt_recording = 0; - ptl_set_cfg_record_cb(NULL); - } else { - fprintf(stderr, "OBD_IOC_ENDRECORD failed: %s\n", - strerror(errno)); - } - return rc; -} - int jt_llog_catlist(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; if (argc != 1) return CMD_HELP; - IOC_INIT(data); - data.ioc_inllen1 = max - size_round(sizeof(data)); - IOC_PACK(argv[0], data); - + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; + data.ioc_inllen1 = sizeof(rawbuf) - cfs_size_round(sizeof(data)); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_CATLOGLIST, buf); - if (rc == 0) + if (rc == 0) fprintf(stdout, "%s", ((struct obd_ioctl_data*)buf)->ioc_bulk); else - fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n", + fprintf(stderr, "OBD_IOC_CATLOGLIST failed: %s\n", strerror(errno)); - + return rc; } int jt_llog_info(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; if (argc != 2) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; - data.ioc_inllen2 = max - size_round(sizeof(data)) - - size_round(data.ioc_inllen1); - IOC_PACK(argv[0], data); + data.ioc_inllen2 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) - + cfs_size_round(data.ioc_inllen1); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_INFO, buf); if (rc == 0) @@ -1874,12 +2129,14 @@ int jt_llog_info(int argc, char **argv) int jt_llog_print(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; if (argc != 2 && argc != 4) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; if (argc == 4) { @@ -1894,11 +2151,17 @@ int jt_llog_print(int argc, char **argv) data.ioc_inllen3 = strlen(to) + 1; data.ioc_inlbuf3 = to; } - data.ioc_inllen4 = max - size_round(sizeof(data)) - - size_round(data.ioc_inllen1) - - size_round(data.ioc_inllen2) - - size_round(data.ioc_inllen3); - IOC_PACK(argv[0], data); + data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) - + cfs_size_round(data.ioc_inllen1) - + cfs_size_round(data.ioc_inllen2) - + cfs_size_round(data.ioc_inllen3); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_PRINT, buf); if (rc == 0) @@ -1913,19 +2176,27 @@ int jt_llog_print(int argc, char **argv) int jt_llog_cancel(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; if (argc != 4) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; data.ioc_inllen2 = strlen(argv[2]) + 1; data.ioc_inlbuf2 = argv[2]; data.ioc_inllen3 = strlen(argv[3]) + 1; data.ioc_inlbuf3 = argv[3]; - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf); if (rc == 0) @@ -1940,12 +2211,14 @@ int jt_llog_cancel(int argc, char **argv) int jt_llog_check(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; if (argc != 2 && argc != 4) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; data.ioc_inllen1 = strlen(argv[1]) + 1; data.ioc_inlbuf1 = argv[1]; if (argc == 4) { @@ -1960,11 +2233,17 @@ int jt_llog_check(int argc, char **argv) data.ioc_inllen3 = strlen(to) + 1; data.ioc_inlbuf3 = to; } - data.ioc_inllen4 = max - size_round(sizeof(data)) - - size_round(data.ioc_inllen1) - - size_round(data.ioc_inllen2) - - size_round(data.ioc_inllen3); - IOC_PACK(argv[0], data); + data.ioc_inllen4 = sizeof(rawbuf) - cfs_size_round(sizeof(data)) - + cfs_size_round(data.ioc_inllen1) - + cfs_size_round(data.ioc_inllen2) - + cfs_size_round(data.ioc_inllen3); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CHECK, buf); if (rc == 0) @@ -1978,26 +2257,34 @@ int jt_llog_check(int argc, char **argv) int jt_llog_remove(int argc, char **argv) { struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int rc; if (argc != 3 && argc != 2) return CMD_HELP; - IOC_INIT(data); + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; 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]; } - IOC_PACK(argv[0], data); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_REMOVE, buf); if (rc == 0) { if (argc == 3) fprintf(stdout, "log %s are removed.\n", argv[2]); else - fprintf(stdout, "the log in catlog %s are removed. \n", argv[1]); + fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]); } else fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n", strerror(errno)); @@ -2005,6 +2292,205 @@ int jt_llog_remove(int argc, char **argv) return rc; } +/* attach a regular file to virtual block device. + * return vaule: + * -1: fatal error + * 1: error, it always means the command run failed + * 0: success + */ +static int jt_blockdev_run_process(const char *file, char *argv[]) +{ + pid_t pid; + int rc; + + pid = vfork(); + if (pid == 0) { /* child process */ + /* don't print error messages */ + close(1), close(2); + (void)execvp(file, argv); + exit(-1); + } else if (pid > 0) { + int status; + + rc = waitpid(pid, &status, 0); + if (rc < 0 || !WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); + } + + return -1; +} + +static int jt_blockdev_find_module(const char *module) +{ + FILE *fp; + int found = 0; + char buf[1024]; + + fp = fopen("/proc/modules", "r"); + if (fp == NULL) + return -1; + + while (fgets(buf, 1024, fp) != NULL) { + *strchr(buf, ' ') = 0; + if (strcmp(module, buf) == 0) { + found = 1; + break; + } + } + fclose(fp); + + return found; +} + +static int jt_blockdev_probe_module(const char *module) +{ + char buf[1024]; + char *argv[10]; + int c, rc; + + if (jt_blockdev_find_module(module) == 1) + return 0; + + /* run modprobe first */ + c = 0; + argv[c++] = "/sbin/modprobe"; + argv[c++] = "-q"; + argv[c++] = (char *)module; + argv[c++] = NULL; + rc = jt_blockdev_run_process("modprobe", argv); + if (rc != 1) + return rc; + + /* cannot find the module in default directory ... */ + sprintf(buf, "../llite/%s.ko", module); + c = 0; + argv[c++] = "/sbin/insmod"; + argv[c++] = buf; + argv[c++] = NULL; + rc = jt_blockdev_run_process("insmod", argv); + return rc ? -1 : 0; +} + +int jt_blockdev_attach(int argc, char **argv) +{ + int rc, fd; + struct stat st; + char *filename, *devname; + unsigned long dev; + + if (argc != 3) + return CMD_HELP; + + if (jt_blockdev_probe_module("llite_lloop") < 0) { + fprintf(stderr, "error: cannot find module llite_lloop.(k)o\n"); + return ENOENT; + } + + filename = argv[1]; + devname = argv[2]; + + fd = open(filename, O_RDWR); + if (fd < 0) { + fprintf(stderr, "file %s can't be opened(%s)\n\n", + filename, strerror(errno)); + return CMD_HELP; + } + + rc = ioctl(fd, LL_IOC_LLOOP_ATTACH, &dev); + if (rc < 0) { + rc = errno; + fprintf(stderr, "attach error(%s)\n", strerror(rc)); + goto out; + } + + rc = stat(devname, &st); + if (rc == 0 && (!S_ISBLK(st.st_mode) || st.st_rdev != dev)) { + rc = EEXIST; + } else if (rc < 0) { + if (errno == ENOENT && + !mknod(devname, S_IFBLK|S_IRUSR|S_IWUSR, dev)) + rc = 0; + else + rc = errno; + } + + if (rc) { + fprintf(stderr, "error: the file %s could be attached to block " + "device %X but creating %s failed: %s\n" + "now detaching the block device..", + filename, (int)dev, devname, strerror(rc)); + + (void)ioctl(fd, LL_IOC_LLOOP_DETACH_BYDEV, dev); + fprintf(stderr, "%s\n", strerror(errno)); + } +out: + close(fd); + return -rc; +} + +int jt_blockdev_detach(int argc, char **argv) +{ + char *filename; + int rc, fd; + + if (argc != 2) + return CMD_HELP; + + filename = argv[1]; + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "cannot open file %s error %s\n", + filename, strerror(errno)); + return CMD_HELP; + } + + rc = ioctl(fd, LL_IOC_LLOOP_DETACH, 0); + if (rc < 0) { + rc = errno; + fprintf(stderr, "detach error(%s)\n", strerror(rc)); + } else { + (void)unlink(filename); + } + + close(fd); + return -rc; +} + +int jt_blockdev_info(int argc, char **argv) +{ + char *filename; + int rc, fd; + __u64 ino; + + if (argc != 2) + return CMD_HELP; + + filename = argv[1]; + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "cannot open file %s error: %s\n", + filename, strerror(errno)); + return CMD_HELP; + } + + rc = ioctl(fd, LL_IOC_LLOOP_INFO, &ino); + if (rc < 0) { + rc = errno; + fprintf(stderr, "error: %s\n", strerror(errno)); + goto out; + } + fprintf(stdout, "lloop device info: "); + if (ino == 0ULL) + fprintf(stdout, "Not attached\n"); + else + fprintf(stdout, "attached to inode "LPU64"\n", ino); +out: + close(fd); + return -rc; +} + static void signal_server(int sig) { if (sig == SIGINT) { @@ -2016,13 +2502,18 @@ static void signal_server(int sig) int obd_initialize(int argc, char **argv) { - SHMEM_SETUP(); - register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH); + int i; + + for (i = 0; i < MAX_STRIPES; i++) + lsm_buffer.lsm.lsm_oinfo[i] = lov_oinfos + i; + + shmem_setup(); + register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH, + OBD_DEV_MAJOR, OBD_DEV_MINOR); return 0; } - void obd_finalize(int argc, char **argv) { struct sigaction sigact; @@ -2032,10 +2523,709 @@ void obd_finalize(int argc, char **argv) sigact.sa_flags = SA_RESTART; sigaction(SIGINT, &sigact, NULL); - if (jt_recording) { - printf("END RECORD\n"); - jt_cfg_endrecord(argc, argv); + shmem_stop(); + do_disconnect(argv[0], 1); +} + +static int check_pool_cmd(enum lcfg_command_type cmd, + char *fsname, char *poolname, + char *ostname) +{ + int rc; + + rc = llapi_search_ost(fsname, poolname, ostname); + if (rc < 0 && (cmd != LCFG_POOL_NEW)) { + fprintf(stderr, "Pool %s.%s not found\n", + fsname, poolname); + return rc; } - do_disconnect(argv[0], 1); + switch (cmd) { + case LCFG_POOL_NEW: { + LASSERT(ostname == NULL); + if (rc >= 0) { + fprintf(stderr, "Pool %s.%s already exists\n", + fsname, poolname); + return -EEXIST; + } + return 0; + } + case LCFG_POOL_DEL: { + LASSERT(ostname == NULL); + if (rc == 1) { + fprintf(stderr, "Pool %s.%s not empty, " + "please remove all members\n", + fsname, poolname); + return -ENOTEMPTY; + } + return 0; + } + case LCFG_POOL_ADD: { + if (rc == 1) { + fprintf(stderr, "OST %s is already in pool %s.%s\n", + ostname, fsname, poolname); + return -EEXIST; + } + rc = llapi_search_ost(fsname, NULL, ostname); + if (rc == 0) { + fprintf(stderr, "OST %s is not part of the '%s' fs.\n", + ostname, fsname); + return -ENOENT; + } + return 0; + } + case LCFG_POOL_REM: { + if (rc == 0) { + fprintf(stderr, "OST %s not found in pool %s.%s\n", + ostname, fsname, poolname); + return -ENOENT; + } + return 0; + } + default: + break; + } /* switch */ + return -EINVAL; +} + +/* This check only verifies that the changes have been "pushed out" to + the client successfully. This involves waiting for a config update, + and so may fail because of problems in that code or post-command + network loss. So reporting a warning is appropriate, but not a failure. +*/ +static int check_pool_cmd_result(enum lcfg_command_type cmd, + char *fsname, char *poolname, + char *ostname) +{ + int cpt = 10; + int rc = 0; + + switch (cmd) { + case LCFG_POOL_NEW: { + do { + rc = llapi_search_ost(fsname, poolname, NULL); + if (rc == -ENODEV) + return rc; + if (rc < 0) + sleep(2); + cpt--; + } while ((rc < 0) && (cpt > 0)); + if (rc >= 0) { + fprintf(stderr, "Pool %s.%s created\n", + fsname, poolname); + return 0; + } else { + fprintf(stderr, "Warning, pool %s.%s not found\n", + fsname, poolname); + return -ENOENT; + } + } + case LCFG_POOL_DEL: { + do { + rc = llapi_search_ost(fsname, poolname, NULL); + if (rc == -ENODEV) + return rc; + if (rc >= 0) + sleep(2); + cpt--; + } while ((rc >= 0) && (cpt > 0)); + if (rc < 0) { + fprintf(stderr, "Pool %s.%s destroyed\n", + fsname, poolname); + return 0; + } else { + fprintf(stderr, "Warning, pool %s.%s still found\n", + fsname, poolname); + return -EEXIST; + } + } + case LCFG_POOL_ADD: { + do { + rc = llapi_search_ost(fsname, poolname, ostname); + if (rc == -ENODEV) + return rc; + if (rc != 1) + sleep(2); + cpt--; + } while ((rc != 1) && (cpt > 0)); + if (rc == 1) { + fprintf(stderr, "OST %s added to pool %s.%s\n", + ostname, fsname, poolname); + return 0; + } else { + fprintf(stderr, "Warning, OST %s not found in pool %s.%s\n", + ostname, fsname, poolname); + return -ENOENT; + } + } + case LCFG_POOL_REM: { + do { + rc = llapi_search_ost(fsname, poolname, ostname); + if (rc == -ENODEV) + return rc; + if (rc == 1) + sleep(2); + cpt--; + } while ((rc == 1) && (cpt > 0)); + if (rc != 1) { + fprintf(stderr, "OST %s removed from pool %s.%s\n", + ostname, fsname, poolname); + return 0; + } else { + fprintf(stderr, "Warning, OST %s still found in pool %s.%s\n", + ostname, fsname, poolname); + return -EEXIST; + } + } + default: + break; + } + return -EINVAL; +} + +static int check_and_complete_ostname(char *fsname, char *ostname) +{ + char *ptr; + char real_ostname[MAX_OBD_NAME + 1]; + char i; + + /* if OST name does not start with fsname, we add it */ + /* if not check if the fsname is the right one */ + ptr = strchr(ostname, '-'); + if (ptr == NULL) { + sprintf(real_ostname, "%s-%s", fsname, ostname); + } else if (strncmp(ostname, fsname, strlen(fsname)) != 0) { + fprintf(stderr, "%s does not start with fsname %s\n", + ostname, fsname); + return -EINVAL; + } else { + strcpy(real_ostname, ostname); + } + /* real_ostname is fsname-????? */ + ptr = real_ostname + strlen(fsname) + 1; + if (strncmp(ptr, "OST", 3) != 0) { + fprintf(stderr, "%s does not start by %s-OST nor OST\n", + ostname, fsname); + return -EINVAL; + } + /* real_ostname is fsname-OST????? */ + ptr += 3; + for (i = 0; i < 4; i++) { + if (!isxdigit(*ptr)) { + fprintf(stderr, + "ost's index in %s is not an hexa number\n", + ostname); + return -EINVAL; + } + ptr++; + } + /* real_ostname is fsname-OSTXXXX????? */ + /* if OST name does not end with _UUID, we add it */ + if (*ptr == '\0') { + strcat(real_ostname, "_UUID"); + } else if (strcmp(ptr, "_UUID") != 0) { + fprintf(stderr, + "ostname %s does not end with _UUID\n", ostname); + return -EINVAL; + } + /* real_ostname is fsname-OSTXXXX_UUID */ + strcpy(ostname, real_ostname); + return 0; +} + +/* returns 0 or -errno */ +static int pool_cmd(enum lcfg_command_type cmd, + char *cmdname, char *fullpoolname, + char *fsname, char *poolname, char *ostname) +{ + int rc = 0; + struct obd_ioctl_data data; + struct lustre_cfg_bufs bufs; + struct lustre_cfg *lcfg; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + + rc = check_pool_cmd(cmd, fsname, poolname, ostname); + if (rc == -ENODEV) + fprintf(stderr, "Can't verify pool command since there " + "is no local MDT or client, proceeding anyhow...\n"); + else if (rc) + return rc; + + lustre_cfg_bufs_reset(&bufs, NULL); + lustre_cfg_bufs_set_string(&bufs, 0, cmdname); + lustre_cfg_bufs_set_string(&bufs, 1, fullpoolname); + if (ostname != NULL) + lustre_cfg_bufs_set_string(&bufs, 2, ostname); + + lcfg = lustre_cfg_new(cmd, &bufs); + if (IS_ERR(lcfg)) { + rc = PTR_ERR(lcfg); + return rc; + } + + memset(&data, 0x00, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + goto out; + + data.ioc_type = LUSTRE_CFG_TYPE; + data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount, + lcfg->lcfg_buflens); + data.ioc_pbuf1 = (void *)lcfg; + + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(cmdname)); + return rc; + } + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_POOL, buf); +out: + if (rc) + rc = -errno; + lustre_cfg_free(lcfg); + return rc; +} + +/* + * this function tranforms a rule [start-end/step] into an array + * of matching numbers + * supported forms are: + * [start] : just this number + * [start-end] : all numbers from start to end + * [start-end/step] : numbers from start to end with increment of step + * on return, format contains a printf format string which can be used + * to generate all the strings + */ +static int get_array_idx(char *rule, char *format, int **array) +{ + char *start, *end, *ptr; + unsigned int lo, hi, step; + int array_sz = 0; + int i, array_idx; + int rc; + + start = strchr(rule, '['); + end = strchr(rule, ']'); + if ((start == NULL) || (end == NULL)) { + *array = malloc(sizeof(int)); + if (*array == NULL) + return 0; + strcpy(format, rule); + array_sz = 1; + return array_sz; + } + *start = '\0'; + *end = '\0'; + end++; + start++; + /* put in format the printf format (the rule without the range) */ + sprintf(format, "%s%%.4x%s", rule, end); + + array_idx = 0; + array_sz = 0; + *array = NULL; + /* loop on , separator */ + do { + /* extract the 3 fields */ + rc = sscanf(start, "%x-%x/%u", &lo, &hi, &step); + switch (rc) { + case 0: { + return 0; + } + case 1: { + array_sz++; + *array = realloc(*array, array_sz * sizeof(int)); + if (*array == NULL) + return 0; + (*array)[array_idx] = lo; + array_idx++; + break; + } + case 2: { + step = 1; + /* do not break to share code with case 3: */ + } + case 3: { + if ((hi < lo) || (step == 0)) + return 0; + array_sz += (hi - lo) / step + 1; + *array = realloc(*array, sizeof(int) * array_sz); + if (*array == NULL) + return 0; + for (i = lo; i <= hi; i+=step, array_idx++) + (*array)[array_idx] = i; + break; + } + } + ptr = strchr(start, ','); + if (ptr != NULL) + start = ptr + 1; + + } while (ptr != NULL); + return array_sz; +} + +static int extract_fsname_poolname(char *arg, char *fsname, char *poolname) +{ + char *ptr; + int len; + int rc; + + strcpy(fsname, arg); + ptr = strchr(fsname, '.'); + if (ptr == NULL) { + fprintf(stderr, ". is missing in %s\n", fsname); + rc = -EINVAL; + goto err; + } + + len = ptr - fsname; + if (len == 0) { + fprintf(stderr, "fsname is empty\n"); + rc = -EINVAL; + goto err; + } + + len = strlen(ptr + 1); + if (len == 0) { + fprintf(stderr, "poolname is empty\n"); + rc = -EINVAL; + goto err; + } + if (len > LOV_MAXPOOLNAME) { + fprintf(stderr, + "poolname %s is too long (length is %d max is %d)\n", + ptr + 1, len, LOV_MAXPOOLNAME); + rc = -ENAMETOOLONG; + goto err; + } + strncpy(poolname, ptr + 1, LOV_MAXPOOLNAME); + poolname[LOV_MAXPOOLNAME] = '\0'; + *ptr = '\0'; + return 0; + +err: + fprintf(stderr, "argument %s must be .\n", arg); + return rc; +} + +int jt_pool_cmd(int argc, char **argv) +{ + enum lcfg_command_type cmd; + char fsname[PATH_MAX + 1]; + char poolname[LOV_MAXPOOLNAME + 1]; + char *ostnames_buf = NULL; + int i, rc; + int *array = NULL, array_sz; + struct { + int rc; + char *ostname; + } *cmds = NULL; + + switch (argc) { + case 0: + case 1: return CMD_HELP; + case 2: { + if (strcmp("pool_new", argv[0]) == 0) + cmd = LCFG_POOL_NEW; + else if (strcmp("pool_destroy", argv[0]) == 0) + cmd = LCFG_POOL_DEL; + else if (strcmp("pool_list", argv[0]) == 0) + return llapi_poollist(argv[1]); + else return CMD_HELP; + + rc = extract_fsname_poolname(argv[1], fsname, poolname); + if (rc) + break; + + rc = pool_cmd(cmd, argv[0], argv[1], fsname, poolname, NULL); + if (rc) + break; + + check_pool_cmd_result(cmd, fsname, poolname, NULL); + break; + } + default: { + char format[2*MAX_OBD_NAME]; + + if (strcmp("pool_remove", argv[0]) == 0) { + cmd = LCFG_POOL_REM; + } else if (strcmp("pool_add", argv[0]) == 0) { + cmd = LCFG_POOL_ADD; + } else { + return CMD_HELP; + } + + rc = extract_fsname_poolname(argv[1], fsname, poolname); + if (rc) + break; + + for (i = 2; i < argc; i++) { + int j; + + array_sz = get_array_idx(argv[i], format, &array); + if (array_sz == 0) + return CMD_HELP; + + cmds = malloc(array_sz * sizeof(cmds[0])); + if (cmds != NULL) { + ostnames_buf = malloc(array_sz * + (MAX_OBD_NAME + 1)); + } else { + free(array); + rc = -ENOMEM; + goto out; + } + + for (j = 0; j < array_sz; j++) { + char ostname[MAX_OBD_NAME + 1]; + + snprintf(ostname, MAX_OBD_NAME, format, + array[j]); + ostname[MAX_OBD_NAME] = '\0'; + + rc = check_and_complete_ostname(fsname,ostname); + if (rc) { + free(array); + free(cmds); + if (ostnames_buf) + free(ostnames_buf); + goto out; + } + if (ostnames_buf != NULL) { + cmds[j].ostname = + &ostnames_buf[(MAX_OBD_NAME + 1) * j]; + strcpy(cmds[j].ostname, ostname); + } else { + cmds[j].ostname = NULL; + } + cmds[j].rc = pool_cmd(cmd, argv[0], argv[1], + fsname, poolname, + ostname); + /* Return an err if any of the add/dels fail */ + if (!rc) + rc = cmds[j].rc; + } + for (j = 0; j < array_sz; j++) { + if (!cmds[j].rc) { + char ostname[MAX_OBD_NAME + 1]; + + if (!cmds[j].ostname) { + snprintf(ostname, MAX_OBD_NAME, + format, array[j]); + ostname[MAX_OBD_NAME] = '\0'; + check_and_complete_ostname( + fsname, ostname); + } else { + strcpy(ostname, + cmds[j].ostname); + } + check_pool_cmd_result(cmd, fsname, + poolname,ostname); + } + } + if (array_sz > 0) + free(array); + if (cmds) + free(cmds); + if (ostnames_buf); + free(ostnames_buf); + } + /* fall through */ + } + } /* switch */ + +out: + if (rc != 0) { + errno = -rc; + perror(argv[0]); + } + + return rc; } + +int jt_get_obj_version(int argc, char **argv) +{ + struct lu_fid fid; + struct obd_ioctl_data data; + __u64 version; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf, *fidstr; + int rc; + + if (argc != 2) + return CMD_HELP; + + fidstr = argv[1]; + while (*fidstr == '[') + fidstr++; + sscanf(fidstr, SFID, RFID(&fid)); + if (!fid_is_sane(&fid)) { + fprintf(stderr, "bad FID format [%s], should be "DFID"\n", + fidstr, (__u64)1, 2, 0); + return -EINVAL; + } + + memset(&data, 0, sizeof data); + data.ioc_dev = cur_device; + data.ioc_inlbuf1 = (char *) &fid; + data.ioc_inllen1 = sizeof fid; + data.ioc_inlbuf2 = (char *) &version; + data.ioc_inllen2 = sizeof version; + + memset(buf, 0, sizeof *buf); + rc = obd_ioctl_pack(&data, &buf, sizeof rawbuf); + if (rc) { + fprintf(stderr, "error: %s: packing ioctl arguments: %s\n", + jt_cmdname(argv[0]), strerror(-rc)); + return rc; + } + + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GET_OBJ_VERSION, buf); + if (rc == -1) { + fprintf(stderr, "error: %s: ioctl: %s\n", + jt_cmdname(argv[0]), strerror(errno)); + return -errno; + } + + obd_ioctl_unpack(&data, buf, sizeof rawbuf); + printf(LPX64"\n", version); + return 0; +} + +void llapi_ping_target(char *obd_type, char *obd_name, + char *obd_uuid, void *args) +{ + int rc; + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + + memset(&data, 0, sizeof(data)); + data.ioc_inlbuf4 = obd_name; + data.ioc_inllen4 = strlen(obd_name) + 1; + data.ioc_dev = OBD_DEV_BY_DEVNAME; + memset(buf, 0, sizeof(rawbuf)); + if (obd_ioctl_pack(&data, &buf, sizeof(rawbuf))) { + fprintf(stderr, "error: invalid ioctl\n"); + return; + } + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_PING_TARGET, buf); + if (rc) + rc = errno; + if (rc == ENOTCONN || rc == ESHUTDOWN) { + printf("%s inactive.\n", obd_name); + } else if (rc) { + fprintf(stderr, "error: check '%s' %s\n", + obd_name, strerror(errno)); + } else { + printf("%s active.\n", obd_name); + } +} + +int jt_changelog_register(int argc, char **argv) +{ + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct obd_ioctl_data data; + char devname[30]; + int rc; + + if (argc > 2) + return CMD_HELP; + else if (argc == 2 && strcmp(argv[1], "-n") != 0) + return CMD_HELP; + if (cur_device < 0) + return CMD_HELP; + + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } + + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CHANGELOG_REG, buf); + if (rc < 0) { + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + return rc; + } + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + + if (data.ioc_u32_1 == 0) { + fprintf(stderr, "received invalid userid!\n"); + return EPROTO; + } + + if (lcfg_get_devname() != NULL) + strcpy(devname, lcfg_get_devname()); + else + sprintf(devname, "dev %d", cur_device); + + if (argc == 2) + /* -n means bare name */ + printf(CHANGELOG_USER_PREFIX"%u\n", data.ioc_u32_1); + else + printf("%s: Registered changelog userid '"CHANGELOG_USER_PREFIX + "%u'\n", devname, data.ioc_u32_1); + return 0; +} + +int jt_changelog_deregister(int argc, char **argv) +{ + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct obd_ioctl_data data; + char devname[30]; + int id, rc; + + if (argc != 2 || cur_device < 0) + return CMD_HELP; + + id = strtol(argv[1] + strlen(CHANGELOG_USER_PREFIX), NULL, 10); + if ((id == 0) || (strncmp(argv[1], CHANGELOG_USER_PREFIX, + strlen(CHANGELOG_USER_PREFIX)) != 0)) { + fprintf(stderr, "expecting id of the form '" + CHANGELOG_USER_PREFIX"'; got '%s'\n", argv[1]); + return CMD_HELP; + } + + memset(&data, 0x00, sizeof(data)); + data.ioc_dev = cur_device; + data.ioc_u32_1 = id; + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; + } + + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CHANGELOG_DEREG, buf); + if (rc < 0) { + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + return rc; + } + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + + if (data.ioc_u32_1 != id) { + fprintf(stderr, "No changelog user '%s'. Blocking user" + " is '"CHANGELOG_USER_PREFIX"%d'.\n", argv[1], + data.ioc_u32_1); + return ENOENT; + } + + if (lcfg_get_devname() != NULL) + strcpy(devname, lcfg_get_devname()); + else + sprintf(devname, "dev %d", cur_device); + + printf("%s: Deregistered changelog user '"CHANGELOG_USER_PREFIX"%d'\n", + devname, data.ioc_u32_1); + return 0; +} + +