Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 214372
b: refs/heads/master
c: 2dc3935
h: refs/heads/master
v: v3
  • Loading branch information
Andy Grover committed Sep 9, 2010
1 parent ba7d588 commit 1571e5e
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 54 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9de0864cf55927a7383b5ba6e48834ff3ef053de
refs/heads/master: 2dc393573430f853e56e25bf4b41c34ba2aa8fd6
53 changes: 53 additions & 0 deletions trunk/net/rds/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,59 @@ struct rds_connection *rds_conn_create_outgoing(__be32 laddr, __be32 faddr,
}
EXPORT_SYMBOL_GPL(rds_conn_create_outgoing);

void rds_conn_shutdown(struct rds_connection *conn)
{
/* shut it down unless it's down already */
if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_DOWN)) {
/*
* Quiesce the connection mgmt handlers before we start tearing
* things down. We don't hold the mutex for the entire
* duration of the shutdown operation, else we may be
* deadlocking with the CM handler. Instead, the CM event
* handler is supposed to check for state DISCONNECTING
*/
mutex_lock(&conn->c_cm_lock);
if (!rds_conn_transition(conn, RDS_CONN_UP, RDS_CONN_DISCONNECTING)
&& !rds_conn_transition(conn, RDS_CONN_ERROR, RDS_CONN_DISCONNECTING)) {
rds_conn_error(conn, "shutdown called in state %d\n",
atomic_read(&conn->c_state));
mutex_unlock(&conn->c_cm_lock);
return;
}
mutex_unlock(&conn->c_cm_lock);

mutex_lock(&conn->c_send_lock);
conn->c_trans->conn_shutdown(conn);
rds_conn_reset(conn);
mutex_unlock(&conn->c_send_lock);

if (!rds_conn_transition(conn, RDS_CONN_DISCONNECTING, RDS_CONN_DOWN)) {
/* This can happen - eg when we're in the middle of tearing
* down the connection, and someone unloads the rds module.
* Quite reproduceable with loopback connections.
* Mostly harmless.
*/
rds_conn_error(conn,
"%s: failed to transition to state DOWN, "
"current state is %d\n",
__func__,
atomic_read(&conn->c_state));
return;
}
}

/* Then reconnect if it's still live.
* The passive side of an IB loopback connection is never added
* to the conn hash, so we never trigger a reconnect on this
* conn - the reconnect is always triggered by the active peer. */
cancel_delayed_work_sync(&conn->c_conn_w);
if (!hlist_unhashed(&conn->c_hash_node))
rds_queue_reconnect(conn);
}

/*
* Stop and free a connection.
*/
void rds_conn_destroy(struct rds_connection *conn)
{
struct rds_message *rm, *rtmp;
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/rds/rds.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ struct rds_connection *rds_conn_create(__be32 laddr, __be32 faddr,
struct rds_transport *trans, gfp_t gfp);
struct rds_connection *rds_conn_create_outgoing(__be32 laddr, __be32 faddr,
struct rds_transport *trans, gfp_t gfp);
void rds_conn_shutdown(struct rds_connection *conn);
void rds_conn_destroy(struct rds_connection *conn);
void rds_conn_reset(struct rds_connection *conn);
void rds_conn_drop(struct rds_connection *conn);
Expand Down Expand Up @@ -681,6 +682,7 @@ extern unsigned int rds_sysctl_trace_level;
int __init rds_threads_init(void);
void rds_threads_exit(void);
extern struct workqueue_struct *rds_wq;
void rds_queue_reconnect(struct rds_connection *conn);
void rds_connect_worker(struct work_struct *);
void rds_shutdown_worker(struct work_struct *);
void rds_send_worker(struct work_struct *);
Expand Down
61 changes: 8 additions & 53 deletions trunk/net/rds/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ EXPORT_SYMBOL_GPL(rds_connect_complete);
* We should *always* start with a random backoff; otherwise a broken connection
* will always take several iterations to be re-established.
*/
static void rds_queue_reconnect(struct rds_connection *conn)
void rds_queue_reconnect(struct rds_connection *conn)
{
unsigned long rand;

Expand Down Expand Up @@ -156,58 +156,6 @@ void rds_connect_worker(struct work_struct *work)
}
}

void rds_shutdown_worker(struct work_struct *work)
{
struct rds_connection *conn = container_of(work, struct rds_connection, c_down_w);

/* shut it down unless it's down already */
if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_DOWN)) {
/*
* Quiesce the connection mgmt handlers before we start tearing
* things down. We don't hold the mutex for the entire
* duration of the shutdown operation, else we may be
* deadlocking with the CM handler. Instead, the CM event
* handler is supposed to check for state DISCONNECTING
*/
mutex_lock(&conn->c_cm_lock);
if (!rds_conn_transition(conn, RDS_CONN_UP, RDS_CONN_DISCONNECTING) &&
!rds_conn_transition(conn, RDS_CONN_ERROR, RDS_CONN_DISCONNECTING)) {
rds_conn_error(conn, "shutdown called in state %d\n",
atomic_read(&conn->c_state));
mutex_unlock(&conn->c_cm_lock);
return;
}
mutex_unlock(&conn->c_cm_lock);

mutex_lock(&conn->c_send_lock);
conn->c_trans->conn_shutdown(conn);
rds_conn_reset(conn);
mutex_unlock(&conn->c_send_lock);

if (!rds_conn_transition(conn, RDS_CONN_DISCONNECTING, RDS_CONN_DOWN)) {
/* This can happen - eg when we're in the middle of tearing
* down the connection, and someone unloads the rds module.
* Quite reproduceable with loopback connections.
* Mostly harmless.
*/
rds_conn_error(conn,
"%s: failed to transition to state DOWN, "
"current state is %d\n",
__func__,
atomic_read(&conn->c_state));
return;
}
}

/* Then reconnect if it's still live.
* The passive side of an IB loopback connection is never added
* to the conn hash, so we never trigger a reconnect on this
* conn - the reconnect is always triggered by the active peer. */
cancel_delayed_work(&conn->c_conn_w);
if (!hlist_unhashed(&conn->c_hash_node))
rds_queue_reconnect(conn);
}

void rds_send_worker(struct work_struct *work)
{
struct rds_connection *conn = container_of(work, struct rds_connection, c_send_w.work);
Expand Down Expand Up @@ -252,6 +200,13 @@ void rds_recv_worker(struct work_struct *work)
}
}

void rds_shutdown_worker(struct work_struct *work)
{
struct rds_connection *conn = container_of(work, struct rds_connection, c_down_w);

rds_conn_shutdown(conn);
}

void rds_threads_exit(void)
{
destroy_workqueue(rds_wq);
Expand Down

0 comments on commit 1571e5e

Please sign in to comment.