Skip to content

Commit

Permalink
xfs: factor out buffer I/O failure code
Browse files Browse the repository at this point in the history
We use the same buffer I/O failure code in a few different places.
It's not much code, but it's not necessarily self-explanatory.
Factor it into a helper and document it in one place.

Signed-off-by: Brian Foster <[email protected]>
Reviewed-by: Allison Collins <[email protected]>
Reviewed-by: Dave Chinner <[email protected]>
Reviewed-by: Darrick J. Wong <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Signed-off-by: Darrick J. Wong <[email protected]>
  • Loading branch information
Brian Foster authored and djwong committed May 7, 2020
1 parent cb6ad09 commit 54b3b1f
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 27 deletions.
21 changes: 17 additions & 4 deletions fs/xfs/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,22 @@ xfs_buf_ioerror_alert(
-bp->b_error);
}

/*
* To simulate an I/O failure, the buffer must be locked and held with at least
* three references. The LRU reference is dropped by the stale call. The buf
* item reference is dropped via ioend processing. The third reference is owned
* by the caller and is dropped on I/O completion if the buffer is XBF_ASYNC.
*/
void
xfs_buf_ioend_fail(
struct xfs_buf *bp)
{
bp->b_flags &= ~XBF_DONE;
xfs_buf_stale(bp);
xfs_buf_ioerror(bp, -EIO);
xfs_buf_ioend(bp);
}

int
xfs_bwrite(
struct xfs_buf *bp)
Expand Down Expand Up @@ -1480,10 +1496,7 @@ __xfs_buf_submit(

/* on shutdown we stale and complete the buffer immediately */
if (XFS_FORCED_SHUTDOWN(bp->b_mount)) {
xfs_buf_ioerror(bp, -EIO);
bp->b_flags &= ~XBF_DONE;
xfs_buf_stale(bp);
xfs_buf_ioend(bp);
xfs_buf_ioend_fail(bp);
return -EIO;
}

Expand Down
1 change: 1 addition & 0 deletions fs/xfs/xfs_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ extern void __xfs_buf_ioerror(struct xfs_buf *bp, int error,
xfs_failaddr_t failaddr);
#define xfs_buf_ioerror(bp, err) __xfs_buf_ioerror((bp), (err), __this_address)
extern void xfs_buf_ioerror_alert(struct xfs_buf *bp, xfs_failaddr_t fa);
void xfs_buf_ioend_fail(struct xfs_buf *);

extern int __xfs_buf_submit(struct xfs_buf *bp, bool);
static inline int xfs_buf_submit(struct xfs_buf *bp)
Expand Down
21 changes: 3 additions & 18 deletions fs/xfs/xfs_buf_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,28 +471,13 @@ xfs_buf_item_unpin(
xfs_buf_relse(bp);
} else if (freed && remove) {
/*
* There are currently two references to the buffer - the active
* LRU reference and the buf log item. What we are about to do
* here - simulate a failed IO completion - requires 3
* references.
*
* The LRU reference is removed by the xfs_buf_stale() call. The
* buf item reference is removed by the xfs_buf_iodone()
* callback that is run by xfs_buf_do_callbacks() during ioend
* processing (via the bp->b_iodone callback), and then finally
* the ioend processing will drop the IO reference if the buffer
* is marked XBF_ASYNC.
*
* Hence we need to take an additional reference here so that IO
* completion processing doesn't free the buffer prematurely.
* The buffer must be locked and held by the caller to simulate
* an async I/O failure.
*/
xfs_buf_lock(bp);
xfs_buf_hold(bp);
bp->b_flags |= XBF_ASYNC;
xfs_buf_ioerror(bp, -EIO);
bp->b_flags &= ~XBF_DONE;
xfs_buf_stale(bp);
xfs_buf_ioend(bp);
xfs_buf_ioend_fail(bp);
}
}

Expand Down
6 changes: 1 addition & 5 deletions fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3630,11 +3630,7 @@ xfs_iflush_cluster(
*/
ASSERT(bp->b_iodone);
bp->b_flags |= XBF_ASYNC;
bp->b_flags &= ~XBF_DONE;
xfs_buf_stale(bp);
xfs_buf_ioerror(bp, -EIO);
xfs_buf_ioend(bp);

xfs_buf_ioend_fail(bp);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);

/* abort the corrupt inode, as it was not attached to the buffer */
Expand Down

0 comments on commit 54b3b1f

Please sign in to comment.