X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fdsl_dir.c;h=377df40a8599cbb4c193a6f33a2c90dac5122cc0;hb=2ae10319624869eef0954cdfcdb6f5e33cba2e09;hp=2e52f9c732a6f470d7c2973843ff6db8ac2d47ab;hpb=c65aa5b2b9c48375ea1c451f252f0056e16f4e49;p=zfs.git diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index 2e52f9c..377df40 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -47,7 +47,7 @@ static void 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++) { @@ -96,7 +96,7 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj, 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; @@ -303,7 +303,7 @@ int 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; @@ -313,14 +313,15 @@ dsl_dir_open_spa(spa_t *spa, const char *name, void *tag, 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; @@ -336,7 +337,7 @@ dsl_dir_open_spa(spa_t *spa, const char *name, void *tag, rw_exit(&dp->dp_config_rwlock); if (openedspa) spa_close(spa, FTAG); - return (err); + goto error; } while (next != NULL) { @@ -372,7 +373,7 @@ dsl_dir_open_spa(spa_t *spa, const char *name, void *tag, dsl_dir_close(dd, tag); if (openedspa) spa_close(spa, FTAG); - return (err); + goto error; } /* @@ -391,6 +392,8 @@ dsl_dir_open_spa(spa_t *spa, const char *name, void *tag, if (openedspa) spa_close(spa, FTAG); *ddp = dd; +error: + kmem_free(buf, MAXNAMELEN); return (err); } @@ -457,12 +460,14 @@ dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx) /* * 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); @@ -788,7 +793,7 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, 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); @@ -822,7 +827,7 @@ dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize, uint64_t asize, 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); @@ -832,7 +837,7 @@ dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize, uint64_t asize, 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); @@ -848,7 +853,7 @@ dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize, uint64_t asize, 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); @@ -1061,10 +1066,6 @@ dsl_dir_set_quota_sync(void *arg1, void *arg2, dmu_tx_t *tx) 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 @@ -1177,10 +1178,6 @@ dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx) 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 @@ -1416,3 +1413,10 @@ dsl_dir_snap_cmtime_update(dsl_dir_t *dd) 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