dsl_dir_evict(dmu_buf_t *db, void *arg)
{
dsl_dir_t *dd = arg;
- dsl_pool_t *dp = dd->dd_pool;
+ ASSERTV(dsl_pool_t *dp = dd->dd_pool;)
int t;
for (t = 0; t < TXG_SIZE; t++) {
if (dd == NULL) {
dsl_dir_t *winner;
- dd = kmem_zalloc(sizeof (dsl_dir_t), KM_SLEEP);
+ dd = kmem_zalloc(sizeof (dsl_dir_t), KM_PUSHPAGE);
dd->dd_object = ddobj;
dd->dd_dbuf = dbuf;
dd->dd_pool = dp;
dsl_dir_open_spa(spa_t *spa, const char *name, void *tag,
dsl_dir_t **ddp, const char **tailp)
{
- char buf[MAXNAMELEN];
+ char *buf;
const char *next, *nextnext = NULL;
int err;
dsl_dir_t *dd;
dprintf("%s\n", name);
+ buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
err = getcomponent(name, buf, &next);
if (err)
- return (err);
+ goto error;
if (spa == NULL) {
err = spa_open(buf, &spa, FTAG);
if (err) {
dprintf("spa_open(%s) failed\n", buf);
- return (err);
+ goto error;
}
openedspa = TRUE;
rw_exit(&dp->dp_config_rwlock);
if (openedspa)
spa_close(spa, FTAG);
- return (err);
+ goto error;
}
while (next != NULL) {
dsl_dir_close(dd, tag);
if (openedspa)
spa_close(spa, FTAG);
- return (err);
+ goto error;
}
/*
if (openedspa)
spa_close(spa, FTAG);
*ddp = dd;
+error:
+ kmem_free(buf, MAXNAMELEN);
return (err);
}
/*
* There should be exactly two holds, both from
* dsl_dataset_destroy: one on the dd directory, and one on its
- * head ds. Otherwise, someone is trying to lookup something
- * inside this dir while we want to destroy it. The
- * config_rwlock ensures that nobody else opens it after we
- * check.
+ * head ds. If there are more holds, then a concurrent thread is
+ * performing a lookup inside this dir while we're trying to destroy
+ * it. To minimize this possibility, we perform this check only
+ * in syncing context and fail the operation if we encounter
+ * additional holds. The dp_config_rwlock ensures that nobody else
+ * opens it after we check.
*/
- if (dmu_buf_refcount(dd->dd_dbuf) > 2)
+ if (dmu_tx_is_syncing(tx) && dmu_buf_refcount(dd->dd_dbuf) > 2)
return (EBUSY);
err = zap_count(mos, dd->dd_phys->dd_child_dir_zapobj, &count);
asize - ref_rsrv);
mutex_exit(&dd->dd_lock);
- tr = kmem_zalloc(sizeof (struct tempreserve), KM_SLEEP);
+ tr = kmem_zalloc(sizeof (struct tempreserve), KM_PUSHPAGE);
tr->tr_ds = dd;
tr->tr_size = asize;
list_insert_tail(tr_list, tr);
return (0);
}
- tr_list = kmem_alloc(sizeof (list_t), KM_SLEEP);
+ tr_list = kmem_alloc(sizeof (list_t), KM_PUSHPAGE);
list_create(tr_list, sizeof (struct tempreserve),
offsetof(struct tempreserve, tr_node));
ASSERT3S(asize, >, 0);
if (err == 0) {
struct tempreserve *tr;
- tr = kmem_zalloc(sizeof (struct tempreserve), KM_SLEEP);
+ tr = kmem_zalloc(sizeof (struct tempreserve), KM_PUSHPAGE);
tr->tr_size = lsize;
list_insert_tail(tr_list, tr);
if (err == 0) {
struct tempreserve *tr;
- tr = kmem_zalloc(sizeof (struct tempreserve), KM_SLEEP);
+ tr = kmem_zalloc(sizeof (struct tempreserve), KM_PUSHPAGE);
tr->tr_dp = dd->dd_pool;
tr->tr_size = asize;
list_insert_tail(tr_list, tr);
if (tr_cookie == NULL)
return;
- while (tr = list_head(tr_list)) {
+ while ((tr = list_head(tr_list))) {
if (tr->tr_dp) {
dsl_pool_tempreserve_clear(tr->tr_dp, tr->tr_size, tx);
} else if (tr->tr_ds) {
mutex_enter(&dd->dd_lock);
dd->dd_phys->dd_quota = effective_value;
mutex_exit(&dd->dd_lock);
-
- spa_history_log_internal(LOG_DS_QUOTA, dd->dd_pool->dp_spa,
- tx, "%lld dataset = %llu ",
- (longlong_t)effective_value, dd->dd_phys->dd_head_dataset_obj);
}
int
delta, 0, 0, tx);
}
mutex_exit(&dd->dd_lock);
-
- spa_history_log_internal(LOG_DS_RESERVATION, dd->dd_pool->dp_spa,
- tx, "%lld dataset = %llu",
- (longlong_t)effective_value, dd->dd_phys->dd_head_dataset_obj);
}
int
if (closest_common_ancestor(dd, ra->newparent) == dd)
return (EINVAL);
- if (err = dsl_dir_transfer_possible(dd->dd_parent,
- ra->newparent, myspace))
+ if ((err = dsl_dir_transfer_possible(dd->dd_parent,
+ ra->newparent, myspace)))
return (err);
}
dd->dd_snap_cmtime = t;
mutex_exit(&dd->dd_lock);
}
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+EXPORT_SYMBOL(dsl_dir_set_quota);
+EXPORT_SYMBOL(dsl_dir_set_reservation);
+EXPORT_SYMBOL(dsl_dir_open);
+EXPORT_SYMBOL(dsl_dir_close);
+#endif