Re: [PATCH] btrfs: Split remaining space to discard in chunks
From: David Sterba
Date: Mon Sep 02 2024 - 16:12:13 EST
On Mon, Sep 02, 2024 at 01:43:00PM +0200, Luca Stefani wrote:
> Per Qu Wenruo in case we have a very large disk, e.g. 8TiB device,
> mostly empty although we will do the split according to our super block
> locations, the last super block ends at 256G, we can submit a huge
> discard for the range [256G, 8T), causing a super large delay.
I'm not sure that this will be different than what we already do, or
have the large delays been observed in practice? The range passed to
blkdev_issue_discard() might be large but internally it's still split to
smaller sizes depending on the queue limits, IOW the device.
Bio is allocated and limited by bio_discard_limit(bdev, *sector);
https://elixir.bootlin.com/linux/v6.10.7/source/block/blk-lib.c#L38
struct bio *blk_alloc_discard_bio(struct block_device *bdev,
sector_t *sector, sector_t *nr_sects, gfp_t gfp_mask)
{
sector_t bio_sects = min(*nr_sects, bio_discard_limit(bdev, *sector));
struct bio *bio;
if (!bio_sects)
return NULL;
bio = bio_alloc(bdev, 0, REQ_OP_DISCARD, gfp_mask);
...
Then used in __blkdev_issue_discard()
https://elixir.bootlin.com/linux/v6.10.7/source/block/blk-lib.c#L63
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop)
{
struct bio *bio;
while ((bio = blk_alloc_discard_bio(bdev, §or, &nr_sects,
gfp_mask)))
*biop = bio_chain_and_submit(*biop, bio);
return 0;
}
This is basically just a loop, chopping the input range as needed. The
btrfs code does effectively the same, there's only the superblock,
progress accounting and error handling done.
As the maximum size of a single discard request depends on a device we
don't need to artificially limit it because this would require more IO
requests and can be slower.