diff --git a/include/sys/zvol.h b/include/sys/zvol.h index c9eefbeb48..c79fe1d9ad 100644 --- a/include/sys/zvol.h +++ b/include/sys/zvol.h @@ -52,6 +52,7 @@ extern void zvol_create_cb(objset_t *, void *, cred_t *, dmu_tx_t *); extern int zvol_set_volsize(const char *, uint64_t); extern int zvol_set_volthreading(const char *, boolean_t); extern int zvol_set_common(const char *, zfs_prop_t, zprop_source_t, uint64_t); +extern int zvol_set_ro(const char *, boolean_t); extern zvol_state_handle_t *zvol_suspend(const char *); extern int zvol_resume(zvol_state_handle_t *); extern void *zvol_tag(zvol_state_handle_t *); diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index c4e99b34a1..b2b06881bd 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -2535,6 +2535,15 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source, case ZFS_PROP_VOLMODE: err = zvol_set_common(dsname, prop, source, intval); break; + case ZFS_PROP_READONLY: + err = zvol_set_ro(dsname, intval); + /* + * Set err to -1 to force the zfs_set_prop_nvlist code down the + * default path to set the value in the nvlist. + */ + if (err == 0) + err = -1; + break; case ZFS_PROP_VERSION: { zfsvfs_t *zfsvfs; diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index d5f0693992..c7e10fbc63 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -383,6 +383,26 @@ zvol_set_volthreading(const char *name, boolean_t value) return (0); } +/* + * Update zvol ro property. + */ +int +zvol_set_ro(const char *name, boolean_t value) +{ + zvol_state_t *zv = zvol_find_by_name(name, RW_NONE); + if (zv == NULL) + return (-1); + if (value) { + zvol_os_set_disk_ro(zv, 1); + zv->zv_flags |= ZVOL_RDONLY; + } else { + zvol_os_set_disk_ro(zv, 0); + zv->zv_flags &= ~ZVOL_RDONLY; + } + mutex_exit(&zv->zv_state_lock); + return (0); +} + /* * Sanity check volume block size. */