[libvirt] [PATCH 5/5] Reuse the socket in virNetDevGetFeatures

Ján Tomko jtomko at redhat.com
Mon Jun 6 07:39:28 UTC 2016


This speeds up node_device_udev driver startup 11x.
---
 src/util/virnetdev.c | 69 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 31 deletions(-)

diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 52f02d3..7863e8a 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -3206,20 +3206,11 @@ virNetDevRDMAFeature(const char *ifname,
  * Returns 0 on success, -1 on failure.
  */
 static int
-virNetDevSendEthtoolIoctl(const char *ifname, void *cmd)
+virNetDevSendEthtoolIoctl(int fd, struct ifreq *ifr)
 {
     int ret = -1;
-    int fd = -1;
-    struct ifreq ifr;
-
-    /* Ultimately uses AF_PACKET for socket which requires privileged
-     * daemon support.
-     */
-    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
-        return ret;
 
-    ifr.ifr_data = cmd;
-    ret = ioctl(fd, SIOCETHTOOL, &ifr);
+    ret = ioctl(fd, SIOCETHTOOL, ifr);
     if (ret != 0) {
         switch (errno) {
             case EINVAL: /* kernel doesn't support SIOCETHTOOL */
@@ -3230,12 +3221,10 @@ virNetDevSendEthtoolIoctl(const char *ifname, void *cmd)
                 break;
             default:
                 virReportSystemError(errno, "%s", _("ethtool ioctl error"));
-                goto cleanup;
+                break;
         }
     }
 
- cleanup:
-    VIR_FORCE_CLOSE(fd);
     return ret;
 }
 
@@ -3255,10 +3244,10 @@ struct ethtool_to_virnetdev_feature {
 * Returns 0 if not found, 1 on success, and -1 on failure.
 */
 static bool
-virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
+virNetDevFeatureAvailable(int fd, struct ifreq *ifr, struct ethtool_value *cmd)
 {
-    cmd = (void*)cmd;
-    if (virNetDevSendEthtoolIoctl(ifname, cmd) == 0 &&
+    ifr->ifr_data = (void*)cmd;
+    if (virNetDevSendEthtoolIoctl(fd, ifr) == 0 &&
         cmd->data > 0)
         return true;
     return false;
@@ -3267,7 +3256,8 @@ virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
 
 static void
 virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
-                            const char *ifname)
+                            int fd,
+                            struct ifreq *ifr)
 {
     size_t i;
     struct ethtool_value cmd = { 0 };
@@ -3306,12 +3296,12 @@ virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
 
     for (i = 0; i < ARRAY_CARDINALITY(ethtool_cmds); i++) {
         cmd.cmd = ethtool_cmds[i].cmd;
-        if (virNetDevFeatureAvailable(ifname, &cmd))
+        if (virNetDevFeatureAvailable(fd, ifr, &cmd))
             ignore_value(virBitmapSetBit(bitmap, ethtool_cmds[i].feat));
     }
 
     cmd.cmd = ETHTOOL_GFLAGS;
-    if (virNetDevFeatureAvailable(ifname, &cmd)) {
+    if (virNetDevFeatureAvailable(fd, ifr, &cmd)) {
         for (i = 0; i < ARRAY_CARDINALITY(flags); i++) {
             if (cmd.data & flags[i].cmd)
                 ignore_value(virBitmapSetBit(bitmap, flags[i].feat));
@@ -3332,10 +3322,12 @@ virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
  * Returns 0 if not found, 1 on success, and -1 on failure.
  */
 static bool
-virNetDevGFeatureAvailable(const char *ifname, struct ethtool_gfeatures *cmd)
+virNetDevGFeatureAvailable(int fd,
+                           struct ifreq *ifr,
+                           struct ethtool_gfeatures *cmd)
 {
-    cmd = (void*)cmd;
-    if (virNetDevSendEthtoolIoctl(ifname, cmd) == 0)
+    ifr->ifr_data = (void*)cmd;
+    if (virNetDevSendEthtoolIoctl(fd, ifr) == 0)
         return !!FEATURE_BIT_IS_SET(cmd->features, TX_UDP_TNL, active);
     return false;
 }
@@ -3343,7 +3335,8 @@ virNetDevGFeatureAvailable(const char *ifname, struct ethtool_gfeatures *cmd)
 
 static int
 virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
-                             const char *ifname)
+                            int fd,
+                            struct ifreq *ifr)
 {
     struct ethtool_gfeatures *g_cmd;
 
@@ -3353,7 +3346,7 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
 
     g_cmd->cmd = ETHTOOL_GFEATURES;
     g_cmd->size = GFEATURES_SIZE;
-    if (virNetDevGFeatureAvailable(ifname, g_cmd))
+    if (virNetDevGFeatureAvailable(fd, ifr, g_cmd))
         ignore_value(virBitmapSetBit(bitmap, VIR_NET_DEV_FEAT_TXUDPTNL));
     VIR_FREE(g_cmd);
     return 0;
@@ -3361,7 +3354,8 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
 # else
 static int
 virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap ATTRIBUTE_UNUSED,
-                             const char *ifname ATTRIBUTE_UNUSED)
+                             int fd ATTRIBUTE_UNUSED,
+                             struct ifreq *ifr ATTRIBUGE_UNUSED)
 {
     return 0;
 }
@@ -3382,6 +3376,10 @@ int
 virNetDevGetFeatures(const char *ifname,
                      virBitmapPtr *out)
 {
+    struct ifreq ifr;
+    int ret = -1;
+    int fd = -1;
+
     if (!(*out = virBitmapNew(VIR_NET_DEV_FEAT_LAST)))
         return -1;
 
@@ -3391,14 +3389,23 @@ virNetDevGetFeatures(const char *ifname,
         return 0;
     }
 
-    virNetDevGetEthtoolFeatures(*out, ifname);
+    /* Ultimately uses AF_PACKET for socket which requires privileged
+     * daemon support.
+     */
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+        goto cleanup;
 
-    if (virNetDevGetEthtoolGFeatures(*out, ifname) < 0)
-        return -1;
+    virNetDevGetEthtoolFeatures(*out, fd, &ifr);
+
+    if (virNetDevGetEthtoolGFeatures(*out, fd, &ifr) < 0)
+        goto cleanup;
 
     if (virNetDevRDMAFeature(ifname, out) < 0)
-        return -1;
-    return 0;
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    return ret;
 }
 #else
 int
-- 
2.7.3




More information about the libvir-list mailing list