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.ivanov@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
I think it is better to check that timeout <= 10 sec in the case of Windows.
Anyway this is a VSS limitation and FS will be unfrozen earlier if timeout
> 10 sec,
this can cause some misunderstanding from a user.
timeout option sounds good in the guest-fsfreeze-freeze command.
In guest-fsfreeze-freeze-list, it looks strange to me. Command returns
list but takes timeout option. Can you explain timeout usage in this
command?
On Wed, Oct 25, 2023 at 5:01 PM Alexander Ivanov <
alexander.ivanov@virtuozzo.com> wrote:
> 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.ivanov@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
>
>
On 10/26/23 11:16, Konstantin Kostiuk wrote:
>
> I think it is better to check that timeout <= 10 sec in the case of
> Windows.
> Anyway this is a VSS limitation and FS will be unfrozen earlier if
> timeout > 10 sec,
> this can cause some misunderstanding from a user.
Thank you, will pay attention.
>
> timeout option sounds good in the guest-fsfreeze-freeze command.
> In guest-fsfreeze-freeze-list, it looks strange to me. Command returns
> list but takes timeout option. Can you explain timeout usage in this
> command?
The second command doesn't return a list, it takes a list of mountpoints.
Both of the commands freeze local guest filesystems. The first one
freezes all the FS,
the second one freeze only FS from the given list.
>
> On Wed, Oct 25, 2023 at 5:01 PM Alexander Ivanov
> <alexander.ivanov@virtuozzo.com> wrote:
>
> 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.ivanov@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
>
--
Best regards,
Alexander Ivanov
On Mon, Oct 30, 2023 at 6:32 PM Alexander Ivanov <
alexander.ivanov@virtuozzo.com> wrote:
>
>
> On 10/26/23 11:16, Konstantin Kostiuk wrote:
> >
> > I think it is better to check that timeout <= 10 sec in the case of
> > Windows.
> > Anyway this is a VSS limitation and FS will be unfrozen earlier if
> > timeout > 10 sec,
> > this can cause some misunderstanding from a user.
> Thank you, will pay attention.
> >
> > timeout option sounds good in the guest-fsfreeze-freeze command.
> > In guest-fsfreeze-freeze-list, it looks strange to me. Command returns
> > list but takes timeout option. Can you explain timeout usage in this
> > command?
> The second command doesn't return a list, it takes a list of mountpoints.
> Both of the commands freeze local guest filesystems. The first one
> freezes all the FS,
> the second one freeze only FS from the given list.
>
Oh, sorry, my mistake.
Just comment about VSS limitation.
Best Regards,
Konstantin Kostiuk.
> >
> > On Wed, Oct 25, 2023 at 5:01 PM Alexander Ivanov
> > <alexander.ivanov@virtuozzo.com> wrote:
> >
> > 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.ivanov@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
> >
>
> --
> Best regards,
> Alexander Ivanov
>
>
© 2016 - 2026 Red Hat, Inc.