virnetlink: Use automatic memory management
Signed-off-by: Tim Wiederhake <twiederh@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
22e67e4e67
commit
20d2cf47bc
@ -799,18 +799,6 @@ virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
virNetlinkEventServerLock(virNetlinkEventSrvPrivate *driver)
|
|
||||||
{
|
|
||||||
virMutexLock(&driver->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
virNetlinkEventServerUnlock(virNetlinkEventSrvPrivate *driver)
|
|
||||||
{
|
|
||||||
virMutexUnlock(&driver->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virNetlinkEventRemoveClientPrimitive:
|
* virNetlinkEventRemoveClientPrimitive:
|
||||||
*
|
*
|
||||||
@ -869,25 +857,23 @@ virNetlinkEventCallback(int watch,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetlinkEventServerLock(srv);
|
|
||||||
|
|
||||||
VIR_DEBUG("dispatching to max %d clients, called from event watch %d",
|
VIR_DEBUG("dispatching to max %d clients, called from event watch %d",
|
||||||
(int)srv->handlesCount, watch);
|
(int)srv->handlesCount, watch);
|
||||||
|
|
||||||
for (i = 0; i < srv->handlesCount; i++) {
|
VIR_WITH_MUTEX_LOCK_GUARD(&srv->lock) {
|
||||||
if (srv->handles[i].deleted != VIR_NETLINK_HANDLE_VALID)
|
for (i = 0; i < srv->handlesCount; i++) {
|
||||||
continue;
|
if (srv->handles[i].deleted != VIR_NETLINK_HANDLE_VALID)
|
||||||
|
continue;
|
||||||
|
|
||||||
VIR_DEBUG("dispatching client %zu.", i);
|
VIR_DEBUG("dispatching client %zu.", i);
|
||||||
|
|
||||||
(srv->handles[i].handleCB)(msg, length, &peer, &handled,
|
(srv->handles[i].handleCB)(msg, length, &peer, &handled,
|
||||||
srv->handles[i].opaque);
|
srv->handles[i].opaque);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handled)
|
if (!handled)
|
||||||
VIR_DEBUG("event not handled.");
|
VIR_DEBUG("event not handled.");
|
||||||
|
|
||||||
virNetlinkEventServerUnlock(srv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -916,21 +902,21 @@ virNetlinkEventServiceStop(unsigned int protocol)
|
|||||||
if (!server[protocol])
|
if (!server[protocol])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
virNetlinkEventServerLock(srv);
|
VIR_WITH_MUTEX_LOCK_GUARD(&srv->lock) {
|
||||||
nl_close(srv->netlinknh);
|
nl_close(srv->netlinknh);
|
||||||
virNetlinkFree(srv->netlinknh);
|
virNetlinkFree(srv->netlinknh);
|
||||||
virEventRemoveHandle(srv->eventwatch);
|
virEventRemoveHandle(srv->eventwatch);
|
||||||
|
|
||||||
/* free any remaining clients on the list */
|
/* free any remaining clients on the list */
|
||||||
for (i = 0; i < srv->handlesCount; i++) {
|
for (i = 0; i < srv->handlesCount; i++) {
|
||||||
if (srv->handles[i].deleted == VIR_NETLINK_HANDLE_VALID)
|
if (srv->handles[i].deleted == VIR_NETLINK_HANDLE_VALID)
|
||||||
virNetlinkEventRemoveClientPrimitive(i, protocol);
|
virNetlinkEventRemoveClientPrimitive(i, protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
server[protocol] = NULL;
|
||||||
|
VIR_FREE(srv->handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
server[protocol] = NULL;
|
|
||||||
VIR_FREE(srv->handles);
|
|
||||||
virNetlinkEventServerUnlock(srv);
|
|
||||||
|
|
||||||
virMutexDestroy(&srv->lock);
|
virMutexDestroy(&srv->lock);
|
||||||
VIR_FREE(srv);
|
VIR_FREE(srv);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1036,53 +1022,52 @@ virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetlinkEventServerLock(srv);
|
VIR_WITH_MUTEX_LOCK_GUARD(&srv->lock) {
|
||||||
|
/* Allocate a new socket and get fd */
|
||||||
|
if (!(srv->netlinknh = virNetlinkCreateSocket(protocol)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* Allocate a new socket and get fd */
|
fd = nl_socket_get_fd(srv->netlinknh);
|
||||||
if (!(srv->netlinknh = virNetlinkCreateSocket(protocol)))
|
if (fd < 0) {
|
||||||
goto error_locked;
|
virReportSystemError(errno,
|
||||||
|
"%s", _("cannot get netlink socket fd"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
fd = nl_socket_get_fd(srv->netlinknh);
|
if (groups && nl_socket_add_membership(srv->netlinknh, groups) < 0) {
|
||||||
if (fd < 0) {
|
virReportSystemError(errno,
|
||||||
virReportSystemError(errno,
|
"%s", _("cannot add netlink membership"));
|
||||||
"%s", _("cannot get netlink socket fd"));
|
goto error;
|
||||||
goto error_server;
|
}
|
||||||
|
|
||||||
|
if (nl_socket_set_nonblocking(srv->netlinknh)) {
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("cannot set netlink socket nonblocking"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((srv->eventwatch = virEventAddHandle(fd,
|
||||||
|
VIR_EVENT_HANDLE_READABLE,
|
||||||
|
virNetlinkEventCallback,
|
||||||
|
srv, NULL)) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Failed to add netlink event handle watch"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
srv->netlinkfd = fd;
|
||||||
|
VIR_DEBUG("netlink event listener on fd: %i running", fd);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
server[protocol] = srv;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (ret < 0 && srv->netlinknh) {
|
||||||
|
nl_close(srv->netlinknh);
|
||||||
|
virNetlinkFree(srv->netlinknh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groups && nl_socket_add_membership(srv->netlinknh, groups) < 0) {
|
|
||||||
virReportSystemError(errno,
|
|
||||||
"%s", _("cannot add netlink membership"));
|
|
||||||
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) {
|
|
||||||
virReportError(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;
|
|
||||||
server[protocol] = srv;
|
|
||||||
|
|
||||||
error_server:
|
|
||||||
if (ret < 0) {
|
|
||||||
nl_close(srv->netlinknh);
|
|
||||||
virNetlinkFree(srv->netlinknh);
|
|
||||||
}
|
|
||||||
error_locked:
|
|
||||||
virNetlinkEventServerUnlock(srv);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
virMutexDestroy(&srv->lock);
|
virMutexDestroy(&srv->lock);
|
||||||
VIR_FREE(srv);
|
VIR_FREE(srv);
|
||||||
@ -1129,45 +1114,44 @@ virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetlinkEventServerLock(srv);
|
VIR_WITH_MUTEX_LOCK_GUARD(&srv->lock) {
|
||||||
|
VIR_DEBUG("adding client: %d.", nextWatch);
|
||||||
|
|
||||||
VIR_DEBUG("adding client: %d.", nextWatch);
|
/* first try to re-use deleted free slots */
|
||||||
|
for (i = 0; i < srv->handlesCount; i++) {
|
||||||
/* first try to re-use deleted free slots */
|
if (srv->handles[i].deleted == VIR_NETLINK_HANDLE_DELETED) {
|
||||||
for (i = 0; i < srv->handlesCount; i++) {
|
r = i;
|
||||||
if (srv->handles[i].deleted == VIR_NETLINK_HANDLE_DELETED) {
|
break;
|
||||||
r = i;
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
/* Resize the eventLoop array if needed */
|
||||||
|
if (srv->handlesCount == srv->handlesAlloc) {
|
||||||
|
VIR_DEBUG("Used %zu handle slots, adding at least %d more",
|
||||||
|
srv->handlesAlloc, NETLINK_EVENT_ALLOC_EXTENT);
|
||||||
|
VIR_RESIZE_N(srv->handles, srv->handlesAlloc,
|
||||||
|
srv->handlesCount, NETLINK_EVENT_ALLOC_EXTENT);
|
||||||
|
}
|
||||||
|
r = srv->handlesCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
srv->handles[r].watch = nextWatch;
|
||||||
|
srv->handles[r].handleCB = handleCB;
|
||||||
|
srv->handles[r].removeCB = removeCB;
|
||||||
|
srv->handles[r].opaque = opaque;
|
||||||
|
srv->handles[r].deleted = VIR_NETLINK_HANDLE_VALID;
|
||||||
|
if (macaddr)
|
||||||
|
virMacAddrSet(&srv->handles[r].macaddr, macaddr);
|
||||||
|
else
|
||||||
|
virMacAddrSetRaw(&srv->handles[r].macaddr,
|
||||||
|
(unsigned char[VIR_MAC_BUFLEN]){0, 0, 0, 0, 0, 0});
|
||||||
|
|
||||||
|
ret = nextWatch++;
|
||||||
|
|
||||||
|
VIR_DEBUG("added client to loop slot: %d. with macaddr ptr=%p", r, macaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
/* Resize the eventLoop array if needed */
|
|
||||||
if (srv->handlesCount == srv->handlesAlloc) {
|
|
||||||
VIR_DEBUG("Used %zu handle slots, adding at least %d more",
|
|
||||||
srv->handlesAlloc, NETLINK_EVENT_ALLOC_EXTENT);
|
|
||||||
VIR_RESIZE_N(srv->handles, srv->handlesAlloc,
|
|
||||||
srv->handlesCount, NETLINK_EVENT_ALLOC_EXTENT);
|
|
||||||
}
|
|
||||||
r = srv->handlesCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
srv->handles[r].watch = nextWatch;
|
|
||||||
srv->handles[r].handleCB = handleCB;
|
|
||||||
srv->handles[r].removeCB = removeCB;
|
|
||||||
srv->handles[r].opaque = opaque;
|
|
||||||
srv->handles[r].deleted = VIR_NETLINK_HANDLE_VALID;
|
|
||||||
if (macaddr)
|
|
||||||
virMacAddrSet(&srv->handles[r].macaddr, macaddr);
|
|
||||||
else
|
|
||||||
virMacAddrSetRaw(&srv->handles[r].macaddr,
|
|
||||||
(unsigned char[VIR_MAC_BUFLEN]){0, 0, 0, 0, 0, 0});
|
|
||||||
|
|
||||||
VIR_DEBUG("added client to loop slot: %d. with macaddr ptr=%p", r, macaddr);
|
|
||||||
|
|
||||||
ret = nextWatch++;
|
|
||||||
|
|
||||||
virNetlinkEventServerUnlock(srv);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,7 +1173,6 @@ virNetlinkEventRemoveClient(int watch, const virMacAddr *macaddr,
|
|||||||
unsigned int protocol)
|
unsigned int protocol)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret = -1;
|
|
||||||
virNetlinkEventSrvPrivate *srv = NULL;
|
virNetlinkEventSrvPrivate *srv = NULL;
|
||||||
|
|
||||||
if (protocol >= MAX_LINKS)
|
if (protocol >= MAX_LINKS)
|
||||||
@ -1204,28 +1187,25 @@ virNetlinkEventRemoveClient(int watch, const virMacAddr *macaddr,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetlinkEventServerLock(srv);
|
VIR_WITH_MUTEX_LOCK_GUARD(&srv->lock) {
|
||||||
|
for (i = 0; i < srv->handlesCount; i++) {
|
||||||
|
if (srv->handles[i].deleted != VIR_NETLINK_HANDLE_VALID)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < srv->handlesCount; i++) {
|
if ((watch && srv->handles[i].watch == watch) ||
|
||||||
if (srv->handles[i].deleted != VIR_NETLINK_HANDLE_VALID)
|
(!watch &&
|
||||||
continue;
|
virMacAddrCmp(macaddr, &srv->handles[i].macaddr) == 0)) {
|
||||||
|
|
||||||
if ((watch && srv->handles[i].watch == watch) ||
|
VIR_DEBUG("removed client: %d by %s.",
|
||||||
(!watch &&
|
srv->handles[i].watch, watch ? "index" : "mac");
|
||||||
virMacAddrCmp(macaddr, &srv->handles[i].macaddr) == 0)) {
|
virNetlinkEventRemoveClientPrimitive(i, protocol);
|
||||||
|
return 0;
|
||||||
VIR_DEBUG("removed client: %d by %s.",
|
}
|
||||||
srv->handles[i].watch, watch ? "index" : "mac");
|
|
||||||
virNetlinkEventRemoveClientPrimitive(i, protocol);
|
|
||||||
ret = 0;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VIR_DEBUG("no client found to remove.");
|
VIR_DEBUG("no client found to remove.");
|
||||||
|
|
||||||
cleanup:
|
return -1;
|
||||||
virNetlinkEventServerUnlock(srv);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user