[DLM] Make sock_sem into a mutex
Now that there can be multiple dlm_recv threads running we need to prevent two recvs running for the same connection - it's unlikely but it can happen and it causes message corruption. Signed-Off-By: Patrick Caulfield <pcaulfie@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
parent
d043e1900c
commit
f1f1c1ccf7
@ -96,7 +96,7 @@ static bool cbuf_empty(struct cbuf *cb)
|
|||||||
struct connection {
|
struct connection {
|
||||||
struct socket *sock; /* NULL if not connected */
|
struct socket *sock; /* NULL if not connected */
|
||||||
uint32_t nodeid; /* So we know who we are in the list */
|
uint32_t nodeid; /* So we know who we are in the list */
|
||||||
struct rw_semaphore sock_sem; /* Stop connect races */
|
struct mutex sock_mutex;
|
||||||
unsigned long flags; /* bit 1,2 = We are on the read/write lists */
|
unsigned long flags; /* bit 1,2 = We are on the read/write lists */
|
||||||
#define CF_READ_PENDING 1
|
#define CF_READ_PENDING 1
|
||||||
#define CF_WRITE_PENDING 2
|
#define CF_WRITE_PENDING 2
|
||||||
@ -171,7 +171,7 @@ static struct connection *nodeid2con(int nodeid, gfp_t allocation)
|
|||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
con->nodeid = nodeid;
|
con->nodeid = nodeid;
|
||||||
init_rwsem(&con->sock_sem);
|
mutex_init(&con->sock_mutex);
|
||||||
INIT_LIST_HEAD(&con->writequeue);
|
INIT_LIST_HEAD(&con->writequeue);
|
||||||
spin_lock_init(&con->writequeue_lock);
|
spin_lock_init(&con->writequeue_lock);
|
||||||
INIT_WORK(&con->swork, process_send_sockets);
|
INIT_WORK(&con->swork, process_send_sockets);
|
||||||
@ -247,7 +247,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
|
|||||||
/* Close a remote connection and tidy up */
|
/* Close a remote connection and tidy up */
|
||||||
static void close_connection(struct connection *con, bool and_other)
|
static void close_connection(struct connection *con, bool and_other)
|
||||||
{
|
{
|
||||||
down_write(&con->sock_sem);
|
mutex_lock(&con->sock_mutex);
|
||||||
|
|
||||||
if (con->sock) {
|
if (con->sock) {
|
||||||
sock_release(con->sock);
|
sock_release(con->sock);
|
||||||
@ -262,7 +262,7 @@ static void close_connection(struct connection *con, bool and_other)
|
|||||||
con->rx_page = NULL;
|
con->rx_page = NULL;
|
||||||
}
|
}
|
||||||
con->retries = 0;
|
con->retries = 0;
|
||||||
up_write(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data received from remote end */
|
/* Data received from remote end */
|
||||||
@ -276,7 +276,7 @@ static int receive_from_sock(struct connection *con)
|
|||||||
int r;
|
int r;
|
||||||
int call_again_soon = 0;
|
int call_again_soon = 0;
|
||||||
|
|
||||||
down_read(&con->sock_sem);
|
mutex_lock(&con->sock_mutex);
|
||||||
|
|
||||||
if (con->sock == NULL)
|
if (con->sock == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
@ -355,17 +355,17 @@ static int receive_from_sock(struct connection *con)
|
|||||||
out:
|
out:
|
||||||
if (call_again_soon)
|
if (call_again_soon)
|
||||||
goto out_resched;
|
goto out_resched;
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_resched:
|
out_resched:
|
||||||
if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
|
if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
|
||||||
queue_work(recv_workqueue, &con->rwork);
|
queue_work(recv_workqueue, &con->rwork);
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
out_close:
|
out_close:
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
|
if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
|
||||||
close_connection(con, false);
|
close_connection(con, false);
|
||||||
/* Reconnect when there is something to send */
|
/* Reconnect when there is something to send */
|
||||||
@ -391,7 +391,7 @@ static int accept_from_sock(struct connection *con)
|
|||||||
if (result < 0)
|
if (result < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
down_read_nested(&con->sock_sem, 0);
|
mutex_lock_nested(&con->sock_mutex, 0);
|
||||||
|
|
||||||
result = -ENOTCONN;
|
result = -ENOTCONN;
|
||||||
if (con->sock == NULL)
|
if (con->sock == NULL)
|
||||||
@ -417,7 +417,7 @@ static int accept_from_sock(struct connection *con)
|
|||||||
if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
|
if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
|
||||||
printk("dlm: connect from non cluster node\n");
|
printk("dlm: connect from non cluster node\n");
|
||||||
sock_release(newsock);
|
sock_release(newsock);
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +434,7 @@ static int accept_from_sock(struct connection *con)
|
|||||||
result = -ENOMEM;
|
result = -ENOMEM;
|
||||||
goto accept_err;
|
goto accept_err;
|
||||||
}
|
}
|
||||||
down_write_nested(&newcon->sock_sem, 1);
|
mutex_lock_nested(&newcon->sock_mutex, 1);
|
||||||
if (newcon->sock) {
|
if (newcon->sock) {
|
||||||
struct connection *othercon = newcon->othercon;
|
struct connection *othercon = newcon->othercon;
|
||||||
|
|
||||||
@ -442,13 +442,13 @@ static int accept_from_sock(struct connection *con)
|
|||||||
othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
|
othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
|
||||||
if (!othercon) {
|
if (!othercon) {
|
||||||
printk("dlm: failed to allocate incoming socket\n");
|
printk("dlm: failed to allocate incoming socket\n");
|
||||||
up_write(&newcon->sock_sem);
|
mutex_unlock(&newcon->sock_mutex);
|
||||||
result = -ENOMEM;
|
result = -ENOMEM;
|
||||||
goto accept_err;
|
goto accept_err;
|
||||||
}
|
}
|
||||||
othercon->nodeid = nodeid;
|
othercon->nodeid = nodeid;
|
||||||
othercon->rx_action = receive_from_sock;
|
othercon->rx_action = receive_from_sock;
|
||||||
init_rwsem(&othercon->sock_sem);
|
mutex_init(&othercon->sock_mutex);
|
||||||
INIT_WORK(&othercon->swork, process_send_sockets);
|
INIT_WORK(&othercon->swork, process_send_sockets);
|
||||||
INIT_WORK(&othercon->rwork, process_recv_sockets);
|
INIT_WORK(&othercon->rwork, process_recv_sockets);
|
||||||
set_bit(CF_IS_OTHERCON, &othercon->flags);
|
set_bit(CF_IS_OTHERCON, &othercon->flags);
|
||||||
@ -466,7 +466,7 @@ static int accept_from_sock(struct connection *con)
|
|||||||
addcon = newcon;
|
addcon = newcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
up_write(&newcon->sock_sem);
|
mutex_unlock(&newcon->sock_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add it to the active queue in case we got data
|
* Add it to the active queue in case we got data
|
||||||
@ -475,12 +475,12 @@ static int accept_from_sock(struct connection *con)
|
|||||||
*/
|
*/
|
||||||
if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
|
if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
|
||||||
queue_work(recv_workqueue, &addcon->rwork);
|
queue_work(recv_workqueue, &addcon->rwork);
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
accept_err:
|
accept_err:
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
sock_release(newsock);
|
sock_release(newsock);
|
||||||
|
|
||||||
if (result != -EAGAIN)
|
if (result != -EAGAIN)
|
||||||
@ -501,7 +501,7 @@ static void connect_to_sock(struct connection *con)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(&con->sock_sem);
|
mutex_lock(&con->sock_mutex);
|
||||||
if (con->retries++ > MAX_CONNECT_RETRIES)
|
if (con->retries++ > MAX_CONNECT_RETRIES)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -553,7 +553,7 @@ out_err:
|
|||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
up_write(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +757,7 @@ static void send_to_sock(struct connection *con)
|
|||||||
struct writequeue_entry *e;
|
struct writequeue_entry *e;
|
||||||
int len, offset;
|
int len, offset;
|
||||||
|
|
||||||
down_read(&con->sock_sem);
|
mutex_lock(&con->sock_mutex);
|
||||||
if (con->sock == NULL)
|
if (con->sock == NULL)
|
||||||
goto out_connect;
|
goto out_connect;
|
||||||
|
|
||||||
@ -803,17 +803,17 @@ static void send_to_sock(struct connection *con)
|
|||||||
}
|
}
|
||||||
spin_unlock(&con->writequeue_lock);
|
spin_unlock(&con->writequeue_lock);
|
||||||
out:
|
out:
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
send_error:
|
send_error:
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
close_connection(con, false);
|
close_connection(con, false);
|
||||||
lowcomms_connect_sock(con);
|
lowcomms_connect_sock(con);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
out_connect:
|
out_connect:
|
||||||
up_read(&con->sock_sem);
|
mutex_unlock(&con->sock_mutex);
|
||||||
connect_to_sock(con);
|
connect_to_sock(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user