* Suspend an intent log. While in suspended mode, we still honor * synchronous semantics, but we rely on txg_wait_synced() to do it. * On old version pools, we suspend the log briefly when taking a * snapshot so that it will have an empty intent log. * * Long holds are not really intended to be used the way we do here -- * held for such a short time. A concurrent caller of dsl_dataset_long
| 3334 | * should be passed into zil_resume(). |
| 3335 | */ |
| 3336 | int |
| 3337 | zil_suspend(const char *osname, void **cookiep) |
| 3338 | { |
| 3339 | objset_t *os; |
| 3340 | zilog_t *zilog; |
| 3341 | const zil_header_t *zh; |
| 3342 | int error; |
| 3343 | |
| 3344 | error = dmu_objset_hold(osname, suspend_tag, &os); |
| 3345 | if (error != 0) |
| 3346 | return (error); |
| 3347 | zilog = dmu_objset_zil(os); |
| 3348 | |
| 3349 | mutex_enter(&zilog->zl_lock); |
| 3350 | zh = zilog->zl_header; |
| 3351 | |
| 3352 | if (zh->zh_flags & ZIL_REPLAY_NEEDED) { /* unplayed log */ |
| 3353 | mutex_exit(&zilog->zl_lock); |
| 3354 | dmu_objset_rele(os, suspend_tag); |
| 3355 | return (SET_ERROR(EBUSY)); |
| 3356 | } |
| 3357 | |
| 3358 | /* |
| 3359 | * Don't put a long hold in the cases where we can avoid it. This |
| 3360 | * is when there is no cookie so we are doing a suspend & resume |
| 3361 | * (i.e. called from zil_vdev_offline()), and there's nothing to do |
| 3362 | * for the suspend because it's already suspended, or there's no ZIL. |
| 3363 | */ |
| 3364 | if (cookiep == NULL && !zilog->zl_suspending && |
| 3365 | (zilog->zl_suspend > 0 || BP_IS_HOLE(&zh->zh_log))) { |
| 3366 | mutex_exit(&zilog->zl_lock); |
| 3367 | dmu_objset_rele(os, suspend_tag); |
| 3368 | return (0); |
| 3369 | } |
| 3370 | |
| 3371 | dsl_dataset_long_hold(dmu_objset_ds(os), suspend_tag); |
| 3372 | dsl_pool_rele(dmu_objset_pool(os), suspend_tag); |
| 3373 | |
| 3374 | zilog->zl_suspend++; |
| 3375 | |
| 3376 | if (zilog->zl_suspend > 1) { |
| 3377 | /* |
| 3378 | * Someone else is already suspending it. |
| 3379 | * Just wait for them to finish. |
| 3380 | */ |
| 3381 | |
| 3382 | while (zilog->zl_suspending) |
| 3383 | cv_wait(&zilog->zl_cv_suspend, &zilog->zl_lock); |
| 3384 | mutex_exit(&zilog->zl_lock); |
| 3385 | |
| 3386 | if (cookiep == NULL) |
| 3387 | zil_resume(os); |
| 3388 | else |
| 3389 | *cookiep = os; |
| 3390 | return (0); |
| 3391 | } |
| 3392 | |
| 3393 | /* |
no test coverage detected