Skip to content

Commit

Permalink
rds: rcu-ize rds_ib_get_device()
Browse files Browse the repository at this point in the history
rds_ib_get_device is called very often as we turn an
ip address into a corresponding device structure.  It currently
take a global spinlock as it walks different lists to find active
devices.

This commit changes the lists over to RCU, which isn't very complex
because they are not updated very often at all.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason authored and Andy Grover committed Sep 9, 2010
1 parent c83188d commit 764f2dd
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
1 change: 1 addition & 0 deletions net/rds/ib.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void rds_ib_remove_one(struct ib_device *device)
if (!rds_ibdev)
return;

synchronize_rcu();
list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) {
list_del(&i_ipaddr->list);
kfree(i_ipaddr);
Expand Down
24 changes: 16 additions & 8 deletions net/rds/ib_rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/rculist.h>

#include "rds.h"
#include "ib.h"
Expand Down Expand Up @@ -83,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;
Expand All @@ -107,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;
Expand All @@ -116,16 +117,23 @@ 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 *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)
Expand Down

0 comments on commit 764f2dd

Please sign in to comment.