[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] Add QMP fsfreeze support
From: |
Jes . Sorensen |
Subject: |
[Qemu-devel] [PATCH] Add QMP fsfreeze support |
Date: |
Tue, 26 Apr 2011 16:49:36 +0200 |
From: Jes Sorensen <address@hidden>
This patch adds the following QMP commands:
qga-guest-fsfreeze:
- Freezes all local file systems in the guest. Command will return
the number of file systems that were frozen.
qga-guest-fsthaw:
- Thaws all local file systems in the guest. Command will return
the number of file systems that were thawed.
Signed-off-by: Jes Sorensen <address@hidden>
---
qapi-schema.json | 24 ++++++
qga/guest-agent-commands.c | 177 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 201 insertions(+), 0 deletions(-)
diff --git a/qapi-schema.json b/qapi-schema.json
index e2f209d..2c86cec 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1562,6 +1562,30 @@
{ 'option': 'blockdev', 'data': 'BlockdevConfig', 'implicit': 'id' }
##
+# @guest-fsfreeze:
+#
+# json gibberish for guest-fsfreeze command
+#
+# Returns: Number of file systems frozen
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-fsfreeze',
+ 'returns': 'int' }
+
+##
+# @guest-fsthaw:
+#
+# json gibberish for guest-fsthaw command
+#
+# Returns: Number of file systems thawed
+#
+# Since: 0.15.0
+##
+{ 'command': 'guest-fsthaw',
+ 'returns': 'int' }
+
+##
# @VncConfig:
#
# Configuration options for the built-in VNC server.
diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
index 843ef36..4bc2c57 100644
--- a/qga/guest-agent-commands.c
+++ b/qga/guest-agent-commands.c
@@ -11,6 +11,10 @@
*/
#include <glib.h>
+#include <mntent.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
#include "guest-agent.h"
static bool enable_syslog = true;
@@ -262,6 +266,179 @@ struct GuestFileSeek *qga_guest_file_seek(int64_t
filehandle, int64_t offset,
return seek_data;
}
+/*
+ * Walk the mount table and build a list of local file systems
+ */
+struct direntry {
+ char *dirname;
+ char *devtype;
+ struct direntry *next;
+};
+
+struct va_freezestate {
+ struct direntry *mount_list;
+ int status;
+};
+
+/*
+ * This should be in a header file, but we have none :(
+ */
+enum va_fsfreeze_status {
+ FREEZE_ERROR = -1,
+ FREEZE_THAWED = 0,
+ FREEZE_INPROGRESS = 1,
+ FREEZE_FROZEN = 2,
+ FREEZE_THAWINPROGRESS = 3,
+};
+
+static struct va_freezestate freezestate;
+
+static int build_mount_list(void)
+{
+ struct mntent *mnt;
+ struct direntry *entry;
+ struct direntry *next;
+ char const *mtab = MOUNTED;
+ FILE *fp;
+
+ fp = setmntent(mtab, "r");
+ if (!fp) {
+ fprintf(stderr, "unable to read mtab\n");
+ goto fail;
+ }
+
+ while ((mnt = getmntent(fp))) {
+ /*
+ * An entry which device name doesn't start with a '/' is
+ * either a dummy file system or a network file system.
+ * Add special handling for smbfs and cifs as is done by
+ * coreutils as well.
+ */
+ if ((mnt->mnt_fsname[0] != '/') ||
+ (strcmp(mnt->mnt_type, "smbfs") == 0) ||
+ (strcmp(mnt->mnt_type, "cifs") == 0)) {
+ continue;
+ }
+
+ entry = qemu_malloc(sizeof(struct direntry));
+ entry->dirname = qemu_strdup(mnt->mnt_dir);
+ entry->devtype = qemu_strdup(mnt->mnt_type);
+ entry->next = freezestate.mount_list;
+
+ freezestate.mount_list = entry;
+ }
+
+ endmntent(fp);
+
+ return 0;
+
+fail:
+ while(freezestate.mount_list) {
+ next = freezestate.mount_list->next;
+ qemu_free(freezestate.mount_list->dirname);
+ qemu_free(freezestate.mount_list->devtype);
+ qemu_free(freezestate.mount_list);
+ freezestate.mount_list = next;
+ }
+
+ return -1;
+}
+
+/*
+ * qga_guest_fsfreeze(): Walk list of mounted file systems in the
+ * guest, and freeze the ones which are real local file systems.
+ * return values: Number of file systems frozen, -1 on error.
+ */
+int64_t qga_guest_fsfreeze(Error **err)
+{
+ struct direntry *entry;
+ int fd, i = 0;
+ int64_t ret;
+ SLOG("va_fsfreeze()");
+
+ if (freezestate.status != FREEZE_THAWED) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = build_mount_list();
+ if (ret < 0) {
+ goto out;
+ }
+
+ freezestate.status = FREEZE_INPROGRESS;
+
+ entry = freezestate.mount_list;
+ while(entry) {
+ fd = qemu_open(entry->dirname, O_RDONLY);
+ if (fd == -1) {
+ ret = errno;
+ goto error;
+ }
+ ret = ioctl(fd, FIFREEZE);
+ close(fd);
+ if (ret < 0 && ret != EOPNOTSUPP) {
+ goto error;
+ }
+
+ entry = entry->next;
+ i++;
+ }
+
+ freezestate.status = FREEZE_FROZEN;
+ ret = i;
+out:
+ return ret;
+error:
+ if (i > 0) {
+ freezestate.status = FREEZE_ERROR;
+ }
+ goto out;
+}
+
+/*
+ * qga_guest_fsthaw(): Walk list of frozen file systems in the guest, and
+ * thaw them.
+ * return values: Number of file systems thawed on success, -1 on error.
+ */
+int64_t qga_guest_fsthaw(Error **err)
+{
+ struct direntry *entry;
+ int fd, i = 0;
+ int64_t ret;
+ SLOG("va_fsthaw()");
+
+ if (freezestate.status != FREEZE_FROZEN) {
+ ret = 0;
+ goto out;
+ }
+
+ while((entry = freezestate.mount_list)) {
+ fd = qemu_open(entry->dirname, O_RDONLY);
+ if (fd == -1) {
+ ret = -1;
+ goto out;
+ }
+ ret = ioctl(fd, FITHAW);
+ close(fd);
+ if (ret < 0 && ret != EOPNOTSUPP) {
+ ret = -1;
+ goto out;
+ }
+
+ freezestate.mount_list = entry->next;
+ qemu_free(entry->dirname);
+ qemu_free(entry->devtype);
+ qemu_free(entry);
+ i++;
+ }
+
+ freezestate.status = FREEZE_THAWED;
+ ret = i;
+out:
+ return ret;
+}
+
void qga_guest_file_close(int64_t filehandle, Error **err)
{
FILE *fh = guest_file_handle_find(filehandle);
--
1.7.4.4
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] Add QMP fsfreeze support,
Jes . Sorensen <=