aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/zram
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2014-04-07 18:38:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-07 19:36:02 -0400
commitf4659d8e620d08bd1a84a8aec5d2f5294a242764 (patch)
tree28490e0ad7668095e600abec488397c78cf00782 /drivers/block/zram
parent56b4e8cb85827a2ccc4752a2a7148e56b62b7e96 (diff)
zram: support REQ_DISCARD
zram is ram based block device and can be used by backend of filesystem. When filesystem deletes a file, it normally doesn't do anything on data block of that file. It just marks on metadata of that file. This behavior has no problem on disk based block device, but has problems on ram based block device, since we can't free memory used for data block. To overcome this disadvantage, there is REQ_DISCARD functionality. If block device support REQ_DISCARD and filesystem is mounted with discard option, filesystem sends REQ_DISCARD to block device whenever some data blocks are discarded. All we have to do is to handle this request. This patch implements to flag up QUEUE_FLAG_DISCARD and handle this REQ_DISCARD request. With it, we can free memory used by zram if it isn't used. [akpm@linux-foundation.org: tweak comments] Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Minchan Kim <minchan@kernel.org> Cc: Nitin Gupta <ngupta@vflare.org> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Jerome Marchand <jmarchan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block/zram')
-rw-r--r--drivers/block/zram/zram_drv.c62
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 */
559static 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
554static void zram_reset_device(struct zram *zram, bool reset_capacity) 595static 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