From: Jack Morgenstein <[email protected]>

Applications can request that the SM assign an mgid, by passing a mcast
member request containing an mgid = 0. When the SM responds by sending
the allocated mgid, this mgid replaces the 0-mgid in the multicast group.

However, the mgid field in the group is also the key field in the IB core
multicast code red-black tree containing the multicast groups for the port.

Since this is a key field, correct handling requires that the group entry
be deleted from the rb table, and then re-inserted with the new key,
so that the table structure is properly maintained.

The current code does not do this correctly. Correct operation
requires that if the key-field gid has changed at all, it should
be deleted and re-inserted, fix that.

Note that when inserting, if the new mgid is zero (not the case here
but the code should handle this correctly), we allow duplicate entries
for 0-mgids.

Signed-off-by: Jack Morgenstein <[email protected]>
Signed-off-by: Or Gerlitz <[email protected]>
---
 drivers/infiniband/core/multicast.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/core/multicast.c 
b/drivers/infiniband/core/multicast.c
index d2360a8..fa17b55 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -525,17 +525,22 @@ static void join_handler(int status, struct 
ib_sa_mcmember_rec *rec,
        if (status)
                process_join_error(group, status);
        else {
+               int mgids_changed, is_mgid0;
                ib_find_pkey(group->port->dev->device, group->port->port_num,
                             be16_to_cpu(rec->pkey), &pkey_index);
 
                spin_lock_irq(&group->port->lock);
-               group->rec = *rec;
                if (group->state == MCAST_BUSY &&
                    group->pkey_index == MCAST_INVALID_PKEY_INDEX)
                        group->pkey_index = pkey_index;
-               if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
+               mgids_changed = memcmp(&rec->mgid, &group->rec.mgid,
+                                      sizeof(group->rec.mgid));
+               group->rec = *rec;
+               if (mgids_changed) {
                        rb_erase(&group->node, &group->port->table);
-                       mcast_insert(group->port, group, 1);
+                       is_mgid0 = !memcmp(&mgid0, &group->rec.mgid,
+                                          sizeof(mgid0));
+                       mcast_insert(group->port, group, is_mgid0);
                }
                spin_unlock_irq(&group->port->lock);
        }
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to