From: pschwan Date: Mon, 12 Aug 2002 21:57:43 +0000 (+0000) Subject: - James Newsome's dlm stress test X-Git-Tag: 0.5.5~164 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=0371af6e8736a2ef7ee8b3a254e5f17a5b858bb0;p=fs%2Flustre-release.git - James Newsome's dlm stress test - Small warning fix in filter.c --- diff --git a/lustre/include/linux/lustre_dlm.h b/lustre/include/linux/lustre_dlm.h index f8b4c21..22b6553 100644 --- a/lustre/include/linux/lustre_dlm.h +++ b/lustre/include/linux/lustre_dlm.h @@ -287,7 +287,11 @@ void ldlm_reprocess_all(struct ldlm_resource *res); void ldlm_lock_dump(struct ldlm_lock *lock); /* ldlm_test.c */ -int ldlm_test(struct obd_device *device, struct ptlrpc_connection *conn); +int ldlm_test(struct obd_device *device, struct lustre_handle *connh); +int ldlm_regression_start(struct obd_device *obddev, + struct lustre_handle *connh, int count); +int ldlm_regression_stop(void); + /* resource.c */ struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 local); @@ -358,6 +362,8 @@ int mds_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, #define IOC_LDLM_TEST _IOWR('f', 40, long) #define IOC_LDLM_DUMP _IOWR('f', 41, long) -#define IOC_LDLM_MAX_NR 41 +#define IOC_LDLM_REGRESS_START _IOWR('f', 42, long) +#define IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long) +#define IOC_LDLM_MAX_NR 43 #endif diff --git a/lustre/ldlm/ldlm_lockd.c b/lustre/ldlm/ldlm_lockd.c index 0848a0f..457a420 100644 --- a/lustre/ldlm/ldlm_lockd.c +++ b/lustre/ldlm/ldlm_lockd.c @@ -414,7 +414,7 @@ static int ldlm_iocontrol(long cmd, struct lustre_handle *conn, int len, switch (cmd) { case IOC_LDLM_TEST: - err = ldlm_test(obddev, connection); + err = ldlm_test(obddev, conn); CERROR("-- done err %d\n", err); GOTO(out, err); case IOC_LDLM_DUMP: @@ -552,6 +552,8 @@ EXPORT_SYMBOL(ldlm_cli_cancel); EXPORT_SYMBOL(ldlm_match_or_enqueue); EXPORT_SYMBOL(ldlm_it2str); EXPORT_SYMBOL(ldlm_test); +EXPORT_SYMBOL(ldlm_regression_start); +EXPORT_SYMBOL(ldlm_regression_stop); EXPORT_SYMBOL(ldlm_lock_dump); EXPORT_SYMBOL(ldlm_namespace_new); EXPORT_SYMBOL(ldlm_namespace_free); diff --git a/lustre/ldlm/ldlm_test.c b/lustre/ldlm/ldlm_test.c index c0c8f13..f2d9f13 100644 --- a/lustre/ldlm/ldlm_test.c +++ b/lustre/ldlm/ldlm_test.c @@ -1,32 +1,87 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (C) 2002 Cluster File Systems, Inc. + * Copyright (c) 2002 Cluster File Systems, Inc. + * Copyright (c) 2002 Lawrence Livermore National Laboratory + * Author: James Newsome * - * This code is issued under the GNU General Public License. - * See the file COPYING in this distribution + * This file is part of Lustre, http://www.lustre.org. * - * by Cluster File Systems, Inc. + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DEBUG_SUBSYSTEM S_LDLM +#include #include #include #include struct ldlm_test_thread { + struct lustre_handle *connh; + struct obd_device *obddev; struct ldlm_namespace *t_ns; struct list_head t_link; - __u32 t_flags; + __u32 t_flags; wait_queue_head_t t_ctl_waitq; }; +struct ldlm_test_lock { + struct list_head l_link; + struct lustre_handle l_lockh; + ldlm_mode_t l_mode; +}; + +static const int max_locks = 10; + static spinlock_t ctl_lock = SPIN_LOCK_UNLOCKED; -static struct list_head ctl_threads; +/* protect these with the ctl_lock */ +static LIST_HEAD(ctl_threads); static int regression_running = 0; +static LIST_HEAD(lock_list); +static int num_locks = 0; + +/* cumulative stats for regression test */ +static atomic_t locks_requested = ATOMIC_INIT(0); +static atomic_t locks_granted = ATOMIC_INIT(0); +static atomic_t locks_matched = ATOMIC_INIT(0); + +/* + * blocking ast for regression test. + * Just cancels lock + */ +static int ldlm_test_blocking_ast(struct ldlm_lock *lock, + struct ldlm_lock_desc *new, + void *data, __u32 data_len) +{ + int rc; + struct lustre_handle lockh; + ENTRY; + + LDLM_DEBUG_NOLOCK("We're blocking. Cancelling lock"); + ldlm_lock2handle(lock, &lockh); + rc = ldlm_cli_cancel(&lockh); + if (rc < 0) { + CERROR("ldlm_cli_cancel: %d\n", rc); + LBUG(); + } + RETURN(0); +} + +/* blocking ast for basic tests. noop */ static int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *new, void *data, __u32 data_len) @@ -36,6 +91,74 @@ static int ldlm_blocking_ast(struct ldlm_lock *lock, RETURN(0); } +/* Completion ast for regression test. + * Does not sleep when blocked. + */ +static int ldlm_test_completion_ast(struct ldlm_lock *lock, int flags) +{ + + ENTRY; + + if (flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | + LDLM_FL_BLOCK_CONV)) { + /* Do nothing */ + LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock"); + ldlm_lock_dump(lock); + } else { + /* add to list of granted locks */ + struct ldlm_test_lock *lock_info; + + if (flags == LDLM_FL_WAIT_NOREPROC) { + atomic_inc(&locks_matched); + LDLM_DEBUG(lock, "lock matched"); + } else if (flags == LDLM_FL_LOCK_CHANGED) { + atomic_inc(&locks_granted); + LDLM_DEBUG(lock, "lock changed and granted"); + } else { + atomic_inc(&locks_granted); + LDLM_DEBUG(lock, "lock granted"); + } + + OBD_ALLOC(lock_info, sizeof(*lock_info)); + if (lock_info == NULL) { + LBUG(); + RETURN(-ENOMEM); + } + + ldlm_lock2handle(lock, &lock_info->l_lockh); + lock_info->l_mode = lock->l_granted_mode; + + spin_lock(&ctl_lock); + list_add_tail(&lock_info->l_link, &lock_list); + num_locks++; + + /* if we're over the max of granted locks, decref some */ + if (num_locks > max_locks) { + /* delete from list */ + lock_info = list_entry(lock_list.next, + struct ldlm_test_lock, l_link); + list_del(lock_list.next); + num_locks--; + spin_unlock(&ctl_lock); + + /* decrement and free the info + * Don't hold ctl_lock here. The decref + * may result in another lock being granted + * and hence this function being called again. + */ + LDLM_DEBUG_NOLOCK("Decrementing lock"); + ldlm_lock_decref(&lock_info->l_lockh, + lock_info->l_mode); + OBD_FREE(lock_info, sizeof(*lock_info)); + + spin_lock(&ctl_lock); + } + spin_unlock(&ctl_lock); + } + + RETURN(0); +} + int ldlm_test_basics(struct obd_device *obddev) { struct ldlm_namespace *ns; @@ -150,7 +273,7 @@ int ldlm_test_extents(struct obd_device *obddev) } static int ldlm_test_network(struct obd_device *obddev, - struct ptlrpc_connection *conn) + struct lustre_handle *connh) { __u64 res_id[RES_NAME_SIZE] = {1, 2, 3}; @@ -159,14 +282,18 @@ static int ldlm_test_network(struct obd_device *obddev, int flags = 0; ldlm_error_t err; - /* FIXME: this needs a connh as 3rd paramter, before it will work */ - - err = ldlm_cli_enqueue(NULL, NULL, obddev->obd_namespace, NULL, res_id, + err = ldlm_cli_enqueue(connh, NULL, obddev->obd_namespace, NULL, res_id, LDLM_EXTENT, &ext, sizeof(ext), LCK_PR, &flags, - NULL, NULL, NULL, 0, &lockh1); + ldlm_completion_ast, NULL, NULL, 0, &lockh1); + CERROR("ldlm_cli_enqueue: %d\n", err); + + flags = 0; + err = ldlm_cli_convert(&lockh1, LCK_EX, &flags); + CERROR("ldlm_cli_convert: %d\n", err); + if (err == ELDLM_OK) - ldlm_lock_decref(&lockh1, LCK_PR); + ldlm_lock_decref(&lockh1, LCK_EX); RETURN(err); } @@ -174,7 +301,8 @@ static int ldlm_test_network(struct obd_device *obddev, static int ldlm_test_main(void *data) { struct ldlm_test_thread *thread = data; - struct ldlm_namespace *ns; + const unsigned int num_resources = 10; + const unsigned int num_extent = 10; ENTRY; lock_kernel(); @@ -186,49 +314,71 @@ static int ldlm_test_main(void *data) sprintf(current->comm, "ldlm_test"); - ns = ldlm_namespace_new("ldlm_test", LDLM_NAMESPACE_CLIENT); - if (ns == NULL) { - LBUG(); - GOTO(out, -ENOMEM); - } - /* Record that the thread is running */ thread->t_flags |= SVC_RUNNING; wake_up(&thread->t_ctl_waitq); - while (1) { + while (!(thread->t_flags & SVC_STOPPING)) { struct lustre_handle lockh; __u64 res_id[3] = {0}; __u32 lock_mode; + struct ldlm_extent ext; char random; - int flags = 0, rc; + int flags = 0, rc = 0; - /* Pick a random resource from 1 to 10 */ + /* Pick a random resource from 1 to num_resources */ get_random_bytes(&random, sizeof(random)); - res_id[0] = random % 10 + 1; + res_id[0] = (unsigned char)random % num_resources; /* Pick a random lock mode */ get_random_bytes(&random, sizeof(random)); - lock_mode = random % LCK_NL + 1; + lock_mode = (unsigned char)random % LCK_NL + 1; - rc = ldlm_cli_enqueue(NULL, NULL, ns, NULL, - res_id, LDLM_PLAIN, NULL, 0, lock_mode, - &flags, ldlm_completion_ast, - ldlm_blocking_ast, NULL, 0, &lockh); + /* Pick a random extent */ + get_random_bytes(&random, sizeof(random)); + ext.start = (unsigned int)random % num_extent; + get_random_bytes(&random, sizeof(random)); + ext.end = (unsigned int)random % + (num_extent - (int)ext.start) + ext.start; + + LDLM_DEBUG_NOLOCK("about to enqueue with resource %d, mode %d," + " extent %d -> %d", (int)res_id[0], lock_mode, + (int)ext.start, (int)ext.end); + + rc = ldlm_match_or_enqueue(thread->connh, NULL, + thread->obddev->obd_namespace, NULL, + res_id, LDLM_EXTENT, &ext, + sizeof(ext), lock_mode, &flags, + ldlm_test_completion_ast, + ldlm_test_blocking_ast, NULL, 0, + &lockh); + + atomic_inc(&locks_requested); if (rc < 0) { CERROR("ldlm_cli_enqueue: %d\n", rc); LBUG(); } + + LDLM_DEBUG_NOLOCK("locks requested: %d, granted: %d, " + "matched: %d", + atomic_read(&locks_requested), + atomic_read(&locks_granted), + atomic_read(&locks_matched)); + + /* I think this may be necessary since we don't sleep + * after a lock being blocked + */ + schedule(); } - out: thread->t_flags |= SVC_STOPPED; wake_up(&thread->t_ctl_waitq); RETURN(0); } -static int ldlm_start_thread(void) +static int ldlm_start_thread(struct obd_device *obddev, + struct lustre_handle *connh) { struct ldlm_test_thread *test; int rc; @@ -241,6 +391,9 @@ static int ldlm_start_thread(void) } init_waitqueue_head(&test->t_ctl_waitq); + test->connh = connh; + test->obddev = obddev; + spin_lock(&ctl_lock); list_add(&test->t_link, &ctl_threads); spin_unlock(&ctl_lock); @@ -257,7 +410,7 @@ static int ldlm_start_thread(void) } int ldlm_regression_start(struct obd_device *obddev, - struct ptlrpc_connection *conn, int count) + struct lustre_handle *connh, int count) { int i, rc = 0; ENTRY; @@ -272,7 +425,7 @@ int ldlm_regression_start(struct obd_device *obddev, spin_unlock(&ctl_lock); for (i = 0; i < count; i++) { - rc = ldlm_start_thread(); + rc = ldlm_start_thread(obddev, connh); if (rc < 0) GOTO(cleanup, rc); } @@ -314,17 +467,18 @@ int ldlm_regression_stop(void) RETURN(0); } -int ldlm_test(struct obd_device *obddev, struct ptlrpc_connection *conn) +int ldlm_test(struct obd_device *obddev, struct lustre_handle *connh) { int rc; - rc = ldlm_test_basics(obddev); +/* rc = ldlm_test_basics(obddev); if (rc) RETURN(rc); rc = ldlm_test_extents(obddev); if (rc) RETURN(rc); +*/ - rc = ldlm_test_network(obddev, conn); + rc = ldlm_test_network(obddev, connh); RETURN(rc); } diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c index 79e30d7..efd5d8b 100644 --- a/lustre/obdecho/echo.c +++ b/lustre/obdecho/echo.c @@ -11,8 +11,8 @@ * by Peter Braam */ -static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.20 2002/08/07 21:46:32 shaver Exp $"; -#define OBDECHO_VERSION "$Revision: 1.20 $" +static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.21 2002/08/12 21:57:42 pschwan Exp $"; +#define OBDECHO_VERSION "$Revision: 1.21 $" #define EXPORT_SYMTAB @@ -32,6 +32,7 @@ static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.20 2002/08/07 21:4 #include #include #include +#include extern struct obd_device obd_dev[MAX_OBD_DEVICES]; static struct obdo OA; @@ -242,12 +243,26 @@ commitrw_cleanup: return rc; } +static int echo_setup(struct obd_device *obddev, obd_count len, void *buf) +{ + ENTRY; + + obddev->obd_namespace = + ldlm_namespace_new("echo-tgt", LDLM_NAMESPACE_SERVER); + if (obddev->obd_namespace == NULL) + LBUG(); + + RETURN(0); +} + + struct obd_ops echo_obd_ops = { o_connect: echo_connect, o_disconnect: echo_disconnect, o_getattr: echo_getattr, o_preprw: echo_preprw, o_commitrw: echo_commitrw, + o_setup: echo_setup }; static int __init obdecho_init(void) diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index f5e13b2..da49f47 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -724,9 +724,9 @@ static int filter_truncate(struct lustre_handle *conn, struct obdo *oa, } static int filter_pgcache_brw(int cmd, struct lustre_handle *conn, - struct lov_stripe_md *md, obd_count oa_bufs, - struct brw_page *pga, - brw_callback_t callback, void *data) + struct lov_stripe_md *md, obd_count oa_bufs, + struct brw_page *pga, brw_callback_t callback, + struct io_cb_data *data) { struct obd_run_ctxt saved; struct super_block *sb; diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 8cb4050..58500f6 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -693,6 +693,51 @@ static int osc_statfs(struct lustre_handle *conn, struct statfs *sfs) return rc; } +static int osc_iocontrol(long cmd, struct lustre_handle *conn, int len, + void *karg, void *uarg) +{ + struct obd_device *obddev = class_conn2obd(conn); + struct obd_ioctl_data *data = karg; + int err = 0; + ENTRY; + + if (_IOC_TYPE(cmd) != IOC_LDLM_TYPE || _IOC_NR(cmd) < + IOC_LDLM_MIN_NR || _IOC_NR(cmd) > IOC_LDLM_MAX_NR) { + CDEBUG(D_IOCTL, "invalid ioctl (type %ld, nr %ld, size %ld)\n", + _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); + RETURN(-EINVAL); + } + + switch (cmd) { + case IOC_LDLM_TEST: { + err = ldlm_test(obddev, conn); + CERROR("-- done err %d\n", err); + GOTO(out, err); + } + case IOC_LDLM_REGRESS_START: { + unsigned int numthreads; + + if (data->ioc_inllen1) + numthreads = simple_strtoul(data->ioc_inlbuf1, NULL, 0); + else + numthreads = 1; + + err = ldlm_regression_start(obddev, conn, numthreads); + CERROR("-- done err %d\n", err); + GOTO(out, err); + } + case IOC_LDLM_REGRESS_STOP: { + err = ldlm_regression_stop(); + CERROR("-- done err %d\n", err); + GOTO(out, err); + } + default: + GOTO(out, err = -EINVAL); + } +out: + return err; +} + struct obd_ops osc_obd_ops = { o_setup: client_obd_setup, o_cleanup: client_obd_cleanup, @@ -708,7 +753,8 @@ struct obd_ops osc_obd_ops = { o_brw: osc_brw, o_punch: osc_punch, o_enqueue: osc_enqueue, - o_cancel: osc_cancel + o_cancel: osc_cancel, + o_iocontrol: osc_iocontrol }; static int __init osc_init(void) diff --git a/lustre/tests/lldlm.sh b/lustre/tests/lldlm.sh index 6c575e1..3aac610 100755 --- a/lustre/tests/lldlm.sh +++ b/lustre/tests/lldlm.sh @@ -4,10 +4,24 @@ SRCDIR="`dirname $0`/" . $SRCDIR/common.sh export DEBUG_WAIT=yes -. $SRCDIR/llsetup.sh $SRCDIR/net-local.cfg $SRCDIR/ldlm.cfg || exit 2 +. $SRCDIR/llsetup.sh $SRCDIR/net-local.cfg $SRCDIR/ldlm.cfg $SRCDIR/obdecho.cfg $SRCDIR/client-echo.cfg || exit 2 -$OBDCTL < [write [verbose [pages [obdos]]]]"}, {"test_ldlm", jt_obd_test_ldlm, 0, "perform lock manager test\n" "usage: test_ldlm"}, + {"ldlm_regress_start", jt_obd_ldlm_regress_start, 0, + "start lock manager stress test (usage: ldlm_regress_start " + "[numthreads])\n"}, + {"ldlm_regress_stop", jt_obd_ldlm_regress_stop, 0, + "stop lock manager stress test (no args)\n"}, {"dump_ldlm", jt_obd_dump_ldlm, 0, "dump all lock manager state (no args)"}, diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index c63d950..7c628d3 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -1170,6 +1170,56 @@ int jt_obd_dump_ldlm(int argc, char **argv) return rc; } +int jt_obd_ldlm_regress_start(int argc, char **argv) +{ + int rc; + struct obd_ioctl_data data; + + IOCINIT(data); + + if (argc > 2) { + fprintf(stderr, "usage: %s [numthreads]\n", cmdname(argv[0])); + return 1; + } else if (argc == 2) { + data.ioc_inllen1 = strlen(argv[1]) + 1; + data.ioc_inlbuf1 = argv[1]; + } else { + data.ioc_inllen1 = 0; + } + + if (obd_ioctl_pack(&data, &buf, max)) { + fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0])); + return -2; + } + + rc = ioctl(fd, IOC_LDLM_REGRESS_START, buf); + + if (rc) + fprintf(stderr, "error: %s: test failed: %s\n", + cmdname(argv[0]), strerror(rc = errno)); + + return rc; +} + +int jt_obd_ldlm_regress_stop(int argc, char **argv) +{ + int rc; + struct obd_ioctl_data data; + IOCINIT(data); + + if (argc != 1) { + fprintf(stderr, "usage: %s\n", cmdname(argv[0])); + return 1; + } + + rc = ioctl(fd, IOC_LDLM_REGRESS_STOP, &data); + + if (rc) + fprintf(stderr, "error: %s: test failed: %s\n", + cmdname(argv[0]), strerror(rc = errno)); + return rc; +} + int jt_obd_newconn(int argc, char **argv) { int rc; diff --git a/lustre/utils/obdctl.h b/lustre/utils/obdctl.h index c075261..eb907b9 100644 --- a/lustre/utils/obdctl.h +++ b/lustre/utils/obdctl.h @@ -51,6 +51,8 @@ int jt_obd_test_getattr(int argc, char **argv); int jt_obd_test_brw(int argc, char **argv); int jt_obd_lov_config(int argc, char **argv); int jt_obd_test_ldlm(int argc, char **argv); +int jt_obd_ldlm_regress_start(int argc, char **argv); +int jt_obd_ldlm_regress_stop(int argc, char **argv); int jt_obd_dump_ldlm(int argc, char **argv); int jt_obd_newconn(int argc, char **argv);