mirror of https://github.com/xemu-project/xemu.git
block: Allow specifying driver-specific options to reopen
Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
ff99129ab8
commit
4d2cb09251
42
block.c
42
block.c
|
@ -1636,6 +1636,9 @@ typedef struct BlockReopenQueueEntry {
|
||||||
*
|
*
|
||||||
* bs is the BlockDriverState to add to the reopen queue.
|
* bs is the BlockDriverState to add to the reopen queue.
|
||||||
*
|
*
|
||||||
|
* options contains the changed options for the associated bs
|
||||||
|
* (the BlockReopenQueue takes ownership)
|
||||||
|
*
|
||||||
* flags contains the open flags for the associated bs
|
* flags contains the open flags for the associated bs
|
||||||
*
|
*
|
||||||
* returns a pointer to bs_queue, which is either the newly allocated
|
* returns a pointer to bs_queue, which is either the newly allocated
|
||||||
|
@ -1643,18 +1646,28 @@ typedef struct BlockReopenQueueEntry {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||||
BlockDriverState *bs, int flags)
|
BlockDriverState *bs,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
assert(bs != NULL);
|
assert(bs != NULL);
|
||||||
|
|
||||||
BlockReopenQueueEntry *bs_entry;
|
BlockReopenQueueEntry *bs_entry;
|
||||||
BdrvChild *child;
|
BdrvChild *child;
|
||||||
|
QDict *old_options;
|
||||||
|
|
||||||
if (bs_queue == NULL) {
|
if (bs_queue == NULL) {
|
||||||
bs_queue = g_new0(BlockReopenQueue, 1);
|
bs_queue = g_new0(BlockReopenQueue, 1);
|
||||||
QSIMPLEQ_INIT(bs_queue);
|
QSIMPLEQ_INIT(bs_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options) {
|
||||||
|
options = qdict_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
old_options = qdict_clone_shallow(bs->options);
|
||||||
|
qdict_join(options, old_options, false);
|
||||||
|
QDECREF(old_options);
|
||||||
|
|
||||||
/* bdrv_open() masks this flag out */
|
/* bdrv_open() masks this flag out */
|
||||||
flags &= ~BDRV_O_PROTOCOL;
|
flags &= ~BDRV_O_PROTOCOL;
|
||||||
|
|
||||||
|
@ -1666,13 +1679,15 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
child_flags = child->role->inherit_flags(flags);
|
child_flags = child->role->inherit_flags(flags);
|
||||||
bdrv_reopen_queue(bs_queue, child->bs, child_flags);
|
/* TODO Pass down child flags (backing.*, extents.*, ...) */
|
||||||
|
bdrv_reopen_queue(bs_queue, child->bs, NULL, child_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bs_entry = g_new0(BlockReopenQueueEntry, 1);
|
bs_entry = g_new0(BlockReopenQueueEntry, 1);
|
||||||
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
|
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
|
||||||
|
|
||||||
bs_entry->state.bs = bs;
|
bs_entry->state.bs = bs;
|
||||||
|
bs_entry->state.options = options;
|
||||||
bs_entry->state.flags = flags;
|
bs_entry->state.flags = flags;
|
||||||
|
|
||||||
return bs_queue;
|
return bs_queue;
|
||||||
|
@ -1725,6 +1740,7 @@ cleanup:
|
||||||
if (ret && bs_entry->prepared) {
|
if (ret && bs_entry->prepared) {
|
||||||
bdrv_reopen_abort(&bs_entry->state);
|
bdrv_reopen_abort(&bs_entry->state);
|
||||||
}
|
}
|
||||||
|
QDECREF(bs_entry->state.options);
|
||||||
g_free(bs_entry);
|
g_free(bs_entry);
|
||||||
}
|
}
|
||||||
g_free(bs_queue);
|
g_free(bs_queue);
|
||||||
|
@ -1737,7 +1753,7 @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, bdrv_flags);
|
BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
|
||||||
|
|
||||||
ret = bdrv_reopen_multiple(queue, &local_err);
|
ret = bdrv_reopen_multiple(queue, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
|
@ -1813,6 +1829,26 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Options that are not handled are only okay if they are unchanged
|
||||||
|
* compared to the old state. It is expected that some options are only
|
||||||
|
* used for the initial open, but not reopen (e.g. filename) */
|
||||||
|
if (qdict_size(reopen_state->options)) {
|
||||||
|
const QDictEntry *entry = qdict_first(reopen_state->options);
|
||||||
|
|
||||||
|
do {
|
||||||
|
QString *new_obj = qobject_to_qstring(entry->value);
|
||||||
|
const char *new = qstring_get_str(new_obj);
|
||||||
|
const char *old = qdict_get_try_str(reopen_state->bs->options,
|
||||||
|
entry->key);
|
||||||
|
|
||||||
|
if (!old || strcmp(new, old)) {
|
||||||
|
error_setg(errp, "Cannot change the option '%s'", entry->key);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} while ((entry = qdict_next(reopen_state->options, entry)));
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -236,11 +236,11 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
||||||
|
|
||||||
/* convert base & overlay_bs to r/w, if necessary */
|
/* convert base & overlay_bs to r/w, if necessary */
|
||||||
if (!(orig_base_flags & BDRV_O_RDWR)) {
|
if (!(orig_base_flags & BDRV_O_RDWR)) {
|
||||||
reopen_queue = bdrv_reopen_queue(reopen_queue, base,
|
reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
|
||||||
orig_base_flags | BDRV_O_RDWR);
|
orig_base_flags | BDRV_O_RDWR);
|
||||||
}
|
}
|
||||||
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
|
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
|
||||||
reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs,
|
reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, NULL,
|
||||||
orig_overlay_flags | BDRV_O_RDWR);
|
orig_overlay_flags | BDRV_O_RDWR);
|
||||||
}
|
}
|
||||||
if (reopen_queue) {
|
if (reopen_queue) {
|
||||||
|
|
|
@ -147,6 +147,7 @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
|
||||||
typedef struct BDRVReopenState {
|
typedef struct BDRVReopenState {
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
int flags;
|
int flags;
|
||||||
|
QDict *options;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
} BDRVReopenState;
|
} BDRVReopenState;
|
||||||
|
|
||||||
|
@ -218,7 +219,8 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp);
|
||||||
int bdrv_open(BlockDriverState **pbs, const char *filename,
|
int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||||
const char *reference, QDict *options, int flags, Error **errp);
|
const char *reference, QDict *options, int flags, Error **errp);
|
||||||
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||||
BlockDriverState *bs, int flags);
|
BlockDriverState *bs,
|
||||||
|
QDict *options, int flags);
|
||||||
int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
|
int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
|
||||||
int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
|
int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
|
||||||
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
|
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
|
||||||
|
|
Loading…
Reference in New Issue