Skip to content

Commit

Permalink
zvol: Support blk-mq for better performance
Browse files Browse the repository at this point in the history
Add support for the kernel's block multiqueue (blk-mq) interface in
the zvol block driver.  blk-mq creates multiple request queues on
different CPUs rather than having a single request queue.  This can
improve zvol performance with multithreaded reads/writes.

This implementation uses the blk-mq interfaces on 4.13 or newer
kernels.  Building against older kernels will fall back to the
older BIO interfaces.

Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Issue #12483
  • Loading branch information
tonyhutter committed Nov 5, 2021
1 parent d5a5ec4 commit 2102b5f
Show file tree
Hide file tree
Showing 12 changed files with 540 additions and 34 deletions.
32 changes: 32 additions & 0 deletions config/kernel-blk-queue.m4
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,36 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS], [
])
])

dnl #
dnl # See if kernel supports block multi-queue and blk_status_t.
dnl # blk_status_t represents the new status codes introduced in the 4.13
dnl # kernel patch:
dnl #
dnl # block: introduce new block status code type
dnl #
dnl # We do not currently support the "old" block multi-queue interfaces from
dnl # prior kernels.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_MQ], [
ZFS_LINUX_TEST_SRC([blk_mq], [
#include <linux/blk-mq.h>
], [
struct blk_mq_tag_set tag_set = {0};
(void) blk_mq_alloc_tag_set(&tag_set);
return BLK_STS_OK;
], [$NO_UNUSED_BUT_SET_VARIABLE])
])

AC_DEFUN([ZFS_AC_KERNEL_BLK_MQ], [
AC_MSG_CHECKING([whether block multiqueue with blk_status_t is available])
ZFS_LINUX_TEST_RESULT([blk_mq], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_MQ, 1, [block multiqueue is available])
], [
AC_MSG_RESULT(no)
])
])

AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE], [
ZFS_AC_KERNEL_SRC_BLK_QUEUE_PLUG
ZFS_AC_KERNEL_SRC_BLK_QUEUE_BDI
Expand All @@ -326,6 +356,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE], [
ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLUSH
ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_HW_SECTORS
ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_SEGMENTS
ZFS_AC_KERNEL_SRC_BLK_MQ
])

AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE], [
Expand All @@ -339,4 +370,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE], [
ZFS_AC_KERNEL_BLK_QUEUE_FLUSH
ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS
ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS
ZFS_AC_KERNEL_BLK_MQ
])
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ AC_CONFIG_FILES([
tests/zfs-tests/tests/functional/zpool_influxdb/Makefile
tests/zfs-tests/tests/functional/zvol/Makefile
tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/Makefile
tests/zfs-tests/tests/functional/zvol/zvol_stress/Makefile
tests/zfs-tests/tests/functional/zvol/zvol_cli/Makefile
tests/zfs-tests/tests/functional/zvol/zvol_misc/Makefile
tests/zfs-tests/tests/functional/zvol/zvol_swap/Makefile
Expand Down
4 changes: 4 additions & 0 deletions include/os/linux/kernel/linux/blkdev_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,9 @@ bio_set_bi_status(struct bio *bio, int error)
{
ASSERT3S(error, <=, 0);
bio->bi_status = errno_to_bi_status(-error);
#ifndef HAVE_BLK_MQ
bio_endio(bio);
#endif
}
#else
#define BIO_END_IO_ERROR(bio) (-(bio->bi_error))
Expand All @@ -247,7 +249,9 @@ bio_set_bi_error(struct bio *bio, int error)
{
ASSERT3S(error, <=, 0);
bio->bi_error = error;
#ifndef HAVE_BLK_MQ
bio_endio(bio);
#endif
}
#endif /* HAVE_BIO_BI_STATUS */

Expand Down
12 changes: 9 additions & 3 deletions man/man4/zfs.4
Original file line number Diff line number Diff line change
Expand Up @@ -2172,9 +2172,15 @@ for each I/O submitter.
When unset, requests are handled asynchronously by a thread pool.
The number of requests which can be handled concurrently is controlled by
.Sy zvol_threads .
.
.It Sy zvol_threads Ns = Ns Sy 32 Pq uint
Max number of threads which can handle zvol I/O requests concurrently.
On blk-mq kernels, zvol_request_sync is ignored.
.
.It Sy zvol_threads Ns = Ns Sy 0 Pq uint
The number of threads to use for processing zvol block IOs.
On older non-blk-mq kernels, zvol_threads is the total number of threads to
use for all zvols.
On newer, blk-mq kernels, zvol_threads is the total number of threads per-zvol.
If zvol_threads = 0 (the default) then internally set zvol_threads to the
number of CPUs present.
.
.It Sy zvol_volmode Ns = Ns Sy 1 Pq uint
Defines zvol block devices behaviour when
Expand Down
Loading

0 comments on commit 2102b5f

Please sign in to comment.