summaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2019-09-16 11:55:42 +0200
committerMike Snitzer <snitzer@redhat.com>2019-09-16 16:18:01 +0200
commitafa179eb603847494aa5061d4f501224a30dd187 (patch)
treec68a8f38bd6994c93dceddc76d05113ca624baa1 /drivers/md
parentdm bufio: introduce a global cache replacement (diff)
downloadlinux-afa179eb603847494aa5061d4f501224a30dd187.tar.xz
linux-afa179eb603847494aa5061d4f501224a30dd187.zip
dm: introduce DM_GET_TARGET_VERSION
This commit introduces a new ioctl DM_GET_TARGET_VERSION. It will load a target that is specified in the "name" entry in the parameter structure and return its version. This functionality is intended to be used by cryptsetup, so that it can query kernel capabilities before activating the device. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-ioctl.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index fb6f8fb1f13d..ac83f5002ce5 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -601,17 +601,27 @@ static void list_version_get_info(struct target_type *tt, void *param)
info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1);
}
-static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param_size)
+static int __list_versions(struct dm_ioctl *param, size_t param_size, const char *name)
{
size_t len, needed = 0;
struct dm_target_versions *vers;
struct vers_iter iter_info;
+ struct target_type *tt = NULL;
+
+ if (name) {
+ tt = dm_get_target_type(name);
+ if (!tt)
+ return -EINVAL;
+ }
/*
* Loop through all the devices working out how much
* space we need.
*/
- dm_target_iterate(list_version_get_needed, &needed);
+ if (!tt)
+ dm_target_iterate(list_version_get_needed, &needed);
+ else
+ list_version_get_needed(tt, &needed);
/*
* Grab our output buffer.
@@ -632,13 +642,28 @@ static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param
/*
* Now loop through filling out the names & versions.
*/
- dm_target_iterate(list_version_get_info, &iter_info);
+ if (!tt)
+ dm_target_iterate(list_version_get_info, &iter_info);
+ else
+ list_version_get_info(tt, &iter_info);
param->flags |= iter_info.flags;
out:
+ if (tt)
+ dm_put_target_type(tt);
return 0;
}
+static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param_size)
+{
+ return __list_versions(param, param_size, NULL);
+}
+
+static int get_target_version(struct file *filp, struct dm_ioctl *param, size_t param_size)
+{
+ return __list_versions(param, param_size, param->name);
+}
+
static int check_name(const char *name)
{
if (strchr(name, '/')) {
@@ -1664,6 +1689,7 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
{DM_TARGET_MSG_CMD, 0, target_message},
{DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry},
{DM_DEV_ARM_POLL, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll},
+ {DM_GET_TARGET_VERSION, 0, get_target_version},
};
if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))