diff --git a/META b/META index 39828e0a10..49d8bd73d5 100644 --- a/META +++ b/META @@ -6,5 +6,5 @@ Release: 1 Release-Tags: relext License: CDDL Author: OpenZFS on Linux -Linux-Maximum: 5.4 +Linux-Maximum: 5.6 Linux-Minimum: 3.10 diff --git a/config/kernel-make-request-fn.m4 b/config/kernel-make-request-fn.m4 index 5183176f58..609926c1b7 100644 --- a/config/kernel-make-request-fn.m4 +++ b/config/kernel-make-request-fn.m4 @@ -17,38 +17,67 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [ ],[ blk_queue_make_request(NULL, &make_request); ]) + + ZFS_LINUX_TEST_SRC([blk_alloc_queue_request_fn], [ + #include + blk_qc_t make_request(struct request_queue *q, + struct bio *bio) { return (BLK_QC_T_NONE); } + ],[ + struct request_queue *q __attribute__ ((unused)); + q = blk_alloc_queue(make_request, NUMA_NO_NODE); + ]) ]) AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [ dnl # - dnl # Linux 3.2 API Change - dnl # make_request_fn returns void. + dnl # Linux 5.7 API Change + dnl # blk_alloc_queue() expects request function. dnl # - AC_MSG_CHECKING([whether make_request_fn() returns void]) - ZFS_LINUX_TEST_RESULT([make_request_fn_void], [ + AC_MSG_CHECKING([whether blk_alloc_queue() expects request function]) + ZFS_LINUX_TEST_RESULT([blk_alloc_queue_request_fn], [ AC_MSG_RESULT(yes) - AC_DEFINE(MAKE_REQUEST_FN_RET, void, - [make_request_fn() return type]) - AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_VOID, 1, - [Noting that make_request_fn() returns void]) - ],[ - AC_MSG_RESULT(no) + dnl # Checked as part of the blk_alloc_queue_request_fn test + AC_MSG_CHECKING([whether make_request_fn() returns blk_qc_t]) + AC_MSG_RESULT(yes) + + AC_DEFINE(HAVE_BLK_ALLOC_QUEUE_REQUEST_FN, 1, + [blk_alloc_queue() expects request function]) + AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t, + [make_request_fn() return type]) + AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1, + [Noting that make_request_fn() returns blk_qc_t]) + ],[ dnl # - dnl # Linux 4.4 API Change - dnl # make_request_fn returns blk_qc_t. + dnl # Linux 3.2 API Change + dnl # make_request_fn returns void. dnl # - AC_MSG_CHECKING( - [whether make_request_fn() returns blk_qc_t]) - ZFS_LINUX_TEST_RESULT([make_request_fn_blk_qc_t], [ + AC_MSG_CHECKING([whether make_request_fn() returns void]) + ZFS_LINUX_TEST_RESULT([make_request_fn_void], [ AC_MSG_RESULT(yes) - AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t, + AC_DEFINE(MAKE_REQUEST_FN_RET, void, [make_request_fn() return type]) - AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1, - [Noting that make_request_fn() ] - [returns blk_qc_t]) + AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_VOID, 1, + [Noting that make_request_fn() returns void]) ],[ - ZFS_LINUX_TEST_ERROR([make_request_fn]) + AC_MSG_RESULT(no) + + dnl # + dnl # Linux 4.4 API Change + dnl # make_request_fn returns blk_qc_t. + dnl # + AC_MSG_CHECKING( + [whether make_request_fn() returns blk_qc_t]) + ZFS_LINUX_TEST_RESULT([make_request_fn_blk_qc_t], [ + AC_MSG_RESULT(yes) + AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t, + [make_request_fn() return type]) + AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1, + [Noting that make_request_fn() ] + [returns blk_qc_t]) + ],[ + ZFS_LINUX_TEST_ERROR([make_request_fn]) + ]) ]) ]) ]) diff --git a/include/os/linux/kernel/linux/blkdev_compat.h b/include/os/linux/kernel/linux/blkdev_compat.h index 3ba14ef404..b46a6e40af 100644 --- a/include/os/linux/kernel/linux/blkdev_compat.h +++ b/include/os/linux/kernel/linux/blkdev_compat.h @@ -487,4 +487,18 @@ blk_generic_end_io_acct(struct request_queue *q, int rw, #endif } +static inline struct request_queue * +blk_generic_alloc_queue(make_request_fn make_request, int node_id) +{ +#if defined(HAVE_BLK_ALLOC_QUEUE_REQUEST_FN) + return (blk_alloc_queue(make_request, node_id)); +#else + struct request_queue *q = blk_alloc_queue(GFP_KERNEL); + if (q != NULL) + blk_queue_make_request(q, make_request); + + return (q); +#endif +} + #endif /* _ZFS_BLKDEV_H */ diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c index 9439954b8a..fe45d76a62 100644 --- a/module/os/linux/zfs/zvol_os.c +++ b/module/os/linux/zfs/zvol_os.c @@ -754,6 +754,7 @@ static zvol_state_t * zvol_alloc(dev_t dev, const char *name) { zvol_state_t *zv; + struct zvol_state_os *zso; uint64_t volmode; if (dsl_prop_get_integer(name, "volmode", &volmode, NULL) != 0) @@ -766,39 +767,38 @@ zvol_alloc(dev_t dev, const char *name) return (NULL); zv = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP); - zv->zv_zso = kmem_zalloc(sizeof (struct zvol_state_os), KM_SLEEP); + zso = kmem_zalloc(sizeof (struct zvol_state_os), KM_SLEEP); + zv->zv_zso = zso; list_link_init(&zv->zv_next); - mutex_init(&zv->zv_state_lock, NULL, MUTEX_DEFAULT, NULL); - zv->zv_zso->zvo_queue = blk_alloc_queue(GFP_ATOMIC); - if (zv->zv_zso->zvo_queue == NULL) + zso->zvo_queue = blk_generic_alloc_queue(zvol_request, NUMA_NO_NODE); + if (zso->zvo_queue == NULL) goto out_kmem; - blk_queue_make_request(zv->zv_zso->zvo_queue, zvol_request); - blk_queue_set_write_cache(zv->zv_zso->zvo_queue, B_TRUE, B_TRUE); + blk_queue_set_write_cache(zso->zvo_queue, B_TRUE, B_TRUE); /* Limit read-ahead to a single page to prevent over-prefetching. */ - blk_queue_set_read_ahead(zv->zv_zso->zvo_queue, 1); + blk_queue_set_read_ahead(zso->zvo_queue, 1); /* Disable write merging in favor of the ZIO pipeline. */ - blk_queue_flag_set(QUEUE_FLAG_NOMERGES, zv->zv_zso->zvo_queue); + blk_queue_flag_set(QUEUE_FLAG_NOMERGES, zso->zvo_queue); - zv->zv_zso->zvo_disk = alloc_disk(ZVOL_MINORS); - if (zv->zv_zso->zvo_disk == NULL) + zso->zvo_disk = alloc_disk(ZVOL_MINORS); + if (zso->zvo_disk == NULL) goto out_queue; - zv->zv_zso->zvo_queue->queuedata = zv; - zv->zv_zso->zvo_dev = dev; + zso->zvo_queue->queuedata = zv; + zso->zvo_dev = dev; zv->zv_open_count = 0; strlcpy(zv->zv_name, name, MAXNAMELEN); zfs_rangelock_init(&zv->zv_rangelock, NULL, NULL); rw_init(&zv->zv_suspend_lock, NULL, RW_DEFAULT, NULL); - zv->zv_zso->zvo_disk->major = zvol_major; - zv->zv_zso->zvo_disk->events = DISK_EVENT_MEDIA_CHANGE; + zso->zvo_disk->major = zvol_major; + zso->zvo_disk->events = DISK_EVENT_MEDIA_CHANGE; if (volmode == ZFS_VOLMODE_DEV) { /* @@ -808,27 +808,27 @@ zvol_alloc(dev_t dev, const char *name) * and suppresses partition scanning (GENHD_FL_NO_PART_SCAN) * setting gendisk->flags accordingly. */ - zv->zv_zso->zvo_disk->minors = 1; + zso->zvo_disk->minors = 1; #if defined(GENHD_FL_EXT_DEVT) - zv->zv_zso->zvo_disk->flags &= ~GENHD_FL_EXT_DEVT; + zso->zvo_disk->flags &= ~GENHD_FL_EXT_DEVT; #endif #if defined(GENHD_FL_NO_PART_SCAN) - zv->zv_zso->zvo_disk->flags |= GENHD_FL_NO_PART_SCAN; + zso->zvo_disk->flags |= GENHD_FL_NO_PART_SCAN; #endif } - zv->zv_zso->zvo_disk->first_minor = (dev & MINORMASK); - zv->zv_zso->zvo_disk->fops = &zvol_ops; - zv->zv_zso->zvo_disk->private_data = zv; - zv->zv_zso->zvo_disk->queue = zv->zv_zso->zvo_queue; - snprintf(zv->zv_zso->zvo_disk->disk_name, DISK_NAME_LEN, "%s%d", + zso->zvo_disk->first_minor = (dev & MINORMASK); + zso->zvo_disk->fops = &zvol_ops; + zso->zvo_disk->private_data = zv; + zso->zvo_disk->queue = zso->zvo_queue; + snprintf(zso->zvo_disk->disk_name, DISK_NAME_LEN, "%s%d", ZVOL_DEV_NAME, (dev & MINORMASK)); return (zv); out_queue: - blk_cleanup_queue(zv->zv_zso->zvo_queue); + blk_cleanup_queue(zso->zvo_queue); out_kmem: - kmem_free(zv->zv_zso, sizeof (struct zvol_state_os)); + kmem_free(zso, sizeof (struct zvol_state_os)); kmem_free(zv, sizeof (zvol_state_t)); return (NULL); }