int dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname, int intsz, int numints, void *buf, char *setpoint) { zfs_prop_t prop = zfs_name_to_prop(propname); boolean_t inheritable; boolean_t snapshot; uint64_t zapobj; ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool)); inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); snapshot = (ds->ds_phys != NULL && dsl_dataset_is_snapshot(ds)); zapobj = (ds->ds_phys == NULL ? 0 : ds->ds_phys->ds_props_obj); if (zapobj != 0) { objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset; int err; ASSERT(snapshot); /* Check for a local value. */ err = zap_lookup(mos, zapobj, propname, intsz, numints, buf); if (err != ENOENT) { if (setpoint != NULL && err == 0) dsl_dataset_name(ds, setpoint); return (err); } /* * Skip the check for a received value if there is an explicit * inheritance entry. */ if (inheritable) { char *inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); err = zap_contains(mos, zapobj, inheritstr); strfree(inheritstr); if (err != 0 && err != ENOENT) return (err); } if (err == ENOENT) { /* Check for a received value. */ char *recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); err = zap_lookup(mos, zapobj, recvdstr, intsz, numints, buf); strfree(recvdstr); if (err != ENOENT) { if (setpoint != NULL && err == 0) (void) strcpy(setpoint, ZPROP_SOURCE_VAL_RECVD); return (err); } } } return (dsl_prop_get_dd(ds->ds_dir, propname, intsz, numints, buf, setpoint, snapshot)); }
int dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, int intsz, int numint, void *buf, char *setpoint) { int err = ENOENT; objset_t *mos = dd->dd_pool->dp_meta_objset; zfs_prop_t prop; ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); if (setpoint) setpoint[0] = '\0'; prop = zfs_name_to_prop(propname); /* * Note: dd may be NULL, therefore we shouldn't dereference it * ouside this loop. */ for (; dd != NULL; dd = dd->dd_parent) { ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, propname, intsz, numint, buf); if (err != ENOENT) { if (setpoint) dsl_dir_name(dd, setpoint); break; } /* * Break out of this loop for non-inheritable properties. */ if (prop != ZPROP_INVAL && !zfs_prop_inheritable(prop)) break; } if (err == ENOENT) err = dodefault(propname, intsz, numint, buf); return (err); }
int dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, int intsz, int numints, void *buf, char *setpoint, boolean_t snapshot) { int err = ENOENT; dsl_dir_t *target = dd; objset_t *mos = dd->dd_pool->dp_meta_objset; zfs_prop_t prop; boolean_t inheritable; boolean_t inheriting = B_FALSE; char *inheritstr; char *recvdstr; ASSERT(dsl_pool_config_held(dd->dd_pool)); if (setpoint) setpoint[0] = '\0'; prop = zfs_name_to_prop(propname); inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); /* * Note: dd may become NULL, therefore we shouldn't dereference it * after this loop. */ for (; dd != NULL; dd = dd->dd_parent) { if (dd != target || snapshot) { if (!inheritable) break; inheriting = B_TRUE; } /* Check for a local value. */ err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, propname, intsz, numints, buf); if (err != ENOENT) { if (setpoint != NULL && err == 0) dsl_dir_name(dd, setpoint); break; } /* * Skip the check for a received value if there is an explicit * inheritance entry. */ err = zap_contains(mos, dsl_dir_phys(dd)->dd_props_zapobj, inheritstr); if (err != 0 && err != ENOENT) break; if (err == ENOENT) { /* Check for a received value. */ err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, recvdstr, intsz, numints, buf); if (err != ENOENT) { if (setpoint != NULL && err == 0) { if (inheriting) { dsl_dir_name(dd, setpoint); } else { (void) strcpy(setpoint, ZPROP_SOURCE_VAL_RECVD); } } 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. */ err = SET_ERROR(ENOENT); } if (err == ENOENT) err = dodefault(propname, intsz, numints, buf); strfree(inheritstr); strfree(recvdstr); return (err); }