diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index be79dd25b8cf..c641c7fa1a03 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1449,15 +1449,34 @@ _xfs_buf_ioapply( } /* - * Asynchronous IO submission path. This transfers the buffer lock ownership and - * the current reference to the IO. It is not safe to reference the buffer after - * a call to this function unless the caller holds an additional reference - * itself. + * Wait for I/O completion of a sync buffer and return the I/O error code. */ static int -__xfs_buf_submit_common( +xfs_buf_iowait( struct xfs_buf *bp) { + ASSERT(!(bp->b_flags & XBF_ASYNC)); + + trace_xfs_buf_iowait(bp, _RET_IP_); + wait_for_completion(&bp->b_iowait); + trace_xfs_buf_iowait_done(bp, _RET_IP_); + + return bp->b_error; +} + +/* + * Buffer I/O submission path, read or write. Asynchronous submission transfers + * the buffer lock ownership and the current reference to the IO. It is not + * safe to reference the buffer after a call to this function unless the caller + * holds an additional reference itself. + */ +int +__xfs_buf_submit( + struct xfs_buf *bp, + bool wait) +{ + int error = 0; + trace_xfs_buf_submit(bp, _RET_IP_); ASSERT(!(bp->b_flags & _XBF_DELWRI_Q)); @@ -1467,9 +1486,18 @@ __xfs_buf_submit_common( xfs_buf_ioerror(bp, -EIO); bp->b_flags &= ~XBF_DONE; xfs_buf_stale(bp); + if (bp->b_flags & XBF_ASYNC) + xfs_buf_ioend(bp); return -EIO; } + /* + * Grab a reference so the buffer does not go away underneath us. For + * async buffers, I/O completion drops the callers reference, which + * could occur before submission returns. + */ + xfs_buf_hold(bp); + if (bp->b_flags & XBF_WRITE) xfs_buf_wait_unpin(bp); @@ -1498,52 +1526,9 @@ __xfs_buf_submit_common( xfs_buf_ioend_async(bp); } - return 0; -} - -/* - * Wait for I/O completion of a sync buffer and return the I/O error code. - */ -static int -xfs_buf_iowait( - struct xfs_buf *bp) -{ - ASSERT(!(bp->b_flags & XBF_ASYNC)); - - trace_xfs_buf_iowait(bp, _RET_IP_); - wait_for_completion(&bp->b_iowait); - trace_xfs_buf_iowait_done(bp, _RET_IP_); - - return bp->b_error; -} - -/* - * Synchronous buffer IO submission path, read or write. - */ -int -__xfs_buf_submit( - struct xfs_buf *bp, - bool wait) -{ - int error; - - /* - * Grab a reference so the buffer does not go away underneath us. For - * async buffers, I/O completion drops the callers reference, which - * could occur before submission returns. - */ - xfs_buf_hold(bp); - - error = __xfs_buf_submit_common(bp); - if (error) { - if (bp->b_flags & XBF_ASYNC) - xfs_buf_ioend(bp); - goto out; - } - if (wait) error = xfs_buf_iowait(bp); -out: + /* * Release the hold that keeps the buffer referenced for the entire * I/O. Note that if the buffer is async, it is not safe to reference