[libvirt] [RFC] [PATCH] Support for uevent netlink and hotplug event.

tangchen tangchen at cn.fujitsu.com
Thu Jul 19 01:11:56 UTC 2012


Hi~

I didn't make it clear. :)

I meant to modify virNetlinkEventServiceStart(), but as you said, I also need to modify
virNetlinkEventAddClient(), virNetlinkEventRemoveClient(), and so on. It is a lot
of work then.

So I added a virNetlinkEventServiceStartProtocol() and see if you guys have any
comments. :)

If you think this is OK, then I will try to improve all of them.

Thanks.

On 07/19/2012 01:17 AM, Viktor Mihajlovski wrote:
> On 07/18/2012 02:22 PM, tangchen wrote:
>> NOTE: This patch is just for some comments, so that we can try to
>>        improve netlink support in libvirt.
>>
>> This patch introduces a new global array servers[MAX_LINKS],
>> and all the netlink protocol (at most 32 protocols)
>> can be supportted.
>>
>> And also, it creates a NETLINK_KOBJECT_UEVENT socket to listen
>> to hotplug events.
>>
>> Signed-off-by: Tang Chen <tangchen at cn.fujitsu.com>
>> ---
>>   src/libvirt_private.syms |    1 +
>>   src/util/virnetlink.c    |  103 ++++++++++++++++++++++++++++++++++++++++++++++
>>   src/util/virnetlink.h    |    5 +++
>>   3 files changed, 109 insertions(+)
>>
>> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
>> index 7373281..0ef21d9 100644
>> --- a/src/libvirt_private.syms
>> +++ b/src/libvirt_private.syms
>> @@ -1378,6 +1378,7 @@ virNetlinkEventServiceIsRunning;
>>   virNetlinkEventServiceLocalPid;
>>   virNetlinkEventServiceStop;
>>   virNetlinkEventServiceStart;
>> +virNetlinkEventServiceStartProtocol;
>>   virNetlinkShutdown;
>>   virNetlinkStartup;
>>
>> diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
>> index bb0dae9..489c149 100644
>> --- a/src/util/virnetlink.c
>> +++ b/src/util/virnetlink.c
>> @@ -98,6 +98,7 @@ static int nextWatch = 1;
>>   # define NETLINK_EVENT_ALLOC_EXTENT 10
>>
>>   static virNetlinkEventSrvPrivatePtr server = NULL;
>> +static virNetlinkEventSrvPrivatePtr servers[MAX_LINKS] = {NULL};
>>   static virNetlinkHandle *placeholder_nlhandle = NULL;
>>
>>   /* Function definitions */
>> @@ -307,6 +308,8 @@ virNetlinkEventCallback(int watch,
>>           return;
>>       }
>>
>> +    VIR_INFO("%s", msg);
>> +
> Is msg always printable? even if so, should be VIR_DEBUG rather than
> VIR_INFO.
>>       virNetlinkEventServerLock(srv);
>>
>>       VIR_DEBUG("dispatching to max %d clients, called from event watch %d",
>> @@ -398,6 +401,106 @@ int virNetlinkEventServiceLocalPid(void)
>>
>>
>>   /**
>> + * virNetlinkEventServiceStartProtocol:
>> + *
>> + * start a monitor to receive netlink messages for libvirtd.
>> + * This registers a netlink socket with the event interface.
>> + *
>> + * @protocol: netlink protocol
>> + * @groups: broadcast groups to join
>> + * Returns -1 if the monitor cannot be registered, 0 upon success
>> + */
>> +int
>> +virNetlinkEventServiceStartProtocol(int protocol, int groups)
>> +{
>> +    virNetlinkEventSrvPrivatePtr srv;
>> +    int fd;
>> +    int ret = -1;
>> +
>> +    if (protocol < 0 || protocol >= MAX_LINKS ||
>> +	groups < 0 || groups >= 32) {
>> +	return -EINVAL;
> 
> You should probably log an error here.
> 
>> +    }
>> +
>> +    if (servers[protocol])
>> +        return 0;
>> +
>> +    VIR_INFO("starting netlink event service with protocol %d", protocol);
>> +
>> +    if (VIR_ALLOC(srv) < 0) {
>> +        virReportOOMError();
>> +        return -1;
>> +    }
>> +
>> +    if (virMutexInit(&srv->lock) < 0) {
>> +        VIR_FREE(srv);
>> +        return -1;
>> +    }
>> +
>> +    virNetlinkEventServerLock(srv);
>> +
>> +    /* Allocate a new socket and get fd */
>> +    srv->netlinknh = virNetlinkAlloc();
>> +
>> +    if (!srv->netlinknh) {
>> +        virReportSystemError(errno,
>> +                             "%s", _("cannot allocate nlhandle for virNetlinkEvent server"));
>> +        goto error_locked;
>> +    }
>> +
>> +    nl_join_groups(srv->netlinknh, groups);
> 
> AFAIK nl_join_groups is deprecated and should be replaced by a 
> setsockopt( ..., NETLINK_ADD_MEMBERSHIP,...)
> 
> Further, I'd recommend to make the group join optional, i.e. something like
>   if (groups)
>       setsockopt(...);
> and perhaps add error handling.
> 
> Not sure, but should the add membership not happen after the connect?
> 
>> +
>> +    if (nl_connect(srv->netlinknh, protocol) < 0) {
>> +        virReportSystemError(errno,
>> +                             "%s", _("cannot connect to netlink socket"));
>> +        goto error_server;
>> +    }
>> +
>> +    fd = nl_socket_get_fd(srv->netlinknh);
>> +
>> +    if (fd < 0) {
>> +        virReportSystemError(errno,
>> +                             "%s", _("cannot get netlink socket fd"));
>> +        goto error_server;
>> +    }
>> +
>> +    if (nl_socket_set_nonblocking(srv->netlinknh)) {
>> +        virReportSystemError(errno, "%s",
>> +                             _("cannot set netlink socket nonblocking"));
>> +        goto error_server;
>> +    }
>> +
>> +    if ((srv->eventwatch = virEventAddHandle(fd,
>> +                                             VIR_EVENT_HANDLE_READABLE,
>> +                                             virNetlinkEventCallback,
>> +                                             srv, NULL)) < 0) {
>> +        netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
>> +                     _("Failed to add netlink event handle watch"));
>> +        goto error_server;
>> +    }
>> +
>> +    srv->netlinkfd = fd;
>> +    VIR_DEBUG("netlink event listener on fd: %i running", fd);
>> +
>> +    ret = 0;
>> +    servers[protocol] = srv;
>> +
>> +error_server:
>> +    if (ret < 0) {
>> +        nl_close(srv->netlinknh);
>> +        virNetlinkFree(srv->netlinknh);
>> +    }
>> +error_locked:
>> +    virNetlinkEventServerUnlock(srv);
>> +    if (ret < 0) {
>> +        virMutexDestroy(&srv->lock);
>> +        VIR_FREE(srv);
>> +    }
>> +    return ret;
>> +}
>> +
>> +
>> +/**
>>    * virNetlinkEventServiceStart:
>>    *
>>    * start a monitor to receive netlink messages for libvirtd.
>> diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
>> index 8ec27c9..256f129 100644
>> --- a/src/util/virnetlink.h
>> +++ b/src/util/virnetlink.h
>> @@ -59,6 +59,11 @@ int virNetlinkEventServiceStop(void);
>>   int virNetlinkEventServiceStart(void);
>>
>>   /**
>> + * startNetlinkEventServerProtocol: start a monitor with specified protocol to receive netlink messages for libvirtd
>> + */
>> +int virNetlinkEventServiceStartProtocol(int protocol, int groups);
>> +
>> +/**
>>    * virNetlinkEventServiceIsRunning: returns if the netlink event service is running.
>>    */
>>   bool virNetlinkEventServiceIsRunning(void);
>>
> 
> As far as I can tell, it is necessary to implement equivalents of
> virNetlinkEventAddClient, virNetlinkEventRemoveClient, 
> virNetlinkEventRemoveClientPrimitive, virNetlinkEventServiceStop and 
> virNetlinkEventServiceIsRunning to include the protocol.
> 
> Generally, you could go all the way and replace the body of 
> virNetlinkEventServiceStart by a call to
>   virNetlinkEventServiceStartProtocol(NETLINK_ROUTE,0);
> or change all occurrences of the call to use the extended signature,
> 
> Maybe Eric or some other maintainer wants to comment as well.
> 

-- 
Best Regards,
Tang chen




More information about the libvir-list mailing list