[PATCH v2] xfs: Fix oops on IO error during xlog_recover_process_iunlinks()
Jan Kara
jack at suse.cz
Tue Mar 6 04:39:48 CST 2012
When an IO error happens during inode deletion run from
xlog_recover_process_iunlinks() filesystem gets shutdown. Thus any subsequent
attempt to read buffers fails. Code in xlog_recover_process_iunlinks() does not
count with the fact that read of a buffer which was read a while ago can
really fail which results in the oops on
agi = XFS_BUF_TO_AGI(agibp);
Fix the problem by cleaning up the buffer handling in
xlog_recover_process_iunlinks(). We release buffer lock but keep buffer
reference to AG buffer. That is enough for buffer to not go away under us
and we don't have to call xfs_read_agi() all the time.
CC: stable at kernel.org
Signed-off-by: Jan Kara <jack at suse.cz>
---
fs/xfs/xfs_log_recover.c | 34 ++++++++++++----------------------
1 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 0ed9ee7..0827644 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3161,37 +3161,27 @@ xlog_recover_process_iunlinks(
*/
continue;
}
+ /*
+ * Take an extra reference to the buffer and then release it
+ * to drop the lock so that it can be acquired in the normal
+ * course of the transaction to truncate and free each
+ * inode. Because we are not racing with anyone else here
+ * for the AGI buffer, we don't even need to hold it locked
+ * to read the initial unlinked bucket entries out of the
+ * buffer.
+ */
agi = XFS_BUF_TO_AGI(agibp);
+ xfs_buf_hold(agibp);
+ xfs_buf_relse(agibp);
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
agino = be32_to_cpu(agi->agi_unlinked[bucket]);
while (agino != NULLAGINO) {
- /*
- * Release the agi buffer so that it can
- * be acquired in the normal course of the
- * transaction to truncate and free the inode.
- */
- xfs_buf_relse(agibp);
-
agino = xlog_recover_process_one_iunlink(mp,
agno, agino, bucket);
-
- /*
- * Reacquire the agibuffer and continue around
- * the loop. This should never fail as we know
- * the buffer was good earlier on.
- */
- error = xfs_read_agi(mp, NULL, agno, &agibp);
- ASSERT(error == 0);
- agi = XFS_BUF_TO_AGI(agibp);
}
}
-
- /*
- * Release the buffer for the current agi so we can
- * go on to the next one.
- */
- xfs_buf_relse(agibp);
+ xfs_buf_rele(agibp);
}
mp->m_dmevmask = mp_dmevmask;
--
1.7.1
--jI8keyz6grp/JLjh--
More information about the xfs
mailing list