@samitouri / QOSamiQemu / commits / 7a3c892c3d

net/tap: fix vhostfds/vhostfd parameters API

There is a bug in the interface: we don't allow vhostfds argument together with queues. But we allow vhostfd, and try use it for all queues of multiqueue TAP. Let's relax the restriction. We already check that number of vhost fds match queues (or number of fds). So, no matter do vhost fds come from vhostfds or vhostfd argument. Let's use correct vhost fds for multiqueue TAP. To achieve this we move vhost fds parsing to separate function and call it earlier in net_init_tap(). Then we have vhost fds available (and already checked) for all further cases. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Reviewed-by: Ben Chaney <bchaney@akamai.com> Signed-off-by: Jason Wang <jasowang@redhat.com>

Vladimir Sementsov-Ogievskiy committed Mar 18, 2026 at 14:31 UTC 7a3c892c3d419c176ad743a1f8aa27197c0703ec
1 file changed +30 -33
net/tap.c
+30 -33
@@ -836,11 +836,32 @@ static int tap_parse_fds_and_queues(const NetdevTapOptions *tap, int **fds,
836 return queues;
837 }
838
839 +static bool tap_parse_vhost_fds(const NetdevTapOptions *tap, int **vhost_fds,
840 + int queues, Error **errp)
841 +{
842 + if (!(tap->vhostfd || tap->vhostfds)) {
843 + *vhost_fds = NULL;
844 + return true;
845 + }
846 +
847 + if (net_parse_fds(tap->vhostfd ?: tap->vhostfds,
848 + vhost_fds, queues, errp) < 0) {
849 + return false;
850 + }
851 +
852 + if (!unblock_fds(*vhost_fds, queues, errp)) {
853 + net_free_fds(*vhost_fds, queues);
854 + return false;
855 + }
856 +
857 + return true;
858 +}
859 +
860 int net_init_tap(const Netdev *netdev, const char *name,
861 NetClientState *peer, Error **errp)
862 {
863 const NetdevTapOptions *tap;
843 - int fd = -1, vhostfd = -1, vnet_hdr = 0, i = 0, queues;
864 + int fd = -1, vnet_hdr = 0, i = 0, queues;
865 /* for the no-fd, no-helper case */
866 char ifname[128];
867 int *fds = NULL, *vhost_fds = NULL;
@@ -873,30 +894,13 @@ int net_init_tap(const Netdev *netdev, const char *name,
894 return -1;
895 }
896
876 - if (tap->vhostfds && !tap->fds) {
877 - error_setg(errp, "vhostfds= is invalid if fds= wasn't specified");
878 - return -1;
879 - }
880 -
881 - if (tap->vhostfd && tap->fds) {
882 - error_setg(errp, "vhostfd= is invalid with fds=");
883 - return -1;
884 - }
885 -
897 queues = tap_parse_fds_and_queues(tap, &fds, errp);
898 if (queues < 0) {
899 return -1;
900 }
901
891 - if (tap->vhostfd) {
892 - vhostfd = monitor_fd_param(monitor_cur(), tap->vhostfd, errp);
893 - if (vhostfd == -1) {
894 - goto fail;
895 - }
896 -
897 - if (!qemu_set_blocking(vhostfd, false, errp)) {
898 - goto fail;
899 - }
902 + if (!tap_parse_vhost_fds(tap, &vhost_fds, queues, errp)) {
903 + goto fail;
904 }
905
906 if (tap->fd) {
@@ -907,20 +911,12 @@ int net_init_tap(const Netdev *netdev, const char *name,
911
912 if (!net_init_tap_one(tap, peer, name, NULL,
913 NULL, NULL,
910 - vhostfd, vnet_hdr, fds[0], errp)) {
914 + vhost_fds ? vhost_fds[0] : -1,
915 + vnet_hdr, fds[0], errp)) {
916 goto fail;
917 }
918 } else if (tap->fds) {
914 - if (tap->vhostfds && net_parse_fds(tap->vhostfds, &vhost_fds,
915 - queues, errp) < 0) {
916 - goto fail;
917 - }
918 -
919 for (i = 0; i < queues; i++) {
920 - if (vhost_fds && !qemu_set_blocking(vhost_fds[i], false, errp)) {
921 - goto fail;
922 - }
923 -
920 if (i == 0) {
921 vnet_hdr = tap_probe_vnet_hdr(fds[i], errp);
922 if (vnet_hdr < 0) {
@@ -946,7 +942,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
942 }
943
944 if (!net_init_tap_one(tap, peer, name, ifname,
949 - NULL, NULL, vhostfd,
945 + NULL, NULL,
946 + vhost_fds ? vhost_fds[0] : -1,
947 vnet_hdr, fds[0], errp)) {
948 goto fail;
949 }
@@ -979,7 +976,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
976 if (!net_init_tap_one(tap, peer, name, ifname,
977 i >= 1 ? NULL : script,
978 i >= 1 ? NULL : downscript,
982 - vhostfd, vnet_hdr, fd, errp)) {
979 + vhost_fds ? vhost_fds[i] : -1,
980 + vnet_hdr, fd, errp)) {
981 goto fail;
982 }
983 }
@@ -989,7 +987,6 @@ int net_init_tap(const Netdev *netdev, const char *name,
987
988 fail:
989 close(fd);
992 - close(vhostfd);
990 net_free_fds(fds, queues);
991 net_free_fds(vhost_fds, queues);
992 return -1;