Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dlm: fix sleep in atomic context

This patch changes the orphans mutex to a spinlock since commit
c288745f1d4a ("dlm: avoid blocking receive at the end of recovery") is
using a rwlock_t to lock the DLM message receive path and do_purge() can
be called while this lock is held that forbids to sleep.

We need to use spin_lock_bh() because also a user context that calls
dlm_user_purge() can call do_purge() and since commit 92d59adfaf71
("dlm: do message processing in softirq context") the DLM message
receive path is done under softirq context.

Fixes: c288745f1d4a ("dlm: avoid blocking receive at the end of recovery")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/gfs2/9ad928eb-2ece-4ad9-a79c-d2bce228e4bc@moroto.mountain/
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>

authored by

Alexander Aring and committed by
David Teigland
7b012732 15fd7e55

+8 -8
+1 -1
fs/dlm/dlm_internal.h
··· 602 602 spinlock_t ls_waiters_lock; 603 603 struct list_head ls_waiters; /* lkbs needing a reply */ 604 604 605 - struct mutex ls_orphans_mutex; 605 + spinlock_t ls_orphans_lock; 606 606 struct list_head ls_orphans; 607 607 608 608 spinlock_t ls_new_rsb_spin;
+6 -6
fs/dlm/lock.c
··· 5880 5880 int found_other_mode = 0; 5881 5881 int rv = 0; 5882 5882 5883 - mutex_lock(&ls->ls_orphans_mutex); 5883 + spin_lock_bh(&ls->ls_orphans_lock); 5884 5884 list_for_each_entry(iter, &ls->ls_orphans, lkb_ownqueue) { 5885 5885 if (iter->lkb_resource->res_length != namelen) 5886 5886 continue; ··· 5897 5897 *lkid = iter->lkb_id; 5898 5898 break; 5899 5899 } 5900 - mutex_unlock(&ls->ls_orphans_mutex); 5900 + spin_unlock_bh(&ls->ls_orphans_lock); 5901 5901 5902 5902 if (!lkb && found_other_mode) { 5903 5903 rv = -EAGAIN; ··· 6089 6089 int error; 6090 6090 6091 6091 hold_lkb(lkb); /* reference for the ls_orphans list */ 6092 - mutex_lock(&ls->ls_orphans_mutex); 6092 + spin_lock_bh(&ls->ls_orphans_lock); 6093 6093 list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans); 6094 - mutex_unlock(&ls->ls_orphans_mutex); 6094 + spin_unlock_bh(&ls->ls_orphans_lock); 6095 6095 6096 6096 set_unlock_args(0, lkb->lkb_ua, &args); 6097 6097 ··· 6241 6241 { 6242 6242 struct dlm_lkb *lkb, *safe; 6243 6243 6244 - mutex_lock(&ls->ls_orphans_mutex); 6244 + spin_lock_bh(&ls->ls_orphans_lock); 6245 6245 list_for_each_entry_safe(lkb, safe, &ls->ls_orphans, lkb_ownqueue) { 6246 6246 if (pid && lkb->lkb_ownpid != pid) 6247 6247 continue; ··· 6249 6249 list_del_init(&lkb->lkb_ownqueue); 6250 6250 dlm_put_lkb(lkb); 6251 6251 } 6252 - mutex_unlock(&ls->ls_orphans_mutex); 6252 + spin_unlock_bh(&ls->ls_orphans_lock); 6253 6253 } 6254 6254 6255 6255 static int send_purge(struct dlm_ls *ls, int nodeid, int pid)
+1 -1
fs/dlm/lockspace.c
··· 436 436 INIT_LIST_HEAD(&ls->ls_waiters); 437 437 spin_lock_init(&ls->ls_waiters_lock); 438 438 INIT_LIST_HEAD(&ls->ls_orphans); 439 - mutex_init(&ls->ls_orphans_mutex); 439 + spin_lock_init(&ls->ls_orphans_lock); 440 440 441 441 INIT_LIST_HEAD(&ls->ls_new_rsb); 442 442 spin_lock_init(&ls->ls_new_rsb_spin);