From 0b715b9a53354ace21fd8574b999b53765522176 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 22 Oct 2014 13:33:01 -0500 Subject: [PATCH] LU-2675 utils: remove loadgen Remove lustre/utils/loadgen.c. It doesn't work and is not being maintained. Signed-off-by: John L. Hammond Change-Id: I214cbbde5a3f18dd2050e852d33cca2bc2998b6a Reviewed-on: http://review.whamcloud.com/12395 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Reviewed-by: Alexey Lyashkov --- lustre.spec.in | 1 - lustre/utils/.gitignore | 1 - lustre/utils/Makefile.am | 7 - lustre/utils/loadgen.c | 1089 ---------------------------------------------- 4 files changed, 1098 deletions(-) delete mode 100644 lustre/utils/loadgen.c diff --git a/lustre.spec.in b/lustre.spec.in index ebebe8f..dd5e81f 100644 --- a/lustre.spec.in +++ b/lustre.spec.in @@ -406,7 +406,6 @@ echo '%{_bindir}/munlink' >>lustre-tests.files echo '%{_bindir}/req_layout' >>lustre-tests.files echo '%{_sbindir}/wirecheck' >>lustre-tests.files echo '%{_sbindir}/wiretest' >>lustre-tests.files -echo '%{_sbindir}/loadgen' >>lustre-tests.files %if %{with lustre_modules} echo '%{?rootdir}/lib/modules/%{kversion}/%{kmoddir}/kernel/fs/@PACKAGE@/llog_test.ko' >>lustre-tests.files %endif diff --git a/lustre/utils/.gitignore b/lustre/utils/.gitignore index d1950fe..3b8dc53 100644 --- a/lustre/utils/.gitignore +++ b/lustre/utils/.gitignore @@ -18,7 +18,6 @@ /mkfs_lustre /mount_lustre /tunefs_lustre -/loadgen /lreplicate /ll_recover_lost_found_objs /ltrack_stats diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index d012030..69a07e3 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -29,9 +29,6 @@ sbin_PROGRAMS = lctl l_getidentity llverfs lustre_rsync ltrack_stats if TESTS bin_PROGRAMS += req_layout sbin_PROGRAMS += wiretest -if LIBPTHREAD -sbin_PROGRAMS += loadgen -endif endif # TESTS if SERVER @@ -58,10 +55,6 @@ lfs_SOURCES = lfs.c lfs_LDADD := liblustreapi.a $(LIBPTLCTL) $(LIBREADLINE) lfs_DEPENDENCIES := $(LIBPTLCTL) liblustreapi.a -loadgen_SOURCES = loadgen.c lustre_cfg.c obd.c -loadgen_LDADD := liblustreapi.a $(LIBPTLCTL) $(PTHREAD_LIBS) $(LIBREADLINE) -loadgen_DEPENDENCIES := $(LIBPTLCTL) liblustreapi.a - lustre_rsync_SOURCES = lustre_rsync.c obd.c lustre_cfg.c lustre_rsync.h lustre_rsync_LDADD := liblustreapi.a $(LIBPTLCTL) $(PTHREAD_LIBS) $(LIBREADLINE) lustre_rsync_DEPENDENCIES := $(LIBPTLCTL) liblustreapi.a diff --git a/lustre/utils/loadgen.c b/lustre/utils/loadgen.c deleted file mode 100644 index 494c5ed..0000000 --- a/lustre/utils/loadgen.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * 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. - * - * 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 - * 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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2013, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/utils/loadgen.c - * - * See how many local OSCs we can start whaling on a OST - * We're doing direct ioctls instead of going though a system() call to lctl - * to avoid the bash overhead. - * Adds an osc / echo client pair in each thread and starts echo transactions. - * - * Author: Nathan Rutman - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "obdctl.h" - -static char cmdname[512]; -static char target[64] = ""; -char nid[64] = ""; -static int sig_received = 0; -static int o_verbose = 4; /* 0-5 */ -static int my_oss = 0; -static int my_ecs = 0; - -static int jt_quit(int argc, char **argv) { - Parser_quit(argc, argv); - return 0; -} - -static int loadgen_usage(int argc, char **argv) -{ - if (argc == 1) { - fprintf(stderr, - "This is a test program used to simulate large numbers of\n" - "clients. The echo obds are used, so the obdecho module must\n" - "be loaded.\n" - "Typical usage would be:\n" - " loadgen> dev lustre-OST0000 set the target device\n" - " loadgen> start 20 start 20 echo clients\n" - " loadgen> wr 10 5 have 10 clients do the brw_write\n" - " test 5 times each\n" - ); - } - return (Parser_help(argc, argv)); -} - -static int loadgen_verbose(int argc, char **argv); -static int loadgen_target(int argc, char **argv); -static int loadgen_start_echosrv(int argc, char **argv); -static int loadgen_start_clients(int argc, char **argv); -static int loadgen_wait(int argc, char **argv); -static int loadgen_write(int argc, char **argv); - -command_t cmdlist[] = { - {"device", loadgen_target, 0, - "set target ost name (e.g. lustre-OST0000)\n" - "usage: device []"}, - {"dl", jt_obd_list, 0, "show all devices\n" - "usage: dl"}, - {"echosrv", loadgen_start_echosrv, 0, "start an echo server\n"}, - {"start", loadgen_start_clients, 0, "set up echo clients\n" - "usage: start_clients "}, - {"verbose", loadgen_verbose, 0, "set verbosity level 0-5\n" - "usage: verbose "}, - {"wait", loadgen_wait, 0, - "wait for all threads to finish\n"}, - {"write", loadgen_write, 0, - "start a test_brw write test on X clients for Y iterations\n" - "usage: write []"}, - - /* User interface commands */ - {"help", loadgen_usage, 0, "help"}, - {"exit", jt_quit, 0, "quit"}, - {"quit", jt_quit, 0, "quit"}, - { 0, 0, 0, NULL } -}; - - -/* Command flags */ -#define C_STOP 0x0001 -#define C_CREATE_EVERY 0x0002 /* destroy and recreate every time */ -#define C_READ 0x0004 -#define C_WRITE 0x0008 - -struct command_t { - int c_flags; - int c_rpt; - int c_delay; -}; - -struct kid_t { - struct command_t k_cmd; - struct kid_t *k_next; - pthread_t k_pthread; - __u64 k_objid; - int k_id; - int k_dev; -}; - -static int live_threads = 0; -static struct kid_t *kid_list = NULL; -pthread_mutex_t m_list = PTHREAD_MUTEX_INITIALIZER; - -static struct kid_t *push_kid(int tnum) -{ - struct kid_t *kid; - kid = (struct kid_t *)calloc(1, sizeof(struct kid_t)); - if (kid == NULL) { - fprintf(stderr, "malloc failure\n"); - return NULL; - } - kid->k_pthread = pthread_self(); - pthread_mutex_lock(&m_list); - kid->k_next = kid_list; - kid->k_id = tnum; - kid_list = kid; - live_threads++; - pthread_mutex_unlock(&m_list); - return kid; -} - -int trigger_count = 0; -int waiting_count = 0; -int timer_on = 0; -int all_done = 1; -struct timeval trigger_start; -struct command_t trigger_cmd; -pthread_mutex_t m_trigger = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cv_trigger = PTHREAD_COND_INITIALIZER; - -unsigned long long write_bytes; -pthread_mutex_t m_count = PTHREAD_MUTEX_INITIALIZER; - -static void trigger(int command, int threads, int repeat, int delay) -{ - - pthread_mutex_lock(&m_trigger); - trigger_cmd.c_flags = command; - trigger_cmd.c_rpt = repeat; - trigger_cmd.c_delay = delay; - trigger_count = threads; - if (o_verbose > 4) - printf("trigger %d cmd c=%d f=%x\n", trigger_count, - trigger_cmd.c_rpt, trigger_cmd.c_flags); - gettimeofday(&trigger_start, NULL); - timer_on = 1; - pthread_mutex_lock(&m_count); - write_bytes = 0; - pthread_mutex_unlock(&m_count); - - pthread_cond_broadcast(&cv_trigger); - pthread_mutex_unlock(&m_trigger); -} - -static __inline__ void stop_all(int unused) -{ - sig_received++; -} - -static void kill_kids(void) -{ - struct kid_t *tmp = kid_list; - - stop_all(SIGINT); - trigger(C_STOP, 0, 0, 0); - while(tmp) { - pthread_kill(tmp->k_pthread, SIGTERM); - tmp = tmp->k_next; - } -} - -static void sig_master(int unused) -{ - stop_all(SIGINT); - //jt_quit(0, NULL); -} - -static int wait_for_threads() -{ - struct kid_t *tmp = kid_list; - int rc = 0, status; - void *statusp; - - printf("waiting for %d children\n", live_threads); - - while(tmp) { - rc = pthread_join(tmp->k_pthread, &statusp); - status = (long)statusp; - if (o_verbose > 2) - printf("%d: joined, rc = %d, status = %d\n", - tmp->k_id, rc, status); - kid_list = tmp->k_next; - free(tmp); - tmp = kid_list; - live_threads--; - } - - if (o_verbose > 0) - printf("%s done, rc = %d\n", cmdname, rc); - return rc; -} - -static int write_proc(char *proc_path, char *value) -{ - int fd, rc; - - fd = open(proc_path, O_WRONLY); - if (fd == -1) { - fprintf(stderr, "open('%s') failed: %s\n", - proc_path, strerror(errno)); - rc = errno; - } else { - rc = write(fd, value, strlen(value)); - if (rc < 0) { - fprintf(stderr, "write('%s') failed: %s\n", - proc_path, strerror(errno)); - } - close(fd); - } - return rc; -} - -static int read_proc(char *proc_path, unsigned long long *value) -{ - int fd, rc; - char buf[50]; - - fd = open(proc_path, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "open('%s') failed: %s\n", - proc_path, strerror(errno)); - return (errno); - } - - rc = read(fd, buf, sizeof(buf)); - close(fd); - if (errno == EOPNOTSUPP) { - /* probably an echo server */ - return rc; - } - if (rc <= 0) { - fprintf(stderr, "read('%s') failed: %s (%d)\n", - proc_path, strerror(errno), errno); - return rc; - } - *value = strtoull(buf, NULL, 10); - return 0; -} - -static int grant_estimate(int thread) -{ - unsigned long long avail, grant; - char proc_path[50]; - int rc; - static int ran = 0; - - /* I don't really care about protecting this with a mutex */ - if (ran) - return 0; - - if (o_verbose < 2) - return 0; - - /* Divide /proc/fs/lustre/osc/o_0001/kbytesavail - by /proc/fs/lustre/osc/o_0001/cur_grant_bytes to find max clients */ - sprintf(proc_path, "/proc/fs/lustre/osc/o%.5d/kbytesavail", thread); - rc = read_proc(proc_path, &avail); - if (rc) - return rc; - sprintf(proc_path, "/proc/fs/lustre/osc/o%.5d/cur_grant_bytes", thread); - rc = read_proc(proc_path, &grant); - if (rc) - return rc; - if (grant == 0) { - return -EINVAL; - } - printf("Estimate %llu clients before we run out of grant space " - "(%lluK / %llu)\n", (avail << 10) / grant, avail, grant); - ran++; - return 0; -} - -/* We hold a thread mutex around create/cleanup because cur_dev is not - shared-memory safe */ -pthread_mutex_t m_config = PTHREAD_MUTEX_INITIALIZER; - -static int cleanup(char *obdname, int quiet) -{ - char *args[3]; - int rc; - - pthread_mutex_lock(&m_config); - - args[0] = cmdname; - args[1] = obdname; - rc = jt_lcfg_device(2, args); - if (rc && !quiet) - fprintf(stderr, "%s: can't configure '%s' (%d)\n", - cmdname, obdname, rc); - args[1] = "force"; - rc = jt_obd_cleanup(2, args); - if (rc && !quiet) - fprintf(stderr, "%s: can't cleanup '%s' (%d)\n", - cmdname, obdname, rc); - rc = jt_obd_detach(1, args); - if (rc && !quiet) - fprintf(stderr, "%s: can't detach '%s' (%d)\n", - cmdname, obdname, rc); - - pthread_mutex_unlock(&m_config); - return rc; -} - -static int echocli_setup(char *oname, char *ename, int *dev) -{ - char *args[5]; - char proc_path[50]; - int rc; - - pthread_mutex_lock(&m_config); - - args[0] = cmdname; - - /* OSC */ - /* attach "osc" oscname oscuuid */ - args[1] = "osc"; - args[2] = args[3] = oname; - rc = jt_lcfg_attach(4, args); - if (rc) { - fprintf(stderr, "%s: can't attach osc '%s' (%d)\n", - cmdname, oname, rc); - /* Assume we want e.g. an old one cleaned anyhow. */ - goto clean; - } - /* setup ostname "OSS_UUID" */ - args[1] = target; - args[2] = "OSS_UUID"; - rc = jt_lcfg_setup(3, args); - if (rc) { - fprintf(stderr, "%s: can't setup osc '%s' (%d)\n", - cmdname, oname, rc); - goto clean; - } - - /* Large grants cause ENOSPC to be reported, even though - there's space left. We can reduce the grant size by - minimizing these */ - sprintf(proc_path, "/proc/fs/lustre/osc/%s/max_dirty_mb", oname); - rc = write_proc(proc_path, "1"); - sprintf(proc_path, "/proc/fs/lustre/osc/%s/max_rpcs_in_flight", oname); - rc = write_proc(proc_path, "1"); - - /* ECHO CLI */ - /* attach "echo_client" echoname echouuid */ - args[1] = "echo_client"; - args[2] = args[3] = ename; - rc = jt_lcfg_attach(4, args); - if (rc) { - fprintf(stderr, "%s: can't attach '%s' (%d)\n", - cmdname, ename, rc); - if (rc == ENODEV) - fprintf(stderr, "%s: is the obdecho module loaded?\n", - cmdname); - goto clean; - } - /* setup oscname */ - args[1] = oname; - rc = jt_lcfg_setup(2, args); - if (rc) { - fprintf(stderr, "%s: can't setup '%s' (%d)\n", - cmdname, ename, rc); - goto clean; - } - - args[1] = ename; - rc = jt_obd_device(2, args); - if (rc) { - fprintf(stderr, "%s: can't set device '%s' (%d)\n", - cmdname, ename, rc); - goto clean; - } - - if (!rc) - *dev = jt_obd_get_device(); - pthread_mutex_unlock(&m_config); - return rc; - -clean: - pthread_mutex_unlock(&m_config); - cleanup(ename, 1); - cleanup(oname, 1); - return rc; -} - -/* We can't use the libptlctl library fns because they are not shared-memory - safe with respect to the ioctl device (cur_dev) */ -static int obj_ioctl(int cmd, struct obd_ioctl_data *data, int unpack) -{ - char *buf = NULL; - int rc; - - //IOC_PACK(cmdname, data); - if (obd_ioctl_pack(data, &buf, sizeof(*data))) { - fprintf(stderr, "dev %d invalid ioctl\n", data->ioc_dev); - rc = EINVAL; - goto out; - } - - rc = l_ioctl(OBD_DEV_ID, cmd, buf); - - if (unpack) { - //IOC_UNPACK(argv[0], data); - if (obd_ioctl_unpack(data, buf, sizeof(*data))) { - fprintf(stderr, "dev %d invalid reply\n", data->ioc_dev); - rc = EINVAL; - goto out; - } - } - -out: - if (buf) - free(buf); - return rc; -} - -/* See jt_obd_create */ -static int obj_create(struct kid_t *kid) -{ - struct obd_ioctl_data data; - int rc; - - memset(&data, 0, sizeof(data)); - data.ioc_dev = kid->k_dev; - data.ioc_obdo1.o_mode = 0100644; - ostid_set_seq_echo(&data.ioc_obdo1.o_oi); - ostid_set_id(&data.ioc_obdo1.o_oi, 1); - data.ioc_obdo1.o_uid = 0; - data.ioc_obdo1.o_gid = 0; - data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE | - OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID; - - rc = obj_ioctl(OBD_IOC_CREATE, &data, 1); - if (rc) { - fprintf(stderr, "%d: create (%d) %s\n", - kid->k_id, rc, strerror(errno)); - return rc; - } - - if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) { - fprintf(stderr, "%d: create oid not valid "LPX64"\n", - kid->k_id, data.ioc_obdo1.o_valid); - return rc; - } - - kid->k_objid = ostid_id(&data.ioc_obdo1.o_oi); - - if (o_verbose > 4) - printf("%d: cr "LPX64"\n", kid->k_id, kid->k_objid); - - return rc; -} - -/* See jt_obd_destroy */ -static int obj_delete(struct kid_t *kid) -{ - struct obd_ioctl_data data; - int rc; - - if (o_verbose > 4) - printf("%d: del "LPX64"\n", kid->k_id, kid->k_objid); - - memset(&data, 0, sizeof(data)); - data.ioc_dev = kid->k_dev; - ostid_set_id(&data.ioc_obdo1.o_oi, kid->k_objid); - data.ioc_obdo1.o_mode = S_IFREG | 0644; - data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE; - - rc = obj_ioctl(OBD_IOC_DESTROY, &data, 1); - if (rc) - fprintf(stderr, "%s-%d: can't destroy obj "LPX64" (%d)\n", - cmdname, kid->k_id, kid->k_objid, rc); - - kid->k_objid = 0; - return rc; -} - -#define difftime(a, b) \ - ((a)->tv_sec - (b)->tv_sec + \ - ((a)->tv_usec - (b)->tv_usec) / 1000000.0) - -/* See jt_obd_test_brw */ -static int obj_write(struct kid_t *kid) -{ - struct obd_ioctl_data data; - struct timeval start; - __u64 count, len; - int rc = 0, i, pages = 0; - - if (o_verbose > 4) - printf("%d: wr "LPX64"\n", kid->k_id, kid->k_objid); - - count = 10; - pages = 32; - len = pages * getpagesize(); - - memset(&data, 0, sizeof(data)); - data.ioc_dev = kid->k_dev; - /* communicate the 'type' of brw test and batching to echo_client. - * don't start. we'd love to refactor this lctl->echo_client - * interface */ - data.ioc_pbuf1 = (void *)1; - data.ioc_plen1 = 1; - - ostid_set_seq_echo(&data.ioc_obdo1.o_oi); - ostid_set_id(&data.ioc_obdo1.o_oi, kid->k_objid); - data.ioc_obdo1.o_mode = S_IFREG; - data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE | - OBD_MD_FLFLAGS | OBD_MD_FLGROUP; - data.ioc_obdo1.o_flags = OBD_FL_DEBUG_CHECK; - data.ioc_count = len; - data.ioc_offset = 0; - - gettimeofday(&start, NULL); - - for (i = 1; i <= count; i++) { - data.ioc_obdo1.o_valid &= ~(OBD_MD_FLBLOCKS|OBD_MD_FLGRANT); - rc = obj_ioctl(OBD_IOC_BRW_WRITE, &data, 0); - if (rc) { - fprintf(stderr, "%d: write %s\n", kid->k_id, - strerror(rc = errno)); - break; - } - - data.ioc_offset += len; - } - - if (!rc) { - struct timeval end; - double diff; - - gettimeofday(&end, NULL); - diff = difftime(&end, &start); - - --i; - - pthread_mutex_lock(&m_count); - write_bytes += i * len; - pthread_mutex_unlock(&m_count); - - if (o_verbose > 4) - printf("%d: wrote %dx%d pages in %.3fs (%.3f MB/s): %s", - kid->k_id, i, pages, diff, - ((double)i * len) / (diff * 1048576.0), - ctime(&end.tv_sec)); - } - - if (rc) - fprintf(stderr, "%s-%d: err test_brw obj "LPX64" (%d)\n", - cmdname, kid->k_id, kid->k_objid, rc); - return rc; -} - -static int do_work(struct kid_t *kid) -{ - int rc = 0, err, iter = 0; - - if (!(kid->k_cmd.c_flags & C_CREATE_EVERY)) - rc = obj_create(kid); - - for (iter = 0; iter < kid->k_cmd.c_rpt; iter++) { - if (rc || sig_received) - break; - - if (kid->k_cmd.c_flags & C_CREATE_EVERY) { - rc = obj_create(kid); - if (rc) - break; - } - - if (kid->k_cmd.c_flags & C_WRITE) { - rc = obj_write(kid); - grant_estimate(kid->k_id); - } - - if (kid->k_cmd.c_flags & C_CREATE_EVERY) { - err = obj_delete(kid); - if (!rc) rc = err; - } - - if ((o_verbose > 3) && (iter % 10 == 0)) - printf("%d: i%d\n", kid->k_id, iter); - if (!rc) - sleep(kid->k_cmd.c_delay); - } - - if (!(kid->k_cmd.c_flags & C_CREATE_EVERY)) { - err = obj_delete(kid); - if (!rc) rc = err; - } - - if (o_verbose > 2) - printf("%d: done (%d)\n", kid->k_id, rc); - - return rc; -} - -static void report_perf() -{ - struct timeval end; - double diff; - - gettimeofday(&end, NULL); - diff = difftime(&end, &trigger_start); - if (o_verbose > 2) { - pthread_mutex_lock(&m_count); - printf("wrote %lluMB in %.3fs (%.3f MB/s)\n", - write_bytes >> 20, diff, - (write_bytes >> 20) / diff); - pthread_mutex_unlock(&m_count); - } -} - -static void *run_one_child(void *threadvp) -{ - struct kid_t *kid; - char oname[16], ename[16]; - int thread = (long)threadvp; - int dev = 0; - int err; - int rc; - - if (o_verbose > 2) - printf("%s: running thread #%d\n", cmdname, thread); - - rc = snprintf(oname, sizeof(oname), "o%.5d", thread); - if (rc != 1) { - rc = -EFAULT; - goto out_exit; - } - rc = snprintf(ename, sizeof(ename), "e%.5d", thread); - if (rc != 1) { - rc = -EFAULT; - goto out_exit; - } - rc = echocli_setup(oname, ename, &dev); - if (rc) { - fprintf(stderr, "%s: can't setup '%s/%s' (%d)\n", - cmdname, oname, ename, rc); - goto out_exit; - } - - kid = push_kid(thread); - if (!kid) { - rc = -ENOMEM; - goto out; - } - kid->k_dev = dev; - - while(!(rc || sig_received)) { - pthread_mutex_lock(&m_trigger); - pthread_mutex_lock(&m_list); - waiting_count++; - if ((waiting_count == live_threads) && timer_on) { - report_perf(); - timer_on = 0; - all_done = 1; - } - pthread_mutex_unlock(&m_list); - pthread_cond_wait(&cv_trigger, &m_trigger); - waiting_count--; - all_done = 0; - - /* First trigger_count threads will do the work, the rest - will block again */ - if (trigger_count) { - if (o_verbose > 4) - printf("%d: trigger %d cmd %x\n", - kid->k_id, trigger_count, - trigger_cmd.c_flags); - trigger_count--; - memcpy(&kid->k_cmd, &trigger_cmd, sizeof(trigger_cmd)); - pthread_mutex_unlock(&m_trigger); - rc = do_work(kid); - } else { - pthread_mutex_unlock(&m_trigger); - } - } - - if (o_verbose > 1) - printf("%s: thread #%d done (%d)\n", cmdname, thread, rc); - - if (rc) - stop_all(SIGINT); - -out: - err = cleanup(ename, 0); - if (!rc) rc = err; - err = cleanup(oname, 0); - if (!rc) rc = err; - -out_exit: - pthread_exit((void *)(long)rc); -} - -/* - * PTHREAD_STACK_MIN is 16K minimal stack for threads. This - * is stack consumed by one thread, which executes NULL procedure. - * We need some more here and 20k stack for one client thread - * is enough to not overflow. In same time it does not consume - * a lot of memory for large number of threads. - * - * 20K virtual clients will only consume 320M + 400M. Still to - * create this number of virtual clients we need to fix 8192 - * OBDs limit. - */ -#define CLIENT_THREAD_STACK_SIZE (PTHREAD_STACK_MIN + (20 * 1024)) - -static int loadgen_start_clients(int argc, char **argv) -{ - int rc = 0, i, numt; - struct timespec ts = {0, 1000*1000*100}; /* .1 sec */ - pthread_attr_t attr; - - if (argc != 2) - return CMD_HELP; - - numt = strtoul(argv[1], NULL, 0); - if (numt < 1) - return CMD_HELP; - - if (!target[0]) { - fprintf(stderr, "%s: target OST is not defined, use 'device' " - "command\n", cmdname); - return -EINVAL; - } - - rc = pthread_attr_init(&attr); - if (rc) { - fprintf(stderr, "%s: pthread_attr_init:(%d) %s\n", - cmdname, rc, strerror(errno)); - return -errno; - } - pthread_attr_setstacksize (&attr, CLIENT_THREAD_STACK_SIZE); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - numt += live_threads; - i = live_threads; - printf("start %d to %d\n", i, numt); - while(!rc && !sig_received && (i < numt)) { - pthread_t thread; - - i++; - rc = pthread_create(&thread, &attr, run_one_child, - (void *)(long)i); - if (rc) { - fprintf(stderr, "%s: pthread: #%d - (%d) %s\n", - cmdname, i, rc, strerror(rc)); - break; - } - - /* give them slightly different start times */ - nanosleep(&ts, NULL); - } - - pthread_attr_destroy(&attr); - - return -rc; -} - -static int loadgen_target(int argc, char **argv) -{ - char *args[3]; - __u64 nidx = 0; - int rc = 0; - - if (argc < 2 || argc > 3) - return CMD_HELP; - - args[0] = cmdname; - - if (argc == 3) { - nidx = libcfs_str2nid(argv[2]); - if (nidx == LNET_NID_ANY) { - fprintf(stderr, "%s: invalid nid '%s'\n", - cmdname, argv[2]); - return -EINVAL; - } - } else { - /* Local device should be in list */ - args[1] = argv[1]; - rc = jt_obd_device(2, args); - if (rc) { - fprintf(stderr, "%s: local device '%s' doesn't " - "seem to exist. You must use obdfilter device " - "names like 'lustre-OST0000'. Use 'dl' to " - "list all devices.\n", - cmdname, argv[1]); - return -EINVAL; - } - - /* Use the first local nid */ - args[1] = (char *)(&nidx); - args[1][0] = 1; /* hack to get back first nid */ - rc = jt_ptl_list_nids(2, args); - if (rc) { - fprintf(stderr, "%s: can't get local nid (%d)\n", - cmdname, rc); - return rc; - } - } - if (strcmp(nid, libcfs_nid2str(nidx)) != 0) { - /* if new, do an add_uuid */ - sprintf(nid, "%s", libcfs_nid2str(nidx)); - - /* Fixme change the uuid for every new one */ - args[1] = "OSS_UUID"; - args[2] = nid; - rc = jt_lcfg_add_uuid(3, args); - if (rc) { - fprintf(stderr, "%s: can't add uuid '%s' (%d)\n", - cmdname, args[2], rc); - return rc; - } - } - - snprintf(target, sizeof(target), "%s", argv[1]); - printf("Target OST name is '%s'\n", target); - - return rc; -} - -static int loadgen_verbose(int argc, char **argv) -{ - if (argc != 2) - return CMD_HELP; - o_verbose = atoi(argv[1]); - printf("verbosity set to %d\n", o_verbose); - return 0; -} - -static int loadgen_write(int argc, char **argv) -{ - int threads; - - if (argc < 3 || argc > 4) - return CMD_HELP; - threads = atoi(argv[1]); - pthread_mutex_lock(&m_list); - if (threads > live_threads) { - pthread_mutex_unlock(&m_list); - fprintf(stderr, "requested %d threads but only %d are running. " - "Use 'start' to start some more.\n", - threads, live_threads); - return -EOVERFLOW; - } else { - pthread_mutex_unlock(&m_list); - } - trigger(C_WRITE, threads, atoi(argv[2]), - (argc == 4) ? atoi(argv[3]) : 0); - return 0; -} - -char ecsname[] = "echosrv"; -static int loadgen_stop_echosrv(int argc, char **argv) -{ - int verbose = (argc != 9); - if (my_oss) { - char name[]="OSS"; - cleanup(name, verbose); - my_oss = 0; - } - if (my_ecs || (argc == 9)) { - cleanup(ecsname, verbose); - my_ecs = 0; - } - return 0; -} - -static int loadgen_start_echosrv(int argc, char **argv) -{ - char *args[5]; - int rc; - - pthread_mutex_lock(&m_config); - - args[0] = cmdname; - - /* attach obdecho echosrv echosrv_UUID */ - args[1] = "obdecho"; - args[2] = args[3] = ecsname; - rc = jt_lcfg_attach(4, args); - if (rc) { - fprintf(stderr, "%s: can't attach echo server (%d)\n", - cmdname, rc); - /* Assume we want e.g. an old one cleaned anyhow. */ - goto clean; - } - my_ecs = 1; - - /* setup */ - rc = jt_lcfg_setup(1, args); - if (rc) { - fprintf(stderr, "%s: can't setup echo server (%d)\n", - cmdname, rc); - goto clean; - } - - /* Create an OSS to handle the communications */ - /* attach ost OSS OSS_UUID */ - args[1] = "ost"; - args[2] = args[3] = "OSS"; - - rc = jt_lcfg_attach(4, args); - if (rc == EEXIST) { - /* Already set up for somebody else, that's fine. */ - printf("OSS already set up, no problem.\n"); - pthread_mutex_unlock(&m_config); - return 0; - } - if (rc) { - fprintf(stderr, "%s: can't attach OSS (%d)\n", - cmdname, rc); - goto clean; - } - my_oss = 1; - - /* setup */ - rc = jt_lcfg_setup(1, args); - if (rc) { - fprintf(stderr, "%s: can't setup OSS (%d)\n", - cmdname, rc); - goto clean; - } - - pthread_mutex_unlock(&m_config); - return rc; - -clean: - pthread_mutex_unlock(&m_config); - loadgen_stop_echosrv(9, argv); - return rc; -} - -static int loadgen_wait(int argc, char **argv) -{ - /* Give scripts a chance to start some threads */ - sleep(1); - while (!all_done) { - sleep(1); - } - return 0; -} - -static int loadgen_init(int argc, char **argv) -{ - char *args[4]; - int rc; - - sprintf(cmdname, "%s", argv[0]); - - signal(SIGTERM, sig_master); - signal(SIGINT, sig_master); - - /* Test to make sure obdecho module is loaded */ - args[0] = cmdname; - args[1] = "echo_client"; - args[2] = args[3] = "ecc_test"; - rc = jt_lcfg_attach(4, args); - if (rc) { - fprintf(stderr, "%s: can't attach echo client (%d)\n", - cmdname, rc); - if (rc == ENODEV) - fprintf(stderr, "%s: is the obdecho module loaded?\n", - cmdname); - } else { - args[1] = args[2]; - jt_obd_detach(1, args); - } - - return rc; -} - -static int loadgen_exit() -{ - int rc; - - printf("stopping %d children\n", live_threads); - kill_kids(); - rc = wait_for_threads(); - - loadgen_stop_echosrv(0, NULL); - - return rc; -} - -/* libptlctl interface */ -static int loadgen_main(int argc, char **argv) -{ - int rc; - - setlinebuf(stdout); - /* without this threaded errors cause segfault */ - setlinebuf(stderr); - - if ((rc = ptl_initialize(argc, argv)) < 0) - exit(rc); - if ((rc = obd_initialize(argc, argv)) < 0) - exit(rc); - if ((rc = dbg_initialize(argc, argv)) < 0) - exit(rc); - - Parser_init("loadgen> ", cmdlist); - - rc = loadgen_init(argc, argv); - if (rc) - goto out; - - if (argc > 1) { - rc = Parser_execarg(argc - 1, argv + 1, cmdlist); - } else { - rc = Parser_commands(); - } - - rc = loadgen_exit(); - -out: - obd_finalize(argc, argv); - return rc < 0 ? -rc : rc; -} - -#ifndef LIBLUSTRE_TEST -int main (int argc, char **argv) -{ - int rc; - rc = loadgen_main(argc, argv); - pthread_exit((void *)(long)rc); - - return rc; -} -#endif -- 1.8.3.1