From: Davidlohr Bueso <dave@xxxxxxxxxxxx> Callers that do not require atomic context for pagecache lookups can use this flavor to avoid the unnencesary contention on the blockdev mapping i_private_lock as well as waiting on noref migration. Convert local caller write_boundary_block() which already takes the buffer lock as well as bdev_getblk() depending on the respective gpf flags. Either way there are no currently changes in semantics. Signed-off-by: Davidlohr Bueso <dave@xxxxxxxxxxxx> Signed-off-by: Luis Chamberlain <mcgrof@xxxxxxxxxx> --- fs/buffer.c | 19 +++++++++++++++++-- include/linux/buffer_head.h | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 5a1a37a6840a..07ec57ec100e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -662,7 +662,8 @@ EXPORT_SYMBOL(generic_buffers_fsync); void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize) { - struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize); + struct buffer_head *bh = __find_get_block_nonatomic(bdev, bblock + 1, + blocksize); if (bh) { if (buffer_dirty(bh)) write_dirty_buffer(bh, 0); @@ -1418,6 +1419,15 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) } EXPORT_SYMBOL(__find_get_block); +/* same as __find_get_block() but allows sleeping contexts */ +struct buffer_head * +__find_get_block_nonatomic(struct block_device *bdev, sector_t block, + unsigned size) +{ + return find_get_block_common(bdev, block, size, false); +} +EXPORT_SYMBOL(__find_get_block_nonatomic); + /** * bdev_getblk - Get a buffer_head in a block device's buffer cache. * @bdev: The block device. @@ -1435,7 +1445,12 @@ EXPORT_SYMBOL(__find_get_block); struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, unsigned size, gfp_t gfp) { - struct buffer_head *bh = __find_get_block(bdev, block, size); + struct buffer_head *bh; + + if (gfpflags_allow_blocking(gfp)) + bh = __find_get_block_nonatomic(bdev, block, size); + else + bh = __find_get_block(bdev, block, size); might_alloc(gfp); if (bh) diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index f0a4ad7839b6..2b5458517def 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -222,6 +222,8 @@ void __wait_on_buffer(struct buffer_head *); wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, unsigned size); +struct buffer_head *__find_get_block_nonatomic(struct block_device *bdev, + sector_t block, unsigned size); struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, unsigned size, gfp_t gfp); void __brelse(struct buffer_head *); -- 2.47.2