From 27e39dd59aefc2c4add1e82c6a2f79fc33b86a9b Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Fri, 25 Aug 2023 15:02:11 +1000 Subject: [PATCH] zil_fail: handle the case where no itxs are found This is possible if spa_sync() completes before the ZIL write/flush does, which then errors. At this point all itxs are in the past, leaving us with nothing to wait for. In a perfect world we would not fail the ZIL, but at this point we've already locked out the itxgs early, so we have to see it through. Signed-off-by: Rob Norris --- module/zfs/zil.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/module/zfs/zil.c b/module/zfs/zil.c index 0049dc0715..ed0a09eb51 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -1239,10 +1239,16 @@ zil_fail(zilog_t *zilog) ASSERT(list_is_empty(&zilog->zl_itx_commit_list)); /* - * If this fails, then we didn't take any itxs at all. If that's true, - * how did we end up here? + * Its possible that we took no itxs if all the work was committed to + * the pool before the ZIL write errored; in that case there's only + * commit waiters left on the lists, and we just completed those. + * + * We've already flagged the itxs for failure though, so we still have + * to fail the whole ZIL. We'll just set its highest to be the last + * synced txg, so it can immediately reopen if the circumstances suit. */ - ASSERT3U(fail_itxg->itxg_txg, <, UINT64_MAX); + if (fail_itxg->itxg_txg == UINT64_MAX) + fail_itxg->itxg_txg = highest_txg; /* Prepare the live itxgs for failure */ for (int i = 0; i < TXG_SIZE; i++) {