Skip to content

Commit 8710d10

Browse files
committed
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 <[email protected]> Sponsored by: iXsystems, Inc.
1 parent 9192ab7 commit 8710d10

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

module/zfs/zil.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,16 @@ zil_lwb_write_done(zio_t *zio)
15501550
lwb->lwb_state = LWB_STATE_WRITE_DONE;
15511551
lwb->lwb_child_zio = NULL;
15521552
lwb->lwb_write_zio = NULL;
1553+
1554+
/*
1555+
* If nlwb is not yet issued, zil_lwb_set_zio_dependency() is not
1556+
* called for it yet, and when it will be, it won't be able to make
1557+
* its write ZIO a parent this ZIO. In such case we can not defer
1558+
* our flushes or below may be a race between the done callbacks.
1559+
*/
15531560
nlwb = list_next(&zilog->zl_lwb_list, lwb);
1561+
if (nlwb && nlwb->lwb_state != LWB_STATE_ISSUED)
1562+
nlwb = NULL;
15541563
mutex_exit(&zilog->zl_lock);
15551564

15561565
if (avl_numnodes(t) == 0)

0 commit comments

Comments
 (0)