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.
Unified · Split
| @@ -1414,6 +1414,22 @@ static int table_status(struct dm_ioctl *param, size_t param_size) · 1413 unmodified lines | ||
| 1414 | 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 | 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) · 5 unmodified lines | ||
| 1425 | 1441 | struct dm_table *table; |
| 1426 | 1442 | struct dm_target *ti; |
| 1427 | 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 | 1447 | md = find_device(param); |
| 1430 | 1448 | if (!md) |
| @@ -1448,6 +1466,10 @@ static int target_message(struct dm_ioctl *param, size_t param_size) · 17 unmodified lines | ||
| 1448 | 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 | 1473 | table = dm_get_live_table(md); |
| 1452 | 1474 | if (!table) |
| 1453 | 1475 | goto out_argv; |
| @@ -1473,7 +1495,18 @@ static int target_message(struct dm_ioctl *param, size_t param_size) · 19 unmodified lines | ||
| 1473 | 1495 | out_argv: |
| 1474 | 1496 | kfree(argv); |
| 1475 | 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 | 1510 | dm_put(md); |
| 1478 | 1511 | return r; |
| 1479 | 1512 | } |
| @@ -1653,6 +1686,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) · 173 unmodified lines | ||
| 1653 | 1686 | param->flags &= ~DM_BUFFER_FULL_FLAG; |
| 1654 | 1687 | param->flags &= ~DM_UEVENT_GENERATED_FLAG; |
| 1655 | 1688 | param->flags &= ~DM_SECURE_DATA_FLAG; |
| 1689 | + param->flags &= ~DM_DATA_OUT_FLAG; | |
| 1656 | 1690 | |
| 1657 | 1691 | /* Ignores parameters */ |
| 1658 | 1692 | if (cmd == DM_REMOVE_ALL_CMD || |
| @@ -336,4 +336,9 @@ enum { · 335 unmodified lines | ||
| 336 | 336 | */ |
| 337 | 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 | 344 | #endif /* _LINUX_DM_IOCTL_H */ |