From: Akinobu Mita <akinobu.mita@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Akinobu Mita <akinobu.mita@gmail.com>,
Jens Axboe <axboe@kernel.dk>,
Andrew Morton <akpm@linux-foundation.org>,
linux-fsdevel@vger.kernel.org
Subject: [PATCH v2] brd: detect zero writes for saving ram
Date: Mon, 9 Feb 2015 22:51:55 +0900 [thread overview]
Message-ID: <1423489915-3013-1-git-send-email-akinobu.mita@gmail.com> (raw)
This introduces a module parameter to detect zero writes and not to
allocate memory. Read requests for unallocated (unwritten) region
end up by reading zero. So this can save zeroed memory consumption
with extra overhead for the detection.
This feature is useful for testing filesystems and user programs to
huge files without huge real storage. So this change also extends
the upper limit on the size of the RAM disk.
The following commands demonstrate that creating about 16TB zero file
on ext4 without huge memory installed.
# modprobe brd zero_detect=1 rd_size=$((16*1024*1024*1024))
# mkfs.ext4 /dev/ram0
# mount /dev/ram0 /mnt/
# dd if=/dev/zero of=/mnt/huge-zero-file bs=1M oflag=direct
Someone might think that we can use zram instead, but zram requires to
allocate contiguous memory region proportional to the size of the disk
((disksize >> PAGE_SHIFT) * sizeof(struct zram_table_entry)).
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-fsdevel@vger.kernel.org
---
* Changes from v1
- add missing flush_dcache_page() before memchr_inv()
- update commit message
drivers/block/brd.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 3598110..7c1c7a7 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -293,6 +293,43 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
}
}
+static bool page_is_zero(struct page *page, unsigned int len, unsigned int off)
+{
+ bool is_zero;
+ void *mem;
+
+ mem = kmap_atomic(page);
+ flush_dcache_page(page);
+ is_zero = !memchr_inv(mem + off, 0, len);
+ kunmap_atomic(mem);
+
+ return is_zero;
+}
+
+static bool zero_detect;
+
+static bool brd_zero_detect(struct brd_device *brd, struct page *page,
+ unsigned int len, unsigned int off, sector_t sector)
+{
+ sector_t end_sector;
+
+ if (!zero_detect)
+ return false;
+ if (!page_is_zero(page, len, off))
+ return false;
+
+ if (brd_lookup_page(brd, sector))
+ return false;
+
+ end_sector = sector + (len >> SECTOR_SHIFT) - 1;
+ if (sector >> PAGE_SECTORS_SHIFT != end_sector >> PAGE_SECTORS_SHIFT) {
+ if (brd_lookup_page(brd, end_sector))
+ return false;
+ }
+
+ return true;
+}
+
/*
* Process a single bvec of a bio.
*/
@@ -304,6 +341,9 @@ static int brd_do_bvec(struct brd_device *brd, struct page *page,
int err = 0;
if (rw != READ) {
+ if (brd_zero_detect(brd, page, len, off, sector))
+ return 0;
+
err = copy_to_brd_setup(brd, sector, len);
if (err)
goto out;
@@ -439,18 +479,20 @@ static const struct block_device_operations brd_fops = {
* And now the modules code and kernel interface.
*/
static int rd_nr;
-int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
+unsigned long long rd_size = CONFIG_BLK_DEV_RAM_SIZE;
static int max_part;
static int part_shift;
static int part_show = 0;
module_param(rd_nr, int, S_IRUGO);
MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
-module_param(rd_size, int, S_IRUGO);
+module_param(rd_size, ullong, S_IRUGO);
MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
module_param(max_part, int, S_IRUGO);
MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
module_param(part_show, int, S_IRUGO);
MODULE_PARM_DESC(part_show, "Control RAM disk visibility in /proc/partitions");
+module_param(zero_detect, bool, 0644);
+MODULE_PARM_DESC(zero_detect, "Detect zero writes for saving ram");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
MODULE_ALIAS("rd");
--
1.9.1
reply other threads:[~2015-02-09 13:51 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1423489915-3013-1-git-send-email-akinobu.mita@gmail.com \
--to=akinobu.mita@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=axboe@kernel.dk \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).