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

brd: implement discard support

The ramdisk memory utilization can only go up when data is written to
new pages. Implement discard to provide the possibility to reduce memory
usage for pages no longer in use. Aligned discards will free the
associated pages, if any, and determinisitically return zeroed data
until written again.

Signed-off-by: Keith Busch <kbusch@kernel.org>
Link: https://lore.kernel.org/r/20240429102308.147627-1-kbusch@meta.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Keith Busch and committed by
Jens Axboe
9ead7efc 25260555

+26
+26
drivers/block/brd.c
··· 222 222 return err; 223 223 } 224 224 225 + static void brd_do_discard(struct brd_device *brd, sector_t sector, u32 size) 226 + { 227 + sector_t aligned_sector = (sector + PAGE_SECTORS) & ~PAGE_SECTORS; 228 + struct page *page; 229 + 230 + size -= (aligned_sector - sector) * SECTOR_SIZE; 231 + xa_lock(&brd->brd_pages); 232 + while (size >= PAGE_SIZE && aligned_sector < rd_size * 2) { 233 + page = __xa_erase(&brd->brd_pages, aligned_sector >> PAGE_SECTORS_SHIFT); 234 + if (page) 235 + __free_page(page); 236 + aligned_sector += PAGE_SECTORS; 237 + size -= PAGE_SIZE; 238 + } 239 + xa_unlock(&brd->brd_pages); 240 + } 241 + 225 242 static void brd_submit_bio(struct bio *bio) 226 243 { 227 244 struct brd_device *brd = bio->bi_bdev->bd_disk->private_data; 228 245 sector_t sector = bio->bi_iter.bi_sector; 229 246 struct bio_vec bvec; 230 247 struct bvec_iter iter; 248 + 249 + if (unlikely(op_is_discard(bio->bi_opf))) { 250 + brd_do_discard(brd, sector, bio->bi_iter.bi_size); 251 + bio_endio(bio); 252 + return; 253 + } 231 254 232 255 bio_for_each_segment(bvec, bio, iter) { 233 256 unsigned int len = bvec.bv_len; ··· 332 309 * is harmless) 333 310 */ 334 311 .physical_block_size = PAGE_SIZE, 312 + .max_hw_discard_sectors = UINT_MAX, 313 + .max_discard_segments = 1, 314 + .discard_granularity = PAGE_SIZE, 335 315 }; 336 316 337 317 list_for_each_entry(brd, &brd_devices, brd_list)