xfs: don't leave EFIs on AIL on mount failure
Log recovery occurs in two phases at mount time. In the first phase, EFIs and EFDs are processed and potentially cancelled out. EFIs without EFD objects are inserted into the AIL for processing and recovery in the second phase. xfs_mountfs() runs various other operations between the phases and is thus subject to failure. If failure occurs after the first phase but before the second, pending EFIs sit on the AIL, pin it and cause the mount to hang. Update the mount sequence to ensure that pending EFIs are cancelled in the event of failure. Add a recovery cancellation mechanism to iterate the AIL and cancel all EFI items when requested. Plumb cancellation support through the log mount finish helper and update xfs_mountfs() to invoke cancellation in the event of failure after recovery has started. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:

committed by
Dave Chinner

parent
e32a1d1fbf
commit
f0b2efad16
@@ -700,6 +700,7 @@ xfs_log_mount(
|
||||
if (error) {
|
||||
xfs_warn(mp, "log mount/recovery failed: error %d",
|
||||
error);
|
||||
xlog_recover_cancel(mp->m_log);
|
||||
goto out_destroy_ail;
|
||||
}
|
||||
}
|
||||
@@ -740,18 +741,35 @@ out:
|
||||
* it.
|
||||
*/
|
||||
int
|
||||
xfs_log_mount_finish(xfs_mount_t *mp)
|
||||
xfs_log_mount_finish(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
|
||||
error = xlog_recover_finish(mp->m_log);
|
||||
if (!error)
|
||||
xfs_log_work_queue(mp);
|
||||
} else {
|
||||
if (mp->m_flags & XFS_MOUNT_NORECOVERY) {
|
||||
ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = xlog_recover_finish(mp->m_log);
|
||||
if (!error)
|
||||
xfs_log_work_queue(mp);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* The mount has failed. Cancel the recovery if it hasn't completed and destroy
|
||||
* the log.
|
||||
*/
|
||||
int
|
||||
xfs_log_mount_cancel(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = xlog_recover_cancel(mp->m_log);
|
||||
xfs_log_unmount(mp);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
Reference in New Issue
Block a user