]> granicus.if.org Git - zfs/commitdiff
Check the dataset type more rigorously when fetching properties.
authorTim Chase <tim@chase2k.com>
Mon, 21 Apr 2014 18:22:08 +0000 (13:22 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 6 May 2014 17:41:46 +0000 (10:41 -0700)
When fetching property values of snapshots, a check against the head
dataset type must be performed.  Previously, this additional check was
performed only when fetching "version", "normalize", "utf8only" or "case".

This caused the ZPL properties "acltype", "exec", "devices", "nbmand",
"setuid" and "xattr" to be erroneously displayed with meaningless values
for snapshots of volumes.  It also did not allow for the display of
"volsize" of a snapshot of a volume.

This patch adds the headcheck flag paramater to zfs_prop_valid_for_type()
and zprop_valid_for_type() to indicate the check is being done
against a head dataset's type in order that properties valid only for
snapshots are handled correctly.  This allows the the head check in
get_numeric_property() to be performed when fetching a property for
a snapshot.

Signed-off-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #2265

cmd/zfs/zfs_iter.c
cmd/zfs/zfs_main.c
include/sys/fs/zfs.h
include/zfs_prop.h
lib/libzfs/libzfs_dataset.c
lib/libzfs/libzfs_mount.c
lib/libzfs/libzfs_util.c
module/zcommon/zfs_prop.c
module/zcommon/zprop_common.c
module/zfs/dsl_prop.c

index 8892d91f24bad380198f17547e3b0a0925287279..eb1d9a54e1ec9471cf57670789364ca3cef2006a 100644 (file)
@@ -328,9 +328,9 @@ zfs_sort(const void *larg, const void *rarg, void *data)
                        rstr = rbuf;
                } else {
                        lvalid = zfs_prop_valid_for_type(psc->sc_prop,
-                           zfs_get_type(l));
+                           zfs_get_type(l), B_FALSE);
                        rvalid = zfs_prop_valid_for_type(psc->sc_prop,
-                           zfs_get_type(r));
+                           zfs_get_type(r), B_FALSE);
 
                        if (lvalid)
                                (void) zfs_prop_get_numeric(l, psc->sc_prop,
index d7c1a2a4774bcbda9391085ac242ae588cc786d7..7faab473414f3d8bede7474b11b81211de297abc 100644 (file)
@@ -846,7 +846,7 @@ zfs_do_create(int argc, char **argv)
         * if the user doesn't want the dataset automatically mounted,
         * then skip the mount/share step
         */
-       if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT, type))
+       if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT, type, B_FALSE))
                canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
 
        /*
@@ -1429,7 +1429,7 @@ get_callback(zfs_handle_t *zhp, void *data)
                                if (pl->pl_all)
                                        continue;
                                if (!zfs_prop_valid_for_type(pl->pl_prop,
-                                   ZFS_TYPE_DATASET)) {
+                                   ZFS_TYPE_DATASET, B_FALSE)) {
                                        (void) fprintf(stderr,
                                            gettext("No such property '%s'\n"),
                                            zfs_prop_to_name(pl->pl_prop));
@@ -1763,7 +1763,7 @@ inherit_recurse_cb(zfs_handle_t *zhp, void *data)
         * are not valid for this type of dataset.
         */
        if (prop != ZPROP_INVAL &&
-           !zfs_prop_valid_for_type(prop, zfs_get_type(zhp)))
+           !zfs_prop_valid_for_type(prop, zfs_get_type(zhp), B_FALSE))
                return (0);
 
        return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0);
index ae72f834de523bb8c9839ee21d3d96071fbdfd2f..7b3ae6cff8f3cd1834fe3af0f4900420b1656262 100644 (file)
@@ -255,7 +255,7 @@ boolean_t zfs_prop_written(const char *);
 int zfs_prop_index_to_string(zfs_prop_t, uint64_t, const char **);
 int zfs_prop_string_to_index(zfs_prop_t, const char *, uint64_t *);
 uint64_t zfs_prop_random_value(zfs_prop_t, uint64_t seed);
-boolean_t zfs_prop_valid_for_type(int, zfs_type_t);
+boolean_t zfs_prop_valid_for_type(int, zfs_type_t, boolean_t);
 
 /*
  * Pool property functions shared between libzfs and kernel.
index a63262311b3d4b4c4f50bc449a8268f803d1d39a..5e7d3f55ac6ac9c455f0e0b5b2b8077927c848cc 100644 (file)
@@ -120,7 +120,7 @@ int zprop_index_to_string(int, uint64_t, const char **, zfs_type_t);
 uint64_t zprop_random_value(int, uint64_t, zfs_type_t);
 const char *zprop_values(int, zfs_type_t);
 size_t zprop_width(int, boolean_t *, zfs_type_t);
-boolean_t zprop_valid_for_type(int, zfs_type_t);
+boolean_t zprop_valid_for_type(int, zfs_type_t, boolean_t);
 
 #ifdef __cplusplus
 }
index 316927c0a8a487c6c9de539f0043366f5a707aec..5e43aab2b14d3f7a062ab228f329aab3c485884d 100644 (file)
@@ -948,7 +948,7 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
                        goto error;
                }
 
-               if (!zfs_prop_valid_for_type(prop, type)) {
+               if (!zfs_prop_valid_for_type(prop, type, B_FALSE)) {
                        zfs_error_aux(hdl,
                            dgettext(TEXT_DOMAIN, "'%s' does not "
                            "apply to datasets of this type"), propname);
@@ -1610,7 +1610,7 @@ zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
        /*
         * Check to see if the value applies to this type
         */
-       if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
+       if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE))
                return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
 
        /*
@@ -1760,6 +1760,14 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
 
        *source = NULL;
 
+       /*
+        * If the property is being fetched for a snapshot, check whether
+        * the property is valid for the snapshot's head dataset type.
+        */
+       if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT &&
+               !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE))
+                       return (-1);
+
        switch (prop) {
        case ZFS_PROP_ATIME:
                mntopt_on = MNTOPT_ATIME;
@@ -1880,8 +1888,7 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
        case ZFS_PROP_NORMALIZE:
        case ZFS_PROP_UTF8ONLY:
        case ZFS_PROP_CASE:
-               if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
-                   zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
+               if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
                        return (-1);
                (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
                if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
@@ -2124,7 +2131,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
        /*
         * Check to see if this property applies to our object
         */
-       if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
+       if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE))
                return (-1);
 
        if (received && zfs_prop_readonly(prop))
@@ -2445,7 +2452,7 @@ zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
        /*
         * Check to see if this property applies to our object
         */
-       if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
+       if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE)) {
                return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
                    dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
                    zfs_prop_to_name(prop)));
index 83396c402678fbd7f0ff0d8a17aa81c63bc032ec..ac3b6822608ce1f2dd06d0bfed812eafe8311f01 100644 (file)
@@ -231,7 +231,8 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
        char sourceloc[ZFS_MAXNAMELEN];
        zprop_source_t sourcetype;
 
-       if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type))
+       if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type,
+           B_FALSE))
                return (B_FALSE);
 
        verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen,
index e99603b49ed986bba06bd010e89bec99bd197847..d029b61e7c90ebe3a2e8680f9e838ea302baa781 100644 (file)
@@ -1531,7 +1531,7 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
 
        prop = zprop_name_to_prop(propname, type);
 
-       if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
+       if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type, B_FALSE))
                prop = ZPROP_INVAL;
 
        /*
index dd456b59a7084d5128f3d9d3b7bd0d99d32c5ade..d81ff3bc622038779e0ec512b92fcf9fc5eb08fe 100644 (file)
@@ -391,7 +391,7 @@ zfs_prop_init(void)
            PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
            "<size> | none", "RESERV");
        zprop_register_number(ZFS_PROP_VOLSIZE, "volsize", 0, PROP_DEFAULT,
-           ZFS_TYPE_VOLUME, "<size>", "VOLSIZE");
+           ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, "<size>", "VOLSIZE");
        zprop_register_number(ZFS_PROP_REFQUOTA, "refquota", 0, PROP_DEFAULT,
            ZFS_TYPE_FILESYSTEM, "<size> | none", "REFQUOTA");
        zprop_register_number(ZFS_PROP_REFRESERVATION, "refreservation", 0,
@@ -555,9 +555,9 @@ zfs_prop_random_value(zfs_prop_t prop, uint64_t seed)
  * Returns TRUE if the property applies to any of the given dataset types.
  */
 boolean_t
-zfs_prop_valid_for_type(int prop, zfs_type_t types)
+zfs_prop_valid_for_type(int prop, zfs_type_t types, boolean_t headcheck)
 {
-       return (zprop_valid_for_type(prop, types));
+       return (zprop_valid_for_type(prop, types, headcheck));
 }
 
 zprop_type_t
index 6d9f89a989ddc6191084bc0363035ebc21ef347d..035f3378d929bbd7396bd74967b883ea926578cf 100644 (file)
@@ -351,9 +351,13 @@ zprop_values(int prop, zfs_type_t type)
 
 /*
  * Returns TRUE if the property applies to any of the given dataset types.
+ *
+ * If headcheck is set, the check is being made against the head dataset
+ * type of a snapshot which requires to return B_TRUE when the property
+ * is only valid for snapshots.
  */
 boolean_t
-zprop_valid_for_type(int prop, zfs_type_t type)
+zprop_valid_for_type(int prop, zfs_type_t type, boolean_t headcheck)
 {
        zprop_desc_t *prop_tbl;
 
@@ -362,6 +366,8 @@ zprop_valid_for_type(int prop, zfs_type_t type)
 
        ASSERT(prop < zprop_get_numprops(type));
        prop_tbl = zprop_get_proptable(type);
+       if (headcheck && prop_tbl[prop].pd_types == ZFS_TYPE_SNAPSHOT)
+               return (B_TRUE);
        return ((prop_tbl[prop].pd_types & type) != 0);
 }
 
index 079ef97423bdb23bd085b9fcc8dd9c6ddbb764ee..ded0da991721a3df2c3d1b25640aa0f882d2ab4a 100644 (file)
@@ -925,7 +925,7 @@ dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj,
 
                /* Skip properties not valid for this type. */
                if ((flags & DSL_PROP_GET_SNAPSHOT) && prop != ZPROP_INVAL &&
-                   !zfs_prop_valid_for_type(prop, ZFS_TYPE_SNAPSHOT))
+                   !zfs_prop_valid_for_type(prop, ZFS_TYPE_SNAPSHOT, B_FALSE))
                        continue;
 
                /* Skip properties already defined. */