aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_buf.c')
-rw-r--r--fs/xfs/xfs_buf.c63
1 files changed, 37 insertions, 26 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index bd1a948ee39c..26673a0b20e7 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -571,7 +571,7 @@ found:
571 ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0); 571 ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0);
572 ASSERT(bp->b_iodone == NULL); 572 ASSERT(bp->b_iodone == NULL);
573 bp->b_flags &= _XBF_KMEM | _XBF_PAGES; 573 bp->b_flags &= _XBF_KMEM | _XBF_PAGES;
574 bp->b_pre_io = NULL; 574 bp->b_ops = NULL;
575 } 575 }
576 576
577 trace_xfs_buf_find(bp, flags, _RET_IP_); 577 trace_xfs_buf_find(bp, flags, _RET_IP_);
@@ -657,7 +657,7 @@ xfs_buf_read_map(
657 struct xfs_buf_map *map, 657 struct xfs_buf_map *map,
658 int nmaps, 658 int nmaps,
659 xfs_buf_flags_t flags, 659 xfs_buf_flags_t flags,
660 xfs_buf_iodone_t verify) 660 const struct xfs_buf_ops *ops)
661{ 661{
662 struct xfs_buf *bp; 662 struct xfs_buf *bp;
663 663
@@ -669,7 +669,7 @@ xfs_buf_read_map(
669 669
670 if (!XFS_BUF_ISDONE(bp)) { 670 if (!XFS_BUF_ISDONE(bp)) {
671 XFS_STATS_INC(xb_get_read); 671 XFS_STATS_INC(xb_get_read);
672 bp->b_iodone = verify; 672 bp->b_ops = ops;
673 _xfs_buf_read(bp, flags); 673 _xfs_buf_read(bp, flags);
674 } else if (flags & XBF_ASYNC) { 674 } else if (flags & XBF_ASYNC) {
675 /* 675 /*
@@ -696,13 +696,13 @@ xfs_buf_readahead_map(
696 struct xfs_buftarg *target, 696 struct xfs_buftarg *target,
697 struct xfs_buf_map *map, 697 struct xfs_buf_map *map,
698 int nmaps, 698 int nmaps,
699 xfs_buf_iodone_t verify) 699 const struct xfs_buf_ops *ops)
700{ 700{
701 if (bdi_read_congested(target->bt_bdi)) 701 if (bdi_read_congested(target->bt_bdi))
702 return; 702 return;
703 703
704 xfs_buf_read_map(target, map, nmaps, 704 xfs_buf_read_map(target, map, nmaps,
705 XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD, verify); 705 XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD, ops);
706} 706}
707 707
708/* 708/*
@@ -715,7 +715,7 @@ xfs_buf_read_uncached(
715 xfs_daddr_t daddr, 715 xfs_daddr_t daddr,
716 size_t numblks, 716 size_t numblks,
717 int flags, 717 int flags,
718 xfs_buf_iodone_t verify) 718 const struct xfs_buf_ops *ops)
719{ 719{
720 struct xfs_buf *bp; 720 struct xfs_buf *bp;
721 721
@@ -728,7 +728,7 @@ xfs_buf_read_uncached(
728 bp->b_bn = daddr; 728 bp->b_bn = daddr;
729 bp->b_maps[0].bm_bn = daddr; 729 bp->b_maps[0].bm_bn = daddr;
730 bp->b_flags |= XBF_READ; 730 bp->b_flags |= XBF_READ;
731 bp->b_iodone = verify; 731 bp->b_ops = ops;
732 732
733 xfsbdstrat(target->bt_mount, bp); 733 xfsbdstrat(target->bt_mount, bp);
734 xfs_buf_iowait(bp); 734 xfs_buf_iowait(bp);
@@ -1001,27 +1001,37 @@ STATIC void
1001xfs_buf_iodone_work( 1001xfs_buf_iodone_work(
1002 struct work_struct *work) 1002 struct work_struct *work)
1003{ 1003{
1004 xfs_buf_t *bp = 1004 struct xfs_buf *bp =
1005 container_of(work, xfs_buf_t, b_iodone_work); 1005 container_of(work, xfs_buf_t, b_iodone_work);
1006 bool read = !!(bp->b_flags & XBF_READ);
1007
1008 bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
1009 if (read && bp->b_ops)
1010 bp->b_ops->verify_read(bp);
1006 1011
1007 if (bp->b_iodone) 1012 if (bp->b_iodone)
1008 (*(bp->b_iodone))(bp); 1013 (*(bp->b_iodone))(bp);
1009 else if (bp->b_flags & XBF_ASYNC) 1014 else if (bp->b_flags & XBF_ASYNC)
1010 xfs_buf_relse(bp); 1015 xfs_buf_relse(bp);
1016 else {
1017 ASSERT(read && bp->b_ops);
1018 complete(&bp->b_iowait);
1019 }
1011} 1020}
1012 1021
1013void 1022void
1014xfs_buf_ioend( 1023xfs_buf_ioend(
1015 xfs_buf_t *bp, 1024 struct xfs_buf *bp,
1016 int schedule) 1025 int schedule)
1017{ 1026{
1027 bool read = !!(bp->b_flags & XBF_READ);
1028
1018 trace_xfs_buf_iodone(bp, _RET_IP_); 1029 trace_xfs_buf_iodone(bp, _RET_IP_);
1019 1030
1020 bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
1021 if (bp->b_error == 0) 1031 if (bp->b_error == 0)
1022 bp->b_flags |= XBF_DONE; 1032 bp->b_flags |= XBF_DONE;
1023 1033
1024 if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) { 1034 if (bp->b_iodone || (read && bp->b_ops) || (bp->b_flags & XBF_ASYNC)) {
1025 if (schedule) { 1035 if (schedule) {
1026 INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work); 1036 INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work);
1027 queue_work(xfslogd_workqueue, &bp->b_iodone_work); 1037 queue_work(xfslogd_workqueue, &bp->b_iodone_work);
@@ -1029,6 +1039,7 @@ xfs_buf_ioend(
1029 xfs_buf_iodone_work(&bp->b_iodone_work); 1039 xfs_buf_iodone_work(&bp->b_iodone_work);
1030 } 1040 }
1031 } else { 1041 } else {
1042 bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
1032 complete(&bp->b_iowait); 1043 complete(&bp->b_iowait);
1033 } 1044 }
1034} 1045}
@@ -1316,6 +1327,20 @@ _xfs_buf_ioapply(
1316 rw |= REQ_FUA; 1327 rw |= REQ_FUA;
1317 if (bp->b_flags & XBF_FLUSH) 1328 if (bp->b_flags & XBF_FLUSH)
1318 rw |= REQ_FLUSH; 1329 rw |= REQ_FLUSH;
1330
1331 /*
1332 * Run the write verifier callback function if it exists. If
1333 * this function fails it will mark the buffer with an error and
1334 * the IO should not be dispatched.
1335 */
1336 if (bp->b_ops) {
1337 bp->b_ops->verify_write(bp);
1338 if (bp->b_error) {
1339 xfs_force_shutdown(bp->b_target->bt_mount,
1340 SHUTDOWN_CORRUPT_INCORE);
1341 return;
1342 }
1343 }
1319 } else if (bp->b_flags & XBF_READ_AHEAD) { 1344 } else if (bp->b_flags & XBF_READ_AHEAD) {
1320 rw = READA; 1345 rw = READA;
1321 } else { 1346 } else {
@@ -1326,20 +1351,6 @@ _xfs_buf_ioapply(
1326 rw |= REQ_META; 1351 rw |= REQ_META;
1327 1352
1328 /* 1353 /*
1329 * run the pre-io callback function if it exists. If this function
1330 * fails it will mark the buffer with an error and the IO should
1331 * not be dispatched.
1332 */
1333 if (bp->b_pre_io) {
1334 bp->b_pre_io(bp);
1335 if (bp->b_error) {
1336 xfs_force_shutdown(bp->b_target->bt_mount,
1337 SHUTDOWN_CORRUPT_INCORE);
1338 return;
1339 }
1340 }
1341
1342 /*
1343 * Walk all the vectors issuing IO on them. Set up the initial offset 1354 * Walk all the vectors issuing IO on them. Set up the initial offset
1344 * into the buffer and the desired IO size before we start - 1355 * into the buffer and the desired IO size before we start -
1345 * _xfs_buf_ioapply_vec() will modify them appropriately for each 1356 * _xfs_buf_ioapply_vec() will modify them appropriately for each