X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Fobd.c;h=0fdec2290350d508e5ad9744c83eeb8f4e484f7c;hb=f7815c80d95b20c97317fbd7010013dca009121e;hp=156f9ef7d3820241dc248f611f48d31504f69b1f;hpb=ad6f6d4ee44675d59931d81bcd966005db47fe2a;p=fs%2Flustre-release.git diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 156f9ef..0fdec22 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -15,11 +15,7 @@ * * 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. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ @@ -27,7 +23,7 @@ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2013, Intel Corporation. + * Copyright (c) 2011, 2016, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -52,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -61,18 +57,27 @@ #include #include #include +#include #include "obdctl.h" - -#include /* for struct lov_stripe_md */ -#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include -#include #include +#include +#include #define MAX_STRING_SIZE 128 -#define DEVICES_LIST "/proc/fs/lustre/devices" #if HAVE_LIBPTHREAD #include @@ -81,9 +86,10 @@ #define MAX_THREADS 4096 #define MAX_BASE_ID 0xffffffff +#define NIDSTRING_LENGTH 64 struct shared_data { - l_mutex_t mutex; - l_cond_t cond; + pthread_mutex_t mutex; + pthread_cond_t cond; int stopping; struct { __u64 counters[MAX_THREADS]; @@ -109,13 +115,6 @@ const int nthreads = 1; static int cur_device = -1; -struct lov_oinfo lov_oinfos[LOV_MAX_STRIPE_COUNT]; - -struct lsm_buffer { - struct lov_stripe_md lsm; - struct lov_oinfo *ptrs[LOV_MAX_STRIPE_COUNT]; -} lsm_buffer; - static int l2_ioctl(int dev_id, int opc, void *buf) { return l_ioctl(dev_id, opc, buf); @@ -204,15 +203,17 @@ char *obdo_print(struct obdo *obd) { char buf[1024]; - 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" - "misc: %x\nnlink: %d,\nvalid "LPX64"\n", - ostid_id(&obd->o_oi), ostid_seq(&obd->o_oi), 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_misc, - obd->o_nlink, obd->o_valid); + snprintf(buf, sizeof(buf), "id: %#jx\ngrp: %#jx\natime: %ju\n" + "mtime: %ju\nctime: %ju\nsize: %ju\nblocks: %ju" + "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n" + "misc: %x\nnlink: %d,\nvalid %#jx\n", + (uintmax_t)ostid_id(&obd->o_oi), + (uintmax_t)ostid_seq(&obd->o_oi), + (uintmax_t)obd->o_atime, (uintmax_t)obd->o_mtime, + (uintmax_t)obd->o_ctime, (uintmax_t)obd->o_size, + (uintmax_t)obd->o_blocks, obd->o_blksize, obd->o_mode, + obd->o_uid, obd->o_gid, obd->o_flags, obd->o_misc, + obd->o_nlink, (uintmax_t)obd->o_valid); return strdup(buf); } @@ -280,75 +281,6 @@ int parse_devname(char *func, char *name) return ret; } -static void -reset_lsmb (struct lsm_buffer *lsmb) -{ - memset (&lsmb->lsm, 0, sizeof (lsmb->lsm)); - memset(lov_oinfos, 0, sizeof(lov_oinfos)); - lsmb->lsm.lsm_magic = LOV_MAGIC; -} - -static int -parse_lsm (struct lsm_buffer *lsmb, char *string) -{ - struct lov_stripe_md *lsm = &lsmb->lsm; - char *end; - int i; - - /* - * object_id[=size#count[@offset:id]*] - */ - - reset_lsmb (lsmb); - - ostid_set_id(&lsm->lsm_oi, strtoull(string, &end, 0)); - if (end == string) - return -1; - string = end; - - if (*string == 0) - return (0); - - if (*string != '=') - return (-1); - string++; - - lsm->lsm_stripe_size = strtoul (string, &end, 0); - if (end == string) - return (-1); - string = end; - - if (*string != '#') - return (-1); - string++; - - lsm->lsm_stripe_count = strtoul (string, &end, 0); - if (end == string) - return (-1); - string = end; - - if (*string == 0) /* don't have to specify obj ids */ - return (0); - - for (i = 0; i < lsm->lsm_stripe_count; i++) { - if (*string != '@') - return (-1); - string++; - lsm->lsm_oinfo[i]->loi_ost_idx = strtoul(string, &end, 0); - if (*end != ':') - return (-1); - string = end + 1; - ostid_set_id(&lsm->lsm_oinfo[i]->loi_oi, - strtoull(string, &end, 0)); - string = end; - } - - if (*string != 0) - return (-1); - - return (0); -} - char *jt_cmdname(char *func) { static char buf[512]; @@ -474,42 +406,42 @@ static int shmem_setup(void) rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); if (rc != 0) { fprintf(stderr, "Can't set shared mutex attr\n"); - return rc; + goto out; } rc = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED); if (rc != 0) { fprintf(stderr, "Can't set shared cond attr\n"); - return rc; + goto out; } pthread_mutex_init(&shared_data->mutex, &mattr); pthread_cond_init(&shared_data->cond, &cattr); - +out: pthread_mutexattr_destroy(&mattr); pthread_condattr_destroy(&cattr); - return 0; + return rc; } static inline void shmem_lock(void) { - l_mutex_lock(&shared_data->mutex); + pthread_mutex_lock(&shared_data->mutex); } static inline void shmem_unlock(void) { - l_mutex_unlock(&shared_data->mutex); + pthread_mutex_unlock(&shared_data->mutex); } static inline void shmem_wait(void) { - l_cond_wait(&shared_data->cond, &shared_data->mutex); + pthread_cond_wait(&shared_data->cond, &shared_data->mutex); } static inline void shmem_wakeup_all(void) { - l_cond_broadcast(&shared_data->cond); + pthread_cond_broadcast(&shared_data->cond); } static inline void shmem_reset(int total_threads) @@ -558,8 +490,8 @@ static void shmem_total(int total_threads) &shared_data->body.start_time); shmem_unlock(); - printf("Total: total "LPU64" threads %d sec %f %f/second\n", - total, total_threads, secs, total / secs); + printf("Total: total %ju threads %d sec %f %f/second\n", + (uintmax_t)total, total_threads, secs, total / secs); return; } @@ -993,72 +925,69 @@ int jt_obd_abort_recovery(int argc, char **argv) int jt_get_version(int argc, char **argv) { - int rc; - char rawbuf[MAX_IOC_BUFLEN]; - char *version; + char version[128]; + int rc; - if (argc != 1) - return CMD_HELP; + if (argc != 1) + return CMD_HELP; - rc = llapi_get_version(rawbuf, MAX_IOC_BUFLEN, &version); - if (rc) - fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), - strerror(-rc)); - else - printf("Lustre version: %s\n", version); + rc = llapi_get_version_string(version, sizeof(version)); + if (rc) + printf("Lustre version: %s\n", LUSTRE_VERSION_STRING); + else + printf("Lustre version: %s\n", version); - printf("lctl version: %s\n", BUILD_VERSION); - return rc; + return 0; } -/* - * Print an obd device line with the ost_conn_uuid inserted, if the obd - * is an osc. - */ static void print_obd_line(char *s) { - 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; - + const char *param = "osc/%s/ost_conn_uuid"; + char buf[MAX_STRING_SIZE]; + char obd_name[MAX_OBD_NAME]; + FILE *fp = NULL; + glob_t path; + char *ptr; +retry: + /* obd device type is the first 3 characters of param name */ + snprintf(buf, sizeof(buf), " %%*d %%*s %.3s %%%zus %%*s %%*d ", + param, sizeof(obd_name) - 1); + if (sscanf(s, buf, obd_name) == 0) + goto try_mdc; + if (cfs_get_param_paths(&path, param, obd_name) != 0) + goto try_mdc; + fp = fopen(path.gl_pathv[0], "r"); + if (fp == NULL) { + /* need to free path data before retry */ + cfs_free_param_data(&path); 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); - - /* trim trailing newlines */ - ptr = strrchr(buf, '\n'); - if (ptr) *ptr = '\0'; - ptr = strrchr(s, '\n'); - if (ptr) *ptr = '\0'; + if (param[0] == 'o') { /* failed with osc, try mdc */ + param = "mdc/%s/mds_conn_uuid"; + goto retry; + } + buf[0] = '\0'; + goto fail_print; + } - printf("%s %s\n", s, buf); - return; + /* should not ignore fgets(3)'s return value */ + if (!fgets(buf, sizeof(buf), fp)) { + fprintf(stderr, "reading from %s: %s", buf, strerror(errno)); + goto fail_close; + } -fail: - printf("%s", s); - return; +fail_close: + fclose(fp); + cfs_free_param_data(&path); + + /* trim trailing newlines */ + ptr = strrchr(buf, '\n'); + if (ptr) + *ptr = '\0'; +fail_print: + ptr = strrchr(s, '\n'); + if (ptr) + *ptr = '\0'; + printf("%s%s%s\n", s, buf[0] ? " " : "", buf); } /* get device list by ioctl */ @@ -1101,10 +1030,10 @@ int jt_obd_list_ioctl(int argc, char **argv) int jt_obd_list(int argc, char **argv) { - int rc; - char buf[MAX_STRING_SIZE]; - FILE *fp = NULL; - int print_obd = 0; + char buf[MAX_STRING_SIZE]; + int print_obd = 0; + glob_t path; + FILE *fp; if (argc > 2) return CMD_HELP; @@ -1115,10 +1044,14 @@ int jt_obd_list(int argc, char **argv) return CMD_HELP; } - fp = fopen(DEVICES_LIST, "r"); + if (cfs_get_param_paths(&path, "devices") != 0) + return -errno; + + fp = fopen(path.gl_pathv[0], "r"); if (fp == NULL) { - fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n", - jt_cmdname(argv[0]), strerror(rc = errno)); + fprintf(stderr, "error: %s: %s opening %s\n", + jt_cmdname(argv[0]), strerror(errno), path.gl_pathv[0]); + cfs_free_param_data(&path); return jt_obd_list_ioctl(argc, argv); } @@ -1128,14 +1061,15 @@ int jt_obd_list(int argc, char **argv) else printf("%s", buf); + cfs_free_param_data(&path); fclose(fp); return 0; } struct jt_fid_space { - obd_seq jt_seq; - obd_id jt_id; - int jt_width; + __u64 jt_seq; + __u64 jt_id; + int jt_width; }; int jt_obd_alloc_fids(struct jt_fid_space *space, struct lu_fid *fid, @@ -1180,7 +1114,9 @@ int jt_obd_alloc_fids(struct jt_fid_space *space, struct lu_fid *fid, fid->f_oid = space->jt_id; fid->f_ver = 0; - space->jt_id = min(space->jt_id + *count, space->jt_width); + space->jt_id = space->jt_id + *count; + if (space->jt_id > space->jt_width) + space->jt_id = space->jt_width; *count = space->jt_id - fid->f_oid; return 0; @@ -1226,7 +1162,6 @@ int jt_obd_md_common(int argc, char **argv, int cmd) {0, 0, 0, 0} }; - optind = 0; while ((c = getopt_long(argc, argv, "b:c:d:D:m:n:t:v", long_opts, NULL)) >= 0) { switch (c) { @@ -1405,8 +1340,7 @@ int jt_obd_md_common(int argc, char **argv, int cmd) struct lu_fid fid = { 0 }; if (child_base_id != -1) - ostid_set_id(&data.ioc_obdo2.o_oi, child_base_id); - + data.ioc_obdo2.o_oi.oi.oi_id = child_base_id; data.ioc_obdo2.o_mode = mode | create_mode; data.ioc_obdo2.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLFLAGS | @@ -1515,25 +1449,19 @@ int jt_obd_test_md_getattr(int argc, char **argv) return jt_obd_md_common(argc, argv, ECHO_MD_GETATTR); } -/* 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. - */ -/* 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 = 1; - int verbose = 1, mode = 0100644, rc = 0, i, valid_lsm = 0; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct obd_ioctl_data data; + struct timeval next_time; + __u64 count = 1, next_count, base_id = 1; + int verbose = 1, mode = 0100644, rc = 0, i; char *end; memset(&data, 0, sizeof(data)); data.ioc_dev = cur_device; - if (argc < 2 || argc > 5) - return CMD_HELP; + if (argc < 2 || argc > 4) + return CMD_HELP; count = strtoull(argv[1], &end, 0); if (*end) { @@ -1559,20 +1487,7 @@ int jt_obd_create(int argc, char **argv) return CMD_HELP; } - if (argc < 5) { - reset_lsmb(&lsm_buffer); /* will set default */ - } else { - rc = parse_lsm(&lsm_buffer, argv[4]); - if (rc != 0) { - fprintf(stderr, "error: %s: invalid lsm '%s'\n", - jt_cmdname(argv[0]), argv[4]); - return CMD_HELP; - } - base_id = ostid_id(&lsm_buffer.lsm.lsm_oi); - valid_lsm = 1; - } - - printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count); + printf("%s: %jd objects\n", jt_cmdname(argv[0]), (uintmax_t)count); gettimeofday(&next_time, NULL); next_time.tv_sec -= verbose; @@ -1582,13 +1497,11 @@ int jt_obd_create(int argc, char **argv) ostid_set_id(&data.ioc_obdo1.o_oi, base_id); data.ioc_obdo1.o_uid = 0; data.ioc_obdo1.o_gid = 0; + data.ioc_obdo1.o_projid = 0; data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLID | OBD_MD_FLUID | - OBD_MD_FLGID | OBD_MD_FLGROUP; - if (valid_lsm) { - data.ioc_plen1 = sizeof lsm_buffer; - data.ioc_pbuf1 = (char *)&lsm_buffer; - } + OBD_MD_FLGID | OBD_MD_FLGROUP | + OBD_MD_FLPROJID; memset(buf, 0, sizeof(rawbuf)); rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); @@ -1606,16 +1519,17 @@ int jt_obd_create(int argc, char **argv) break; } if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) { - fprintf(stderr,"error: %s: oid not valid #%d:"LPX64"\n", - jt_cmdname(argv[0]), i, data.ioc_obdo1.o_valid); + fprintf(stderr, "error: %s: oid not valid #%d:%#jx\n", + jt_cmdname(argv[0]), i, + (uintmax_t)data.ioc_obdo1.o_valid); rc = EINVAL; break; } if (be_verbose(verbose, &next_time, i, &next_count, count)) - printf("%s: #%d is object id "LPX64"\n", + printf("%s: #%d is object id %#jx\n", jt_cmdname(argv[0]), i, - ostid_id(&data.ioc_obdo1.o_oi)); + (uintmax_t) ostid_id(&data.ioc_obdo1.o_oi)); } return rc; } @@ -1666,10 +1580,10 @@ int jt_obd_test_setattr(int argc, char **argv) { struct obd_ioctl_data data; struct timeval start, next_time; - __u64 i, count, next_count; + __u64 i, count, next_count; char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; int verbose = 1; - obd_id objid = 3; + __u64 objid = 3; char *end; int rc = 0; @@ -1709,8 +1623,9 @@ int jt_obd_test_setattr(int argc, char **argv) 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)); + printf("%s: setting %jd attrs (objid %#jx): %s", + jt_cmdname(argv[0]), (uintmax_t)count, + (uintmax_t)objid, ctime(&start.tv_sec)); ostid_set_seq_echo(&data.ioc_obdo1.o_oi); for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) { @@ -1727,14 +1642,15 @@ int jt_obd_test_setattr(int argc, char **argv) rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_SETATTR, &data); shmem_bump(1); if (rc < 0) { - fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n", - jt_cmdname(argv[0]), i, errno, strerror(rc = errno)); + fprintf(stderr, "error: %s: #%jd - %d:%s\n", + jt_cmdname(argv[0]), (uintmax_t)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); + printf("%s: set attr #%jd\n", + jt_cmdname(argv[0]), (uintmax_t)i); } } @@ -1748,9 +1664,9 @@ int jt_obd_test_setattr(int argc, char **argv) --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)); + printf("%s: %jd attrs in %.3fs (%.3f attr/s): %s", + jt_cmdname(argv[0]), (uintmax_t)i, diff, + i / diff, ctime(&end.tv_sec)); } return rc; } @@ -1793,7 +1709,7 @@ int jt_obd_destroy(int argc, char **argv) return CMD_HELP; } - printf("%s: "LPD64" objects\n", jt_cmdname(argv[0]), count); + printf("%s: %jd objects\n", jt_cmdname(argv[0]), (uintmax_t)count); gettimeofday(&next_time, NULL); next_time.tv_sec -= verbose; @@ -1814,14 +1730,15 @@ int jt_obd_destroy(int argc, char **argv) obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); shmem_bump(1); if (rc < 0) { - fprintf(stderr, "error: %s: objid "LPX64": %s\n", - jt_cmdname(argv[0]), id, strerror(rc = errno)); + fprintf(stderr, "error: %s: objid %#jx: %s\n", + jt_cmdname(argv[0]), (uintmax_t)id, + strerror(rc = errno)); break; } if (be_verbose(verbose, &next_time, i, &next_count, count)) - printf("%s: #%d is object id "LPX64"\n", - jt_cmdname(argv[0]), i, id); + printf("%s: #%d is object id %#jx\n", + jt_cmdname(argv[0]), i, (uintmax_t)id); } return rc; @@ -1849,8 +1766,8 @@ int jt_obd_getattr(int argc, char **argv) /* to help obd filter */ data.ioc_obdo1.o_mode = 0100644; data.ioc_obdo1.o_valid = 0xffffffff; - printf("%s: object id "LPX64"\n", jt_cmdname(argv[0]), - ostid_id(&data.ioc_obdo1.o_oi)); + printf("%s: object id %#jx\n", jt_cmdname(argv[0]), + (uintmax_t)ostid_id(&data.ioc_obdo1.o_oi)); memset(buf, 0, sizeof(rawbuf)); rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); @@ -1865,8 +1782,9 @@ int jt_obd_getattr(int argc, char **argv) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); } else { - printf("%s: object id "LPU64", mode %o\n", jt_cmdname(argv[0]), - ostid_id(&data.ioc_obdo1.o_oi), data.ioc_obdo1.o_mode); + printf("%s: object id %ju, mode %o\n", jt_cmdname(argv[0]), + (uintmax_t)ostid_id(&data.ioc_obdo1.o_oi), + data.ioc_obdo1.o_mode); } return rc; } @@ -1876,9 +1794,9 @@ 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; + __u64 i, count, next_count; int verbose = 1; - obd_id objid = 3; + __u64 objid = 3; char *end; int rc = 0; @@ -1918,8 +1836,9 @@ int jt_obd_test_getattr(int argc, char **argv) next_time.tv_sec = start.tv_sec - verbose; next_time.tv_usec = start.tv_usec; if (verbose != 0) - printf("%s: getting "LPD64" attrs (objid "LPX64"): %s", - jt_cmdname(argv[0]), count, objid, ctime(&start.tv_sec)); + printf("%s: getting %jd attrs (objid %#jx): %s", + jt_cmdname(argv[0]), (uintmax_t) count, + (uintmax_t)objid, ctime(&start.tv_sec)); ostid_set_seq_echo(&data.ioc_obdo1.o_oi); for (i = 1, next_count = verbose; i <= count && shmem_running(); i++) { @@ -1936,14 +1855,15 @@ int jt_obd_test_getattr(int argc, char **argv) rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GETATTR, &data); shmem_bump(1); if (rc < 0) { - fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n", - jt_cmdname(argv[0]), i, errno, strerror(rc = errno)); + fprintf(stderr, "error: %s: #%jd - %d:%s\n", + jt_cmdname(argv[0]), (uintmax_t)i, + errno, strerror(rc = errno)); break; } else { if (be_verbose (verbose, &next_time, i, &next_count, count)) - printf("%s: got attr #"LPD64"\n", - jt_cmdname(argv[0]), i); + printf("%s: got attr #%jd\n", + jt_cmdname(argv[0]), (uintmax_t)i); } } @@ -1957,9 +1877,9 @@ int jt_obd_test_getattr(int argc, char **argv) --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)); + printf("%s: %jd attrs in %.3fs (%.3f attr/s): %s", + jt_cmdname(argv[0]), (uintmax_t) i, diff, + i / diff, ctime(&end.tv_sec)); } return rc; } @@ -2142,9 +2062,10 @@ int jt_obd_test_brw(int argc, char **argv) next_time.tv_usec = start.tv_usec; if (verbose != 0) - printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s", - jt_cmdname(argv[0]), write ? "writing" : "reading", count, - pages, objid, data.ioc_offset, ctime(&start.tv_sec)); + printf("%s: %s %jux%d pages (obj %#jx, off %ju): %s", + jt_cmdname(argv[0]), write ? "writing" : "reading", + (uintmax_t)count, pages, (uintmax_t) objid, + (uintmax_t)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 && shmem_running(); i++) { @@ -2165,9 +2086,10 @@ int jt_obd_test_brw(int argc, char **argv) break; } else if (be_verbose(verbose, &next_time,i, &next_count,count)) { shmem_lock (); - printf("%s: %s number %d @ "LPD64":"LPU64" for %d\n", + printf("%s: %s number %d @ %jd:%ju for %d\n", jt_cmdname(argv[0]), write ? "write" : "read", i, - ostid_id(&data.ioc_obdo1.o_oi), data.ioc_offset, + (uintmax_t)ostid_id(&data.ioc_obdo1.o_oi), + (uintmax_t)data.ioc_offset, (int)(pages * getpagesize())); shmem_unlock (); } @@ -2301,10 +2223,10 @@ repeat: 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_size: %ju\n", + (uintmax_t)desc.ld_default_stripe_size); + printf("default_stripe_offset: %ju\n", + (uintmax_t)desc.ld_default_stripe_offset); printf("default_stripe_pattern: %u\n", desc.ld_pattern); printf("obd_count: %u\n", desc.ld_tgt_count); printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n"); @@ -2322,74 +2244,6 @@ out: 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; - - memset(&data, 0, sizeof(data)); - data.ioc_dev = cur_device; - if (argc > 5) - return CMD_HELP; - - argstring[0] = '\0'; - for (i = 1; i < argc; i++) { - strncat(argstring, " ", count); - count--; - strncat(argstring, argv[i], count); - count -= strlen(argv[i]); - } - - if (strlen(argstring)) { - data.ioc_inlbuf1 = argstring; - data.ioc_inllen1 = strlen(argstring) + 1; - } - - 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", - jt_cmdname(argv[0]), strerror(rc = errno)); - - return rc; -} - -int jt_obd_ldlm_regress_stop(int argc, char **argv) -{ - int rc; - char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; - struct obd_ioctl_data data; - - memset(&data, 0, sizeof(data)); - data.ioc_dev = cur_device; - - if (argc != 1) - return CMD_HELP; - - 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) - fprintf(stderr, "error: %s: test failed: %s\n", - jt_cmdname(argv[0]), strerror(rc = errno)); - return rc; -} - static int do_activate(int argc, char **argv, int flag) { struct obd_ioctl_data data; @@ -2569,33 +2423,71 @@ int jt_obd_mdc_lookup(int argc, char **argv) return rc; } -int jt_cfg_dump_log(int argc, char **argv) +int jt_lcfg_fork(int argc, char **argv) { - struct obd_ioctl_data data; - char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; - int rc; + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int rc; - if (argc != 2) - return CMD_HELP; + if (argc != 3) + return CMD_HELP; - memset(&data, 0, sizeof(data)); - data.ioc_dev = cur_device; - data.ioc_inllen1 = strlen(argv[1]) + 1; - data.ioc_inlbuf1 = argv[1]; + memset(&data, 0, sizeof(data)); + data.ioc_dev = get_mgs_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]; - 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_DUMP_LOG, buf); - if (rc < 0) - fprintf(stderr, "OBD_IOC_DUMP_LOG failed: %s\n", - strerror(errno)); + 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; + } - return rc; + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LCFG_FORK, buf); + if (rc < 0) + fprintf(stderr, "error: %s: OBD_IOC_LCFG_FORK failed: %s\n", + jt_cmdname(argv[0]), strerror(errno)); + + return rc; +} + +int jt_lcfg_erase(int argc, char **argv) +{ + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int rc; + + if (argc == 3) { + if (strncmp(argv[2], "-q", strlen("-q")) != 0 && + strncmp(argv[2], "--quiet", strlen("--quiet")) != 0) + return CMD_HELP; + } else if (argc != 2) { + return CMD_HELP; + } + + memset(&data, 0, sizeof(data)); + data.ioc_dev = get_mgs_device(); + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + + 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_LCFG_ERASE, buf); + if (rc < 0) + fprintf(stderr, "error: %s: OBD_IOC_LCFG_ERASE failed: %s\n", + jt_cmdname(argv[0]), strerror(errno)); + + return rc; } int jt_llog_catlist(int argc, char **argv) @@ -2707,41 +2599,118 @@ int jt_llog_print(int argc, char **argv) return rc; } -int jt_llog_cancel(int argc, char **argv) +static int llog_cancel_parse_optional(int argc, char **argv, + struct obd_ioctl_data *data) { - struct obd_ioctl_data data; - char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; - int rc; + int cOpt; + const char *const short_options = "c:l:i:h"; + const struct option long_options[] = { + {"catalog", required_argument, NULL, 'c'}, + {"log_id", required_argument, NULL, 'l'}, + {"log_idx", required_argument, NULL, 'i'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + /* sanity check */ + if (!data || argc <= 1) { + return -1; + } - if (argc != 4) - return CMD_HELP; + /*now process command line arguments*/ + while ((cOpt = getopt_long(argc, argv, short_options, + long_options, NULL)) != -1) { + switch (cOpt) { + case 'c': + data->ioc_inllen1 = strlen(optarg) + 1; + data->ioc_inlbuf1 = optarg; + break; - memset(&data, 0, 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]; - 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; - } + case 'l': + data->ioc_inllen2 = strlen(optarg) + 1; + data->ioc_inlbuf2 = optarg; + break; - rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf); - if (rc == 0) - fprintf(stdout, "index %s be canceled.\n", argv[3]); - else - fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n", - strerror(errno)); + case 'i': + data->ioc_inllen3 = strlen(optarg) + 1; + data->ioc_inlbuf3 = optarg; + break; - return rc; + case 'h': + default: + return -1; + } + } + + if ((data->ioc_inlbuf1 == NULL) || (data->ioc_inlbuf3 == NULL)) { + /* missing mandatory parameters */ + return -1; + } + + return 0; +} + +int jt_llog_cancel(int argc, char **argv) +{ + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int rc, i; + + /* check that the arguments provided are either all + * optional or all positional. No mixing allowed + * + * if argc is 4 or 3 then check all arguments to ensure that none + * of them start with a '-'. If so then this is invalid. + * Otherwise if arg is > 4 then assume that this is optional + * arguments, and parse as such ignoring any thing that's not + * optional. The result is that user must use optional arguments + * for all mandatory parameters. Code will ignore all other args + * + * The positional arguments option should eventually be phased out. + */ + memset(&data, 0, sizeof(data)); + data.ioc_dev = cur_device; + + if (argc == 3 || argc == 4) { + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') + return CMD_HELP; + } + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + if (argc == 4) { + data.ioc_inllen2 = strlen(argv[2]) + 1; + data.ioc_inlbuf2 = argv[2]; + data.ioc_inllen3 = strlen(argv[3]) + 1; + data.ioc_inlbuf3 = argv[3]; + } else { + data.ioc_inllen3 = strlen(argv[2]) + 1; + data.ioc_inlbuf3 = argv[2]; + } + } else { + if (llog_cancel_parse_optional(argc, argv, &data) != 0) + return CMD_HELP; + } + + 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) + fprintf(stdout, "index %s was canceled.\n", + argc == 4 ? argv[3] : argv[2]); + else + fprintf(stderr, "OBD_IOC_LLOG_CANCEL failed: %s\n", + strerror(errno)); + + return rc; } + int jt_llog_check(int argc, char **argv) { struct obd_ioctl_data data; @@ -2815,10 +2784,11 @@ int jt_llog_remove(int argc, char **argv) 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 catalog %s are removed. \n", argv[1]); + if (argc == 2) + fprintf(stdout, "log %s is removed.\n", argv[1]); + else + fprintf(stdout, "the log in catalog %s is removed. \n", + argv[1]); } else fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n", strerror(errno)); @@ -2826,209 +2796,7 @@ 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]; - char *ptr; - - fp = fopen("/proc/modules", "r"); - if (fp == NULL) - return -1; - - while (fgets(buf, 1024, fp) != NULL) { - ptr = strchr(buf, ' '); - if (ptr != NULL) - *ptr = 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; - struct lu_fid fid; - - 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, &fid); - if (rc < 0) { - rc = errno; - fprintf(stderr, "error: %s\n", strerror(errno)); - goto out; - } - fprintf(stdout, "lloop device info: "); - if (fid_is_zero(&fid)) - fprintf(stdout, "Not attached\n"); - else - fprintf(stdout, "attached to inode "DFID"\n", PFID(&fid)); -out: - close(fd); - return -rc; -} - -static void signal_server(int sig) +static void signal_server(int sig) { if (sig == SIGINT) { do_disconnect("sigint", 1); @@ -3039,18 +2807,13 @@ static void signal_server(int sig) int obd_initialize(int argc, char **argv) { - int i; - - for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) - lsm_buffer.lsm.lsm_oinfo[i] = lov_oinfos + i; - - if (shmem_setup() != 0) - return -1; + if (shmem_setup() != 0) + return -1; - register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH, - OBD_DEV_MAJOR, OBD_DEV_MINOR); + register_ioc_dev(OBD_DEV_ID, OBD_DEV_PATH, + OBD_DEV_MAJOR, OBD_DEV_MINOR); - return 0; + return 0; } void obd_finalize(int argc, char **argv) @@ -3083,7 +2846,9 @@ static int check_pool_cmd(enum lcfg_command_type cmd, switch (cmd) { case LCFG_POOL_NEW: { - LASSERT(ostname == NULL); + if (ostname != NULL) + return -EINVAL; + if (rc >= 0) { fprintf(stderr, "Pool %s.%s already exists\n", fsname, poolname); @@ -3092,7 +2857,9 @@ static int check_pool_cmd(enum lcfg_command_type cmd, return 0; } case LCFG_POOL_DEL: { - LASSERT(ostname == NULL); + if (ostname != NULL) + return -EINVAL; + if (rc == 1) { fprintf(stderr, "Pool %s.%s not empty, " "please remove all members\n", @@ -3300,11 +3067,9 @@ static int pool_cmd(enum lcfg_command_type cmd, 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; - } + lcfg = lustre_cfg_new(cmd, &bufs); + if (lcfg == NULL) + return -ENOMEM; memset(&data, 0, sizeof(data)); rc = data.ioc_dev = get_mgs_device(); @@ -3321,6 +3086,7 @@ static int pool_cmd(enum lcfg_command_type cmd, if (rc) { fprintf(stderr, "error: %s: invalid ioctl\n", jt_cmdname(cmdname)); + lustre_cfg_free(lcfg); return rc; } rc = l_ioctl(OBD_DEV_ID, OBD_IOC_POOL, buf); @@ -3331,190 +3097,971 @@ out: 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 +/** + * Format and send the ioctl to the MGS. + * + * \param cmd IOCTL to send + * \param ret_data void pointer to return anything from + * ioctl + * \param num_args number of arguments to pack into the + * ioctl buffer + * \param argv[] variable number of string arguments + * + * \retval 0 on success */ -static int get_array_idx(char *rule, char *format, int **array) +static int nodemap_cmd(enum lcfg_command_type cmd, void *ret_data, + unsigned int ret_size, ...) { - char *start, *end, *ptr; - unsigned int lo, hi, step; - int array_sz = 0; - int i, array_idx; - int rc; + va_list ap; + char *arg; + int i = 0; + struct lustre_cfg_bufs bufs; + struct obd_ioctl_data data; + struct lustre_cfg *lcfg; + char rawbuf[MAX_IOC_BUFLEN]; + char *buf = rawbuf; + int rc = 0; + + lustre_cfg_bufs_reset(&bufs, NULL); + + va_start(ap, ret_size); + arg = va_arg(ap, char *); + while (arg != NULL) { + lustre_cfg_bufs_set_string(&bufs, i, arg); + i++; + arg = va_arg(ap, char *); + } + va_end(ap); - 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); + lcfg = lustre_cfg_new(cmd, &bufs); + if (lcfg == NULL) + return -ENOMEM; - 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; + memset(&data, 0, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + goto out; - } while (ptr != NULL); - return array_sz; -} + data.ioc_type = LUSTRE_CFG_TYPE; + data.ioc_plen1 = lustre_cfg_len(lcfg->lcfg_bufcount, + lcfg->lcfg_buflens); + data.ioc_pbuf1 = (void *)lcfg; -static int extract_fsname_poolname(char *arg, char *fsname, char *poolname) -{ - char *ptr; - int len; - int rc; + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc != 0) { + fprintf(stderr, "error: invalid ioctl: %08x errno: %d with " + "rc=%d\n", cmd, errno, rc); + goto out; + } - strcpy(fsname, arg); - ptr = strchr(fsname, '.'); - if (ptr == NULL) { - fprintf(stderr, ". is missing in %s\n", fsname); - rc = -EINVAL; - goto err; - } + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NODEMAP, buf); + if (rc != 0) { + fprintf(stderr, "error: invalid ioctl: %08x errno: %d with " + "rc=%d\n", cmd, errno, rc); + goto out; + } - len = ptr - fsname; - if (len == 0) { - fprintf(stderr, "fsname is empty\n"); - rc = -EINVAL; - goto err; - } + if (ret_data != NULL) { + rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + if (rc != 0) + goto out; - 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; + if (ret_size > data.ioc_plen1) + ret_size = data.ioc_plen1; -err: - fprintf(stderr, "argument %s must be .\n", arg); - return rc; + memcpy(ret_data, data.ioc_pbuf1, ret_size); + } +out: + lustre_cfg_free(lcfg); + + return rc; } -int jt_pool_cmd(int argc, char **argv) +/** + * activate nodemap functions + * + * \param argc number of args + * \param argv[] variable string arguments + * + * argv[0] 1 for activate or 0 for deactivate + * + * \retval 0 on success + */ +int jt_nodemap_activate(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; + int rc; - 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 = nodemap_cmd(LCFG_NODEMAP_ACTIVATE, NULL, 0, argv[0], argv[1], + NULL); - rc = extract_fsname_poolname(argv[1], fsname, poolname); - if (rc) - break; + if (rc != 0) { + errno = -rc; + perror(argv[0]); + } - rc = pool_cmd(cmd, argv[0], argv[1], fsname, poolname, NULL); - if (rc) - break; + return rc; +} - check_pool_cmd_result(cmd, fsname, poolname, NULL); - break; - } - default: { - char format[2*MAX_OBD_NAME]; +/** + * add a nodemap + * + * \param argc number of args + * \param argv[] variable string arguments + * + * argv[0] nodemap name + * + * \retval 0 on success + */ +int jt_nodemap_add(int argc, char **argv) +{ + int rc; - 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 = llapi_nodemap_exists(argv[1]); + if (rc == 0) { + fprintf(stderr, "error: %s existing nodemap name\n", argv[1]); + return 1; + } - rc = extract_fsname_poolname(argv[1], fsname, poolname); - if (rc) - break; + rc = nodemap_cmd(LCFG_NODEMAP_ADD, NULL, 0, argv[0], argv[1], NULL); - for (i = 2; i < argc; i++) { - int j; + if (rc != 0) { + errno = -rc; + perror(argv[0]); + } - array_sz = get_array_idx(argv[i], format, &array); - if (array_sz == 0) - return CMD_HELP; + return rc; +} - cmds = malloc(array_sz * sizeof(cmds[0])); - if (cmds != NULL) { - ostnames_buf = malloc(array_sz * +/** + * delete a nodemap + * + * \param argc number of args + * \param argv[] variable string arguments + * + * argv[0] nodemap name + * + * \retval 0 on success + */ +int jt_nodemap_del(int argc, char **argv) +{ + int rc; + + rc = llapi_nodemap_exists(argv[1]); + if (rc != 0) { + fprintf(stderr, "error: %s not existing nodemap name\n", + argv[1]); + return rc; + } + rc = nodemap_cmd(LCFG_NODEMAP_DEL, NULL, 0, argv[0], argv[1], NULL); + + if (rc != 0) { + errno = -rc; + perror(argv[0]); + } + + return rc; +} + +/** + * test a nid for nodemap membership + * + * \param argc number of args + * \param argv[] variable string arguments + * + * argv[0] properly formatted nid + * + * \retval 0 on success + */ +int jt_nodemap_test_nid(int argc, char **argv) +{ + + char rawbuf[MAX_IOC_BUFLEN]; + int rc; + + rc = nodemap_cmd(LCFG_NODEMAP_TEST_NID, &rawbuf, sizeof(rawbuf), + argv[0], argv[1], NULL); + if (rc == 0) + printf("%s\n", (char *)rawbuf); + + return rc; +} + +/** + * test a nodemap id pair for mapping + * + * \param argc number of args + * \param argv[[] variable string arguments + * + * \retval 0 on success + * + * The argv array should contain the nodemap name, the id + * to checking the mapping on, and the id type (UID or GID) + * + */ +int jt_nodemap_test_id(int argc, char **argv) +{ + char rawbuf[MAX_IOC_BUFLEN]; + char *nidstr = NULL; + char *idstr = NULL; + char *typestr = NULL; + int rc = 0; + int c; + + static struct option long_options[] = { + { + .name = "nid", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "idtype", + .has_arg = required_argument, + .flag = 0, + .val = 't', + }, + { + .name = "id", + .has_arg = required_argument, + .flag = 0, + .val = 'i', + }, + { + NULL + } + }; + + while ((c = getopt_long(argc, argv, "n:t:i:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nidstr = optarg; + break; + case 't': + typestr = optarg; + break; + case 'i': + idstr = optarg; + break; + } + } + + if (nidstr == NULL || typestr == NULL || idstr == NULL) { + fprintf(stderr, "usage: nodemap_test_id --nid " + "--idtype [uid|gid] --id \n"); + return -1; + } + + rc = nodemap_cmd(LCFG_NODEMAP_TEST_ID, &rawbuf, sizeof(rawbuf), + argv[0], nidstr, typestr, idstr); + if (rc == 0) + printf("%s\n", (char *)rawbuf); + + return rc; +} + +/** + * add an nid range to a nodemap + * + * \param argc number of args + * \param argv[] variable string arguments + * + * --name nodemap name + * --range properly formatted nid range + * + * \retval 0 on success + */ +int jt_nodemap_add_range(int argc, char **argv) +{ + char *nodemap_name = NULL; + char *nodemap_range = NULL; + struct list_head nidlist; + char min_nid[LNET_NIDSTR_SIZE + 1]; + char max_nid[LNET_NIDSTR_SIZE + 1]; + char nid_range[2 * LNET_NIDSTR_SIZE + 2]; + int rc = 0; + int c; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "range", + .has_arg = required_argument, + .flag = 0, + .val = 'r', + }, + { + NULL + } + }; + + INIT_LIST_HEAD(&nidlist); + + while ((c = getopt_long(argc, argv, "n:r:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'r': + nodemap_range = optarg; + break; + } + } + + if (nodemap_name == NULL || nodemap_range == NULL) { + fprintf(stderr, "usage: nodemap_add_range --name " + "--range \n"); + return -1; + } + + if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range), + &nidlist) <= 0) { + fprintf(stderr, "error: %s: can't parse nid range: %s\n", + jt_cmdname(argv[0]), nodemap_range); + return -1; + } + + if (!cfs_nidrange_is_contiguous(&nidlist)) { + fprintf(stderr, "error: %s: nodemap ranges must be " + "contiguous\n", jt_cmdname(argv[0])); + return -1; + } + + cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0], + LNET_NIDSTR_SIZE); + snprintf(nid_range, sizeof(nid_range), "%s:%s", min_nid, max_nid); + + rc = nodemap_cmd(LCFG_NODEMAP_ADD_RANGE, NULL, 0, argv[0], + nodemap_name, nid_range, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "error: %s: cannot add range '%s' to nodemap " + "'%s': rc = %d\n", + jt_cmdname(argv[0]), nodemap_range, nodemap_name, rc); + } + + return rc; +} + +/** + * delete an nid range to a nodemap + * + * \param argc number of args + * \param argv[] variable string arguments + * + * --name nodemap name + * --range properly formatted nid range + * + * \retval 0 on success + */ +int jt_nodemap_del_range(int argc, char **argv) +{ + char *nodemap_name = NULL; + char *nodemap_range = NULL; + struct list_head nidlist; + char min_nid[LNET_NIDSTR_SIZE + 1]; + char max_nid[LNET_NIDSTR_SIZE + 1]; + char nid_range[2 * LNET_NIDSTR_SIZE + 2]; + int rc = 0; + int c; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "range", + .has_arg = required_argument, + .flag = 0, + .val = 'r', + }, + { + NULL + } + }; + + INIT_LIST_HEAD(&nidlist); + + while ((c = getopt_long(argc, argv, "n:r:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'r': + nodemap_range = optarg; + break; + } + } + + if (nodemap_name == NULL || nodemap_range == NULL) { + fprintf(stderr, "usage: nodemap_del_range --name " + "--range \n"); + return -1; + } + + if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range), + &nidlist) <= 0) { + fprintf(stderr, "error: %s: can't parse nid range: %s\n", + jt_cmdname(argv[0]), nodemap_range); + return -1; + } + + if (!cfs_nidrange_is_contiguous(&nidlist)) { + fprintf(stderr, "error: %s: nodemap ranges must be " + "contiguous\n", jt_cmdname(argv[0])); + return -1; + } + + cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0], + LNET_NIDSTR_SIZE); + snprintf(nid_range, sizeof(nid_range), "%s:%s", min_nid, max_nid); + + rc = nodemap_cmd(LCFG_NODEMAP_DEL_RANGE, NULL, 0, argv[0], + nodemap_name, nid_range, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "error: %s: cannot delete range '%s' to " + "nodemap '%s': rc = %d\n", + jt_cmdname(argv[0]), nodemap_range, nodemap_name, rc); + } + + return rc; +} + +/** + * set a fileset on a nodemap + * + * \param argc number of args + * \param argv[] variable string arguments + * + * --name nodemap name + * --fileset fileset name + * + * \retval 0 on success + */ +int jt_nodemap_set_fileset(int argc, char **argv) +{ + char *nodemap_name = NULL; + char *fileset_name = NULL; + int rc = 0; + int c; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "fileset", + .has_arg = required_argument, + .flag = 0, + .val = 'f', + }, + { + NULL + } + }; + + while ((c = getopt_long(argc, argv, "n:f:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'f': + fileset_name = optarg; + break; + } + } + + if (nodemap_name == NULL || fileset_name == NULL) { + fprintf(stderr, "usage: nodemap_set_fileset --name " + "--fileset \n"); + return -1; + } + + rc = nodemap_cmd(LCFG_NODEMAP_SET_FILESET, NULL, 0, argv[0], + nodemap_name, fileset_name, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "error: %s: cannot set fileset '%s' on nodemap " + "'%s': rc = %d\n", + jt_cmdname(argv[0]), fileset_name, nodemap_name, rc); + } + + return rc; +} + +/** + * modify a nodemap's behavior + * + * \param argc number of args + * \param argv[] variable string arguments + * + * --name nodemap name + * --property nodemap property to change + * admin, trusted, squash_uid, squash_gid) + * --value value to set property + * + * \retval 0 on success + */ +int jt_nodemap_modify(int argc, char **argv) +{ + int c; + int rc = 0; + enum lcfg_command_type cmd = 0; + char *nodemap_name = NULL; + char *param = NULL; + char *value = NULL; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "property", + .has_arg = required_argument, + .flag = 0, + .val = 'p', + }, + { + .name = "value", + .has_arg = required_argument, + .flag = 0, + .val = 'v', + }, + { + NULL + } + }; + + while ((c = getopt_long(argc, argv, "n:p:v:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'p': + param = optarg; + break; + case 'v': + value = optarg; + break; + } + } + + if (nodemap_name == NULL || param == NULL || value == NULL) { + fprintf(stderr, "usage: nodemap_modify --name " + "--property --value \n"); + fprintf(stderr, "valid properties: admin trusted map_mode " + "squash_uid squash_gid deny_unknown\n"); + return -1; + } + + if (strcmp("admin", param) == 0) { + cmd = LCFG_NODEMAP_ADMIN; + } else if (strcmp("trusted", param) == 0) { + cmd = LCFG_NODEMAP_TRUSTED; + } else if (strcmp("deny_unknown", param) == 0) { + cmd = LCFG_NODEMAP_DENY_UNKNOWN; + } else if (strcmp("squash_uid", param) == 0) { + cmd = LCFG_NODEMAP_SQUASH_UID; + } else if (strcmp("squash_gid", param) == 0) { + cmd = LCFG_NODEMAP_SQUASH_GID; + } else if (strcmp("map_mode", param) == 0) { + cmd = LCFG_NODEMAP_MAP_MODE; + } else { + fprintf(stderr, "error: %s: nodemap_modify invalid " + "subcommand: %s\n", + jt_cmdname(argv[0]), param); + return -1; + } + + rc = nodemap_cmd(cmd, NULL, 0, argv[0], nodemap_name, param, + value, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "error: %s: cannot modify nodemap '%s' " + "to param '%s': value '%s': rc = %d\n", + jt_cmdname(argv[0]), nodemap_name, param, value, rc); + } + + return rc; +} + +int jt_nodemap_add_idmap(int argc, char **argv) +{ + int c; + enum lcfg_command_type cmd = 0; + char *nodemap_name = NULL; + char *idmap = NULL; + char *idtype = NULL; + int rc = 0; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "idmap", + .has_arg = required_argument, + .flag = 0, + .val = 'm', + }, + { + .name = "idtype", + .has_arg = required_argument, + .flag = 0, + .val = 'i', + }, + { + NULL + } + }; + + while ((c = getopt_long(argc, argv, "n:m:i:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'm': + idmap = optarg; + break; + case 'i': + idtype = optarg; + break; + } + } + + if (nodemap_name == NULL || idmap == NULL || idtype == NULL) { + fprintf(stderr, "usage: %s --name --idtype [uid | gid]" + " --idmap :\n", argv[0]); + return -1; + } + + if (strcmp("uid", idtype) == 0) { + cmd = LCFG_NODEMAP_ADD_UIDMAP; + } else if (strcmp("gid", idtype) == 0) { + cmd = LCFG_NODEMAP_ADD_GIDMAP; + } else { + fprintf(stderr, "usage: %s --name --idtype [uid | gid]" + " --idmap :\n", argv[0]); + return -1; + } + + rc = nodemap_cmd(cmd, NULL, 0, argv[0], nodemap_name, idmap, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "cannot add %smap '%s' to nodemap '%s'" + ": rc = %d\n", idtype, idmap, nodemap_name, rc); + } + + return rc; +} + +int jt_nodemap_del_idmap(int argc, char **argv) +{ + int c; + enum lcfg_command_type cmd = 0; + char *nodemap_name = NULL; + char *idmap = NULL; + char *idtype = NULL; + int rc = 0; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "idmap", + .has_arg = required_argument, + .flag = 0, + .val = 'm', + }, + { + .name = "idtype", + .has_arg = required_argument, + .flag = 0, + .val = 'i', + }, + { + NULL + } + }; + + while ((c = getopt_long(argc, argv, "n:m:i:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'm': + idmap = optarg; + break; + case 'i': + idtype = optarg; + break; + } + } + + if (nodemap_name == NULL || idmap == NULL || idtype == NULL) { + fprintf(stderr, "usage: %s --name --idtype [uid | gid]" + " --idmap :\n", argv[0]); + return -1; + } + + if (strcmp("uid", idtype) == 0) + cmd = LCFG_NODEMAP_DEL_UIDMAP; + else + cmd = LCFG_NODEMAP_DEL_GIDMAP; + + rc = nodemap_cmd(cmd, NULL, 0, argv[0], nodemap_name, idmap, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "cannot delete %smap '%s' from nodemap '%s'" + ": rc = %d\n", idtype, idmap, nodemap_name, rc); + } + + 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: + goto err; + case 1: { + void *tmp; + + array_sz++; + tmp = realloc(*array, array_sz * sizeof(int)); + if (tmp == NULL) + goto err; + *array = tmp; + (*array)[array_idx] = lo; + array_idx++; + break; + } + case 2: { + step = 1; + /* do not break to share code with case 3: */ + } + case 3: { + void *tmp; + + if ((hi < lo) || (step == 0)) + goto err; + array_sz += (hi - lo) / step + 1; + tmp = realloc(*array, array_sz * sizeof(int)); + if (tmp == NULL) + goto err; + *array = tmp; + 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; +err: + if (*array != NULL) { + free(*array); + *array = NULL; + } + return 0; +} + +static int extract_fsname_poolname(const char *arg, char *fsname, + char *poolname) +{ + char *ptr; + int rc; + + strlcpy(fsname, arg, PATH_MAX + 1); + ptr = strchr(fsname, '.'); + if (ptr == NULL) { + fprintf(stderr, ". is missing in %s\n", fsname); + rc = -EINVAL; + goto err; + } + + if ((ptr - fsname) == 0) { + fprintf(stderr, "fsname is empty\n"); + rc = -EINVAL; + goto err; + } + + *ptr = '\0'; + ++ptr; + + rc = lustre_is_fsname_valid(fsname, 1, LUSTRE_MAXFSNAME); + if (rc < 0) { + fprintf(stderr, "filesystem name %s must be 1-%d chars\n", + fsname, LUSTRE_MAXFSNAME); + rc = -EINVAL; + goto err; + } else if (rc > 0) { + fprintf(stderr, "char '%c' not allowed in filesystem name\n", + rc); + rc = -EINVAL; + goto err; + } + + rc = lustre_is_poolname_valid(ptr, 1, LOV_MAXPOOLNAME); + if (rc == -1) { + fprintf(stderr, "poolname is empty\n"); + rc = -EINVAL; + goto err; + } else if (rc == -2) { + fprintf(stderr, + "poolname %s is too long (max is %d)\n", + ptr, LOV_MAXPOOLNAME); + rc = -ENAMETOOLONG; + goto err; + } else if (rc > 0) { + fprintf(stderr, "char '%c' not allowed in pool name '%s'\n", + rc, ptr); + rc = -EINVAL; + goto err; + } + + strncpy(poolname, ptr, LOV_MAXPOOLNAME); + poolname[LOV_MAXPOOLNAME] = '\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); @@ -3589,6 +4136,236 @@ out: return rc; } +static const char *barrier_status2name(enum barrier_status status) +{ + switch (status) { + case BS_INIT: + return "init"; + case BS_FREEZING_P1: + return "freezing_p1"; + case BS_FREEZING_P2: + return "freezing_p2"; + case BS_FROZEN: + return "frozen"; + case BS_THAWING: + return "thawing"; + case BS_THAWED: + return "thawed"; + case BS_FAILED: + return "failed"; + case BS_EXPIRED: + return "expired"; + case BS_RESCAN: + return "rescan"; + default: + return "unknown"; + } +} + +int jt_barrier_freeze(int argc, char **argv) +{ + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct barrier_ctl bc; + int rc; + + if (argc < 2 || argc > 3) + return CMD_HELP; + + memset(&data, 0, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + return rc; + + memset(&bc, 0, sizeof(bc)); + bc.bc_version = BARRIER_VERSION_V1; + bc.bc_cmd = BC_FREEZE; + if (argc == 3) + bc.bc_timeout = atoi(argv[2]); + if (bc.bc_timeout == 0) + bc.bc_timeout = BARRIER_TIMEOUT_DEFAULT; + + if (strlen(argv[1]) > 8) { + fprintf(stderr, "%s: fsname name %s is too long. " + "It should not exceed 8.\n", argv[0], argv[1]); + return -EINVAL; + } + + strncpy(bc.bc_name, argv[1], sizeof(bc.bc_name)); + data.ioc_inlbuf1 = (char *)&bc; + data.ioc_inllen1 = sizeof(bc); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc); + return rc; + } + + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_BARRIER, buf); + if (rc < 0) + fprintf(stderr, "Fail to freeze barrier for %s: %s\n", + argv[1], strerror(errno)); + + return rc; +} + +int jt_barrier_thaw(int argc, char **argv) +{ + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct barrier_ctl bc; + int rc; + + if (argc != 2) + return CMD_HELP; + + memset(&data, 0, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + return rc; + + memset(&bc, 0, sizeof(bc)); + bc.bc_version = BARRIER_VERSION_V1; + bc.bc_cmd = BC_THAW; + + if (strlen(argv[1]) > 8) { + fprintf(stderr, "fsname name %s is too long. " + "It should not exceed 8.\n", argv[1]); + return -EINVAL; + } + + strncpy(bc.bc_name, argv[1], sizeof(bc.bc_name)); + data.ioc_inlbuf1 = (char *)&bc; + data.ioc_inllen1 = sizeof(bc); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc); + return rc; + } + + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_BARRIER, buf); + if (rc < 0) + fprintf(stderr, "Fail to thaw barrier for %s: %s\n", + argv[1], strerror(errno)); + + return rc; +} + +int __jt_barrier_stat(int argc, char **argv, struct barrier_ctl *bc) +{ + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + int rc; + + memset(&data, 0, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + return rc; + + memset(bc, 0, sizeof(*bc)); + bc->bc_version = BARRIER_VERSION_V1; + bc->bc_cmd = BC_STAT; + strncpy(bc->bc_name, argv[1], sizeof(bc->bc_name)); + data.ioc_inlbuf1 = (char *)bc; + data.ioc_inllen1 = sizeof(*bc); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc); + return rc; + } + + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_BARRIER, buf); + if (rc < 0) + fprintf(stderr, "Fail to query barrier for %s: %s\n", + argv[1], strerror(errno)); + else + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + + return rc; +} + +int jt_barrier_stat(int argc, char **argv) +{ + struct barrier_ctl bc; + int rc; + + if (argc != 2) + return CMD_HELP; + + if (strlen(argv[1]) > 8) { + fprintf(stderr, "fsname name %s is too long. " + "It should not exceed 8.\n", argv[1]); + return -EINVAL; + } + + rc = __jt_barrier_stat(argc, argv, &bc); + if (!rc) { + printf("The barrier for %s is in '%s'\n", + argv[1], barrier_status2name(bc.bc_status)); + if (bc.bc_status == BS_FREEZING_P1 || + bc.bc_status == BS_FREEZING_P2 || + bc.bc_status == BS_FROZEN) + printf("The barrier will be expired after %d " + "seconds\n", bc.bc_timeout); + } + + return rc; +} + +int jt_barrier_rescan(int argc, char **argv) +{ + struct obd_ioctl_data data; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct barrier_ctl bc; + int rc; + + if (argc < 2 || argc > 3) + return CMD_HELP; + + memset(&data, 0, sizeof(data)); + rc = data.ioc_dev = get_mgs_device(); + if (rc < 0) + return rc; + + memset(&bc, 0, sizeof(bc)); + bc.bc_version = BARRIER_VERSION_V1; + bc.bc_cmd = BC_RESCAN; + if (argc == 3) + bc.bc_timeout = atoi(argv[2]); + if (bc.bc_timeout == 0) + bc.bc_timeout = BARRIER_TIMEOUT_DEFAULT; + + if (strlen(argv[1]) > 8) { + fprintf(stderr, "fsname name %s is too long. " + "It should not exceed 8.\n", argv[1]); + return -EINVAL; + } + + strncpy(bc.bc_name, argv[1], sizeof(bc.bc_name)); + data.ioc_inlbuf1 = (char *)&bc; + data.ioc_inllen1 = sizeof(bc); + memset(buf, 0, sizeof(rawbuf)); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + fprintf(stderr, "Fail to pack ioctl data: rc = %d.\n", rc); + return rc; + } + + rc = l_ioctl(OBD_DEV_ID, OBD_IOC_BARRIER, buf); + if (rc < 0) { + fprintf(stderr, "Fail to rescan barrier bitmap for %s: %s\n", + argv[1], strerror(errno)); + } else { + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + printf("%u of %u MDT(s) in the filesystem %s are inactive\n", + bc.bc_absence, bc.bc_total, argv[1]); + } + + return rc; +} + int jt_get_obj_version(int argc, char **argv) { struct lu_fid fid; @@ -3652,160 +4429,110 @@ int jt_get_obj_version(int argc, char **argv) } obd_ioctl_unpack(&data, buf, sizeof rawbuf); - printf(LPX64"\n", version); + printf("%#jx\n", (uintmax_t)version); return 0; } -void llapi_ping_target(char *obd_type, char *obd_name, - char *obd_uuid, void *args) +int jt_changelog_register(int argc, char **argv) { - int rc; - struct obd_ioctl_data data; - char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; + struct obd_ioctl_data data = { 0 }; + char rawbuf[MAX_IOC_BUFLEN] = ""; + char *buf = rawbuf; + char *device = lcfg_get_devname(); + bool print_name_only = false; + int c; + int rc; + + if (argc > 2) + return CMD_HELP; - 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) { - printf("%s: check error: %s\n", - obd_name, strerror(errno)); - } else { - printf("%s: active\n", obd_name); - } -} + while ((c = getopt(argc, argv, "hn")) >= 0) { + switch (c) { + case 'n': + print_name_only = true; + break; + case 'h': + default: + return CMD_HELP; + } + } -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 (cur_device < 0 || device == NULL) + return CMD_HELP; - 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; + data.ioc_dev = cur_device; - memset(&data, 0, 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 = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc < 0) { + fprintf(stderr, "error: %s: cannot pack ioctl: %s\n", + jt_cmdname(argv[0]), strerror(-rc)); + 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)); + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_CHANGELOG_REG, buf); + if (rc < 0) { + rc = -errno; + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(-rc)); + 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) { - if (strlen(lcfg_get_devname()) > sizeof(devname)-1) { - fprintf(stderr, "Dev name too long\n"); - return -E2BIG; - } - strncpy(devname, lcfg_get_devname(), sizeof(devname)); - } else { - if (snprintf(devname, sizeof(devname), "dev %d", cur_device) >= - sizeof(devname)) { - fprintf(stderr, "Dev name too long\n"); - return -E2BIG; - } - } + if (print_name_only) + printf("%s%u\n", CHANGELOG_USER_PREFIX, data.ioc_u32_1); + else + printf("%s: Registered changelog userid '%s%u'\n", + device, CHANGELOG_USER_PREFIX, data.ioc_u32_1); - 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; + 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; - } + struct obd_ioctl_data data = { 0 }; + char rawbuf[MAX_IOC_BUFLEN] = ""; + char *buf = rawbuf; + char *device = lcfg_get_devname(); + int id; + int rc; + + if (argc != 2 || cur_device < 0 || device == NULL) + return CMD_HELP; - memset(&data, 0, 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 = sscanf(argv[1], CHANGELOG_USER_PREFIX"%d", &id); + if (rc != 1 || id <= 0) { + fprintf(stderr, + "error: %s: expected id of the form %s got '%s'\n", + jt_cmdname(argv[0]), CHANGELOG_USER_PREFIX, argv[1]); + return CMD_HELP; + } - 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)); + data.ioc_dev = cur_device; + data.ioc_u32_1 = id; - 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; + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc < 0) { + fprintf(stderr, "error: %s: invalid ioctl\n", + jt_cmdname(argv[0])); + return rc; } - if (lcfg_get_devname() != NULL) { - if (strlen(lcfg_get_devname()) > sizeof(devname)-1) { - fprintf(stderr, "Dev name too long\n"); - return -E2BIG; - } - strncpy(devname, lcfg_get_devname(), sizeof(devname)); - } else { - if (snprintf(devname, sizeof(devname), "dev %d", cur_device) >= - sizeof(devname)) { - fprintf(stderr, "Dev name too long\n"); - return -E2BIG; - } + 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; } - printf("%s: Deregistered changelog user '"CHANGELOG_USER_PREFIX"%d'\n", - devname, data.ioc_u32_1); - return 0; -} - + obd_ioctl_unpack(&data, buf, sizeof(rawbuf)); + printf("%s: Deregistered changelog user '%s%u'\n", + device, CHANGELOG_USER_PREFIX, data.ioc_u32_1); + return 0; +}