diff options
Diffstat (limited to '')
-rw-r--r-- | fs/dlm/lock.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 9d3ec359d5e3..865dc70a9dfc 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -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; |