From: Tomoki Sekiyama <tomoki.sekiyama.qu@hitachi.com>
To: qemu-devel@nongnu.org
Cc: mdroth@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH 1/2] qemu-ga: execute script to quiesce the guest on fsfreeze-freeze/thaw
Date: Thu, 08 Nov 2012 21:05:03 +0900 [thread overview]
Message-ID: <509B9FEF.4040604@hitachi.com> (raw)
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.
When the qemu-ga receives fsfreeze-freeze command, the script specified
in --fsfreeze-script option is executed with "freeze" argument before the
filesystem is frozen. For fsfreeze-thaw command, the script is executed
with "thaw" argument after the filesystem is thawed.
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama.qu@hitachi.com>
---
qemu-ga.c | 42 +++++++++++++++++++++++++++++++++++++++++-
qga/commands-posix.c | 34 ++++++++++++++++++++++++++++++++++
qga/guest-agent-core.h | 2 ++
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/qemu-ga.c b/qemu-ga.c
index 9b59a52..7cb682e 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -34,6 +34,12 @@
#include "qga/service-win32.h"
#include <windows.h>
#endif
+#ifdef __linux__
+#include <linux/fs.h>
+#ifdef FIFREEZE
+#define CONFIG_FSFREEZE
+#endif
+#endif
#ifndef _WIN32
#define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
@@ -42,6 +48,9 @@
#endif
#define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run"
#define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid"
+#ifdef CONFIG_FSFREEZE
+#define QGA_FSFREEZE_SCRIPT_DEFAULT CONFIG_QEMU_CONFDIR "/fsfreeze.sh"
+#endif
#define QGA_SENTINEL_BYTE 0xFF
struct GAState {
@@ -64,6 +73,9 @@ struct GAState {
const char *log_filepath;
const char *pid_filepath;
} deferred_options;
+#ifdef CONFIG_FSFREEZE
+ const char *fsfreeze_script;
+#endif
};
struct GAState *ga_state;
@@ -153,6 +165,10 @@ static void usage(const char *cmd)
" %s)\n"
" -l, --logfile set logfile path, logs to stderr by default\n"
" -f, --pidfile specify pidfile (default is %s)\n"
+#ifdef CONFIG_FSFREEZE
+" -F, --fsfreeze_script\n"
+" specify fsfreeze script (default is %s)\n"
+#endif
" -t, --statedir specify dir to store state information (absolute paths\n"
" only, default is %s)\n"
" -v, --verbose log extra debugging information\n"
@@ -167,6 +183,9 @@ static void usage(const char *cmd)
"\n"
"Report bugs to <mdroth@linux.vnet.ibm.com>\n"
, cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
+#ifdef CONFIG_FSFREEZE
+ QGA_FSFREEZE_SCRIPT_DEFAULT,
+#endif
QGA_STATEDIR_DEFAULT);
}
@@ -401,6 +420,13 @@ void ga_unset_frozen(GAState *s)
}
}
+#ifdef CONFIG_FSFREEZE
+const char *ga_fsfreeze_script(GAState *s)
+{
+ return s->fsfreeze_script;
+}
+#endif
+
static void become_daemon(const char *pidfile)
{
#ifndef _WIN32
@@ -678,10 +704,13 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
int main(int argc, char **argv)
{
- const char *sopt = "hVvdm:p:l:f:b:s:t:";
+ const char *sopt = "hVvdm:p:l:f:F:b:s:t:";
const char *method = NULL, *path = NULL;
const char *log_filepath = NULL;
const char *pid_filepath = QGA_PIDFILE_DEFAULT;
+#ifdef CONFIG_FSFREEZE
+ const char *fsfreeze_script = QGA_FSFREEZE_SCRIPT_DEFAULT;
+#endif
const char *state_dir = QGA_STATEDIR_DEFAULT;
#ifdef _WIN32
const char *service = NULL;
@@ -691,6 +720,9 @@ int main(int argc, char **argv)
{ "version", 0, NULL, 'V' },
{ "logfile", 1, NULL, 'l' },
{ "pidfile", 1, NULL, 'f' },
+#ifdef CONFIG_FSFREEZE
+ { "fsfreeze-script", 1, NULL, 'F' },
+#endif
{ "verbose", 0, NULL, 'v' },
{ "method", 1, NULL, 'm' },
{ "path", 1, NULL, 'p' },
@@ -723,6 +755,11 @@ int main(int argc, char **argv)
case 'f':
pid_filepath = optarg;
break;
+#ifdef CONFIG_FSFREEZE
+ case 'F':
+ fsfreeze_script = optarg;
+ break;
+#endif
case 't':
state_dir = optarg;
break;
@@ -786,6 +823,9 @@ int main(int argc, char **argv)
s = g_malloc0(sizeof(GAState));
s->log_level = log_level;
s->log_file = stderr;
+#ifdef CONFIG_FSFREEZE
+ s->fsfreeze_script = fsfreeze_script;
+#endif
g_log_set_default_handler(ga_log, s);
g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR);
ga_enable_logging(s);
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 726930a..007c0a3 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -13,6 +13,7 @@
#include <glib.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include "qga/guest-agent-core.h"
@@ -396,6 +397,34 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
return GUEST_FSFREEZE_STATUS_THAWED;
}
+int execute_fsfreeze_script(const char *arg)
+{
+ int ret = -1;
+ const char *fsfreeze_script;
+ char *cmdline;
+ struct stat st;
+
+ fsfreeze_script = ga_fsfreeze_script(ga_state);
+ if (fsfreeze_script && stat(fsfreeze_script, &st) == 0) {
+ if (S_ISREG(st.st_mode) && (st.st_mode & S_IXUSR)) {
+ slog("executing fsfreeze script with arg `%s'", arg);
+ cmdline = malloc(strlen(fsfreeze_script) + strlen(arg) + 2);
+ if (cmdline) {
+ sprintf(cmdline, "%s %s", fsfreeze_script, arg);
+ ret = system(cmdline);
+ free(cmdline);
+ }
+ if (ret > 0) {
+ g_warning("fsfreeze script failed with status=%d", ret);
+ } else if (ret == -1) {
+ g_warning("execution of fsfreeze script failed: %s",
+ strerror(errno));
+ }
+ }
+ }
+ return ret;
+}
+
/*
* Walk list of mounted file systems in the guest, and freeze the ones which
* are real local file systems.
@@ -410,6 +439,8 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
slog("guest-fsfreeze called");
+ execute_fsfreeze_script("freeze");
+
QTAILQ_INIT(&mounts);
ret = build_fs_mount_list(&mounts);
if (ret < 0) {
@@ -513,6 +544,9 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
ga_unset_frozen(ga_state);
free_fs_mount_list(&mounts);
+
+ execute_fsfreeze_script("thaw");
+
return i;
}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index 49a7abe..b466bfd 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -34,6 +34,8 @@ void ga_set_response_delimited(GAState *s);
bool ga_is_frozen(GAState *s);
void ga_set_frozen(GAState *s);
void ga_unset_frozen(GAState *s);
+const char *ga_fsfreeze_script(GAState *s);
+int execute_fsfreeze_script(const char *arg);
#ifndef _WIN32
void reopen_fd_to_null(int fd);
--
1.7.11.7
next reply other threads:[~2012-11-08 12:04 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-08 12:05 Tomoki Sekiyama [this message]
2012-11-08 12:36 ` [Qemu-devel] [PATCH 2/2] qemu-ga: sample fsfreeze-script Tomoki Sekiyama
2012-11-08 18:25 ` Eric Blake
2012-11-12 4:10 ` Tomoki Sekiyama
2012-11-08 18:38 ` [Qemu-devel] [PATCH 1/2] qemu-ga: execute script to quiesce the guest on fsfreeze-freeze/thaw Eric Blake
2012-11-12 4:10 ` Tomoki Sekiyama
-- strict thread matches above, loose matches on Subject: below --
2012-11-08 12:36 Tomoki Sekiyama
2012-11-09 3:05 ` Lei Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=509B9FEF.4040604@hitachi.com \
--to=tomoki.sekiyama.qu@hitachi.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.