dlm for 5.11
This set includes more low level communication layer cleanups. The main change is the listening socket is no longer handled as a special case of node connection sockets. There is one small fix for checking the number of local connections. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJf16V5AAoJEDgbc8f8gGmq3Q0P/1dkBfle74X26xyACzKlb4iS s/1wN1s0eMcxv2gRwWsw1q30OuNKkvZhVaI2a5djx8KimrR3Xizy6jcnopLrlna9 NHL9chLu1NbBI98ad8UugYciwukyRBI0ZgE5hMuef1LeLXlSFWWu8VTv92ejXTxf O2B7/oJuFAjQtWGysOVKNOJLoUIKKmQngyRVfMuhC8p6bauL1+ljAQv/s3dfM6wg dNHAb6BKgBmEmbzdBDuUahBfdh528Ih1+zMuaRx3yIUoVcGagnACjypcNefX8Bhk IU+JHjgHg8v3KazovIxFV6KDoS8c0aQ9Lt3GO0zfDqN/joHNtAF4FtSdfM5SQUzB LSbVYXS5nr5sfJ+Jg+dA7EzVF7ZtQEcfkFQLkwVhbOCLkDoTAQ0Qulqk7n7I5wMZ 4FQRqCKNhawAvTS9Bv5CoVldk/48c9Bhbum6Y9FsisiMxXtoJeG1H0UWOlLqYexV eF99fxT+fWW85QPb0zeZblzO0uw8hbTuc4EYCW1ZsRXV7nxblG/T6SK1keZqKL6C +edWJNIJgP7PPyfLkVrsTSNYwRUOBKYIyNjy/iZfist6ueWYtH3p2pbKuVt1UT5O R6UGFlGP/NgtcSibQkSBW/FXXgCzy056+jVYFJVcniKnSO9sq5519DB3kSWnm7Uk ZxjfxMCG9pWxLVrwftcl =ORtZ -----END PGP SIGNATURE----- Merge tag 'dlm-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm Pull dlm updates from David Teigland: "This set includes more low level communication layer cleanups. The main change is the listening socket is no longer handled as a special case of node connection sockets. There is one small fix for checking the number of local connections" * tag 'dlm-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm: fs: dlm: check on existing node address fs: dlm: constify addr_compare fs: dlm: fix check for multi-homed hosts fs: dlm: listen socket out of connection hash fs: dlm: refactor sctp sock parameter fs: dlm: move shutdown action to node creation fs: dlm: move connect callback in node creation fs: dlm: add helper for init connection fs: dlm: handle non blocked connect event fs: dlm: flush othercon at close fs: dlm: add get buffer error handling fs: dlm: define max send buffer fs: dlm: fix proper srcu api call
This commit is contained in:
commit
8a7a4301dd
@ -572,7 +572,7 @@ static int new_lockspace(const char *name, const char *cluster,
|
||||
mutex_init(&ls->ls_requestqueue_mutex);
|
||||
mutex_init(&ls->ls_clear_proc_locks);
|
||||
|
||||
ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
|
||||
ls->ls_recover_buf = kmalloc(LOWCOMMS_MAX_TX_BUFFER_LEN, GFP_NOFS);
|
||||
if (!ls->ls_recover_buf)
|
||||
goto out_lkbidr;
|
||||
|
||||
|
@ -78,9 +78,9 @@ struct connection {
|
||||
#define CF_APP_LIMITED 7
|
||||
#define CF_CLOSING 8
|
||||
#define CF_SHUTDOWN 9
|
||||
#define CF_CONNECTED 10
|
||||
struct list_head writequeue; /* List of outgoing writequeue_entries */
|
||||
spinlock_t writequeue_lock;
|
||||
int (*rx_action) (struct connection *); /* What to do when active */
|
||||
void (*connect_action) (struct connection *); /* What to do to connect */
|
||||
void (*shutdown_action)(struct connection *con); /* What to do to shutdown */
|
||||
int retries;
|
||||
@ -97,6 +97,11 @@ struct connection {
|
||||
};
|
||||
#define sock2con(x) ((struct connection *)(x)->sk_user_data)
|
||||
|
||||
struct listen_connection {
|
||||
struct socket *sock;
|
||||
struct work_struct rwork;
|
||||
};
|
||||
|
||||
/* An entry waiting to be sent */
|
||||
struct writequeue_entry {
|
||||
struct list_head list;
|
||||
@ -126,6 +131,7 @@ static struct listen_sock_callbacks {
|
||||
static LIST_HEAD(dlm_node_addrs);
|
||||
static DEFINE_SPINLOCK(dlm_node_addrs_spin);
|
||||
|
||||
static struct listen_connection listen_con;
|
||||
static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
|
||||
static int dlm_local_count;
|
||||
static int dlm_allow_conn;
|
||||
@ -141,6 +147,9 @@ DEFINE_STATIC_SRCU(connections_srcu);
|
||||
static void process_recv_sockets(struct work_struct *work);
|
||||
static void process_send_sockets(struct work_struct *work);
|
||||
|
||||
static void sctp_connect_to_sock(struct connection *con);
|
||||
static void tcp_connect_to_sock(struct connection *con);
|
||||
static void dlm_tcp_shutdown(struct connection *con);
|
||||
|
||||
/* This is deliberately very simple because most clusters have simple
|
||||
sequential nodeids, so we should be able to go straight to a connection
|
||||
@ -169,29 +178,12 @@ static struct connection *__find_con(int nodeid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If 'allocation' is zero then we don't attempt to create a new
|
||||
* connection structure for this node.
|
||||
*/
|
||||
static struct connection *nodeid2con(int nodeid, gfp_t alloc)
|
||||
static int dlm_con_init(struct connection *con, int nodeid)
|
||||
{
|
||||
struct connection *con, *tmp;
|
||||
int r;
|
||||
|
||||
con = __find_con(nodeid);
|
||||
if (con || !alloc)
|
||||
return con;
|
||||
|
||||
con = kzalloc(sizeof(*con), alloc);
|
||||
if (!con)
|
||||
return NULL;
|
||||
|
||||
con->rx_buflen = dlm_config.ci_buffer_size;
|
||||
con->rx_buf = kmalloc(con->rx_buflen, GFP_NOFS);
|
||||
if (!con->rx_buf) {
|
||||
kfree(con);
|
||||
return NULL;
|
||||
}
|
||||
if (!con->rx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
con->nodeid = nodeid;
|
||||
mutex_init(&con->sock_mutex);
|
||||
@ -201,13 +193,37 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
|
||||
INIT_WORK(&con->rwork, process_recv_sockets);
|
||||
init_waitqueue_head(&con->shutdown_wait);
|
||||
|
||||
/* Setup action pointers for child sockets */
|
||||
if (con->nodeid) {
|
||||
struct connection *zerocon = __find_con(0);
|
||||
if (dlm_config.ci_protocol == 0) {
|
||||
con->connect_action = tcp_connect_to_sock;
|
||||
con->shutdown_action = dlm_tcp_shutdown;
|
||||
} else {
|
||||
con->connect_action = sctp_connect_to_sock;
|
||||
}
|
||||
|
||||
con->connect_action = zerocon->connect_action;
|
||||
if (!con->rx_action)
|
||||
con->rx_action = zerocon->rx_action;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If 'allocation' is zero then we don't attempt to create a new
|
||||
* connection structure for this node.
|
||||
*/
|
||||
static struct connection *nodeid2con(int nodeid, gfp_t alloc)
|
||||
{
|
||||
struct connection *con, *tmp;
|
||||
int r, ret;
|
||||
|
||||
con = __find_con(nodeid);
|
||||
if (con || !alloc)
|
||||
return con;
|
||||
|
||||
con = kzalloc(sizeof(*con), alloc);
|
||||
if (!con)
|
||||
return NULL;
|
||||
|
||||
ret = dlm_con_init(con, nodeid);
|
||||
if (ret) {
|
||||
kfree(con);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = nodeid_hash(nodeid);
|
||||
@ -258,7 +274,8 @@ static struct dlm_node_addr *find_node_addr(int nodeid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
|
||||
static int addr_compare(const struct sockaddr_storage *x,
|
||||
const struct sockaddr_storage *y)
|
||||
{
|
||||
switch (x->ss_family) {
|
||||
case AF_INET: {
|
||||
@ -357,10 +374,25 @@ unlock:
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* caller need to held dlm_node_addrs_spin lock */
|
||||
static bool dlm_lowcomms_na_has_addr(const struct dlm_node_addr *na,
|
||||
const struct sockaddr_storage *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < na->addr_count; i++) {
|
||||
if (addr_compare(na->addr[i], addr))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len)
|
||||
{
|
||||
struct sockaddr_storage *new_addr;
|
||||
struct dlm_node_addr *new_node, *na;
|
||||
bool ret;
|
||||
|
||||
new_node = kzalloc(sizeof(struct dlm_node_addr), GFP_NOFS);
|
||||
if (!new_node)
|
||||
@ -385,6 +417,14 @@ int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dlm_lowcomms_na_has_addr(na, addr);
|
||||
if (ret) {
|
||||
spin_unlock(&dlm_node_addrs_spin);
|
||||
kfree(new_addr);
|
||||
kfree(new_node);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (na->addr_count >= DLM_MAX_ADDR_COUNT) {
|
||||
spin_unlock(&dlm_node_addrs_spin);
|
||||
kfree(new_addr);
|
||||
@ -410,6 +450,11 @@ static void lowcomms_data_ready(struct sock *sk)
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
static void lowcomms_listen_data_ready(struct sock *sk)
|
||||
{
|
||||
queue_work(recv_workqueue, &listen_con.rwork);
|
||||
}
|
||||
|
||||
static void lowcomms_write_space(struct sock *sk)
|
||||
{
|
||||
struct connection *con;
|
||||
@ -419,6 +464,12 @@ static void lowcomms_write_space(struct sock *sk)
|
||||
if (!con)
|
||||
goto out;
|
||||
|
||||
if (!test_and_set_bit(CF_CONNECTED, &con->flags)) {
|
||||
log_print("successful connected to node %d", con->nodeid);
|
||||
queue_work(send_workqueue, &con->swork);
|
||||
goto out;
|
||||
}
|
||||
|
||||
clear_bit(SOCK_NOSPACE, &con->sock->flags);
|
||||
|
||||
if (test_and_clear_bit(CF_APP_LIMITED, &con->flags)) {
|
||||
@ -539,6 +590,21 @@ static void restore_callbacks(struct socket *sock)
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
static void add_listen_sock(struct socket *sock, struct listen_connection *con)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
save_listen_callbacks(sock);
|
||||
con->sock = sock;
|
||||
|
||||
sk->sk_user_data = con;
|
||||
sk->sk_allocation = GFP_NOFS;
|
||||
/* Install a data_ready callback */
|
||||
sk->sk_data_ready = lowcomms_listen_data_ready;
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
/* Make a socket active */
|
||||
static void add_sock(struct socket *sock, struct connection *con)
|
||||
{
|
||||
@ -576,6 +642,15 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
|
||||
memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len);
|
||||
}
|
||||
|
||||
static void dlm_close_sock(struct socket **sock)
|
||||
{
|
||||
if (*sock) {
|
||||
restore_callbacks(*sock);
|
||||
sock_release(*sock);
|
||||
*sock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close a remote connection and tidy up */
|
||||
static void close_connection(struct connection *con, bool and_other,
|
||||
bool tx, bool rx)
|
||||
@ -592,11 +667,8 @@ static void close_connection(struct connection *con, bool and_other,
|
||||
}
|
||||
|
||||
mutex_lock(&con->sock_mutex);
|
||||
if (con->sock) {
|
||||
restore_callbacks(con->sock);
|
||||
sock_release(con->sock);
|
||||
con->sock = NULL;
|
||||
}
|
||||
dlm_close_sock(&con->sock);
|
||||
|
||||
if (con->othercon && and_other) {
|
||||
/* Will only re-enter once. */
|
||||
close_connection(con->othercon, false, true, true);
|
||||
@ -604,6 +676,7 @@ static void close_connection(struct connection *con, bool and_other,
|
||||
|
||||
con->rx_leftover = 0;
|
||||
con->retries = 0;
|
||||
clear_bit(CF_CONNECTED, &con->flags);
|
||||
mutex_unlock(&con->sock_mutex);
|
||||
clear_bit(CF_CLOSING, &con->flags);
|
||||
}
|
||||
@ -691,11 +764,6 @@ static int receive_from_sock(struct connection *con)
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (con->nodeid == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
/* realloc if we get new buffer size to read out */
|
||||
buflen = dlm_config.ci_buffer_size;
|
||||
if (con->rx_buflen != buflen && con->rx_leftover <= buflen) {
|
||||
@ -767,7 +835,7 @@ out_close:
|
||||
}
|
||||
|
||||
/* Listening socket is busy, accept a connection */
|
||||
static int accept_from_sock(struct connection *con)
|
||||
static int accept_from_sock(struct listen_connection *con)
|
||||
{
|
||||
int result;
|
||||
struct sockaddr_storage peeraddr;
|
||||
@ -782,12 +850,8 @@ static int accept_from_sock(struct connection *con)
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock_nested(&con->sock_mutex, 0);
|
||||
|
||||
if (!con->sock) {
|
||||
mutex_unlock(&con->sock_mutex);
|
||||
if (!con->sock)
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
result = kernel_accept(con->sock, &newsock, O_NONBLOCK);
|
||||
if (result < 0)
|
||||
@ -809,7 +873,6 @@ static int accept_from_sock(struct connection *con)
|
||||
print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE,
|
||||
b, sizeof(struct sockaddr_storage));
|
||||
sock_release(newsock);
|
||||
mutex_unlock(&con->sock_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -828,7 +891,8 @@ static int accept_from_sock(struct connection *con)
|
||||
result = -ENOMEM;
|
||||
goto accept_err;
|
||||
}
|
||||
mutex_lock_nested(&newcon->sock_mutex, 1);
|
||||
|
||||
mutex_lock(&newcon->sock_mutex);
|
||||
if (newcon->sock) {
|
||||
struct connection *othercon = newcon->othercon;
|
||||
|
||||
@ -841,38 +905,24 @@ static int accept_from_sock(struct connection *con)
|
||||
goto accept_err;
|
||||
}
|
||||
|
||||
othercon->rx_buflen = dlm_config.ci_buffer_size;
|
||||
othercon->rx_buf = kmalloc(othercon->rx_buflen, GFP_NOFS);
|
||||
if (!othercon->rx_buf) {
|
||||
mutex_unlock(&newcon->sock_mutex);
|
||||
result = dlm_con_init(othercon, nodeid);
|
||||
if (result < 0) {
|
||||
kfree(othercon);
|
||||
log_print("failed to allocate incoming socket receive buffer");
|
||||
result = -ENOMEM;
|
||||
goto accept_err;
|
||||
}
|
||||
|
||||
othercon->nodeid = nodeid;
|
||||
othercon->rx_action = receive_from_sock;
|
||||
mutex_init(&othercon->sock_mutex);
|
||||
INIT_LIST_HEAD(&othercon->writequeue);
|
||||
spin_lock_init(&othercon->writequeue_lock);
|
||||
INIT_WORK(&othercon->swork, process_send_sockets);
|
||||
INIT_WORK(&othercon->rwork, process_recv_sockets);
|
||||
init_waitqueue_head(&othercon->shutdown_wait);
|
||||
set_bit(CF_IS_OTHERCON, &othercon->flags);
|
||||
newcon->othercon = othercon;
|
||||
} else {
|
||||
/* close other sock con if we have something new */
|
||||
close_connection(othercon, false, true, false);
|
||||
}
|
||||
|
||||
mutex_lock_nested(&othercon->sock_mutex, 2);
|
||||
newcon->othercon = othercon;
|
||||
mutex_lock_nested(&othercon->sock_mutex, 1);
|
||||
add_sock(newsock, othercon);
|
||||
addcon = othercon;
|
||||
mutex_unlock(&othercon->sock_mutex);
|
||||
}
|
||||
else {
|
||||
newcon->rx_action = receive_from_sock;
|
||||
/* accept copies the sk after we've saved the callbacks, so we
|
||||
don't want to save them a second time or comm errors will
|
||||
result in calling sk_error_report recursively. */
|
||||
@ -889,12 +939,10 @@ static int accept_from_sock(struct connection *con)
|
||||
*/
|
||||
if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
|
||||
queue_work(recv_workqueue, &addcon->rwork);
|
||||
mutex_unlock(&con->sock_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
accept_err:
|
||||
mutex_unlock(&con->sock_mutex);
|
||||
if (newsock)
|
||||
sock_release(newsock);
|
||||
|
||||
@ -930,7 +978,7 @@ static void writequeue_entry_complete(struct writequeue_entry *e, int completed)
|
||||
/*
|
||||
* sctp_bind_addrs - bind a SCTP socket to all our addresses
|
||||
*/
|
||||
static int sctp_bind_addrs(struct connection *con, uint16_t port)
|
||||
static int sctp_bind_addrs(struct socket *sock, uint16_t port)
|
||||
{
|
||||
struct sockaddr_storage localaddr;
|
||||
struct sockaddr *addr = (struct sockaddr *)&localaddr;
|
||||
@ -941,9 +989,9 @@ static int sctp_bind_addrs(struct connection *con, uint16_t port)
|
||||
make_sockaddr(&localaddr, port, &addr_len);
|
||||
|
||||
if (!i)
|
||||
result = kernel_bind(con->sock, addr, addr_len);
|
||||
result = kernel_bind(sock, addr, addr_len);
|
||||
else
|
||||
result = sock_bind_add(con->sock->sk, addr, addr_len);
|
||||
result = sock_bind_add(sock->sk, addr, addr_len);
|
||||
|
||||
if (result < 0) {
|
||||
log_print("Can't bind to %d addr number %d, %d.\n",
|
||||
@ -967,11 +1015,6 @@ static void sctp_connect_to_sock(struct connection *con)
|
||||
struct socket *sock;
|
||||
unsigned int mark;
|
||||
|
||||
if (con->nodeid == 0) {
|
||||
log_print("attempt to connect sock 0 foiled");
|
||||
return;
|
||||
}
|
||||
|
||||
dlm_comm_mark(con->nodeid, &mark);
|
||||
|
||||
mutex_lock(&con->sock_mutex);
|
||||
@ -1000,12 +1043,10 @@ static void sctp_connect_to_sock(struct connection *con)
|
||||
|
||||
sock_set_mark(sock->sk, mark);
|
||||
|
||||
con->rx_action = receive_from_sock;
|
||||
con->connect_action = sctp_connect_to_sock;
|
||||
add_sock(sock, con);
|
||||
|
||||
/* Bind to all addresses. */
|
||||
if (sctp_bind_addrs(con, 0))
|
||||
if (sctp_bind_addrs(con->sock, 0))
|
||||
goto bind_err;
|
||||
|
||||
make_sockaddr(&daddr, dlm_config.ci_tcp_port, &addr_len);
|
||||
@ -1027,8 +1068,11 @@ static void sctp_connect_to_sock(struct connection *con)
|
||||
|
||||
if (result == -EINPROGRESS)
|
||||
result = 0;
|
||||
if (result == 0)
|
||||
if (result == 0) {
|
||||
if (!test_and_set_bit(CF_CONNECTED, &con->flags))
|
||||
log_print("successful connected to node %d", con->nodeid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bind_err:
|
||||
con->sock = NULL;
|
||||
@ -1065,11 +1109,6 @@ static void tcp_connect_to_sock(struct connection *con)
|
||||
unsigned int mark;
|
||||
int result;
|
||||
|
||||
if (con->nodeid == 0) {
|
||||
log_print("attempt to connect sock 0 foiled");
|
||||
return;
|
||||
}
|
||||
|
||||
dlm_comm_mark(con->nodeid, &mark);
|
||||
|
||||
mutex_lock(&con->sock_mutex);
|
||||
@ -1095,9 +1134,6 @@ static void tcp_connect_to_sock(struct connection *con)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
con->rx_action = receive_from_sock;
|
||||
con->connect_action = tcp_connect_to_sock;
|
||||
con->shutdown_action = dlm_tcp_shutdown;
|
||||
add_sock(sock, con);
|
||||
|
||||
/* Bind to our cluster-known address connecting to avoid
|
||||
@ -1153,8 +1189,11 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
static struct socket *tcp_create_listen_sock(struct connection *con,
|
||||
struct sockaddr_storage *saddr)
|
||||
/* On error caller must run dlm_close_sock() for the
|
||||
* listen connection socket.
|
||||
*/
|
||||
static int tcp_create_listen_sock(struct listen_connection *con,
|
||||
struct sockaddr_storage *saddr)
|
||||
{
|
||||
struct socket *sock = NULL;
|
||||
int result = 0;
|
||||
@ -1180,21 +1219,13 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
|
||||
|
||||
sock_set_reuseaddr(sock->sk);
|
||||
|
||||
write_lock_bh(&sock->sk->sk_callback_lock);
|
||||
sock->sk->sk_user_data = con;
|
||||
save_listen_callbacks(sock);
|
||||
con->rx_action = accept_from_sock;
|
||||
con->connect_action = tcp_connect_to_sock;
|
||||
write_unlock_bh(&sock->sk->sk_callback_lock);
|
||||
add_listen_sock(sock, con);
|
||||
|
||||
/* Bind to our port */
|
||||
make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
|
||||
result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
|
||||
if (result < 0) {
|
||||
log_print("Can't bind to port %d", dlm_config.ci_tcp_port);
|
||||
sock_release(sock);
|
||||
sock = NULL;
|
||||
con->sock = NULL;
|
||||
goto create_out;
|
||||
}
|
||||
sock_set_keepalive(sock->sk);
|
||||
@ -1202,13 +1233,13 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
|
||||
result = sock->ops->listen(sock, 5);
|
||||
if (result < 0) {
|
||||
log_print("Can't listen on port %d", dlm_config.ci_tcp_port);
|
||||
sock_release(sock);
|
||||
sock = NULL;
|
||||
goto create_out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
create_out:
|
||||
return sock;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Get local addresses */
|
||||
@ -1237,15 +1268,14 @@ static void deinit_local(void)
|
||||
kfree(dlm_local_addr[i]);
|
||||
}
|
||||
|
||||
/* Initialise SCTP socket and bind to all interfaces */
|
||||
static int sctp_listen_for_all(void)
|
||||
/* Initialise SCTP socket and bind to all interfaces
|
||||
* On error caller must run dlm_close_sock() for the
|
||||
* listen connection socket.
|
||||
*/
|
||||
static int sctp_listen_for_all(struct listen_connection *con)
|
||||
{
|
||||
struct socket *sock = NULL;
|
||||
int result = -EINVAL;
|
||||
struct connection *con = nodeid2con(0, GFP_NOFS);
|
||||
|
||||
if (!con)
|
||||
return -ENOMEM;
|
||||
|
||||
log_print("Using SCTP for communications");
|
||||
|
||||
@ -1260,47 +1290,29 @@ static int sctp_listen_for_all(void)
|
||||
sock_set_mark(sock->sk, dlm_config.ci_mark);
|
||||
sctp_sock_set_nodelay(sock->sk);
|
||||
|
||||
write_lock_bh(&sock->sk->sk_callback_lock);
|
||||
/* Init con struct */
|
||||
sock->sk->sk_user_data = con;
|
||||
save_listen_callbacks(sock);
|
||||
con->sock = sock;
|
||||
con->sock->sk->sk_data_ready = lowcomms_data_ready;
|
||||
con->rx_action = accept_from_sock;
|
||||
con->connect_action = sctp_connect_to_sock;
|
||||
|
||||
write_unlock_bh(&sock->sk->sk_callback_lock);
|
||||
add_listen_sock(sock, con);
|
||||
|
||||
/* Bind to all addresses. */
|
||||
if (sctp_bind_addrs(con, dlm_config.ci_tcp_port))
|
||||
goto create_delsock;
|
||||
result = sctp_bind_addrs(con->sock, dlm_config.ci_tcp_port);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
result = sock->ops->listen(sock, 5);
|
||||
if (result < 0) {
|
||||
log_print("Can't set socket listening");
|
||||
goto create_delsock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
create_delsock:
|
||||
sock_release(sock);
|
||||
con->sock = NULL;
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int tcp_listen_for_all(void)
|
||||
{
|
||||
struct socket *sock = NULL;
|
||||
struct connection *con = nodeid2con(0, GFP_NOFS);
|
||||
int result = -EINVAL;
|
||||
|
||||
if (!con)
|
||||
return -ENOMEM;
|
||||
|
||||
/* We don't support multi-homed hosts */
|
||||
if (dlm_local_addr[1] != NULL) {
|
||||
if (dlm_local_count > 1) {
|
||||
log_print("TCP protocol can't handle multi-homed hosts, "
|
||||
"try SCTP");
|
||||
return -EINVAL;
|
||||
@ -1308,16 +1320,7 @@ static int tcp_listen_for_all(void)
|
||||
|
||||
log_print("Using TCP for communications");
|
||||
|
||||
sock = tcp_create_listen_sock(con, dlm_local_addr[0]);
|
||||
if (sock) {
|
||||
add_sock(sock, con);
|
||||
result = 0;
|
||||
}
|
||||
else {
|
||||
result = -EADDRINUSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
return tcp_create_listen_sock(&listen_con, dlm_local_addr[0]);
|
||||
}
|
||||
|
||||
|
||||
@ -1352,6 +1355,12 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
|
||||
struct writequeue_entry *e;
|
||||
int offset = 0;
|
||||
|
||||
if (len > LOWCOMMS_MAX_TX_BUFFER_LEN) {
|
||||
BUILD_BUG_ON(PAGE_SIZE < LOWCOMMS_MAX_TX_BUFFER_LEN);
|
||||
log_print("failed to allocate a buffer of size %d", len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
con = nodeid2con(nodeid, allocation);
|
||||
if (!con)
|
||||
return NULL;
|
||||
@ -1506,6 +1515,8 @@ int dlm_lowcomms_close(int nodeid)
|
||||
set_bit(CF_CLOSE, &con->flags);
|
||||
close_connection(con, true, true, true);
|
||||
clean_one_writequeue(con);
|
||||
if (con->othercon)
|
||||
clean_one_writequeue(con->othercon);
|
||||
}
|
||||
|
||||
spin_lock(&dlm_node_addrs_spin);
|
||||
@ -1529,10 +1540,15 @@ static void process_recv_sockets(struct work_struct *work)
|
||||
|
||||
clear_bit(CF_READ_PENDING, &con->flags);
|
||||
do {
|
||||
err = con->rx_action(con);
|
||||
err = receive_from_sock(con);
|
||||
} while (!err);
|
||||
}
|
||||
|
||||
static void process_listen_recv_socket(struct work_struct *work)
|
||||
{
|
||||
accept_from_sock(&listen_con);
|
||||
}
|
||||
|
||||
/* Send workqueue function */
|
||||
static void process_send_sockets(struct work_struct *work)
|
||||
{
|
||||
@ -1616,10 +1632,11 @@ static void free_conn(struct connection *con)
|
||||
spin_unlock(&connections_lock);
|
||||
if (con->othercon) {
|
||||
clean_one_writequeue(con->othercon);
|
||||
call_rcu(&con->othercon->rcu, connection_release);
|
||||
call_srcu(&connections_srcu, &con->othercon->rcu,
|
||||
connection_release);
|
||||
}
|
||||
clean_one_writequeue(con);
|
||||
call_rcu(&con->rcu, connection_release);
|
||||
call_srcu(&connections_srcu, &con->rcu, connection_release);
|
||||
}
|
||||
|
||||
static void work_flush(void)
|
||||
@ -1665,6 +1682,8 @@ void dlm_lowcomms_stop(void)
|
||||
if (send_workqueue)
|
||||
flush_workqueue(send_workqueue);
|
||||
|
||||
dlm_close_sock(&listen_con.sock);
|
||||
|
||||
foreach_conn(shutdown_conn);
|
||||
work_flush();
|
||||
foreach_conn(free_conn);
|
||||
@ -1675,7 +1694,6 @@ void dlm_lowcomms_stop(void)
|
||||
int dlm_lowcomms_start(void)
|
||||
{
|
||||
int error = -EINVAL;
|
||||
struct connection *con;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONN_HASH_SIZE; i++)
|
||||
@ -1688,6 +1706,8 @@ int dlm_lowcomms_start(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
INIT_WORK(&listen_con.rwork, process_listen_recv_socket);
|
||||
|
||||
error = work_start();
|
||||
if (error)
|
||||
goto fail;
|
||||
@ -1698,7 +1718,7 @@ int dlm_lowcomms_start(void)
|
||||
if (dlm_config.ci_protocol == 0)
|
||||
error = tcp_listen_for_all();
|
||||
else
|
||||
error = sctp_listen_for_all();
|
||||
error = sctp_listen_for_all(&listen_con);
|
||||
if (error)
|
||||
goto fail_unlisten;
|
||||
|
||||
@ -1706,9 +1726,7 @@ int dlm_lowcomms_start(void)
|
||||
|
||||
fail_unlisten:
|
||||
dlm_allow_conn = 0;
|
||||
con = nodeid2con(0,0);
|
||||
if (con)
|
||||
free_conn(con);
|
||||
dlm_close_sock(&listen_con.sock);
|
||||
fail:
|
||||
return error;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#ifndef __LOWCOMMS_DOT_H__
|
||||
#define __LOWCOMMS_DOT_H__
|
||||
|
||||
#define LOWCOMMS_MAX_TX_BUFFER_LEN 4096
|
||||
|
||||
int dlm_lowcomms_start(void);
|
||||
void dlm_lowcomms_stop(void);
|
||||
void dlm_lowcomms_exit(void);
|
||||
|
@ -270,7 +270,7 @@ int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size,
|
||||
|
||||
log_slots(ls, gen, num, NULL, array, array_size);
|
||||
|
||||
max_slots = (dlm_config.ci_buffer_size - sizeof(struct dlm_rcom) -
|
||||
max_slots = (LOWCOMMS_MAX_TX_BUFFER_LEN - sizeof(struct dlm_rcom) -
|
||||
sizeof(struct rcom_config)) / sizeof(struct rcom_slot);
|
||||
|
||||
if (num > max_slots) {
|
||||
|
@ -162,7 +162,7 @@ retry:
|
||||
set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags);
|
||||
|
||||
allow_sync_reply(ls, &rc->rc_id);
|
||||
memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
|
||||
memset(ls->ls_recover_buf, 0, LOWCOMMS_MAX_TX_BUFFER_LEN);
|
||||
|
||||
send_rcom(ls, mh, rc);
|
||||
|
||||
@ -284,7 +284,7 @@ retry:
|
||||
memcpy(rc->rc_buf, last_name, last_len);
|
||||
|
||||
allow_sync_reply(ls, &rc->rc_id);
|
||||
memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
|
||||
memset(ls->ls_recover_buf, 0, LOWCOMMS_MAX_TX_BUFFER_LEN);
|
||||
|
||||
send_rcom(ls, mh, rc);
|
||||
|
||||
@ -304,7 +304,7 @@ static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in)
|
||||
|
||||
nodeid = rc_in->rc_header.h_nodeid;
|
||||
inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
|
||||
outlen = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom);
|
||||
outlen = LOWCOMMS_MAX_TX_BUFFER_LEN - sizeof(struct dlm_rcom);
|
||||
|
||||
error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh);
|
||||
if (error)
|
||||
|
Loading…
x
Reference in New Issue
Block a user