X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fdsl_dir.c;fp=module%2Fzfs%2Fdsl_dir.c;h=97b38d209bff315d79c88237f81d913440e5a27b;hb=65947351e71bec2ec5673bf0c3ad02f2c2b96b6c;hp=d615832c56c20c750ed90e1915dc02806d4a3fdb;hpb=d13524579162b35189804c357a63993be758b84c;p=zfs.git diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index d615832..97b38d2 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -460,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);