bcachefs: Make sure to initialize j->last_flushed
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 29 Apr 2021 02:12:07 +0000 (22:12 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:02 +0000 (17:09 -0400)
If the journal reclaim thread makes it to the timeout without ever
initializing j->last_flushed, we could end up sleeping for a very long
time.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/journal.c
fs/bcachefs/journal_reclaim.c
fs/bcachefs/journal_reclaim.h
fs/bcachefs/journal_types.h

index 2724a58ada05f0370debfe9ef57ce95ceb7dbe6b..a70540853586ad38fdbcb23a69183eb679b27e02 100644 (file)
@@ -1189,6 +1189,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
               "nr noflush writes:\t%llu\n"
               "nr direct reclaim:\t%llu\n"
               "nr background reclaim:\t%llu\n"
+              "reclaim kicked:\t\t%u\n"
+              "reclaim runs in:\t%u ms\n"
               "current entry sectors:\t%u\n"
               "current entry error:\t%u\n"
               "current entry:\t\t",
@@ -1204,6 +1206,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
               j->nr_noflush_writes,
               j->nr_direct_reclaim,
               j->nr_background_reclaim,
+              j->reclaim_kicked,
+              jiffies_to_msecs(j->next_reclaim - jiffies),
               j->cur_entry_sectors,
               j->cur_entry_error);
 
index 416f8611f0085bc31011dd582f7c17ad4502fd6c..812620d3de31ea5a92ec9bbc120d6eb3a8a04735 100644 (file)
@@ -677,13 +677,15 @@ int bch2_journal_reclaim(struct journal *j)
 static int bch2_journal_reclaim_thread(void *arg)
 {
        struct journal *j = arg;
-       unsigned long next;
+       unsigned long delay, now;
        int ret = 0;
 
        set_freezable();
 
        kthread_wait_freezable(test_bit(JOURNAL_RECLAIM_STARTED, &j->flags));
 
+       j->last_flushed = jiffies;
+
        while (!ret && !kthread_should_stop()) {
                j->reclaim_kicked = false;
 
@@ -691,18 +693,22 @@ static int bch2_journal_reclaim_thread(void *arg)
                ret = __bch2_journal_reclaim(j, false);
                mutex_unlock(&j->reclaim_lock);
 
-               next = j->last_flushed + msecs_to_jiffies(j->reclaim_delay_ms);
+               now = jiffies;
+               delay = msecs_to_jiffies(j->reclaim_delay_ms);
+               j->next_reclaim = j->last_flushed + delay;
+
+               if (!time_in_range(j->next_reclaim, now, now + delay))
+                       j->next_reclaim = now + delay;
 
                while (1) {
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE);
                        if (kthread_should_stop())
                                break;
                        if (j->reclaim_kicked)
                                break;
-                       if (time_after_eq(jiffies, next))
+                       if (time_after_eq(jiffies, j->next_reclaim))
                                break;
-                       schedule_timeout(next - jiffies);
-                       try_to_freeze();
+                       schedule_timeout(j->next_reclaim - jiffies);
 
                }
                __set_current_state(TASK_RUNNING);
index adf1f5c981cdfa80e227516d7c203306a543eba3..0fd1af120db551746fc5cac54000c8616914a4f3 100644 (file)
@@ -8,11 +8,9 @@ static inline void journal_reclaim_kick(struct journal *j)
 {
        struct task_struct *p = READ_ONCE(j->reclaim_thread);
 
-       if (p && !j->reclaim_kicked) {
-               j->reclaim_kicked = true;
-               if (p)
-                       wake_up_process(p);
-       }
+       j->reclaim_kicked = true;
+       if (p)
+               wake_up_process(p);
 }
 
 unsigned bch2_journal_dev_buckets_available(struct journal *,
index f597eb78e66e2db76488edacc3c0a5880088fabe..6e2a2d6b83466e9e9a319089eb9125034518c22e 100644 (file)
@@ -248,6 +248,7 @@ struct journal {
        wait_queue_head_t       reclaim_wait;
        struct task_struct      *reclaim_thread;
        bool                    reclaim_kicked;
+       unsigned long           next_reclaim;
        u64                     nr_direct_reclaim;
        u64                     nr_background_reclaim;