diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-12-31 07:35:57 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-12-31 07:35:57 -0500 |
commit | 2ca1a615835d9f4990f42102ab1f2ef434e7e89c (patch) | |
tree | 726cf3d5f29a6c66c44e4bd68e7ebed2fd83d059 /fs/xfs/linux-2.6/xfs_buf.c | |
parent | e12f0102ac81d660c9f801d0a0e10ccf4537a9de (diff) | |
parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
arch/x86/kernel/io_apic.c
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_buf.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 87 |
1 files changed, 49 insertions, 38 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 36d5fcd3f593..cb329edc925b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -630,6 +630,29 @@ xfs_buf_get_flags( | |||
630 | return NULL; | 630 | return NULL; |
631 | } | 631 | } |
632 | 632 | ||
633 | STATIC int | ||
634 | _xfs_buf_read( | ||
635 | xfs_buf_t *bp, | ||
636 | xfs_buf_flags_t flags) | ||
637 | { | ||
638 | int status; | ||
639 | |||
640 | XB_TRACE(bp, "_xfs_buf_read", (unsigned long)flags); | ||
641 | |||
642 | ASSERT(!(flags & (XBF_DELWRI|XBF_WRITE))); | ||
643 | ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); | ||
644 | |||
645 | bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \ | ||
646 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | ||
647 | bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | \ | ||
648 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | ||
649 | |||
650 | status = xfs_buf_iorequest(bp); | ||
651 | if (!status && !(flags & XBF_ASYNC)) | ||
652 | status = xfs_buf_iowait(bp); | ||
653 | return status; | ||
654 | } | ||
655 | |||
633 | xfs_buf_t * | 656 | xfs_buf_t * |
634 | xfs_buf_read_flags( | 657 | xfs_buf_read_flags( |
635 | xfs_buftarg_t *target, | 658 | xfs_buftarg_t *target, |
@@ -646,7 +669,7 @@ xfs_buf_read_flags( | |||
646 | if (!XFS_BUF_ISDONE(bp)) { | 669 | if (!XFS_BUF_ISDONE(bp)) { |
647 | XB_TRACE(bp, "read", (unsigned long)flags); | 670 | XB_TRACE(bp, "read", (unsigned long)flags); |
648 | XFS_STATS_INC(xb_get_read); | 671 | XFS_STATS_INC(xb_get_read); |
649 | xfs_buf_iostart(bp, flags); | 672 | _xfs_buf_read(bp, flags); |
650 | } else if (flags & XBF_ASYNC) { | 673 | } else if (flags & XBF_ASYNC) { |
651 | XB_TRACE(bp, "read_async", (unsigned long)flags); | 674 | XB_TRACE(bp, "read_async", (unsigned long)flags); |
652 | /* | 675 | /* |
@@ -1048,50 +1071,39 @@ xfs_buf_ioerror( | |||
1048 | XB_TRACE(bp, "ioerror", (unsigned long)error); | 1071 | XB_TRACE(bp, "ioerror", (unsigned long)error); |
1049 | } | 1072 | } |
1050 | 1073 | ||
1051 | /* | ||
1052 | * Initiate I/O on a buffer, based on the flags supplied. | ||
1053 | * The b_iodone routine in the buffer supplied will only be called | ||
1054 | * when all of the subsidiary I/O requests, if any, have been completed. | ||
1055 | */ | ||
1056 | int | 1074 | int |
1057 | xfs_buf_iostart( | 1075 | xfs_bawrite( |
1058 | xfs_buf_t *bp, | 1076 | void *mp, |
1059 | xfs_buf_flags_t flags) | 1077 | struct xfs_buf *bp) |
1060 | { | 1078 | { |
1061 | int status = 0; | 1079 | XB_TRACE(bp, "bawrite", 0); |
1062 | 1080 | ||
1063 | XB_TRACE(bp, "iostart", (unsigned long)flags); | 1081 | ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); |
1064 | 1082 | ||
1065 | if (flags & XBF_DELWRI) { | 1083 | xfs_buf_delwri_dequeue(bp); |
1066 | bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC); | ||
1067 | bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC); | ||
1068 | xfs_buf_delwri_queue(bp, 1); | ||
1069 | return 0; | ||
1070 | } | ||
1071 | 1084 | ||
1072 | bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \ | 1085 | bp->b_flags &= ~(XBF_READ | XBF_DELWRI | XBF_READ_AHEAD); |
1073 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | 1086 | bp->b_flags |= (XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES); |
1074 | bp->b_flags |= flags & (XBF_READ | XBF_WRITE | XBF_ASYNC | \ | 1087 | |
1075 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | 1088 | bp->b_mount = mp; |
1089 | bp->b_strat = xfs_bdstrat_cb; | ||
1090 | return xfs_bdstrat_cb(bp); | ||
1091 | } | ||
1076 | 1092 | ||
1077 | BUG_ON(bp->b_bn == XFS_BUF_DADDR_NULL); | 1093 | void |
1094 | xfs_bdwrite( | ||
1095 | void *mp, | ||
1096 | struct xfs_buf *bp) | ||
1097 | { | ||
1098 | XB_TRACE(bp, "bdwrite", 0); | ||
1078 | 1099 | ||
1079 | /* For writes allow an alternate strategy routine to precede | 1100 | bp->b_strat = xfs_bdstrat_cb; |
1080 | * the actual I/O request (which may not be issued at all in | 1101 | bp->b_mount = mp; |
1081 | * a shutdown situation, for example). | ||
1082 | */ | ||
1083 | status = (flags & XBF_WRITE) ? | ||
1084 | xfs_buf_iostrategy(bp) : xfs_buf_iorequest(bp); | ||
1085 | 1102 | ||
1086 | /* Wait for I/O if we are not an async request. | 1103 | bp->b_flags &= ~XBF_READ; |
1087 | * Note: async I/O request completion will release the buffer, | 1104 | bp->b_flags |= (XBF_DELWRI | XBF_ASYNC); |
1088 | * and that can already be done by this point. So using the | ||
1089 | * buffer pointer from here on, after async I/O, is invalid. | ||
1090 | */ | ||
1091 | if (!status && !(flags & XBF_ASYNC)) | ||
1092 | status = xfs_buf_iowait(bp); | ||
1093 | 1105 | ||
1094 | return status; | 1106 | xfs_buf_delwri_queue(bp, 1); |
1095 | } | 1107 | } |
1096 | 1108 | ||
1097 | STATIC_INLINE void | 1109 | STATIC_INLINE void |
@@ -1114,8 +1126,7 @@ xfs_buf_bio_end_io( | |||
1114 | unsigned int blocksize = bp->b_target->bt_bsize; | 1126 | unsigned int blocksize = bp->b_target->bt_bsize; |
1115 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 1127 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
1116 | 1128 | ||
1117 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) | 1129 | xfs_buf_ioerror(bp, -error); |
1118 | bp->b_error = EIO; | ||
1119 | 1130 | ||
1120 | do { | 1131 | do { |
1121 | struct page *page = bvec->bv_page; | 1132 | struct page *page = bvec->bv_page; |