1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
From 39db4bda8078eb83776ad7ac90ecb6cdcbd083eb Mon Sep 17 00:00:00 2001
From: Rob Norris <robn@despairlabs.com>
Date: Fri, 12 Sep 2025 10:23:28 +1000
Subject: [PATCH 2/6] Linux 6.18: block_device_operations->getgeo takes struct
gendisk*
Sponsored-by: https://despairlabs.com/sponsor/
Signed-off-by: Rob Norris <robn@despairlabs.com>
Last-Update: 2025-11-19
[john-cabaj: context changes in zvol_getgeo_impl()]
Signed-off-by: John Cabaj <john.cabaj@canonical.com>
---
config/kernel-block-device-operations.m4 | 34 ++++++++++++++++++++++++
module/os/linux/zfs/zvol_os.c | 20 +++++++++++---
2 files changed, 51 insertions(+), 3 deletions(-)
--- a/config/kernel-block-device-operations.m4
+++ b/config/kernel-block-device-operations.m4
@@ -119,15 +119,49 @@
])
])
+dnl #
+dnl # 6.18 API change
+dnl # block_device_operation->getgeo takes struct gendisk* as first arg
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
+ ZFS_LINUX_TEST_SRC([block_device_operations_getgeo_gendisk], [
+ #include <linux/blkdev.h>
+
+ static int blk_getgeo(struct gendisk *disk, struct hd_geometry *geo)
+ {
+ (void) disk, (void) geo;
+ return (0);
+ }
+
+ static const struct block_device_operations
+ bops __attribute__ ((unused)) = {
+ .getgeo = blk_getgeo,
+ };
+ ], [], [])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
+ AC_MSG_CHECKING([whether bops->getgeo() takes gendisk as first arg])
+ ZFS_LINUX_TEST_RESULT([block_device_operations_getgeo_gendisk], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [1],
+ [Define if getgeo() in block_device_operations takes struct gendisk * as its first arg])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
+ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
])
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS], [
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
+ ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
])
--- a/module/os/linux/zfs/zvol_os.c
+++ b/module/os/linux/zfs/zvol_os.c
@@ -1067,10 +1067,10 @@
* tiny devices. For devices over 1 Mib a standard head and sector count
* is used to keep the cylinders count reasonable.
*/
-static int
-zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+static inline int
+zvol_getgeo_impl(struct gendisk *disk, struct hd_geometry *geo)
{
- zvol_state_t *zv = bdev->bd_disk->private_data;
+ zvol_state_t *zv = atomic_load_ptr(&disk->private_data);
sector_t sectors;
ASSERT3U(zv->zv_open_count, >, 0);
@@ -1091,6 +1091,20 @@
return (0);
}
+#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
+static int
+zvol_getgeo(struct gendisk *disk, struct hd_geometry *geo)
+{
+ return (zvol_getgeo_impl(disk, geo));
+}
+#else
+static int
+zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ return (zvol_getgeo_impl(bdev->bd_disk, geo));
+}
+#endif
+
/*
* Why have two separate block_device_operations structs?
*
|