[PATCH v2 3/8] net/tap: refactor net_tap_setup_vhost()

Vladimir Sementsov-Ogievskiy posted 8 patches 3 days, 1 hour ago
There is a newer version of this series
[PATCH v2 3/8] net/tap: refactor net_tap_setup_vhost()
Posted by Vladimir Sementsov-Ogievskiy 3 days, 1 hour ago
1. Move function higher. (we anyway want to split it into two functions,
and change the code a lot, so take an opportunity to get rid of extra
declaration).

2. Split into _set_options() and _init_vhost(): we'll need it later
to implement TAP local migration feature.

3. Split requires to store options somewhere, and to be able to call
_init_vhost() later (from migriation _load() in later commit), store
options in the TAPState.

4. So, take an opportunity to zero-initialize options:
 - be safe (avoid uninitialized options)
 - don't care to initialize half of the options to zero by hand

5. Also, don't worry too much about poll_us: absent option should be
zero-initialized anyway.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
 net/tap.c | 123 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 66 insertions(+), 57 deletions(-)

diff --git a/net/tap.c b/net/tap.c
index 7dc8af1e57..a9d955ac5f 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -78,6 +78,7 @@ typedef struct TAPState {
     bool has_ufo;
     bool has_uso;
     bool enabled;
+    VhostNetOptions *vhost_options;
     VHostNetState *vhost_net;
     unsigned host_vnet_hdr_len;
     Notifier exit;
@@ -95,8 +96,6 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
                                   const char *downscript,
                                   const char *vhostfdname,
                                   int vnet_hdr, int fd, Error **errp);
-static int net_tap_setup_vhost(TAPState *s, const NetdevTapOptions *tap,
-                               const char *vhostfdname, Error **errp);
 
 static void tap_update_fd_handler(TAPState *s)
 {
@@ -382,6 +381,8 @@ static void tap_cleanup(NetClientState *nc)
         s->vhost_net = NULL;
     }
 
+    g_free(s->vhost_options);
+
     qemu_purge_queued_packets(nc);
 
     if (s->exit.notify) {
@@ -745,6 +746,63 @@ static int net_tap_open_one(const Netdev *netdev,
 
 #define MAX_TAP_QUEUES 1024
 
+static int net_tap_set_vhost_options(TAPState *s, const NetdevTapOptions *tap,
+                                     const char *vhostfdname, Error **errp)
+{
+    int vhostfd;
+    bool vhost_on = tap->has_vhost ? tap->vhost :
+        vhostfdname || (tap->has_vhostforce && tap->vhostforce);
+
+    if (!vhost_on) {
+        return 0;
+    }
+
+    if (vhostfdname) {
+        vhostfd = monitor_fd_param(monitor_cur(), vhostfdname, errp);
+        if (vhostfd == -1) {
+            return -1;
+        }
+    } else {
+        vhostfd = open("/dev/vhost-net", O_RDWR);
+        if (vhostfd < 0) {
+            error_setg_errno(errp, errno,
+                             "tap: open vhost char device failed");
+            return -1;
+        }
+    }
+
+    if (!qemu_set_blocking(vhostfd, false, errp)) {
+        return -1;
+    }
+
+    s->vhost_options = g_new(VhostNetOptions, 1);
+    *s->vhost_options = (VhostNetOptions) {
+        .backend_type = VHOST_BACKEND_TYPE_KERNEL,
+        .net_backend = &s->nc,
+        .busyloop_timeout = tap->poll_us,
+        .opaque = (void *)(uintptr_t)vhostfd,
+        .nvqs = 2,
+        .feature_bits = kernel_feature_bits,
+    };
+
+    return 0;
+}
+
+static int net_tap_init_vhost(TAPState *s, Error **errp) {
+    if (!s->vhost_options) {
+        return 0;
+    }
+
+    s->vhost_net = vhost_net_init(s->vhost_options);
+    if (!s->vhost_net) {
+        error_setg(errp,
+                   "vhost-net requested but could not be initialized");
+        return -1;
+    }
+
+    return 0;
+}
+
 static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
                                   const char *model, const char *name,
                                   const char *ifname, const char *script,
@@ -810,7 +868,12 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
         }
     }
 
-    ret = net_tap_setup_vhost(s, tap, vhostfdname, errp);
+    ret = net_tap_set_vhost_options(s, tap, vhostfdname, errp);
+    if (ret < 0) {
+        goto failed;
+    }
+
+    ret = net_tap_init_vhost(s, errp);
     if (ret < 0) {
         goto failed;
     }
@@ -822,60 +885,6 @@ failed:
     return -1;
 }
 
-static int net_tap_setup_vhost(TAPState *s, const NetdevTapOptions *tap,
-                               const char *vhostfdname, Error **errp)
-{
-    if (tap->has_vhost ? tap->vhost :
-        vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
-        VhostNetOptions options;
-        int vhostfd;
-
-        options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
-        options.net_backend = &s->nc;
-        if (tap->has_poll_us) {
-            options.busyloop_timeout = tap->poll_us;
-        } else {
-            options.busyloop_timeout = 0;
-        }
-
-        if (vhostfdname) {
-            vhostfd = monitor_fd_param(monitor_cur(), vhostfdname, errp);
-            if (vhostfd == -1) {
-                return -1;
-            }
-            if (!qemu_set_blocking(vhostfd, false, errp)) {
-                return -1;
-            }
-        } else {
-            vhostfd = open("/dev/vhost-net", O_RDWR);
-            if (vhostfd < 0) {
-                error_setg_errno(errp, errno,
-                                 "tap: open vhost char device failed");
-                return -1;
-            }
-            if (!qemu_set_blocking(vhostfd, false, errp)) {
-                return -1;
-            }
-        }
-        options.opaque = (void *)(uintptr_t)vhostfd;
-        options.nvqs = 2;
-        options.feature_bits = kernel_feature_bits;
-        options.get_acked_features = NULL;
-        options.save_acked_features = NULL;
-        options.max_tx_queue_size = 0;
-        options.is_vhost_user = false;
-
-        s->vhost_net = vhost_net_init(&options);
-        if (!s->vhost_net) {
-            error_setg(errp,
-                       "vhost-net requested but could not be initialized");
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
 static int net_tap_from_monitor_fd(const Netdev *netdev, NetClientState *peer,
                                    const char *name, const char *vhostfdname,
                                    int *pvnet_hdr, const char *fdname,
-- 
2.48.1