dsl_prop.c revision 03bad06fbb261fd4a7151a70dfeff2f5041cce1f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
*/
#include <sys/zfs_context.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_dataset.h>
#include <sys/dsl_prop.h>
#include <sys/dsl_synctask.h>
#include "zfs_prop.h"
#define ZPROP_INHERIT_SUFFIX "$inherit"
#define ZPROP_RECVD_SUFFIX "$recvd"
static int
{
/*
* The setonce properties are read-only, BUT they still
* have a default value that can be used as the initial
* value.
*/
if (intsz != 1)
numints);
} else {
}
return (0);
}
int
{
char *inheritstr;
char *recvdstr;
if (setpoint)
setpoint[0] = '\0';
/*
* Note: dd may become NULL, therefore we shouldn't dereference it
* after this loop.
*/
if (!inheritable)
break;
inheriting = B_TRUE;
}
/* Check for a local value. */
break;
}
/*
* Skip the check for a received value if there is an explicit
* inheritance entry.
*/
break;
/* Check for a received value. */
if (inheriting) {
} else {
}
}
break;
}
}
/*
* If we found an explicit inheritance entry, err is zero even
* though we haven't yet found the value, so reinitializing err
* at the end of the loop (instead of at the beginning) ensures
* that err has a valid post-loop value.
*/
}
return (err);
}
int
{
if (zapobj != 0) {
int err;
/* Check for a local value. */
return (err);
}
/*
* Skip the check for a received value if there is an explicit
* inheritance entry.
*/
if (inheritable) {
return (err);
}
/* Check for a received value. */
return (err);
}
}
}
}
static dsl_prop_record_t *
{
break;
}
return (pr);
}
static dsl_prop_record_t *
{
return (pr);
}
void
{
}
void
{
}
}
/*
* Register interest in the named property. We'll call the callback
* once to notify it of the current property value, and again each time
* the property changes, until this callback is unregistered.
*
* Return 0 on success, errno if the prop is not an integer value.
*/
int
{
int err;
if (err != 0)
return (err);
return (0);
}
int
{
int error;
if (error != 0)
return (error);
return (error);
}
/*
* Get the current property value. It may have changed by the time this
* function returns, so it is NOT safe to follow up with
* dsl_prop_register() and assume that the value has not changed in
* between.
*
* Return 0 on success, ENOENT if ddname is invalid.
*/
int
{
}
int
{
}
/*
* Predict the effective value of the given special property if it were set with
* the given value and source. This is not a general purpose function. It exists
* only to handle the special requirements of the quota and reservation
* properties. The fact that these properties are non-inheritable greatly
* simplifies the prediction logic.
*
* Returns 0 on success, a positive error code on failure, or -1 if called with
* a property not handled by this function.
*/
int
{
char *recvdstr;
int err = 0;
switch (prop) {
case ZFS_PROP_QUOTA:
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_REFRESERVATION:
break;
default:
return (-1);
}
if (version < SPA_VERSION_RECVD_PROPS) {
if (source & ZPROP_SRC_NONE)
else if (source & ZPROP_SRC_RECEIVED)
}
switch (source) {
case ZPROP_SRC_NONE:
/* Revert to the received value, if any. */
*newvalp = 0;
break;
case ZPROP_SRC_LOCAL:
break;
case ZPROP_SRC_RECEIVED:
/*
* If there's no local setting, then the new received value will
* be the effective value.
*/
break;
case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED):
/*
* We're clearing the received value, so the local setting (if
* it exists) remains the effective value.
*/
*newvalp = 0;
break;
default:
}
return (0);
return (err);
}
/*
* Unregister all callbacks that are registered with the
* given callback argument.
*/
void
{
}
}
}
{
}
/* ARGSUSED */
static int
{
/*
* Callback entries do not have holds on their
* datasets so that datasets with registered
* callbacks are still eligible for eviction.
* Unlike operations to update properties on a
* single dataset, we are performing a recursive
* descent of related head datasets. The caller
* of this function only has a dataset hold on
* the passed in head dataset, not the snapshots
* associated with this dataset. Without a hold,
* the dataset pointer within callback records
* for snapshots can be invalidated by eviction
* at any time.
*
* Use dsl_dataset_try_add_ref() to verify
* that the dataset for a snapshot has not
* begun eviction processing and to prevent
* eviction from occurring for the duration of
* the callback. If the hold attempt fails,
* this object is already being evicted and the
* callback can be safely ignored.
*/
continue;
}
}
return (0);
}
/*
* Update all property values for ddobj & its descendants. This is used
* when renaming the dir.
*/
void
{
}
static void
{
int err;
if (err)
return;
if (!first) {
/*
* If the prop is set here, then this change is not
* being inherited here or below; stop the recursion.
*/
propname);
if (err == 0) {
return;
}
}
/*
* cbr->cbr_ds may be invalidated due to eviction,
* requiring the use of dsl_dataset_try_add_ref().
* See comment block in dsl_prop_notify_all_cb()
* for details.
*/
continue;
/*
* If the property is not set on this ds, then it is
* inherited here; call the callback.
*/
if (propobj == 0 ||
}
}
zap_cursor_advance(&zc)) {
}
}
void
{
int isint;
char valbuf[32];
char *inheritstr;
char *recvdstr;
int err;
if (ds->ds_is_snapshot) {
}
} else {
}
if (version < SPA_VERSION_RECVD_PROPS) {
if (source & ZPROP_SRC_NONE)
else if (source & ZPROP_SRC_RECEIVED)
}
switch (source) {
case ZPROP_SRC_NONE:
/*
* revert to received value, if any (inherit -S)
* - remove propname
* - remove propname$inherit
*/
break;
case ZPROP_SRC_LOCAL:
/*
* remove propname$inherit
* set propname -> value
*/
break;
case ZPROP_SRC_INHERITED:
/*
* explicitly inherit
* - remove propname
* - set propname$inherit
*/
if (version >= SPA_VERSION_RECVD_PROPS &&
dummy = 0;
}
break;
case ZPROP_SRC_RECEIVED:
/*
* set propname$recvd -> value
*/
break;
/*
* clear local and received settings
* - remove propname
* - remove propname$inherit
* - remove propname$recvd
*/
/* FALLTHRU */
case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED):
/*
* remove propname$recvd
*/
break;
default:
}
if (isint) {
if (ds->ds_is_snapshot) {
/*
* It's a snapshot; nothing can inherit this
* property, so just look for callbacks on this
* ds here.
*/
propname) == 0)
}
} else {
}
} else {
if (source == ZPROP_SRC_LOCAL) {
} else {
}
}
}
int
{
int error;
return (error);
}
int
{
int error;
return (error);
}
int
{
int error;
return (error);
}
typedef struct dsl_props_set_arg {
const char *dpsa_dsname;
static int
{
int err;
if (err != 0)
return (err);
return (SET_ERROR(ENAMETOOLONG));
}
return (E2BIG);
}
}
}
}
return (0);
}
void
{
/*
* dsl_prop_get_all_impl() returns properties in this
* format.
*/
}
} else {
panic("invalid nvpair type");
}
}
}
static void
{
}
/*
* All-or-nothing; if any prop can't be set, nothing will be modified.
*/
int
{
int nblks = 0;
/*
* If the source includes NONE, then we will only be removing entries
* from the ZAP object. In that case don't check for ENOSPC.
*/
if ((source & ZPROP_SRC_NONE) == 0)
}
typedef enum dsl_prop_getflags {
static int
{
int err = 0;
zap_cursor_advance(&zc)) {
char buf[ZAP_MAXNAMELEN];
char *valstr;
const char *suffix;
const char *propname;
const char *source;
/*
* Skip local properties if we only want received
* properties.
*/
if (flags & DSL_PROP_GET_RECEIVED)
continue;
/* Skip explicitly inherited entries. */
continue;
if (flags & DSL_PROP_GET_LOCAL)
continue;
if (!(flags & DSL_PROP_GET_RECEIVED)) {
/* Skip if locally overridden. */
if (err == 0)
continue;
break;
/* Skip if explicitly inherited. */
if (err == 0)
continue;
break;
}
} else {
/*
* For backward compatibility, skip suffixes we don't
* recognize.
*/
continue;
}
/* Skip non-inheritable properties. */
continue;
/* Skip properties not valid for this type. */
continue;
/* Skip properties already defined. */
continue;
/*
* String property
*/
KM_SLEEP);
if (err != 0) {
break;
}
tmp) == 0);
} else {
/*
* Integer property
*/
}
}
err = 0;
return (err);
}
/*
* Iterate over all properties for this dataset and return them in an nvlist.
*/
static int
{
int err = 0;
char setpoint[MAXNAMELEN];
if (ds->ds_is_snapshot)
if (err)
goto out;
}
if (flags & (DSL_PROP_GET_LOCAL |
break;
}
if (err)
break;
}
out:
return (err);
}
dsl_prop_get_hasrecvd(const char *dsname)
{
return (0 ==
}
static int
{
int error = 0;
if (version >= SPA_VERSION_RECVD_PROPS)
return (error);
}
/*
* Call after successfully receiving properties to ensure that only the first
* receive on or after SPA_VERSION_RECVD_PROPS blows away local properties.
*/
int
dsl_prop_set_hasrecvd(const char *dsname)
{
int error = 0;
if (!dsl_prop_get_hasrecvd(dsname))
return (error);
}
void
dsl_prop_unset_hasrecvd(const char *dsname)
{
}
int
{
}
int
{
int error;
/*
* Received properties are not distinguishable from local properties
* until the dataset has received properties on or after
* SPA_VERSION_RECVD_PROPS.
*/
if (error != 0)
return (error);
return (error);
}
void
{
return;
}
/* Indicate the default source if we can. */
value == default_value) {
}
}
void
{
return;
}
}