Commit a2606241 authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Alasdair G Kergon

dm ioctl: allow message to return data

This patch introduces enhanced message support that allows the
device-mapper core to recognise messages that are common to all devices,
and for messages to return data to userspace.

Core messages are processed by the function "message_for_md".  If the
device mapper doesn't support the message, it is passed to the target
driver.

If the message returns data, the kernel sets the flag
DM_MESSAGE_OUT_FLAG.
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 02cde50b
...@@ -1414,6 +1414,22 @@ static int table_status(struct dm_ioctl *param, size_t param_size) ...@@ -1414,6 +1414,22 @@ static int table_status(struct dm_ioctl *param, size_t param_size)
return 0; 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. * 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) ...@@ -1425,6 +1441,8 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
struct dm_table *table; struct dm_table *table;
struct dm_target *ti; struct dm_target *ti;
struct dm_target_msg *tmsg = (void *) param + param->data_start; 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); md = find_device(param);
if (!md) if (!md)
...@@ -1448,6 +1466,10 @@ static int target_message(struct dm_ioctl *param, size_t param_size) ...@@ -1448,6 +1466,10 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
goto out_argv; goto out_argv;
} }
r = message_for_md(md, argc, argv, result, maxlen);
if (r <= 1)
goto out_argv;
table = dm_get_live_table(md); table = dm_get_live_table(md);
if (!table) if (!table)
goto out_argv; goto out_argv;
...@@ -1473,7 +1495,18 @@ static int target_message(struct dm_ioctl *param, size_t param_size) ...@@ -1473,7 +1495,18 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
out_argv: out_argv:
kfree(argv); kfree(argv);
out: 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); dm_put(md);
return r; return r;
} }
...@@ -1653,6 +1686,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) ...@@ -1653,6 +1686,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
param->flags &= ~DM_BUFFER_FULL_FLAG; param->flags &= ~DM_BUFFER_FULL_FLAG;
param->flags &= ~DM_UEVENT_GENERATED_FLAG; param->flags &= ~DM_UEVENT_GENERATED_FLAG;
param->flags &= ~DM_SECURE_DATA_FLAG; param->flags &= ~DM_SECURE_DATA_FLAG;
param->flags &= ~DM_DATA_OUT_FLAG;
/* Ignores parameters */ /* Ignores parameters */
if (cmd == DM_REMOVE_ALL_CMD || if (cmd == DM_REMOVE_ALL_CMD ||
......
...@@ -336,4 +336,9 @@ enum { ...@@ -336,4 +336,9 @@ enum {
*/ */
#define DM_SECURE_DATA_FLAG (1 << 15) /* In */ #define DM_SECURE_DATA_FLAG (1 << 15) /* In */
/*
* If set, a message generated output data.
*/
#define DM_DATA_OUT_FLAG (1 << 16) /* Out */
#endif /* _LINUX_DM_IOCTL_H */ #endif /* _LINUX_DM_IOCTL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment