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

device-dax: Introduce bus + driver model

In support of multiple device-dax instances per device-dax-region and
allowing the 'kmem' driver to attach to dax-instances instead of the
current device-node access, convert the dax sub-system from a class to a
bus. Recall that the kmem driver takes reserved / special purpose
memories and assigns them to be managed by the core-mm.

Aside from the fact the device-dax instances are registered and probed
on a bus, two other lifetime-management changes are made:

1/ Delay attaching a cdev until driver probe time

2/ A new run_dax() helper is introduced to allow restoring dax-operation
after a kill_dax() event. So, at driver ->probe() time we run_dax()
and at ->remove() time we kill_dax() and invalidate all mappings.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+205 -89
+125 -8
drivers/dax/bus.c
··· 6 6 #include "dax-private.h" 7 7 #include "bus.h" 8 8 9 + static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 10 + { 11 + /* 12 + * We only ever expect to handle device-dax instances, i.e. the 13 + * @type argument to MODULE_ALIAS_DAX_DEVICE() is always zero 14 + */ 15 + return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0); 16 + } 17 + 18 + static int dax_bus_match(struct device *dev, struct device_driver *drv); 19 + 20 + static struct bus_type dax_bus_type = { 21 + .name = "dax", 22 + .uevent = dax_bus_uevent, 23 + .match = dax_bus_match, 24 + }; 25 + 26 + static int dax_bus_match(struct device *dev, struct device_driver *drv) 27 + { 28 + /* 29 + * The drivers that can register on the 'dax' bus are private to 30 + * drivers/dax/ so any device and driver on the bus always 31 + * match. 32 + */ 33 + return 1; 34 + } 35 + 9 36 /* 10 37 * Rely on the fact that drvdata is set before the attributes are 11 38 * registered, and that the attributes are unregistered before drvdata ··· 169 142 .attrs = dev_dax_attributes, 170 143 }; 171 144 172 - const struct attribute_group *dax_attribute_groups[] = { 145 + static const struct attribute_group *dax_attribute_groups[] = { 173 146 &dev_dax_attribute_group, 174 147 NULL, 175 148 }; 176 - EXPORT_SYMBOL_GPL(dax_attribute_groups); 177 149 178 150 void kill_dev_dax(struct dev_dax *dev_dax) 179 151 { ··· 184 158 } 185 159 EXPORT_SYMBOL_GPL(kill_dev_dax); 186 160 187 - void unregister_dev_dax(void *dev) 161 + static void dev_dax_release(struct device *dev) 188 162 { 189 163 struct dev_dax *dev_dax = to_dev_dax(dev); 164 + struct dax_region *dax_region = dev_dax->region; 190 165 struct dax_device *dax_dev = dev_dax->dax_dev; 191 - struct inode *inode = dax_inode(dax_dev); 192 - struct cdev *cdev = inode->i_cdev; 193 166 194 - dev_dbg(dev, "trace\n"); 167 + dax_region_put(dax_region); 168 + put_dax(dax_dev); 169 + kfree(dev_dax); 170 + } 171 + 172 + static void unregister_dev_dax(void *dev) 173 + { 174 + struct dev_dax *dev_dax = to_dev_dax(dev); 175 + 176 + dev_dbg(dev, "%s\n", __func__); 195 177 196 178 kill_dev_dax(dev_dax); 197 - cdev_device_del(cdev, dev); 179 + device_del(dev); 198 180 put_device(dev); 199 181 } 200 - EXPORT_SYMBOL_GPL(unregister_dev_dax); 182 + 183 + struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id) 184 + { 185 + struct device *parent = dax_region->dev; 186 + struct dax_device *dax_dev; 187 + struct dev_dax *dev_dax; 188 + struct inode *inode; 189 + struct device *dev; 190 + int rc = -ENOMEM; 191 + 192 + if (id < 0) 193 + return ERR_PTR(-EINVAL); 194 + 195 + dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL); 196 + if (!dev_dax) 197 + return ERR_PTR(-ENOMEM); 198 + 199 + /* 200 + * No 'host' or dax_operations since there is no access to this 201 + * device outside of mmap of the resulting character device. 202 + */ 203 + dax_dev = alloc_dax(dev_dax, NULL, NULL); 204 + if (!dax_dev) 205 + goto err; 206 + 207 + /* a device_dax instance is dead while the driver is not attached */ 208 + kill_dax(dax_dev); 209 + 210 + /* from here on we're committed to teardown via dax_dev_release() */ 211 + dev = &dev_dax->dev; 212 + device_initialize(dev); 213 + 214 + dev_dax->dax_dev = dax_dev; 215 + dev_dax->region = dax_region; 216 + kref_get(&dax_region->kref); 217 + 218 + inode = dax_inode(dax_dev); 219 + dev->devt = inode->i_rdev; 220 + dev->bus = &dax_bus_type; 221 + dev->parent = parent; 222 + dev->groups = dax_attribute_groups; 223 + dev->release = dev_dax_release; 224 + dev_set_name(dev, "dax%d.%d", dax_region->id, id); 225 + 226 + rc = device_add(dev); 227 + if (rc) { 228 + kill_dev_dax(dev_dax); 229 + put_device(dev); 230 + return ERR_PTR(rc); 231 + } 232 + 233 + rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev); 234 + if (rc) 235 + return ERR_PTR(rc); 236 + 237 + return dev_dax; 238 + 239 + err: 240 + kfree(dev_dax); 241 + 242 + return ERR_PTR(rc); 243 + } 244 + EXPORT_SYMBOL_GPL(devm_create_dev_dax); 245 + 246 + int __dax_driver_register(struct device_driver *drv, 247 + struct module *module, const char *mod_name) 248 + { 249 + drv->owner = module; 250 + drv->name = mod_name; 251 + drv->mod_name = mod_name; 252 + drv->bus = &dax_bus_type; 253 + return driver_register(drv); 254 + } 255 + EXPORT_SYMBOL_GPL(__dax_driver_register); 256 + 257 + int __init dax_bus_init(void) 258 + { 259 + return bus_register(&dax_bus_type); 260 + } 261 + 262 + void __exit dax_bus_exit(void) 263 + { 264 + bus_unregister(&dax_bus_type); 265 + }
+16
drivers/dax/bus.h
··· 11 11 struct dax_region *alloc_dax_region(struct device *parent, int region_id, 12 12 struct resource *res, unsigned int align, unsigned long flags); 13 13 struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id); 14 + int __dax_driver_register(struct device_driver *drv, 15 + struct module *module, const char *mod_name); 16 + #define dax_driver_register(driver) \ 17 + __dax_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) 14 18 void kill_dev_dax(struct dev_dax *dev_dax); 19 + 20 + /* 21 + * While run_dax() is potentially a generic operation that could be 22 + * defined in include/linux/dax.h we don't want to grow any users 23 + * outside of drivers/dax/ 24 + */ 25 + void run_dax(struct dax_device *dax_dev); 26 + 27 + #define MODULE_ALIAS_DAX_DEVICE(type) \ 28 + MODULE_ALIAS("dax:t" __stringify(type) "*") 29 + #define DAX_DEVICE_MODALIAS_FMT "dax:t%d" 30 + 15 31 #endif /* __DAX_BUS_H__ */
+2 -4
drivers/dax/dax-private.h
··· 20 20 struct dax_device; 21 21 struct dax_device *inode_dax(struct inode *inode); 22 22 struct inode *dax_inode(struct dax_device *dax_dev); 23 - 24 - /* temporary until devm_create_dax_dev moves to bus.c */ 25 - extern const struct attribute_group *dax_attribute_groups[]; 26 - void unregister_dev_dax(void *dev); 23 + int dax_bus_init(void); 24 + void dax_bus_exit(void); 27 25 28 26 /** 29 27 * struct dax_region - mapping infrastructure for dax devices
+34 -65
drivers/dax/device.c
··· 13 13 #include "dax-private.h" 14 14 #include "bus.h" 15 15 16 - static struct class *dax_class; 17 - 18 16 static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma, 19 17 const char *func) 20 18 { ··· 402 404 .mmap_supported_flags = MAP_SYNC, 403 405 }; 404 406 405 - static void dev_dax_release(struct device *dev) 407 + static void dev_dax_cdev_del(void *cdev) 406 408 { 407 - struct dev_dax *dev_dax = to_dev_dax(dev); 408 - struct dax_region *dax_region = dev_dax->region; 409 - struct dax_device *dax_dev = dev_dax->dax_dev; 410 - 411 - dax_region_put(dax_region); 412 - put_dax(dax_dev); 413 - kfree(dev_dax); 409 + cdev_del(cdev); 414 410 } 415 411 416 - struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id) 412 + static void dev_dax_kill(void *dev_dax) 417 413 { 418 - struct device *parent = dax_region->dev; 419 - struct dax_device *dax_dev; 420 - struct dev_dax *dev_dax; 414 + kill_dev_dax(dev_dax); 415 + } 416 + 417 + static int dev_dax_probe(struct device *dev) 418 + { 419 + struct dev_dax *dev_dax = to_dev_dax(dev); 420 + struct dax_device *dax_dev = dev_dax->dax_dev; 421 421 struct inode *inode; 422 - struct device *dev; 423 422 struct cdev *cdev; 424 423 int rc; 425 - 426 - dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL); 427 - if (!dev_dax) 428 - return ERR_PTR(-ENOMEM); 429 - 430 - /* 431 - * No 'host' or dax_operations since there is no access to this 432 - * device outside of mmap of the resulting character device. 433 - */ 434 - dax_dev = alloc_dax(dev_dax, NULL, NULL); 435 - if (!dax_dev) { 436 - rc = -ENOMEM; 437 - goto err; 438 - } 439 - 440 - /* from here on we're committed to teardown via dax_dev_release() */ 441 - dev = &dev_dax->dev; 442 - device_initialize(dev); 443 424 444 425 inode = dax_inode(dax_dev); 445 426 cdev = inode->i_cdev; 446 427 cdev_init(cdev, &dax_fops); 447 - cdev->owner = parent->driver->owner; 448 - 449 - dev_dax->dax_dev = dax_dev; 450 - dev_dax->region = dax_region; 451 - kref_get(&dax_region->kref); 452 - 453 - dev->devt = inode->i_rdev; 454 - dev->class = dax_class; 455 - dev->parent = parent; 456 - dev->groups = dax_attribute_groups; 457 - dev->release = dev_dax_release; 458 - dev_set_name(dev, "dax%d.%d", dax_region->id, id); 459 - 460 - rc = cdev_device_add(cdev, dev); 461 - if (rc) { 462 - kill_dev_dax(dev_dax); 463 - put_device(dev); 464 - return ERR_PTR(rc); 465 - } 466 - 467 - rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev); 428 + cdev->owner = dev->driver->owner; 429 + cdev_set_parent(cdev, &dev->kobj); 430 + rc = cdev_add(cdev, dev->devt, 1); 468 431 if (rc) 469 - return ERR_PTR(rc); 432 + return rc; 470 433 471 - return dev_dax; 434 + rc = devm_add_action_or_reset(dev, dev_dax_cdev_del, cdev); 435 + if (rc) 436 + return rc; 472 437 473 - err: 474 - kfree(dev_dax); 475 - 476 - return ERR_PTR(rc); 438 + run_dax(dax_dev); 439 + return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax); 477 440 } 478 - EXPORT_SYMBOL_GPL(devm_create_dev_dax); 441 + 442 + static int dev_dax_remove(struct device *dev) 443 + { 444 + /* all probe actions are unwound by devm */ 445 + return 0; 446 + } 447 + 448 + static struct device_driver device_dax_driver = { 449 + .probe = dev_dax_probe, 450 + .remove = dev_dax_remove, 451 + }; 479 452 480 453 static int __init dax_init(void) 481 454 { 482 - dax_class = class_create(THIS_MODULE, "dax"); 483 - return PTR_ERR_OR_ZERO(dax_class); 455 + return dax_driver_register(&device_dax_driver); 484 456 } 485 457 486 458 static void __exit dax_exit(void) 487 459 { 488 - class_destroy(dax_class); 460 + driver_unregister(&device_dax_driver); 489 461 } 490 462 491 463 MODULE_AUTHOR("Intel Corporation"); 492 464 MODULE_LICENSE("GPL v2"); 493 - subsys_initcall(dax_init); 465 + module_init(dax_init); 494 466 module_exit(dax_exit); 467 + MODULE_ALIAS_DAX_DEVICE(0);
+28 -12
drivers/dax/super.c
··· 366 366 spin_lock(&dax_host_lock); 367 367 hlist_del_init(&dax_dev->list); 368 368 spin_unlock(&dax_host_lock); 369 - 370 - dax_dev->private = NULL; 371 369 } 372 370 EXPORT_SYMBOL_GPL(kill_dax); 371 + 372 + void run_dax(struct dax_device *dax_dev) 373 + { 374 + set_bit(DAXDEV_ALIVE, &dax_dev->flags); 375 + } 376 + EXPORT_SYMBOL_GPL(run_dax); 373 377 374 378 static struct inode *dax_alloc_inode(struct super_block *sb) 375 379 { ··· 589 585 590 586 void *dax_get_private(struct dax_device *dax_dev) 591 587 { 588 + if (!test_bit(DAXDEV_ALIVE, &dax_dev->flags)) 589 + return NULL; 592 590 return dax_dev->private; 593 591 } 594 592 EXPORT_SYMBOL_GPL(dax_get_private); ··· 604 598 inode_init_once(inode); 605 599 } 606 600 607 - static int __dax_fs_init(void) 601 + static int dax_fs_init(void) 608 602 { 609 603 int rc; 610 604 ··· 636 630 return rc; 637 631 } 638 632 639 - static void __dax_fs_exit(void) 633 + static void dax_fs_exit(void) 640 634 { 641 635 kern_unmount(dax_mnt); 642 636 unregister_filesystem(&dax_fs_type); 643 637 kmem_cache_destroy(dax_cache); 644 638 } 645 639 646 - static int __init dax_fs_init(void) 640 + static int __init dax_core_init(void) 647 641 { 648 642 int rc; 649 643 650 - rc = __dax_fs_init(); 644 + rc = dax_fs_init(); 651 645 if (rc) 652 646 return rc; 653 647 654 648 rc = alloc_chrdev_region(&dax_devt, 0, MINORMASK+1, "dax"); 655 649 if (rc) 656 - __dax_fs_exit(); 657 - return rc; 650 + goto err_chrdev; 651 + 652 + rc = dax_bus_init(); 653 + if (rc) 654 + goto err_bus; 655 + return 0; 656 + 657 + err_bus: 658 + unregister_chrdev_region(dax_devt, MINORMASK+1); 659 + err_chrdev: 660 + dax_fs_exit(); 661 + return 0; 658 662 } 659 663 660 - static void __exit dax_fs_exit(void) 664 + static void __exit dax_core_exit(void) 661 665 { 662 666 unregister_chrdev_region(dax_devt, MINORMASK+1); 663 667 ida_destroy(&dax_minor_ida); 664 - __dax_fs_exit(); 668 + dax_fs_exit(); 665 669 } 666 670 667 671 MODULE_AUTHOR("Intel Corporation"); 668 672 MODULE_LICENSE("GPL v2"); 669 - subsys_initcall(dax_fs_init); 670 - module_exit(dax_fs_exit); 673 + subsys_initcall(dax_core_init); 674 + module_exit(dax_core_exit);