]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dlm: move lkb xarray lookup out of lock
authorAlexander Aring <aahringo@redhat.com>
Fri, 2 Aug 2024 17:26:46 +0000 (13:26 -0400)
committerDavid Teigland <teigland@redhat.com>
Thu, 8 Aug 2024 20:15:08 +0000 (15:15 -0500)
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: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/memory.c

index 0562099e60eba1c03ff1700df108d0bdaf8f6fc4..d534a4bc162bba382c5ffab2335d7f1284c7abfe 100644 (file)
@@ -295,6 +295,7 @@ struct dlm_lkb {
                void                    *lkb_astparam;  /* caller's ast arg */
                struct dlm_user_args    *lkb_ua;
        };
+       struct rcu_head         rcu;
 };
 
 /*
index 9d3ec359d5e3433245df4c8dd8d36ed6224d8405..865dc70a9dfc47f98fae8ac9e199e31fa03fbb84 100644 (file)
@@ -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)
-               kref_get(&lkb->lkb_ref);
-       read_unlock_bh(&ls->ls_lkbxa_lock);
+       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;
index 442898cf7185e030c0ad2434929e3ebd8d05fdfe..5c35cc67aca4c4dd4d3725ff108f99027a69d876 100644 (file)
@@ -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);