[libvirt] [PATCH 4/6 v5] list: Implement listAllInterfaces

Laine Stump laine at laine.org
Wed Sep 12 06:09:42 UTC 2012


On 09/11/2012 11:37 PM, Osier Yang wrote:
> This is not that ideal as API for other objects, as it's still
> O(n). Because interface driver uses netcf APIs to manage the
> stuffs, instead of by itself. And netcf APIs don't return a object.
> It provides APIs like old libvirt APIs:
>
>    ncf_number_of_interfaces
>    ncf_list_interfaces
>    ncf_lookup_by_name
>    ......
>
> Perhaps we should further improve netcf to let it provide an API
> to return the object, but it could be a later patch. And anyway,
> we will still benefit from the new API for the simplification,
> and no race like the old APIs.
>
> src/interface/netcf_driver.c: Implement listAllInterfaces
>
> v4 - v5:
>   * Ignore the NETCF_NOERROR, in case of the iface could be deleted
>     by other management apps as a race.
>
>   * Fix the memory leak caught by Laine.
>
>   * The version number fix.
>
> ---
>  src/interface/netcf_driver.c |  143 ++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 143 insertions(+), 0 deletions(-)
>
> diff --git a/src/interface/netcf_driver.c b/src/interface/netcf_driver.c
> index 935be66..26d25d7 100644
> --- a/src/interface/netcf_driver.c
> +++ b/src/interface/netcf_driver.c
> @@ -30,6 +30,7 @@
>  #include "netcf_driver.h"
>  #include "interface_conf.h"
>  #include "memory.h"
> +#include "logging.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_INTERFACE
>  
> @@ -259,6 +260,147 @@ static int interfaceListDefinedInterfaces(virConnectPtr conn, char **const names
>  
>  }
>  
> +static int
> +interfaceListAllInterfaces(virConnectPtr conn,
> +                           virInterfacePtr **ifaces,
> +                           unsigned int flags)
> +{
> +    struct interface_driver *driver = conn->interfacePrivateData;
> +    int count;
> +    int i;
> +    struct netcf_if *iface = NULL;
> +    virInterfacePtr *tmp_iface_objs = NULL;
> +    virInterfacePtr iface_obj = NULL;
> +    unsigned int status;
> +    int niface_objs = 0;
> +    int ret = -1;
> +    char **names;
> +
> +    virCheckFlags(VIR_CONNECT_LIST_INTERFACES_ACTIVE |
> +                  VIR_CONNECT_LIST_INTERFACES_INACTIVE, -1);
> +
> +    interfaceDriverLock(driver);
> +
> +    /* List all interfaces, in case of we might support new filter flags
> +     * except active|inactive in future.
> +     */
> +    count = ncf_num_of_interfaces(driver->netcf, NETCF_IFACE_ACTIVE |
> +                                  NETCF_IFACE_INACTIVE);
> +    if (count < 0) {
> +        const char *errmsg, *details;
> +        int errcode = ncf_error(driver->netcf, &errmsg, &details);
> +        virReportError(netcf_to_vir_err(errcode),
> +                       _("failed to get number of host interfaces: %s%s%s"),
> +                       errmsg, details ? " - " : "",
> +                       details ? details : "");
> +        return -1;


Ooh! I just noticed that you have several return paths here that don't
call interfaceDriverUnlock()!!

If you initialize names = NULL, then qualify the loop to free names with
"if (names) { ... }", you should be able to just to "ret = X; goto
cleanup;" instead of return.

> +    }
> +
> +    if (count == 0)
> +        return 0;
> +
> +    if (VIR_ALLOC_N(names, count) < 0) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +
> +    if ((count = ncf_list_interfaces(driver->netcf, count, names,
> +                                     NETCF_IFACE_ACTIVE |
> +                                     NETCF_IFACE_INACTIVE)) < 0) {
> +        const char *errmsg, *details;
> +        int errcode = ncf_error(driver->netcf, &errmsg, &details);
> +        virReportError(netcf_to_vir_err(errcode),
> +                       _("failed to list host interfaces: %s%s%s"),
> +                       errmsg, details ? " - " : "",
> +                       details ? details : "");
> +        goto cleanup;
> +    }
> +
> +    if (ifaces) {
> +        if (VIR_ALLOC_N(tmp_iface_objs, count + 1) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +    }
> +
> +    for (i = 0; i < count; i++) {
> +        iface = ncf_lookup_by_name(driver->netcf, names[i]);
> +        if (!iface) {
> +            const char *errmsg, *details;
> +            int errcode = ncf_error(driver->netcf, &errmsg, &details);
> +            if (errcode != NETCF_NOERROR) {
> +                virReportError(netcf_to_vir_err(errcode),
> +                               _("couldn't find interface named '%s': %s%s%s"),
> +                               names[i], errmsg,
> +                               details ? " - " : "", details ? details : "");
> +                goto cleanup;
> +            } else {
> +                /* Ignore the NETCF_NOERROR, as the interface is very likely
> +                 * deleted by other management apps (e.g. virt-manager).
> +                 */
> +                VIR_WARN("couldn't find interface named '%s', might be "
> +                         "deleted by other process", names[i]);


Yeah, I guess this is uncommon enough (as in "I bet this will never
happen, unless I actually put money on the bet" :-) that it's okay to
print a warning.


> +                continue;
> +            }
> +        }
> +
> +        if (ncf_if_status(iface, &status) < 0) {
> +            const char *errmsg, *details;
> +            int errcode = ncf_error(driver->netcf, &errmsg, &details);
> +            virReportError(netcf_to_vir_err(errcode),
> +                           _("failed to get status of interface %s: %s%s%s"),
> +                           names[i], errmsg, details ? " - " : "",
> +                           details ? details : "");
> +            goto cleanup;
> +        }
> +
> +        /* XXX: Filter the result, need to be splitted once new filter flags
> +         * except active|inactive are supported.
> +         */
> +        if (((status & NETCF_IFACE_ACTIVE) &&
> +             (flags & VIR_CONNECT_LIST_INTERFACES_ACTIVE)) ||
> +            ((status & NETCF_IFACE_INACTIVE) &&
> +             (flags & VIR_CONNECT_LIST_INTERFACES_INACTIVE))) {
> +            if (ifaces) {
> +                iface_obj = virGetInterface(conn, ncf_if_name(iface),
> +                                            ncf_if_mac_string(iface));
> +                tmp_iface_objs[niface_objs] = iface_obj;
> +            }
> +            niface_objs++;
> +        }
> +
> +        ncf_if_free(iface);
> +        iface = NULL;
> +    }
> +
> +    if (tmp_iface_objs) {
> +        /* trim the array to the final size */
> +        ignore_value(VIR_REALLOC_N(tmp_iface_objs, niface_objs + 1));
> +        *ifaces = tmp_iface_objs;
> +        tmp_iface_objs = NULL;
> +    }
> +
> +    ret = niface_objs;
> +
> +cleanup:
> +    ncf_if_free(iface);
> +
> +    for (i = 0; i < count; i++)
> +        VIR_FREE(names[i]);
> +    VIR_FREE(names);
> +
> +    if (tmp_iface_objs) {
> +        for (i = 0; i < niface_objs; i++) {
> +            if (tmp_iface_objs[i])
> +                virInterfaceFree(tmp_iface_objs[i]);
> +        }
> +    }
> +
> +    interfaceDriverUnlock(driver);
> +    return ret;
> +}
> +
> +
>  static virInterfacePtr interfaceLookupByName(virConnectPtr conn,
>                                               const char *name)
>  {
> @@ -642,6 +784,7 @@ static virInterfaceDriver interfaceDriver = {
>      .listInterfaces = interfaceListInterfaces, /* 0.7.0 */
>      .numOfDefinedInterfaces = interfaceNumOfDefinedInterfaces, /* 0.7.0 */
>      .listDefinedInterfaces = interfaceListDefinedInterfaces, /* 0.7.0 */
> +    .listAllInterfaces = interfaceListAllInterfaces, /* 0.10.2 */
>      .interfaceLookupByName = interfaceLookupByName, /* 0.7.0 */
>      .interfaceLookupByMACString = interfaceLookupByMACString, /* 0.7.0 */
>      .interfaceGetXMLDesc = interfaceGetXMLDesc, /* 0.7.0 */

ACK with the interfaceDriverUnlock() problem fixed.




More information about the libvir-list mailing list