From 998341e1eadbcbca097a92fe9f045e04e04ab154 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Fri, 15 Sep 2023 13:38:31 -0400 Subject: [PATCH] ZIL: Fix potential race on flush deferring. zil_lwb_set_zio_dependency() can not set write ZIO dependency on previous LWB's write ZIO if one is already in done handler and set state to LWB_STATE_WRITE_DONE. So theoretically done handler of next LWB's write ZIO may run before done handler of previous LWB write ZIO completes. In such case we can not defer flushes, since the flush issue process is not locked. This may fix some reported assertions of lwb_vdev_tree not being empty inside zil_free_lwb(). Signed-off-by: Alexander Motin Sponsored by: iXsystems, Inc. --- module/zfs/zil.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/module/zfs/zil.c b/module/zfs/zil.c index b30676b42d88..ee647bd74493 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -1550,7 +1550,14 @@ zil_lwb_write_done(zio_t *zio) lwb->lwb_state = LWB_STATE_WRITE_DONE; lwb->lwb_child_zio = NULL; lwb->lwb_write_zio = NULL; + + /* + * If nlwb is not yet issued, its write ZIO will not parent this ZIO. + * In such case we can not defer our flushes or below may be a race. + */ nlwb = list_next(&zilog->zl_lwb_list, lwb); + if (nlwb && nlwb->lwb_state != LWB_STATE_ISSUED) + nlwb = NULL; mutex_exit(&zilog->zl_lock); if (avl_numnodes(t) == 0)