Merge tag 'zonefs-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal...
[sfrench/cifs-2.6.git] / block / bio.c
index b9642a41f286e5bb52d841255aa9286c1449e83d..d24420ed1c4c6f20b80bc043cdf0378afcb43668 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
 #include <linux/highmem.h>
-#include <linux/sched/sysctl.h>
 #include <linux/blk-crypto.h>
 #include <linux/xarray.h>
 
@@ -251,6 +250,7 @@ void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
        bio->bi_opf = opf;
        bio->bi_flags = 0;
        bio->bi_ioprio = 0;
+       bio->bi_write_hint = 0;
        bio->bi_status = 0;
        bio->bi_iter.bi_sector = 0;
        bio->bi_iter.bi_size = 0;
@@ -762,29 +762,31 @@ static inline void bio_put_percpu_cache(struct bio *bio)
        struct bio_alloc_cache *cache;
 
        cache = per_cpu_ptr(bio->bi_pool->cache, get_cpu());
-       if (READ_ONCE(cache->nr_irq) + cache->nr > ALLOC_CACHE_MAX) {
-               put_cpu();
-               bio_free(bio);
-               return;
-       }
+       if (READ_ONCE(cache->nr_irq) + cache->nr > ALLOC_CACHE_MAX)
+               goto out_free;
 
-       bio_uninit(bio);
-
-       if ((bio->bi_opf & REQ_POLLED) && !WARN_ON_ONCE(in_interrupt())) {
+       if (in_task()) {
+               bio_uninit(bio);
                bio->bi_next = cache->free_list;
+               /* Not necessary but helps not to iopoll already freed bios */
                bio->bi_bdev = NULL;
                cache->free_list = bio;
                cache->nr++;
-       } else {
-               unsigned long flags;
+       } else if (in_hardirq()) {
+               lockdep_assert_irqs_disabled();
 
-               local_irq_save(flags);
+               bio_uninit(bio);
                bio->bi_next = cache->free_list_irq;
                cache->free_list_irq = bio;
                cache->nr_irq++;
-               local_irq_restore(flags);
+       } else {
+               goto out_free;
        }
        put_cpu();
+       return;
+out_free:
+       put_cpu();
+       bio_free(bio);
 }
 
 /**
@@ -813,6 +815,7 @@ static int __bio_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp)
 {
        bio_set_flag(bio, BIO_CLONED);
        bio->bi_ioprio = bio_src->bi_ioprio;
+       bio->bi_write_hint = bio_src->bi_write_hint;
        bio->bi_iter = bio_src->bi_iter;
 
        if (bio->bi_bdev) {
@@ -1152,7 +1155,7 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty)
 
        bio_for_each_folio_all(fi, bio) {
                struct page *page;
-               size_t done = 0;
+               size_t nr_pages;
 
                if (mark_dirty) {
                        folio_lock(fi.folio);
@@ -1160,10 +1163,11 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty)
                        folio_unlock(fi.folio);
                }
                page = folio_page(fi.folio, fi.offset / PAGE_SIZE);
+               nr_pages = (fi.offset + fi.length - 1) / PAGE_SIZE -
+                          fi.offset / PAGE_SIZE + 1;
                do {
                        bio_release_page(bio, page++);
-                       done += PAGE_SIZE;
-               } while (done < fi.length);
+               } while (--nr_pages != 0);
        }
 }
 EXPORT_SYMBOL_GPL(__bio_release_pages);
@@ -1369,21 +1373,12 @@ int submit_bio_wait(struct bio *bio)
 {
        DECLARE_COMPLETION_ONSTACK_MAP(done,
                        bio->bi_bdev->bd_disk->lockdep_map);
-       unsigned long hang_check;
 
        bio->bi_private = &done;
        bio->bi_end_io = submit_bio_wait_endio;
        bio->bi_opf |= REQ_SYNC;
        submit_bio(bio);
-
-       /* Prevent hang_check timer from firing at us during very long I/O */
-       hang_check = sysctl_hung_task_timeout_secs;
-       if (hang_check)
-               while (!wait_for_completion_io_timeout(&done,
-                                       hang_check * (HZ/2)))
-                       ;
-       else
-               wait_for_completion_io(&done);
+       blk_wait_io(&done);
 
        return blk_status_to_errno(bio->bi_status);
 }