xfs: reduce context switches for synchronous buffered I/O
Currently all metadata I/O completions happen in the m_buf_workqueue workqueue. But for synchronous I/O (i.e. all buffer reads) there is no need for that, as there always is a called in process context that is waiting for the I/O. Factor out the guts of xfs_buf_ioend into a separate helper and call it from xfs_buf_iowait to avoid a double an extra context switch to the workqueue. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
2d873efd17
commit
4b90de5bc0
1 changed files with 27 additions and 16 deletions
|
@ -1345,6 +1345,7 @@ xfs_buf_ioend_handle_error(
|
||||||
resubmit:
|
resubmit:
|
||||||
xfs_buf_ioerror(bp, 0);
|
xfs_buf_ioerror(bp, 0);
|
||||||
bp->b_flags |= (XBF_DONE | XBF_WRITE_FAIL);
|
bp->b_flags |= (XBF_DONE | XBF_WRITE_FAIL);
|
||||||
|
reinit_completion(&bp->b_iowait);
|
||||||
xfs_buf_submit(bp);
|
xfs_buf_submit(bp);
|
||||||
return true;
|
return true;
|
||||||
out_stale:
|
out_stale:
|
||||||
|
@ -1355,8 +1356,9 @@ out_stale:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* returns false if the caller needs to resubmit the I/O, else true */
|
||||||
xfs_buf_ioend(
|
static bool
|
||||||
|
__xfs_buf_ioend(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
trace_xfs_buf_iodone(bp, _RET_IP_);
|
trace_xfs_buf_iodone(bp, _RET_IP_);
|
||||||
|
@ -1376,7 +1378,7 @@ xfs_buf_ioend(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(bp->b_error) && xfs_buf_ioend_handle_error(bp))
|
if (unlikely(bp->b_error) && xfs_buf_ioend_handle_error(bp))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
/* clear the retry state */
|
/* clear the retry state */
|
||||||
bp->b_last_error = 0;
|
bp->b_last_error = 0;
|
||||||
|
@ -1397,7 +1399,15 @@ xfs_buf_ioend(
|
||||||
|
|
||||||
bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD |
|
bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD |
|
||||||
_XBF_LOGRECOVERY);
|
_XBF_LOGRECOVERY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xfs_buf_ioend(
|
||||||
|
struct xfs_buf *bp)
|
||||||
|
{
|
||||||
|
if (!__xfs_buf_ioend(bp))
|
||||||
|
return;
|
||||||
if (bp->b_flags & XBF_ASYNC)
|
if (bp->b_flags & XBF_ASYNC)
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
else
|
else
|
||||||
|
@ -1411,15 +1421,8 @@ xfs_buf_ioend_work(
|
||||||
struct xfs_buf *bp =
|
struct xfs_buf *bp =
|
||||||
container_of(work, struct xfs_buf, b_ioend_work);
|
container_of(work, struct xfs_buf, b_ioend_work);
|
||||||
|
|
||||||
xfs_buf_ioend(bp);
|
if (__xfs_buf_ioend(bp))
|
||||||
}
|
xfs_buf_relse(bp);
|
||||||
|
|
||||||
static void
|
|
||||||
xfs_buf_ioend_async(
|
|
||||||
struct xfs_buf *bp)
|
|
||||||
{
|
|
||||||
INIT_WORK(&bp->b_ioend_work, xfs_buf_ioend_work);
|
|
||||||
queue_work(bp->b_mount->m_buf_workqueue, &bp->b_ioend_work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1491,7 +1494,13 @@ xfs_buf_bio_end_io(
|
||||||
XFS_TEST_ERROR(false, bp->b_mount, XFS_ERRTAG_BUF_IOERROR))
|
XFS_TEST_ERROR(false, bp->b_mount, XFS_ERRTAG_BUF_IOERROR))
|
||||||
xfs_buf_ioerror(bp, -EIO);
|
xfs_buf_ioerror(bp, -EIO);
|
||||||
|
|
||||||
xfs_buf_ioend_async(bp);
|
if (bp->b_flags & XBF_ASYNC) {
|
||||||
|
INIT_WORK(&bp->b_ioend_work, xfs_buf_ioend_work);
|
||||||
|
queue_work(bp->b_mount->m_buf_workqueue, &bp->b_ioend_work);
|
||||||
|
} else {
|
||||||
|
complete(&bp->b_iowait);
|
||||||
|
}
|
||||||
|
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1568,9 +1577,11 @@ xfs_buf_iowait(
|
||||||
{
|
{
|
||||||
ASSERT(!(bp->b_flags & XBF_ASYNC));
|
ASSERT(!(bp->b_flags & XBF_ASYNC));
|
||||||
|
|
||||||
trace_xfs_buf_iowait(bp, _RET_IP_);
|
do {
|
||||||
wait_for_completion(&bp->b_iowait);
|
trace_xfs_buf_iowait(bp, _RET_IP_);
|
||||||
trace_xfs_buf_iowait_done(bp, _RET_IP_);
|
wait_for_completion(&bp->b_iowait);
|
||||||
|
trace_xfs_buf_iowait_done(bp, _RET_IP_);
|
||||||
|
} while (!__xfs_buf_ioend(bp));
|
||||||
|
|
||||||
return bp->b_error;
|
return bp->b_error;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue