mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-01-25 10:12:13 +03:00
zvol: cleanup error handling and passthrough
This is trying to get all the uses and non-uses of SET_ERROR correct (being: only call it if we're the originator of an error _within ZFS_), and correctly negating errors going to/from the kernel. And/or both. Sponsored-by: Klara, Inc. Sponsored-by: Railway Corporation Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #17605
This commit is contained in:
parent
90a1e13df2
commit
2fd145b578
@ -84,8 +84,9 @@ static unsigned int zvol_blk_mq_blocks_per_thread = 8;
|
|||||||
static inline void
|
static inline void
|
||||||
zvol_end_io(struct bio *bio, struct request *rq, int error)
|
zvol_end_io(struct bio *bio, struct request *rq, int error)
|
||||||
{
|
{
|
||||||
|
ASSERT3U(error, >=, 0);
|
||||||
if (bio) {
|
if (bio) {
|
||||||
bio->bi_status = errno_to_bi_status(-error);
|
bio->bi_status = errno_to_bi_status(error);
|
||||||
bio_endio(bio);
|
bio_endio(bio);
|
||||||
} else {
|
} else {
|
||||||
blk_mq_end_request(rq, errno_to_bi_status(error));
|
blk_mq_end_request(rq, errno_to_bi_status(error));
|
||||||
@ -288,7 +289,7 @@ zvol_write(zv_request_t *zvr)
|
|||||||
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
|
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
zvol_end_io(bio, rq, -error);
|
zvol_end_io(bio, rq, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -377,7 +378,7 @@ unlock:
|
|||||||
start_time);
|
start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
zvol_end_io(bio, rq, -error);
|
zvol_end_io(bio, rq, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -455,7 +456,7 @@ zvol_read(zv_request_t *zvr)
|
|||||||
blk_generic_end_io_acct(q, disk, READ, bio, start_time);
|
blk_generic_end_io_acct(q, disk, READ, bio, start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
zvol_end_io(bio, rq, -error);
|
zvol_end_io(bio, rq, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -486,7 +487,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
|
|||||||
int rw = io_data_dir(bio, rq);
|
int rw = io_data_dir(bio, rq);
|
||||||
|
|
||||||
if (unlikely(zv->zv_flags & ZVOL_REMOVING)) {
|
if (unlikely(zv->zv_flags & ZVOL_REMOVING)) {
|
||||||
zvol_end_io(bio, rq, -SET_ERROR(ENXIO));
|
zvol_end_io(bio, rq, SET_ERROR(ENXIO));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +506,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
|
|||||||
(long long unsigned)offset,
|
(long long unsigned)offset,
|
||||||
(long unsigned)size);
|
(long unsigned)size);
|
||||||
|
|
||||||
zvol_end_io(bio, rq, -SET_ERROR(EIO));
|
zvol_end_io(bio, rq, SET_ERROR(EIO));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +528,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
|
|||||||
|
|
||||||
if (rw == WRITE) {
|
if (rw == WRITE) {
|
||||||
if (unlikely(zv->zv_flags & ZVOL_RDONLY)) {
|
if (unlikely(zv->zv_flags & ZVOL_RDONLY)) {
|
||||||
zvol_end_io(bio, rq, -SET_ERROR(EROFS));
|
zvol_end_io(bio, rq, SET_ERROR(EROFS));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,16 +893,18 @@ zvol_ioctl(struct block_device *bdev, fmode_t mode,
|
|||||||
|
|
||||||
case BLKZNAME:
|
case BLKZNAME:
|
||||||
mutex_enter(&zv->zv_state_lock);
|
mutex_enter(&zv->zv_state_lock);
|
||||||
error = copy_to_user((void *)arg, zv->zv_name, MAXNAMELEN);
|
error = -copy_to_user((void *)arg, zv->zv_name, MAXNAMELEN);
|
||||||
mutex_exit(&zv->zv_state_lock);
|
mutex_exit(&zv->zv_state_lock);
|
||||||
|
if (error)
|
||||||
|
error = SET_ERROR(error);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error = -ENOTTY;
|
error = SET_ERROR(ENOTTY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (SET_ERROR(error));
|
return (-error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
@ -1480,7 +1483,9 @@ __zvol_os_add_disk(struct gendisk *disk)
|
|||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
#ifdef HAVE_ADD_DISK_RET
|
#ifdef HAVE_ADD_DISK_RET
|
||||||
error = add_disk(disk);
|
error = -add_disk(disk);
|
||||||
|
if (error)
|
||||||
|
error = SET_ERROR(error);
|
||||||
#else
|
#else
|
||||||
add_disk(disk);
|
add_disk(disk);
|
||||||
#endif
|
#endif
|
||||||
@ -1765,10 +1770,10 @@ zvol_init(void)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = register_blkdev(zvol_major, ZVOL_DRIVER);
|
error = -register_blkdev(zvol_major, ZVOL_DRIVER);
|
||||||
if (error) {
|
if (error) {
|
||||||
printk(KERN_INFO "ZFS: register_blkdev() failed %d\n", error);
|
printk(KERN_INFO "ZFS: register_blkdev() failed %d\n", error);
|
||||||
return (error);
|
return (SET_ERROR(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zvol_blk_mq_queue_depth == 0) {
|
if (zvol_blk_mq_queue_depth == 0) {
|
||||||
|
|||||||
@ -253,7 +253,7 @@ zvol_get_stats(objset_t *os, nvlist_t *nv)
|
|||||||
|
|
||||||
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
|
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
|
||||||
if (error)
|
if (error)
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
|
|
||||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);
|
||||||
doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP);
|
doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP);
|
||||||
@ -266,7 +266,7 @@ zvol_get_stats(objset_t *os, nvlist_t *nv)
|
|||||||
|
|
||||||
kmem_free(doi, sizeof (dmu_object_info_t));
|
kmem_free(doi, sizeof (dmu_object_info_t));
|
||||||
|
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -304,7 +304,7 @@ zvol_update_volsize(uint64_t volsize, objset_t *os)
|
|||||||
error = dmu_tx_assign(tx, DMU_TX_WAIT);
|
error = dmu_tx_assign(tx, DMU_TX_WAIT);
|
||||||
if (error) {
|
if (error) {
|
||||||
dmu_tx_abort(tx);
|
dmu_tx_abort(tx);
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
txg = dmu_tx_get_txg(tx);
|
txg = dmu_tx_get_txg(tx);
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ zvol_set_volsize(const char *name, uint64_t volsize)
|
|||||||
error = dsl_prop_get_integer(name,
|
error = dsl_prop_get_integer(name,
|
||||||
zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL);
|
zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
if (readonly)
|
if (readonly)
|
||||||
return (SET_ERROR(EROFS));
|
return (SET_ERROR(EROFS));
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ zvol_set_volsize(const char *name, uint64_t volsize)
|
|||||||
FTAG, &os)) != 0) {
|
FTAG, &os)) != 0) {
|
||||||
if (zv != NULL)
|
if (zv != NULL)
|
||||||
mutex_exit(&zv->zv_state_lock);
|
mutex_exit(&zv->zv_state_lock);
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
owned = B_TRUE;
|
owned = B_TRUE;
|
||||||
if (zv != NULL)
|
if (zv != NULL)
|
||||||
@ -389,7 +389,7 @@ out:
|
|||||||
if (error == 0 && zv != NULL)
|
if (error == 0 && zv != NULL)
|
||||||
zvol_os_update_volsize(zv, volsize);
|
zvol_os_update_volsize(zv, volsize);
|
||||||
|
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -400,7 +400,7 @@ zvol_set_volthreading(const char *name, boolean_t value)
|
|||||||
{
|
{
|
||||||
zvol_state_t *zv = zvol_find_by_name(name, RW_NONE);
|
zvol_state_t *zv = zvol_find_by_name(name, RW_NONE);
|
||||||
if (zv == NULL)
|
if (zv == NULL)
|
||||||
return (ENOENT);
|
return (SET_ERROR(ENOENT));
|
||||||
zv->zv_threading = value;
|
zv->zv_threading = value;
|
||||||
mutex_exit(&zv->zv_state_lock);
|
mutex_exit(&zv->zv_state_lock);
|
||||||
return (0);
|
return (0);
|
||||||
@ -619,7 +619,7 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst,
|
|||||||
dmu_tx_t *tx;
|
dmu_tx_t *tx;
|
||||||
blkptr_t *bps;
|
blkptr_t *bps;
|
||||||
size_t maxblocks;
|
size_t maxblocks;
|
||||||
int error = EINVAL;
|
int error = 0;
|
||||||
|
|
||||||
rw_enter(&zv_dst->zv_suspend_lock, RW_READER);
|
rw_enter(&zv_dst->zv_suspend_lock, RW_READER);
|
||||||
if (zv_dst->zv_zilog == NULL) {
|
if (zv_dst->zv_zilog == NULL) {
|
||||||
@ -645,23 +645,22 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst,
|
|||||||
*/
|
*/
|
||||||
if (!spa_feature_is_enabled(dmu_objset_spa(outos),
|
if (!spa_feature_is_enabled(dmu_objset_spa(outos),
|
||||||
SPA_FEATURE_BLOCK_CLONING)) {
|
SPA_FEATURE_BLOCK_CLONING)) {
|
||||||
error = EOPNOTSUPP;
|
error = SET_ERROR(EOPNOTSUPP);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (dmu_objset_spa(inos) != dmu_objset_spa(outos)) {
|
if (dmu_objset_spa(inos) != dmu_objset_spa(outos)) {
|
||||||
error = EXDEV;
|
error = SET_ERROR(EXDEV);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (inos->os_encrypted != outos->os_encrypted) {
|
if (inos->os_encrypted != outos->os_encrypted) {
|
||||||
error = EXDEV;
|
error = SET_ERROR(EXDEV);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (zv_src->zv_volblocksize != zv_dst->zv_volblocksize) {
|
if (zv_src->zv_volblocksize != zv_dst->zv_volblocksize) {
|
||||||
error = EINVAL;
|
error = SET_ERROR(EINVAL);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (inoff >= zv_src->zv_volsize || outoff >= zv_dst->zv_volsize) {
|
if (inoff >= zv_src->zv_volsize || outoff >= zv_dst->zv_volsize) {
|
||||||
error = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,17 +671,15 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst,
|
|||||||
len = zv_src->zv_volsize - inoff;
|
len = zv_src->zv_volsize - inoff;
|
||||||
if (len > zv_dst->zv_volsize - outoff)
|
if (len > zv_dst->zv_volsize - outoff)
|
||||||
len = zv_dst->zv_volsize - outoff;
|
len = zv_dst->zv_volsize - outoff;
|
||||||
if (len == 0) {
|
if (len == 0)
|
||||||
error = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No overlapping if we are cloning within the same file
|
* No overlapping if we are cloning within the same file
|
||||||
*/
|
*/
|
||||||
if (zv_src == zv_dst) {
|
if (zv_src == zv_dst) {
|
||||||
if (inoff < outoff + len && outoff < inoff + len) {
|
if (inoff < outoff + len && outoff < inoff + len) {
|
||||||
error = EINVAL;
|
error = SET_ERROR(EINVAL);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -692,7 +689,7 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst,
|
|||||||
*/
|
*/
|
||||||
if ((inoff % zv_src->zv_volblocksize) != 0 ||
|
if ((inoff % zv_src->zv_volblocksize) != 0 ||
|
||||||
(outoff % zv_dst->zv_volblocksize) != 0) {
|
(outoff % zv_dst->zv_volblocksize) != 0) {
|
||||||
error = EINVAL;
|
error = SET_ERROR(EINVAL);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,7 +697,7 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst,
|
|||||||
* Length must be multiple of block size
|
* Length must be multiple of block size
|
||||||
*/
|
*/
|
||||||
if ((len % zv_src->zv_volblocksize) != 0) {
|
if ((len % zv_src->zv_volblocksize) != 0) {
|
||||||
error = EINVAL;
|
error = SET_ERROR(EINVAL);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,7 +775,7 @@ out:
|
|||||||
if (zv_src != zv_dst)
|
if (zv_src != zv_dst)
|
||||||
rw_exit(&zv_src->zv_suspend_lock);
|
rw_exit(&zv_src->zv_suspend_lock);
|
||||||
rw_exit(&zv_dst->zv_suspend_lock);
|
rw_exit(&zv_dst->zv_suspend_lock);
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1027,7 +1024,7 @@ zvol_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
|
|||||||
|
|
||||||
zvol_get_done(zgd, error);
|
zvol_get_done(zgd, error);
|
||||||
|
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1072,15 +1069,15 @@ zvol_setup_zv(zvol_state_t *zv)
|
|||||||
|
|
||||||
error = dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL);
|
error = dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
|
|
||||||
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
|
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
|
||||||
if (error)
|
if (error)
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
|
|
||||||
error = dnode_hold(os, ZVOL_OBJ, zv, &zv->zv_dn);
|
error = dnode_hold(os, ZVOL_OBJ, zv, &zv->zv_dn);
|
||||||
if (error)
|
if (error)
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
|
|
||||||
zvol_os_set_capacity(zv, volsize >> 9);
|
zvol_os_set_capacity(zv, volsize >> 9);
|
||||||
zv->zv_volsize = volsize;
|
zv->zv_volsize = volsize;
|
||||||
@ -1199,7 +1196,7 @@ zvol_resume(zvol_state_t *zv)
|
|||||||
if (zv->zv_flags & ZVOL_REMOVING)
|
if (zv->zv_flags & ZVOL_REMOVING)
|
||||||
cv_broadcast(&zv->zv_removing_cv);
|
cv_broadcast(&zv->zv_removing_cv);
|
||||||
|
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1215,7 +1212,7 @@ zvol_first_open(zvol_state_t *zv, boolean_t readonly)
|
|||||||
boolean_t ro = (readonly || (strchr(zv->zv_name, '@') != NULL));
|
boolean_t ro = (readonly || (strchr(zv->zv_name, '@') != NULL));
|
||||||
error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, ro, B_TRUE, zv, &os);
|
error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, ro, B_TRUE, zv, &os);
|
||||||
if (error)
|
if (error)
|
||||||
return (SET_ERROR(error));
|
return (error);
|
||||||
|
|
||||||
zv->zv_objset = os;
|
zv->zv_objset = os;
|
||||||
|
|
||||||
@ -1725,7 +1722,7 @@ zvol_remove_minor_impl(const char *name)
|
|||||||
|
|
||||||
if (zv == NULL) {
|
if (zv == NULL) {
|
||||||
rw_exit(&zvol_state_lock);
|
rw_exit(&zvol_state_lock);
|
||||||
return (ENOENT);
|
return (SET_ERROR(ENOENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
|
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user