aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/module/zfs/zvol.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/module/zfs/zvol.c')
-rw-r--r--sys/contrib/openzfs/module/zfs/zvol.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/sys/contrib/openzfs/module/zfs/zvol.c b/sys/contrib/openzfs/module/zfs/zvol.c
index 2b20b02e4942..7c6dae8650c7 100644
--- a/sys/contrib/openzfs/module/zfs/zvol.c
+++ b/sys/contrib/openzfs/module/zfs/zvol.c
@@ -772,7 +772,7 @@ zvol_setup_zv(zvol_state_t *zv)
if (error)
return (SET_ERROR(error));
- error = dnode_hold(os, ZVOL_OBJ, FTAG, &zv->zv_dn);
+ error = dnode_hold(os, ZVOL_OBJ, zv, &zv->zv_dn);
if (error)
return (SET_ERROR(error));
@@ -807,7 +807,7 @@ zvol_shutdown_zv(zvol_state_t *zv)
zv->zv_zilog = NULL;
- dnode_rele(zv->zv_dn, FTAG);
+ dnode_rele(zv->zv_dn, zv);
zv->zv_dn = NULL;
/*
@@ -1376,7 +1376,9 @@ typedef struct zvol_volmode_cb_arg {
static void
zvol_set_volmode_impl(char *name, uint64_t volmode)
{
- fstrans_cookie_t cookie = spl_fstrans_mark();
+ fstrans_cookie_t cookie;
+ uint64_t old_volmode;
+ zvol_state_t *zv;
if (strchr(name, '@') != NULL)
return;
@@ -1386,9 +1388,18 @@ zvol_set_volmode_impl(char *name, uint64_t volmode)
* this is necessary because our backing gendisk (zvol_state->zv_disk)
* could be different when we set, for instance, volmode from "geom"
* to "dev" (or vice versa).
- * A possible optimization is to modify our consumers so we don't get
- * called when "volmode" does not change.
*/
+ zv = zvol_find_by_name(name, RW_NONE);
+ if (zv == NULL && volmode == ZFS_VOLMODE_NONE)
+ return;
+ if (zv != NULL) {
+ old_volmode = zv->zv_volmode;
+ mutex_exit(&zv->zv_state_lock);
+ if (old_volmode == volmode)
+ return;
+ zvol_wait_close(zv);
+ }
+ cookie = spl_fstrans_mark();
switch (volmode) {
case ZFS_VOLMODE_NONE:
(void) zvol_remove_minor_impl(name);
@@ -1406,7 +1417,6 @@ zvol_set_volmode_impl(char *name, uint64_t volmode)
(void) ops->zv_create_minor(name);
break;
}
-
spl_fstrans_unmark(cookie);
}