There is no need to use dynamic bio allocation for BDI_CAP_SYNCHRONOUS devices. They can with on-stack bio without concern about waiting bio allocation from mempool under heavy memory pressure. Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Signed-off-by: Minchan Kim <minchan@xxxxxxxxxx> --- Hi Mattew, I didn't use sbvec[nr_pages] as you suggested[1] because I don't think it's pointless in do_mpage_readpage which works per-page base as I replied to you. If I misunderstood something, please correct me. [1] http://lkml.kernel.org/r/<20170808132904.GC31390@xxxxxxxxxxxxxxxxxxxxxx> fs/mpage.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/fs/mpage.c b/fs/mpage.c index 2e4c41ccb5c9..d3b777fdfd5a 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -162,6 +162,9 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, int fully_mapped = 1; unsigned nblocks; unsigned relative_block; + /* on-stack bio for synchronous devices */ + struct bio sbio; + struct bio_vec sbvec; if (page_has_buffers(page)) goto confused; @@ -282,10 +285,22 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, page)) goto out; } - bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), + + if (bdi_cap_synchronous_io(inode_to_bdi(inode))) { + bio = &sbio; + /* mpage_end_io calls bio_put unconditionally */ + bio_get(&sbio); + + bio_init(&sbio, &sbvec, 1); + sbio.bi_bdev = bdev; + sbio.bi_iter.bi_sector = blocks[0] << (blkbits - 9); + } else { + + bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), min_t(int, nr_pages, BIO_MAX_PAGES), gfp); - if (bio == NULL) - goto confused; + if (bio == NULL) + goto confused; + } } length = first_hole << blkbits; @@ -302,6 +317,8 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, else *last_block_in_bio = blocks[blocks_per_page - 1]; out: + if (bio == &sbio) + bio = mpage_bio_submit(REQ_OP_READ, 0, bio); return bio; confused: @@ -492,6 +509,9 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, loff_t i_size = i_size_read(inode); int ret = 0; int op_flags = wbc_to_write_flags(wbc); + /* on-stack-bio */ + struct bio sbio; + struct bio_vec sbvec; if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); @@ -610,10 +630,21 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, goto out; } } - bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), - BIO_MAX_PAGES, GFP_NOFS|__GFP_HIGH); - if (bio == NULL) - goto confused; + + if (bdi_cap_synchronous_io(inode_to_bdi(inode))) { + bio = &sbio; + /* mpage_end_io calls bio_put unconditionally */ + bio_get(&sbio); + + bio_init(&sbio, &sbvec, 1); + sbio.bi_bdev = bdev; + sbio.bi_iter.bi_sector = blocks[0] << (blkbits - 9); + } else { + bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), + BIO_MAX_PAGES, GFP_NOFS|__GFP_HIGH); + if (bio == NULL) + goto confused; + } wbc_init_bio(wbc, bio); bio->bi_write_hint = inode->i_write_hint; @@ -662,6 +693,8 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, */ mapping_set_error(mapping, ret); out: + if (bio == &sbio) + bio = mpage_bio_submit(REQ_OP_WRITE, op_flags, bio); mpd->bio = bio; return ret; } -- 2.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>