]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
dm-delay: avoid duplicate logic
authorMikulas Patocka <mpatocka@redhat.com>
Fri, 17 Nov 2023 17:24:04 +0000 (18:24 +0100)
committerMike Snitzer <snitzer@kernel.org>
Fri, 17 Nov 2023 19:41:14 +0000 (14:41 -0500)
This is small refactoring of dm-delay - we avoid duplicate logic in
flush_delayed_bios and flush_delayed_bios_fast and join these two
functions into one.

We also add cond_resched() to flush_delayed_bios because the list may have
unbounded number of entries.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
drivers/md/dm-delay.c

index 00c09d9fffebf9e7ac6654cd9a3b17460b3d4fa0..5eabdb06c6498b103f24e7316e3de2587f6bca45 100644 (file)
@@ -85,24 +85,40 @@ static void flush_bios(struct bio *bio)
        }
 }
 
-static void flush_delayed_bios_fast(struct delay_c *dc, bool flush_all)
+static void flush_delayed_bios(struct delay_c *dc, bool flush_all)
 {
        struct dm_delay_info *delayed, *next;
        struct bio_list flush_bio_list;
+       unsigned long next_expires = 0;
+       bool start_timer = false;
        bio_list_init(&flush_bio_list);
 
        mutex_lock(&delayed_bios_lock);
        list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) {
+               cond_resched();
                if (flush_all || time_after_eq(jiffies, delayed->expires)) {
                        struct bio *bio = dm_bio_from_per_bio_data(delayed,
                                                sizeof(struct dm_delay_info));
                        list_del(&delayed->list);
                        bio_list_add(&flush_bio_list, bio);
                        delayed->class->ops--;
+                       continue;
+               }
+
+               if (!delay_is_fast(dc)) {
+                       if (!start_timer) {
+                               start_timer = true;
+                               next_expires = delayed->expires;
+                       } else {
+                               next_expires = min(next_expires, delayed->expires);
+                       }
                }
        }
        mutex_unlock(&delayed_bios_lock);
 
+       if (start_timer)
+               queue_timeout(dc, next_expires);
+
        flush_bios(bio_list_get(&flush_bio_list));
 }
 
@@ -111,7 +127,7 @@ static int flush_worker_fn(void *data)
        struct delay_c *dc = data;
 
        while (!kthread_should_stop()) {
-               flush_delayed_bios_fast(dc, false);
+               flush_delayed_bios(dc, false);
                mutex_lock(&delayed_bios_lock);
                if (unlikely(list_empty(&dc->delayed_bios))) {
                        set_current_state(TASK_INTERRUPTIBLE);
@@ -126,48 +142,12 @@ static int flush_worker_fn(void *data)
        return 0;
 }
 
-static void flush_delayed_bios(struct delay_c *dc, bool flush_all)
-{
-       struct dm_delay_info *delayed, *next;
-       unsigned long next_expires = 0;
-       unsigned long start_timer = 0;
-       struct bio_list flush_bio_list;
-       bio_list_init(&flush_bio_list);
-
-       mutex_lock(&delayed_bios_lock);
-       list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) {
-               if (flush_all || time_after_eq(jiffies, delayed->expires)) {
-                       struct bio *bio = dm_bio_from_per_bio_data(delayed,
-                                               sizeof(struct dm_delay_info));
-                       list_del(&delayed->list);
-                       bio_list_add(&flush_bio_list, bio);
-                       delayed->class->ops--;
-                       continue;
-               }
-
-               if (!start_timer) {
-                       start_timer = 1;
-                       next_expires = delayed->expires;
-               } else
-                       next_expires = min(next_expires, delayed->expires);
-       }
-       mutex_unlock(&delayed_bios_lock);
-
-       if (start_timer)
-               queue_timeout(dc, next_expires);
-
-       flush_bios(bio_list_get(&flush_bio_list));
-}
-
 static void flush_expired_bios(struct work_struct *work)
 {
        struct delay_c *dc;
 
        dc = container_of(work, struct delay_c, flush_expired_bios);
-       if (delay_is_fast(dc))
-               flush_delayed_bios_fast(dc, false);
-       else
-               flush_delayed_bios(dc, false);
+       flush_delayed_bios(dc, false);
 }
 
 static void delay_dtr(struct dm_target *ti)
@@ -354,12 +334,9 @@ static void delay_presuspend(struct dm_target *ti)
        dc->may_delay = false;
        mutex_unlock(&delayed_bios_lock);
 
-       if (delay_is_fast(dc)) {
-               flush_delayed_bios_fast(dc, true);
-       } else {
+       if (!delay_is_fast(dc))
                del_timer_sync(&dc->delay_timer);
-               flush_delayed_bios(dc, true);
-       }
+       flush_delayed_bios(dc, true);
 }
 
 static void delay_resume(struct dm_target *ti)