]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Check large block feature flag on volumes
authorBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 24 Aug 2015 21:18:48 +0000 (14:18 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 28 Aug 2015 16:25:03 +0000 (09:25 -0700)
Since ZoL allows large blocks to be used by volumes, unlike upstream
illumos, the feature flag must be checked prior to volume creation.
This is critical because unlike filesystems, volumes will create a
object which uses large blocks as part of the create.  Therefore, it
cannot be safely checked in zfs_check_settable() after the dataset
can been created.

In addition this patch updates the relevant error messages to use
zfs_nicenum() to print the maximum blocksize.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3591

include/sys/zvol.h
lib/libzfs/libzfs_dataset.c
module/zfs/zfs_ioctl.c
module/zfs/zvol.c

index 04e0996570c9598e8c12d025dfa4156b4a0b9056..898e2352156b29ff3f1d4d4805031dd688c85901 100644 (file)
@@ -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);
index 4bb826aca9cf01c4e28d9afc9df2eece0be82961..6b67a73efd8b51aee3eab9f0c37c47930336eb74 100644 (file)
@@ -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));
 
index a7bfecea6f18364b61a475080ce7421758a5184f..51382e8b6d109da5bb339e5d50aa53576e5f86c0 100644 (file)
@@ -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 &&
index 2b99f44de6a877b6c63b3cf12665ebc2bb39aa44..3cce00fb686eed77c07107bcaabbd9e731e2730c 100644 (file)
@@ -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))