Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xfs: fix number of GC bvecs

GC scratch allocations can wrap around and use the same buffer twice, and
the current code fails to account for that. So far this worked due to
rounding in the block layer, but changes to the bio allocator drop the
over-provisioning and generic/256 or generic/361 will now usually fail
when running against the current block tree.

Simplify the allocation to always pass the maximum value that is easier to
verify, as a saving of up to one bvec per allocation isn't worth the
effort to verify a complicated calculated value.

Fixes: 102f444b57b3 ("xfs: rework zone GC buffer management")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
Link: https://patch.msgid.link/20260407140538.633364-2-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
452c8f6c affb5f67

+10 -9
+10 -9
fs/xfs/xfs_zone_gc.c
··· 671 671 struct xfs_inode *ip; 672 672 struct bio *bio; 673 673 xfs_daddr_t daddr; 674 - unsigned int len; 675 674 bool is_seq; 676 675 677 676 if (xfs_is_shutdown(mp)) ··· 685 686 return false; 686 687 } 687 688 688 - len = XFS_FSB_TO_B(mp, irec.rm_blockcount); 689 - bio = bio_alloc_bioset(bdev, 690 - min(howmany(len, XFS_GC_BUF_SIZE) + 1, XFS_GC_NR_BUFS), 691 - REQ_OP_READ, GFP_NOFS, &data->bio_set); 692 - 689 + /* 690 + * Scratch allocation can wrap around to the same buffer again, 691 + * provision an extra bvec for that case. 692 + */ 693 + bio = bio_alloc_bioset(bdev, XFS_GC_NR_BUFS + 1, REQ_OP_READ, GFP_NOFS, 694 + &data->bio_set); 693 695 chunk = container_of(bio, struct xfs_gc_bio, bio); 694 696 chunk->ip = ip; 695 697 chunk->offset = XFS_FSB_TO_B(mp, irec.rm_offset); 696 - chunk->len = len; 698 + chunk->len = XFS_FSB_TO_B(mp, irec.rm_blockcount); 697 699 chunk->old_startblock = 698 700 xfs_rgbno_to_rtb(iter->victim_rtg, irec.rm_startblock); 699 701 chunk->new_daddr = daddr; ··· 708 708 bio->bi_iter.bi_sector = xfs_rtb_to_daddr(mp, chunk->old_startblock); 709 709 bio->bi_end_io = xfs_zone_gc_end_io; 710 710 xfs_zone_gc_add_data(chunk); 711 - data->scratch_head = (data->scratch_head + len) % data->scratch_size; 712 - data->scratch_available -= len; 711 + data->scratch_head = 712 + (data->scratch_head + chunk->len) % data->scratch_size; 713 + data->scratch_available -= chunk->len; 713 714 714 715 XFS_STATS_INC(mp, xs_gc_read_calls); 715 716