Message ID | alpine.LRH.2.02.2209160500190.543@file01.intranet.prod.int.rdu2.redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | brd: implement discard | expand |
On Fri, Sep 16, 2022 at 05:00:46AM -0400, Mikulas Patocka wrote: > This patch implements REQ_OP_SECURE_ERASE and 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. Secure erase is just like write zeroes, > except that it clears the page content before freeing the page. What is the use case of this? And just a single overwrite is not what storage standards would consider a secure erase, but then again we don't really have any documentation or standards for the Linux OP, which strongly suggests not actually implementing it for now.
On Tue, 20 Sep 2022, Christoph Hellwig wrote: > On Fri, Sep 16, 2022 at 05:00:46AM -0400, Mikulas Patocka wrote: > > This patch implements REQ_OP_SECURE_ERASE and 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. Secure erase is just like write zeroes, > > except that it clears the page content before freeing the page. > > What is the use case of this? And just a single overwrite is not what > storage standards would consider a secure erase, but then again we > don't really have any documentation or standards for the Linux OP, > which strongly suggests not actually implementing it for now. Without support for REQ_OP_WRITE_ZEROES, "blkdiscard -z" actually overwrites the ramdisk with zeroes and allocates all the blocks. Allocating all the blocks is pointless if we want to clear them. I implemented REQ_OP_SECURE_ERASE just because it is similar to REQ_OP_WRITE_ZEROES. Unlike disks, DRAM has no memory of previous content, so a single overwrite should be OK. We could also flush cache in REQ_OP_SECURE_ERASE, but I don't know if Linux has any portable function that does it. Mikulas
Index: linux-2.6/drivers/block/brd.c =================================================================== --- linux-2.6.orig/drivers/block/brd.c +++ linux-2.6/drivers/block/brd.c @@ -118,7 +118,7 @@ static void brd_free_page_rcu(struct rcu __free_page(page); } -static void brd_free_page(struct brd_device *brd, sector_t sector) +static void brd_free_page(struct brd_device *brd, sector_t sector, bool secure) { struct page *page; pgoff_t idx; @@ -127,8 +127,11 @@ static void brd_free_page(struct brd_dev idx = sector >> PAGE_SECTORS_SHIFT; page = radix_tree_delete(&brd->brd_pages, idx); spin_unlock(&brd->brd_lock); - if (page) + if (page) { + if (secure) + clear_highpage(page); call_rcu(&page->rcu_head, brd_free_page_rcu); + } } /* @@ -308,16 +311,29 @@ static void brd_submit_bio(struct bio *b struct bio_vec bvec; struct bvec_iter iter; - if (bio_op(bio) == REQ_OP_DISCARD) { + if (bio_op(bio) == REQ_OP_DISCARD || + bio_op(bio) == REQ_OP_SECURE_ERASE || + bio_op(bio) == REQ_OP_WRITE_ZEROES) { + bool zero_padding = bio_op(bio) == REQ_OP_SECURE_ERASE || bio_op(bio) == REQ_OP_WRITE_ZEROES; sector_t len = bio_sectors(bio); sector_t front_pad = -sector & (PAGE_SECTORS - 1); + sector_t end_pad; + + 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)) goto endio; 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); + brd_free_page(brd, sector, bio_op(bio) == REQ_OP_SECURE_ERASE); sector += PAGE_SECTORS; len -= PAGE_SECTORS; cond_resched(); @@ -448,6 +464,8 @@ static int brd_alloc(int i) disk->queue->limits.discard_granularity = PAGE_SIZE; blk_queue_max_discard_sectors(disk->queue, UINT_MAX); + blk_queue_max_write_zeroes_sectors(disk->queue, UINT_MAX); + blk_queue_max_secure_erase_sectors(disk->queue, UINT_MAX); /* Tell the block layer that this is not a rotational device */ blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
This patch implements REQ_OP_SECURE_ERASE and 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. Secure erase is just like write zeroes, except that it clears the page content before freeing the page. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> --- drivers/block/brd.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-)