From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932481AbcA2PTP (ORCPT ); Fri, 29 Jan 2016 10:19:15 -0500 Received: from mga09.intel.com ([134.134.136.24]:37915 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932272AbcA2PTL (ORCPT ); Fri, 29 Jan 2016 10:19:11 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,364,1449561600"; d="scan'208";a="871772372" Subject: [PATCH 2/2] block: use DAX for partition table reads From: Dan Williams To: linux-block@vger.kernel.org Cc: linux-nvdimm@ml01.01.org, Dave Chinner , linux-kernel@vger.kernel.org, Christoph Hellwig , axboe@fb.com, Jeff Moyer , Jan Kara , linux-fsdevel@vger.kernel.org, Matthew Wilcox , Andrew Morton , Ross Zwisler Date: Fri, 29 Jan 2016 07:18:46 -0800 Message-ID: <20160129151846.18752.48460.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <20160129151835.18752.9423.stgit@dwillia2-desk3.amr.corp.intel.com> References: <20160129151835.18752.9423.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Avoid populating pagecache when the block device is in DAX mode. Otherwise these page cache entries collide with the fsync/msync implementation and break data durability guarantees. Cc: Jan Kara Cc: Jeff Moyer Cc: Christoph Hellwig Cc: Dave Chinner Cc: Matthew Wilcox Cc: Andrew Morton Reported-by: Ross Zwisler Signed-off-by: Dan Williams --- block/partition-generic.c | 18 +++++++++++++++--- fs/dax.c | 20 ++++++++++++++++++++ include/linux/blkdev.h | 10 ++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/block/partition-generic.c b/block/partition-generic.c index 746935a5973c..8e6fa1868249 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "partitions/check.h" @@ -550,13 +551,24 @@ int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) return 0; } -unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) +static struct page *read_pagecache_sector(struct block_device *bdev, sector_t n) { struct address_space *mapping = bdev->bd_inode->i_mapping; + + return read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), + NULL); +} + +unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) +{ struct page *page; - page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), - NULL); + /* don't populate page cache for dax capable devices */ + if (IS_DAX(bdev->bd_inode)) + page = read_dax_sector(bdev, n); + else + page = read_pagecache_sector(bdev, n); + if (!IS_ERR(page)) { if (PageError(page)) goto fail; diff --git a/fs/dax.c b/fs/dax.c index 4fd6b0c5c6b5..227974adecb9 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -58,6 +58,26 @@ static void dax_unmap_atomic(struct block_device *bdev, blk_queue_exit(bdev->bd_queue); } +struct page *read_dax_sector(struct block_device *bdev, sector_t n) +{ + struct page *page = __page_cache_alloc(GFP_KERNEL | __GFP_COLD); + struct blk_dax_ctl dax = { + .size = PAGE_SIZE, + .sector = n & ~((((int) PAGE_SIZE) / 512) - 1), + }; + long rc; + + if (!page) + return ERR_PTR(-ENOMEM); + + rc = dax_map_atomic(bdev, &dax); + if (rc < 0) + return ERR_PTR(rc); + memcpy_from_pmem(page_address(page), dax.addr, PAGE_SIZE); + dax_unmap_atomic(bdev, &dax); + return page; +} + /* * dax_clear_blocks() is called from within transaction context from XFS, * and hence this means the stack from this point must follow GFP_NOFS diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 29189aeace19..b1452c04f1a9 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1633,6 +1633,16 @@ struct blk_dax_ctl { pfn_t pfn; }; +#ifdef CONFIG_FS_DAX +struct page *read_dax_sector(struct block_device *bdev, sector_t n); +#else +static inline struct page *read_dax_sector(struct block_device *bdev, + sector_t n) +{ + return ERR_PTR(-ENXIO); +} +#endif + struct block_device_operations { int (*open) (struct block_device *, fmode_t); void (*release) (struct gendisk *, fmode_t);