From patchwork Sat Feb 7 15:03:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 5796221 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8A81FBF440 for ; Sat, 7 Feb 2015 15:04:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A62D72012B for ; Sat, 7 Feb 2015 15:04:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A81B520125 for ; Sat, 7 Feb 2015 15:04:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755708AbbBGPEE (ORCPT ); Sat, 7 Feb 2015 10:04:04 -0500 Received: from mail-pa0-f44.google.com ([209.85.220.44]:43634 "EHLO mail-pa0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754638AbbBGPED (ORCPT ); Sat, 7 Feb 2015 10:04:03 -0500 Received: by mail-pa0-f44.google.com with SMTP id rd3so23675412pab.3; Sat, 07 Feb 2015 07:04:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=RxcIcqAz3bmMR5gnmSt2+89c6/HB9IU96RNPw6TxR98=; b=DWbynkS2guOYMaKMkdGt3KlMVNmELg+HQSbAId4WuDR98xMp0TCPIpmeWHOzxbMwZ9 fTsql0G4IkOIY+2OUPQ3lLIND0DKR5O31X9r1EO4cm39tUj3J3ETnTO18ZlIZW6BFFwr sBz+wSQ6vWOI70TmBUL+s1vsfpJxbjO4Ip3LUuKAgZJm5NkIiaDXAwSlA728Pq30RsPX z7qsMBnmLOe0Z39cXFxfaXupQJRprFHE5BcOOlFtQvuzgfKrgKB2MdX9UrVY7Hrx/8Jr I1N7q97MMUsFdM2PW7UPR/CbhaG1NozJNkw42n5Z51RG5FLlj53UIN8muiodhvgcpHWH j1vQ== X-Received: by 10.68.211.7 with SMTP id my7mr14385314pbc.115.1423321441825; Sat, 07 Feb 2015 07:04:01 -0800 (PST) Received: from localhost.localdomain (KD106168100169.ppp-bb.dion.ne.jp. [106.168.100.169]) by mx.google.com with ESMTPSA id km4sm8039209pdb.16.2015.02.07.07.03.58 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 07 Feb 2015 07:04:00 -0800 (PST) From: Akinobu Mita To: linux-kernel@vger.kernel.org Cc: Akinobu Mita , Nick Piggin , Jens Axboe , Andrew Morton , linux-fsdevel@vger.kernel.org Subject: [PATCH] brd: detect zero writes for saving ram Date: Sun, 8 Feb 2015 00:03:44 +0900 Message-Id: <1423321424-9657-1-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 1.9.1 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Signed-off-by: Akinobu Mita Cc: Nick Piggin Cc: Jens Axboe Cc: Andrew Morton Cc: linux-fsdevel@vger.kernel.org --- drivers/block/brd.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 3598110..82e4328 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -293,6 +293,42 @@ 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); + 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 +340,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 +478,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");