aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c53
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h1
2 files changed, 49 insertions, 5 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index a7c7cb27fa5a..522cfaa70258 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -409,7 +409,6 @@ _xfs_buf_lookup_pages(
409 congestion_wait(WRITE, HZ/50); 409 congestion_wait(WRITE, HZ/50);
410 goto retry; 410 goto retry;
411 } 411 }
412 unlock_page(page);
413 412
414 XFS_STATS_INC(xb_page_found); 413 XFS_STATS_INC(xb_page_found);
415 414
@@ -419,7 +418,10 @@ _xfs_buf_lookup_pages(
419 ASSERT(!PagePrivate(page)); 418 ASSERT(!PagePrivate(page));
420 if (!PageUptodate(page)) { 419 if (!PageUptodate(page)) {
421 page_count--; 420 page_count--;
422 if (blocksize < PAGE_CACHE_SIZE && !PagePrivate(page)) { 421 if (blocksize >= PAGE_CACHE_SIZE) {
422 if (flags & XBF_READ)
423 bp->b_locked = 1;
424 } else if (!PagePrivate(page)) {
423 if (test_page_region(page, offset, nbytes)) 425 if (test_page_region(page, offset, nbytes))
424 page_count++; 426 page_count++;
425 } 427 }
@@ -429,6 +431,11 @@ _xfs_buf_lookup_pages(
429 offset = 0; 431 offset = 0;
430 } 432 }
431 433
434 if (!bp->b_locked) {
435 for (i = 0; i < bp->b_page_count; i++)
436 unlock_page(bp->b_pages[i]);
437 }
438
432 if (page_count == bp->b_page_count) 439 if (page_count == bp->b_page_count)
433 bp->b_flags |= XBF_DONE; 440 bp->b_flags |= XBF_DONE;
434 441
@@ -745,6 +752,7 @@ xfs_buf_associate_memory(
745 bp->b_pages[i] = mem_to_page((void *)pageaddr); 752 bp->b_pages[i] = mem_to_page((void *)pageaddr);
746 pageaddr += PAGE_CACHE_SIZE; 753 pageaddr += PAGE_CACHE_SIZE;
747 } 754 }
755 bp->b_locked = 0;
748 756
749 bp->b_count_desired = len; 757 bp->b_count_desired = len;
750 bp->b_buffer_length = buflen; 758 bp->b_buffer_length = buflen;
@@ -1091,13 +1099,25 @@ xfs_buf_iostart(
1091 return status; 1099 return status;
1092} 1100}
1093 1101
1102STATIC_INLINE int
1103_xfs_buf_iolocked(
1104 xfs_buf_t *bp)
1105{
1106 ASSERT(bp->b_flags & (XBF_READ | XBF_WRITE));
1107 if (bp->b_flags & XBF_READ)
1108 return bp->b_locked;
1109 return 0;
1110}
1111
1094STATIC_INLINE void 1112STATIC_INLINE void
1095_xfs_buf_ioend( 1113_xfs_buf_ioend(
1096 xfs_buf_t *bp, 1114 xfs_buf_t *bp,
1097 int schedule) 1115 int schedule)
1098{ 1116{
1099 if (atomic_dec_and_test(&bp->b_io_remaining) == 1) 1117 if (atomic_dec_and_test(&bp->b_io_remaining) == 1) {
1118 bp->b_locked = 0;
1100 xfs_buf_ioend(bp, schedule); 1119 xfs_buf_ioend(bp, schedule);
1120 }
1101} 1121}
1102 1122
1103STATIC void 1123STATIC void
@@ -1128,6 +1148,10 @@ xfs_buf_bio_end_io(
1128 1148
1129 if (--bvec >= bio->bi_io_vec) 1149 if (--bvec >= bio->bi_io_vec)
1130 prefetchw(&bvec->bv_page->flags); 1150 prefetchw(&bvec->bv_page->flags);
1151
1152 if (_xfs_buf_iolocked(bp)) {
1153 unlock_page(page);
1154 }
1131 } while (bvec >= bio->bi_io_vec); 1155 } while (bvec >= bio->bi_io_vec);
1132 1156
1133 _xfs_buf_ioend(bp, 1); 1157 _xfs_buf_ioend(bp, 1);
@@ -1138,12 +1162,13 @@ STATIC void
1138_xfs_buf_ioapply( 1162_xfs_buf_ioapply(
1139 xfs_buf_t *bp) 1163 xfs_buf_t *bp)
1140{ 1164{
1141 int rw, map_i, total_nr_pages, nr_pages; 1165 int i, rw, map_i, total_nr_pages, nr_pages;
1142 struct bio *bio; 1166 struct bio *bio;
1143 int offset = bp->b_offset; 1167 int offset = bp->b_offset;
1144 int size = bp->b_count_desired; 1168 int size = bp->b_count_desired;
1145 sector_t sector = bp->b_bn; 1169 sector_t sector = bp->b_bn;
1146 unsigned int blocksize = bp->b_target->bt_bsize; 1170 unsigned int blocksize = bp->b_target->bt_bsize;
1171 int locking = _xfs_buf_iolocked(bp);
1147 1172
1148 total_nr_pages = bp->b_page_count; 1173 total_nr_pages = bp->b_page_count;
1149 map_i = 0; 1174 map_i = 0;
@@ -1166,7 +1191,7 @@ _xfs_buf_ioapply(
1166 * filesystem block size is not smaller than the page size. 1191 * filesystem block size is not smaller than the page size.
1167 */ 1192 */
1168 if ((bp->b_buffer_length < PAGE_CACHE_SIZE) && 1193 if ((bp->b_buffer_length < PAGE_CACHE_SIZE) &&
1169 (bp->b_flags & XBF_READ) && 1194 (bp->b_flags & XBF_READ) && locking &&
1170 (blocksize >= PAGE_CACHE_SIZE)) { 1195 (blocksize >= PAGE_CACHE_SIZE)) {
1171 bio = bio_alloc(GFP_NOIO, 1); 1196 bio = bio_alloc(GFP_NOIO, 1);
1172 1197
@@ -1183,6 +1208,24 @@ _xfs_buf_ioapply(
1183 goto submit_io; 1208 goto submit_io;
1184 } 1209 }
1185 1210
1211 /* Lock down the pages which we need to for the request */
1212 if (locking && (bp->b_flags & XBF_WRITE) && (bp->b_locked == 0)) {
1213 for (i = 0; size; i++) {
1214 int nbytes = PAGE_CACHE_SIZE - offset;
1215 struct page *page = bp->b_pages[i];
1216
1217 if (nbytes > size)
1218 nbytes = size;
1219
1220 lock_page(page);
1221
1222 size -= nbytes;
1223 offset = 0;
1224 }
1225 offset = bp->b_offset;
1226 size = bp->b_count_desired;
1227 }
1228
1186next_chunk: 1229next_chunk:
1187 atomic_inc(&bp->b_io_remaining); 1230 atomic_inc(&bp->b_io_remaining);
1188 nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); 1231 nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT);
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index a3d207de48b8..b5908a34b15d 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -143,6 +143,7 @@ typedef struct xfs_buf {
143 void *b_fspriv2; 143 void *b_fspriv2;
144 void *b_fspriv3; 144 void *b_fspriv3;
145 unsigned short b_error; /* error code on I/O */ 145 unsigned short b_error; /* error code on I/O */
146 unsigned short b_locked; /* page array is locked */
146 unsigned int b_page_count; /* size of page array */ 147 unsigned int b_page_count; /* size of page array */
147 unsigned int b_offset; /* page offset in first page */ 148 unsigned int b_offset; /* page offset in first page */
148 struct page **b_pages; /* array of page pointers */ 149 struct page **b_pages; /* array of page pointers */