From patchwork Thu Apr 30 22:15:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 6307521 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 AB3749F32B for ; Thu, 30 Apr 2015 22:18:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 94055201C0 for ; Thu, 30 Apr 2015 22:18:31 +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 5BF1E201BB for ; Thu, 30 Apr 2015 22:18:30 +0000 (UTC) Received: from ml01.vlan14.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 48935182854; Thu, 30 Apr 2015 15:18:30 -0700 (PDT) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by ml01.01.org (Postfix) with ESMTP id 1DE5F18284E for ; Thu, 30 Apr 2015 15:18:29 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP; 30 Apr 2015 15:18:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,679,1422950400"; d="scan'208";a="564561723" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.23.232.36]) by orsmga003.jf.intel.com with ESMTP; 30 Apr 2015 15:18:28 -0700 From: Dan Williams To: linux-nvdimm@lists.01.org Date: Thu, 30 Apr 2015 18:15:48 -0400 Message-ID: <20150430221144.26376.30479.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-8-g92dd MIME-Version: 1.0 Cc: hch@infradead.org, Christoph Hellwig Subject: [Linux-nvdimm] [PATCH] libnd: stable(ish) block device names X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.15 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, 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 >From Toshi: We have seen a case that the region#->pmem# binding becomes inconsistent across a reboot when there are 8 NVDIMM cards (reported by Robert Elliott). This leads user to access a wrong device. While it is a bug for userspace to depend on stable device names from boot-to-boot, we should try not to give random results in the case where the configuration has not changed. Now that PMEM only ever attaches to 'region' devices emitted by libnd, we can simply carry the region-id all the way down to the pmem device name. Since BLK-regions allow multiple namespaces per-region we need to carry the . in the block device name if we want stable(ish) device names. Cc: Christoph Hellwig Cc: Ross Zwisler Reported-by: Toshi Kani Reported-by: Robert Elliott Signed-off-by: Dan Williams --- Will fold this into the v3 posting. v3 will be a rebase on top of the upcoming ACPICA NFIT enabling. drivers/block/nd/blk.c | 14 ++------------ drivers/block/nd/pmem.c | 21 +++++---------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/drivers/block/nd/blk.c b/drivers/block/nd/blk.c index 8536ee8b2009..9a2b93bdeccc 100644 --- a/drivers/block/nd/blk.c +++ b/drivers/block/nd/blk.c @@ -28,11 +28,9 @@ struct nd_blk_device { struct nd_blk_region *ndbr; struct nd_io ndio; size_t disk_size; - int id; }; static int nd_blk_major; -static DEFINE_IDA(nd_blk_ida); static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, resource_size_t ns_offset, unsigned int len) @@ -139,6 +137,7 @@ static const struct block_device_operations nd_blk_fops = { static int nd_blk_probe(struct device *dev) { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); + struct nd_region *nd_region = to_nd_region(dev->parent); struct nd_blk_device *blk_dev; resource_size_t disk_size; struct gendisk *disk; @@ -152,12 +151,6 @@ static int nd_blk_probe(struct device *dev) if (!blk_dev) return -ENOMEM; - blk_dev->id = ida_simple_get(&nd_blk_ida, 0, 0, GFP_KERNEL); - if (blk_dev->id < 0) { - err = blk_dev->id; - goto err_ida; - } - blk_dev->disk_size = disk_size; blk_dev->queue = blk_alloc_queue(GFP_KERNEL); @@ -186,7 +179,7 @@ static int nd_blk_probe(struct device *dev) disk->private_data = blk_dev; disk->queue = blk_dev->queue; disk->flags = GENHD_FL_EXT_DEVT; - sprintf(disk->disk_name, "ndblk%d", blk_dev->id); + sprintf(disk->disk_name, "ndblk%d.%d", nd_region->id, nsblk->id); set_capacity(disk, disk_size >> SECTOR_SHIFT); nd_bus_lock(dev); @@ -202,8 +195,6 @@ static int nd_blk_probe(struct device *dev) err_alloc_disk: blk_cleanup_queue(blk_dev->queue); err_alloc_queue: - ida_simple_remove(&nd_blk_ida, blk_dev->id); - err_ida: kfree(blk_dev); return err; } @@ -219,7 +210,6 @@ static int nd_blk_remove(struct device *dev) del_gendisk(blk_dev->disk); put_disk(blk_dev->disk); blk_cleanup_queue(blk_dev->queue); - ida_simple_remove(&nd_blk_ida, blk_dev->id); kfree(blk_dev); return 0; diff --git a/drivers/block/nd/pmem.c b/drivers/block/nd/pmem.c index 900dad61a6b9..5814c8aed481 100644 --- a/drivers/block/nd/pmem.c +++ b/drivers/block/nd/pmem.c @@ -37,11 +37,9 @@ struct pmem_device { phys_addr_t phys_addr; void *virt_addr; size_t size; - int id; }; static int pmem_major; -static DEFINE_IDA(pmem_ida); static void pmem_do_bvec(struct pmem_device *pmem, struct page *page, unsigned int len, unsigned int off, int rw, @@ -142,7 +140,7 @@ static const struct block_device_operations pmem_fops = { .direct_access = pmem_direct_access, }; -static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res) +static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res, int id) { struct pmem_device *pmem; struct gendisk *disk; @@ -153,19 +151,13 @@ static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res) if (!pmem) goto out; - pmem->id = ida_simple_get(&pmem_ida, 0, 0, GFP_KERNEL); - if (pmem->id < 0) { - err = pmem->id; - goto out_free_dev; - } - pmem->phys_addr = res->start; pmem->size = resource_size(res); err = -EINVAL; if (!request_mem_region(pmem->phys_addr, pmem->size, "pmem")) { dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n", &pmem->phys_addr, pmem->size); - goto out_free_ida; + goto out_free_dev; } /* @@ -190,12 +182,12 @@ static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res) goto out_free_queue; disk->major = pmem_major; - disk->first_minor = PMEM_MINORS * pmem->id; + disk->first_minor = PMEM_MINORS * id; disk->fops = &pmem_fops; disk->private_data = pmem; disk->queue = pmem->pmem_queue; disk->flags = GENHD_FL_EXT_DEVT; - sprintf(disk->disk_name, "pmem%d", pmem->id); + sprintf(disk->disk_name, "pmem%d", id); disk->driverfs_dev = dev; set_capacity(disk, pmem->size >> 9); pmem->pmem_disk = disk; @@ -208,8 +200,6 @@ out_unmap: iounmap(pmem->virt_addr); out_release_region: release_mem_region(pmem->phys_addr, pmem->size); -out_free_ida: - ida_simple_remove(&pmem_ida, pmem->id); out_free_dev: kfree(pmem); out: @@ -223,7 +213,6 @@ static void pmem_free(struct pmem_device *pmem) blk_cleanup_queue(pmem->pmem_queue); iounmap(pmem->virt_addr); release_mem_region(pmem->phys_addr, pmem->size); - ida_simple_remove(&pmem_ida, pmem->id); kfree(pmem); } @@ -250,7 +239,7 @@ static int nd_pmem_probe(struct device *dev) } } - pmem = pmem_alloc(dev, &nsio->res); + pmem = pmem_alloc(dev, &nsio->res, nd_region->id); if (IS_ERR(pmem)) return PTR_ERR(pmem);