2018-01-09 18:50:57 +03:00
|
|
|
/*
|
|
|
|
* Block layer code related to image creation
|
|
|
|
*
|
|
|
|
* Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "block/block_int.h"
|
2018-01-18 16:33:04 +03:00
|
|
|
#include "qemu/job.h"
|
Include qemu/main-loop.h less
In my "build everything" tree, changing qemu/main-loop.h triggers a
recompile of some 5600 out of 6600 objects (not counting tests and
objects that don't depend on qemu/osdep.h). It includes block/aio.h,
which in turn includes qemu/event_notifier.h, qemu/notify.h,
qemu/processor.h, qemu/qsp.h, qemu/queue.h, qemu/thread-posix.h,
qemu/thread.h, qemu/timer.h, and a few more.
Include qemu/main-loop.h only where it's needed. Touching it now
recompiles only some 1700 objects. For block/aio.h and
qemu/event_notifier.h, these numbers drop from 5600 to 2800. For the
others, they shrink only slightly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20190812052359.30071-21-armbru@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2019-08-12 08:23:50 +03:00
|
|
|
#include "qemu/main-loop.h"
|
2018-01-09 18:50:57 +03:00
|
|
|
#include "qapi/qapi-commands-block-core.h"
|
2018-01-18 16:33:04 +03:00
|
|
|
#include "qapi/qapi-visit-block-core.h"
|
|
|
|
#include "qapi/clone-visitor.h"
|
2018-01-09 18:50:57 +03:00
|
|
|
#include "qapi/error.h"
|
|
|
|
|
2018-01-18 16:33:04 +03:00
|
|
|
typedef struct BlockdevCreateJob {
|
|
|
|
Job common;
|
2018-01-09 18:50:57 +03:00
|
|
|
BlockDriver *drv;
|
|
|
|
BlockdevCreateOptions *opts;
|
2018-01-18 16:33:04 +03:00
|
|
|
} BlockdevCreateJob;
|
2018-01-09 18:50:57 +03:00
|
|
|
|
2018-08-30 04:57:26 +03:00
|
|
|
static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
|
2018-01-09 18:50:57 +03:00
|
|
|
{
|
2018-08-30 04:57:26 +03:00
|
|
|
BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common);
|
2018-08-30 04:57:31 +03:00
|
|
|
int ret;
|
2018-01-18 16:33:04 +03:00
|
|
|
|
2022-03-03 18:16:11 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2018-01-18 16:33:04 +03:00
|
|
|
job_progress_set_remaining(&s->common, 1);
|
2018-08-30 04:57:31 +03:00
|
|
|
ret = s->drv->bdrv_co_create(s->opts, errp);
|
2018-01-18 16:33:04 +03:00
|
|
|
job_progress_update(&s->common, 1);
|
|
|
|
|
|
|
|
qapi_free_BlockdevCreateOptions(s->opts);
|
2018-08-30 04:57:26 +03:00
|
|
|
|
2018-08-30 04:57:31 +03:00
|
|
|
return ret;
|
2018-01-18 16:33:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static const JobDriver blockdev_create_job_driver = {
|
|
|
|
.instance_size = sizeof(BlockdevCreateJob),
|
|
|
|
.job_type = JOB_TYPE_CREATE,
|
2018-08-30 04:57:26 +03:00
|
|
|
.run = blockdev_create_run,
|
2018-01-18 16:33:04 +03:00
|
|
|
};
|
|
|
|
|
2023-02-03 18:21:55 +03:00
|
|
|
/* Checking whether the function is present doesn't require the graph lock */
|
|
|
|
static inline bool TSA_NO_TSA has_bdrv_co_create(BlockDriver *drv)
|
|
|
|
{
|
|
|
|
return drv->bdrv_co_create;
|
|
|
|
}
|
|
|
|
|
2018-05-25 19:24:51 +03:00
|
|
|
void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
|
|
|
|
Error **errp)
|
2018-01-18 16:33:04 +03:00
|
|
|
{
|
|
|
|
BlockdevCreateJob *s;
|
2018-01-09 18:50:57 +03:00
|
|
|
const char *fmt = BlockdevDriver_str(options->driver);
|
|
|
|
BlockDriver *drv = bdrv_find_format(fmt);
|
|
|
|
|
block/create: Do not abort if a block driver is not available
The 'blockdev-create' QMP command was introduced as experimental
feature in commit b0292b851b8, using the assert() debug call.
It got promoted to 'stable' command in 3fb588a0f2c, but the
assert call was not removed.
Some block drivers are optional, and bdrv_find_format() might
return a NULL value, triggering the assertion.
Stable code is not expected to abort, so return an error instead.
This is easily reproducible when libnfs is not installed:
./configure
[...]
module support no
Block whitelist (rw)
Block whitelist (ro)
libiscsi support yes
libnfs support no
[...]
Start QEMU:
$ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait
Send the 'blockdev-create' with the 'nfs' driver:
$ ( cat << 'EOF'
{'execute': 'qmp_capabilities'}
{'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'}
EOF
) | socat STDIO UNIX:/tmp/qemu.qmp
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}}
{"return": {}}
QEMU crashes:
$ gdb qemu-system-x86_64 core
Program received signal SIGSEGV, Segmentation fault.
(gdb) bt
#0 0x00007ffff510957f in raise () at /lib64/libc.so.6
#1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6
#2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6
#3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6
#4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69
#5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314
#6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131
#7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174
With this patch applied, QEMU returns a QMP error:
{'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'}
{"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}}
Cc: qemu-stable@nongnu.org
Reported-by: Xu Tian <xutian@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2019-09-12 01:08:49 +03:00
|
|
|
if (!drv) {
|
|
|
|
error_setg(errp, "Block driver '%s' not found or not supported", fmt);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-09 18:50:57 +03:00
|
|
|
/* If the driver is in the schema, we know that it exists. But it may not
|
|
|
|
* be whitelisted. */
|
|
|
|
if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
|
|
|
|
error_setg(errp, "Driver is not whitelisted");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-18 16:33:04 +03:00
|
|
|
/* Error out if the driver doesn't support .bdrv_co_create */
|
2023-02-03 18:21:55 +03:00
|
|
|
if (!has_bdrv_co_create(drv)) {
|
2018-01-09 18:50:57 +03:00
|
|
|
error_setg(errp, "Driver does not support blockdev-create");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-18 16:33:04 +03:00
|
|
|
/* Create the block job */
|
|
|
|
/* TODO Running in the main context. Block drivers need to error out or add
|
|
|
|
* locking when they use a BDS in a different AioContext. */
|
|
|
|
s = job_create(job_id, &blockdev_create_job_driver, NULL,
|
|
|
|
qemu_get_aio_context(), JOB_DEFAULT | JOB_MANUAL_DISMISS,
|
|
|
|
NULL, NULL, errp);
|
|
|
|
if (!s) {
|
|
|
|
return;
|
2018-01-09 18:50:57 +03:00
|
|
|
}
|
2018-01-18 16:33:04 +03:00
|
|
|
|
|
|
|
s->drv = drv,
|
|
|
|
s->opts = QAPI_CLONE(BlockdevCreateOptions, options),
|
|
|
|
|
|
|
|
job_start(&s->common);
|
2018-01-09 18:50:57 +03:00
|
|
|
}
|