summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAlexander Aring <aahringo@redhat.com>2022-08-15 15:43:14 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-10-26 13:25:08 +0200
commit0b2d8e4db40c44d4bfe7c8819888f6299f7c0a54 (patch)
treeda5ea95f28651c226ca6876026df5e4efea55dae /fs
parent057d5838c795cccde749536daad61f0db251d697 (diff)
downloadlinux-0b2d8e4db40c44d4bfe7c8819888f6299f7c0a54.tar.gz
linux-0b2d8e4db40c44d4bfe7c8819888f6299f7c0a54.tar.bz2
linux-0b2d8e4db40c44d4bfe7c8819888f6299f7c0a54.zip
fs: dlm: fix race between test_bit() and queue_work()
commit eef6ec9bf390e836a6c4029f3620fe49528aa1fe upstream. This patch fixes a race by using ls_cb_mutex around the bit operations and conditional code blocks for LSFL_CB_DELAY. The function dlm_callback_stop() expects to stop all callbacks and flush all currently queued onces. The set_bit() is not enough because there can still be queue_work() after the workqueue was flushed. To avoid queue_work() after set_bit(), surround both by ls_cb_mutex. Cc: stable@vger.kernel.org Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/dlm/ast.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 283c7b94edda..ca06069e95c8 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -198,13 +198,13 @@ void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
if (!prev_seq) {
kref_get(&lkb->lkb_ref);
+ mutex_lock(&ls->ls_cb_mutex);
if (test_bit(LSFL_CB_DELAY, &ls->ls_flags)) {
- mutex_lock(&ls->ls_cb_mutex);
list_add(&lkb->lkb_cb_list, &ls->ls_cb_delay);
- mutex_unlock(&ls->ls_cb_mutex);
} else {
queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
}
+ mutex_unlock(&ls->ls_cb_mutex);
}
out:
mutex_unlock(&lkb->lkb_cb_mutex);
@@ -284,7 +284,9 @@ void dlm_callback_stop(struct dlm_ls *ls)
void dlm_callback_suspend(struct dlm_ls *ls)
{
+ mutex_lock(&ls->ls_cb_mutex);
set_bit(LSFL_CB_DELAY, &ls->ls_flags);
+ mutex_unlock(&ls->ls_cb_mutex);
if (ls->ls_callback_wq)
flush_workqueue(ls->ls_callback_wq);