summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-08-12 17:10:42 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-08-14 12:28:45 -0400
commit0e474135ce7b8e885e32d0c3adc49b96bad17cd7 (patch)
tree8446b58fa9844311a77e5eea7b1d7174a9e00bb3
parent6547d0e7f0d9540434b74d26fac1f45f93e2b2e8 (diff)
bcachefs: six locks: Guard against wakee exiting in __six_lock_wakeup()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/six.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/bcachefs/six.c b/fs/bcachefs/six.c
index b6ca53c85249..14cffa68d722 100644
--- a/fs/bcachefs/six.c
+++ b/fs/bcachefs/six.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/sched/rt.h>
+#include <linux/sched/task.h>
#include <linux/slab.h>
#include <trace/events/lock.h>
@@ -223,7 +224,12 @@ again:
if (ret <= 0)
goto unlock;
- task = w->task;
+ /*
+ * Similar to percpu_rwsem_wake_function(), we need to guard
+ * against the wakee noticing w->lock_acquired, returning, and
+ * then exiting before we do the wakeup:
+ */
+ task = get_task_struct(w->task);
__list_del(w->list.prev, w->list.next);
/*
* The release barrier here ensures the ordering of the
@@ -234,6 +240,7 @@ again:
*/
smp_store_release(&w->lock_acquired, true);
wake_up_process(task);
+ put_task_struct(task);
}
six_clear_bitmask(lock, SIX_LOCK_WAITING_read << lock_type);