Commit 5be323b0 authored by Alexander Aring's avatar Alexander Aring Committed by David Teigland
Browse files

dlm: move dlm_search_rsb_tree() out of lock



The rhashtable structure is lockless for readers such as
rhashtable_lookup_fast(). It should be save to call this lookup
functionality out of holding ls_rsbtbl_lock to get the rsb pointer out
of the hash. This reduce the contention time of ls_rsbtbl_lock in some
cases. We still need to check if the rsb is part of the check as this
state can be changed while ls_rsbtbl_lock is not held. If its part of
the rhashtable data structure we take a reference to be sure it will not
be freed after we drop the ls_rsbtbl_lock read lock.

Signed-off-by: default avatarAlexander Aring <aahringo@redhat.com>
Signed-off-by: default avatarDavid Teigland <teigland@redhat.com>
parent 98ff7d95
Loading
Loading
Loading
Loading
+47 −30
Original line number Diff line number Diff line
@@ -733,11 +733,13 @@ static int find_rsb_dir(struct dlm_ls *ls, const void *name, int len,
	}

 retry:
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (error)
		goto do_new;

	/* check if the rsb is active under read lock - likely path */
	read_lock_bh(&ls->ls_rsbtbl_lock);
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (error) {
	if (!rsb_flag(r, RSB_HASHED)) {
		read_unlock_bh(&ls->ls_rsbtbl_lock);
		goto do_new;
	}
@@ -918,11 +920,13 @@ static int find_rsb_nodir(struct dlm_ls *ls, const void *name, int len,
	int error;

 retry:
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (error)
		goto do_new;

	/* check if the rsb is in active state under read lock - likely path */
	read_lock_bh(&ls->ls_rsbtbl_lock);
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (error) {
	if (!rsb_flag(r, RSB_HASHED)) {
		read_unlock_bh(&ls->ls_rsbtbl_lock);
		goto do_new;
	}
@@ -1276,11 +1280,17 @@ static int _dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *na
	}

 retry:
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (error)
		goto not_found;

	/* check if the rsb is active under read lock - likely path */
	read_lock_bh(&ls->ls_rsbtbl_lock);
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (!error) {
	if (!rsb_flag(r, RSB_HASHED)) {
		read_unlock_bh(&ls->ls_rsbtbl_lock);
		goto not_found;
	}

	if (rsb_flag(r, RSB_INACTIVE)) {
		read_unlock_bh(&ls->ls_rsbtbl_lock);
		goto do_inactive;
@@ -1302,10 +1312,6 @@ static int _dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *na
	put_rsb(r);

	return 0;
	} else {
		read_unlock_bh(&ls->ls_rsbtbl_lock);
		goto not_found;
	}

 do_inactive:
	/* unlikely path - check if still part of ls_rsbtbl */
@@ -1403,14 +1409,14 @@ void dlm_dump_rsb_name(struct dlm_ls *ls, const char *name, int len)
	struct dlm_rsb *r = NULL;
	int error;

	read_lock_bh(&ls->ls_rsbtbl_lock);
	rcu_read_lock();
	error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (!error)
		goto out;

	dlm_dump_rsb(r);
 out:
	read_unlock_bh(&ls->ls_rsbtbl_lock);
	rcu_read_unlock();
}

static void deactivate_rsb(struct kref *kref)
@@ -4309,16 +4315,27 @@ static void receive_remove(struct dlm_ls *ls, const struct dlm_message *ms)
	memset(name, 0, sizeof(name));
	memcpy(name, ms->m_extra, len);

	write_lock_bh(&ls->ls_rsbtbl_lock);

	rcu_read_lock();
	rv = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
	if (rv) {
		rcu_read_unlock();
		/* should not happen */
		log_error(ls, "%s from %d not found %s", __func__,
			  from_nodeid, name);
		return;
	}

	write_lock_bh(&ls->ls_rsbtbl_lock);
	if (!rsb_flag(r, RSB_HASHED)) {
		rcu_read_unlock();
		write_unlock_bh(&ls->ls_rsbtbl_lock);
		/* should not happen */
		log_error(ls, "%s from %d got removed during removal %s",
			  __func__, from_nodeid, name);
		return;
	}
	/* at this stage the rsb can only being freed here */
	rcu_read_unlock();

	if (!rsb_flag(r, RSB_INACTIVE)) {
		if (r->res_master_nodeid != from_nodeid) {