• Dave Chinner's avatar
    xfs: log shutdown triggers should only shut down the log · b5f17bec
    Dave Chinner authored
    We've got a mess on our hands.
    
    1. xfs_trans_commit() cannot cancel transactions because the mount is
    shut down - that causes dirty, aborted, unlogged log items to sit
    unpinned in memory and potentially get written to disk before the
    log is shut down. Hence xfs_trans_commit() can only abort
    transactions when xlog_is_shutdown() is true.
    
    2. xfs_force_shutdown() is used in places to cause the current
    modification to be aborted via xfs_trans_commit() because it may be
    impractical or impossible to cancel the transaction directly, and
    hence xfs_trans_commit() must cancel transactions when
    xfs_is_shutdown() is true in this situation. But we can't do that
    because of #1.
    
    3. Log IO errors cause log shutdowns by calling xfs_force_shutdown()
    to shut down the mount and then the log from log IO completion.
    
    4. xfs_force_shutdown() can result in a log force being issued,
    which has to wait for log IO completion before it will mark the log
    as shut down. If #3 races with some other shutdown trigger that runs
    a log force, we rely on xfs_force_shutdown() silently ignoring #3
    and avoiding shutting down the log until the failed log force
    completes.
    
    5. To ensure #2 always works, we have to ensure that
    xfs_force_shutdown() does not return until the the log is shut down.
    But in the case of #4, this will result in a deadlock because the
    log Io completion will block waiting for a log force to complete
    which is blocked waiting for log IO to complete....
    
    So the very first thing we have to do here to untangle this mess is
    dissociate log shutdown triggers from mount shutdowns. We already
    have xlog_forced_shutdown, which will atomically transistion to the
    log a shutdown state. Due to internal asserts it cannot be called
    multiple times, but was done simply because the only place that
    could call it was xfs_do_force_shutdown() (i.e. the mount shutdown!)
    and that could only call it once and once only.  So the first thing
    we do is remove the asserts.
    
    We then convert all the internal log shutdown triggers to call
    xlog_force_shutdown() directly instead of xfs_force_shutdown(). This
    allows the log shutdown triggers to shut down the log without
    needing to care about mount based shutdown constraints. This means
    we shut down the log independently of the mount and the mount may
    not notice this until it's next attempt to read or modify metadata.
    At that point (e.g. xfs_trans_commit()) it will see that the log is
    shutdown, error out and shutdown the mount.
    
    To ensure that all the unmount behaviours and asserts track
    correctly as a result of a log shutdown, propagate the shutdown up
    to the mount if it is not already set. This keeps the mount and log
    state in sync, and saves a huge amount of hassle where code fails
    because of a log shutdown but only checks for mount shutdowns and
    hence ends up doing the wrong thing. Cleaning up that mess is
    an exercise for another day.
    
    This enables us to address the other problems noted above in
    followup patches.
    Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
    Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
    Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
    b5f17bec
xfs_mount.c 36.4 KB