Commit 730926c3 authored by Dan Williams's avatar Dan Williams
Browse files

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: default avatarDan Williams <dan.j.williams@intel.com>
parent d200781e
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
What:           /sys/class/dax/
Date:           May, 2016
KernelVersion:  v4.7
Contact:        linux-nvdimm@lists.01.org
Description:	Device DAX is the device-centric analogue of Filesystem
		DAX (CONFIG_FS_DAX).  It allows memory ranges to be
		allocated and mapped without need of an intervening file
		system.  Device DAX is strict, precise and predictable.
		Specifically this interface:

		1/ Guarantees fault granularity with respect to a given
		page size (pte, pmd, or pud) set at configuration time.

		2/ Enforces deterministic behavior by being strict about
		what fault scenarios are supported.

		The /sys/class/dax/ interface enumerates all the
		device-dax instances in the system. The ABI is
		deprecated and will be removed after 2020. It is
		replaced with the DAX bus interface /sys/bus/dax/ where
		device-dax instances can be found under
		/sys/bus/dax/devices/
+11 −1
Original line number Diff line number Diff line
@@ -23,12 +23,22 @@ config DEV_DAX
config DEV_DAX_PMEM
	tristate "PMEM DAX: direct access to persistent memory"
	depends on LIBNVDIMM && NVDIMM_DAX && DEV_DAX
	depends on m # until we can kill DEV_DAX_PMEM_COMPAT
	default DEV_DAX
	help
	  Support raw access to persistent memory.  Note that this
	  driver consumes memory ranges allocated and exported by the
	  libnvdimm sub-system.

	  Say Y if unsure
	  Say M if unsure

config DEV_DAX_PMEM_COMPAT
	tristate "PMEM DAX: support the deprecated /sys/class/dax interface"
	depends on DEV_DAX_PMEM
	default DEV_DAX_PMEM
	help
	  Older versions of the libdaxctl library expect to find all
	  device-dax instances under /sys/class/dax. If libdaxctl in
	  your distribution is older than v58 say M, otherwise say N.

endif
+2 −2
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_DAX) += dax.o
obj-$(CONFIG_DEV_DAX) += device_dax.o
obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o

dax-y := super.o
dax-y += bus.o
dax_pmem-y := pmem.o
device_dax-y := device.o

obj-y += pmem/
+24 −5
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
#include "dax-private.h"
#include "bus.h"

static struct class *dax_class;

static DEFINE_MUTEX(dax_bus_lock);

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

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

	inode = dax_inode(dax_dev);
	dev->devt = inode->i_rdev;
	if (subsys == DEV_DAX_BUS)
		dev->bus = &dax_bus_type;
	else
		dev->class = dax_class;
	dev->parent = parent;
	dev->groups = dax_attribute_groups;
	dev->release = dev_dax_release;
@@ -374,7 +379,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,

	return ERR_PTR(rc);
}
EXPORT_SYMBOL_GPL(devm_create_dev_dax);
EXPORT_SYMBOL_GPL(__devm_create_dev_dax);

static int match_always_count;

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

void dax_driver_unregister(struct dax_device_driver *dax_drv)
{
	struct device_driver *drv = &dax_drv->drv;
	struct dax_id *dax_id, *_id;

	mutex_lock(&dax_bus_lock);
@@ -416,15 +422,28 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv)
		kfree(dax_id);
	}
	mutex_unlock(&dax_bus_lock);
	driver_unregister(drv);
}
EXPORT_SYMBOL_GPL(dax_driver_unregister);

int __init dax_bus_init(void)
{
	return bus_register(&dax_bus_type);
	int rc;

	if (IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)) {
		dax_class = class_create(THIS_MODULE, "dax");
		if (IS_ERR(dax_class))
			return PTR_ERR(dax_class);
	}

	rc = bus_register(&dax_bus_type);
	if (rc)
		class_destroy(dax_class);
	return rc;
}

void __exit dax_bus_exit(void)
{
	bus_unregister(&dax_bus_type);
	class_destroy(dax_class);
}
+23 −3
Original line number Diff line number Diff line
@@ -2,7 +2,8 @@
/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
#ifndef __DAX_BUS_H__
#define __DAX_BUS_H__
struct device;
#include <linux/device.h>

struct dev_dax;
struct resource;
struct dax_device;
@@ -10,8 +11,23 @@ struct dax_region;
void dax_region_put(struct dax_region *dax_region);
struct dax_region *alloc_dax_region(struct device *parent, int region_id,
		struct resource *res, unsigned int align, unsigned long flags);
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
		struct dev_pagemap *pgmap);

enum dev_dax_subsys {
	DEV_DAX_BUS,
	DEV_DAX_CLASS,
};

struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
		struct dev_pagemap *pgmap, enum dev_dax_subsys subsys);

static inline struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
		int id, struct dev_pagemap *pgmap)
{
	return __devm_create_dev_dax(dax_region, id, pgmap, DEV_DAX_BUS);
}

/* to be deleted when DEV_DAX_CLASS is removed */
struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys);

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

#if IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)
int dev_dax_probe(struct device *dev);
#endif

/*
 * While run_dax() is potentially a generic operation that could be
 * defined in include/linux/dax.h we don't want to grow any users
Loading