Merge tag 'fixes-for-v3.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
[firefly-linux-kernel-4.4.55.git] / drivers / md / dm-ioctl.c
index 7eb0682d574f273ae4abb426b175ed53d33d9326..aa04f02246421f503c63f267d1f0604454ddaecf 100644 (file)
@@ -1414,6 +1414,22 @@ static int table_status(struct dm_ioctl *param, size_t param_size)
        return 0;
 }
 
+static bool buffer_test_overflow(char *result, unsigned maxlen)
+{
+       return !maxlen || strlen(result) + 1 >= maxlen;
+}
+
+/*
+ * Process device-mapper dependent messages.
+ * Returns a number <= 1 if message was processed by device mapper.
+ * Returns 2 if message should be delivered to the target.
+ */
+static int message_for_md(struct mapped_device *md, unsigned argc, char **argv,
+                         char *result, unsigned maxlen)
+{
+       return 2;
+}
+
 /*
  * Pass a message to the target that's at the supplied device offset.
  */
@@ -1425,6 +1441,8 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
        struct dm_table *table;
        struct dm_target *ti;
        struct dm_target_msg *tmsg = (void *) param + param->data_start;
+       size_t maxlen;
+       char *result = get_result_buffer(param, param_size, &maxlen);
 
        md = find_device(param);
        if (!md)
@@ -1448,6 +1466,10 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
                goto out_argv;
        }
 
+       r = message_for_md(md, argc, argv, result, maxlen);
+       if (r <= 1)
+               goto out_argv;
+
        table = dm_get_live_table(md);
        if (!table)
                goto out_argv;
@@ -1473,7 +1495,18 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
  out_argv:
        kfree(argv);
  out:
-       param->data_size = 0;
+       if (r >= 0)
+               __dev_status(md, param);
+
+       if (r == 1) {
+               param->flags |= DM_DATA_OUT_FLAG;
+               if (buffer_test_overflow(result, maxlen))
+                       param->flags |= DM_BUFFER_FULL_FLAG;
+               else
+                       param->data_size = param->data_start + strlen(result) + 1;
+               r = 0;
+       }
+
        dm_put(md);
        return r;
 }
@@ -1653,6 +1686,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
        param->flags &= ~DM_BUFFER_FULL_FLAG;
        param->flags &= ~DM_UEVENT_GENERATED_FLAG;
        param->flags &= ~DM_SECURE_DATA_FLAG;
+       param->flags &= ~DM_DATA_OUT_FLAG;
 
        /* Ignores parameters */
        if (cmd == DM_REMOVE_ALL_CMD ||