From patchwork Wed Jan 6 22:31:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 7971571 Return-Path: X-Original-To: patchwork-linux-nvdimm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C5A109F38D for ; Wed, 6 Jan 2016 22:31:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C33BD2015E for ; Wed, 6 Jan 2016 22:31:56 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B95DF20154 for ; Wed, 6 Jan 2016 22:31:55 +0000 (UTC) Received: from ml01.vlan14.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id AE8091A2231; Wed, 6 Jan 2016 14:31:55 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by ml01.01.org (Postfix) with ESMTP id C142D1A2231 for ; Wed, 6 Jan 2016 14:31:54 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga104.fm.intel.com with ESMTP; 06 Jan 2016 14:31:54 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,530,1444719600"; d="scan'208";a="875979630" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.54.39.136]) by fmsmga001.fm.intel.com with ESMTP; 06 Jan 2016 14:31:54 -0800 Subject: [PATCH v2 7/9] libnvdimm, pmem: prepare for handling badblocks via nvdimm_read_bytes() From: Dan Williams To: linux-nvdimm@lists.01.org Date: Wed, 06 Jan 2016 14:31:28 -0800 Message-ID: <20160106223128.2736.40342.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <20160106223051.2736.43057.stgit@dwillia2-desk3.amr.corp.intel.com> References: <20160106223051.2736.43057.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 Cc: linux-block@vger.kernel.org X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, 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 When performing reads through the nvdimm_read_bytes() interface we still want to consult the badblocks list, but we do not have access to a gendisk in that path. Convert the badblocks list to be a generic attribute of a namespace. Signed-off-by: Dan Williams --- drivers/nvdimm/core.c | 44 +++++++++++++++++++++++++++----------------- drivers/nvdimm/nd.h | 4 ++-- drivers/nvdimm/pmem.c | 13 +++++++++---- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 5541612bb449..63b7386b7299 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -411,32 +411,41 @@ static int __add_badblock_range(struct device *dev, struct badblocks **bb, } /** - * nvdimm_namespace_add_poison() - Convert a list of poison ranges to badblocks - * @disk: the gendisk associated with the namespace where badblocks - * will be stored + * nvdimm_namespace_badblocks() - Convert a list of poison ranges to badblocks + * @ndns: namespace hosting potential badblocks * @offset: offset at the start of the namespace before 'sector 0' - * @ndns: the namespace containing poison ranges * - * The poison list generated during NFIT initialization may contain multiple, - * possibly overlapping ranges in the SPA (System Physical Address) space. - * Compare each of these ranges to the namespace currently being initialized, - * and add badblocks to the gendisk for all matching sub-ranges + * The poison list generated during NFIT initialization may contain + * multiple, possibly overlapping ranges in the SPA (System Physical + * Address) space. Compare each of these ranges to the namespace + * currently being initialized, and add badblocks for all matching + * sub-ranges * * Return: - * 0 - Success + * valid badblocks instance on success + * ERR_PTR(-ENOENT) on no badblocks present + * ERR_PTR(-) on failure */ -int nvdimm_namespace_add_poison(struct gendisk *disk, resource_size_t offset, - struct nd_namespace_common *ndns) +struct badblocks *nvdimm_namespace_badblocks(struct nd_namespace_common *ndns, + resource_size_t offset) { - struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); struct nd_region *nd_region = to_nd_region(ndns->dev.parent); struct nvdimm_bus *nvdimm_bus; struct list_head *poison_list; u64 ns_start, ns_end, ns_size; + struct nd_namespace_io *nsio; struct badblocks *bb = NULL; struct nd_poison *pl; int rc; + /* + * For now, the addresses retrieved from an nvdimm bus are + * communicated in terms of system physical address not a dimm + * address (dpa). This implies pmem only. + */ + if (!is_nd_pmem(&nd_region->dev)) + return ERR_PTR(-ENOENT); + nsio = to_nd_namespace_io(&ndns->dev); ns_size = nvdimm_namespace_capacity(ndns) - offset; ns_start = nsio->res.start + offset; ns_end = nsio->res.end; @@ -444,7 +453,7 @@ int nvdimm_namespace_add_poison(struct gendisk *disk, resource_size_t offset, nvdimm_bus = to_nvdimm_bus(nd_region->dev.parent); poison_list = &nvdimm_bus->poison_list; if (list_empty(poison_list)) - return 0; + return ERR_PTR(-ENOENT); list_for_each_entry(pl, poison_list, list) { u64 pl_end = pl->start + pl->length - 1; @@ -467,7 +476,7 @@ int nvdimm_namespace_add_poison(struct gendisk *disk, resource_size_t offset, rc = __add_badblock_range(&ndns->dev, &bb, start - ns_start, len); if (rc) - return rc; + return ERR_PTR(rc); dev_info(&nvdimm_bus->dev, "Found a poison range (0x%llx, 0x%llx)\n", start, len); @@ -484,16 +493,17 @@ int nvdimm_namespace_add_poison(struct gendisk *disk, resource_size_t offset, rc = __add_badblock_range(&ndns->dev, &bb, 0, len); if (rc) - return rc; + return ERR_PTR(rc); dev_info(&nvdimm_bus->dev, "Found a poison range (0x%llx, 0x%llx)\n", pl->start, len); } } - return 0; + WARN_ON(!bb); + return bb; } -EXPORT_SYMBOL_GPL(nvdimm_namespace_add_poison); +EXPORT_SYMBOL_GPL(nvdimm_namespace_badblocks); static int __add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) { diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 198933da83e5..65f1031f2bf9 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -268,8 +268,8 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns); int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns); const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, char *name); -int nvdimm_namespace_add_poison(struct gendisk *disk, resource_size_t offset, - struct nd_namespace_common *ndns); +struct badblocks *nvdimm_namespace_badblocks(struct nd_namespace_common *ndns, + resource_size_t offset); int nd_blk_region_init(struct nd_region *nd_region); void __nd_iostat_start(struct bio *bio, unsigned long *start); static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index bbe81b7fe031..eb2b1dc14335 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -192,8 +192,8 @@ static int pmem_attach_disk(struct device *dev, struct nd_namespace_common *ndns, struct pmem_device *pmem) { int nid = dev_to_node(dev); + struct badblocks *bb; struct gendisk *disk; - int ret; pmem->pmem_queue = blk_alloc_queue_node(GFP_KERNEL, nid); if (!pmem->pmem_queue) @@ -222,10 +222,15 @@ static int pmem_attach_disk(struct device *dev, set_capacity(disk, (pmem->size - pmem->data_offset) / 512); pmem->pmem_disk = disk; - ret = nvdimm_namespace_add_poison(disk, pmem->data_offset, ndns); - if (ret) - return ret; + bb = nvdimm_namespace_badblocks(ndns, pmem->data_offset); + if (IS_ERR(bb)) { + if (PTR_ERR(bb) == -ENOENT) + bb = NULL; + else + return PTR_ERR(bb); + } + disk->bb = bb; add_disk(disk); revalidate_disk(disk);