mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
qemu-ga: execute hook to quiesce the guest on fsfreeze-freeze/thaw
To use the online disk snapshot for online-backup, application-level consistency of the snapshot image is required. However, currently the guest agent can provide only filesystem-level consistency, and the snapshot may contain dirty data, for example, incomplete transactions. This patch provides the opportunity to quiesce applications before snapshot is taken. If --fsfreeze-hook option is specified, the hook is executed with "freeze" argument before the filesystem is frozen by fsfreeze-freeze command. As for fsfreeze-thaw command, the hook is executed with "thaw" argument after the filesystem is thawed. This patch depends on patchset to improve error reporting by Luiz Capitulino: http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg03016.html Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama.qu@hitachi.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com> *clarified usage in help output Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit is contained in:
parent
7b3760879b
commit
ec0f694c11
3 changed files with 117 additions and 1 deletions
|
@ -410,6 +410,66 @@ static void build_fs_mount_list(FsMountList *mounts, Error **err)
|
|||
|
||||
#if defined(CONFIG_FSFREEZE)
|
||||
|
||||
typedef enum {
|
||||
FSFREEZE_HOOK_THAW = 0,
|
||||
FSFREEZE_HOOK_FREEZE,
|
||||
} FsfreezeHookArg;
|
||||
|
||||
const char *fsfreeze_hook_arg_string[] = {
|
||||
"thaw",
|
||||
"freeze",
|
||||
};
|
||||
|
||||
static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
const char *hook;
|
||||
const char *arg_str = fsfreeze_hook_arg_string[arg];
|
||||
Error *local_err = NULL;
|
||||
|
||||
hook = ga_fsfreeze_hook(ga_state);
|
||||
if (!hook) {
|
||||
return;
|
||||
}
|
||||
if (access(hook, X_OK) != 0) {
|
||||
error_setg_errno(err, errno, "can't access fsfreeze hook '%s'", hook);
|
||||
return;
|
||||
}
|
||||
|
||||
slog("executing fsfreeze hook with arg '%s'", arg_str);
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
setsid();
|
||||
reopen_fd_to_null(0);
|
||||
reopen_fd_to_null(1);
|
||||
reopen_fd_to_null(2);
|
||||
|
||||
execle(hook, hook, arg_str, NULL, environ);
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid < 0) {
|
||||
error_setg_errno(err, errno, "failed to create child process");
|
||||
return;
|
||||
}
|
||||
|
||||
ga_wait_child(pid, &status, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(err, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WIFEXITED(status)) {
|
||||
error_setg(err, "fsfreeze hook has terminated abnormally");
|
||||
return;
|
||||
}
|
||||
|
||||
status = WEXITSTATUS(status);
|
||||
if (status) {
|
||||
error_setg(err, "fsfreeze hook has failed with status %d", status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return status of freeze/thaw
|
||||
*/
|
||||
|
@ -436,6 +496,12 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
|
|||
|
||||
slog("guest-fsfreeze called");
|
||||
|
||||
execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(err, local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
QTAILQ_INIT(&mounts);
|
||||
build_fs_mount_list(&mounts, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
|
@ -537,6 +603,9 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
|
|||
|
||||
ga_unset_frozen(ga_state);
|
||||
free_fs_mount_list(&mounts);
|
||||
|
||||
execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, err);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue