]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/md/dm-ioctl.c
Merge tag 'selinux-pr-20191007' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / md / dm-ioctl.c
index 1e03bc89e20f68ce25c7e0c60e178c1985cec8bf..ac83f5002ce5fe3a0483ea5630e389a9f29576ae 100644 (file)
@@ -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, '/')) {
@@ -1592,7 +1617,7 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para
        }
 
        ti = dm_table_find_target(table, tmsg->sector);
-       if (!dm_target_is_valid(ti)) {
+       if (!ti) {
                DMWARN("Target message sector outside device.");
                r = -EINVAL;
        } else if (ti->type->message)
@@ -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)))