six locks: Add start_time to six_lock_waiter
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 24 Sep 2022 05:33:13 +0000 (01:33 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:41 +0000 (17:09 -0400)
This is needed by the cycle detector in bcachefs - we need a way to
iterater over waitlist entries while dropping and retaking the waitlist
lock.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/six.c
fs/bcachefs/six.h

index 82e8d77c3082f2ffb52bfcac00b6b4025b811e84..e2cebd3ba5fed5818c34a4b46298f92050d583c2 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/preempt.h>
 #include <linux/rcupdate.h>
 #include <linux/sched.h>
+#include <linux/sched/clock.h>
 #include <linux/sched/rt.h>
 #include <linux/slab.h>
 
@@ -466,6 +467,17 @@ static int __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type ty
        raw_spin_lock(&lock->wait_lock);
        if (!(lock->state.waiters & (1 << type)))
                set_bit(waitlist_bitnr(type), (unsigned long *) &lock->state.v);
+       wait->start_time = local_clock();
+
+       if (!list_empty(&lock->wait_list)) {
+               struct six_lock_waiter *last =
+                       list_last_entry(&lock->wait_list,
+                               struct six_lock_waiter, list);
+
+               if (time_before_eq64(wait->start_time, last->start_time))
+                       wait->start_time = last->start_time + 1;
+       }
+
        list_add_tail(&wait->list, &lock->wait_list);
        raw_spin_unlock(&lock->wait_lock);
 
@@ -503,6 +515,8 @@ static int __six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type
 {
        int ret;
 
+       wait->start_time = 0;
+
        if (type != SIX_LOCK_write)
                six_acquire(&lock->dep_map, 0);
 
index ab06773e80947fb12da0d4a2cb8cf977abc909b5..757f8aa4d3393410840a9a1215645826c25f6cec 100644 (file)
@@ -126,6 +126,7 @@ struct six_lock_waiter {
        struct list_head        list;
        struct task_struct      *task;
        enum six_lock_type      lock_want;
+       u64                     start_time;
 };
 
 typedef int (*six_lock_should_sleep_fn)(struct six_lock *lock, void *);