diff --git a/config/kernel-blk-queue-bdi.m4 b/config/kernel-blk-queue-bdi.m4 new file mode 100644 index 0000000000..816471166a --- /dev/null +++ b/config/kernel-blk-queue-bdi.m4 @@ -0,0 +1,20 @@ +dnl # +dnl # 2.6.32 - 4.11, statically allocated bdi in request_queue +dnl # 4.12 - x.y, dynamically allocated bdi in request_queue +dnl # +AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_BDI], [ + AC_MSG_CHECKING([whether blk_queue bdi is dynamic]) + ZFS_LINUX_TRY_COMPILE([ + #include + ],[ + struct request_queue q; + struct backing_dev_info bdi; + q.backing_dev_info = &bdi; + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_BLK_QUEUE_BDI_DYNAMIC, 1, + [blk queue backing_dev_info is dynamic]) + ],[ + AC_MSG_RESULT(no) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 638d9e143b..57dad7b3aa 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -32,6 +32,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_BIO_END_IO_T_ARGS ZFS_AC_KERNEL_BIO_RW_BARRIER ZFS_AC_KERNEL_BIO_RW_DISCARD + ZFS_AC_KERNEL_BLK_QUEUE_BDI ZFS_AC_KERNEL_BLK_QUEUE_FLUSH ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS diff --git a/include/linux/blkdev_compat.h b/include/linux/blkdev_compat.h index 15824c0b85..822e964a71 100644 --- a/include/linux/blkdev_compat.h +++ b/include/linux/blkdev_compat.h @@ -31,6 +31,7 @@ #include #include +#include #ifndef HAVE_FMODE_T typedef unsigned __bitwise__ fmode_t; @@ -128,6 +129,16 @@ __blk_queue_max_segments(struct request_queue *q, unsigned short max_segments) } #endif +static inline void +blk_queue_set_read_ahead(struct request_queue *q, unsigned long ra_pages) +{ +#ifdef HAVE_BLK_QUEUE_BDI_DYNAMIC + q->backing_dev_info->ra_pages = ra_pages; +#else + q->backing_dev_info.ra_pages = ra_pages; +#endif +} + #ifndef HAVE_GET_DISK_RO static inline int get_disk_ro(struct gendisk *disk) diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index d0f7b9912b..fef1d299a0 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -1468,6 +1468,9 @@ zvol_alloc(dev_t dev, const char *name) blk_queue_make_request(zv->zv_queue, zvol_request); blk_queue_set_write_cache(zv->zv_queue, B_TRUE, B_TRUE); + /* Limit read-ahead to a single page to prevent over-prefetching. */ + blk_queue_set_read_ahead(zv->zv_queue, 1); + /* Disable write merging in favor of the ZIO pipeline. */ queue_flag_set(QUEUE_FLAG_NOMERGES, zv->zv_queue);