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

nvdimm: Replace lockdep_mutex with local lock classes

In response to an attempt to expand dev->lockdep_mutex for device_lock()
validation [1], Peter points out [2] that the lockdep API already has
the ability to assign a dedicated lock class per subsystem device-type.

Use lockdep_set_class() to override the default device_lock()
'__lockdep_no_validate__' class for each NVDIMM subsystem device-type. This
enables lockdep to detect deadlocks and recursive locking within the
device-driver core and the subsystem.

Link: https://lore.kernel.org/r/164982968798.684294.15817853329823976469.stgit@dwillia2-desk3.amr.corp.intel.com [1]
Link: https://lore.kernel.org/r/Ylf0dewci8myLvoW@hirez.programming.kicks-ass.net [2]
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Link: https://lore.kernel.org/r/165055520896.3745911.8021255583475547548.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+37 -15
+5 -2
drivers/nvdimm/btt_devs.c
··· 178 178 } 179 179 EXPORT_SYMBOL(is_nd_btt); 180 180 181 + static struct lock_class_key nvdimm_btt_key; 182 + 181 183 static struct device *__nd_btt_create(struct nd_region *nd_region, 182 184 unsigned long lbasize, uuid_t *uuid, 183 185 struct nd_namespace_common *ndns) ··· 207 205 dev->parent = &nd_region->dev; 208 206 dev->type = &nd_btt_device_type; 209 207 device_initialize(&nd_btt->dev); 208 + lockdep_set_class(&nd_btt->dev.mutex, &nvdimm_btt_key); 210 209 if (ndns && !__nd_attach_ndns(&nd_btt->dev, ndns, &nd_btt->ndns)) { 211 210 dev_dbg(&ndns->dev, "failed, already claimed by %s\n", 212 211 dev_name(ndns->claim)); ··· 228 225 { 229 226 struct device *dev = __nd_btt_create(nd_region, 0, NULL, NULL); 230 227 231 - __nd_device_register(dev); 228 + nd_device_register(dev); 232 229 return dev; 233 230 } 234 231 ··· 327 324 if (!nd_btt->uuid) 328 325 return -ENOMEM; 329 326 330 - __nd_device_register(&nd_btt->dev); 327 + nd_device_register(&nd_btt->dev); 331 328 332 329 return 0; 333 330 }
+7 -7
drivers/nvdimm/bus.c
··· 334 334 } 335 335 EXPORT_SYMBOL_GPL(nvdimm_to_bus); 336 336 337 + static struct lock_class_key nvdimm_bus_key; 338 + 337 339 struct nvdimm_bus *nvdimm_bus_register(struct device *parent, 338 340 struct nvdimm_bus_descriptor *nd_desc) 339 341 { ··· 362 360 nvdimm_bus->dev.bus = &nvdimm_bus_type; 363 361 nvdimm_bus->dev.of_node = nd_desc->of_node; 364 362 device_initialize(&nvdimm_bus->dev); 363 + lockdep_set_class(&nvdimm_bus->dev.mutex, &nvdimm_bus_key); 365 364 device_set_pm_not_required(&nvdimm_bus->dev); 366 365 rc = dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id); 367 366 if (rc) ··· 514 511 put_device(dev); 515 512 } 516 513 517 - void __nd_device_register(struct device *dev) 514 + void nd_device_register(struct device *dev) 518 515 { 519 516 if (!dev) 520 517 return; ··· 539 536 540 537 async_schedule_dev_domain(nd_async_device_register, dev, 541 538 &nd_async_domain); 542 - } 543 - 544 - void nd_device_register(struct device *dev) 545 - { 546 - device_initialize(dev); 547 - __nd_device_register(dev); 548 539 } 549 540 EXPORT_SYMBOL(nd_device_register); 550 541 ··· 721 724 kfree(dev); 722 725 } 723 726 727 + static struct lock_class_key nvdimm_ndctl_key; 728 + 724 729 int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus) 725 730 { 726 731 dev_t devt = MKDEV(nvdimm_bus_major, nvdimm_bus->id); ··· 733 734 if (!dev) 734 735 return -ENOMEM; 735 736 device_initialize(dev); 737 + lockdep_set_class(&dev->mutex, &nvdimm_ndctl_key); 736 738 device_set_pm_not_required(dev); 737 739 dev->class = nd_class; 738 740 dev->parent = &nvdimm_bus->dev;
+2 -2
drivers/nvdimm/dax_devs.c
··· 80 80 nd_dax = nd_dax_alloc(nd_region); 81 81 if (nd_dax) 82 82 dev = nd_pfn_devinit(&nd_dax->nd_pfn, NULL); 83 - __nd_device_register(dev); 83 + nd_device_register(dev); 84 84 return dev; 85 85 } 86 86 ··· 119 119 nd_detach_ndns(dax_dev, &nd_pfn->ndns); 120 120 put_device(dax_dev); 121 121 } else 122 - __nd_device_register(dax_dev); 122 + nd_device_register(dax_dev); 123 123 124 124 return rc; 125 125 }
+4
drivers/nvdimm/dimm_devs.c
··· 570 570 return dev->type == &nvdimm_device_type; 571 571 } 572 572 573 + static struct lock_class_key nvdimm_key; 574 + 573 575 struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, 574 576 void *provider_data, const struct attribute_group **groups, 575 577 unsigned long flags, unsigned long cmd_mask, int num_flush, ··· 615 613 /* get security state and extended (master) state */ 616 614 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER); 617 615 nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER); 616 + device_initialize(dev); 617 + lockdep_set_class(&dev->mutex, &nvdimm_key); 618 618 nd_device_register(dev); 619 619 620 620 return nvdimm;
+9 -1
drivers/nvdimm/namespace_devs.c
··· 1830 1830 return dev; 1831 1831 } 1832 1832 1833 + static struct lock_class_key nvdimm_namespace_key; 1834 + 1833 1835 void nd_region_create_ns_seed(struct nd_region *nd_region) 1834 1836 { 1835 1837 WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev)); ··· 1847 1845 */ 1848 1846 if (!nd_region->ns_seed) 1849 1847 dev_err(&nd_region->dev, "failed to create namespace\n"); 1850 - else 1848 + else { 1849 + device_initialize(nd_region->ns_seed); 1850 + lockdep_set_class(&nd_region->ns_seed->mutex, 1851 + &nvdimm_namespace_key); 1851 1852 nd_device_register(nd_region->ns_seed); 1853 + } 1852 1854 } 1853 1855 1854 1856 void nd_region_create_dax_seed(struct nd_region *nd_region) ··· 2206 2200 if (id < 0) 2207 2201 break; 2208 2202 dev_set_name(dev, "namespace%d.%d", nd_region->id, id); 2203 + device_initialize(dev); 2204 + lockdep_set_class(&dev->mutex, &nvdimm_namespace_key); 2209 2205 nd_device_register(dev); 2210 2206 } 2211 2207 if (i)
+1 -1
drivers/nvdimm/nd-core.h
··· 106 106 int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus); 107 107 void nvdimm_bus_destroy_ndctl(struct nvdimm_bus *nvdimm_bus); 108 108 void nd_synchronize(void); 109 - void __nd_device_register(struct device *dev); 109 + void nd_device_register(struct device *dev); 110 110 struct nd_label_id; 111 111 char *nd_label_gen_id(struct nd_label_id *label_id, const uuid_t *uuid, 112 112 u32 flags);
+5 -2
drivers/nvdimm/pfn_devs.c
··· 291 291 } 292 292 EXPORT_SYMBOL(is_nd_pfn); 293 293 294 + static struct lock_class_key nvdimm_pfn_key; 295 + 294 296 struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn, 295 297 struct nd_namespace_common *ndns) 296 298 { ··· 305 303 nd_pfn->align = nd_pfn_default_alignment(); 306 304 dev = &nd_pfn->dev; 307 305 device_initialize(&nd_pfn->dev); 306 + lockdep_set_class(&nd_pfn->dev.mutex, &nvdimm_pfn_key); 308 307 if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) { 309 308 dev_dbg(&ndns->dev, "failed, already claimed by %s\n", 310 309 dev_name(ndns->claim)); ··· 349 346 nd_pfn = nd_pfn_alloc(nd_region); 350 347 dev = nd_pfn_devinit(nd_pfn, NULL); 351 348 352 - __nd_device_register(dev); 349 + nd_device_register(dev); 353 350 return dev; 354 351 } 355 352 ··· 646 643 nd_detach_ndns(pfn_dev, &nd_pfn->ndns); 647 644 put_device(pfn_dev); 648 645 } else 649 - __nd_device_register(pfn_dev); 646 + nd_device_register(pfn_dev); 650 647 651 648 return rc; 652 649 }
+4
drivers/nvdimm/region_devs.c
··· 949 949 return align; 950 950 } 951 951 952 + static struct lock_class_key nvdimm_region_key; 953 + 952 954 static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, 953 955 struct nd_region_desc *ndr_desc, 954 956 const struct device_type *dev_type, const char *caller) ··· 1037 1035 else 1038 1036 nd_region->flush = NULL; 1039 1037 1038 + device_initialize(dev); 1039 + lockdep_set_class(&dev->mutex, &nvdimm_region_key); 1040 1040 nd_device_register(dev); 1041 1041 1042 1042 return nd_region;