commit e330c9c7c09f14d79ce220dcb2a15b271e3d50aa Author: Eric Multanen Date: Wed Aug 18 17:00:17 2010 -0700 fipvlan updates to fix hang when link state changes. This patch combines the following patches from fcoe-utils on open-fcoe.org: lib/fip.c: make fip_recv() non-blocking commitid: 4c4a3fd17f97d82f337c1a990535b58f4abe2c68 fipvlan: don't add FIP socket to poll list if interface ... commitid: 04aa7a6908a345eadf55697202ae3dd5daadca96 [Open-FCoE] [PATCH] fipvlan: ensure that a socket is never in the poll ... http://www.open-fcoe.org/pipermail/devel/2010-July/010483.html diff --git a/fipvlan.c b/fipvlan.c index 432ff84..d32dda0 100644 --- a/fipvlan.c +++ b/fipvlan.c @@ -78,6 +78,11 @@ static int pfd_len = 0; void pfd_add(int fd) { struct pollfd *npfd; + int i; + + for (i = 0; i < pfd_len; i++) + if (pfd[i].fd == fd) + return; npfd = realloc(pfd, (pfd_len + 1) * sizeof(struct pollfd)); if (!npfd) { @@ -315,6 +320,10 @@ void rtnl_recv_newlink(struct nlmsghdr *nh) if (iff) { /* already tracking, update operstate and return */ iff->running = (ifm->ifi_flags & IFF_RUNNING) == IFF_RUNNING; + if (iff->running) + pfd_add(iff->ps); + else + pfd_remove(iff->ps); return; } @@ -363,7 +372,8 @@ void rtnl_recv_newlink(struct nlmsghdr *nh) iff->ps = fip_socket(iff->ifindex); setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV, &origdev, sizeof(origdev)); - pfd_add(iff->ps); + if (iff->running) + pfd_add(iff->ps); TAILQ_INSERT_TAIL(&interfaces, iff, list_node); } @@ -536,7 +546,7 @@ void print_results() printf("\n"); } -void recv_loop(struct pollfd *pfd, int pfd_len, int timeout) +void recv_loop(int timeout) { int i; int rc; @@ -551,14 +561,12 @@ void recv_loop(struct pollfd *pfd, int pfd_len, int timeout) break; } /* pfd[0] must be the netlink socket */ - if (pfd[0].revents) + if (pfd[0].revents & POLLIN) rtnl_recv(pfd[0].fd, rtnl_listener_handler, NULL); - pfd[0].revents = 0; /* everything else should be FIP packet sockets */ for (i = 1; i < pfd_len; i++) { - if (pfd[i].revents) + if (pfd[i].revents & POLLIN) fip_recv(pfd[i].fd, fip_vlan_handler, NULL); - pfd[i].revents = 0; } } } @@ -622,12 +630,12 @@ retry: skipped += send_vlan_requests(); if (skipped && skip_retry_count++ < 30) { FIP_LOG_DBG("waiting for IFF_RUNNING [%d]\n", skip_retry_count); - recv_loop(pfd, pfd_len, 500); + recv_loop(500); skipped = 0; retry_count = 0; goto retry; } - recv_loop(pfd, pfd_len, 200); + recv_loop(200); TAILQ_FOREACH(iff, &interfaces, list_node) /* if we did not receive a response, retry */ if (iff->req_sent && !iff->resp_recv && retry_count++ < 10) { @@ -675,7 +683,7 @@ int main(int argc, char **argv) * need to listen for the RTM_NETLINK messages * about the new VLAN devices */ - recv_loop(pfd, pfd_len, 500); + recv_loop(500); } if (config.start) start_fcoe(); diff --git a/lib/fip.c b/lib/fip.c index 4db245f..f8c8014 100644 --- a/lib/fip.c +++ b/lib/fip.c @@ -245,7 +245,7 @@ int fip_recv(int s, fip_handler *fn, void *arg) struct fiphdr *fh; ssize_t len, desc_len; - len = recvmsg(s, &msg, 0); + len = recvmsg(s, &msg, MSG_DONTWAIT); if (len < 0) { FIP_LOG_ERRNO("packet socket recv error"); return len;