From: pschwan Date: Sat, 9 Nov 2002 19:40:59 +0000 (+0000) Subject: the first try at lock LRU X-Git-Tag: v1_7_100~4263 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=4d029e817e4cb9cd376e5326f68440d331070f13;hp=d4eaef32c0e7b686806b4a1b32f07dee54ea690c;p=fs%2Flustre-release.git the first try at lock LRU --- diff --git a/lustre/ChangeLog b/lustre/ChangeLog index ad23c1d..ac05e5c 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -1,6 +1,9 @@ TBD * version TBD * bug fixes + - fix null d_it dereference (346) + - fix full OST/dbench hang (333) + - fix permission problem with file removal (286) - fix removal of OSCs from LOV when they fail - fix NULL deref during bulk timeout (214) - fix problems related to multiple filesystems on one MDS (241) @@ -12,6 +15,7 @@ TBD - data locks weren't cancelled at clear_inode time (290, 311) - intent locks could lead to unbounded lock growth (205) * protocol change + - Add capability to MDS protocol - LDLM cancellations and callbacks on different portals 2002-10-28 Andreas Dilger diff --git a/lustre/include/linux/lustre_dlm.h b/lustre/include/linux/lustre_dlm.h index b60032c..cc2c268 100644 --- a/lustre/include/linux/lustre_dlm.h +++ b/lustre/include/linux/lustre_dlm.h @@ -44,6 +44,7 @@ typedef enum { #define LDLM_FL_LOCAL_ONLY (1 << 11) /* see ldlm_cli_cancel_unused */ #define LDLM_FL_NO_CALLBACK (1 << 12) /* see ldlm_cli_cancel_unused */ #define LDLM_FL_HAS_INTENT (1 << 13) /* lock request has intent */ +#define LDLM_FL_REDUCE (1 << 14) /* throw away unused locks */ #define LDLM_CB_BLOCKING 1 #define LDLM_CB_CANCELING 2 @@ -102,6 +103,10 @@ struct ldlm_namespace { struct list_head ns_list_chain; /* position in global NS list */ struct proc_dir_entry *ns_proc_dir; + struct list_head ns_unused_list; /* all root resources in ns */ + unsigned int ns_nr_unused; + unsigned int ns_max_unused; + spinlock_t ns_counter_lock; __u64 ns_locks; __u64 ns_resources; @@ -132,6 +137,7 @@ struct ldlm_lock { struct ldlm_lock *l_parent; struct list_head l_children; struct list_head l_childof; + struct list_head l_lru; struct list_head l_res_link; /*position in one of three res lists*/ struct list_head l_export_chain; /* per-export chain of locks */ struct list_head l_pending_chain; /* locks with callbacks pending*/ diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 5798d6e..6ac4a4a 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -215,6 +215,7 @@ void ldlm_lock_destroy(struct ldlm_lock *lock) return; } + list_del_init(&lock->l_lru); list_del(&lock->l_export_chain); lock->l_export = NULL; lock->l_flags |= LDLM_FL_DESTROYED; @@ -258,6 +259,7 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent, lock->l_refc = 1; INIT_LIST_HEAD(&lock->l_children); INIT_LIST_HEAD(&lock->l_res_link); + INIT_LIST_HEAD(&lock->l_lru); INIT_LIST_HEAD(&lock->l_export_chain); INIT_LIST_HEAD(&lock->l_pending_chain); init_waitqueue_head(&lock->l_waitq); @@ -435,6 +437,13 @@ void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode) void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode) { l_lock(&lock->l_resource->lr_namespace->ns_lock); + + if (!list_empty(&lock->l_lru)) { + list_del_init(&lock->l_lru); + lock->l_resource->lr_namespace->ns_nr_unused--; + LASSERT(lock->l_resource->lr_namespace->ns_nr_unused >= 0); + } + if (mode == LCK_NL || mode == LCK_CR || mode == LCK_PR) lock->l_readers++; else @@ -445,15 +454,20 @@ void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode) } /* Args: unlocked lock */ +int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, + __u64 *res_id, int flags); + void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode) { struct ldlm_lock *lock = __ldlm_handle2lock(lockh, 0); + struct ldlm_namespace *ns; ENTRY; if (lock == NULL) LBUG(); LDLM_DEBUG(lock, "ldlm_lock_decref(%s)", ldlm_lockname[mode]); + ns = lock->l_resource->lr_namespace; l_lock(&lock->l_resource->lr_namespace->ns_lock); if (mode == LCK_NL || mode == LCK_CR || mode == LCK_PR) lock->l_readers--; @@ -475,6 +489,18 @@ void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode) /* FIXME: need a real 'desc' here */ lock->l_blocking_ast(lock, NULL, lock->l_data, lock->l_data_len, LDLM_CB_BLOCKING); + } else if (!lock->l_readers && !lock->l_writers) { + LASSERT(list_empty(&lock->l_lru)); + LASSERT(ns->ns_nr_unused >= 0); + list_add_tail(&lock->l_lru, &ns->ns_unused_list); + ns->ns_nr_unused++; + if (ns->ns_client && ns->ns_nr_unused >= ns->ns_max_unused) { + CDEBUG(D_DLMTRACE, "%d unused (max %d), cancelling " + "LRU\n", ns->ns_nr_unused, ns->ns_max_unused); + ldlm_cli_cancel_unused_resource + (ns, lock->l_resource->lr_name, LDLM_FL_REDUCE); + } + l_unlock(&lock->l_resource->lr_namespace->ns_lock); } else l_unlock(&lock->l_resource->lr_namespace->ns_lock); diff --git a/lustre/ldlm/ldlm_request.c b/lustre/ldlm/ldlm_request.c index c4089bf..7aa9694 100644 --- a/lustre/ldlm/ldlm_request.c +++ b/lustre/ldlm/ldlm_request.c @@ -492,14 +492,18 @@ int ldlm_cli_cancel(struct lustre_handle *lockh) return rc; } -static int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, - __u64 *res_id, int flags) +int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, + __u64 *res_id, int flags) { struct ldlm_resource *res; struct list_head *tmp, *next, list = LIST_HEAD_INIT(list); struct ldlm_ast_work *w; ENTRY; + if ((flags & LDLM_FL_REDUCE) && + ns->ns_max_unused > ns->ns_nr_unused) + RETURN(0); + res = ldlm_resource_get(ns, NULL, res_id, 0, 0); if (res == NULL) { /* This is not a problem. */ @@ -522,11 +526,14 @@ static int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, * won't see this flag and call l_blocking_ast */ lock->l_flags |= LDLM_FL_CBPENDING; - OBD_ALLOC(w, sizeof(*w)); + OBD_ALLOC(w, sizeof(*w)); LASSERT(w); w->w_lock = LDLM_LOCK_GET(lock); list_add(&w->w_list, &list); + if ((flags & LDLM_FL_REDUCE) && + ns->ns_max_unused > ns->ns_nr_unused) + break; } l_unlock(&ns->ns_lock); diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index 8b850df..494b74e 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -52,6 +52,7 @@ static int ldlm_proc_ll_rd(char *page, char **start, off_t off, return len; } +#define LDLM_MAX_UNUSED 20 struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client) { struct ldlm_namespace *ns = NULL; @@ -90,6 +91,10 @@ struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client) bucket--) INIT_LIST_HEAD(bucket); + INIT_LIST_HEAD(&ns->ns_unused_list); + ns->ns_nr_unused = 0; + ns->ns_max_unused = LDLM_MAX_UNUSED; + spin_lock(&ldlm_namespace_lock); list_add(&ns->ns_list_chain, &ldlm_namespace_list); spin_unlock(&ldlm_namespace_lock); diff --git a/lustre/tests/ba-mount.sh b/lustre/tests/ba-mount.sh new file mode 100644 index 0000000..fe0a8e2 --- /dev/null +++ b/lustre/tests/ba-mount.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# There are configurations for three machines in this config file: the OST, +# the MDS/client, other clients +# +# To start your cluster using the ba-mount.xml file that this produces, first +# run: +# > lconf ba-mount.xml +# on the MDS/client, and then run: +# > lconf --node client ba-mount.xml +# on any other clients. + +config=${1:-ba-mount.xml} + +LMC="save_cmd" +LMC_REAL="../../lustre/utils/lmc -m $config" + +PORT=2432 +TCPBUF=1048576 +OST=ba-ost-1 +MDS=mds-hostname + +UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt} + +h2ip () { + echo "${1}" +} +BATCH=/tmp/lmc-batch.$$ +save_cmd() { + echo "$@" >> $BATCH +} + +[ -f $config ] && rm $config + +# MDS/client node +${LMC} --node $MDS --tcpbuf $TCPBUF --net '*' tcp $PORT +${LMC} --node $MDS --mds mds1 /tmp/mds1 50000 + +OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST` +[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID" + +# server node +${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp $PORT +${LMC} --node $OST $OBD_UUID --ost bluearc + +# mount point on the MDS/client +${LMC} --node $MDS --mtpt /mnt/lustre mds1 OSC_$OST + +# other clients +${LMC} --node client --tcpbuf $TCPBUF --net '*' tcp $PORT +${LMC} --node client --mtpt /mnt/lustre mds1 OSC_$OST + +$LMC_REAL --batch $BATCH +rm -f $BATCH diff --git a/lustre/tests/runtests b/lustre/tests/runtests index 5c80ea5..28288aa 100755 --- a/lustre/tests/runtests +++ b/lustre/tests/runtests @@ -89,6 +89,8 @@ done [ "$ERROR" ] && fail "old and new files are different" $ERROR cleanup || exit 19 +sync + $LCONF $OPTS || exit 20 echo "comparing previously copied files" @@ -100,6 +102,7 @@ done [ "$ERROR" ] && fail "old and new files are different on second diff" $ERROR cleanup || exit 29 +sync $LCONF $OPTS || exit 30 echo "renaming $HOSTS.ren to $HOSTS" @@ -118,3 +121,4 @@ if [ $NOWUSED -gt $USED ]; then fi cleanup $OPTS || exit 29 +sync