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

dlm: move lkb xarray lookup out of lock



This patch moves the xarray lookup functionality for the lkb out of the
ls_lkbxa_lock read lock handling. We can do that as the xarray should be
possible to access lockless in case of reader like xa_load(). We confirm
under ls_lkbxa_lock that the lkb is still part of the data structure and
take a reference when its still part of ls_lkbxa to avoid being freed
after doing the lookup. To do a check if the lkb is still part of the
ls_lkbxa data structure we use a kref_read() as the last put will remove
it from the ls_lkbxa data structure and any reference taken means it is
still part of ls_lkbxa.

A similar approach was done with the DLM rsb rhashtable just with a flag
instead of the refcounter because the refcounter has a slightly
different meaning.

Signed-off-by: default avatarAlexander Aring <aahringo@redhat.com>
Signed-off-by: default avatarDavid Teigland <teigland@redhat.com>
parent 5be323b0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -295,6 +295,7 @@ struct dlm_lkb {
		void			*lkb_astparam;	/* caller's ast arg */
		struct dlm_user_args	*lkb_ua;
	};
	struct rcu_head		rcu;
};

/*
+14 −4
Original line number Diff line number Diff line
@@ -1527,11 +1527,21 @@ static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
{
	struct dlm_lkb *lkb;

	read_lock_bh(&ls->ls_lkbxa_lock);
	rcu_read_lock();
	lkb = xa_load(&ls->ls_lkbxa, lkid);
	if (lkb)
	if (lkb) {
		/* check if lkb is still part of lkbxa under lkbxa_lock as
		 * the lkb_ref is tight to the lkbxa data structure, see
		 * __put_lkb().
		 */
		read_lock_bh(&ls->ls_lkbxa_lock);
		if (kref_read(&lkb->lkb_ref))
			kref_get(&lkb->lkb_ref);
		else
			lkb = NULL;
		read_unlock_bh(&ls->ls_lkbxa_lock);
	}
	rcu_read_unlock();

	*lkb_ret = lkb;
	return lkb ? 0 : -ENOENT;
+8 −1
Original line number Diff line number Diff line
@@ -115,8 +115,10 @@ struct dlm_lkb *dlm_allocate_lkb(void)
	return kmem_cache_zalloc(lkb_cache, GFP_ATOMIC);
}

void dlm_free_lkb(struct dlm_lkb *lkb)
static void __free_lkb_rcu(struct rcu_head *rcu)
{
	struct dlm_lkb *lkb = container_of(rcu, struct dlm_lkb, rcu);

	if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) {
		struct dlm_user_args *ua;
		ua = lkb->lkb_ua;
@@ -129,6 +131,11 @@ void dlm_free_lkb(struct dlm_lkb *lkb)
	kmem_cache_free(lkb_cache, lkb);
}

void dlm_free_lkb(struct dlm_lkb *lkb)
{
	call_rcu(&lkb->rcu, __free_lkb_rcu);
}

struct dlm_mhandle *dlm_allocate_mhandle(void)
{
	return kmem_cache_alloc(mhandle_cache, GFP_ATOMIC);