[...]
> 
> diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
> index 102fd85c1..cca9d81a4 100644
> --- a/src/util/virhostdev.c
> +++ b/src/util/virhostdev.c
> @@ -534,6 +534,10 @@ virHostdevRestoreNetConfig(virDomainHostdevDefPtr 
> hostdev,
>      int ret = -1;
>      int vf = -1;
>      bool port_profile_associate = false;
> +    virMacAddrPtr MAC = NULL;
> +    virMacAddrPtr adminMAC = NULL;
> +    virNetDevVlanPtr vlan = NULL;
> +
>  
>      /* This is only needed for PCI devices that have been defined
>       * using <interface type='hostdev'>. For all others, it is a NOP.
> @@ -559,62 +563,92 @@ virHostdevRestoreNetConfig(virDomainHostdevDefPtr 
> hostdev,
>                                                   NULL,
>                                                   port_profile_associate);
>      } else {
> -        virMacAddrPtr MAC = NULL;
> -        virMacAddrPtr adminMAC = NULL;
> -        virNetDevVlanPtr vlan = NULL;
> -
> -        ret = virNetDevReadNetConfig(linkdev, vf, stateDir, &adminMAC, 
> &vlan, &MAC);
> -        if (ret < 0 && oldStateDir)
> -            ret = virNetDevReadNetConfig(linkdev, vf, oldStateDir,
> -                                         &adminMAC, &vlan, &MAC);
> -
> -        if (ret < 0) {
> -            /* see if the config was saved using the PF's "port 2"
> -             * netdev for the file name.
> -             */
> -            VIR_FREE(linkdev);
> +        /* we need to try 3 different places for the config file:
> +         * 1) ${stateDir}/${PF}_vf${vf}
> +         *    This is almost always where the saved config is
> +         *
> +         * 2) ${oldStateDir/${PF}_vf${vf}
> +         *    saved config is only here if this machine was running a
> +         *    (by now *very*) old version of libvirt that saved the
> +         *    file in a different directory
> +         *
> +         * 3) ${stateDir}${PF[1]}_vf${VF}
> +         *    PF[1] means "the netdev for port 2 of the PF device", and
> +         *    is only valid when the PF is a Mellanox dual port NIC with
> +         *    a VF that was created in "single port" mode.
> +         *
> +         *  NB: if virNetDevReadNetConfig() returns < 0, then it found
> +         *  the file, but there was a problem, so we should
> +         *  immediately return an error to our caller. If it returns
> +         *  0, but all of the interesting stuff is NULL, that means
> +         *  the file wasn't found, so we can/should check other
> +         *  locations for it.
> +         */
>  
> -            if (virHostdevNetDevice(hostdev, 1, &linkdev, &vf) >= 0) {
> -                ret = virNetDevReadNetConfig(linkdev, vf, stateDir,
> -                                             &adminMAC, &vlan, &MAC);
> -            }
> +        /* 1) standard location */
> +        if (virNetDevReadNetConfig(linkdev, vf, stateDir,
> +                                   &adminMAC, &vlan, &MAC) < 0) {
> +            goto cleanup;
>          }
>  
> -        if (ret == 0) {
> -            /* if a MAC was stored for the VF, we should now restore
> -             * that as the adminMAC. We have to do it this way because
> -             * the VF is still not bound to the host's net driver, so
> -             * we can't directly set its MAC (and even after it is
> -             * re-bound to the host net driver, it will still have its
> -             * "administratively set" flag on, and that prohibits the
> -             * VF's net driver from directly setting the MAC
> -             * anyway). But it we set the desired VF MAC as the "admin
> -             * MAC" *now*, then when the VF is re-bound to the host
> -             * net driver (which will happen soon after returning from
> -             * this function), that adminMAC will be set (by the PF)
> -             * as the VF's new initial MAC.
> -             *
> -             * If no MAC was stored for the VF, that means it wasn't
> -             * bound to a net driver before we used it anyway, so the
> -             * adminMAC is all we have, and we can just restore it
> -             * directly.
> -             */
> -            if (MAC) {
> -                VIR_FREE(adminMAC);
> -                adminMAC = MAC;
> -                MAC = NULL;
> +        /* 2) "old" (pre-1.2.3 circa 2014) location - whenever we get
> +        *  to the point that nobody will ever upgrade directly from
> +        *  1.2.3 (or older) directly to current libvirt, we can
> +        *  eliminate this clause
> +        **/
> +        if (!(adminMAC || vlan || MAC) && oldStateDir &&
> +            virNetDevReadNetConfig(linkdev, vf, oldStateDir,
> +                                   &adminMAC, &vlan, &MAC) < 0) {
> +            goto cleanup;
> +        }
> +
> +        /* 3) try using the PF's "port 2" netdev as the name of the
> +         * config file
> +         */
> +        if (!(adminMAC || vlan || MAC)) {
> +            VIR_FREE(linkdev);
> +
> +            if (virHostdevNetDevice(hostdev, 1, &linkdev, &vf) < 0 ||
> +                virNetDevReadNetConfig(linkdev, vf, stateDir,
> +                                       &adminMAC, &vlan, &MAC) < 0) {
> +                goto cleanup;
>              }
> +        }
>  
> -            ignore_value(virNetDevSetNetConfig(linkdev, vf,
> -                                               adminMAC, vlan, MAC, true));
> +        /* if a MAC was stored for the VF, we should now restore
> +         * that as the adminMAC. We have to do it this way because
> +         * the VF is still not bound to the host's net driver, so
> +         * we can't directly set its MAC (and even after it is
> +         * re-bound to the host net driver, it will still have its
> +         * "administratively set" flag on, and that prohibits the
> +         * VF's net driver from directly setting the MAC
> +         * anyway). But it we set the desired VF MAC as the "admin
> +         * MAC" *now*, then when the VF is re-bound to the host
> +         * net driver (which will happen soon after returning from
> +         * this function), that adminMAC will be set (by the PF)
> +         * as the VF's new initial MAC.
> +         *
> +         * If no MAC was stored for the VF, that means it wasn't
> +         * bound to a net driver before we used it anyway, so the
> +         * adminMAC is all we have, and we can just restore it
> +         * directly.
> +         */
> +        if (MAC) {
> +            VIR_FREE(adminMAC);
> +            adminMAC = MAC;
> +            MAC = NULL;
>          }
>  
> -        VIR_FREE(MAC);
> -        VIR_FREE(adminMAC);
> -        virNetDevVlanFree(vlan);
> +        ignore_value(virNetDevSetNetConfig(linkdev, vf,
> +                                           adminMAC, vlan, MAC, true));
>      }
>  
> +    ret = 0;

Coverity notes that in the first half of the if statement :

ret = virHostdevNetConfigVirtPortProfile(...)

However, this overwrites that.

John

> + cleanup:
>      VIR_FREE(linkdev);
> +    VIR_FREE(MAC);
> +    VIR_FREE(adminMAC);
> +    virNetDevVlanFree(vlan);
>  
>      return ret;
>  }
[...]

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to