]>
Commit | Line | Data |
---|---|---|
5b497af4 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
7b6be844 DW |
2 | /* |
3 | * Copyright(c) 2017 Intel Corporation. All rights reserved. | |
7b6be844 DW |
4 | */ |
5 | #include <linux/pagemap.h> | |
6 | #include <linux/module.h> | |
7 | #include <linux/mount.h> | |
75d4e06f | 8 | #include <linux/pseudo_fs.h> |
7b6be844 | 9 | #include <linux/magic.h> |
569d0365 | 10 | #include <linux/pfn_t.h> |
7b6be844 | 11 | #include <linux/cdev.h> |
7b6be844 | 12 | #include <linux/slab.h> |
7e026c8c | 13 | #include <linux/uio.h> |
6568b08b | 14 | #include <linux/dax.h> |
7b6be844 | 15 | #include <linux/fs.h> |
51cf784c | 16 | #include "dax-private.h" |
7b6be844 | 17 | |
1b764601 CH |
18 | /** |
19 | * struct dax_device - anchor object for dax services | |
20 | * @inode: core vfs | |
21 | * @cdev: optional character interface for "device dax" | |
1b764601 CH |
22 | * @private: dax driver private data |
23 | * @flags: state and boolean properties | |
db8cd5ef | 24 | * @ops: operations for this device |
8012b866 SR |
25 | * @holder_data: holder of a dax_device: could be filesystem or mapped device |
26 | * @holder_ops: operations for the inner holder | |
1b764601 CH |
27 | */ |
28 | struct dax_device { | |
1b764601 CH |
29 | struct inode inode; |
30 | struct cdev cdev; | |
1b764601 CH |
31 | void *private; |
32 | unsigned long flags; | |
33 | const struct dax_operations *ops; | |
8012b866 SR |
34 | void *holder_data; |
35 | const struct dax_holder_operations *holder_ops; | |
1b764601 CH |
36 | }; |
37 | ||
7b6be844 DW |
38 | static dev_t dax_devt; |
39 | DEFINE_STATIC_SRCU(dax_srcu); | |
40 | static struct vfsmount *dax_mnt; | |
41 | static DEFINE_IDA(dax_minor_ida); | |
42 | static struct kmem_cache *dax_cache __read_mostly; | |
43 | static struct super_block *dax_superblock __read_mostly; | |
44 | ||
45 | int dax_read_lock(void) | |
46 | { | |
47 | return srcu_read_lock(&dax_srcu); | |
48 | } | |
49 | EXPORT_SYMBOL_GPL(dax_read_lock); | |
50 | ||
51 | void dax_read_unlock(int id) | |
52 | { | |
53 | srcu_read_unlock(&dax_srcu, id); | |
54 | } | |
55 | EXPORT_SYMBOL_GPL(dax_read_unlock); | |
56 | ||
fb08a190 CH |
57 | #if defined(CONFIG_BLOCK) && defined(CONFIG_FS_DAX) |
58 | #include <linux/blkdev.h> | |
59 | ||
60 | static DEFINE_XARRAY(dax_hosts); | |
61 | ||
62 | int dax_add_host(struct dax_device *dax_dev, struct gendisk *disk) | |
1b764601 | 63 | { |
fb08a190 | 64 | return xa_insert(&dax_hosts, (unsigned long)disk, dax_dev, GFP_KERNEL); |
1b764601 | 65 | } |
fb08a190 | 66 | EXPORT_SYMBOL_GPL(dax_add_host); |
1b764601 | 67 | |
fb08a190 CH |
68 | void dax_remove_host(struct gendisk *disk) |
69 | { | |
70 | xa_erase(&dax_hosts, (unsigned long)disk); | |
71 | } | |
72 | EXPORT_SYMBOL_GPL(dax_remove_host); | |
e765f13e | 73 | |
1b764601 | 74 | /** |
fb08a190 CH |
75 | * fs_dax_get_by_bdev() - temporary lookup mechanism for filesystem-dax |
76 | * @bdev: block device to find a dax_device for | |
cd913c76 | 77 | * @start_off: returns the byte offset into the dax_device that @bdev starts |
8012b866 SR |
78 | * @holder: filesystem or mapped device inside the dax_device |
79 | * @ops: operations for the inner holder | |
1b764601 | 80 | */ |
8012b866 SR |
81 | struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev, u64 *start_off, |
82 | void *holder, const struct dax_holder_operations *ops) | |
1b764601 | 83 | { |
fb08a190 | 84 | struct dax_device *dax_dev; |
cd913c76 | 85 | u64 part_size; |
fb08a190 | 86 | int id; |
1b764601 | 87 | |
fb08a190 | 88 | if (!blk_queue_dax(bdev->bd_disk->queue)) |
1b764601 CH |
89 | return NULL; |
90 | ||
cd913c76 CH |
91 | *start_off = get_start_sect(bdev) * SECTOR_SIZE; |
92 | part_size = bdev_nr_sectors(bdev) * SECTOR_SIZE; | |
93 | if (*start_off % PAGE_SIZE || part_size % PAGE_SIZE) { | |
0c445871 CH |
94 | pr_info("%pg: error: unaligned partition for dax\n", bdev); |
95 | return NULL; | |
96 | } | |
97 | ||
1b764601 | 98 | id = dax_read_lock(); |
fb08a190 CH |
99 | dax_dev = xa_load(&dax_hosts, (unsigned long)bdev->bd_disk); |
100 | if (!dax_dev || !dax_alive(dax_dev) || !igrab(&dax_dev->inode)) | |
101 | dax_dev = NULL; | |
8012b866 SR |
102 | else if (holder) { |
103 | if (!cmpxchg(&dax_dev->holder_data, NULL, holder)) | |
104 | dax_dev->holder_ops = ops; | |
105 | else | |
106 | dax_dev = NULL; | |
107 | } | |
1b764601 CH |
108 | dax_read_unlock(id); |
109 | ||
fb08a190 | 110 | return dax_dev; |
78f35473 DW |
111 | } |
112 | EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev); | |
8012b866 SR |
113 | |
114 | void fs_put_dax(struct dax_device *dax_dev, void *holder) | |
115 | { | |
116 | if (dax_dev && holder && | |
117 | cmpxchg(&dax_dev->holder_data, holder, NULL) == holder) | |
118 | dax_dev->holder_ops = NULL; | |
119 | put_dax(dax_dev); | |
120 | } | |
121 | EXPORT_SYMBOL_GPL(fs_put_dax); | |
5d2a228b | 122 | #endif /* CONFIG_BLOCK && CONFIG_FS_DAX */ |
ef510424 | 123 | |
9a60c3ef DW |
124 | enum dax_device_flags { |
125 | /* !alive + rcu grace period == no new operations / mappings */ | |
126 | DAXDEV_ALIVE, | |
6e0c90d6 DW |
127 | /* gate whether dax_flush() calls the low level flush routine */ |
128 | DAXDEV_WRITE_CACHE, | |
fefc1d97 PG |
129 | /* flag to check if device supports synchronous flush */ |
130 | DAXDEV_SYNC, | |
7ac5360c CH |
131 | /* do not leave the caches dirty after writes */ |
132 | DAXDEV_NOCACHE, | |
133 | /* handle CPU fetch exceptions during reads */ | |
134 | DAXDEV_NOMC, | |
9a60c3ef DW |
135 | }; |
136 | ||
b0686260 DW |
137 | /** |
138 | * dax_direct_access() - translate a device pgoff to an absolute pfn | |
139 | * @dax_dev: a dax_device instance representing the logical memory range | |
140 | * @pgoff: offset in pages from the start of the device to translate | |
141 | * @nr_pages: number of consecutive pages caller can handle relative to @pfn | |
e511c4a3 | 142 | * @mode: indicator on normal access or recovery write |
b0686260 DW |
143 | * @kaddr: output parameter that returns a virtual address mapping of pfn |
144 | * @pfn: output parameter that returns an absolute pfn translation of @pgoff | |
145 | * | |
146 | * Return: negative errno if an error occurs, otherwise the number of | |
147 | * pages accessible at the device relative @pgoff. | |
148 | */ | |
149 | long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, | |
e511c4a3 | 150 | enum dax_access_mode mode, void **kaddr, pfn_t *pfn) |
b0686260 DW |
151 | { |
152 | long avail; | |
153 | ||
b0686260 DW |
154 | if (!dax_dev) |
155 | return -EOPNOTSUPP; | |
156 | ||
157 | if (!dax_alive(dax_dev)) | |
158 | return -ENXIO; | |
159 | ||
160 | if (nr_pages < 0) | |
b05d4c57 | 161 | return -EINVAL; |
b0686260 DW |
162 | |
163 | avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages, | |
e511c4a3 | 164 | mode, kaddr, pfn); |
b0686260 DW |
165 | if (!avail) |
166 | return -ERANGE; | |
167 | return min(avail, nr_pages); | |
168 | } | |
169 | EXPORT_SYMBOL_GPL(dax_direct_access); | |
170 | ||
7e026c8c DW |
171 | size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, |
172 | size_t bytes, struct iov_iter *i) | |
173 | { | |
174 | if (!dax_alive(dax_dev)) | |
175 | return 0; | |
176 | ||
7ac5360c CH |
177 | /* |
178 | * The userspace address for the memory copy has already been validated | |
179 | * via access_ok() in vfs_write, so use the 'no check' version to bypass | |
180 | * the HARDENED_USERCOPY overhead. | |
181 | */ | |
182 | if (test_bit(DAXDEV_NOCACHE, &dax_dev->flags)) | |
183 | return _copy_from_iter_flushcache(addr, bytes, i); | |
184 | return _copy_from_iter(addr, bytes, i); | |
7e026c8c | 185 | } |
7e026c8c | 186 | |
b3a9a0c3 DW |
187 | size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, |
188 | size_t bytes, struct iov_iter *i) | |
189 | { | |
190 | if (!dax_alive(dax_dev)) | |
191 | return 0; | |
192 | ||
7ac5360c CH |
193 | /* |
194 | * The userspace address for the memory copy has already been validated | |
195 | * via access_ok() in vfs_red, so use the 'no check' version to bypass | |
196 | * the HARDENED_USERCOPY overhead. | |
197 | */ | |
198 | if (test_bit(DAXDEV_NOMC, &dax_dev->flags)) | |
199 | return _copy_mc_to_iter(addr, bytes, i); | |
200 | return _copy_to_iter(addr, bytes, i); | |
b3a9a0c3 | 201 | } |
b3a9a0c3 | 202 | |
f605a263 VG |
203 | int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, |
204 | size_t nr_pages) | |
205 | { | |
1ea7ca1b JC |
206 | int ret; |
207 | ||
f605a263 VG |
208 | if (!dax_alive(dax_dev)) |
209 | return -ENXIO; | |
f605a263 VG |
210 | /* |
211 | * There are no callers that want to zero more than one page as of now. | |
212 | * Once users are there, this check can be removed after the | |
213 | * device mapper code has been updated to split ranges across targets. | |
214 | */ | |
215 | if (nr_pages != 1) | |
216 | return -EIO; | |
217 | ||
1ea7ca1b JC |
218 | ret = dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages); |
219 | return dax_mem2blk_err(ret); | |
f605a263 VG |
220 | } |
221 | EXPORT_SYMBOL_GPL(dax_zero_page_range); | |
222 | ||
047218ec JC |
223 | size_t dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff, |
224 | void *addr, size_t bytes, struct iov_iter *iter) | |
225 | { | |
226 | if (!dax_dev->ops->recovery_write) | |
227 | return 0; | |
228 | return dax_dev->ops->recovery_write(dax_dev, pgoff, addr, bytes, iter); | |
229 | } | |
230 | EXPORT_SYMBOL_GPL(dax_recovery_write); | |
231 | ||
8012b866 SR |
232 | int dax_holder_notify_failure(struct dax_device *dax_dev, u64 off, |
233 | u64 len, int mf_flags) | |
234 | { | |
235 | int rc, id; | |
236 | ||
237 | id = dax_read_lock(); | |
238 | if (!dax_alive(dax_dev)) { | |
239 | rc = -ENXIO; | |
240 | goto out; | |
241 | } | |
242 | ||
243 | if (!dax_dev->holder_ops) { | |
244 | rc = -EOPNOTSUPP; | |
245 | goto out; | |
246 | } | |
247 | ||
248 | rc = dax_dev->holder_ops->notify_failure(dax_dev, off, len, mf_flags); | |
249 | out: | |
250 | dax_read_unlock(id); | |
251 | return rc; | |
252 | } | |
253 | EXPORT_SYMBOL_GPL(dax_holder_notify_failure); | |
254 | ||
c3ca015f MP |
255 | #ifdef CONFIG_ARCH_HAS_PMEM_API |
256 | void arch_wb_cache_pmem(void *addr, size_t size); | |
257 | void dax_flush(struct dax_device *dax_dev, void *addr, size_t size) | |
abebfbe2 | 258 | { |
808c340b | 259 | if (unlikely(!dax_write_cache_enabled(dax_dev))) |
6e0c90d6 DW |
260 | return; |
261 | ||
c3ca015f | 262 | arch_wb_cache_pmem(addr, size); |
abebfbe2 | 263 | } |
c3ca015f MP |
264 | #else |
265 | void dax_flush(struct dax_device *dax_dev, void *addr, size_t size) | |
266 | { | |
267 | } | |
268 | #endif | |
abebfbe2 DW |
269 | EXPORT_SYMBOL_GPL(dax_flush); |
270 | ||
6e0c90d6 DW |
271 | void dax_write_cache(struct dax_device *dax_dev, bool wc) |
272 | { | |
273 | if (wc) | |
274 | set_bit(DAXDEV_WRITE_CACHE, &dax_dev->flags); | |
275 | else | |
276 | clear_bit(DAXDEV_WRITE_CACHE, &dax_dev->flags); | |
277 | } | |
278 | EXPORT_SYMBOL_GPL(dax_write_cache); | |
279 | ||
273752c9 VG |
280 | bool dax_write_cache_enabled(struct dax_device *dax_dev) |
281 | { | |
282 | return test_bit(DAXDEV_WRITE_CACHE, &dax_dev->flags); | |
283 | } | |
284 | EXPORT_SYMBOL_GPL(dax_write_cache_enabled); | |
285 | ||
fd1d00ec | 286 | bool dax_synchronous(struct dax_device *dax_dev) |
fefc1d97 PG |
287 | { |
288 | return test_bit(DAXDEV_SYNC, &dax_dev->flags); | |
289 | } | |
fd1d00ec | 290 | EXPORT_SYMBOL_GPL(dax_synchronous); |
fefc1d97 | 291 | |
fd1d00ec | 292 | void set_dax_synchronous(struct dax_device *dax_dev) |
fefc1d97 PG |
293 | { |
294 | set_bit(DAXDEV_SYNC, &dax_dev->flags); | |
295 | } | |
fd1d00ec | 296 | EXPORT_SYMBOL_GPL(set_dax_synchronous); |
fefc1d97 | 297 | |
7ac5360c CH |
298 | void set_dax_nocache(struct dax_device *dax_dev) |
299 | { | |
300 | set_bit(DAXDEV_NOCACHE, &dax_dev->flags); | |
301 | } | |
302 | EXPORT_SYMBOL_GPL(set_dax_nocache); | |
303 | ||
304 | void set_dax_nomc(struct dax_device *dax_dev) | |
305 | { | |
306 | set_bit(DAXDEV_NOMC, &dax_dev->flags); | |
307 | } | |
308 | EXPORT_SYMBOL_GPL(set_dax_nomc); | |
309 | ||
7b6be844 DW |
310 | bool dax_alive(struct dax_device *dax_dev) |
311 | { | |
312 | lockdep_assert_held(&dax_srcu); | |
9a60c3ef | 313 | return test_bit(DAXDEV_ALIVE, &dax_dev->flags); |
7b6be844 DW |
314 | } |
315 | EXPORT_SYMBOL_GPL(dax_alive); | |
316 | ||
317 | /* | |
318 | * Note, rcu is not protecting the liveness of dax_dev, rcu is ensuring | |
319 | * that any fault handlers or operations that might have seen | |
320 | * dax_alive(), have completed. Any operations that start after | |
321 | * synchronize_srcu() has run will abort upon seeing !dax_alive(). | |
322 | */ | |
323 | void kill_dax(struct dax_device *dax_dev) | |
324 | { | |
325 | if (!dax_dev) | |
326 | return; | |
327 | ||
8012b866 | 328 | if (dax_dev->holder_data != NULL) |
fa422b35 SR |
329 | dax_holder_notify_failure(dax_dev, 0, U64_MAX, |
330 | MF_MEM_PRE_REMOVE); | |
8012b866 | 331 | |
9a60c3ef | 332 | clear_bit(DAXDEV_ALIVE, &dax_dev->flags); |
7b6be844 | 333 | synchronize_srcu(&dax_srcu); |
8012b866 SR |
334 | |
335 | /* clear holder data */ | |
336 | dax_dev->holder_ops = NULL; | |
337 | dax_dev->holder_data = NULL; | |
7b6be844 DW |
338 | } |
339 | EXPORT_SYMBOL_GPL(kill_dax); | |
340 | ||
9567da0b DW |
341 | void run_dax(struct dax_device *dax_dev) |
342 | { | |
343 | set_bit(DAXDEV_ALIVE, &dax_dev->flags); | |
344 | } | |
345 | EXPORT_SYMBOL_GPL(run_dax); | |
346 | ||
7b6be844 DW |
347 | static struct inode *dax_alloc_inode(struct super_block *sb) |
348 | { | |
349 | struct dax_device *dax_dev; | |
b9d39d17 | 350 | struct inode *inode; |
7b6be844 | 351 | |
fd60b288 | 352 | dax_dev = alloc_inode_sb(sb, dax_cache, GFP_KERNEL); |
9f586fff MP |
353 | if (!dax_dev) |
354 | return NULL; | |
355 | ||
b9d39d17 DW |
356 | inode = &dax_dev->inode; |
357 | inode->i_rdev = 0; | |
358 | return inode; | |
7b6be844 DW |
359 | } |
360 | ||
361 | static struct dax_device *to_dax_dev(struct inode *inode) | |
362 | { | |
363 | return container_of(inode, struct dax_device, inode); | |
364 | } | |
365 | ||
53e22829 | 366 | static void dax_free_inode(struct inode *inode) |
7b6be844 | 367 | { |
7b6be844 | 368 | struct dax_device *dax_dev = to_dax_dev(inode); |
b9d39d17 | 369 | if (inode->i_rdev) |
0f702033 | 370 | ida_free(&dax_minor_ida, iminor(inode)); |
7b6be844 DW |
371 | kmem_cache_free(dax_cache, dax_dev); |
372 | } | |
373 | ||
374 | static void dax_destroy_inode(struct inode *inode) | |
375 | { | |
376 | struct dax_device *dax_dev = to_dax_dev(inode); | |
9a60c3ef | 377 | WARN_ONCE(test_bit(DAXDEV_ALIVE, &dax_dev->flags), |
7b6be844 | 378 | "kill_dax() must be called before final iput()\n"); |
7b6be844 DW |
379 | } |
380 | ||
381 | static const struct super_operations dax_sops = { | |
382 | .statfs = simple_statfs, | |
383 | .alloc_inode = dax_alloc_inode, | |
384 | .destroy_inode = dax_destroy_inode, | |
53e22829 | 385 | .free_inode = dax_free_inode, |
7b6be844 DW |
386 | .drop_inode = generic_delete_inode, |
387 | }; | |
388 | ||
75d4e06f | 389 | static int dax_init_fs_context(struct fs_context *fc) |
7b6be844 | 390 | { |
75d4e06f DH |
391 | struct pseudo_fs_context *ctx = init_pseudo(fc, DAXFS_MAGIC); |
392 | if (!ctx) | |
393 | return -ENOMEM; | |
394 | ctx->ops = &dax_sops; | |
395 | return 0; | |
7b6be844 DW |
396 | } |
397 | ||
398 | static struct file_system_type dax_fs_type = { | |
75d4e06f DH |
399 | .name = "dax", |
400 | .init_fs_context = dax_init_fs_context, | |
401 | .kill_sb = kill_anon_super, | |
7b6be844 DW |
402 | }; |
403 | ||
404 | static int dax_test(struct inode *inode, void *data) | |
405 | { | |
406 | dev_t devt = *(dev_t *) data; | |
407 | ||
408 | return inode->i_rdev == devt; | |
409 | } | |
410 | ||
411 | static int dax_set(struct inode *inode, void *data) | |
412 | { | |
413 | dev_t devt = *(dev_t *) data; | |
414 | ||
415 | inode->i_rdev = devt; | |
416 | return 0; | |
417 | } | |
418 | ||
419 | static struct dax_device *dax_dev_get(dev_t devt) | |
420 | { | |
421 | struct dax_device *dax_dev; | |
422 | struct inode *inode; | |
423 | ||
424 | inode = iget5_locked(dax_superblock, hash_32(devt + DAXFS_MAGIC, 31), | |
425 | dax_test, dax_set, &devt); | |
426 | ||
427 | if (!inode) | |
428 | return NULL; | |
429 | ||
430 | dax_dev = to_dax_dev(inode); | |
431 | if (inode->i_state & I_NEW) { | |
9a60c3ef | 432 | set_bit(DAXDEV_ALIVE, &dax_dev->flags); |
7b6be844 DW |
433 | inode->i_cdev = &dax_dev->cdev; |
434 | inode->i_mode = S_IFCHR; | |
435 | inode->i_flags = S_DAX; | |
436 | mapping_set_gfp_mask(&inode->i_data, GFP_USER); | |
437 | unlock_new_inode(inode); | |
438 | } | |
439 | ||
440 | return dax_dev; | |
441 | } | |
442 | ||
30c6828a | 443 | struct dax_device *alloc_dax(void *private, const struct dax_operations *ops) |
7b6be844 DW |
444 | { |
445 | struct dax_device *dax_dev; | |
446 | dev_t devt; | |
447 | int minor; | |
448 | ||
fb08a190 | 449 | if (WARN_ON_ONCE(ops && !ops->zero_page_range)) |
4e4ced93 | 450 | return ERR_PTR(-EINVAL); |
72058005 | 451 | |
0f702033 | 452 | minor = ida_alloc_max(&dax_minor_ida, MINORMASK, GFP_KERNEL); |
7b6be844 | 453 | if (minor < 0) |
fb08a190 | 454 | return ERR_PTR(-ENOMEM); |
7b6be844 DW |
455 | |
456 | devt = MKDEV(MAJOR(dax_devt), minor); | |
457 | dax_dev = dax_dev_get(devt); | |
458 | if (!dax_dev) | |
72058005 | 459 | goto err_dev; |
7b6be844 | 460 | |
6568b08b | 461 | dax_dev->ops = ops; |
7b6be844 DW |
462 | dax_dev->private = private; |
463 | return dax_dev; | |
464 | ||
72058005 | 465 | err_dev: |
0f702033 | 466 | ida_free(&dax_minor_ida, minor); |
4e4ced93 | 467 | return ERR_PTR(-ENOMEM); |
7b6be844 DW |
468 | } |
469 | EXPORT_SYMBOL_GPL(alloc_dax); | |
470 | ||
471 | void put_dax(struct dax_device *dax_dev) | |
472 | { | |
473 | if (!dax_dev) | |
474 | return; | |
475 | iput(&dax_dev->inode); | |
476 | } | |
477 | EXPORT_SYMBOL_GPL(put_dax); | |
478 | ||
8012b866 SR |
479 | /** |
480 | * dax_holder() - obtain the holder of a dax device | |
481 | * @dax_dev: a dax_device instance | |
1c88b9ba | 482 | * |
8012b866 SR |
483 | * Return: the holder's data which represents the holder if registered, |
484 | * otherwize NULL. | |
485 | */ | |
486 | void *dax_holder(struct dax_device *dax_dev) | |
487 | { | |
488 | return dax_dev->holder_data; | |
489 | } | |
490 | EXPORT_SYMBOL_GPL(dax_holder); | |
491 | ||
7b6be844 DW |
492 | /** |
493 | * inode_dax: convert a public inode into its dax_dev | |
494 | * @inode: An inode with i_cdev pointing to a dax_dev | |
495 | * | |
496 | * Note this is not equivalent to to_dax_dev() which is for private | |
497 | * internal use where we know the inode filesystem type == dax_fs_type. | |
498 | */ | |
499 | struct dax_device *inode_dax(struct inode *inode) | |
500 | { | |
501 | struct cdev *cdev = inode->i_cdev; | |
502 | ||
503 | return container_of(cdev, struct dax_device, cdev); | |
504 | } | |
505 | EXPORT_SYMBOL_GPL(inode_dax); | |
506 | ||
507 | struct inode *dax_inode(struct dax_device *dax_dev) | |
508 | { | |
509 | return &dax_dev->inode; | |
510 | } | |
511 | EXPORT_SYMBOL_GPL(dax_inode); | |
512 | ||
513 | void *dax_get_private(struct dax_device *dax_dev) | |
514 | { | |
9567da0b DW |
515 | if (!test_bit(DAXDEV_ALIVE, &dax_dev->flags)) |
516 | return NULL; | |
7b6be844 DW |
517 | return dax_dev->private; |
518 | } | |
519 | EXPORT_SYMBOL_GPL(dax_get_private); | |
520 | ||
521 | static void init_once(void *_dax_dev) | |
522 | { | |
523 | struct dax_device *dax_dev = _dax_dev; | |
524 | struct inode *inode = &dax_dev->inode; | |
525 | ||
b9d39d17 | 526 | memset(dax_dev, 0, sizeof(*dax_dev)); |
7b6be844 DW |
527 | inode_init_once(inode); |
528 | } | |
529 | ||
9567da0b | 530 | static int dax_fs_init(void) |
7b6be844 DW |
531 | { |
532 | int rc; | |
533 | ||
534 | dax_cache = kmem_cache_create("dax_cache", sizeof(struct dax_device), 0, | |
535 | (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| | |
536 | SLAB_MEM_SPREAD|SLAB_ACCOUNT), | |
537 | init_once); | |
538 | if (!dax_cache) | |
539 | return -ENOMEM; | |
540 | ||
7b6be844 DW |
541 | dax_mnt = kern_mount(&dax_fs_type); |
542 | if (IS_ERR(dax_mnt)) { | |
543 | rc = PTR_ERR(dax_mnt); | |
544 | goto err_mount; | |
545 | } | |
546 | dax_superblock = dax_mnt->mnt_sb; | |
547 | ||
548 | return 0; | |
549 | ||
550 | err_mount: | |
7b6be844 DW |
551 | kmem_cache_destroy(dax_cache); |
552 | ||
553 | return rc; | |
554 | } | |
555 | ||
9567da0b | 556 | static void dax_fs_exit(void) |
7b6be844 DW |
557 | { |
558 | kern_unmount(dax_mnt); | |
a7e8de82 | 559 | rcu_barrier(); |
7b6be844 DW |
560 | kmem_cache_destroy(dax_cache); |
561 | } | |
562 | ||
9567da0b | 563 | static int __init dax_core_init(void) |
7b6be844 DW |
564 | { |
565 | int rc; | |
566 | ||
9567da0b | 567 | rc = dax_fs_init(); |
7b6be844 DW |
568 | if (rc) |
569 | return rc; | |
570 | ||
cf1e2289 | 571 | rc = alloc_chrdev_region(&dax_devt, 0, MINORMASK+1, "dax"); |
7b6be844 | 572 | if (rc) |
9567da0b DW |
573 | goto err_chrdev; |
574 | ||
575 | rc = dax_bus_init(); | |
576 | if (rc) | |
577 | goto err_bus; | |
578 | return 0; | |
579 | ||
580 | err_bus: | |
581 | unregister_chrdev_region(dax_devt, MINORMASK+1); | |
582 | err_chrdev: | |
583 | dax_fs_exit(); | |
584 | return 0; | |
7b6be844 DW |
585 | } |
586 | ||
9567da0b | 587 | static void __exit dax_core_exit(void) |
7b6be844 | 588 | { |
1aa57431 | 589 | dax_bus_exit(); |
cf1e2289 | 590 | unregister_chrdev_region(dax_devt, MINORMASK+1); |
7b6be844 | 591 | ida_destroy(&dax_minor_ida); |
9567da0b | 592 | dax_fs_exit(); |
7b6be844 DW |
593 | } |
594 | ||
595 | MODULE_AUTHOR("Intel Corporation"); | |
596 | MODULE_LICENSE("GPL v2"); | |
9567da0b DW |
597 | subsys_initcall(dax_core_init); |
598 | module_exit(dax_core_exit); |