In some cases it would be useful to thaw a filesystem by timeout after freezing this filesystem by guest-fsfreeze-freeze-list. Add an optional argument "timeout" to the command.
Signed-off-by: Alexander Ivanov <alexander.iva...@virtuozzo.com> --- qga/commands-posix.c | 21 ++++++++++++++++++--- qga/commands-win32.c | 16 ++++++++++++++-- qga/guest-agent-core.h | 3 ++- qga/main.c | 19 ++++++++++++++++++- qga/qapi-schema.json | 9 ++++++++- 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 26711a1a72..e8a79e0a41 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -707,13 +707,17 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) return GUEST_FSFREEZE_STATUS_THAWED; } -int64_t qmp_guest_fsfreeze_freeze(Error **errp) +int64_t qmp_guest_fsfreeze_freeze(bool has_timeout, int64_t timeout, + Error **errp) { - return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); + return qmp_guest_fsfreeze_freeze_list(false, NULL, has_timeout, timeout, + errp); } int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, strList *mountpoints, + bool has_timeout, + int64_t timeout, Error **errp) { int ret; @@ -734,8 +738,11 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, return -1; } + if (!has_timeout || timeout < 0) { + timeout = 0; + } /* cannot risk guest agent blocking itself on a write in this state */ - ga_set_frozen(ga_state); + ga_set_frozen(ga_state, timeout); ret = qmp_guest_fsfreeze_do_freeze_list(has_mountpoints, mountpoints, mounts, errp); @@ -780,6 +787,12 @@ static void guest_fsfreeze_cleanup(void) } } } + +gboolean ga_frozen_timeout_cb(gpointer data) +{ + guest_fsfreeze_cleanup(); + return G_SOURCE_REMOVE; +} #endif /* linux-specific implementations. avoid this if at all possible. */ @@ -3119,6 +3132,8 @@ int64_t qmp_guest_fsfreeze_freeze(Error **errp) int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, strList *mountpoints, + bool has_timeout, + int64_t timeout, Error **errp) { error_setg(errp, QERR_UNSUPPORTED); diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 618d862c00..51fd6dcd58 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -1221,13 +1221,16 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) * Freeze local file systems using Volume Shadow-copy Service. * The frozen state is limited for up to 10 seconds by VSS. */ -int64_t qmp_guest_fsfreeze_freeze(Error **errp) +int64_t qmp_guest_fsfreeze_freeze(bool has_timeout, int64_t timeout, + Error **errp) { return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); } int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, strList *mountpoints, + bool has_timeout, + int64_t timeout, Error **errp) { int i; @@ -1240,8 +1243,11 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, slog("guest-fsfreeze called"); + if (!has_timeout || timeout < 0) { + timeout = 0; + } /* cannot risk guest agent blocking itself on a write in this state */ - ga_set_frozen(ga_state); + ga_set_frozen(ga_state, timeout); qga_vss_fsfreeze(&i, true, mountpoints, &local_err); if (local_err) { @@ -1299,6 +1305,12 @@ static void guest_fsfreeze_cleanup(void) vss_deinit(true); } +gboolean ga_frozen_timeout_cb(gpointer data) +{ + guest_fsfreeze_cleanup(); + return G_SOURCE_REMOVE; +} + /* * Walk list of mounted file systems in the guest, and discard unused * areas. diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h index b4e7c52c61..d8d1bb9505 100644 --- a/qga/guest-agent-core.h +++ b/qga/guest-agent-core.h @@ -39,8 +39,9 @@ void ga_enable_logging(GAState *s); void G_GNUC_PRINTF(1, 2) slog(const gchar *fmt, ...); void ga_set_response_delimited(GAState *s); bool ga_is_frozen(GAState *s); -void ga_set_frozen(GAState *s); +void ga_set_frozen(GAState *s, int64_t timeout); void ga_unset_frozen(GAState *s); +gboolean ga_frozen_timeout_cb(gpointer data); const char *ga_fsfreeze_hook(GAState *s); int64_t ga_get_fd_handle(GAState *s, Error **errp); int ga_parse_whence(GuestFileWhence *whence, Error **errp); diff --git a/qga/main.c b/qga/main.c index 8668b9f3d3..6c7c7d68d8 100644 --- a/qga/main.c +++ b/qga/main.c @@ -94,6 +94,7 @@ struct GAState { const char *pid_filepath; } deferred_options; #ifdef CONFIG_FSFREEZE + guint frozen_timeout_id; const char *fsfreeze_hook; #endif gchar *pstate_filepath; @@ -478,7 +479,7 @@ bool ga_is_frozen(GAState *s) return s->frozen; } -void ga_set_frozen(GAState *s) +void ga_set_frozen(GAState *s, int64_t timeout) { if (ga_is_frozen(s)) { return; @@ -492,6 +493,15 @@ void ga_set_frozen(GAState *s) g_warning("unable to create %s, fsfreeze may not function properly", s->state_filepath_isfrozen); } +#ifdef CONFIG_FSFREEZE + if (timeout) { + s->frozen_timeout_id = g_timeout_add_seconds(timeout, + ga_frozen_timeout_cb, + NULL); + } else { + s->frozen_timeout_id = 0; + } +#endif } void ga_unset_frozen(GAState *s) @@ -500,6 +510,13 @@ void ga_unset_frozen(GAState *s) return; } +#ifdef CONFIG_FSFREEZE + /* remove timeout callback */ + if (s->frozen_timeout_id) { + g_source_remove(s->frozen_timeout_id); + } +#endif + /* if we delayed creation/opening of pid/log files due to being * in a frozen state at start up, do it now */ diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index e96d463639..29ad342f0a 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -440,6 +440,9 @@ # command succeeded, you may call @guest-fsfreeze-thaw later to # unfreeze. # +# @timeout: after this period in seconds filesystems will be thawed +# (since 8.2) +# # Note: On Windows, the command is implemented with the help of a # Volume Shadow-copy Service DLL helper. The frozen state is # limited for up to 10 seconds by VSS. @@ -452,6 +455,7 @@ # Since: 0.15.0 ## { 'command': 'guest-fsfreeze-freeze', + 'data': { '*timeout': 'int' }, 'returns': 'int' } ## @@ -464,13 +468,16 @@ # If omitted, every mounted filesystem is frozen. Invalid mount # points are ignored. # +# @timeout: after this period in seconds filesystems will be thawed +# (since 8.2) +# # Returns: Number of file systems currently frozen. On error, all # filesystems will be thawed. # # Since: 2.2 ## { 'command': 'guest-fsfreeze-freeze-list', - 'data': { '*mountpoints': ['str'] }, + 'data': { '*mountpoints': ['str'], '*timeout': 'int' }, 'returns': 'int' } ## -- 2.34.1