aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Norris <[email protected]>2024-03-27 10:07:50 +1100
committerTony Hutter <[email protected]>2024-04-22 09:23:23 -0700
commit3bd7cd06b711339d170b4caf7a72a46b166fbd8a (patch)
tree49b0f7d0d66f0568882093638fc8654934673853
parentb9c3040b10b60350ece42aed8c29972031fb14a0 (diff)
Linux 6.9 compat: bdev handles are now struct file
bdev_open_by_path() is replaced by bdev_file_open_by_path(), which returns a plain old struct file*. Release function is gone entirely; the regular file release function fput() will take care of the bdev specifics. Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Rob Norris <[email protected]> Sponsored-by: https://despairlabs.com/sponsor/ Closes #16027 Closes #16033
-rw-r--r--config/kernel-blkdev.m443
-rw-r--r--module/os/linux/zfs/vdev_disk.c24
2 files changed, 60 insertions, 7 deletions
diff --git a/config/kernel-blkdev.m4 b/config/kernel-blkdev.m4
index dae7bef9c..b6ce1e1cf 100644
--- a/config/kernel-blkdev.m4
+++ b/config/kernel-blkdev.m4
@@ -54,6 +54,26 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_OPEN_BY_PATH], [
])
])
+dnl #
+dnl # 6.9.x API change
+dnl # bdev_file_open_by_path() replaced bdev_open_by_path(),
+dnl # and returns struct file*
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_FILE_OPEN_BY_PATH], [
+ ZFS_LINUX_TEST_SRC([bdev_file_open_by_path], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct file *file __attribute__ ((unused)) = NULL;
+ const char *path = "path";
+ fmode_t mode = 0;
+ void *holder = NULL;
+ struct blk_holder_ops h;
+
+ 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 +93,16 @@ 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)
+ ], [
+ AC_MSG_RESULT(no)
+ ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
+ ])
])
])
])
@@ -149,10 +178,19 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_RELEASE], [
])
])
+dnl #
+dnl # 6.9.x API change
+dnl #
+dnl # bdev_release() now private, but because bdev_file_open_by_path() returns
+dnl # struct file*, we can just use fput(). So the blkdev_put test no longer
+dnl # fails if not found.
+dnl #
+
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [
AC_MSG_CHECKING([whether blkdev_put() exists])
ZFS_LINUX_TEST_RESULT([blkdev_put], [
AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_PUT, 1, [blkdev_put() exists])
], [
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether blkdev_put() accepts void* as arg 2])
@@ -168,7 +206,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [
AC_DEFINE(HAVE_BDEV_RELEASE, 1,
[bdev_release() exists])
], [
- ZFS_LINUX_TEST_ERROR([blkdev_put()])
+ AC_MSG_RESULT(no)
])
])
])
@@ -697,6 +735,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 35e2a573f..943e534ef 100644
--- a/module/os/linux/zfs/vdev_disk.c
+++ b/module/os/linux/zfs/vdev_disk.c
@@ -45,15 +45,25 @@
/*
* 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.
+ * just use the handle as a proxy.
+ *
+ * Linux 6.9.x uses a file for the same purpose.
+ *
+ * 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)
@@ -242,7 +252,9 @@ vdev_blkdev_get_by_path(const char *path, spa_mode_t smode, void *holder)
{
vdev_bdev_mode_t bmode = vdev_bdev_mode(smode);
-#if defined(HAVE_BDEV_OPEN_BY_PATH)
+#if defined(HAVE_BDEV_FILE_OPEN_BY_PATH)
+ return (bdev_file_open_by_path(path, bmode, holder, NULL));
+#elif defined(HAVE_BDEV_OPEN_BY_PATH)
return (bdev_open_by_path(path, bmode, holder, NULL));
#elif defined(HAVE_BLKDEV_GET_BY_PATH_4ARG)
return (blkdev_get_by_path(path, bmode, holder, NULL));
@@ -258,8 +270,10 @@ vdev_blkdev_put(zfs_bdev_handle_t *bdh, spa_mode_t smode, void *holder)
return (bdev_release(bdh));
#elif defined(HAVE_BLKDEV_PUT_HOLDER)
return (blkdev_put(BDH_BDEV(bdh), holder));
-#else
+#elif defined(HAVE_BLKDEV_PUT)
return (blkdev_put(BDH_BDEV(bdh), vdev_bdev_mode(smode)));
+#else
+ fput(bdh);
#endif
}