aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/zvol.h2
-rw-r--r--lib/libzfs/libzfs_dataset.c10
-rw-r--r--module/zfs/zfs_ioctl.c3
-rw-r--r--module/zfs/zvol.c26
4 files changed, 36 insertions, 5 deletions
diff --git a/include/sys/zvol.h b/include/sys/zvol.h
index 04e099657..898e23521 100644
--- a/include/sys/zvol.h
+++ b/include/sys/zvol.h
@@ -34,7 +34,7 @@
#ifdef _KERNEL
extern int zvol_check_volsize(uint64_t volsize, uint64_t blocksize);
-extern int zvol_check_volblocksize(uint64_t volblocksize);
+extern int zvol_check_volblocksize(const char *name, uint64_t volblocksize);
extern int zvol_get_stats(objset_t *os, nvlist_t *nv);
extern boolean_t zvol_is_zvol(const char *);
extern void zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c
index 4bb826aca..6b67a73ef 100644
--- a/lib/libzfs/libzfs_dataset.c
+++ b/lib/libzfs/libzfs_dataset.c
@@ -1059,6 +1059,8 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
case ZFS_PROP_RECORDSIZE:
{
int maxbs = SPA_MAXBLOCKSIZE;
+ char buf[64];
+
if (zhp != NULL) {
maxbs = zpool_get_prop_int(zhp->zpool_hdl,
ZPOOL_PROP_MAXBLOCKSIZE, NULL);
@@ -1069,9 +1071,10 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
*/
if (intval < SPA_MINBLOCKSIZE ||
intval > maxbs || !ISP2(intval)) {
+ zfs_nicenum(maxbs, buf, sizeof (buf));
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' must be power of 2 from 512B "
- "to %uKB"), propname, maxbs >> 10);
+ "to %s"), propname, buf);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
@@ -3210,6 +3213,8 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
/* check for failure */
if (ret != 0) {
char parent[ZFS_MAXNAMELEN];
+ char buf[64];
+
(void) parent_name(path, parent, sizeof (parent));
switch (errno) {
@@ -3224,9 +3229,10 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
case EDOM:
+ zfs_nicenum(SPA_MAXBLOCKSIZE, buf, sizeof (buf));
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"volume block size must be power of 2 from "
- "512B to %uKB"), zfs_max_recordsize >> 10);
+ "512B to %s"), buf);
return (zfs_error(hdl, EZFS_BADPROP, errbuf));
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index a7bfecea6..51382e8b6 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -3201,7 +3201,7 @@ zfs_ioc_create(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
volblocksize = zfs_prop_default_numeric(
ZFS_PROP_VOLBLOCKSIZE);
- if ((error = zvol_check_volblocksize(
+ if ((error = zvol_check_volblocksize(fsname,
volblocksize)) != 0 ||
(error = zvol_check_volsize(volsize,
volblocksize)) != 0)
@@ -3841,6 +3841,7 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr)
return (SET_ERROR(ENOTSUP));
break;
+ case ZFS_PROP_VOLBLOCKSIZE:
case ZFS_PROP_RECORDSIZE:
/* Record sizes above 128k need the feature to be enabled */
if (nvpair_value_uint64(pair, &intval) == 0 &&
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index 2b99f44de..3cce00fb6 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -40,6 +40,7 @@
#include <sys/dsl_dataset.h>
#include <sys/dsl_prop.h>
#include <sys/zap.h>
+#include <sys/zfeature.h>
#include <sys/zil_impl.h>
#include <sys/zio.h>
#include <sys/zfs_rlock.h>
@@ -380,8 +381,31 @@ out:
* Sanity check volume block size.
*/
int
-zvol_check_volblocksize(uint64_t volblocksize)
+zvol_check_volblocksize(const char *name, uint64_t volblocksize)
{
+ /* Record sizes above 128k need the feature to be enabled */
+ if (volblocksize > SPA_OLD_MAXBLOCKSIZE) {
+ spa_t *spa;
+ int error;
+
+ if ((error = spa_open(name, &spa, FTAG)) != 0)
+ return (error);
+
+ if (!spa_feature_is_enabled(spa, SPA_FEATURE_LARGE_BLOCKS)) {
+ spa_close(spa, FTAG);
+ return (SET_ERROR(ENOTSUP));
+ }
+
+ /*
+ * We don't allow setting the property above 1MB,
+ * unless the tunable has been changed.
+ */
+ if (volblocksize > zfs_max_recordsize)
+ return (SET_ERROR(EDOM));
+
+ spa_close(spa, FTAG);
+ }
+
if (volblocksize < SPA_MINBLOCKSIZE ||
volblocksize > SPA_MAXBLOCKSIZE ||
!ISP2(volblocksize))