From: Gregory Price <[email protected]> Recent kernels add /sys/bus/dax/devices/daxX.Y/state to dax_kmem devices for atomic whole-device hotplug. It reads 'unplugged', 'offline', 'online', 'online_kernel' or 'online_movable', and accepts all but 'offline'.
Add an enum and get/set accessors for it. The getter returns DAXCTL_KMEM_UNKNOWN when the attribute is absent, so callers can fall back to per-block operations. Signed-off-by: Gregory Price <[email protected]> --- daxctl/lib/libdaxctl-private.h | 9 ++++++ daxctl/lib/libdaxctl.c | 59 ++++++++++++++++++++++++++++++++++ daxctl/lib/libdaxctl.sym | 6 ++++ daxctl/libdaxctl.h | 18 +++++++++++ 4 files changed, 92 insertions(+) diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h index b902e3d..00e906c 100644 --- a/daxctl/lib/libdaxctl-private.h +++ b/daxctl/lib/libdaxctl-private.h @@ -58,6 +58,15 @@ static const char *state_strings[] = { [MEM_ZONE_MOVABLE] = "online_movable", }; +/* dax_kmem daxX.Y/state strings */ +static const char *kmem_state_strings[] = { + [DAXCTL_KMEM_UNPLUGGED] = "unplugged", + [DAXCTL_KMEM_OFFLINE] = "offline", + [DAXCTL_KMEM_ONLINE] = "online", + [DAXCTL_KMEM_ONLINE_KERNEL] = "online_kernel", + [DAXCTL_KMEM_ONLINE_MOVABLE] = "online_movable", +}; + /** * struct daxctl_region - container for dax_devices */ diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c index 01b1915..cbb42e3 100644 --- a/daxctl/lib/libdaxctl.c +++ b/daxctl/lib/libdaxctl.c @@ -1794,3 +1794,62 @@ DAXCTL_EXPORT int daxctl_dev_has_online_memory(struct daxctl_dev *dev) else return 0; } + +DAXCTL_EXPORT enum daxctl_kmem_state daxctl_dev_get_kmem_state( + struct daxctl_dev *dev) +{ + struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev); + char *path = dev->dev_buf; + int len = dev->buf_len; + char buf[SYSFS_ATTR_SIZE]; + int i; + + if (snprintf(path, len, "%s/state", dev->dev_path) >= len) { + err(ctx, "%s: buffer too small!\n", + daxctl_dev_get_devname(dev)); + return DAXCTL_KMEM_UNKNOWN; + } + + /* absent on older kernels */ + if (sysfs_read_attr(ctx, path, buf) < 0) + return DAXCTL_KMEM_UNKNOWN; + + for (i = DAXCTL_KMEM_UNPLUGGED; i <= DAXCTL_KMEM_ONLINE_MOVABLE; i++) + if (strcmp(buf, kmem_state_strings[i]) == 0) + return i; + + dbg(ctx, "%s: unrecognized kmem state '%s'\n", + daxctl_dev_get_devname(dev), buf); + return DAXCTL_KMEM_UNKNOWN; +} + +DAXCTL_EXPORT int daxctl_dev_set_kmem_state(struct daxctl_dev *dev, + enum daxctl_kmem_state state) +{ + struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev); + char *path = dev->dev_buf; + int len = dev->buf_len; + + switch (state) { + case DAXCTL_KMEM_UNPLUGGED: + case DAXCTL_KMEM_ONLINE: + case DAXCTL_KMEM_ONLINE_KERNEL: + case DAXCTL_KMEM_ONLINE_MOVABLE: + break; + /* 'offline' is read-only */ + case DAXCTL_KMEM_OFFLINE: + case DAXCTL_KMEM_UNKNOWN: + default: + dbg(ctx, "%s: invalid kmem state %d\n", + daxctl_dev_get_devname(dev), state); + return -EINVAL; + } + + if (snprintf(path, len, "%s/state", dev->dev_path) >= len) { + err(ctx, "%s: buffer too small!\n", + daxctl_dev_get_devname(dev)); + return -ENXIO; + } + + return sysfs_write_attr(ctx, path, kmem_state_strings[state]); +} diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym index 43dd60b..d247542 100644 --- a/daxctl/lib/libdaxctl.sym +++ b/daxctl/lib/libdaxctl.sym @@ -113,3 +113,9 @@ global: daxctl_dev_get_mode; daxctl_dev_is_system_ram_mode; } LIBDAXCTL_10; + +LIBDAXCTL_12 { +global: + daxctl_dev_get_kmem_state; + daxctl_dev_set_kmem_state; +} LIBDAXCTL_11; diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h index 7ec159e..e2812cc 100644 --- a/daxctl/libdaxctl.h +++ b/daxctl/libdaxctl.h @@ -77,6 +77,24 @@ int daxctl_dev_get_target_node(struct daxctl_dev *dev); int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev); int daxctl_dev_has_online_memory(struct daxctl_dev *dev); +/* + * dax_kmem whole-device hotplug state (daxX.Y/state). UNKNOWN means the + * attribute is absent (older kernel, or device not bound to kmem) or + * reports a state this library does not recognize. + */ +enum daxctl_kmem_state { + DAXCTL_KMEM_UNKNOWN = -1, + DAXCTL_KMEM_UNPLUGGED = 0, + DAXCTL_KMEM_OFFLINE, + DAXCTL_KMEM_ONLINE, + DAXCTL_KMEM_ONLINE_KERNEL, + DAXCTL_KMEM_ONLINE_MOVABLE, +}; + +enum daxctl_kmem_state daxctl_dev_get_kmem_state(struct daxctl_dev *dev); +int daxctl_dev_set_kmem_state(struct daxctl_dev *dev, + enum daxctl_kmem_state state); + struct daxctl_memory; enum daxctl_dev_mode { -- 2.53.0-Meta
