rds: Use RCU for the bind lookup searches
[linux-2.6.git] / net / rds / ib_rdma.c
index a92aebc..4ba01b9 100644 (file)
@@ -32,9 +32,9 @@
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/rculist.h>
 
 #include "rds.h"
-#include "rdma.h"
 #include "ib.h"
 
 
@@ -84,14 +84,14 @@ static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
        struct rds_ib_ipaddr *i_ipaddr;
 
        list_for_each_entry(rds_ibdev, &rds_ib_devices, list) {
-               spin_lock_irq(&rds_ibdev->spinlock);
-               list_for_each_entry(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
+               rcu_read_lock();
+               list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
                        if (i_ipaddr->ipaddr == ipaddr) {
-                               spin_unlock_irq(&rds_ibdev->spinlock);
+                               rcu_read_unlock();
                                return rds_ibdev;
                        }
                }
-               spin_unlock_irq(&rds_ibdev->spinlock);
+               rcu_read_unlock();
        }
 
        return NULL;
@@ -108,7 +108,7 @@ static int rds_ib_add_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
        i_ipaddr->ipaddr = ipaddr;
 
        spin_lock_irq(&rds_ibdev->spinlock);
-       list_add_tail(&i_ipaddr->list, &rds_ibdev->ipaddr_list);
+       list_add_tail_rcu(&i_ipaddr->list, &rds_ibdev->ipaddr_list);
        spin_unlock_irq(&rds_ibdev->spinlock);
 
        return 0;
@@ -116,17 +116,24 @@ static int rds_ib_add_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
 
 static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
 {
-       struct rds_ib_ipaddr *i_ipaddr, *next;
+       struct rds_ib_ipaddr *i_ipaddr;
+       struct rds_ib_ipaddr *to_free = NULL;
+
 
        spin_lock_irq(&rds_ibdev->spinlock);
-       list_for_each_entry_safe(i_ipaddr, next, &rds_ibdev->ipaddr_list, list) {
+       list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
                if (i_ipaddr->ipaddr == ipaddr) {
-                       list_del(&i_ipaddr->list);
-                       kfree(i_ipaddr);
+                       list_del_rcu(&i_ipaddr->list);
+                       to_free = i_ipaddr;
                        break;
                }
        }
        spin_unlock_irq(&rds_ibdev->spinlock);
+
+       if (to_free) {
+               synchronize_rcu();
+               kfree(to_free);
+       }
 }
 
 int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
@@ -290,16 +297,20 @@ static struct rds_ib_mr *rds_ib_alloc_fmr(struct rds_ib_device *rds_ibdev)
                rds_ib_flush_mr_pool(pool, 0);
        }
 
-       ibmr = kzalloc(sizeof(*ibmr), GFP_KERNEL);
+       ibmr = kzalloc_node(sizeof(*ibmr), GFP_KERNEL, rdsibdev_to_node(rds_ibdev));
        if (!ibmr) {
                err = -ENOMEM;
                goto out_no_cigar;
        }
 
+       memset(ibmr, 0, sizeof(*ibmr));
+
        ibmr->fmr = ib_alloc_fmr(rds_ibdev->pd,
                        (IB_ACCESS_LOCAL_WRITE |
                         IB_ACCESS_REMOTE_READ |
-                        IB_ACCESS_REMOTE_WRITE),
+                        IB_ACCESS_REMOTE_WRITE|
+                        IB_ACCESS_REMOTE_ATOMIC),
+
                        &pool->fmr_attr);
        if (IS_ERR(ibmr->fmr)) {
                err = PTR_ERR(ibmr->fmr);
@@ -367,7 +378,8 @@ static int rds_ib_map_fmr(struct rds_ib_device *rds_ibdev, struct rds_ib_mr *ibm
        if (page_cnt > fmr_message_size)
                return -EINVAL;
 
-       dma_pages = kmalloc(sizeof(u64) * page_cnt, GFP_ATOMIC);
+       dma_pages = kmalloc_node(sizeof(u64) * page_cnt, GFP_ATOMIC,
+                                rdsibdev_to_node(rds_ibdev));
        if (!dma_pages)
                return -ENOMEM;