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;