Skip to content

Commit 730926c

Browse files
committed
device-dax: Add /sys/class/dax backwards compatibility
On the expectation that some environments may not upgrade libdaxctl (userspace component that depends on the /sys/class/dax hierarchy), provide a default / legacy dax_pmem_compat driver. The dax_pmem_compat driver implements the original /sys/class/dax sysfs layout rather than /sys/bus/dax. When userspace is upgraded it can blacklist this module and switch to the dax_pmem driver going forward. CONFIG_DEV_DAX_PMEM_COMPAT and supporting code will be deleted according to the dax_pmem entry in Documentation/ABI/obsolete/. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent d200781 commit 730926c

File tree

11 files changed

+229
-50
lines changed

11 files changed

+229
-50
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
What: /sys/class/dax/
2+
Date: May, 2016
3+
KernelVersion: v4.7
4+
Contact: linux-nvdimm@lists.01.org
5+
Description: Device DAX is the device-centric analogue of Filesystem
6+
DAX (CONFIG_FS_DAX). It allows memory ranges to be
7+
allocated and mapped without need of an intervening file
8+
system. Device DAX is strict, precise and predictable.
9+
Specifically this interface:
10+
11+
1/ Guarantees fault granularity with respect to a given
12+
page size (pte, pmd, or pud) set at configuration time.
13+
14+
2/ Enforces deterministic behavior by being strict about
15+
what fault scenarios are supported.
16+
17+
The /sys/class/dax/ interface enumerates all the
18+
device-dax instances in the system. The ABI is
19+
deprecated and will be removed after 2020. It is
20+
replaced with the DAX bus interface /sys/bus/dax/ where
21+
device-dax instances can be found under
22+
/sys/bus/dax/devices/

drivers/dax/Kconfig

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,22 @@ config DEV_DAX
2323
config DEV_DAX_PMEM
2424
tristate "PMEM DAX: direct access to persistent memory"
2525
depends on LIBNVDIMM && NVDIMM_DAX && DEV_DAX
26+
depends on m # until we can kill DEV_DAX_PMEM_COMPAT
2627
default DEV_DAX
2728
help
2829
Support raw access to persistent memory. Note that this
2930
driver consumes memory ranges allocated and exported by the
3031
libnvdimm sub-system.
3132

32-
Say Y if unsure
33+
Say M if unsure
34+
35+
config DEV_DAX_PMEM_COMPAT
36+
tristate "PMEM DAX: support the deprecated /sys/class/dax interface"
37+
depends on DEV_DAX_PMEM
38+
default DEV_DAX_PMEM
39+
help
40+
Older versions of the libdaxctl library expect to find all
41+
device-dax instances under /sys/class/dax. If libdaxctl in
42+
your distribution is older than v58 say M, otherwise say N.
3343

3444
endif

drivers/dax/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_DAX) += dax.o
33
obj-$(CONFIG_DEV_DAX) += device_dax.o
4-
obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
54

65
dax-y := super.o
76
dax-y += bus.o
8-
dax_pmem-y := pmem.o
97
device_dax-y := device.o
8+
9+
obj-y += pmem/

drivers/dax/bus.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "dax-private.h"
1010
#include "bus.h"
1111

12+
static struct class *dax_class;
13+
1214
static DEFINE_MUTEX(dax_bus_lock);
1315

1416
#define DAX_NAME_LEN 30
@@ -310,8 +312,8 @@ static void unregister_dev_dax(void *dev)
310312
put_device(dev);
311313
}
312314

313-
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
314-
struct dev_pagemap *pgmap)
315+
struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
316+
struct dev_pagemap *pgmap, enum dev_dax_subsys subsys)
315317
{
316318
struct device *parent = dax_region->dev;
317319
struct dax_device *dax_dev;
@@ -350,7 +352,10 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
350352

351353
inode = dax_inode(dax_dev);
352354
dev->devt = inode->i_rdev;
353-
dev->bus = &dax_bus_type;
355+
if (subsys == DEV_DAX_BUS)
356+
dev->bus = &dax_bus_type;
357+
else
358+
dev->class = dax_class;
354359
dev->parent = parent;
355360
dev->groups = dax_attribute_groups;
356361
dev->release = dev_dax_release;
@@ -374,7 +379,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
374379

375380
return ERR_PTR(rc);
376381
}
377-
EXPORT_SYMBOL_GPL(devm_create_dev_dax);
382+
EXPORT_SYMBOL_GPL(__devm_create_dev_dax);
378383

379384
static int match_always_count;
380385

@@ -407,6 +412,7 @@ EXPORT_SYMBOL_GPL(__dax_driver_register);
407412

408413
void dax_driver_unregister(struct dax_device_driver *dax_drv)
409414
{
415+
struct device_driver *drv = &dax_drv->drv;
410416
struct dax_id *dax_id, *_id;
411417

412418
mutex_lock(&dax_bus_lock);
@@ -416,15 +422,28 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv)
416422
kfree(dax_id);
417423
}
418424
mutex_unlock(&dax_bus_lock);
425+
driver_unregister(drv);
419426
}
420427
EXPORT_SYMBOL_GPL(dax_driver_unregister);
421428

422429
int __init dax_bus_init(void)
423430
{
424-
return bus_register(&dax_bus_type);
431+
int rc;
432+
433+
if (IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)) {
434+
dax_class = class_create(THIS_MODULE, "dax");
435+
if (IS_ERR(dax_class))
436+
return PTR_ERR(dax_class);
437+
}
438+
439+
rc = bus_register(&dax_bus_type);
440+
if (rc)
441+
class_destroy(dax_class);
442+
return rc;
425443
}
426444

427445
void __exit dax_bus_exit(void)
428446
{
429447
bus_unregister(&dax_bus_type);
448+
class_destroy(dax_class);
430449
}

drivers/dax/bus.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,32 @@
22
/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
33
#ifndef __DAX_BUS_H__
44
#define __DAX_BUS_H__
5-
struct device;
5+
#include <linux/device.h>
6+
67
struct dev_dax;
78
struct resource;
89
struct dax_device;
910
struct dax_region;
1011
void dax_region_put(struct dax_region *dax_region);
1112
struct dax_region *alloc_dax_region(struct device *parent, int region_id,
1213
struct resource *res, unsigned int align, unsigned long flags);
13-
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
14-
struct dev_pagemap *pgmap);
14+
15+
enum dev_dax_subsys {
16+
DEV_DAX_BUS,
17+
DEV_DAX_CLASS,
18+
};
19+
20+
struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
21+
struct dev_pagemap *pgmap, enum dev_dax_subsys subsys);
22+
23+
static inline struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
24+
int id, struct dev_pagemap *pgmap)
25+
{
26+
return __devm_create_dev_dax(dax_region, id, pgmap, DEV_DAX_BUS);
27+
}
28+
29+
/* to be deleted when DEV_DAX_CLASS is removed */
30+
struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys);
1531

1632
struct dax_device_driver {
1733
struct device_driver drv;
@@ -26,6 +42,10 @@ int __dax_driver_register(struct dax_device_driver *dax_drv,
2642
void dax_driver_unregister(struct dax_device_driver *dax_drv);
2743
void kill_dev_dax(struct dev_dax *dev_dax);
2844

45+
#if IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)
46+
int dev_dax_probe(struct device *dev);
47+
#endif
48+
2949
/*
3050
* While run_dax() is potentially a generic operation that could be
3151
* defined in include/linux/dax.h we don't want to grow any users

drivers/dax/device.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ static void dev_dax_kill(void *dev_dax)
445445
kill_dev_dax(dev_dax);
446446
}
447447

448-
static int dev_dax_probe(struct device *dev)
448+
int dev_dax_probe(struct device *dev)
449449
{
450450
struct dev_dax *dev_dax = to_dev_dax(dev);
451451
struct dax_device *dax_dev = dev_dax->dax_dev;
@@ -484,7 +484,11 @@ static int dev_dax_probe(struct device *dev)
484484
inode = dax_inode(dax_dev);
485485
cdev = inode->i_cdev;
486486
cdev_init(cdev, &dax_fops);
487-
cdev->owner = dev->driver->owner;
487+
if (dev->class) {
488+
/* for the CONFIG_DEV_DAX_PMEM_COMPAT case */
489+
cdev->owner = dev->parent->driver->owner;
490+
} else
491+
cdev->owner = dev->driver->owner;
488492
cdev_set_parent(cdev, &dev->kobj);
489493
rc = cdev_add(cdev, dev->devt, 1);
490494
if (rc)
@@ -497,6 +501,7 @@ static int dev_dax_probe(struct device *dev)
497501
run_dax(dax_dev);
498502
return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
499503
}
504+
EXPORT_SYMBOL_GPL(dev_dax_probe);
500505

501506
static int dev_dax_remove(struct device *dev)
502507
{

drivers/dax/pmem/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
2+
obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem_core.o
3+
obj-$(CONFIG_DEV_DAX_PMEM_COMPAT) += dax_pmem_compat.o
4+
5+
dax_pmem-y := pmem.o
6+
dax_pmem_core-y := core.o
7+
dax_pmem_compat-y := compat.o

drivers/dax/pmem/compat.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
3+
#include <linux/percpu-refcount.h>
4+
#include <linux/memremap.h>
5+
#include <linux/module.h>
6+
#include <linux/pfn_t.h>
7+
#include <linux/nd.h>
8+
#include "../bus.h"
9+
10+
/* we need the private definitions to implement compat suport */
11+
#include "../dax-private.h"
12+
13+
static int dax_pmem_compat_probe(struct device *dev)
14+
{
15+
struct dev_dax *dev_dax = __dax_pmem_probe(dev, DEV_DAX_CLASS);
16+
int rc;
17+
18+
if (IS_ERR(dev_dax))
19+
return PTR_ERR(dev_dax);
20+
21+
if (!devres_open_group(&dev_dax->dev, dev_dax, GFP_KERNEL))
22+
return -ENOMEM;
23+
24+
device_lock(&dev_dax->dev);
25+
rc = dev_dax_probe(&dev_dax->dev);
26+
device_unlock(&dev_dax->dev);
27+
28+
devres_close_group(&dev_dax->dev, dev_dax);
29+
if (rc)
30+
devres_release_group(&dev_dax->dev, dev_dax);
31+
32+
return rc;
33+
}
34+
35+
static int dax_pmem_compat_release(struct device *dev, void *data)
36+
{
37+
device_lock(dev);
38+
devres_release_group(dev, to_dev_dax(dev));
39+
device_unlock(dev);
40+
41+
return 0;
42+
}
43+
44+
static int dax_pmem_compat_remove(struct device *dev)
45+
{
46+
device_for_each_child(dev, NULL, dax_pmem_compat_release);
47+
return 0;
48+
}
49+
50+
static struct nd_device_driver dax_pmem_compat_driver = {
51+
.probe = dax_pmem_compat_probe,
52+
.remove = dax_pmem_compat_remove,
53+
.drv = {
54+
.name = "dax_pmem_compat",
55+
},
56+
.type = ND_DRIVER_DAX_PMEM,
57+
};
58+
59+
static int __init dax_pmem_compat_init(void)
60+
{
61+
return nd_driver_register(&dax_pmem_compat_driver);
62+
}
63+
module_init(dax_pmem_compat_init);
64+
65+
static void __exit dax_pmem_compat_exit(void)
66+
{
67+
driver_unregister(&dax_pmem_compat_driver.drv);
68+
}
69+
module_exit(dax_pmem_compat_exit);
70+
71+
MODULE_LICENSE("GPL v2");
72+
MODULE_AUTHOR("Intel Corporation");
73+
MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM);
Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
1-
/*
2-
* Copyright(c) 2016 Intel Corporation. All rights reserved.
3-
*
4-
* This program is free software; you can redistribute it and/or modify
5-
* it under the terms of version 2 of the GNU General Public License as
6-
* published by the Free Software Foundation.
7-
*
8-
* This program is distributed in the hope that it will be useful, but
9-
* WITHOUT ANY WARRANTY; without even the implied warranty of
10-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11-
* General Public License for more details.
12-
*/
13-
#include <linux/percpu-refcount.h>
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
143
#include <linux/memremap.h>
154
#include <linux/module.h>
165
#include <linux/pfn_t.h>
17-
#include "../nvdimm/pfn.h"
18-
#include "../nvdimm/nd.h"
19-
#include "bus.h"
6+
#include "../../nvdimm/pfn.h"
7+
#include "../../nvdimm/nd.h"
8+
#include "../bus.h"
209

21-
static int dax_pmem_probe(struct device *dev)
10+
struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
2211
{
2312
struct resource res;
2413
int rc, id, region_id;
@@ -34,16 +23,16 @@ static int dax_pmem_probe(struct device *dev)
3423

3524
ndns = nvdimm_namespace_common_probe(dev);
3625
if (IS_ERR(ndns))
37-
return PTR_ERR(ndns);
26+
return ERR_CAST(ndns);
3827
nsio = to_nd_namespace_io(&ndns->dev);
3928

4029
/* parse the 'pfn' info block via ->rw_bytes */
4130
rc = devm_nsio_enable(dev, nsio);
4231
if (rc)
43-
return rc;
32+
return ERR_PTR(rc);
4433
rc = nvdimm_setup_pfn(nd_pfn, &pgmap);
4534
if (rc)
46-
return rc;
35+
return ERR_PTR(rc);
4736
devm_nsio_disable(dev, nsio);
4837

4938
/* reserve the metadata area, device-dax will reserve the data */
@@ -52,39 +41,29 @@ static int dax_pmem_probe(struct device *dev)
5241
if (!devm_request_mem_region(dev, nsio->res.start, offset,
5342
dev_name(&ndns->dev))) {
5443
dev_warn(dev, "could not reserve metadata\n");
55-
return -EBUSY;
44+
return ERR_PTR(-EBUSY);
5645
}
5746

5847
rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id);
5948
if (rc != 2)
60-
return -EINVAL;
49+
return ERR_PTR(-EINVAL);
6150

6251
/* adjust the dax_region resource to the start of data */
6352
memcpy(&res, &pgmap.res, sizeof(res));
6453
res.start += offset;
6554
dax_region = alloc_dax_region(dev, region_id, &res,
6655
le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
6756
if (!dax_region)
68-
return -ENOMEM;
57+
return ERR_PTR(-ENOMEM);
6958

70-
dev_dax = devm_create_dev_dax(dax_region, id, &pgmap);
59+
dev_dax = __devm_create_dev_dax(dax_region, id, &pgmap, subsys);
7160

7261
/* child dev_dax instances now own the lifetime of the dax_region */
7362
dax_region_put(dax_region);
7463

75-
return PTR_ERR_OR_ZERO(dev_dax);
64+
return dev_dax;
7665
}
77-
78-
static struct nd_device_driver dax_pmem_driver = {
79-
.probe = dax_pmem_probe,
80-
.drv = {
81-
.name = "dax_pmem",
82-
},
83-
.type = ND_DRIVER_DAX_PMEM,
84-
};
85-
86-
module_nd_driver(dax_pmem_driver);
66+
EXPORT_SYMBOL_GPL(__dax_pmem_probe);
8767

8868
MODULE_LICENSE("GPL v2");
8969
MODULE_AUTHOR("Intel Corporation");
90-
MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM);

0 commit comments

Comments
 (0)