From e8ac4557af67a46a2cb90bd7db4d426c0b358d51 Mon Sep 17 00:00:00 2001 From: Isaac Huang Date: Thu, 29 Sep 2016 14:13:31 -0600 Subject: [PATCH] Explicit block device plugging when submitting multiple BIOs Without plugging, the default 'noop' scheduler will not merge the BIOs which are part of a large ZIO. Reviewed-by: Andreas Dilger Reviewed-by: Brian Behlendorf Signed-off-by: Isaac Huang Closes #5181 --- config/kernel-blk-queue-unplug.m4 | 21 +++++++++++++++++++++ config/kernel.m4 | 1 + module/zfs/vdev_disk.c | 13 +++++++++++++ 3 files changed, 35 insertions(+) diff --git a/config/kernel-blk-queue-unplug.m4 b/config/kernel-blk-queue-unplug.m4 index 45cc2322a5..075fbccd1a 100644 --- a/config/kernel-blk-queue-unplug.m4 +++ b/config/kernel-blk-queue-unplug.m4 @@ -21,3 +21,24 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG], [ ]) EXTRA_KCFLAGS="$tmp_flags" ]) + +AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BLK_PLUG], [ + AC_MSG_CHECKING([whether struct blk_plug is available]) + tmp_flags="$EXTRA_KCFLAGS" + EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}" + ZFS_LINUX_TRY_COMPILE([ + #include + ],[ + struct blk_plug plug; + + blk_start_plug(&plug); + blk_finish_plug(&plug); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_BLK_QUEUE_HAVE_BLK_PLUG, 1, + [struct blk_plug is available]) + ],[ + AC_MSG_RESULT(no) + ]) + EXTRA_KCFLAGS="$tmp_flags" +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 798f3511bd..c53e611578 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -34,6 +34,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG + ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BLK_PLUG ZFS_AC_KERNEL_GET_DISK_RO ZFS_AC_KERNEL_GET_GENDISK ZFS_AC_KERNEL_DISCARD_GRANULARITY diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c index e399e66306..ce65760ee8 100644 --- a/module/zfs/vdev_disk.c +++ b/module/zfs/vdev_disk.c @@ -524,6 +524,9 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr, uint64_t bio_offset; int bio_size, bio_count = 16; int i = 0, error = 0; +#if defined(HAVE_BLK_QUEUE_HAVE_BLK_PLUG) + struct blk_plug plug; +#endif ASSERT3U(kbuf_offset + kbuf_size, <=, bdev->bd_inode->i_size); @@ -592,11 +595,21 @@ retry: /* Extra reference to protect dio_request during vdev_submit_bio */ vdev_disk_dio_get(dr); +#if defined(HAVE_BLK_QUEUE_HAVE_BLK_PLUG) + if (dr->dr_bio_count > 1) + blk_start_plug(&plug); +#endif + /* Submit all bio's associated with this dio */ for (i = 0; i < dr->dr_bio_count; i++) if (dr->dr_bio[i]) vdev_submit_bio(dr->dr_bio[i]); +#if defined(HAVE_BLK_QUEUE_HAVE_BLK_PLUG) + if (dr->dr_bio_count > 1) + blk_finish_plug(&plug); +#endif + (void) vdev_disk_dio_put(dr); return (error);