/* ARGSUSED */ static int dsl_prop_notify_all_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) { dsl_dir_t *dd = ds->ds_dir; dsl_prop_record_t *pr; dsl_prop_cb_record_t *cbr; mutex_enter(&dd->dd_lock); for (pr = list_head(&dd->dd_props); pr; pr = list_next(&dd->dd_props, pr)) { for (cbr = list_head(&pr->pr_cbs); cbr; cbr = list_next(&pr->pr_cbs, cbr)) { uint64_t value; /* * 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. */ if (ds != cbr->cbr_ds && !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) continue; if (dsl_prop_get_ds(cbr->cbr_ds, cbr->cbr_pr->pr_propname, sizeof (value), 1, &value, NULL) == 0) cbr->cbr_func(cbr->cbr_arg, value); if (ds != cbr->cbr_ds) dsl_dataset_rele(cbr->cbr_ds, FTAG); } } mutex_exit(&dd->dd_lock); return (0); }
/* ARGSUSED */ static int dsl_prop_notify_all_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) { dsl_dir_t *dd = ds->ds_dir; dsl_prop_cb_record_t *cbr; mutex_enter(&dd->dd_lock); for (cbr = list_head(&dd->dd_prop_cbs); cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { uint64_t value; /* * Callback entries do not have holds on their datasets * so that datasets with registered callbacks are still * eligible for eviction. Unlike operations on callbacks * for a single dataset, we are performing a recursive * descent of related datasets and the calling context * for this iteration only has a dataset hold on the root. * Without a hold, the callback's pointer to the dataset * could be invalidated by eviction at any time. * * Use dsl_dataset_try_add_ref() to verify that the * dataset 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. */ if (!dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) continue; if (dsl_prop_get_ds(cbr->cbr_ds, cbr->cbr_propname, sizeof (value), 1, &value, NULL) == 0) cbr->cbr_func(cbr->cbr_arg, value); dsl_dataset_rele(cbr->cbr_ds, FTAG); } mutex_exit(&dd->dd_lock); return (0); }