This patch implements REQ_OP_WRITE_ZEROES on brd. Write zeroes will free the pages just like discard, but the difference is that it writes zeroes to the preceding and following page if the range is not aligned on page boundary. Signed-off-by: Mikulas Patocka <mpatocka@xxxxxxxxxx> --- drivers/block/brd.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) Index: linux-2.6/drivers/block/brd.c =================================================================== --- linux-2.6.orig/drivers/block/brd.c +++ linux-2.6/drivers/block/brd.c @@ -301,7 +301,8 @@ out: void brd_do_discard(struct brd_device *brd, struct bio *bio) { struct free_page_batch *batch = NULL; - sector_t sector, len, front_pad; + bool zero_padding = bio_op(bio) == REQ_OP_WRITE_ZEROES; + sector_t sector, len, front_pad, end_pad; if (unlikely(!discard)) { bio->bi_status = BLK_STS_NOTSUPP; @@ -311,11 +312,22 @@ void brd_do_discard(struct brd_device *b sector = bio->bi_iter.bi_sector; len = bio_sectors(bio); front_pad = -sector & (PAGE_SECTORS - 1); + + if (zero_padding && unlikely(front_pad != 0)) + copy_to_brd(brd, page_address(ZERO_PAGE(0)), + sector, min(len, front_pad) << SECTOR_SHIFT); + sector += front_pad; if (unlikely(len <= front_pad)) return; len -= front_pad; - len = round_down(len, PAGE_SECTORS); + + end_pad = len & (PAGE_SECTORS - 1); + if (zero_padding && unlikely(end_pad != 0)) + copy_to_brd(brd, page_address(ZERO_PAGE(0)), + sector + len - end_pad, end_pad << SECTOR_SHIFT); + len -= end_pad; + while (len) { brd_free_page(brd, sector, &batch); sector += PAGE_SECTORS; @@ -359,6 +371,7 @@ static void brd_submit_bio(struct bio *b } break; case REQ_OP_DISCARD: + case REQ_OP_WRITE_ZEROES: brd_do_discard(brd, bio); break; default: @@ -383,9 +396,11 @@ static void brd_set_discard_limits(struc if (discard) { queue->limits.discard_granularity = PAGE_SIZE; blk_queue_max_discard_sectors(queue, round_down(UINT_MAX, PAGE_SECTORS)); + blk_queue_max_write_zeroes_sectors(queue, round_down(UINT_MAX, PAGE_SECTORS)); } else { queue->limits.discard_granularity = 0; blk_queue_max_discard_sectors(queue, 0); + blk_queue_max_write_zeroes_sectors(queue, 0); } } @@ -425,7 +440,7 @@ MODULE_PARM_DESC(max_part, "Num Minors t static bool discard = false; module_param_cb(discard, &discard_ops, &discard, 0644); -MODULE_PARM_DESC(discard, "Support discard"); +MODULE_PARM_DESC(discard, "Support discard and write zeroes"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);