diff options
author | Andy Grover <andy.grover@oracle.com> | 2009-04-01 04:20:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-02 03:52:22 -0400 |
commit | 745cbccac3fe8cead529a1b3358e1e86a1505bfa (patch) | |
tree | 6c865b19881dbdd64556cc1827f6966d8a646a38 /net/rds/ib_cm.c | |
parent | f1cffcbfcc53b825da7d1d26244aabd8dccb24aa (diff) |
RDS: Rewrite connection cleanup, fixing oops on rmmod
This fixes a bug where a connection was unexpectedly
not on *any* list while being destroyed. It also
cleans up some code duplication and regularizes some
function names.
* Grab appropriate lock in conn_free() and explain in comment
* Ensure via locking that a conn is never not on either
a dev's list or the nodev list
* Add rds_xx_remove_conn() to match rds_xx_add_conn()
* Make rds_xx_add_conn() return void
* Rename remove_{,nodev_}conns() to
destroy_{,nodev_}conns() and unify their implementation
in a helper function
* Document lock ordering as nodev conn_lock before
dev_conn_lock
Reported-by: Yosef Etigin <yosefe@voltaire.com>
Signed-off-by: Andy Grover <andy.grover@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rds/ib_cm.c')
-rw-r--r-- | net/rds/ib_cm.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 0532237bd128..889ab0441359 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -126,9 +126,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even | |||
126 | err = rds_ib_update_ipaddr(rds_ibdev, conn->c_laddr); | 126 | err = rds_ib_update_ipaddr(rds_ibdev, conn->c_laddr); |
127 | if (err) | 127 | if (err) |
128 | printk(KERN_ERR "rds_ib_update_ipaddr failed (%d)\n", err); | 128 | printk(KERN_ERR "rds_ib_update_ipaddr failed (%d)\n", err); |
129 | err = rds_ib_add_conn(rds_ibdev, conn); | 129 | rds_ib_add_conn(rds_ibdev, conn); |
130 | if (err) | ||
131 | printk(KERN_ERR "rds_ib_add_conn failed (%d)\n", err); | ||
132 | 130 | ||
133 | /* If the peer gave us the last packet it saw, process this as if | 131 | /* If the peer gave us the last packet it saw, process this as if |
134 | * we had received a regular ACK. */ | 132 | * we had received a regular ACK. */ |
@@ -616,18 +614,8 @@ void rds_ib_conn_shutdown(struct rds_connection *conn) | |||
616 | /* | 614 | /* |
617 | * Move connection back to the nodev list. | 615 | * Move connection back to the nodev list. |
618 | */ | 616 | */ |
619 | if (ic->rds_ibdev) { | 617 | if (ic->rds_ibdev) |
620 | 618 | rds_ib_remove_conn(ic->rds_ibdev, conn); | |
621 | spin_lock_irq(&ic->rds_ibdev->spinlock); | ||
622 | BUG_ON(list_empty(&ic->ib_node)); | ||
623 | list_del(&ic->ib_node); | ||
624 | spin_unlock_irq(&ic->rds_ibdev->spinlock); | ||
625 | |||
626 | spin_lock_irq(&ib_nodev_conns_lock); | ||
627 | list_add_tail(&ic->ib_node, &ib_nodev_conns); | ||
628 | spin_unlock_irq(&ib_nodev_conns_lock); | ||
629 | ic->rds_ibdev = NULL; | ||
630 | } | ||
631 | 619 | ||
632 | ic->i_cm_id = NULL; | 620 | ic->i_cm_id = NULL; |
633 | ic->i_pd = NULL; | 621 | ic->i_pd = NULL; |
@@ -701,11 +689,27 @@ int rds_ib_conn_alloc(struct rds_connection *conn, gfp_t gfp) | |||
701 | return 0; | 689 | return 0; |
702 | } | 690 | } |
703 | 691 | ||
692 | /* | ||
693 | * Free a connection. Connection must be shut down and not set for reconnect. | ||
694 | */ | ||
704 | void rds_ib_conn_free(void *arg) | 695 | void rds_ib_conn_free(void *arg) |
705 | { | 696 | { |
706 | struct rds_ib_connection *ic = arg; | 697 | struct rds_ib_connection *ic = arg; |
698 | spinlock_t *lock_ptr; | ||
699 | |||
707 | rdsdebug("ic %p\n", ic); | 700 | rdsdebug("ic %p\n", ic); |
701 | |||
702 | /* | ||
703 | * Conn is either on a dev's list or on the nodev list. | ||
704 | * A race with shutdown() or connect() would cause problems | ||
705 | * (since rds_ibdev would change) but that should never happen. | ||
706 | */ | ||
707 | lock_ptr = ic->rds_ibdev ? &ic->rds_ibdev->spinlock : &ib_nodev_conns_lock; | ||
708 | |||
709 | spin_lock_irq(lock_ptr); | ||
708 | list_del(&ic->ib_node); | 710 | list_del(&ic->ib_node); |
711 | spin_unlock_irq(lock_ptr); | ||
712 | |||
709 | kfree(ic); | 713 | kfree(ic); |
710 | } | 714 | } |
711 | 715 | ||