From b1f9a75abb91eb3b810a8c70eb853ea55cb3ade8 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Fri, 21 Jun 2024 00:16:35 +0200 Subject: [PATCH 1/3] Linux 6.9 compat: bdev_open_by_path Support the new `bdev_open_by_path` API introduced in https://lore.kernel.org/all/20240123-vfs-bdev-file-v2-0-adbd023e19cc@kernel.org/. Signed-off-by: Ryan Lahfa --- config/kernel-blkdev.m4 | 32 +++++++++++++++++++++++++++++++- module/os/linux/zfs/vdev_disk.c | 14 +++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/config/kernel-blkdev.m4 b/config/kernel-blkdev.m4 index 8e9e638b125a..b3bc5739adf0 100644 --- a/config/kernel-blkdev.m4 +++ b/config/kernel-blkdev.m4 @@ -54,6 +54,27 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_OPEN_BY_PATH], [ ]) ]) + +dnl # +dnl # 6.9.x API change +dnl # bdev_file_open_by_path() replaces bdev_open_by_path() +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_FILE_OPEN_BY_PATH], [ + ZFS_LINUX_TEST_SRC([bdev_file_open_by_path], [ + #include + #include + ], [ + struct file *bdev_file __attribute__ ((unused)) = NULL; + const char *path = "path"; + fmode_t mode = 0; + void *holder = NULL; + struct blk_holder_ops h; + + bdev_file = bdev_file_open_by_path(path, mode, holder, &h); + ]) +]) + + AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [ AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 3 args]) ZFS_LINUX_TEST_RESULT([blkdev_get_by_path], [ @@ -73,7 +94,15 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [ [bdev_open_by_path() exists]) AC_MSG_RESULT(yes) ], [ - ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()]) + AC_MSG_RESULT(no) + AC_MSG_CHECKING([whether bdev_file_open_by_path() exists]) + ZFS_LINUX_TEST_RESULT([bdev_file_open_by_path], [ + AC_DEFINE(HAVE_BDEV_FILE_OPEN_BY_PATH, 1, + [bdev_file_open_by_path() exists]) + AC_MSG_RESULT(yes) + ], [ + ZFS_LINUX_TEST_ERROR([blkdev_get_by_path() or bdev_open_by_path() or bdev_file_open_by_path()]) + ]) ]) ]) ]) @@ -621,6 +650,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [ ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_OPEN_BY_PATH + ZFS_AC_KERNEL_SRC_BDEV_FILE_OPEN_BY_PATH ZFS_AC_KERNEL_SRC_BLKDEV_PUT ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_RELEASE diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index 3ec4f0f09696..9f5b526d7203 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -42,17 +42,26 @@ #endif /* + * Linux 6.9.x uses a file as an instance/refcount for an underlying + * block_device. We follow the same methodology as in Linux 6.8.x for it. + * * Linux 6.8.x uses a bdev_handle as an instance/refcount for an underlying * block_device. Since it carries the block_device inside, its convenient to * just use the handle as a proxy. For pre-6.8, we just emulate this with * a cast, since we don't need any of the other fields inside the handle. */ -#ifdef HAVE_BDEV_OPEN_BY_PATH +#if defined(HAVE_BDEV_OPEN_BY_PATH) typedef struct bdev_handle zfs_bdev_handle_t; #define BDH_BDEV(bdh) ((bdh)->bdev) #define BDH_IS_ERR(bdh) (IS_ERR(bdh)) #define BDH_PTR_ERR(bdh) (PTR_ERR(bdh)) #define BDH_ERR_PTR(err) (ERR_PTR(err)) +#elif defined(HAVE_BDEV_FILE_OPEN_BY_PATH) +typedef struct file zfs_bdev_handle_t; +#define BDH_BDEV(bdh) (file_bdev(bdh)) +#define BDH_IS_ERR(bdh) (IS_ERR(bdh)) +#define BDH_PTR_ERR(bdh) (PTR_ERR(bdh)) +#define BDH_ERR_PTR(err) (ERR_PTR(err)) #else typedef void zfs_bdev_handle_t; #define BDH_BDEV(bdh) ((struct block_device *)bdh) @@ -237,6 +246,9 @@ vdev_blkdev_get_by_path(const char *path, spa_mode_t mode, void *holder) #if defined(HAVE_BDEV_OPEN_BY_PATH) return (bdev_open_by_path(path, vdev_bdev_mode(mode, B_TRUE), holder, NULL)); +#elif defined(HAVE_BDEV_FILE_OPEN_BY_PATH) + return (bdev_file_open_by_path(path, + vdev_bdev_mode(mode, B_TRUE), holder, NULL)); #elif defined(HAVE_BLKDEV_GET_BY_PATH_4ARG) return (blkdev_get_by_path(path, vdev_bdev_mode(mode, B_TRUE), holder, NULL)); From 08f57a31507274fd19c3fe207ffca21b3d1fcf74 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Fri, 21 Jun 2024 00:39:40 +0200 Subject: [PATCH 2/3] Linux 6.9 compat: fput for block device release With new file-driven API, it is sufficient to `fput` the block device handle to release it. Signed-off-by: Ryan Lahfa --- config/kernel-blkdev.m4 | 24 +++++++++++++++++++++++- module/os/linux/zfs/vdev_disk.c | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/config/kernel-blkdev.m4 b/config/kernel-blkdev.m4 index b3bc5739adf0..88b2f69cc439 100644 --- a/config/kernel-blkdev.m4 +++ b/config/kernel-blkdev.m4 @@ -178,6 +178,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_RELEASE], [ ]) ]) +dnl # +dnl # 6.9.x API change +dnl # fput() replaces bdev_release() +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_FPUT], [ + ZFS_LINUX_TEST_SRC([fput], [ + #include + #include + ], [ + struct file *f = NULL; + fput(f); + ]) +]) + AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [ AC_MSG_CHECKING([whether blkdev_put() exists]) ZFS_LINUX_TEST_RESULT([blkdev_put], [ @@ -197,7 +211,14 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [ AC_DEFINE(HAVE_BDEV_RELEASE, 1, [bdev_release() exists]) ], [ - ZFS_LINUX_TEST_ERROR([blkdev_put()]) + ZFS_LINUX_TEST_RESULT([fput], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_BDEV_RELEASE_VIA_FPUT, 1, + [fput() can release a block device and exists] + ) + ], [ + ZFS_LINUX_TEST_ERROR([blkdev_put()]) + ]) ]) ]) ]) @@ -654,6 +675,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [ ZFS_AC_KERNEL_SRC_BLKDEV_PUT ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_RELEASE + ZFS_AC_KERNEL_SRC_BLKDEV_FPUT ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART ZFS_AC_KERNEL_SRC_BLKDEV_INVALIDATE_BDEV ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index 9f5b526d7203..da30dfad5a15 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -263,6 +263,8 @@ vdev_blkdev_put(zfs_bdev_handle_t *bdh, spa_mode_t mode, void *holder) { #if defined(HAVE_BDEV_RELEASE) return (bdev_release(bdh)); +#elif defined(HAVE_BDEV_RELEASE_VIA_FPUT) + return (fput(bdh)); #elif defined(HAVE_BLKDEV_PUT_HOLDER) return (blkdev_put(BDH_BDEV(bdh), holder)); #else From 980aca470c229b2fd238076e9c3c4d285c20279a Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Fri, 21 Jun 2024 00:54:58 +0200 Subject: [PATCH 3/3] Linux 6.9 compat: blk_alloc_disk takes 2 args Now, it takes queue limits, this is a trivial implementation with no queue limits, implementing proper queue limits is left as an exercise to the reader. Signed-off-by: Ryan Lahfa --- config/kernel-make-request-fn.m4 | 50 +++++++++++++++++++++++--------- module/os/linux/zfs/zvol_os.c | 4 +++ 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/config/kernel-make-request-fn.m4 b/config/kernel-make-request-fn.m4 index 4d20dd45c4a1..ef79612f9d02 100644 --- a/config/kernel-make-request-fn.m4 +++ b/config/kernel-make-request-fn.m4 @@ -50,6 +50,13 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [ disk = blk_alloc_disk(NUMA_NO_NODE); ]) + ZFS_LINUX_TEST_SRC([blk_alloc_disk_2args], [ + #include + ],[ + struct gendisk *disk __attribute__ ((unused)); + disk = blk_alloc_disk(NULL, NUMA_NO_NODE); + ]) + ZFS_LINUX_TEST_SRC([blk_cleanup_disk], [ #include ],[ @@ -71,30 +78,45 @@ AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [ AC_DEFINE(HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS, 1, [submit_bio is member of struct block_device_operations]) + dnl + dnl # Linux 6.9 API change + dnl # blk_alloc_disk() takes 2 arguments: + dnl # a queue limit and NUMA node ID. dnl # - dnl # Linux 5.14 API Change: - dnl # blk_alloc_queue() + alloc_disk() combo replaced by - dnl # a single call to blk_alloc_disk(). - dnl # - AC_MSG_CHECKING([whether blk_alloc_disk() exists]) - ZFS_LINUX_TEST_RESULT([blk_alloc_disk], [ + AC_MSG_CHECKING([whether blk_alloc_disk() takes 2 args]) + ZFS_LINUX_TEST_RESULT([blk_alloc_disk_2args], [ AC_MSG_RESULT(yes) AC_DEFINE([HAVE_BLK_ALLOC_DISK], 1, [blk_alloc_disk() exists]) + AC_DEFINE([HAVE_BLK_ALLOC_DISK_2ARGS], 1, [blk_alloc_disk() takes 2 args]) + dnl # put_disk() should be used in 6.9. + ], [ + AC_MSG_RESULT(no) dnl # - dnl # 5.20 API change, - dnl # Removed blk_cleanup_disk(), put_disk() should be used. + dnl # Linux 5.14 API Change: + dnl # blk_alloc_queue() + alloc_disk() combo replaced by + dnl # a single call to blk_alloc_disk(). dnl # - AC_MSG_CHECKING([whether blk_cleanup_disk() exists]) - ZFS_LINUX_TEST_RESULT([blk_cleanup_disk], [ + AC_MSG_CHECKING([whether blk_alloc_disk() exists]) + ZFS_LINUX_TEST_RESULT([blk_alloc_disk], [ AC_MSG_RESULT(yes) - AC_DEFINE([HAVE_BLK_CLEANUP_DISK], 1, - [blk_cleanup_disk() exists]) + AC_DEFINE([HAVE_BLK_ALLOC_DISK], 1, [blk_alloc_disk() exists]) + + dnl # + dnl # 5.20 API change, + dnl # Removed blk_cleanup_disk(), put_disk() should be used. + dnl # + AC_MSG_CHECKING([whether blk_cleanup_disk() exists]) + ZFS_LINUX_TEST_RESULT([blk_cleanup_disk], [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_BLK_CLEANUP_DISK], 1, + [blk_cleanup_disk() exists]) + ], [ + AC_MSG_RESULT(no) + ]) ], [ AC_MSG_RESULT(no) ]) - ], [ - AC_MSG_RESULT(no) ]) ],[ AC_MSG_RESULT(no) diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c index 87288190e7c0..92d1189d0e9c 100644 --- a/module/os/linux/zfs/zvol_os.c +++ b/module/os/linux/zfs/zvol_os.c @@ -874,7 +874,11 @@ zvol_alloc(dev_t dev, const char *name) #ifdef HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS #ifdef HAVE_BLK_ALLOC_DISK +#ifdef HAVE_BLK_ALLOC_DISK_2ARGS + zso->zvo_disk = blk_alloc_disk(NULL, NUMA_NO_NODE); +#else zso->zvo_disk = blk_alloc_disk(NUMA_NO_NODE); +#endif if (zso->zvo_disk == NULL) goto out_kmem;