diff --git a/migration/Makefile.objs b/migration/Makefile.objs
index 521a83b..2d1d8cd 100644
--- a/migration/Makefile.objs
+++ b/migration/Makefile.objs
@@ -1,11 +1,11 @@
-common-obj-y += migration.o tcp.o unix.o
+common-obj-y += migration.o tcp.o unix.o fd.o
 common-obj-y += vmstate.o
 common-obj-y += qemu-file.o qemu-file-unix.o qemu-file-stdio.o
 common-obj-y += qemu-file-channel.o
 common-obj-y += xbzrle.o
 
 common-obj-$(CONFIG_RDMA) += rdma.o
-common-obj-$(CONFIG_POSIX) += exec.o fd.o
+common-obj-$(CONFIG_POSIX) += exec.o
 
 common-obj-y += block.o
 
diff --git a/migration/fd.c b/migration/fd.c
index 3e4bed0..8d48e0d 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -20,6 +20,8 @@
 #include "monitor/monitor.h"
 #include "migration/qemu-file.h"
 #include "block/block.h"
+#include "io/channel-file.h"
+#include "io/channel-socket.h"
 
 //#define DEBUG_MIGRATION_FD
 
@@ -33,56 +35,71 @@
 
 static bool fd_is_socket(int fd)
 {
-    struct stat stat;
-    int ret = fstat(fd, &stat);
-    if (ret == -1) {
-        /* When in doubt say no */
-        return false;
-    }
-    return S_ISSOCK(stat.st_mode);
+    int optval;
+    socklen_t optlen;
+    optlen = sizeof(optval);
+    return getsockopt(fd,
+                      SOL_SOCKET,
+                      SO_TYPE,
+                      (char *)&optval,
+                      &optlen) == 0;
 }
 
 void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
 {
+    QIOChannel *ioc;
     int fd = monitor_get_fd(cur_mon, fdname, errp);
     if (fd == -1) {
         return;
     }
 
     if (fd_is_socket(fd)) {
-        s->file = qemu_fopen_socket(fd, "wb");
+        ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fd, errp));
+        if (!ioc) {
+            close(fd);
+            return;
+        }
     } else {
-        s->file = qemu_fdopen(fd, "wb");
+        ioc = QIO_CHANNEL(qio_channel_file_new_fd(fd));
     }
+    s->file = qemu_fopen_channel_output(ioc);
 
     migrate_fd_connect(s);
 }
 
-static void fd_accept_incoming_migration(void *opaque)
+static gboolean fd_accept_incoming_migration(QIOChannel *ioc,
+                                             GIOCondition condition,
+                                             gpointer opaque)
 {
     QEMUFile *f = opaque;
-
-    qemu_set_fd_handler(qemu_get_fd(f), NULL, NULL, NULL);
     process_incoming_migration(f);
+    return FALSE;
 }
 
 void fd_start_incoming_migration(const char *infd, Error **errp)
 {
-    int fd;
     QEMUFile *f;
+    QIOChannel *ioc;
+    int fd;
 
     DPRINTF("Attempting to start an incoming migration via fd\n");
 
     fd = strtol(infd, NULL, 0);
     if (fd_is_socket(fd)) {
-        f = qemu_fopen_socket(fd, "rb");
+        ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fd, errp));
+        if (!ioc) {
+            close(fd);
+            return;
+        }
     } else {
-        f = qemu_fdopen(fd, "rb");
-    }
-    if(f == NULL) {
-        error_setg_errno(errp, errno, "failed to open the source descriptor");
-        return;
+        ioc = QIO_CHANNEL(qio_channel_file_new_fd(fd));
     }
+    f = qemu_fopen_channel_input(ioc);
+    object_unref(OBJECT(ioc));
 
-    qemu_set_fd_handler(fd, fd_accept_incoming_migration, NULL, f);
+    qio_channel_add_watch(ioc,
+                          G_IO_IN,
+                          fd_accept_incoming_migration,
+                          f,
+                          NULL);
 }
diff --git a/migration/migration.c b/migration/migration.c
index bd7024f..f8cf8dc 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -259,10 +259,8 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
 #endif
     } else if (strstart(uri, "unix:", &p)) {
         unix_start_incoming_migration(p, errp);
-#if !defined(WIN32)
     } else if (strstart(uri, "fd:", &p)) {
         fd_start_incoming_migration(p, errp);
-#endif
     } else {
         error_setg(errp, "unknown migration protocol: %s", uri);
     }
@@ -752,10 +750,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
 #endif
     } else if (strstart(uri, "unix:", &p)) {
         unix_start_outgoing_migration(s, p, &local_err);
-#if !defined(WIN32)
     } else if (strstart(uri, "fd:", &p)) {
         fd_start_outgoing_migration(s, p, &local_err);
-#endif
     } else {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
                    "a valid migration protocol");
