This patch fixes the following sparse warning: warning: context imbalance in '__put_lkb' - unexpected unlock
it does this by unlock the ls_lkbidr_spin lock inside of the release functionality of kref_put_lock() and do a __releases() annotation at the release function. The kref_put_lock() for __put_lkb() has a special requirement to pass an additional dlm_ls pointer to the release callback, this is done by providing an own implementation of kref_put_lock() that is named dlm_kref_put_lock() and can pass an additional parameter. Signed-off-by: Alexander Aring <aahri...@redhat.com> --- fs/dlm/lock.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index dac7eb75dba9..4b5cff76d376 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -1256,7 +1256,8 @@ static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret) return lkb ? 0 : -ENOENT; } -static void kill_lkb(struct kref *kref) +static void kill_lkb(struct kref *kref, struct dlm_ls *ls) + __releases(&ls->ls_lkbidr_spin) { struct dlm_lkb *lkb = container_of(kref, struct dlm_lkb, lkb_ref); @@ -1264,6 +1265,29 @@ static void kill_lkb(struct kref *kref) can release the write_lock before the detach_lkb */ DLM_ASSERT(!lkb->lkb_status, dlm_print_lkb(lkb);); + + idr_remove(&ls->ls_lkbidr, lkb->lkb_id); + spin_unlock(&ls->ls_lkbidr_spin); + + detach_lkb(lkb); + + /* for local/process lkbs, lvbptr points to caller's lksb */ + if (lkb->lkb_lvbptr && is_master_copy(lkb)) + dlm_free_lvb(lkb->lkb_lvbptr); + dlm_free_lkb(lkb); +} + +static inline int dlm_kref_put_lock(struct kref *kref, + void (*release)(struct kref *kref, + struct dlm_ls *ls), + spinlock_t *lock, + struct dlm_ls *ls) +{ + if (refcount_dec_and_lock(&kref->refcount, lock)) { + release(kref, ls); + return 1; + } + return 0; } /* __put_lkb() is used when an lkb may not have an rsb attached to @@ -1271,24 +1295,8 @@ static void kill_lkb(struct kref *kref) static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb) { - uint32_t lkid = lkb->lkb_id; - int rv; - - rv = kref_put_lock(&lkb->lkb_ref, kill_lkb, - &ls->ls_lkbidr_spin); - if (rv) { - idr_remove(&ls->ls_lkbidr, lkid); - spin_unlock(&ls->ls_lkbidr_spin); - - detach_lkb(lkb); - - /* for local/process lkbs, lvbptr points to caller's lksb */ - if (lkb->lkb_lvbptr && is_master_copy(lkb)) - dlm_free_lvb(lkb->lkb_lvbptr); - dlm_free_lkb(lkb); - } - - return rv; + return dlm_kref_put_lock(&lkb->lkb_ref, kill_lkb, + &ls->ls_lkbidr_spin, ls); } int dlm_put_lkb(struct dlm_lkb *lkb) -- 2.31.1