Linux 5.11 compat: lookup_bdev()

The lookup_bdev() function has been updated to require a dev_t
be passed as the second argument. This is actually pretty nice
since the major number stored in the dev_t was the only part we
were interested in. This allows to us avoid handling the bdev
entirely.  The vdev_lookup_bdev() wrapper was updated to emulate
the behavior of the new lookup_bdev() for all supported kernels.

Reviewed-by: Rafael Kitover <rkitover@gmail.com>
Reviewed-by: Coleman Kane <ckane@colemankane.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #11387
Closes #11390
This commit is contained in:
Brian Behlendorf 2020-12-22 10:26:45 -08:00
parent 944180ab50
commit 67cff6e4c1
3 changed files with 74 additions and 30 deletions

View File

@ -154,42 +154,69 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_INVALIDATE_BDEV], [
]) ])
dnl # dnl #
dnl # 2.6.27, lookup_bdev() was exported. dnl # 5.11 API, lookup_bdev() takes dev_t argument.
dnl # 4.4.0-6.21 - lookup_bdev() takes 2 arguments. dnl # 2.6.27 API, lookup_bdev() was first exported.
dnl # 4.4.0-6.21 API, lookup_bdev() on Ubuntu takes mode argument.
dnl # dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV], [ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV], [
ZFS_LINUX_TEST_SRC([lookup_bdev_devt], [
#include <linux/blkdev.h>
], [
int error __attribute__ ((unused));
const char path[] = "/example/path";
dev_t dev;
error = lookup_bdev(path, &dev);
])
ZFS_LINUX_TEST_SRC([lookup_bdev_1arg], [ ZFS_LINUX_TEST_SRC([lookup_bdev_1arg], [
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
], [ ], [
lookup_bdev(NULL); struct block_device *bdev __attribute__ ((unused));
const char path[] = "/example/path";
bdev = lookup_bdev(path);
]) ])
ZFS_LINUX_TEST_SRC([lookup_bdev_2args], [ ZFS_LINUX_TEST_SRC([lookup_bdev_mode], [
#include <linux/fs.h> #include <linux/fs.h>
], [ ], [
lookup_bdev(NULL, FMODE_READ); struct block_device *bdev __attribute__ ((unused));
const char path[] = "/example/path";
bdev = lookup_bdev(path, FMODE_READ);
]) ])
]) ])
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_LOOKUP_BDEV], [ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_LOOKUP_BDEV], [
AC_MSG_CHECKING([whether lookup_bdev() wants 1 arg]) AC_MSG_CHECKING([whether lookup_bdev() wants dev_t arg])
ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_1arg], ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_devt],
[lookup_bdev], [fs/block_dev.c], [ [lookup_bdev], [fs/block_dev.c], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_1ARG_LOOKUP_BDEV, 1, AC_DEFINE(HAVE_DEVT_LOOKUP_BDEV, 1,
[lookup_bdev() wants 1 arg]) [lookup_bdev() wants dev_t arg])
], [ ], [
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether lookup_bdev() wants 2 args]) AC_MSG_CHECKING([whether lookup_bdev() wants 1 arg])
ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_2args], ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_1arg],
[lookup_bdev], [fs/block_dev.c], [ [lookup_bdev], [fs/block_dev.c], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_2ARGS_LOOKUP_BDEV, 1, AC_DEFINE(HAVE_1ARG_LOOKUP_BDEV, 1,
[lookup_bdev() wants 2 args]) [lookup_bdev() wants 1 arg])
], [ ], [
ZFS_LINUX_TEST_ERROR([lookup_bdev()]) AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether lookup_bdev() wants mode arg])
ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_mode],
[lookup_bdev], [fs/block_dev.c], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_MODE_LOOKUP_BDEV, 1,
[lookup_bdev() wants mode arg])
], [
ZFS_LINUX_TEST_ERROR([lookup_bdev()])
])
]) ])
]) ])
]) ])

View File

@ -318,16 +318,38 @@ zfs_check_media_change(struct block_device *bdev)
* *
* 4.4.0-6.21 API change for Ubuntu * 4.4.0-6.21 API change for Ubuntu
* lookup_bdev() gained a second argument, FMODE_*, to check inode permissions. * lookup_bdev() gained a second argument, FMODE_*, to check inode permissions.
*
* 5.11 API change
* Changed to take a dev_t argument which is set on success and return a
* non-zero error code on failure.
*/ */
#ifdef HAVE_1ARG_LOOKUP_BDEV static inline int
#define vdev_lookup_bdev(path) lookup_bdev(path) vdev_lookup_bdev(const char *path, dev_t *dev)
#else {
#ifdef HAVE_2ARGS_LOOKUP_BDEV #if defined(HAVE_DEVT_LOOKUP_BDEV)
#define vdev_lookup_bdev(path) lookup_bdev(path, 0) return (lookup_bdev(path, dev));
#elif defined(HAVE_1ARG_LOOKUP_BDEV)
struct block_device *bdev = lookup_bdev(path);
if (IS_ERR(bdev))
return (PTR_ERR(bdev));
*dev = bdev->bd_dev;
bdput(bdev);
return (0);
#elif defined(HAVE_MODE_LOOKUP_BDEV)
struct block_device *bdev = lookup_bdev(path, FMODE_READ);
if (IS_ERR(bdev))
return (PTR_ERR(bdev));
*dev = bdev->bd_dev;
bdput(bdev);
return (0);
#else #else
#error "Unsupported kernel" #error "Unsupported kernel"
#endif /* HAVE_2ARGS_LOOKUP_BDEV */ #endif
#endif /* HAVE_1ARG_LOOKUP_BDEV */ }
/* /*
* Kernels without bio_set_op_attrs use bi_rw for the bio flags. * Kernels without bio_set_op_attrs use bi_rw for the bio flags.

View File

@ -66,19 +66,14 @@ typedef struct zv_request {
* Given a path, return TRUE if path is a ZVOL. * Given a path, return TRUE if path is a ZVOL.
*/ */
static boolean_t static boolean_t
zvol_is_zvol_impl(const char *device) zvol_is_zvol_impl(const char *path)
{ {
struct block_device *bdev; dev_t dev = 0;
unsigned int major;
bdev = vdev_lookup_bdev(device); if (vdev_lookup_bdev(path, &dev) != 0)
if (IS_ERR(bdev))
return (B_FALSE); return (B_FALSE);
major = MAJOR(bdev->bd_dev); if (MAJOR(dev) == zvol_major)
bdput(bdev);
if (major == zvol_major)
return (B_TRUE); return (B_TRUE);
return (B_FALSE); return (B_FALSE);