From: David Chinner It looks like the workqueue is being run while the log is being torn down. On unmount, we write a log record to indicate a clean unmount just before we tear the log down. We sleep on the iclog force semaphore waiting for the log I/O to complete, which is processed by xfslogd and xlog_iodone(). xlog_iodone() calls xlog_state_done_syncing() which processes the I/O completion and wakes the unmount process sleeping on the semaphore. xlog_state_done_syncing() then does a bit more work before returning to xlog_iodone() where we check the buffer to determine if it was an async I/o or not. However, before we get to this, the unmount process has woken and continued onwards which then frees the iclogs and the buffer. Hence we have a race between xlog_iodone() looking at the buffer and the unmount process tearing the buffer down. There's a couple of different ways I can see to fix the problem - the first is to not reference the buffer in xlog_iodone() after running the callbacks that may trigger it being freed. I'd prfer to see if this fixes the problem before having to do more invasive surgery. Cc: Michal Piotrowski Signed-off-by: Andrew Morton --- fs/xfs/xfs_log.c | 11 ++++------- 1 files changed, 4 insertions(+), 7 deletions(-) diff -puN fs/xfs/xfs_log.c~xfs-fix-unmount-race fs/xfs/xfs_log.c --- a/fs/xfs/xfs_log.c~xfs-fix-unmount-race +++ a/fs/xfs/xfs_log.c @@ -967,14 +967,11 @@ xlog_iodone(xfs_buf_t *bp) } else if (iclog->ic_state & XLOG_STATE_IOERROR) { aborted = XFS_LI_ABORTED; } + /* log I/O is always issued ASYNC, so we should see that here */ + WARN_ON(!(XFS_BUF_ISASYNC(bp))); xlog_state_done_syncing(iclog, aborted); - if (!(XFS_BUF_ISASYNC(bp))) { - /* - * Corresponding psema() will be done in bwrite(). If we don't - * vsema() here, panic. - */ - XFS_BUF_V_IODONESEMA(bp); - } + /* do not reference bp here - it may have been freed during unmount */ + } /* xlog_iodone */ /* _