aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_buf.c88
-rw-r--r--fs/xfs/xfs_buf.h2
-rw-r--r--fs/xfs/xfs_buf_item.c4
-rw-r--r--fs/xfs/xfs_inode.c2
-rw-r--r--fs/xfs/xfs_log.c2
-rw-r--r--fs/xfs/xfs_log_recover.c2
6 files changed, 45 insertions, 55 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 48b1e2989ea4..a046149e6099 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -998,26 +998,30 @@ xfs_buf_wait_unpin(
998 * Buffer Utility Routines 998 * Buffer Utility Routines
999 */ 999 */
1000 1000
1001STATIC void 1001void
1002xfs_buf_iodone_work( 1002xfs_buf_ioend(
1003 struct work_struct *work) 1003 struct xfs_buf *bp)
1004{ 1004{
1005 struct xfs_buf *bp = 1005 bool read = bp->b_flags & XBF_READ;
1006 container_of(work, xfs_buf_t, b_iodone_work); 1006
1007 bool read = !!(bp->b_flags & XBF_READ); 1007 trace_xfs_buf_iodone(bp, _RET_IP_);
1008 1008
1009 bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD); 1009 bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
1010 1010
1011 /* only validate buffers that were read without errors */ 1011 /* Only validate buffers that were read without errors */
1012 if (read && bp->b_ops && !bp->b_error && (bp->b_flags & XBF_DONE)) 1012 if (read && !bp->b_error && bp->b_ops) {
1013 ASSERT(!bp->b_iodone);
1013 bp->b_ops->verify_read(bp); 1014 bp->b_ops->verify_read(bp);
1015 }
1016
1017 if (!bp->b_error)
1018 bp->b_flags |= XBF_DONE;
1014 1019
1015 if (bp->b_iodone) 1020 if (bp->b_iodone)
1016 (*(bp->b_iodone))(bp); 1021 (*(bp->b_iodone))(bp);
1017 else if (bp->b_flags & XBF_ASYNC) 1022 else if (bp->b_flags & XBF_ASYNC)
1018 xfs_buf_relse(bp); 1023 xfs_buf_relse(bp);
1019 else { 1024 else {
1020 ASSERT(read && bp->b_ops);
1021 complete(&bp->b_iowait); 1025 complete(&bp->b_iowait);
1022 1026
1023 /* release the !XBF_ASYNC ref now we are done. */ 1027 /* release the !XBF_ASYNC ref now we are done. */
@@ -1025,30 +1029,22 @@ xfs_buf_iodone_work(
1025 } 1029 }
1026} 1030}
1027 1031
1028void 1032static void
1029xfs_buf_ioend( 1033xfs_buf_ioend_work(
1030 struct xfs_buf *bp, 1034 struct work_struct *work)
1031 int schedule)
1032{ 1035{
1033 bool read = !!(bp->b_flags & XBF_READ); 1036 struct xfs_buf *bp =
1034 1037 container_of(work, xfs_buf_t, b_iodone_work);
1035 trace_xfs_buf_iodone(bp, _RET_IP_);
1036 1038
1037 if (bp->b_error == 0) 1039 xfs_buf_ioend(bp);
1038 bp->b_flags |= XBF_DONE; 1040}
1039 1041
1040 if (bp->b_iodone || (read && bp->b_ops) || (bp->b_flags & XBF_ASYNC)) { 1042void
1041 if (schedule) { 1043xfs_buf_ioend_async(
1042 INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work); 1044 struct xfs_buf *bp)
1043 queue_work(xfslogd_workqueue, &bp->b_iodone_work); 1045{
1044 } else { 1046 INIT_WORK(&bp->b_iodone_work, xfs_buf_ioend_work);
1045 xfs_buf_iodone_work(&bp->b_iodone_work); 1047 queue_work(xfslogd_workqueue, &bp->b_iodone_work);
1046 }
1047 } else {
1048 bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
1049 complete(&bp->b_iowait);
1050 xfs_buf_rele(bp);
1051 }
1052} 1048}
1053 1049
1054void 1050void
@@ -1099,7 +1095,7 @@ xfs_bioerror(
1099 XFS_BUF_UNDONE(bp); 1095 XFS_BUF_UNDONE(bp);
1100 xfs_buf_stale(bp); 1096 xfs_buf_stale(bp);
1101 1097
1102 xfs_buf_ioend(bp, 0); 1098 xfs_buf_ioend(bp);
1103 1099
1104 return -EIO; 1100 return -EIO;
1105} 1101}
@@ -1186,15 +1182,6 @@ xfs_bwrite(
1186} 1182}
1187 1183
1188STATIC void 1184STATIC void
1189_xfs_buf_ioend(
1190 xfs_buf_t *bp,
1191 int schedule)
1192{
1193 if (atomic_dec_and_test(&bp->b_io_remaining) == 1)
1194 xfs_buf_ioend(bp, schedule);
1195}
1196
1197STATIC void
1198xfs_buf_bio_end_io( 1185xfs_buf_bio_end_io(
1199 struct bio *bio, 1186 struct bio *bio,
1200 int error) 1187 int error)
@@ -1211,7 +1198,8 @@ xfs_buf_bio_end_io(
1211 if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) 1198 if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
1212 invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); 1199 invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
1213 1200
1214 _xfs_buf_ioend(bp, 1); 1201 if (atomic_dec_and_test(&bp->b_io_remaining) == 1)
1202 xfs_buf_ioend_async(bp);
1215 bio_put(bio); 1203 bio_put(bio);
1216} 1204}
1217 1205
@@ -1423,15 +1411,17 @@ xfs_buf_iorequest(
1423 /* 1411 /*
1424 * If _xfs_buf_ioapply failed or we are doing synchronous IO that 1412 * If _xfs_buf_ioapply failed or we are doing synchronous IO that
1425 * completes extremely quickly, we can get back here with only the IO 1413 * completes extremely quickly, we can get back here with only the IO
1426 * reference we took above. _xfs_buf_ioend will drop it to zero. Run 1414 * reference we took above. If we drop it to zero, run completion
1427 * completion processing synchronously so that we don't return to the 1415 * processing synchronously so that we don't return to the caller with
1428 * caller with completion still pending. This avoids unnecessary context 1416 * completion still pending. This avoids unnecessary context switches
1429 * switches associated with the end_io workqueue. 1417 * associated with the end_io workqueue.
1430 */ 1418 */
1431 if (bp->b_error || !(bp->b_flags & XBF_ASYNC)) 1419 if (atomic_dec_and_test(&bp->b_io_remaining) == 1) {
1432 _xfs_buf_ioend(bp, 0); 1420 if (bp->b_error || !(bp->b_flags & XBF_ASYNC))
1433 else 1421 xfs_buf_ioend(bp);
1434 _xfs_buf_ioend(bp, 1); 1422 else
1423 xfs_buf_ioend_async(bp);
1424 }
1435 1425
1436 xfs_buf_rele(bp); 1426 xfs_buf_rele(bp);
1437} 1427}
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index c753183900b3..4585c1595a98 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -286,7 +286,7 @@ extern void xfs_buf_unlock(xfs_buf_t *);
286 286
287/* Buffer Read and Write Routines */ 287/* Buffer Read and Write Routines */
288extern int xfs_bwrite(struct xfs_buf *bp); 288extern int xfs_bwrite(struct xfs_buf *bp);
289extern void xfs_buf_ioend(xfs_buf_t *, int); 289extern void xfs_buf_ioend(struct xfs_buf *bp);
290extern void xfs_buf_ioerror(xfs_buf_t *, int); 290extern void xfs_buf_ioerror(xfs_buf_t *, int);
291extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); 291extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
292extern void xfs_buf_iorequest(xfs_buf_t *); 292extern void xfs_buf_iorequest(xfs_buf_t *);
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 76007deed31f..4fd41b58e6d2 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -491,7 +491,7 @@ xfs_buf_item_unpin(
491 xfs_buf_ioerror(bp, -EIO); 491 xfs_buf_ioerror(bp, -EIO);
492 XFS_BUF_UNDONE(bp); 492 XFS_BUF_UNDONE(bp);
493 xfs_buf_stale(bp); 493 xfs_buf_stale(bp);
494 xfs_buf_ioend(bp, 0); 494 xfs_buf_ioend(bp);
495 } 495 }
496} 496}
497 497
@@ -1115,7 +1115,7 @@ do_callbacks:
1115 xfs_buf_do_callbacks(bp); 1115 xfs_buf_do_callbacks(bp);
1116 bp->b_fspriv = NULL; 1116 bp->b_fspriv = NULL;
1117 bp->b_iodone = NULL; 1117 bp->b_iodone = NULL;
1118 xfs_buf_ioend(bp, 0); 1118 xfs_buf_ioend(bp);
1119} 1119}
1120 1120
1121/* 1121/*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index fea3c92fb3f0..00d210bbf3c3 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3056,7 +3056,7 @@ cluster_corrupt_out:
3056 XFS_BUF_UNDONE(bp); 3056 XFS_BUF_UNDONE(bp);
3057 xfs_buf_stale(bp); 3057 xfs_buf_stale(bp);
3058 xfs_buf_ioerror(bp, -EIO); 3058 xfs_buf_ioerror(bp, -EIO);
3059 xfs_buf_ioend(bp, 0); 3059 xfs_buf_ioend(bp);
3060 } else { 3060 } else {
3061 xfs_buf_stale(bp); 3061 xfs_buf_stale(bp);
3062 xfs_buf_relse(bp); 3062 xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 85f36f212641..3567396f4428 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1678,7 +1678,7 @@ xlog_bdstrat(
1678 if (iclog->ic_state & XLOG_STATE_IOERROR) { 1678 if (iclog->ic_state & XLOG_STATE_IOERROR) {
1679 xfs_buf_ioerror(bp, -EIO); 1679 xfs_buf_ioerror(bp, -EIO);
1680 xfs_buf_stale(bp); 1680 xfs_buf_stale(bp);
1681 xfs_buf_ioend(bp, 0); 1681 xfs_buf_ioend(bp);
1682 /* 1682 /*
1683 * It would seem logical to return EIO here, but we rely on 1683 * It would seem logical to return EIO here, but we rely on
1684 * the log state machine to propagate I/O errors instead of 1684 * the log state machine to propagate I/O errors instead of
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 1fd5787add99..4ba19bf7da1f 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -383,7 +383,7 @@ xlog_recover_iodone(
383 SHUTDOWN_META_IO_ERROR); 383 SHUTDOWN_META_IO_ERROR);
384 } 384 }
385 bp->b_iodone = NULL; 385 bp->b_iodone = NULL;
386 xfs_buf_ioend(bp, 0); 386 xfs_buf_ioend(bp);
387} 387}
388 388
389/* 389/*