Linux 6.5 compat: blkdev changes
Multiple changes to the blkdev API were introduced in Linux 6.5. This includes passing (void* holder) to blkdev_put, adding a new blk_holder_ops* arg to blkdev_get_by_path, adding a new blk_mode_t type that replaces uses of fmode_t, and removing an argument from the release handler on block_device_operations that we weren't using. The open function definition has also changed to take gendisk* and blk_mode_t, so update it accordingly, too. Implement local wrappers for blkdev_get_by_path() and vdev_blkdev_put() so that the in-line calls are cleaner, and place the conditionally-compiled implementation details inside of both of these local wrappers. Both calls are exclusively used within vdev_disk.c, at this time. Add blk_mode_is_open_write() to test FMODE_WRITE / BLK_OPEN_WRITE The wrapper function is now used for testing using the appropriate method for the kernel, whether the open mode is writable or not. Emphasize fmode_t arg in zvol_release is not used Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Coleman Kane <ckane@colemankane.org> Closes #15099
This commit is contained in:
parent
3ff9e4f8ac
commit
7c0618bdb7
|
@ -16,12 +16,63 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH], [
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # 6.5.x API change,
|
||||||
|
dnl # blkdev_get_by_path() takes 4 args
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG], [
|
||||||
|
ZFS_LINUX_TEST_SRC([blkdev_get_by_path_4arg], [
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
], [
|
||||||
|
struct block_device *bdev __attribute__ ((unused)) = NULL;
|
||||||
|
const char *path = "path";
|
||||||
|
fmode_t mode = 0;
|
||||||
|
void *holder = NULL;
|
||||||
|
struct blk_holder_ops h;
|
||||||
|
|
||||||
|
bdev = blkdev_get_by_path(path, mode, holder, &h);
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [
|
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [
|
||||||
AC_MSG_CHECKING([whether blkdev_get_by_path() exists])
|
AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 3 args])
|
||||||
ZFS_LINUX_TEST_RESULT([blkdev_get_by_path], [
|
ZFS_LINUX_TEST_RESULT([blkdev_get_by_path], [
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
], [
|
], [
|
||||||
ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 4 args])
|
||||||
|
ZFS_LINUX_TEST_RESULT([blkdev_get_by_path_4arg], [
|
||||||
|
AC_DEFINE(HAVE_BLKDEV_GET_BY_PATH_4ARG, 1,
|
||||||
|
[blkdev_get_by_path() exists and takes 4 args])
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
], [
|
||||||
|
ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # 6.5.x API change
|
||||||
|
dnl # blk_mode_t was added as a type to supercede some places where fmode_t
|
||||||
|
dnl # is used
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BLK_MODE_T], [
|
||||||
|
ZFS_LINUX_TEST_SRC([blk_mode_t], [
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
], [
|
||||||
|
blk_mode_t m __attribute((unused)) = (blk_mode_t)0;
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BLK_MODE_T], [
|
||||||
|
AC_MSG_CHECKING([whether blk_mode_t is defined])
|
||||||
|
ZFS_LINUX_TEST_RESULT([blk_mode_t], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_BLK_MODE_T, 1, [blk_mode_t is defined])
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -41,12 +92,35 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PUT], [
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # 6.5.x API change.
|
||||||
|
dnl # blkdev_put() takes (void* holder) as arg 2
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER], [
|
||||||
|
ZFS_LINUX_TEST_SRC([blkdev_put_holder], [
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
], [
|
||||||
|
struct block_device *bdev = NULL;
|
||||||
|
void *holder = NULL;
|
||||||
|
|
||||||
|
blkdev_put(bdev, holder);
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [
|
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [
|
||||||
AC_MSG_CHECKING([whether blkdev_put() exists])
|
AC_MSG_CHECKING([whether blkdev_put() exists])
|
||||||
ZFS_LINUX_TEST_RESULT([blkdev_put], [
|
ZFS_LINUX_TEST_RESULT([blkdev_put], [
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
], [
|
], [
|
||||||
ZFS_LINUX_TEST_ERROR([blkdev_put()])
|
AC_MSG_CHECKING([whether blkdev_put() accepts void* as arg 2])
|
||||||
|
ZFS_LINUX_TEST_RESULT([blkdev_put_holder], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_BLKDEV_PUT_HOLDER, 1,
|
||||||
|
[blkdev_put() accepts void* as arg 2])
|
||||||
|
], [
|
||||||
|
ZFS_LINUX_TEST_ERROR([blkdev_put()])
|
||||||
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -495,7 +569,9 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT], [
|
||||||
|
|
||||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH
|
ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH
|
||||||
|
ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_PUT
|
ZFS_AC_KERNEL_SRC_BLKDEV_PUT
|
||||||
|
ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART
|
ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_INVALIDATE_BDEV
|
ZFS_AC_KERNEL_SRC_BLKDEV_INVALIDATE_BDEV
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV
|
ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV
|
||||||
|
@ -510,6 +586,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV
|
ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_DISK_CHECK_MEDIA_CHANGE
|
ZFS_AC_KERNEL_SRC_BLKDEV_DISK_CHECK_MEDIA_CHANGE
|
||||||
ZFS_AC_KERNEL_SRC_BLKDEV_BLK_STS_RESV_CONFLICT
|
ZFS_AC_KERNEL_SRC_BLKDEV_BLK_STS_RESV_CONFLICT
|
||||||
|
ZFS_AC_KERNEL_SRC_BLKDEV_BLK_MODE_T
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
||||||
|
@ -530,4 +607,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
||||||
ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV
|
ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV
|
||||||
ZFS_AC_KERNEL_BLKDEV_DISK_CHECK_MEDIA_CHANGE
|
ZFS_AC_KERNEL_BLKDEV_DISK_CHECK_MEDIA_CHANGE
|
||||||
ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT
|
ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT
|
||||||
|
ZFS_AC_KERNEL_BLKDEV_BLK_MODE_T
|
||||||
])
|
])
|
||||||
|
|
|
@ -49,12 +49,42 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
|
||||||
], [], [])
|
], [], [])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # 5.9.x API change
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG], [
|
||||||
|
ZFS_LINUX_TEST_SRC([block_device_operations_release_void_1arg], [
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
|
||||||
|
void blk_release(struct gendisk *g) {
|
||||||
|
(void) g;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct block_device_operations
|
||||||
|
bops __attribute__ ((unused)) = {
|
||||||
|
.open = NULL,
|
||||||
|
.release = blk_release,
|
||||||
|
.ioctl = NULL,
|
||||||
|
.compat_ioctl = NULL,
|
||||||
|
};
|
||||||
|
], [], [])
|
||||||
|
])
|
||||||
|
|
||||||
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
|
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
|
||||||
AC_MSG_CHECKING([whether bops->release() is void])
|
AC_MSG_CHECKING([whether bops->release() is void and takes 2 args])
|
||||||
ZFS_LINUX_TEST_RESULT([block_device_operations_release_void], [
|
ZFS_LINUX_TEST_RESULT([block_device_operations_release_void], [
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
],[
|
],[
|
||||||
ZFS_LINUX_TEST_ERROR([bops->release()])
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_CHECKING([whether bops->release() is void and takes 1 arg])
|
||||||
|
ZFS_LINUX_TEST_RESULT([block_device_operations_release_void_1arg], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG], [1],
|
||||||
|
[Define if release() in block_device_operations takes 1 arg])
|
||||||
|
],[
|
||||||
|
ZFS_LINUX_TEST_ERROR([bops->release()])
|
||||||
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -92,6 +122,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
|
||||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
|
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_CHECK_EVENTS
|
||||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
|
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_REVALIDATE_DISK
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -387,6 +387,12 @@ vdev_lookup_bdev(const char *path, dev_t *dev)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_BLK_MODE_T)
|
||||||
|
#define blk_mode_is_open_write(flag) ((flag) & BLK_OPEN_WRITE)
|
||||||
|
#else
|
||||||
|
#define blk_mode_is_open_write(flag) ((flag) & FMODE_WRITE)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -74,9 +74,22 @@ typedef struct dio_request {
|
||||||
struct bio *dr_bio[0]; /* Attached bio's */
|
struct bio *dr_bio[0]; /* Attached bio's */
|
||||||
} dio_request_t;
|
} dio_request_t;
|
||||||
|
|
||||||
|
#ifdef HAVE_BLK_MODE_T
|
||||||
|
static blk_mode_t
|
||||||
|
#else
|
||||||
static fmode_t
|
static fmode_t
|
||||||
|
#endif
|
||||||
vdev_bdev_mode(spa_mode_t spa_mode)
|
vdev_bdev_mode(spa_mode_t spa_mode)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_BLK_MODE_T
|
||||||
|
blk_mode_t mode = 0;
|
||||||
|
|
||||||
|
if (spa_mode & SPA_MODE_READ)
|
||||||
|
mode |= BLK_OPEN_READ;
|
||||||
|
|
||||||
|
if (spa_mode & SPA_MODE_WRITE)
|
||||||
|
mode |= BLK_OPEN_WRITE;
|
||||||
|
#else
|
||||||
fmode_t mode = 0;
|
fmode_t mode = 0;
|
||||||
|
|
||||||
if (spa_mode & SPA_MODE_READ)
|
if (spa_mode & SPA_MODE_READ)
|
||||||
|
@ -84,6 +97,7 @@ vdev_bdev_mode(spa_mode_t spa_mode)
|
||||||
|
|
||||||
if (spa_mode & SPA_MODE_WRITE)
|
if (spa_mode & SPA_MODE_WRITE)
|
||||||
mode |= FMODE_WRITE;
|
mode |= FMODE_WRITE;
|
||||||
|
#endif
|
||||||
|
|
||||||
return (mode);
|
return (mode);
|
||||||
}
|
}
|
||||||
|
@ -191,12 +205,47 @@ vdev_disk_kobj_evt_post(vdev_t *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(HAVE_BLKDEV_GET_BY_PATH_4ARG)
|
||||||
|
/*
|
||||||
|
* Define a dummy struct blk_holder_ops for kernel versions
|
||||||
|
* prior to 6.5.
|
||||||
|
*/
|
||||||
|
struct blk_holder_ops {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct block_device *
|
||||||
|
vdev_blkdev_get_by_path(const char *path, spa_mode_t mode, void *holder,
|
||||||
|
const struct blk_holder_ops *hops)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_BLKDEV_GET_BY_PATH_4ARG
|
||||||
|
return (blkdev_get_by_path(path,
|
||||||
|
vdev_bdev_mode(mode) | BLK_OPEN_EXCL, holder, hops));
|
||||||
|
#else
|
||||||
|
return (blkdev_get_by_path(path,
|
||||||
|
vdev_bdev_mode(mode) | FMODE_EXCL, holder));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vdev_blkdev_put(struct block_device *bdev, spa_mode_t mode, void *holder)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_BLKDEV_PUT_HOLDER
|
||||||
|
return (blkdev_put(bdev, holder));
|
||||||
|
#else
|
||||||
|
return (blkdev_put(bdev, vdev_bdev_mode(mode) | FMODE_EXCL));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||||
uint64_t *logical_ashift, uint64_t *physical_ashift)
|
uint64_t *logical_ashift, uint64_t *physical_ashift)
|
||||||
{
|
{
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
|
#ifdef HAVE_BLK_MODE_T
|
||||||
|
blk_mode_t mode = vdev_bdev_mode(spa_mode(v->vdev_spa));
|
||||||
|
#else
|
||||||
fmode_t mode = vdev_bdev_mode(spa_mode(v->vdev_spa));
|
fmode_t mode = vdev_bdev_mode(spa_mode(v->vdev_spa));
|
||||||
|
#endif
|
||||||
hrtime_t timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms);
|
hrtime_t timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms);
|
||||||
vdev_disk_t *vd;
|
vdev_disk_t *vd;
|
||||||
|
|
||||||
|
@ -246,15 +295,15 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||||
reread_part = B_TRUE;
|
reread_part = B_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkdev_put(bdev, mode | FMODE_EXCL);
|
vdev_blkdev_put(bdev, mode, zfs_vdev_holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reread_part) {
|
if (reread_part) {
|
||||||
bdev = blkdev_get_by_path(disk_name, mode | FMODE_EXCL,
|
bdev = vdev_blkdev_get_by_path(disk_name, mode,
|
||||||
zfs_vdev_holder);
|
zfs_vdev_holder, NULL);
|
||||||
if (!IS_ERR(bdev)) {
|
if (!IS_ERR(bdev)) {
|
||||||
int error = vdev_bdev_reread_part(bdev);
|
int error = vdev_bdev_reread_part(bdev);
|
||||||
blkdev_put(bdev, mode | FMODE_EXCL);
|
vdev_blkdev_put(bdev, mode, zfs_vdev_holder);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
timeout = MSEC2NSEC(
|
timeout = MSEC2NSEC(
|
||||||
zfs_vdev_open_timeout_ms * 2);
|
zfs_vdev_open_timeout_ms * 2);
|
||||||
|
@ -299,8 +348,8 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||||
hrtime_t start = gethrtime();
|
hrtime_t start = gethrtime();
|
||||||
bdev = ERR_PTR(-ENXIO);
|
bdev = ERR_PTR(-ENXIO);
|
||||||
while (IS_ERR(bdev) && ((gethrtime() - start) < timeout)) {
|
while (IS_ERR(bdev) && ((gethrtime() - start) < timeout)) {
|
||||||
bdev = blkdev_get_by_path(v->vdev_path, mode | FMODE_EXCL,
|
bdev = vdev_blkdev_get_by_path(v->vdev_path, mode,
|
||||||
zfs_vdev_holder);
|
zfs_vdev_holder, NULL);
|
||||||
if (unlikely(PTR_ERR(bdev) == -ENOENT)) {
|
if (unlikely(PTR_ERR(bdev) == -ENOENT)) {
|
||||||
/*
|
/*
|
||||||
* There is no point of waiting since device is removed
|
* There is no point of waiting since device is removed
|
||||||
|
@ -376,8 +425,8 @@ vdev_disk_close(vdev_t *v)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (vd->vd_bdev != NULL) {
|
if (vd->vd_bdev != NULL) {
|
||||||
blkdev_put(vd->vd_bdev,
|
vdev_blkdev_put(vd->vd_bdev, spa_mode(v->vdev_spa),
|
||||||
vdev_bdev_mode(spa_mode(v->vdev_spa)) | FMODE_EXCL);
|
zfs_vdev_holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
rw_destroy(&vd->vd_lock);
|
rw_destroy(&vd->vd_lock);
|
||||||
|
|
|
@ -198,7 +198,7 @@ zfs_open(struct inode *ip, int mode, int flag, cred_t *cr)
|
||||||
ZFS_VERIFY_ZP(zp);
|
ZFS_VERIFY_ZP(zp);
|
||||||
|
|
||||||
/* Honor ZFS_APPENDONLY file attribute */
|
/* Honor ZFS_APPENDONLY file attribute */
|
||||||
if ((mode & FMODE_WRITE) && (zp->z_pflags & ZFS_APPENDONLY) &&
|
if (blk_mode_is_open_write(mode) && (zp->z_pflags & ZFS_APPENDONLY) &&
|
||||||
((flag & O_APPEND) == 0)) {
|
((flag & O_APPEND) == 0)) {
|
||||||
ZFS_EXIT(zfsvfs);
|
ZFS_EXIT(zfsvfs);
|
||||||
return (SET_ERROR(EPERM));
|
return (SET_ERROR(EPERM));
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
static int
|
static int
|
||||||
zpl_common_open(struct inode *ip, struct file *filp)
|
zpl_common_open(struct inode *ip, struct file *filp)
|
||||||
{
|
{
|
||||||
if (filp->f_mode & FMODE_WRITE)
|
if (blk_mode_is_open_write(filp->f_mode))
|
||||||
return (-EACCES);
|
return (-EACCES);
|
||||||
|
|
||||||
return (generic_file_open(ip, filp));
|
return (generic_file_open(ip, filp));
|
||||||
|
|
|
@ -492,7 +492,11 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
#ifdef HAVE_BLK_MODE_T
|
||||||
|
zvol_open(struct gendisk *disk, blk_mode_t flag)
|
||||||
|
#else
|
||||||
zvol_open(struct block_device *bdev, fmode_t flag)
|
zvol_open(struct block_device *bdev, fmode_t flag)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
zvol_state_t *zv;
|
zvol_state_t *zv;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
@ -507,10 +511,14 @@ retry:
|
||||||
/*
|
/*
|
||||||
* Obtain a copy of private_data under the zvol_state_lock to make
|
* Obtain a copy of private_data under the zvol_state_lock to make
|
||||||
* sure that either the result of zvol free code path setting
|
* sure that either the result of zvol free code path setting
|
||||||
* bdev->bd_disk->private_data to NULL is observed, or zvol_free()
|
* disk->private_data to NULL is observed, or zvol_os_free()
|
||||||
* is not called on this zv because of the positive zv_open_count.
|
* is not called on this zv because of the positive zv_open_count.
|
||||||
*/
|
*/
|
||||||
|
#ifdef HAVE_BLK_MODE_T
|
||||||
|
zv = disk->private_data;
|
||||||
|
#else
|
||||||
zv = bdev->bd_disk->private_data;
|
zv = bdev->bd_disk->private_data;
|
||||||
|
#endif
|
||||||
if (zv == NULL) {
|
if (zv == NULL) {
|
||||||
rw_exit(&zvol_state_lock);
|
rw_exit(&zvol_state_lock);
|
||||||
return (SET_ERROR(-ENXIO));
|
return (SET_ERROR(-ENXIO));
|
||||||
|
@ -590,14 +598,15 @@ retry:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = -zvol_first_open(zv, !(flag & FMODE_WRITE));
|
error = -zvol_first_open(zv, !(blk_mode_is_open_write(flag)));
|
||||||
|
|
||||||
if (drop_namespace)
|
if (drop_namespace)
|
||||||
mutex_exit(&spa_namespace_lock);
|
mutex_exit(&spa_namespace_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
if ((flag & FMODE_WRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
|
if ((blk_mode_is_open_write(flag)) &&
|
||||||
|
(zv->zv_flags & ZVOL_RDONLY)) {
|
||||||
if (zv->zv_open_count == 0)
|
if (zv->zv_open_count == 0)
|
||||||
zvol_last_close(zv);
|
zvol_last_close(zv);
|
||||||
|
|
||||||
|
@ -612,14 +621,25 @@ retry:
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
|
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
|
#ifdef HAVE_BLK_MODE_T
|
||||||
|
disk_check_media_change(disk);
|
||||||
|
#else
|
||||||
zfs_check_media_change(bdev);
|
zfs_check_media_change(bdev);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zvol_release(struct gendisk *disk, fmode_t mode)
|
#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
|
||||||
|
zvol_release(struct gendisk *disk)
|
||||||
|
#else
|
||||||
|
zvol_release(struct gendisk *disk, fmode_t unused)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#if !defined(HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG)
|
||||||
|
(void) unused;
|
||||||
|
#endif
|
||||||
zvol_state_t *zv;
|
zvol_state_t *zv;
|
||||||
boolean_t drop_suspend = B_TRUE;
|
boolean_t drop_suspend = B_TRUE;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue