There was actually a second potential deadlock.  I fixed both of them and
systematically annotated the functions, hopefully preventing the problem in the
future.

---
 lib/bfd.c |   66 +++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/lib/bfd.c b/lib/bfd.c
index 054a6ae..aa9a627 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -188,6 +188,7 @@ static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
 static struct hmap all_bfds__ = HMAP_INITIALIZER(&all_bfds__);
 static struct hmap *all_bfds OVS_GUARDED_BY(mutex) = &all_bfds__;
 
+static bool bfd_forwarding__(const struct bfd *) OVS_REQ_WRLOCK(mutex);
 static bool bfd_in_poll(const struct bfd *) OVS_REQ_WRLOCK(&mutex);
 static void bfd_poll(struct bfd *bfd) OVS_REQ_WRLOCK(&mutex);
 static const char *bfd_diag_str(enum diag) OVS_REQ_WRLOCK(&mutex);
@@ -216,19 +217,12 @@ static struct vlog_rate_limit rl = 
VLOG_RATE_LIMIT_INIT(20, 20);
 /* Returns true if the interface on which 'bfd' is running may be used to
  * forward traffic according to the BFD session state. */
 bool
-bfd_forwarding(const struct bfd *bfd)
+bfd_forwarding(const struct bfd *bfd) OVS_LOCKS_EXCLUDED(mutex)
 {
     bool ret;
 
     ovs_mutex_lock(&mutex);
-    if (bfd->forwarding_override != -1) {
-        ret = bfd->forwarding_override == 1;
-    } else {
-        ret = bfd->state == STATE_UP
-            && bfd->rmt_diag != DIAG_PATH_DOWN
-            && bfd->rmt_diag != DIAG_CPATH_DOWN
-            && bfd->rmt_diag != DIAG_RCPATH_DOWN;
-    }
+    ret = bfd_forwarding__(bfd);
     ovs_mutex_unlock(&mutex);
     return ret;
 }
@@ -237,9 +231,10 @@ bfd_forwarding(const struct bfd *bfd)
  * intended for the OVS database. */
 void
 bfd_get_status(const struct bfd *bfd, struct smap *smap)
+    OVS_LOCKS_EXCLUDED(mutex)
 {
     ovs_mutex_lock(&mutex);
-    smap_add(smap, "forwarding", bfd_forwarding(bfd) ? "true" : "false");
+    smap_add(smap, "forwarding", bfd_forwarding__(bfd)? "true" : "false");
     smap_add(smap, "state", bfd_state_str(bfd->state));
     smap_add(smap, "diagnostic", bfd_diag_str(bfd->diag));
 
@@ -256,8 +251,8 @@ bfd_get_status(const struct bfd *bfd, struct smap *smap)
  * handle for the session, or NULL if BFD is not enabled according to 'cfg'.
  * Also returns NULL if cfg is NULL. */
 struct bfd *
-bfd_configure(struct bfd *bfd, const char *name,
-              const struct smap *cfg)
+bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg)
+    OVS_LOCKS_EXCLUDED(mutex)
 {
     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     static atomic_uint16_t udp_src = ATOMIC_VAR_INIT(0);
@@ -352,7 +347,7 @@ bfd_ref(const struct bfd *bfd_)
 }
 
 void
-bfd_unref(struct bfd *bfd)
+bfd_unref(struct bfd *bfd) OVS_LOCKS_EXCLUDED(mutex)
 {
     if (bfd) {
         int orig;
@@ -370,7 +365,7 @@ bfd_unref(struct bfd *bfd)
 }
 
 void
-bfd_wait(const struct bfd *bfd)
+bfd_wait(const struct bfd *bfd) OVS_LOCKS_EXCLUDED(mutex)
 {
     ovs_mutex_lock(&mutex);
     if (bfd->flags & FLAG_FINAL) {
@@ -385,7 +380,7 @@ bfd_wait(const struct bfd *bfd)
 }
 
 void
-bfd_run(struct bfd *bfd)
+bfd_run(struct bfd *bfd) OVS_LOCKS_EXCLUDED(mutex)
 {
     ovs_mutex_lock(&mutex);
     if (bfd->state > STATE_DOWN && time_msec() >= bfd->detect_time) {
@@ -399,7 +394,7 @@ bfd_run(struct bfd *bfd)
 }
 
 bool
-bfd_should_send_packet(const struct bfd *bfd)
+bfd_should_send_packet(const struct bfd *bfd) OVS_LOCKS_EXCLUDED(mutex)
 {
     bool ret;
     ovs_mutex_lock(&mutex);
@@ -410,7 +405,7 @@ bfd_should_send_packet(const struct bfd *bfd)
 
 void
 bfd_put_packet(struct bfd *bfd, struct ofpbuf *p,
-               uint8_t eth_src[ETH_ADDR_LEN])
+               uint8_t eth_src[ETH_ADDR_LEN]) OVS_LOCKS_EXCLUDED(mutex)
 {
     long long int min_tx, min_rx;
     struct udp_header *udp;
@@ -504,7 +499,7 @@ bfd_should_process_flow(const struct bfd *bfd, const struct 
flow *flow,
 
 void
 bfd_process_packet(struct bfd *bfd, const struct flow *flow,
-                   const struct ofpbuf *p)
+                   const struct ofpbuf *p) OVS_LOCKS_EXCLUDED(mutex)
 {
     uint32_t rmt_min_rx, pkt_your_disc;
     enum state rmt_state;
@@ -665,15 +660,28 @@ out:
     ovs_mutex_unlock(&mutex);
 }
 
+static bool
+bfd_forwarding__(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
+{
+    if (bfd->forwarding_override != -1) {
+        return bfd->forwarding_override == 1;
+    }
+
+    return bfd->state == STATE_UP
+        && bfd->rmt_diag != DIAG_PATH_DOWN
+        && bfd->rmt_diag != DIAG_CPATH_DOWN
+        && bfd->rmt_diag != DIAG_RCPATH_DOWN;
+}
+
 /* Helpers. */
 static bool
-bfd_in_poll(const struct bfd *bfd)
+bfd_in_poll(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     return (bfd->flags & FLAG_POLL) != 0;
 }
 
 static void
-bfd_poll(struct bfd *bfd)
+bfd_poll(struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     if (bfd->state > STATE_DOWN && !bfd_in_poll(bfd)
         && !(bfd->flags & FLAG_FINAL)) {
@@ -686,7 +694,7 @@ bfd_poll(struct bfd *bfd)
 }
 
 static long long int
-bfd_min_tx(const struct bfd *bfd)
+bfd_min_tx(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     /* RFC 5880 Section 6.8.3
      * When bfd.SessionState is not Up, the system MUST set
@@ -698,20 +706,20 @@ bfd_min_tx(const struct bfd *bfd)
 }
 
 static long long int
-bfd_tx_interval(const struct bfd *bfd)
+bfd_tx_interval(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     long long int interval = bfd_min_tx(bfd);
     return MAX(interval, bfd->rmt_min_rx);
 }
 
 static long long int
-bfd_rx_interval(const struct bfd *bfd)
+bfd_rx_interval(const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     return MAX(bfd->min_rx, bfd->rmt_min_tx);
 }
 
 static void
-bfd_set_next_tx(struct bfd *bfd)
+bfd_set_next_tx(struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     long long int interval = bfd_tx_interval(bfd);
     interval -= interval * random_range(26) / 100;
@@ -787,7 +795,7 @@ bfd_diag_str(enum diag diag) {
 
 static void
 log_msg(enum vlog_level level, const struct msg *p, const char *message,
-        const struct bfd *bfd)
+        const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
 
@@ -819,6 +827,7 @@ log_msg(enum vlog_level level, const struct msg *p, const 
char *message,
 
 static void
 bfd_set_state(struct bfd *bfd, enum state state, enum diag diag)
+    OVS_REQ_WRLOCK(mutex)
 {
     if (diag == DIAG_NONE && bfd->cpath_down) {
         diag = DIAG_CPATH_DOWN;
@@ -880,7 +889,7 @@ generate_discriminator(void)
 }
 
 static struct bfd *
-bfd_find_by_name(const char *name) OVS_REQ_WRLOCK(&mutex)
+bfd_find_by_name(const char *name) OVS_REQ_WRLOCK(mutex)
 {
     struct bfd *bfd;
 
@@ -896,7 +905,7 @@ static void
 bfd_put_details(struct ds *ds, const struct bfd *bfd) OVS_REQ_WRLOCK(mutex)
 {
     ds_put_format(ds, "\tForwarding: %s\n",
-                  bfd_forwarding(bfd) ? "true" : "false");
+                  bfd_forwarding__(bfd) ? "true" : "false");
     ds_put_format(ds, "\tDetect Multiplier: %d\n", bfd->mult);
     ds_put_format(ds, "\tConcatenated Path Down: %s\n",
                   bfd->cpath_down ? "true" : "false");
@@ -936,7 +945,7 @@ bfd_put_details(struct ds *ds, const struct bfd *bfd) 
OVS_REQ_WRLOCK(mutex)
 
 static void
 bfd_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[],
-                 void *aux OVS_UNUSED)
+                 void *aux OVS_UNUSED) OVS_LOCKS_EXCLUDED(mutex)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
     struct bfd *bfd;
@@ -966,6 +975,7 @@ out:
 static void
 bfd_unixctl_set_forwarding_override(struct unixctl_conn *conn, int argc,
                                     const char *argv[], void *aux OVS_UNUSED)
+    OVS_LOCKS_EXCLUDED(mutex)
 {
     const char *forward_str = argv[argc - 1];
     int forwarding_override;
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to