• Dave Chinner's avatar
    xfs: xfs_ail_push_all_sync() stalls when racing with updates · 941fbdfd
    Dave Chinner authored
    xfs_ail_push_all_sync() has a loop like this:
    
    while max_ail_lsn {
    	prepare_to_wait(ail_empty)
    	target = max_ail_lsn
    	wake_up(ail_task);
    	schedule()
    }
    
    Which is designed to sleep until the AIL is emptied. When
    xfs_ail_update_finish() moves the tail of the log, it does:
    
    	if (list_empty(&ailp->ail_head))
    		wake_up_all(&ailp->ail_empty);
    
    So it will only wake up the sync push waiter when the AIL goes
    empty. If, by the time the push waiter has woken, the AIL has more
    in it, it will reset the target, wake the push task and go back to
    sleep.
    
    The problem here is that if the AIL is having items added to it
    when xfs_ail_push_all_sync() is called, then they may get inserted
    into the AIL at a LSN higher than the target LSN. At this point,
    xfsaild_push() will see that the target is X, the item LSNs are
    (X+N) and skip over them, hence never pushing the out.
    
    The result of this the AIL will not get emptied by the AIL push
    thread, hence xfs_ail_finish_update() will never see the AIL being
    empty even if it moves the tail. Hence xfs_ail_push_all_sync() never
    gets woken and hence cannot update the push target to capture the
    items beyond the current target on the LSN.
    
    This is a TOCTOU type of issue so the way to avoid it is to not
    use the push target at all for sync pushes. We know that a sync push
    is being requested by the fact the ail_empty wait queue is active,
    hence the xfsaild can just set the target to max_ail_lsn on every
    push that we see the wait queue active. Hence we no longer will
    leave items on the AIL that are beyond the LSN sampled at the start
    of a sync push.
    Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
    Reviewed-by: default avatarChandan Babu R <chandan.babu@oracle.com>
    Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
    Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
    941fbdfd
xfs_trans_ail.c 24.5 KB