| /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| #include "qemu/osdep.h" |
| |
| #include "system/block-backend.h" |
| #include "block/block_int.h" |
| #include "qapi/qapi-commands-block.h" |
| #include "qapi/error.h" |
| #include "qemu-io.h" |
| |
| void qmp_x_qemu_io(const char *device, const char *qdev, |
| const char *command, Error **errp) |
| { |
| BlockBackend *blk = NULL; |
| BlockBackend *local_blk = NULL; |
| BlockDriverState *bs = NULL; |
| int ret; |
| |
| if (!device && !qdev) { |
| error_setg(errp, "Must specify either device or qdev"); |
| return; |
| } |
| if (qdev && device) { |
| error_setg(errp, "Cannot specify both qdev and device"); |
| return; |
| } |
| |
| if (qdev) { |
| blk = blk_by_qdev_id(qdev, errp); |
| if (!blk) { |
| return; |
| } |
| } else { |
| blk = blk_by_name(device); |
| if (!blk) { |
| bs = bdrv_lookup_bs(NULL, device, errp); |
| if (!bs) { |
| return; |
| } |
| } |
| } |
| |
| if (bs) { |
| blk = local_blk = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL); |
| ret = blk_insert_bs(blk, bs, errp); |
| if (ret < 0) { |
| goto fail; |
| } |
| } |
| |
| /* |
| * Notably absent: Proper permission management. This is sad, but it seems |
| * almost impossible to achieve without changing the semantics and thereby |
| * limiting the use cases of the qemu-io command. |
| * |
| * In an ideal world we would unconditionally create a new BlockBackend for |
| * qemuio_command(), but we have commands like 'reopen' and want them to |
| * take effect on the exact BlockBackend whose name the user passed instead |
| * of just on a temporary copy of it. |
| * |
| * Another problem is that deleting the temporary BlockBackend involves |
| * draining all requests on it first, but some qemu-iotests cases want to |
| * issue multiple aio_read/write requests and expect them to complete in |
| * the background while the monitor has already returned. |
| * |
| * This is also what prevents us from saving the original permissions and |
| * restoring them later: We can't revoke permissions until all requests |
| * have completed, and we don't know when that is nor can we really let |
| * anything else run before we have revoken them to avoid race conditions. |
| * |
| * What happens now is that command() in qemu-io-cmds.c can extend the |
| * permissions if necessary for the qemu-io command. And they simply stay |
| * extended, possibly resulting in a read-only guest device keeping write |
| * permissions. Ugly, but it appears to be the lesser evil. |
| */ |
| qemuio_command(blk, command, errp); |
| |
| fail: |
| blk_unref(local_blk); |
| } |