diff mbox series

[4/4] dm: support global feature string and per-target feature strings

Message ID alpine.LRH.2.21.2211011654340.7766@file01.intranet.prod.int.rdu2.redhat.com (mailing list archive)
State Under Review
Delegated to: Mike Snitzer
Headers show
Series [1/4] dm-ioctl: fix misbehavior if list_versions races with module loading | expand

Commit Message

Mikulas Patocka Nov. 1, 2022, 8:55 p.m. UTC
This patch enables support for feature strings that may be returned from
the kernel to userspace and may be used instead of version numbers to
determine if the kernel supports a particular feature.

So far, all the strings are empty. When new features will be introduced,
they will be added to the device mapper feature string or target feature
string.

We add a new ioctl DM_GET_FEATURE_STRING that returns device-mapper
feature string in it's data area. If the buffer has insufficient size, the
flag DM_BUFFER_FULL_FLAG is set.

Per-target feature strings are returned after a target name in the
existing ioctls DM_LIST_VERSIONS and DM_GET_TARGET_VERSION. The current
libdevmapper code does not user the bytes after the name's terminating 0,
so this change is backward-compatible.

This patch increases minor version to 48 to notify userspace that feature
strings are supported.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
 drivers/md/dm-ioctl.c         |   36 ++++++++++++++++++++++++++++++++----
 include/linux/device-mapper.h |    1 +
 include/uapi/linux/dm-ioctl.h |    6 ++++--
 3 files changed, 37 insertions(+), 6 deletions(-)

--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
diff mbox series

Patch

Index: linux-2.6/include/linux/device-mapper.h
===================================================================
--- linux-2.6.orig/include/linux/device-mapper.h	2022-11-01 19:36:06.000000000 +0100
+++ linux-2.6/include/linux/device-mapper.h	2022-11-01 19:36:06.000000000 +0100
@@ -188,6 +188,7 @@  struct target_type {
 	const char *name;
 	struct module *module;
 	unsigned version[3];
+	const char *feature_string;
 	dm_ctr_fn ctr;
 	dm_dtr_fn dtr;
 	dm_map_fn map;
Index: linux-2.6/drivers/md/dm-ioctl.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-ioctl.c	2022-11-01 19:36:06.000000000 +0100
+++ linux-2.6/drivers/md/dm-ioctl.c	2022-11-01 19:36:06.000000000 +0100
@@ -26,6 +26,8 @@ 
 #define DM_MSG_PREFIX "ioctl"
 #define DM_DRIVER_EMAIL "dm-devel@redhat.com"
 
+static const char dm_feature_string[] = "";
+
 struct dm_file {
 	/*
 	 * poll will wait until the global event number is greater than
@@ -653,19 +655,23 @@  static int list_devices(struct file *fil
 static void list_version_get_needed(struct target_type *tt, void *needed_param)
 {
     size_t *needed = needed_param;
+    const char *feature_string = tt->feature_string ? : "";
 
     *needed += sizeof(struct dm_target_versions);
     *needed += strlen(tt->name) + 1;
+    *needed += strlen(feature_string) + 1;
     *needed += ALIGN_MASK;
 }
 
 static void list_version_get_info(struct target_type *tt, void *param)
 {
     struct vers_iter *info = param;
+    const char *feature_string = tt->feature_string ? : "";
+    char *ptr;
 
     /* Check space - it might have changed since the first iteration */
-    if ((char *)info->vers + sizeof(tt->version) + strlen(tt->name) + 1 >
-	info->end) {
+    if ((char *)info->vers + sizeof(tt->version) + strlen(tt->name) + 1 +
+	strlen(feature_string) + 1 > info->end) {
 
 	info->flags = DM_BUFFER_FULL_FLAG;
 	return;
@@ -674,14 +680,18 @@  static void list_version_get_info(struct
     if (info->old_vers)
 	info->old_vers->next = (uint32_t) ((void *)info->vers -
 					   (void *)info->old_vers);
+    info->old_vers = info->vers;
+
     info->vers->version[0] = tt->version[0];
     info->vers->version[1] = tt->version[1];
     info->vers->version[2] = tt->version[2];
     info->vers->next = 0;
     strcpy(info->vers->name, tt->name);
+    ptr = (char *)(info->vers + 1) + strlen(tt->name) + 1;
+    strcpy(ptr, feature_string);
+    ptr += strlen(feature_string) + 1;
 
-    info->old_vers = info->vers;
-    info->vers = align_ptr((void *)(info->vers + 1) + strlen(tt->name) + 1);
+    info->vers = align_ptr(ptr);
 }
 
 static int __list_versions(struct dm_ioctl *param, size_t param_size, const char *name)
@@ -747,6 +757,23 @@  static int get_target_version(struct fil
 	return __list_versions(param, param_size, param->name);
 }
 
+static int get_feature_string(struct file *filp, struct dm_ioctl *param, size_t param_size)
+{
+	size_t len;
+	size_t needed = strlen(dm_feature_string) + 1;
+	char *res;
+
+	res = get_result_buffer(param, param_size, &len);
+	if (len < needed) {
+		param->flags |= DM_BUFFER_FULL_FLAG;
+		return 0;
+	}
+
+	param->data_size = param->data_start + needed;
+	strcpy(res, dm_feature_string);
+	return 0;
+}
+
 static int check_name(const char *name)
 {
 	if (strchr(name, '/')) {
@@ -1790,6 +1817,7 @@  static ioctl_fn lookup_ioctl(unsigned in
 		{DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry},
 		{DM_DEV_ARM_POLL_CMD, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll},
 		{DM_GET_TARGET_VERSION_CMD, 0, get_target_version},
+		{DM_GET_FEATURE_STRING_CMD, 0, get_feature_string},
 	};
 
 	if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))
Index: linux-2.6/include/uapi/linux/dm-ioctl.h
===================================================================
--- linux-2.6.orig/include/uapi/linux/dm-ioctl.h	2022-11-01 19:36:06.000000000 +0100
+++ linux-2.6/include/uapi/linux/dm-ioctl.h	2022-11-01 19:50:58.000000000 +0100
@@ -258,6 +258,7 @@  enum {
 	DM_DEV_SET_GEOMETRY_CMD,
 	DM_DEV_ARM_POLL_CMD,
 	DM_GET_TARGET_VERSION_CMD,
+	DM_GET_FEATURE_STRING_CMD,
 };
 
 #define DM_IOCTL 0xfd
@@ -281,14 +282,15 @@  enum {
 
 #define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
 #define DM_GET_TARGET_VERSION _IOWR(DM_IOCTL, DM_GET_TARGET_VERSION_CMD, struct dm_ioctl)
+#define DM_GET_FEATURE_STRING _IOWR(DM_IOCTL, DM_GET_FEATURE_STRING_CMD, struct dm_ioctl)
 
 #define DM_TARGET_MSG	 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	47
+#define DM_VERSION_MINOR	48
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2022-07-28)"
+#define DM_VERSION_EXTRA	"-ioctl (2022-11-01)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */