Save all tap fd's in canonical order, leveraging the index argument of cpr_save_fd. For the i'th queue, the tap device fd is saved at index 2*i, and the vhostfd (if any) at index 2*i+1.
tap and vhost fd's are passed by name to the monitor when a NIC is hot plugged, but the name is not known to qemu after cpr-exec. Allow the manager to pass -1 for the fd "name" in the new qemu args to indicate that qemu should search for a saved value. Example: -netdev tap,id=hostnet2,fds=-1:-1,vhostfds=-1:-1 Signed-off-by: Steve Sistare <steven.sist...@oracle.com> --- net/tap.c | 55 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/net/tap.c b/net/tap.c index 20e4dae..4d57a53 100644 --- a/net/tap.c +++ b/net/tap.c @@ -35,6 +35,7 @@ #include "net/eth.h" #include "net/net.h" #include "clients.h" +#include "migration/cpr.h" #include "monitor/monitor.h" #include "sysemu/sysemu.h" #include "qapi/error.h" @@ -290,6 +291,8 @@ static void tap_cleanup(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); + cpr_delete_fd_all(nc->name); + if (s->vhost_net) { vhost_net_cleanup(s->vhost_net); g_free(s->vhost_net); @@ -636,13 +639,17 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, return fd; } +/* CPR fd's for each queue are saved at these indices */ +#define TAP_FD_INDEX(queue) (2 * (queue) + 0) +#define TAP_VHOSTFD_INDEX(queue) (2 * (queue) + 1) + #define MAX_TAP_QUEUES 1024 static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, const char *model, const char *name, const char *ifname, const char *script, const char *downscript, const char *vhostfdname, - int vnet_hdr, int fd, Error **errp) + int vnet_hdr, int fd, int index, Error **errp) { Error *err = NULL; TAPState *s = net_tap_fd_init(peer, model, name, fd, vnet_hdr); @@ -682,7 +689,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } if (vhostfdname) { - vhostfd = monitor_fd_param(monitor_cur(), vhostfdname, &err); + vhostfd = cpr_get_fd_param(name, vhostfdname, index, &err); if (vhostfd == -1) { error_propagate(errp, err); goto failed; @@ -693,7 +700,10 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, goto failed; } } else { - vhostfd = open("/dev/vhost-net", O_RDWR); + vhostfd = cpr_find_fd(name, index); + if (vhostfd < 0) { + vhostfd = open("/dev/vhost-net", O_RDWR); + } if (vhostfd < 0) { error_setg_errno(errp, errno, "tap: open vhost char device failed"); @@ -703,6 +713,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, error_setg_errno(errp, errno, "Failed to set FD nonblocking"); goto failed; } + cpr_resave_fd(name, index, vhostfd); } options.opaque = (void *)(uintptr_t)vhostfd; options.nvqs = 2; @@ -721,6 +732,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, return; failed: + cpr_delete_fd_all(name); qemu_del_net_client(&s->nc); } @@ -789,7 +801,7 @@ int net_init_tap(const Netdev *netdev, const char *name, goto out; } - fd = monitor_fd_param(monitor_cur(), tap->fd, errp); + fd = cpr_get_fd_param(name, tap->fd, TAP_FD_INDEX(0), errp); if (fd == -1) { ret = -1; goto out; @@ -812,13 +824,14 @@ int net_init_tap(const Netdev *netdev, const char *name, net_init_tap_one(tap, peer, "tap", name, NULL, script, downscript, - vhostfdname, vnet_hdr, fd, &err); + vhostfdname, vnet_hdr, fd, TAP_VHOSTFD_INDEX(0), &err); if (err) { error_propagate(errp, err); close(fd); ret = -1; goto out; } + } else if (tap->fds) { char **fds; char **vhost_fds; @@ -849,7 +862,7 @@ int net_init_tap(const Netdev *netdev, const char *name, } for (i = 0; i < nfds; i++) { - fd = monitor_fd_param(monitor_cur(), fds[i], errp); + fd = cpr_get_fd_param(name, fds[i], TAP_FD_INDEX(i), errp); if (fd == -1) { ret = -1; goto free_fail; @@ -878,7 +891,7 @@ int net_init_tap(const Netdev *netdev, const char *name, net_init_tap_one(tap, peer, "tap", name, ifname, script, downscript, tap->vhostfds ? vhost_fds[i] : NULL, - vnet_hdr, fd, &err); + vnet_hdr, fd, TAP_VHOSTFD_INDEX(i), &err); if (err) { error_propagate(errp, err); ret = -1; @@ -906,9 +919,12 @@ free_fail: goto out; } - fd = net_bridge_run_helper(tap->helper, - tap->br ?: DEFAULT_BRIDGE_INTERFACE, - errp); + fd = cpr_find_fd(name, TAP_FD_INDEX(0)); + if (fd < 0) { + fd = net_bridge_run_helper(tap->helper, + tap->br ?: DEFAULT_BRIDGE_INTERFACE, + errp); + } if (fd == -1) { ret = -1; goto out; @@ -928,13 +944,15 @@ free_fail: net_init_tap_one(tap, peer, "bridge", name, ifname, script, downscript, vhostfdname, - vnet_hdr, fd, &err); + vnet_hdr, fd, TAP_VHOSTFD_INDEX(0), &err); if (err) { error_propagate(errp, err); close(fd); ret = -1; goto out; } + cpr_resave_fd(name, TAP_FD_INDEX(0), fd); + } else { g_autofree char *default_script = NULL; g_autofree char *default_downscript = NULL; @@ -959,8 +977,11 @@ free_fail: } for (i = 0; i < queues; i++) { - fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script, - ifname, sizeof ifname, queues > 1, errp); + fd = cpr_find_fd(name, TAP_FD_INDEX(i)); + if (fd < 0) { + fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script, + ifname, sizeof ifname, queues > 1, errp); + } if (fd == -1) { ret = -1; goto out; @@ -978,17 +999,23 @@ free_fail: net_init_tap_one(tap, peer, "tap", name, ifname, i >= 1 ? "no" : script, i >= 1 ? "no" : downscript, - vhostfdname, vnet_hdr, fd, &err); + vhostfdname, vnet_hdr, + fd, TAP_VHOSTFD_INDEX(i), + &err); if (err) { error_propagate(errp, err); close(fd); ret = -1; goto out; } + cpr_resave_fd(name, TAP_FD_INDEX(i), fd); } } out: + if (ret) { + cpr_delete_fd_all(name); + } return ret; } -- 1.8.3.1