diff options
Diffstat (limited to 'drivers/block/zram')
-rw-r--r-- | drivers/block/zram/zram_drv.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 15e7b8e64cbb..9849b5233bf4 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c | |||
@@ -551,6 +551,47 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
551 | return ret; | 551 | return ret; |
552 | } | 552 | } |
553 | 553 | ||
554 | /* | ||
555 | * zram_bio_discard - handler on discard request | ||
556 | * @index: physical block index in PAGE_SIZE units | ||
557 | * @offset: byte offset within physical block | ||
558 | */ | ||
559 | static void zram_bio_discard(struct zram *zram, u32 index, | ||
560 | int offset, struct bio *bio) | ||
561 | { | ||
562 | size_t n = bio->bi_iter.bi_size; | ||
563 | |||
564 | /* | ||
565 | * zram manages data in physical block size units. Because logical block | ||
566 | * size isn't identical with physical block size on some arch, we | ||
567 | * could get a discard request pointing to a specific offset within a | ||
568 | * certain physical block. Although we can handle this request by | ||
569 | * reading that physiclal block and decompressing and partially zeroing | ||
570 | * and re-compressing and then re-storing it, this isn't reasonable | ||
571 | * because our intent with a discard request is to save memory. So | ||
572 | * skipping this logical block is appropriate here. | ||
573 | */ | ||
574 | if (offset) { | ||
575 | if (n < offset) | ||
576 | return; | ||
577 | |||
578 | n -= offset; | ||
579 | index++; | ||
580 | } | ||
581 | |||
582 | while (n >= PAGE_SIZE) { | ||
583 | /* | ||
584 | * Discard request can be large so the lock hold times could be | ||
585 | * lengthy. So take the lock once per page. | ||
586 | */ | ||
587 | write_lock(&zram->meta->tb_lock); | ||
588 | zram_free_page(zram, index); | ||
589 | write_unlock(&zram->meta->tb_lock); | ||
590 | index++; | ||
591 | n -= PAGE_SIZE; | ||
592 | } | ||
593 | } | ||
594 | |||
554 | static void zram_reset_device(struct zram *zram, bool reset_capacity) | 595 | static void zram_reset_device(struct zram *zram, bool reset_capacity) |
555 | { | 596 | { |
556 | size_t index; | 597 | size_t index; |
@@ -686,6 +727,12 @@ static void __zram_make_request(struct zram *zram, struct bio *bio) | |||
686 | offset = (bio->bi_iter.bi_sector & | 727 | offset = (bio->bi_iter.bi_sector & |
687 | (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; | 728 | (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; |
688 | 729 | ||
730 | if (unlikely(bio->bi_rw & REQ_DISCARD)) { | ||
731 | zram_bio_discard(zram, index, offset, bio); | ||
732 | bio_endio(bio, 0); | ||
733 | return; | ||
734 | } | ||
735 | |||
689 | bio_for_each_segment(bvec, bio, iter) { | 736 | bio_for_each_segment(bvec, bio, iter) { |
690 | int max_transfer_size = PAGE_SIZE - offset; | 737 | int max_transfer_size = PAGE_SIZE - offset; |
691 | 738 | ||
@@ -855,6 +902,21 @@ static int create_device(struct zram *zram, int device_id) | |||
855 | ZRAM_LOGICAL_BLOCK_SIZE); | 902 | ZRAM_LOGICAL_BLOCK_SIZE); |
856 | blk_queue_io_min(zram->disk->queue, PAGE_SIZE); | 903 | blk_queue_io_min(zram->disk->queue, PAGE_SIZE); |
857 | blk_queue_io_opt(zram->disk->queue, PAGE_SIZE); | 904 | blk_queue_io_opt(zram->disk->queue, PAGE_SIZE); |
905 | zram->disk->queue->limits.discard_granularity = PAGE_SIZE; | ||
906 | zram->disk->queue->limits.max_discard_sectors = UINT_MAX; | ||
907 | /* | ||
908 | * zram_bio_discard() will clear all logical blocks if logical block | ||
909 | * size is identical with physical block size(PAGE_SIZE). But if it is | ||
910 | * different, we will skip discarding some parts of logical blocks in | ||
911 | * the part of the request range which isn't aligned to physical block | ||
912 | * size. So we can't ensure that all discarded logical blocks are | ||
913 | * zeroed. | ||
914 | */ | ||
915 | if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE) | ||
916 | zram->disk->queue->limits.discard_zeroes_data = 1; | ||
917 | else | ||
918 | zram->disk->queue->limits.discard_zeroes_data = 0; | ||
919 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zram->disk->queue); | ||
858 | 920 | ||
859 | add_disk(zram->disk); | 921 | add_disk(zram->disk); |
860 | 922 | ||