diff --git a/cmd/zfs/zfs_iter.c b/cmd/zfs/zfs_iter.c index 8892d91f2..eb1d9a54e 100644 --- a/cmd/zfs/zfs_iter.c +++ b/cmd/zfs/zfs_iter.c @@ -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, diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index d7c1a2a47..7faab4734 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -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); diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index ae72f834d..7b3ae6cff 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -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. diff --git a/include/zfs_prop.h b/include/zfs_prop.h index a63262311..5e7d3f55a 100644 --- a/include/zfs_prop.h +++ b/include/zfs_prop.h @@ -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 } diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 316927c0a..5e43aab2b 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -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))); diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 83396c402..ac3b68226 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -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, diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index e99603b49..d029b61e7 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -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; /* diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index dd456b59a..d81ff3bc6 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -391,7 +391,7 @@ zfs_prop_init(void) PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, " | none", "RESERV"); zprop_register_number(ZFS_PROP_VOLSIZE, "volsize", 0, PROP_DEFAULT, - ZFS_TYPE_VOLUME, "", "VOLSIZE"); + ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, "", "VOLSIZE"); zprop_register_number(ZFS_PROP_REFQUOTA, "refquota", 0, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM, " | 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 diff --git a/module/zcommon/zprop_common.c b/module/zcommon/zprop_common.c index 6d9f89a98..035f3378d 100644 --- a/module/zcommon/zprop_common.c +++ b/module/zcommon/zprop_common.c @@ -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); } diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c index 079ef9742..ded0da991 100644 --- a/module/zfs/dsl_prop.c +++ b/module/zfs/dsl_prop.c @@ -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. */