aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2012-02-03 18:37:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-02-03 19:16:41 -0500
commit3deaa7190a8da38453c4fabd9dec7f66d17fff67 (patch)
tree23c522d5661bf7e73a39718eaf4eb547cf02b086 /mm/filemap.c
parent55ca6140e9bb307efc97a9301a4f501de02a6fd6 (diff)
readahead: fix pipeline break caused by block plug
Herbert Poetzl reported a performance regression since 2.6.39. The test is a simple dd read, but with big block size. The reason is: T1: ra (A, A+128k), (A+128k, A+256k) T2: lock_page for page A, submit the 256k T3: hit page A+128K, ra (A+256k, A+384). the range isn't submitted because of plug and there isn't any lock_page till we hit page A+256k because all pages from A to A+256k is in memory T4: hit page A+256k, ra (A+384, A+ 512). Because of plug, the range isn't submitted again. T5: lock_page A+256k, so (A+256k, A+512k) will be submitted. The task is waitting for (A+256k, A+512k) finish. There is no request to disk in T3 and T4, so readahead pipeline breaks. We really don't need block plug for generic_file_aio_read() for buffered I/O. The readahead already has plug and has fine grained control when I/O should be submitted. Deleting plug for buffered I/O fixes the regression. One side effect is plug makes the request size 256k, the size is 128k without it. This is because default ra size is 128k and not a reason we need plug here. Vivek said: : We submit some readahead IO to device request queue but because of nested : plug, queue never gets unplugged. When read logic reaches a page which is : not in page cache, it waits for page to be read from the disk : (lock_page_killable()) and that time we flush the plug list. : : So effectively read ahead logic is kind of broken in parts because of : nested plugging. Removing top level plug (generic_file_aio_read()) for : buffered reads, will allow unplugging queue earlier for readahead. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Wu Fengguang <fengguang.wu@intel.com> Reported-by: Herbert Poetzl <herbert@13thfloor.at> Tested-by: Eric Dumazet <eric.dumazet@gmail.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 97f49ed35bd2..b66275757c28 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1400 unsigned long seg = 0; 1400 unsigned long seg = 0;
1401 size_t count; 1401 size_t count;
1402 loff_t *ppos = &iocb->ki_pos; 1402 loff_t *ppos = &iocb->ki_pos;
1403 struct blk_plug plug;
1404 1403
1405 count = 0; 1404 count = 0;
1406 retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); 1405 retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
1407 if (retval) 1406 if (retval)
1408 return retval; 1407 return retval;
1409 1408
1410 blk_start_plug(&plug);
1411
1412 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ 1409 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
1413 if (filp->f_flags & O_DIRECT) { 1410 if (filp->f_flags & O_DIRECT) {
1414 loff_t size; 1411 loff_t size;
@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1424 retval = filemap_write_and_wait_range(mapping, pos, 1421 retval = filemap_write_and_wait_range(mapping, pos,
1425 pos + iov_length(iov, nr_segs) - 1); 1422 pos + iov_length(iov, nr_segs) - 1);
1426 if (!retval) { 1423 if (!retval) {
1424 struct blk_plug plug;
1425
1426 blk_start_plug(&plug);
1427 retval = mapping->a_ops->direct_IO(READ, iocb, 1427 retval = mapping->a_ops->direct_IO(READ, iocb,
1428 iov, pos, nr_segs); 1428 iov, pos, nr_segs);
1429 blk_finish_plug(&plug);
1429 } 1430 }
1430 if (retval > 0) { 1431 if (retval > 0) {
1431 *ppos = pos + retval; 1432 *ppos = pos + retval;
@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1481 break; 1482 break;
1482 } 1483 }
1483out: 1484out:
1484 blk_finish_plug(&plug);
1485 return retval; 1485 return retval;
1486} 1486}
1487EXPORT_SYMBOL(generic_file_aio_read); 1487EXPORT_SYMBOL(generic_file_aio_read);