diff options
-rw-r--r-- | drivers/dax/dax.c | 150 | ||||
-rw-r--r-- | fs/char_dev.c | 1 | ||||
-rw-r--r-- | include/uapi/linux/magic.h | 1 |
3 files changed, 148 insertions, 4 deletions
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 17715773c097..e8b9319aeadb 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c | |||
@@ -13,7 +13,9 @@ | |||
13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/mount.h> | ||
16 | #include <linux/pfn_t.h> | 17 | #include <linux/pfn_t.h> |
18 | #include <linux/hash.h> | ||
17 | #include <linux/cdev.h> | 19 | #include <linux/cdev.h> |
18 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
19 | #include <linux/dax.h> | 21 | #include <linux/dax.h> |
@@ -26,6 +28,9 @@ static struct class *dax_class; | |||
26 | static DEFINE_IDA(dax_minor_ida); | 28 | static DEFINE_IDA(dax_minor_ida); |
27 | static int nr_dax = CONFIG_NR_DEV_DAX; | 29 | static int nr_dax = CONFIG_NR_DEV_DAX; |
28 | module_param(nr_dax, int, S_IRUGO); | 30 | module_param(nr_dax, int, S_IRUGO); |
31 | static struct vfsmount *dax_mnt; | ||
32 | static struct kmem_cache *dax_cache __read_mostly; | ||
33 | static struct super_block *dax_superblock __read_mostly; | ||
29 | MODULE_PARM_DESC(nr_dax, "max number of device-dax instances"); | 34 | MODULE_PARM_DESC(nr_dax, "max number of device-dax instances"); |
30 | 35 | ||
31 | /** | 36 | /** |
@@ -61,6 +66,7 @@ struct dax_region { | |||
61 | */ | 66 | */ |
62 | struct dax_dev { | 67 | struct dax_dev { |
63 | struct dax_region *region; | 68 | struct dax_region *region; |
69 | struct inode *inode; | ||
64 | struct device dev; | 70 | struct device dev; |
65 | struct cdev cdev; | 71 | struct cdev cdev; |
66 | bool alive; | 72 | bool alive; |
@@ -69,6 +75,117 @@ struct dax_dev { | |||
69 | struct resource res[0]; | 75 | struct resource res[0]; |
70 | }; | 76 | }; |
71 | 77 | ||
78 | static struct inode *dax_alloc_inode(struct super_block *sb) | ||
79 | { | ||
80 | return kmem_cache_alloc(dax_cache, GFP_KERNEL); | ||
81 | } | ||
82 | |||
83 | static void dax_i_callback(struct rcu_head *head) | ||
84 | { | ||
85 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
86 | |||
87 | kmem_cache_free(dax_cache, inode); | ||
88 | } | ||
89 | |||
90 | static void dax_destroy_inode(struct inode *inode) | ||
91 | { | ||
92 | call_rcu(&inode->i_rcu, dax_i_callback); | ||
93 | } | ||
94 | |||
95 | static const struct super_operations dax_sops = { | ||
96 | .statfs = simple_statfs, | ||
97 | .alloc_inode = dax_alloc_inode, | ||
98 | .destroy_inode = dax_destroy_inode, | ||
99 | .drop_inode = generic_delete_inode, | ||
100 | }; | ||
101 | |||
102 | static struct dentry *dax_mount(struct file_system_type *fs_type, | ||
103 | int flags, const char *dev_name, void *data) | ||
104 | { | ||
105 | return mount_pseudo(fs_type, "dax:", &dax_sops, NULL, DAXFS_MAGIC); | ||
106 | } | ||
107 | |||
108 | static struct file_system_type dax_type = { | ||
109 | .name = "dax", | ||
110 | .mount = dax_mount, | ||
111 | .kill_sb = kill_anon_super, | ||
112 | }; | ||
113 | |||
114 | static int dax_test(struct inode *inode, void *data) | ||
115 | { | ||
116 | return inode->i_cdev == data; | ||
117 | } | ||
118 | |||
119 | static int dax_set(struct inode *inode, void *data) | ||
120 | { | ||
121 | inode->i_cdev = data; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static struct inode *dax_inode_get(struct cdev *cdev, dev_t devt) | ||
126 | { | ||
127 | struct inode *inode; | ||
128 | |||
129 | inode = iget5_locked(dax_superblock, hash_32(devt + DAXFS_MAGIC, 31), | ||
130 | dax_test, dax_set, cdev); | ||
131 | |||
132 | if (!inode) | ||
133 | return NULL; | ||
134 | |||
135 | if (inode->i_state & I_NEW) { | ||
136 | inode->i_mode = S_IFCHR; | ||
137 | inode->i_flags = S_DAX; | ||
138 | inode->i_rdev = devt; | ||
139 | mapping_set_gfp_mask(&inode->i_data, GFP_USER); | ||
140 | unlock_new_inode(inode); | ||
141 | } | ||
142 | return inode; | ||
143 | } | ||
144 | |||
145 | static void init_once(void *inode) | ||
146 | { | ||
147 | inode_init_once(inode); | ||
148 | } | ||
149 | |||
150 | static int dax_inode_init(void) | ||
151 | { | ||
152 | int rc; | ||
153 | |||
154 | dax_cache = kmem_cache_create("dax_cache", sizeof(struct inode), 0, | ||
155 | (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| | ||
156 | SLAB_MEM_SPREAD|SLAB_ACCOUNT), | ||
157 | init_once); | ||
158 | if (!dax_cache) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | rc = register_filesystem(&dax_type); | ||
162 | if (rc) | ||
163 | goto err_register_fs; | ||
164 | |||
165 | dax_mnt = kern_mount(&dax_type); | ||
166 | if (IS_ERR(dax_mnt)) { | ||
167 | rc = PTR_ERR(dax_mnt); | ||
168 | goto err_mount; | ||
169 | } | ||
170 | dax_superblock = dax_mnt->mnt_sb; | ||
171 | |||
172 | return 0; | ||
173 | |||
174 | err_mount: | ||
175 | unregister_filesystem(&dax_type); | ||
176 | err_register_fs: | ||
177 | kmem_cache_destroy(dax_cache); | ||
178 | |||
179 | return rc; | ||
180 | } | ||
181 | |||
182 | static void dax_inode_exit(void) | ||
183 | { | ||
184 | kern_unmount(dax_mnt); | ||
185 | unregister_filesystem(&dax_type); | ||
186 | kmem_cache_destroy(dax_cache); | ||
187 | } | ||
188 | |||
72 | static void dax_region_free(struct kref *kref) | 189 | static void dax_region_free(struct kref *kref) |
73 | { | 190 | { |
74 | struct dax_region *dax_region; | 191 | struct dax_region *dax_region; |
@@ -379,6 +496,9 @@ static int dax_open(struct inode *inode, struct file *filp) | |||
379 | 496 | ||
380 | dax_dev = container_of(inode->i_cdev, struct dax_dev, cdev); | 497 | dax_dev = container_of(inode->i_cdev, struct dax_dev, cdev); |
381 | dev_dbg(&dax_dev->dev, "%s\n", __func__); | 498 | dev_dbg(&dax_dev->dev, "%s\n", __func__); |
499 | inode->i_mapping = dax_dev->inode->i_mapping; | ||
500 | inode->i_mapping->host = dax_dev->inode; | ||
501 | filp->f_mapping = inode->i_mapping; | ||
382 | filp->private_data = dax_dev; | 502 | filp->private_data = dax_dev; |
383 | inode->i_flags = S_DAX; | 503 | inode->i_flags = S_DAX; |
384 | 504 | ||
@@ -410,6 +530,7 @@ static void dax_dev_release(struct device *dev) | |||
410 | ida_simple_remove(&dax_region->ida, dax_dev->id); | 530 | ida_simple_remove(&dax_region->ida, dax_dev->id); |
411 | ida_simple_remove(&dax_minor_ida, MINOR(dev->devt)); | 531 | ida_simple_remove(&dax_minor_ida, MINOR(dev->devt)); |
412 | dax_region_put(dax_region); | 532 | dax_region_put(dax_region); |
533 | iput(dax_dev->inode); | ||
413 | kfree(dax_dev); | 534 | kfree(dax_dev); |
414 | } | 535 | } |
415 | 536 | ||
@@ -459,6 +580,12 @@ int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res, | |||
459 | goto err_minor; | 580 | goto err_minor; |
460 | } | 581 | } |
461 | 582 | ||
583 | dax_dev->inode = dax_inode_get(&dax_dev->cdev, dev_t); | ||
584 | if (!dax_dev->inode) { | ||
585 | rc = -ENOMEM; | ||
586 | goto err_inode; | ||
587 | } | ||
588 | |||
462 | /* device_initialize() so cdev can reference kobj parent */ | 589 | /* device_initialize() so cdev can reference kobj parent */ |
463 | dev_t = MKDEV(MAJOR(dax_devt), minor); | 590 | dev_t = MKDEV(MAJOR(dax_devt), minor); |
464 | dev = &dax_dev->dev; | 591 | dev = &dax_dev->dev; |
@@ -494,6 +621,8 @@ int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res, | |||
494 | return devm_add_action_or_reset(dax_region->dev, unregister_dax_dev, dev); | 621 | return devm_add_action_or_reset(dax_region->dev, unregister_dax_dev, dev); |
495 | 622 | ||
496 | err_cdev: | 623 | err_cdev: |
624 | iput(dax_dev->inode); | ||
625 | err_inode: | ||
497 | ida_simple_remove(&dax_minor_ida, minor); | 626 | ida_simple_remove(&dax_minor_ida, minor); |
498 | err_minor: | 627 | err_minor: |
499 | ida_simple_remove(&dax_region->ida, dax_dev->id); | 628 | ida_simple_remove(&dax_region->ida, dax_dev->id); |
@@ -508,16 +637,28 @@ static int __init dax_init(void) | |||
508 | { | 637 | { |
509 | int rc; | 638 | int rc; |
510 | 639 | ||
640 | rc = dax_inode_init(); | ||
641 | if (rc) | ||
642 | return rc; | ||
643 | |||
511 | nr_dax = max(nr_dax, 256); | 644 | nr_dax = max(nr_dax, 256); |
512 | rc = alloc_chrdev_region(&dax_devt, 0, nr_dax, "dax"); | 645 | rc = alloc_chrdev_region(&dax_devt, 0, nr_dax, "dax"); |
513 | if (rc) | 646 | if (rc) |
514 | return rc; | 647 | goto err_chrdev; |
515 | 648 | ||
516 | dax_class = class_create(THIS_MODULE, "dax"); | 649 | dax_class = class_create(THIS_MODULE, "dax"); |
517 | if (IS_ERR(dax_class)) | 650 | if (IS_ERR(dax_class)) { |
518 | unregister_chrdev_region(dax_devt, nr_dax); | 651 | rc = PTR_ERR(dax_class); |
652 | goto err_class; | ||
653 | } | ||
519 | 654 | ||
520 | return PTR_ERR_OR_ZERO(dax_class); | 655 | return 0; |
656 | |||
657 | err_class: | ||
658 | unregister_chrdev_region(dax_devt, nr_dax); | ||
659 | err_chrdev: | ||
660 | dax_inode_exit(); | ||
661 | return rc; | ||
521 | } | 662 | } |
522 | 663 | ||
523 | static void __exit dax_exit(void) | 664 | static void __exit dax_exit(void) |
@@ -525,6 +666,7 @@ static void __exit dax_exit(void) | |||
525 | class_destroy(dax_class); | 666 | class_destroy(dax_class); |
526 | unregister_chrdev_region(dax_devt, nr_dax); | 667 | unregister_chrdev_region(dax_devt, nr_dax); |
527 | ida_destroy(&dax_minor_ida); | 668 | ida_destroy(&dax_minor_ida); |
669 | dax_inode_exit(); | ||
528 | } | 670 | } |
529 | 671 | ||
530 | MODULE_AUTHOR("Intel Corporation"); | 672 | MODULE_AUTHOR("Intel Corporation"); |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 6edd825231c5..44a240c4bb65 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -406,6 +406,7 @@ void cd_forget(struct inode *inode) | |||
406 | spin_lock(&cdev_lock); | 406 | spin_lock(&cdev_lock); |
407 | list_del_init(&inode->i_devices); | 407 | list_del_init(&inode->i_devices); |
408 | inode->i_cdev = NULL; | 408 | inode->i_cdev = NULL; |
409 | inode->i_mapping = &inode->i_data; | ||
409 | spin_unlock(&cdev_lock); | 410 | spin_unlock(&cdev_lock); |
410 | } | 411 | } |
411 | 412 | ||
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index e398beac67b8..9bd559472c92 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h | |||
@@ -65,6 +65,7 @@ | |||
65 | #define V9FS_MAGIC 0x01021997 | 65 | #define V9FS_MAGIC 0x01021997 |
66 | 66 | ||
67 | #define BDEVFS_MAGIC 0x62646576 | 67 | #define BDEVFS_MAGIC 0x62646576 |
68 | #define DAXFS_MAGIC 0x64646178 | ||
68 | #define BINFMTFS_MAGIC 0x42494e4d | 69 | #define BINFMTFS_MAGIC 0x42494e4d |
69 | #define DEVPTS_SUPER_MAGIC 0x1cd1 | 70 | #define DEVPTS_SUPER_MAGIC 0x1cd1 |
70 | #define FUTEXFS_SUPER_MAGIC 0xBAD1DEA | 71 | #define FUTEXFS_SUPER_MAGIC 0xBAD1DEA |