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)
- 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 <adilger@clusterfs.com>
#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
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;
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*/
return;
}
+ list_del_init(&lock->l_lru);
list_del(&lock->l_export_chain);
lock->l_export = NULL;
lock->l_flags |= LDLM_FL_DESTROYED;
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);
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
}
/* 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--;
/* 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);
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. */
* 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);
return len;
}
+#define LDLM_MAX_UNUSED 20
struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client)
{
struct ldlm_namespace *ns = NULL;
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);
--- /dev/null
+#!/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
[ "$ERROR" ] && fail "old and new files are different" $ERROR
cleanup || exit 19
+sync
+
$LCONF $OPTS || exit 20
echo "comparing previously copied files"
[ "$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"
fi
cleanup $OPTS || exit 29
+sync