* This function is responsible for performing the following two tasks: * * 1. its primary responsibility is to block until the given "commit * waiter" is considered "done". * * 2. its secondary responsibility is to issue the zio for the lwb that * the given "commit waiter" is waiting on, if this function has * waited "long enough" and the lwb is still in the "open" state. * * Giv
| 2639 | * the comment at the bottom of that function. |
| 2640 | */ |
| 2641 | static void |
| 2642 | zil_commit_waiter(zilog_t *zilog, zil_commit_waiter_t *zcw) |
| 2643 | { |
| 2644 | ASSERT(!MUTEX_HELD(&zilog->zl_lock)); |
| 2645 | ASSERT(!MUTEX_HELD(&zilog->zl_issuer_lock)); |
| 2646 | ASSERT(spa_writeable(zilog->zl_spa)); |
| 2647 | |
| 2648 | mutex_enter(&zcw->zcw_lock); |
| 2649 | |
| 2650 | /* |
| 2651 | * The timeout is scaled based on the lwb latency to avoid |
| 2652 | * significantly impacting the latency of each individual itx. |
| 2653 | * For more details, see the comment at the bottom of the |
| 2654 | * zil_process_commit_list() function. |
| 2655 | */ |
| 2656 | int pct = MAX(zfs_commit_timeout_pct, 1); |
| 2657 | hrtime_t sleep = (zilog->zl_last_lwb_latency * pct) / 100; |
| 2658 | hrtime_t wakeup = gethrtime() + sleep; |
| 2659 | boolean_t timedout = B_FALSE; |
| 2660 | |
| 2661 | while (!zcw->zcw_done) { |
| 2662 | ASSERT(MUTEX_HELD(&zcw->zcw_lock)); |
| 2663 | |
| 2664 | lwb_t *lwb = zcw->zcw_lwb; |
| 2665 | |
| 2666 | /* |
| 2667 | * Usually, the waiter will have a non-NULL lwb field here, |
| 2668 | * but it's possible for it to be NULL as a result of |
| 2669 | * zil_commit() racing with spa_sync(). |
| 2670 | * |
| 2671 | * When zil_clean() is called, it's possible for the itxg |
| 2672 | * list (which may be cleaned via a taskq) to contain |
| 2673 | * commit itxs. When this occurs, the commit waiters linked |
| 2674 | * off of these commit itxs will not be committed to an |
| 2675 | * lwb. Additionally, these commit waiters will not be |
| 2676 | * marked done until zil_commit_waiter_skip() is called via |
| 2677 | * zil_itxg_clean(). |
| 2678 | * |
| 2679 | * Thus, it's possible for this commit waiter (i.e. the |
| 2680 | * "zcw" variable) to be found in this "in between" state; |
| 2681 | * where it's "zcw_lwb" field is NULL, and it hasn't yet |
| 2682 | * been skipped, so it's "zcw_done" field is still B_FALSE. |
| 2683 | */ |
| 2684 | IMPLY(lwb != NULL, lwb->lwb_state != LWB_STATE_CLOSED); |
| 2685 | |
| 2686 | if (lwb != NULL && lwb->lwb_state == LWB_STATE_OPENED) { |
| 2687 | ASSERT3B(timedout, ==, B_FALSE); |
| 2688 | |
| 2689 | /* |
| 2690 | * If the lwb hasn't been issued yet, then we |
| 2691 | * need to wait with a timeout, in case this |
| 2692 | * function needs to issue the lwb after the |
| 2693 | * timeout is reached; responsibility (2) from |
| 2694 | * the comment above this function. |
| 2695 | */ |
| 2696 | int rc = cv_timedwait_hires(&zcw->zcw_cv, |
| 2697 | &zcw->zcw_lock, wakeup, USEC2NSEC(1), |
| 2698 | CALLOUT_FLAG_ABSOLUTE); |
no test coverage detected