diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2013-03-01 17:45:49 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2013-03-01 17:45:49 -0500 |
commit | a26062416ef8add48f16fbadded2b5f6fb84d024 (patch) | |
tree | 4f960c51bd22d99e55a1f56cf28f86f018de01a3 | |
parent | 02cde50b7ea74557d32ff778c73809322445ccd2 (diff) |
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: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm-ioctl.c | 36 | ||||
-rw-r--r-- | include/uapi/linux/dm-ioctl.h | 5 |
2 files changed, 40 insertions, 1 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 7eb0682d574f..aa04f0224642 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -1414,6 +1414,22 @@ static int table_status(struct dm_ioctl *param, size_t param_size) | |||
1414 | return 0; | 1414 | return 0; |
1415 | } | 1415 | } |
1416 | 1416 | ||
1417 | static bool buffer_test_overflow(char *result, unsigned maxlen) | ||
1418 | { | ||
1419 | return !maxlen || strlen(result) + 1 >= maxlen; | ||
1420 | } | ||
1421 | |||
1422 | /* | ||
1423 | * Process device-mapper dependent messages. | ||
1424 | * Returns a number <= 1 if message was processed by device mapper. | ||
1425 | * Returns 2 if message should be delivered to the target. | ||
1426 | */ | ||
1427 | static int message_for_md(struct mapped_device *md, unsigned argc, char **argv, | ||
1428 | char *result, unsigned maxlen) | ||
1429 | { | ||
1430 | return 2; | ||
1431 | } | ||
1432 | |||
1417 | /* | 1433 | /* |
1418 | * Pass a message to the target that's at the supplied device offset. | 1434 | * Pass a message to the target that's at the supplied device offset. |
1419 | */ | 1435 | */ |
@@ -1425,6 +1441,8 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1425 | struct dm_table *table; | 1441 | struct dm_table *table; |
1426 | struct dm_target *ti; | 1442 | struct dm_target *ti; |
1427 | struct dm_target_msg *tmsg = (void *) param + param->data_start; | 1443 | struct dm_target_msg *tmsg = (void *) param + param->data_start; |
1444 | size_t maxlen; | ||
1445 | char *result = get_result_buffer(param, param_size, &maxlen); | ||
1428 | 1446 | ||
1429 | md = find_device(param); | 1447 | md = find_device(param); |
1430 | if (!md) | 1448 | if (!md) |
@@ -1448,6 +1466,10 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1448 | goto out_argv; | 1466 | goto out_argv; |
1449 | } | 1467 | } |
1450 | 1468 | ||
1469 | r = message_for_md(md, argc, argv, result, maxlen); | ||
1470 | if (r <= 1) | ||
1471 | goto out_argv; | ||
1472 | |||
1451 | table = dm_get_live_table(md); | 1473 | table = dm_get_live_table(md); |
1452 | if (!table) | 1474 | if (!table) |
1453 | goto out_argv; | 1475 | goto out_argv; |
@@ -1473,7 +1495,18 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1473 | out_argv: | 1495 | out_argv: |
1474 | kfree(argv); | 1496 | kfree(argv); |
1475 | out: | 1497 | out: |
1476 | param->data_size = 0; | 1498 | if (r >= 0) |
1499 | __dev_status(md, param); | ||
1500 | |||
1501 | if (r == 1) { | ||
1502 | param->flags |= DM_DATA_OUT_FLAG; | ||
1503 | if (buffer_test_overflow(result, maxlen)) | ||
1504 | param->flags |= DM_BUFFER_FULL_FLAG; | ||
1505 | else | ||
1506 | param->data_size = param->data_start + strlen(result) + 1; | ||
1507 | r = 0; | ||
1508 | } | ||
1509 | |||
1477 | dm_put(md); | 1510 | dm_put(md); |
1478 | return r; | 1511 | return r; |
1479 | } | 1512 | } |
@@ -1653,6 +1686,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) | |||
1653 | param->flags &= ~DM_BUFFER_FULL_FLAG; | 1686 | param->flags &= ~DM_BUFFER_FULL_FLAG; |
1654 | param->flags &= ~DM_UEVENT_GENERATED_FLAG; | 1687 | param->flags &= ~DM_UEVENT_GENERATED_FLAG; |
1655 | param->flags &= ~DM_SECURE_DATA_FLAG; | 1688 | param->flags &= ~DM_SECURE_DATA_FLAG; |
1689 | param->flags &= ~DM_DATA_OUT_FLAG; | ||
1656 | 1690 | ||
1657 | /* Ignores parameters */ | 1691 | /* Ignores parameters */ |
1658 | if (cmd == DM_REMOVE_ALL_CMD || | 1692 | if (cmd == DM_REMOVE_ALL_CMD || |
diff --git a/include/uapi/linux/dm-ioctl.h b/include/uapi/linux/dm-ioctl.h index b8a6bddf0727..7e75b6fd8d45 100644 --- a/include/uapi/linux/dm-ioctl.h +++ b/include/uapi/linux/dm-ioctl.h | |||
@@ -336,4 +336,9 @@ enum { | |||
336 | */ | 336 | */ |
337 | #define DM_SECURE_DATA_FLAG (1 << 15) /* In */ | 337 | #define DM_SECURE_DATA_FLAG (1 << 15) /* In */ |
338 | 338 | ||
339 | /* | ||
340 | * If set, a message generated output data. | ||
341 | */ | ||
342 | #define DM_DATA_OUT_FLAG (1 << 16) /* Out */ | ||
343 | |||
339 | #endif /* _LINUX_DM_IOCTL_H */ | 344 | #endif /* _LINUX_DM_IOCTL_H */ |