From e50ca619790a51140dfe2f64a1b1f2a386f78393 Mon Sep 17 00:00:00 2001 From: "varinder.p" Date: Wed, 23 Mar 2022 23:10:48 +0530 Subject: [PATCH] Fixed SDCard and emulator controller commands. Change-Id: Icda220e14ce17f9674fce0f9a64da97e214eee41 Signed-off-by: varinder.p --- tizen/src/ecs/Makefile.objs | 2 +- tizen/src/ecs/ecs-json-streamer.c | 138 ---------------- tizen/src/ecs/ecs-json-streamer.h | 49 ------ tizen/src/ecs/ecs.c | 18 +-- tizen/src/ecs/ecs_internal.h | 20 +-- tizen/src/ecs/ecs_mon.c | 257 ++++++++++-------------------- tizen/src/ecs/ecs_msg.c | 2 - tizen/src/util/device_hotplug.c | 4 +- 8 files changed, 101 insertions(+), 389 deletions(-) delete mode 100644 tizen/src/ecs/ecs-json-streamer.c delete mode 100644 tizen/src/ecs/ecs-json-streamer.h diff --git a/tizen/src/ecs/Makefile.objs b/tizen/src/ecs/Makefile.objs index 0662176a67..7c345ba3ab 100644 --- a/tizen/src/ecs/Makefile.objs +++ b/tizen/src/ecs/Makefile.objs @@ -1,7 +1,7 @@ obj-y += genmsg/ecs.pb-c.o genmsg/ecs_ids.pb-c.o obj-y += ecs.o ecs_msg.o ecs_msg_injector.o ecs_msg_device.o ecs_msg_injector.o-cflags += -Wno-stringop-overflow -obj-y += ecs_mon.o ecs-json-streamer.o +obj-y += ecs_mon.o obj-y += ecs_eventcast.o obj-y += ecs_sensor.o obj-$(CONFIG_VIRTFS) += ecs_hds.o diff --git a/tizen/src/ecs/ecs-json-streamer.c b/tizen/src/ecs/ecs-json-streamer.c deleted file mode 100644 index 1db50d84b8..0000000000 --- a/tizen/src/ecs/ecs-json-streamer.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * JSON streaming support - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "ecs-json-streamer.h" - -#define MAX_TOKEN_SIZE (64ULL << 20) -#define MAX_TOKEN_COUNT (2ULL << 20) -#define MAX_NESTING (1ULL << 10) - -static void json_message_free_tokens(ECSJSONMessageParser *parser) -{ - //TIZEN_VERIFY FIXME - #if 0 - if (parser->tokens) { - g_queue_free(parser->tokens); - parser->tokens = NULL; - } - #endif -} - -// TIZEN_VERIFY -#if 0 -static void ecs_json_message_process_token(JSONLexer *lexer, GString *input, - JSONTokenType type, int x, int y) -{ - ECSJSONMessageParser *parser = container_of(lexer, ECSJSONMessageParser, lexer); - JSONToken *token; - - switch (type) { - case JSON_LCURLY: - parser->brace_count++; - break; - case JSON_RCURLY: - parser->brace_count--; - break; - case JSON_LSQUARE: - parser->bracket_count++; - break; - case JSON_RSQUARE: - parser->bracket_count--; - break; - default: - break; - } - - token = g_malloc(sizeof(JSONToken) + input->len + 1); - token->type = type; - memcpy(token->str, input->str, input->len); - token->str[input->len] = 0; - token->x = x; - token->y = y; - - parser->token_size += input->len; - - g_queue_push_tail(parser->tokens, token); - - if (type == JSON_ERROR) { - goto out_emit_bad; - } else if (parser->brace_count < 0 || - parser->bracket_count < 0 || - (parser->brace_count == 0 && - parser->bracket_count == 0)) { - goto out_emit; - } else if (parser->token_size > MAX_TOKEN_SIZE || - g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT || - parser->bracket_count + parser->brace_count > MAX_NESTING) { - /* Security consideration, we limit total memory allocated per object - * and the maximum recursion depth that a message can force. - */ - goto out_emit_bad; - } - - return; - -out_emit_bad: - /* - * Clear out token list and tell the parser to emit an error - * indication by passing it a NULL list - */ - json_message_free_tokens(parser); -out_emit: - /* send current list of tokens to parser and reset tokenizer */ - parser->brace_count = 0; - parser->bracket_count = 0; - /* parser->emit takes ownership of parser->tokens. */ - parser->emit(parser, parser->tokens, parser->opaque); - parser->tokens = g_queue_new(); - parser->token_size = 0; -} -#endif - -//TIZEN_VERIFY: -void ecs_json_message_parser_init(ECSJSONMessageParser *parser, - void (*emit)(void *opaque, QObject *json, - Error *err), - void *opaque, va_list *ap) { - parser->emit = emit; - parser->opaque = opaque; - parser->ap = ap; - parser->brace_count = 0; - parser->bracket_count = 0; - g_queue_init(&parser->tokens); - parser->token_size = 0; - - json_lexer_init(&parser->lexer, !!ap); -} - - -int ecs_json_message_parser_feed(ECSJSONMessageParser *parser, - const char *buffer, size_t size) -{ - json_lexer_feed(&parser->lexer, buffer, size); - return 0; -} - -int ecs_json_message_parser_flush(ECSJSONMessageParser *parser) -{ - json_lexer_flush(&parser->lexer); - return 0; -} - -void ecs_json_message_parser_destroy(ECSJSONMessageParser *parser) -{ - json_lexer_destroy(&parser->lexer); - json_message_free_tokens(parser); -} diff --git a/tizen/src/ecs/ecs-json-streamer.h b/tizen/src/ecs/ecs-json-streamer.h deleted file mode 100644 index c3ea1057cc..0000000000 --- a/tizen/src/ecs/ecs-json-streamer.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * JSON streaming support - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ - -#ifndef QEMU_JSON_STREAMER_H -#define QEMU_JSON_STREAMER_H - -#include "qobject/json-parser-int.h" - -typedef struct JSONToken { - int type; - int x; - int y; - char str[]; -} JSONToken; - -typedef struct ECSJSONMessageParser { - void (*emit)(void *opaque, QObject *json, Error *err); - void *opaque; - va_list *ap; - JSONLexer lexer; - int brace_count; - int bracket_count; - GQueue tokens; - uint64_t token_size; -} ECSJSONMessageParser; - -void ecs_json_message_parser_init(ECSJSONMessageParser *parser, - void (*emit)(void *opaque, QObject *json, - Error *err), - void *opaque, va_list *ap); - -int ecs_json_message_parser_feed(ECSJSONMessageParser *parser, - const char *buffer, size_t size); - -int ecs_json_message_parser_flush(ECSJSONMessageParser *parser); - -void ecs_json_message_parser_destroy(ECSJSONMessageParser *parser); - -#endif diff --git a/tizen/src/ecs/ecs.c b/tizen/src/ecs/ecs.c index eec866df55..7407cc1cbd 100644 --- a/tizen/src/ecs/ecs.c +++ b/tizen/src/ecs/ecs.c @@ -34,10 +34,8 @@ #include "qemu/queue.h" #include "qemu/sockets.h" #include "qemu/option.h" -#include "qemu/thread.h" #include "qemu/timer.h" #include "qemu/main-loop.h" -#include "chardev/char.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qnum.h" #include "hw/qdev.h" @@ -331,13 +329,13 @@ void ecs_make_header(QDict *obj, type_length length, type_group group, qdict_put(obj, "action", qnum_from_int((int64_t)action)); } -static EcsMonitor *monitor_create(void) +static MonitorQMP *monitor_create(void) { - EcsMonitor *mon; + MonitorQMP *mon; - mon = g_malloc0(sizeof(EcsMonitor)); + mon = g_malloc0(sizeof(MonitorQMP)); if (NULL == mon) { - LOG_SEVERE("EcsMonitor allocation failed.\n"); + LOG_SEVERE("Monitor allocation failed.\n"); return NULL; } @@ -637,8 +635,8 @@ static int ecs_add_client(ECS_State *cs, int fd) clii->client_fd = fd; clii->cs = cs; clii->client_type = TYPE_NONE; - - ecs_json_message_parser_init(&clii->parser, ecs_handle_qmp_command, clii, NULL); + + json_message_parser_init(&clii->parser, ecs_handle_qmp_command, clii, NULL); #ifdef CONFIG_LINUX epoll_cli_add(cs, fd); @@ -898,7 +896,7 @@ static void *ecs_initialize(void *args) { int ret = 1; ECS_State *cs = NULL; - EcsMonitor *mon = NULL; + MonitorQMP *mon = NULL; LOG_INFO("ecs starts initializing.\n"); @@ -921,7 +919,7 @@ static void *ecs_initialize(void *args) mon = monitor_create(); if (NULL == mon) { - LOG_SEVERE("EcsMonitor initialization failed.\n"); + LOG_SEVERE("Monitor initialization failed.\n"); ecs_close(cs); return NULL; } diff --git a/tizen/src/ecs/ecs_internal.h b/tizen/src/ecs/ecs_internal.h index 99671fd768..5c8781f4b6 100644 --- a/tizen/src/ecs/ecs_internal.h +++ b/tizen/src/ecs/ecs_internal.h @@ -31,12 +31,12 @@ #ifndef __ECS_INTERNAL_H__ #define __ECS_INTERNAL_H__ - #include "emulator_common.h" #include "qemu/queue.h" -#include "ecs-json-streamer.h" +#include "qapi/qmp/json-parser.h" #include "genmsg/ecs.pb-c.h" #include "genmsg/ecs_ids.pb-c.h" +#include "monitor/monitor-internal.h" #define TIMER_ALIVE_S 60 @@ -97,16 +97,6 @@ struct mon_fd_t { QLIST_ENTRY(mon_fd_t) next; }; -typedef struct EcsMonitor { - int suspend_cnt; - uint8_t outbuf[OUT_BUF_SIZE]; - int outbuf_index; - void *password_opaque; - Error *error; - QLIST_HEAD(, mon_fd_t) fds; - QLIST_ENTRY(EcsMonitor) entry; -}EcsMonitor; - #define MAX_EVENTS 1000 #define MAX_FD_NUM 300 typedef struct ECS_State { @@ -120,7 +110,7 @@ typedef struct ECS_State { int is_unix; int ecs_running; QEMUTimer *alive_timer; - EcsMonitor *mon; + MonitorQMP *mon; } ECS_State; #define TYPE_NONE 0x00 @@ -137,7 +127,7 @@ typedef struct ECS_Client { ecsbuffer sbuff; ECS_State *cs; - ECSJSONMessageParser parser; + JSONMessageParser parser; QTAILQ_ENTRY(ECS_Client) next; }ECS_Client; @@ -180,7 +170,7 @@ int ecs_write(int fd, const uint8_t *buf, int len); void ecs_make_header(QDict *obj, type_length length, type_group group, type_action action); -/* EcsMonitor */ +/* Monitor handler */ void ecs_handle_qmp_command(void *opaque, QObject *req, Error *err); #endif /* __ECS_INTERNAL_H__ */ diff --git a/tizen/src/ecs/ecs_mon.c b/tizen/src/ecs/ecs_mon.c index 4866fbf2a2..42474b97a1 100644 --- a/tizen/src/ecs/ecs_mon.c +++ b/tizen/src/ecs/ecs_mon.c @@ -29,9 +29,7 @@ * */ - -#include "qemu/osdep.h" -#include "qemu-common.h" +#include "emulator_common.h" #include "qemu/queue.h" #include "qemu/sockets.h" #include "qemu/option.h" @@ -42,6 +40,7 @@ #include "block/qdict.h" #include "qapi/error.h" #include "qapi/qmp/qjson.h" +#include "qapi/qmp/qerror.h" #include "qapi/qmp/qstring.h" #include "qapi/qmp/json-parser.h" #include "qapi/qmp/dispatch.h" @@ -56,24 +55,6 @@ #include "debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, ecs); - - -typedef struct mon_cmd_t { - const char *name; - const char *args_type; - const char *params; - const char *help; - void (*cmd)(EcsMonitor *mon, const QDict *qdict); - /* @sub_table is a list of 2nd level of commands. If it do not exist, - * mhandler should be used. If it exist, sub_table[?].mhandler should be - * used, and mhandler of 1st level plays the role of help function. - */ - struct mon_cmd_t *sub_table; - void (*command_completion)(ReadLineState *rs, int nb_args, const char *str); -} mon_cmd_t; - -#define QMP_ACCEPT_UNKNOWNS 1 - bool send_monitor_ntf(const char *data, int size) { ECS__Master master = ECS__MASTER__INIT; @@ -93,61 +74,53 @@ bool send_monitor_ntf(const char *data, int size) return true; } -#if 0 -static void ecs_monitor_flush(ECS_Client *clii, EcsMonitor *mon) -{ - int ret; - if (clii && 0 < clii->client_fd && mon && mon->outbuf_index != 0) { -#if 0 - ret = ecs_write(clii->client_fd, mon->outbuf, mon->outbuf_index); -#endif - ret = send_monitor_ntf((char *)mon->outbuf, mon->outbuf_index); - memset(mon->outbuf, 0, sizeof(mon->outbuf)); - mon->outbuf_index = 0; +static void ecs_monitor_flush(Monitor *mon) +{ + if (mon && mon->outbuf != NULL) { + bool ret = send_monitor_ntf(qstring_get_str(mon->outbuf), qstring_get_length(mon->outbuf)); + qstring_free(mon->outbuf, false); + mon->outbuf = NULL; TRACE("ecs_monitor_flush return value of send_monitor_ntf : %d, \n", ret); } } -static void ecs_monitor_puts(ECS_Client *clii, EcsMonitor *mon, const char *str) +/* flush at every end of line */ +static void ecs_monitor_puts(Monitor *mon, const char *str) { + int i; char c; - if (!clii || !mon) { - return; + if (str == NULL) { + str = "\n"; } - for (;;) { - c = *str++; - if (c == '\0') { - break; - } -#ifndef _WIN32 + LOG_INFO("ecs_monitor_puts - data: %s", str); + + for (i = 0; str[i]; i++) { + c = str[i]; if (c == '\n') { - mon->outbuf[mon->outbuf_index++] = '\r'; +#ifdef _WIN32 + qstring_append_chr(mon->outbuf, '\r'); +#endif // _WIN32 } -#endif - mon->outbuf[mon->outbuf_index++] = c; - if (mon->outbuf_index >= (sizeof(mon->outbuf) - 2) || c == '\n') { - mon->outbuf[mon->outbuf_index++] = 0; - ecs_monitor_flush(clii, mon); + qstring_append_chr(mon->outbuf, c); + if (c == '\n') { + ecs_monitor_flush(mon); } } } static QDict *build_qmp_error_dict(Error *err) { - //TIZEN_VERIFY - QDict *rsp; - - rsp = qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s } }", + QDict *rsp = qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s } }", QapiErrorClass_str(error_get_class(err)), error_get_pretty(err)); - error_free(err); return rsp; } -static void ecs_json_emitter(ECS_Client *clii, const QObject *data) +#if 0 +static void ecs_json_emitter(Monitor *mon, const QObject *data) { QString *json; @@ -156,22 +129,18 @@ static void ecs_json_emitter(ECS_Client *clii, const QObject *data) assert(json != NULL); qstring_append_chr(json, '\n'); - ecs_monitor_puts(clii, clii->cs->mon, qstring_get_str(json)); + ecs_monitor_puts(mon, qstring_get_str(json)); qobject_unref(json); } -static void ecs_protocol_emitter(ECS_Client *clii, const char *type, +static void ecs_protocol_emitter(Monitor *mon, const char *type, QObject *data, Error *err) { - QDict *qmp; + QDict *qmp = NULL; QObject *obj; TRACE("ecs_protocol_emitter called.\n"); -#if 0 - trace_monitor_protocol_emitter(clii->cs->mon); -#endif - if (!err) { /* success response */ if (data) { @@ -195,10 +164,10 @@ static void ecs_protocol_emitter(ECS_Client *clii, const char *type, qmp = build_qmp_error_dict(err); } - ecs_json_emitter(clii, QOBJECT(qmp)); + ecs_json_emitter(mon, QOBJECT(qmp)); qobject_unref(qmp); } - +#endif //0 static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp) { const QDictEntry *ent; @@ -212,6 +181,7 @@ static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp) input_dict = qobject_to(QDict, input_obj); + for (ent = qdict_first(input_dict); ent; ent = qdict_next(input_dict, ent)) { const char *arg_name = qdict_entry_key(ent); @@ -246,35 +216,45 @@ static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp) return input_dict; } -#endif -//TIZEN_VERIFY -#if 0 -/* - * Emit QMP response @rsp to @mon. - * Null @rsp can only happen for commands with QCO_NO_SUCCESS_RESP. - * Nothing is emitted then. - */ static void ecs_monitor_qmp_respond(MonitorQMP *mon, QDict *rsp) { - if (rsp) { - qmp_send_response(mon, rsp); + const QObject *data = QOBJECT(rsp); + QString *json; + + //Add type in response + if (mon->common.outbuf) { + qdict_put(rsp, "type", mon->common.outbuf); + qstring_free(mon->common.outbuf , false); + mon->common.outbuf = NULL; + } else { + qdict_put_str(rsp, "type", "unknown"); } + + json = mon->pretty ? qobject_to_json_pretty(data) : qobject_to_json(data); + assert(json != NULL); + + qstring_append_chr(json, '\n'); + ecs_monitor_puts(&mon->common, qstring_get_str(json)); + + qobject_unref(json); +} + +static bool ecs_qmp_oob_enabled(MonitorQMP *mon) +{ + return mon->capab[QMP_CAPABILITY_OOB]; } -#endif static void ecs_monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) { - //TIZEN_VERIFY. FIXME: Uncomment - #if 0 - EcsMonitor *old_mon; + Monitor *old_mon; QDict *rsp; QDict *error; old_mon = cur_mon; cur_mon = &mon->common; - rsp = qmp_dispatch(mon->commands, req, qmp_oob_enabled(mon)); + rsp = qmp_dispatch(mon->commands, req, ecs_qmp_oob_enabled(mon)); cur_mon = old_mon; @@ -292,26 +272,35 @@ static void ecs_monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) ecs_monitor_qmp_respond(mon, rsp); qobject_unref(rsp); - #endif -} - -static bool ecs_qmp_oob_enabled(MonitorQMP *mon) -{ - return mon->capab[QMP_CAPABILITY_OOB]; } void ecs_handle_qmp_command(void *opaque, QObject *req, Error *err) { - MonitorQMP *mon = opaque; + ECS_Client* ccli = opaque; + MonitorQMP *mon = ccli->cs->mon; QObject *id = NULL; QDict *qdict; - QMPRequest *req_obj; - + Error *local_err = NULL; + assert(!req != !err); - qdict = qobject_to(QDict, req); + if (err) { + local_err = err; + goto out_err; + } + + qdict = qmp_check_input_obj(req, &local_err); + + if (local_err) { + goto out_err; + } if (qdict) { id = qdict_get(qdict, "id"); + if (qdict_haskey(qdict, "type")) { + //store type in outbuf to return in response + mon->common.outbuf = qobject_to(QString, qdict_get(qdict, "type")); + qdict_del(qdict, "type"); + } } /* else will fail qmp_dispatch() */ if (req && trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) { @@ -320,103 +309,27 @@ void ecs_handle_qmp_command(void *opaque, QObject *req, Error *err) qobject_unref(req_json); } - if (qdict && qmp_is_oob(qdict)) { - /* OOB commands are executed immediately */ + if (qdict) { + /* Consider all commands OOB, OOB commands are executed immediately */ trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id) ?: ""); ecs_monitor_qmp_dispatch(mon, req); qobject_unref(req); return; } +out_err: - req_obj = g_new0(QMPRequest, 1); - req_obj->mon = mon; - req_obj->req = req; - req_obj->err = err; - - /* Protect qmp_requests and fetching its length. */ - qemu_mutex_lock(&mon->qmp_queue_lock); - - /* - * Suspend the monitor when we can't queue more requests after - * this one. Dequeuing in monitor_qmp_bh_dispatcher() or - * monitor_qmp_cleanup_queue_and_resume() will resume it. - * Note that when OOB is disabled, we queue at most one command, - * for backward compatibility. - */ - if (!ecs_qmp_oob_enabled(mon) || - mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) { - monitor_suspend(&mon->common); - } - - /* - * Put the request to the end of queue so that requests will be - * handled in time order. Ownership for req_obj, req, - * etc. will be delivered to the handler side. - */ - assert(mon->qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX); - g_queue_push_tail(mon->qmp_requests, req_obj); - qemu_mutex_unlock(&mon->qmp_queue_lock); - - /* Kick the dispatcher routine */ - qemu_bh_schedule(qmp_dispatcher_bh); - /* - QObject *req, *rsp = NULL, *id = NULL; - QDict *qdict = NULL; - ECS_Client *clii = opaque; - Error *err = NULL; - char* type = NULL; - - req = json_parser_parse(tokens, NULL, &err); - if (err || !req || qobject_type(req) != QTYPE_QDICT) { - if (!err) { - error_setg(&err, QERR_JSON_PARSING); - } - goto err_out; - } - - qdict = qmp_check_input_obj(req, &err); - if (!qdict) { - goto err_out; + //emit error response + if (local_err) { + qdict = build_qmp_error_dict(local_err); + ecs_monitor_qmp_respond(mon, qdict); + error_free(local_err); } - - id = qdict_get(qdict, "id"); - qobject_ref(id); - qdict_del(qdict, "id"); - - if (qdict_haskey(qdict, "type")) { - type = g_strdup(qdict_get_str(qdict, "type")); - qdict_del(qdict, "type"); - } - - req = QOBJECT(qdict); - - rsp = qmp_dispatch(req); - - ecs_protocol_emitter(clii, (const char*)type, rsp, err); - - g_free(type); -err_out: - if (err) { - //TIZEN_VERIFY - rsp = qmp_error_response(err); - } - - if (rsp) { - if (id) { - qdict_put_obj(qobject_to(QDict, rsp), "id", id); - id = NULL; - } - } - - qobject_unref(id); - qobject_unref(rsp); - qobject_unref(req);*/ } bool msgproc_monitor_req(ECS_Client *ccli, ECS__MonitorReq *msg) { TRACE(">> monitor req: data = %s\n", msg->command); - ecs_json_message_parser_feed(&(ccli->parser), (const char *) msg->command, strlen(msg->command)); + json_message_parser_feed(&(ccli->parser), (const char *) msg->command, strlen(msg->command)); return true; } diff --git a/tizen/src/ecs/ecs_msg.c b/tizen/src/ecs/ecs_msg.c index 89f5a596fc..0ab6a7aea2 100644 --- a/tizen/src/ecs/ecs_msg.c +++ b/tizen/src/ecs/ecs_msg.c @@ -55,8 +55,6 @@ #include #endif -#include "ecs-json-streamer.h" - #include "hw/virtio/maru_virtio_vmodem.h" #include "hw/virtio/maru_virtio_evdi.h" diff --git a/tizen/src/util/device_hotplug.c b/tizen/src/util/device_hotplug.c index 3f6c0bd3d4..2f8a9af3d8 100644 --- a/tizen/src/util/device_hotplug.c +++ b/tizen/src/util/device_hotplug.c @@ -117,7 +117,7 @@ static bool do_sdcard_attach(const char * const file) gchar *sdcard_drive_id = g_strdup_printf("drive_id_%s", sdcard_img); /* refer from test-replication.c */ - cmdline = g_strdup_printf("driver=qcow2,node-name=sdcard," + cmdline = g_strdup_printf("driver=qcow2,node-name=sdcard,file.locking=off," "file.driver=file,file.filename=%s" , file); opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false); @@ -128,7 +128,7 @@ static bool do_sdcard_attach(const char * const file) qdict = qemu_opts_to_qdict(opts, NULL); qemu_opts_del(opts); - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH, &error_abort); if (error_abort) { goto fail_attach; } -- 2.34.1