gfs2: More gfs2_find_jhead fixes
It turns out that when extending an existing bio, gfs2_find_jhead fails to check if the block number is consecutive, which leads to incorrect reads for fragmented journals. In addition, limit the maximum bio size to an arbitrary value of 2 megabytes: since commit07173c3ec2
("block: enable multipage bvecs"), if we just keep adding pages until bio_add_page fails, bios will grow much larger than useful, which pins more memory than necessary with barely any additional performance gains. Fixes:f4686c26ec
("gfs2: read journal in large chunks") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
This commit is contained in:
Родитель
566a2ab3c9
Коммит
aa83da7f47
|
@ -263,7 +263,7 @@ static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno,
|
||||||
struct super_block *sb = sdp->sd_vfs;
|
struct super_block *sb = sdp->sd_vfs;
|
||||||
struct bio *bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES);
|
struct bio *bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES);
|
||||||
|
|
||||||
bio->bi_iter.bi_sector = blkno << (sb->s_blocksize_bits - 9);
|
bio->bi_iter.bi_sector = blkno << sdp->sd_fsb2bb_shift;
|
||||||
bio_set_dev(bio, sb->s_bdev);
|
bio_set_dev(bio, sb->s_bdev);
|
||||||
bio->bi_end_io = end_io;
|
bio->bi_end_io = end_io;
|
||||||
bio->bi_private = sdp;
|
bio->bi_private = sdp;
|
||||||
|
@ -509,7 +509,7 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
|
||||||
unsigned int bsize = sdp->sd_sb.sb_bsize, off;
|
unsigned int bsize = sdp->sd_sb.sb_bsize, off;
|
||||||
unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
|
unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
|
||||||
unsigned int shift = PAGE_SHIFT - bsize_shift;
|
unsigned int shift = PAGE_SHIFT - bsize_shift;
|
||||||
unsigned int readahead_blocks = BIO_MAX_PAGES << shift;
|
unsigned int max_bio_size = 2 * 1024 * 1024;
|
||||||
struct gfs2_journal_extent *je;
|
struct gfs2_journal_extent *je;
|
||||||
int sz, ret = 0;
|
int sz, ret = 0;
|
||||||
struct bio *bio = NULL;
|
struct bio *bio = NULL;
|
||||||
|
@ -537,12 +537,17 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
|
||||||
off = 0;
|
off = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bio || (bio_chained && !off)) {
|
if (!bio || (bio_chained && !off) ||
|
||||||
|
bio->bi_iter.bi_size >= max_bio_size) {
|
||||||
/* start new bio */
|
/* start new bio */
|
||||||
} else {
|
} else {
|
||||||
|
sector_t sector = dblock << sdp->sd_fsb2bb_shift;
|
||||||
|
|
||||||
|
if (bio_end_sector(bio) == sector) {
|
||||||
sz = bio_add_page(bio, page, bsize, off);
|
sz = bio_add_page(bio, page, bsize, off);
|
||||||
if (sz == bsize)
|
if (sz == bsize)
|
||||||
goto block_added;
|
goto block_added;
|
||||||
|
}
|
||||||
if (off) {
|
if (off) {
|
||||||
unsigned int blocks =
|
unsigned int blocks =
|
||||||
(PAGE_SIZE - off) >> bsize_shift;
|
(PAGE_SIZE - off) >> bsize_shift;
|
||||||
|
@ -568,7 +573,7 @@ block_added:
|
||||||
off += bsize;
|
off += bsize;
|
||||||
if (off == PAGE_SIZE)
|
if (off == PAGE_SIZE)
|
||||||
page = NULL;
|
page = NULL;
|
||||||
if (blocks_submitted < blocks_read + readahead_blocks) {
|
if (blocks_submitted < 2 * max_bio_size >> bsize_shift) {
|
||||||
/* Keep at least one bio in flight */
|
/* Keep at least one bio in flight */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче