]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rds/rdma_cm: send RDMA_CM_EVENT_ADDR_CHANGE event for active bonding
authorBang Nguyen <bang.nguyen@oracle.com>
Mon, 28 Oct 2013 13:53:31 +0000 (06:53 -0700)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Wed, 8 Jul 2015 20:59:52 +0000 (13:59 -0700)
Orabug: 18421516

This patch is forward ported from ofa-2.6.32-400.1.1.el5.x86_64-1.5.5-4.1.15

Signed-off-by: Bang Nguyen <bang.nguyen@oracle.com>
Signed-off-by: Avneesh Pant <avneesh.pant@oracle.com>
Signed-off-by: Chien Yen <chien.yen@oracle.com>
Signed-off-by: Ajaykumar Hotchandani <ajaykumar.hotchandani@oracle.com>
(cherry picked from commit b90f280baeedf4a56fae0c248d108ae118bb94ab)
Signed-off-by: Jerry Snitselaar <jerry.snitselaar@oracle.com>
Conflicts:
drivers/infiniband/core/cma.c

drivers/infiniband/core/cma.c
include/rdma/rdma_cm.h
net/rds/ib.c
net/rds/ib.h
net/rds/rdma_transport.c

index 3eef7e352a7280eb330566ed07950781260a82c5..f1f2eb60ac4448e07966fad69cf6ee99187b851d 100644 (file)
@@ -2267,6 +2267,42 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse)
 }
 EXPORT_SYMBOL(rdma_set_reuseaddr);
 
+int rdma_notify_addr_change(struct sockaddr *addr)
+{
+       struct cma_device *cma_dev;
+       struct rdma_id_private *id_priv;
+       struct sockaddr *src_addr;
+       struct cma_ndev_work *work;
+       int     ret;
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list) {
+               list_for_each_entry(id_priv, &cma_dev->id_list, list) {
+                       src_addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
+                       if (addr->sa_family == AF_INET &&
+                                       addr->sa_family == src_addr->sa_family &&
+                                       ((struct sockaddr_in *) addr)->sin_addr.s_addr ==
+                                       ((struct sockaddr_in *) src_addr)->sin_addr.s_addr) {
+                               work = kzalloc(sizeof *work, GFP_ATOMIC);
+                               if (!work) {
+                                       ret = -ENOMEM;
+                                       goto out;
+                               }
+
+                               INIT_WORK(&work->work, cma_ndev_work_handler);
+                               work->id = id_priv;
+                               work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
+                               atomic_inc(&id_priv->refcount);
+                               queue_work(cma_wq, &work->work);
+                       }
+               }
+       }
+out:
+       mutex_unlock(&lock);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_notify_addr_change);
+
 int rdma_set_afonly(struct rdma_cm_id *id, int afonly)
 {
        struct rdma_id_private *id_priv;
index 1ed2088dc9f5f029532f0b09765cf01a768624ba..feb5f95c129db1c2c6031eea41b7d1bd43d72288 100644 (file)
@@ -191,6 +191,14 @@ void rdma_destroy_id(struct rdma_cm_id *id);
  */
 int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);
 
+/**
+ * rdma_notify_addr_change - Notify users that its IP has moved to a
+ * different device.
+ *
+ * @addr: address information.
+ */
+int rdma_notify_addr_change(struct sockaddr *addr);
+
 /**
  * rdma_resolve_addr - Resolve destination and optional source addresses
  *   from IP addresses to an RDMA address.  If successful, the specified
index 948a3b3c036352d95bbfceec3d9a1ce837b06437..7bf7aa4c0e2e7fad0c4c885b828bd9ee31356a81 100644 (file)
@@ -559,6 +559,22 @@ static void rds_ib_conn_drop(struct work_struct *_work)
        kfree(work);
 }
 
+static void rds_ib_notify_addr_change(struct work_struct *_work)
+{
+       struct rds_ib_addr_change_work  *work =
+               container_of(_work, struct rds_ib_addr_change_work, work.work);
+       struct sockaddr_in      sin;
+       int ret;
+
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = work->addr;
+       sin.sin_port = 0;
+
+       ret = rdma_notify_addr_change((struct sockaddr *)&sin);
+
+       kfree(work);
+}
+
 static int rds_ib_move_ip(char                 *from_dev,
                        char                    *to_dev,
                        u8                      from_port,
@@ -583,6 +599,7 @@ static int rds_ib_move_ip(char                      *from_dev,
        struct rds_ib_connection *ic, *ic2;
        struct rds_ib_device *rds_ibdev;
        struct rds_ib_conn_drop_work *work;
+       struct rds_ib_addr_change_work *work_addrchange;
 
        page = alloc_page(GFP_HIGHUSER);
        if (!page) {
@@ -779,6 +796,15 @@ static int rds_ib_move_ip(char                     *from_dev,
                        }
                }
                spin_unlock_bh(&rds_ibdev->spinlock);
+
+               work_addrchange = kzalloc(sizeof *work, GFP_ATOMIC);
+               if (!work_addrchange) {
+                       printk(KERN_WARNING "RDS/IB: failed to allocate work\n");
+                       goto out;
+               }
+               work_addrchange->addr = addr;
+               INIT_DELAYED_WORK(&work_addrchange->work, rds_ib_notify_addr_change);
+               queue_delayed_work(rds_wq, &work_addrchange->work, 10);
        }
 
 out:
index 419b51e5ce669e9831953fa1ff20d26083aa421f..eda984eeaf1d5fc1ff08cc1b0db8c41f97432abf 100644 (file)
@@ -324,6 +324,11 @@ struct rds_ib_conn_drop_work {
        struct rds_ib_connection        *conn;
 };
 
+struct rds_ib_addr_change_work {
+       struct delayed_work             work;
+       __be32                          addr;
+};
+
 enum {
        RDS_IB_MR_8K_POOL,
        RDS_IB_MR_1M_POOL,
index 9e7c4bcf89c000ee1e3790ddee1d97a257d79502..70019e1947e7a5c416bd224a3593cd172a7402dd 100644 (file)
@@ -203,6 +203,8 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
                break;
 
        case RDMA_CM_EVENT_ADDR_CHANGE:
+               rdsdebug("ADDR_CHANGE event <%u.%u.%u.%u,%u.%u.%u.%u>\n",
+                        NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr));
 #if RDMA_RDS_APM_SUPPORTED
                if (conn && !rds_ib_apm_enabled)
                        rds_conn_drop(conn);