Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

device-dax: fix sysfs duplicate warnings

Fix warnings of the form...

WARNING: CPU: 10 PID: 4983 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x62/0x80
sysfs: cannot create duplicate filename '/class/dax/dax12.0'
Call Trace:
dump_stack+0x63/0x86
__warn+0xcb/0xf0
warn_slowpath_fmt+0x5a/0x80
? kernfs_path_from_node+0x4f/0x60
sysfs_warn_dup+0x62/0x80
sysfs_do_create_link_sd.isra.2+0x97/0xb0
sysfs_create_link+0x25/0x40
device_add+0x266/0x630
devm_create_dax_dev+0x2cf/0x340 [dax]
dax_pmem_probe+0x1f5/0x26e [dax_pmem]
nvdimm_bus_probe+0x71/0x120

...by reusing the namespace id for the device-dax instance name.

Now that we have decided that there will never by more than one
device-dax instance per libnvdimm-namespace parent device [1], we can
directly reuse the namepace ids. There are some possible follow-on
cleanups, but those are saved for a later patch to simplify the -stable
backport.

[1]: https://lists.01.org/pipermail/linux-nvdimm/2016-December/008266.html

Fixes: 98a29c39dc68 ("libnvdimm, namespace: allow creation of multiple pmem...")
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: <stable@vger.kernel.org>
Reported-by: Dariusz Dokupil <dariusz.dokupil@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+24 -14
+1 -1
drivers/dax/device-dax.h
··· 21 21 int region_id, struct resource *res, unsigned int align, 22 22 void *addr, unsigned long flags); 23 23 struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, 24 - struct resource *res, int count); 24 + int id, struct resource *res, int count); 25 25 #endif /* __DEVICE_DAX_H__ */
+16 -8
drivers/dax/device.c
··· 529 529 struct dax_region *dax_region = dev_dax->region; 530 530 struct dax_device *dax_dev = dev_dax->dax_dev; 531 531 532 - ida_simple_remove(&dax_region->ida, dev_dax->id); 532 + if (dev_dax->id >= 0) 533 + ida_simple_remove(&dax_region->ida, dev_dax->id); 533 534 dax_region_put(dax_region); 534 535 put_dax(dax_dev); 535 536 kfree(dev_dax); ··· 560 559 } 561 560 562 561 struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, 563 - struct resource *res, int count) 562 + int id, struct resource *res, int count) 564 563 { 565 564 struct device *parent = dax_region->dev; 566 565 struct dax_device *dax_dev; ··· 591 590 if (i < count) 592 591 goto err_id; 593 592 594 - dev_dax->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL); 595 - if (dev_dax->id < 0) { 596 - rc = dev_dax->id; 597 - goto err_id; 593 + if (id < 0) { 594 + id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL); 595 + dev_dax->id = id; 596 + if (id < 0) { 597 + rc = id; 598 + goto err_id; 599 + } 600 + } else { 601 + /* region provider owns @id lifetime */ 602 + dev_dax->id = -1; 598 603 } 599 604 600 605 /* ··· 632 625 dev->parent = parent; 633 626 dev->groups = dax_attribute_groups; 634 627 dev->release = dev_dax_release; 635 - dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id); 628 + dev_set_name(dev, "dax%d.%d", dax_region->id, id); 636 629 637 630 rc = cdev_device_add(cdev, dev); 638 631 if (rc) { ··· 648 641 return dev_dax; 649 642 650 643 err_dax: 651 - ida_simple_remove(&dax_region->ida, dev_dax->id); 644 + if (dev_dax->id >= 0) 645 + ida_simple_remove(&dax_region->ida, dev_dax->id); 652 646 err_id: 653 647 kfree(dev_dax); 654 648
+7 -5
drivers/dax/pmem.c
··· 58 58 59 59 static int dax_pmem_probe(struct device *dev) 60 60 { 61 - int rc; 62 61 void *addr; 63 62 struct resource res; 63 + int rc, id, region_id; 64 64 struct nd_pfn_sb *pfn_sb; 65 65 struct dev_dax *dev_dax; 66 66 struct dax_pmem *dax_pmem; 67 - struct nd_region *nd_region; 68 67 struct nd_namespace_io *nsio; 69 68 struct dax_region *dax_region; 70 69 struct nd_namespace_common *ndns; ··· 122 123 /* adjust the dax_region resource to the start of data */ 123 124 res.start += le64_to_cpu(pfn_sb->dataoff); 124 125 125 - nd_region = to_nd_region(dev->parent); 126 - dax_region = alloc_dax_region(dev, nd_region->id, &res, 126 + rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id); 127 + if (rc != 2) 128 + return -EINVAL; 129 + 130 + dax_region = alloc_dax_region(dev, region_id, &res, 127 131 le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP); 128 132 if (!dax_region) 129 133 return -ENOMEM; 130 134 131 135 /* TODO: support for subdividing a dax region... */ 132 - dev_dax = devm_create_dev_dax(dax_region, &res, 1); 136 + dev_dax = devm_create_dev_dax(dax_region, id, &res, 1); 133 137 134 138 /* child dev_dax instances now own the lifetime of the dax_region */ 135 139 dax_region_put(dax_region);