Skip to content

Commit d87f639

Browse files
rgushchintytso
authored andcommitted
ext4: use non-movable memory for superblock readahead
Since commit a8ac900 ("ext4: use non-movable memory for the superblock") buffers for ext4 superblock were allocated using the sb_bread_unmovable() helper which allocated buffer heads out of non-movable memory blocks. It was necessarily to not block page migrations and do not cause cma allocation failures. However commit 85c8f17 ("ext4: preload block group descriptors") broke this by introducing pre-reading of the ext4 superblock. The problem is that __breadahead() is using __getblk() underneath, which allocates buffer heads out of movable memory. It resulted in page migration failures I've seen on a machine with an ext4 partition and a preallocated cma area. Fix this by introducing sb_breadahead_unmovable() and __breadahead_gfp() helpers which use non-movable memory for buffer head allocations and use them for the ext4 superblock readahead. Reviewed-by: Andreas Dilger <[email protected]> Fixes: 85c8f17 ("ext4: preload block group descriptors") Signed-off-by: Roman Gushchin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent c2a559b commit d87f639

File tree

4 files changed

+21
-2
lines changed

4 files changed

+21
-2
lines changed

fs/buffer.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,17 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
13711371
}
13721372
EXPORT_SYMBOL(__breadahead);
13731373

1374+
void __breadahead_gfp(struct block_device *bdev, sector_t block, unsigned size,
1375+
gfp_t gfp)
1376+
{
1377+
struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
1378+
if (likely(bh)) {
1379+
ll_rw_block(REQ_OP_READ, REQ_RAHEAD, 1, &bh);
1380+
brelse(bh);
1381+
}
1382+
}
1383+
EXPORT_SYMBOL(__breadahead_gfp);
1384+
13741385
/**
13751386
* __bread_gfp() - reads a specified block and returns the bh
13761387
* @bdev: the block_device to read from

fs/ext4/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4364,7 +4364,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
43644364
if (end > table)
43654365
end = table;
43664366
while (b <= end)
4367-
sb_breadahead(sb, b++);
4367+
sb_breadahead_unmovable(sb, b++);
43684368
}
43694369

43704370
/*

fs/ext4/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4340,7 +4340,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
43404340
/* Pre-read the descriptors into the buffer cache */
43414341
for (i = 0; i < db_count; i++) {
43424342
block = descriptor_loc(sb, logical_sb_block, i);
4343-
sb_breadahead(sb, block);
4343+
sb_breadahead_unmovable(sb, block);
43444344
}
43454345

43464346
for (i = 0; i < db_count; i++) {

include/linux/buffer_head.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ struct buffer_head *__getblk_gfp(struct block_device *bdev, sector_t block,
189189
void __brelse(struct buffer_head *);
190190
void __bforget(struct buffer_head *);
191191
void __breadahead(struct block_device *, sector_t block, unsigned int size);
192+
void __breadahead_gfp(struct block_device *, sector_t block, unsigned int size,
193+
gfp_t gfp);
192194
struct buffer_head *__bread_gfp(struct block_device *,
193195
sector_t block, unsigned size, gfp_t gfp);
194196
void invalidate_bh_lrus(void);
@@ -319,6 +321,12 @@ sb_breadahead(struct super_block *sb, sector_t block)
319321
__breadahead(sb->s_bdev, block, sb->s_blocksize);
320322
}
321323

324+
static inline void
325+
sb_breadahead_unmovable(struct super_block *sb, sector_t block)
326+
{
327+
__breadahead_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
328+
}
329+
322330
static inline struct buffer_head *
323331
sb_getblk(struct super_block *sb, sector_t block)
324332
{

0 commit comments

Comments
 (0)