Skip to contentSkip to conversation

add file: migration support

PATCH In review Charles Duffy 3 participants 3 messages Nov 13, 2008 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 add file: migration support

This patch adds support for migration to and from file: targets, moves common helpers between exec: and file: use cases from migration-exec.c to migration.c, and adds a qemu_fdopen() helper parallel to qemu_fopen().

.gitignore +1 -1
index e70ebab..8e28325 100644
@@ -30,4 +30,4 @@ qemu-nbd.8
 *.tp
 *.vr
 *.d
-
+*.o
Makefile +2 -2
index 3ed8b2a..a5db522 100644
@@ -78,8 +78,8 @@ OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o
 OBJS+=usb-serial.o usb-net.o
 OBJS+=sd.o ssi-sd.o
 OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
-OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
-OBJS+=qemu-char.o aio.o net-checksum.o savevm.o
+OBJS+=buffered_file.o migration.o migration-file.o migration-tcp.o net.o
+OBJS+=qemu-sockets.o qemu-char.o aio.o net-checksum.o savevm.o
 
 ifdef CONFIG_BRLAPI
 OBJS+= baum.o
hw/hw.h +1 -0
index eab7bb4..4d5ae42 100644
@@ -35,6 +35,7 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
                          QEMUFileRateLimit *rate_limit);
 QEMUFile *qemu_fopen(const char *filename, const char *mode);
 QEMUFile *qemu_fopen_socket(int fd);
+QEMUFile *qemu_fdopen(int fd, const char *mode);
 QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
 QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
 void qemu_fflush(QEMUFile *f);
migration-exec.c +2 -12
index caeed4b..f625689 100644
@@ -32,16 +32,6 @@
     do { } while (0)
 #endif
 
-static int file_errno(FdMigrationState *s)
-{
-    return errno;
-}
-
-static int file_write(FdMigrationState *s, const void * buf, size_t size)
-{
-    return write(s->fd, buf, size);
-}
-
 static int exec_close(FdMigrationState *s)
 {
     dprintf("exec_close\n");
@@ -86,8 +76,8 @@ MigrationState *exec_start_outgoing_migration(const char *command,
     s->opaque = qemu_popen(f, "w");
 
     s->close = exec_close;
-    s->get_error = file_errno;
-    s->write = file_write;
+    s->get_error = migrate_file_errno;
+    s->write = migrate_file_write;
     s->mig_state.cancel = migrate_fd_cancel;
     s->mig_state.get_status = migrate_fd_get_status;
     s->mig_state.release = migrate_fd_release;
migration-file.c new file +119 -0

119 lines not on this page · raw message

migration.c +19 -0
index 0ef777a..709ee49 100644
@@ -40,6 +40,8 @@ void qemu_start_incoming_migration(const char *uri)
 
     if (strstart(uri, "tcp:", &p))
         tcp_start_incoming_migration(p);
+    else if (strstart(uri, "file:", &p))
+        file_start_incoming_migration(p);
 #if !defined(WIN32)
     else if (strstart(uri, "exec:", &p))
         exec_start_incoming_migration(p);
@@ -55,6 +57,8 @@ void do_migrate(int detach, const char *uri)
 
     if (strstart(uri, "tcp:", &p))
         s = tcp_start_outgoing_migration(p, max_throttle, detach);
+    else if (strstart(uri, "file:", &p))
+        s = file_start_outgoing_migration(p, max_throttle, detach);
 #if !defined(WIN32)
     else if (strstart(uri, "exec:", &p))
         s = exec_start_outgoing_migration(p, max_throttle, detach);
@@ -279,3 +283,18 @@ int migrate_fd_close(void *opaque)
     FdMigrationState *s = opaque;
     return s->close(s);
 }
+
+int migrate_file_errno(FdMigrationState *s)
+{
+    return errno;
+}
+
+int migrate_file_write(FdMigrationState *s, const void * buf, size_t size)
+{
+    return write(s->fd, buf, size);
+}
+
+int migrate_file_close(FdMigrationState *s)
+{
+    return close(s->fd);
+}
migration.h +12 -0
index 953ec70..dcbda39 100644
@@ -61,6 +61,12 @@ MigrationState *exec_start_outgoing_migration(const char *host_port,
 					     int64_t bandwidth_limit,
 					     int detach);
 
+int file_start_incoming_migration(const char *filename);
+
+MigrationState *file_start_outgoing_migration(const char *filename,
+                                             int64_t bandwidth_limit,
+                                             int async);
+
 int tcp_start_incoming_migration(const char *host_port);
 
 MigrationState *tcp_start_outgoing_migration(const char *host_port,
@@ -89,6 +95,12 @@ void migrate_fd_wait_for_unfreeze(void *opaque);
 
 int migrate_fd_close(void *opaque);
 
+int migrate_file_errno(FdMigrationState *s);
+
+int migrate_file_write(FdMigrationState *s, const void * buf, size_t size);
+
+int migrate_file_close(FdMigrationState *s);
+
 static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state)
 {
     return container_of(mig_state, FdMigrationState, mig_state);
savevm.c +24 -1
index 1ee5a6f..8f5fd16 100644
@@ -226,7 +226,6 @@ QEMUFile *qemu_popen(FILE *popen_file, const char *mode)
     } else {
         s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL);
     }
-    fprintf(stderr, "qemu_popen: returning result of qemu_fopen_ops\n");
     return s->file;
 }
 
@@ -283,6 +282,30 @@ static int file_close(void *opaque)
     return 0;
 }
 
+QEMUFile *qemu_fdopen(int fd, const char *mode)
+{
+    QEMUFileStdio *s;
+
+    s = qemu_mallocz(sizeof(QEMUFileStdio));
+    if (!s)
+        return NULL;
+
+    s->outfile = fdopen(fd, mode);
+    if (!s->outfile)
+        goto fail;
+
+    if (!strcmp(mode, "wb"))
+        return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL);
+    else if (!strcmp(mode, "rb"))
+        return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL);
+
+fail:
+    if (s->outfile)
+        fclose(s->outfile);
+    qemu_free(s);
+    return NULL;
+}
+
 QEMUFile *qemu_fopen(const char *filename, const char *mode)
 {
     QEMUFileStdio *s;
#1 lore raw

Oops -- didn't mean to include my local .gitignore changes in that.

#2 lore raw
In reply to Charles Duffy
Quoted 9 lines · Charles Duffy

This patch adds support for migration to and from file: targets, moves common helpers between exec: and file: use cases from migration-exec.c to migration.c, and adds a qemu_fdopen() helper parallel to qemu_fopen().

.gitignore +0 -0
index e70ebab..8e28325 100644

.gitignore qemu-nbd.8 · line 33

Quoted 5 lines
.gitignore +1 -1
@@ -30,4 +30,4 @@ qemu-nbd.8
 *.tp
 *.vr
 *.d
-
+*.o

Please keep this sort of stuff separate from a general patch.

.gitignore

Quoted 11 lines
.gitignore +10 -0
+    s->fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+    if (s->fd == -1) {
+        perror("Unable to open migration target");
+        goto err_after_alloc;
+    }
+
+    if (fcntl(s->fd, F_SETFD, O_NONBLOCK) == -1) {
+        dprintf("Unable to set nonblocking mode on file descriptor\n");
+        goto err_after_open;
+    }

Did you mean F_SETFL?

At any rate, this doesn't do what you think it does. O_NONBLOCK still blocks with a file. To implement a proper file: migration protocol, you have to use something like posix-aio to write to the file asychronously.

You can observe the problem here by setting the migration data limit to something very, very high (like 10GB). That will cause the VM to become unresponsive until all the data is on disk which is certainly not live migration.

Regards,

Anthony Liguori