diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-07-24 18:55:42 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-08-24 01:58:51 -0400 |
commit | ba09c01d2fa866f22e42ac2af405fe386f491879 (patch) | |
tree | c0028867440d5d50709bf787221bb4c64f29586b | |
parent | ebd84d724c85f22037a5c9cb04b9e6631309cb78 (diff) |
dax: convert to the cdev api
A goal of the device-DAX interface is to be able to support many
exclusive allocations (partitions) of performance / feature
differentiated memory. This count may exceed the default minors limit
of 256.
As a result of switching to an embedded cdev the inode-to-dax_dev
conversion is simplified, as well as reference counting which can switch
to the cdev kobject lifetime.
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/dax/Kconfig | 5 | ||||
-rw-r--r-- | drivers/dax/dax.c | 82 |
2 files changed, 46 insertions, 41 deletions
diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig index cedab7572de3..daadd20aa936 100644 --- a/drivers/dax/Kconfig +++ b/drivers/dax/Kconfig | |||
@@ -23,4 +23,9 @@ config DEV_DAX_PMEM | |||
23 | 23 | ||
24 | Say Y if unsure | 24 | Say Y if unsure |
25 | 25 | ||
26 | config NR_DEV_DAX | ||
27 | int "Maximum number of Device-DAX instances" | ||
28 | default 32768 | ||
29 | range 256 2147483647 | ||
30 | |||
26 | endif | 31 | endif |
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 181d2a5a21e4..17715773c097 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c | |||
@@ -14,15 +14,19 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/pfn_t.h> | 16 | #include <linux/pfn_t.h> |
17 | #include <linux/cdev.h> | ||
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/dax.h> | 19 | #include <linux/dax.h> |
19 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
20 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
21 | #include "dax.h" | 22 | #include "dax.h" |
22 | 23 | ||
23 | static int dax_major; | 24 | static dev_t dax_devt; |
24 | static struct class *dax_class; | 25 | static struct class *dax_class; |
25 | static DEFINE_IDA(dax_minor_ida); | 26 | static DEFINE_IDA(dax_minor_ida); |
27 | static int nr_dax = CONFIG_NR_DEV_DAX; | ||
28 | module_param(nr_dax, int, S_IRUGO); | ||
29 | MODULE_PARM_DESC(nr_dax, "max number of device-dax instances"); | ||
26 | 30 | ||
27 | /** | 31 | /** |
28 | * struct dax_region - mapping infrastructure for dax devices | 32 | * struct dax_region - mapping infrastructure for dax devices |
@@ -49,6 +53,7 @@ struct dax_region { | |||
49 | * struct dax_dev - subdivision of a dax region | 53 | * struct dax_dev - subdivision of a dax region |
50 | * @region - parent region | 54 | * @region - parent region |
51 | * @dev - device backing the character device | 55 | * @dev - device backing the character device |
56 | * @cdev - core chardev data | ||
52 | * @alive - !alive + rcu grace period == no new mappings can be established | 57 | * @alive - !alive + rcu grace period == no new mappings can be established |
53 | * @id - child id in the region | 58 | * @id - child id in the region |
54 | * @num_resources - number of physical address extents in this device | 59 | * @num_resources - number of physical address extents in this device |
@@ -57,6 +62,7 @@ struct dax_region { | |||
57 | struct dax_dev { | 62 | struct dax_dev { |
58 | struct dax_region *region; | 63 | struct dax_region *region; |
59 | struct device dev; | 64 | struct device dev; |
65 | struct cdev cdev; | ||
60 | bool alive; | 66 | bool alive; |
61 | int id; | 67 | int id; |
62 | int num_resources; | 68 | int num_resources; |
@@ -367,29 +373,12 @@ static unsigned long dax_get_unmapped_area(struct file *filp, | |||
367 | return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); | 373 | return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); |
368 | } | 374 | } |
369 | 375 | ||
370 | static int __match_devt(struct device *dev, const void *data) | ||
371 | { | ||
372 | const dev_t *devt = data; | ||
373 | |||
374 | return dev->devt == *devt; | ||
375 | } | ||
376 | |||
377 | static struct device *dax_dev_find(dev_t dev_t) | ||
378 | { | ||
379 | return class_find_device(dax_class, NULL, &dev_t, __match_devt); | ||
380 | } | ||
381 | |||
382 | static int dax_open(struct inode *inode, struct file *filp) | 376 | static int dax_open(struct inode *inode, struct file *filp) |
383 | { | 377 | { |
384 | struct dax_dev *dax_dev = NULL; | 378 | struct dax_dev *dax_dev; |
385 | struct device *dev; | ||
386 | |||
387 | dev = dax_dev_find(inode->i_rdev); | ||
388 | if (!dev) | ||
389 | return -ENXIO; | ||
390 | 379 | ||
391 | dax_dev = to_dax_dev(dev); | 380 | dax_dev = container_of(inode->i_cdev, struct dax_dev, cdev); |
392 | dev_dbg(dev, "%s\n", __func__); | 381 | dev_dbg(&dax_dev->dev, "%s\n", __func__); |
393 | filp->private_data = dax_dev; | 382 | filp->private_data = dax_dev; |
394 | inode->i_flags = S_DAX; | 383 | inode->i_flags = S_DAX; |
395 | 384 | ||
@@ -399,11 +388,8 @@ static int dax_open(struct inode *inode, struct file *filp) | |||
399 | static int dax_release(struct inode *inode, struct file *filp) | 388 | static int dax_release(struct inode *inode, struct file *filp) |
400 | { | 389 | { |
401 | struct dax_dev *dax_dev = filp->private_data; | 390 | struct dax_dev *dax_dev = filp->private_data; |
402 | struct device *dev = &dax_dev->dev; | ||
403 | |||
404 | dev_dbg(dev, "%s\n", __func__); | ||
405 | put_device(dev); | ||
406 | 391 | ||
392 | dev_dbg(&dax_dev->dev, "%s\n", __func__); | ||
407 | return 0; | 393 | return 0; |
408 | } | 394 | } |
409 | 395 | ||
@@ -430,6 +416,7 @@ static void dax_dev_release(struct device *dev) | |||
430 | static void unregister_dax_dev(void *dev) | 416 | static void unregister_dax_dev(void *dev) |
431 | { | 417 | { |
432 | struct dax_dev *dax_dev = to_dax_dev(dev); | 418 | struct dax_dev *dax_dev = to_dax_dev(dev); |
419 | struct cdev *cdev = &dax_dev->cdev; | ||
433 | 420 | ||
434 | dev_dbg(dev, "%s\n", __func__); | 421 | dev_dbg(dev, "%s\n", __func__); |
435 | 422 | ||
@@ -442,6 +429,7 @@ static void unregister_dax_dev(void *dev) | |||
442 | */ | 429 | */ |
443 | dax_dev->alive = false; | 430 | dax_dev->alive = false; |
444 | synchronize_rcu(); | 431 | synchronize_rcu(); |
432 | cdev_del(cdev); | ||
445 | device_unregister(dev); | 433 | device_unregister(dev); |
446 | } | 434 | } |
447 | 435 | ||
@@ -451,17 +439,13 @@ int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res, | |||
451 | struct device *parent = dax_region->dev; | 439 | struct device *parent = dax_region->dev; |
452 | struct dax_dev *dax_dev; | 440 | struct dax_dev *dax_dev; |
453 | struct device *dev; | 441 | struct device *dev; |
442 | struct cdev *cdev; | ||
454 | int rc, minor; | 443 | int rc, minor; |
455 | dev_t dev_t; | 444 | dev_t dev_t; |
456 | 445 | ||
457 | dax_dev = kzalloc(sizeof(*dax_dev) + sizeof(*res) * count, GFP_KERNEL); | 446 | dax_dev = kzalloc(sizeof(*dax_dev) + sizeof(*res) * count, GFP_KERNEL); |
458 | if (!dax_dev) | 447 | if (!dax_dev) |
459 | return -ENOMEM; | 448 | return -ENOMEM; |
460 | memcpy(dax_dev->res, res, sizeof(*res) * count); | ||
461 | dax_dev->num_resources = count; | ||
462 | dax_dev->alive = true; | ||
463 | dax_dev->region = dax_region; | ||
464 | kref_get(&dax_region->kref); | ||
465 | 449 | ||
466 | dax_dev->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL); | 450 | dax_dev->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL); |
467 | if (dax_dev->id < 0) { | 451 | if (dax_dev->id < 0) { |
@@ -475,10 +459,26 @@ int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res, | |||
475 | goto err_minor; | 459 | goto err_minor; |
476 | } | 460 | } |
477 | 461 | ||
478 | dev_t = MKDEV(dax_major, minor); | 462 | /* device_initialize() so cdev can reference kobj parent */ |
479 | 463 | dev_t = MKDEV(MAJOR(dax_devt), minor); | |
480 | dev = &dax_dev->dev; | 464 | dev = &dax_dev->dev; |
481 | device_initialize(dev); | 465 | device_initialize(dev); |
466 | |||
467 | cdev = &dax_dev->cdev; | ||
468 | cdev_init(cdev, &dax_fops); | ||
469 | cdev->owner = parent->driver->owner; | ||
470 | cdev->kobj.parent = &dev->kobj; | ||
471 | rc = cdev_add(&dax_dev->cdev, dev_t, 1); | ||
472 | if (rc) | ||
473 | goto err_cdev; | ||
474 | |||
475 | /* from here on we're committed to teardown via dax_dev_release() */ | ||
476 | memcpy(dax_dev->res, res, sizeof(*res) * count); | ||
477 | dax_dev->num_resources = count; | ||
478 | dax_dev->alive = true; | ||
479 | dax_dev->region = dax_region; | ||
480 | kref_get(&dax_region->kref); | ||
481 | |||
482 | dev->devt = dev_t; | 482 | dev->devt = dev_t; |
483 | dev->class = dax_class; | 483 | dev->class = dax_class; |
484 | dev->parent = parent; | 484 | dev->parent = parent; |
@@ -493,6 +493,8 @@ int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res, | |||
493 | 493 | ||
494 | return devm_add_action_or_reset(dax_region->dev, unregister_dax_dev, dev); | 494 | return devm_add_action_or_reset(dax_region->dev, unregister_dax_dev, dev); |
495 | 495 | ||
496 | err_cdev: | ||
497 | ida_simple_remove(&dax_minor_ida, minor); | ||
496 | err_minor: | 498 | err_minor: |
497 | ida_simple_remove(&dax_region->ida, dax_dev->id); | 499 | ida_simple_remove(&dax_region->ida, dax_dev->id); |
498 | err_id: | 500 | err_id: |
@@ -506,24 +508,22 @@ static int __init dax_init(void) | |||
506 | { | 508 | { |
507 | int rc; | 509 | int rc; |
508 | 510 | ||
509 | rc = register_chrdev(0, "dax", &dax_fops); | 511 | nr_dax = max(nr_dax, 256); |
510 | if (rc < 0) | 512 | rc = alloc_chrdev_region(&dax_devt, 0, nr_dax, "dax"); |
513 | if (rc) | ||
511 | return rc; | 514 | return rc; |
512 | dax_major = rc; | ||
513 | 515 | ||
514 | dax_class = class_create(THIS_MODULE, "dax"); | 516 | dax_class = class_create(THIS_MODULE, "dax"); |
515 | if (IS_ERR(dax_class)) { | 517 | if (IS_ERR(dax_class)) |
516 | unregister_chrdev(dax_major, "dax"); | 518 | unregister_chrdev_region(dax_devt, nr_dax); |
517 | return PTR_ERR(dax_class); | ||
518 | } | ||
519 | 519 | ||
520 | return 0; | 520 | return PTR_ERR_OR_ZERO(dax_class); |
521 | } | 521 | } |
522 | 522 | ||
523 | static void __exit dax_exit(void) | 523 | static void __exit dax_exit(void) |
524 | { | 524 | { |
525 | class_destroy(dax_class); | 525 | class_destroy(dax_class); |
526 | unregister_chrdev(dax_major, "dax"); | 526 | unregister_chrdev_region(dax_devt, nr_dax); |
527 | ida_destroy(&dax_minor_ida); | 527 | ida_destroy(&dax_minor_ida); |
528 | } | 528 | } |
529 | 529 | ||