bcachefs: bch2_kthread_io_clock_wait_once()
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 24 May 2025 19:24:00 +0000 (15:24 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 27 May 2025 04:02:44 +0000 (00:02 -0400)
Add a version of bch2_kthread_io_clock_wait() that only schedules once -
behaving more like schedule_timeout().

This will be used for fixing rebalance wakeups.

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

index d6dd12d74d4f6cc1d20f1c786bc2e0a5f5a913f2..8e9264b5a84e3d3eece97eb6567a8cd79cd3d5fc 100644 (file)
@@ -53,7 +53,6 @@ void bch2_io_timer_del(struct io_clock *clock, struct io_timer *timer)
 
 struct io_clock_wait {
        struct io_timer         io_timer;
-       struct timer_list       cpu_timer;
        struct task_struct      *task;
        int                     expired;
 };
@@ -67,15 +66,6 @@ static void io_clock_wait_fn(struct io_timer *timer)
        wake_up_process(wait->task);
 }
 
-static void io_clock_cpu_timeout(struct timer_list *timer)
-{
-       struct io_clock_wait *wait = container_of(timer,
-                               struct io_clock_wait, cpu_timer);
-
-       wait->expired = 1;
-       wake_up_process(wait->task);
-}
-
 void bch2_io_clock_schedule_timeout(struct io_clock *clock, u64 until)
 {
        struct io_clock_wait wait = {
@@ -90,8 +80,8 @@ void bch2_io_clock_schedule_timeout(struct io_clock *clock, u64 until)
        bch2_io_timer_del(clock, &wait.io_timer);
 }
 
-void bch2_kthread_io_clock_wait(struct io_clock *clock,
-                               u64 io_until, unsigned long cpu_timeout)
+unsigned long bch2_kthread_io_clock_wait_once(struct io_clock *clock,
+                                    u64 io_until, unsigned long cpu_timeout)
 {
        bool kthread = (current->flags & PF_KTHREAD) != 0;
        struct io_clock_wait wait = {
@@ -103,27 +93,26 @@ void bch2_kthread_io_clock_wait(struct io_clock *clock,
 
        bch2_io_timer_add(clock, &wait.io_timer);
 
-       timer_setup_on_stack(&wait.cpu_timer, io_clock_cpu_timeout, 0);
-
-       if (cpu_timeout != MAX_SCHEDULE_TIMEOUT)
-               mod_timer(&wait.cpu_timer, cpu_timeout + jiffies);
-
-       do {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (kthread && kthread_should_stop())
-                       break;
-
-               if (wait.expired)
-                       break;
-
-               schedule();
+       set_current_state(TASK_INTERRUPTIBLE);
+       if (!(kthread && kthread_should_stop())) {
+               cpu_timeout = schedule_timeout(cpu_timeout);
                try_to_freeze();
-       } while (0);
+       }
 
        __set_current_state(TASK_RUNNING);
-       timer_delete_sync(&wait.cpu_timer);
-       destroy_timer_on_stack(&wait.cpu_timer);
        bch2_io_timer_del(clock, &wait.io_timer);
+       return cpu_timeout;
+}
+
+void bch2_kthread_io_clock_wait(struct io_clock *clock,
+                               u64 io_until, unsigned long cpu_timeout)
+{
+       bool kthread = (current->flags & PF_KTHREAD) != 0;
+
+       while (!(kthread && kthread_should_stop()) &&
+              cpu_timeout &&
+              atomic64_read(&clock->now) < io_until)
+               cpu_timeout = bch2_kthread_io_clock_wait_once(clock, io_until, cpu_timeout);
 }
 
 static struct io_timer *get_expired_timer(struct io_clock *clock, u64 now)
index 82c79c8baf923f5ad6d08d9ca8428d61e8380d5b..8769be2aa21e893c356a42cdb4e38ba5bdb6cba5 100644 (file)
@@ -4,6 +4,7 @@
 
 void bch2_io_timer_add(struct io_clock *, struct io_timer *);
 void bch2_io_timer_del(struct io_clock *, struct io_timer *);
+unsigned long bch2_kthread_io_clock_wait_once(struct io_clock *, u64, unsigned long);
 void bch2_kthread_io_clock_wait(struct io_clock *, u64, unsigned long);
 
 void __bch2_increment_clock(struct io_clock *, u64);