]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Linux 5.18 compat: bio_alloc()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 27 May 2022 20:28:51 +0000 (20:28 +0000)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 1 Jun 2022 21:24:49 +0000 (14:24 -0700)
As for the Linux 5.18 kernel bio_alloc() expects a block_device struct
as an argument.  This removes the need for the bio_set_dev() compatibility
code for 5.18 and newer kernels.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515

module/os/linux/zfs/vdev_disk.c

index 2708535b3b886b2c77c950d40d57e71b80ed85f3..d6f9311be72b2b8614f6d7f8c4a8535a2e330dd3 100644 (file)
@@ -460,6 +460,13 @@ vdev_submit_bio_impl(struct bio *bio)
 #define        preempt_schedule_notrace(x) preempt_schedule(x)
 #endif
 
+/*
+ * As for the Linux 5.18 kernel bio_alloc() expects a block_device struct
+ * as an argument removing the need to set it with bio_set_dev().  This
+ * removes the need for all of the following compatibility code.
+ */
+#if !defined(HAVE_BIO_ALLOC_4ARG)
+
 #ifdef HAVE_BIO_SET_DEV
 #if defined(CONFIG_BLK_CGROUP) && defined(HAVE_BIO_SET_DEV_GPL_ONLY)
 /*
@@ -556,6 +563,7 @@ bio_set_dev(struct bio *bio, struct block_device *bdev)
        bio->bi_bdev = bdev;
 }
 #endif /* HAVE_BIO_SET_DEV */
+#endif /* !HAVE_BIO_ALLOC_4ARG */
 
 static inline void
 vdev_submit_bio(struct bio *bio)
@@ -566,10 +574,36 @@ vdev_submit_bio(struct bio *bio)
        current->bio_list = bio_list;
 }
 
+static inline struct bio *
+vdev_bio_alloc(struct block_device *bdev, gfp_t gfp_mask,
+    unsigned short nr_vecs)
+{
+       struct bio *bio;
+
 #ifdef HAVE_BIO_ALLOC_4ARG
-#define        bio_alloc(gfp_mask, nr_iovecs) bio_alloc(NULL, nr_iovecs, 0, gfp_mask)
+       bio = bio_alloc(bdev, nr_vecs, 0, gfp_mask);
+#else
+       bio = bio_alloc(gfp_mask, nr_vecs);
+       if (likely(bio != NULL))
+               bio_set_dev(bio, bdev);
 #endif
 
+       return (bio);
+}
+
+static inline unsigned int
+vdev_bio_max_segs(zio_t *zio, int bio_size, uint64_t abd_offset)
+{
+       unsigned long nr_segs = abd_nr_pages_off(zio->io_abd,
+           bio_size, abd_offset);
+
+#ifdef HAVE_BIO_MAX_SEGS
+       return (bio_max_segs(nr_segs));
+#else
+       return (MIN(nr_segs, BIO_MAX_PAGES));
+#endif
+}
+
 static int
 __vdev_disk_physio(struct block_device *bdev, zio_t *zio,
     size_t io_size, uint64_t io_offset, int rw, int flags)
@@ -581,6 +615,7 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio,
        int bio_count = 16;
        int error = 0;
        struct blk_plug plug;
+       unsigned short nr_vecs;
 
        /*
         * Accessing outside the block device is never allowed.
@@ -630,15 +665,8 @@ retry:
                        goto retry;
                }
 
-               /* bio_alloc() with __GFP_WAIT never returns NULL */
-#ifdef HAVE_BIO_MAX_SEGS
-               dr->dr_bio[i] = bio_alloc(GFP_NOIO, bio_max_segs(
-                   abd_nr_pages_off(zio->io_abd, bio_size, abd_offset)));
-#else
-               dr->dr_bio[i] = bio_alloc(GFP_NOIO,
-                   MIN(abd_nr_pages_off(zio->io_abd, bio_size, abd_offset),
-                   BIO_MAX_PAGES));
-#endif
+               nr_vecs = vdev_bio_max_segs(zio, bio_size, abd_offset);
+               dr->dr_bio[i] = vdev_bio_alloc(bdev, GFP_NOIO, nr_vecs);
                if (unlikely(dr->dr_bio[i] == NULL)) {
                        vdev_disk_dio_free(dr);
                        return (SET_ERROR(ENOMEM));
@@ -647,7 +675,6 @@ retry:
                /* Matching put called by vdev_disk_physio_completion */
                vdev_disk_dio_get(dr);
 
-               bio_set_dev(dr->dr_bio[i], bdev);
                BIO_BI_SECTOR(dr->dr_bio[i]) = bio_offset >> 9;
                dr->dr_bio[i]->bi_end_io = vdev_disk_physio_completion;
                dr->dr_bio[i]->bi_private = dr;
@@ -711,14 +738,12 @@ vdev_disk_io_flush(struct block_device *bdev, zio_t *zio)
        if (!q)
                return (SET_ERROR(ENXIO));
 
-       bio = bio_alloc(GFP_NOIO, 0);
-       /* bio_alloc() with __GFP_WAIT never returns NULL */
+       bio = vdev_bio_alloc(bdev, GFP_NOIO, 0);
        if (unlikely(bio == NULL))
                return (SET_ERROR(ENOMEM));
 
        bio->bi_end_io = vdev_disk_io_flush_completion;
        bio->bi_private = zio;
-       bio_set_dev(bio, bdev);
        bio_set_flush(bio);
        vdev_submit_bio(bio);
        invalidate_bdev(bdev);