mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
fs: dlm: introduce generic listen
This patch combines each transport layer listen functionality into one listen function. Per transport layer differences are provided by additional callbacks in dlm_proto_ops. This patch drops silently sock_set_keepalive() for listen tcp sockets only. This socket option is not set at connecting sockets, I also don't see the sense of set keepalive for sockets which are created by accept() only. Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
This commit is contained in:
parent
a66c008cd1
commit
2dc6b1158c
@ -143,6 +143,13 @@ struct dlm_node_addr {
|
||||
};
|
||||
|
||||
struct dlm_proto_ops {
|
||||
const char *name;
|
||||
int proto;
|
||||
|
||||
int (*listen_validate)(void);
|
||||
void (*listen_sockopts)(struct socket *sock);
|
||||
int (*listen_bind)(struct socket *sock);
|
||||
|
||||
/* What to do to connect */
|
||||
void (*connect_action)(struct connection *con);
|
||||
/* What to do to shutdown */
|
||||
@ -1327,59 +1334,6 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int addr_len;
|
||||
|
||||
if (dlm_local_addr[0]->ss_family == AF_INET)
|
||||
addr_len = sizeof(struct sockaddr_in);
|
||||
else
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
|
||||
/* Create a socket to communicate with */
|
||||
result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
|
||||
SOCK_STREAM, IPPROTO_TCP, &sock);
|
||||
if (result < 0) {
|
||||
log_print("Can't create listening comms socket");
|
||||
goto create_out;
|
||||
}
|
||||
|
||||
sock_set_mark(sock->sk, dlm_config.ci_mark);
|
||||
|
||||
/* Turn off Nagle's algorithm */
|
||||
tcp_sock_set_nodelay(sock->sk);
|
||||
|
||||
sock_set_reuseaddr(sock->sk);
|
||||
|
||||
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);
|
||||
goto create_out;
|
||||
}
|
||||
sock_set_keepalive(sock->sk);
|
||||
|
||||
result = sock->ops->listen(sock, 5);
|
||||
if (result < 0) {
|
||||
log_print("Can't listen on port %d", dlm_config.ci_tcp_port);
|
||||
goto create_out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
create_out:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Get local addresses */
|
||||
static void init_local(void)
|
||||
{
|
||||
@ -1406,63 +1360,6 @@ static void deinit_local(void)
|
||||
kfree(dlm_local_addr[i]);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
log_print("Using SCTP for communications");
|
||||
|
||||
result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
|
||||
SOCK_STREAM, IPPROTO_SCTP, &sock);
|
||||
if (result < 0) {
|
||||
log_print("Can't create comms socket, check SCTP is loaded");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sock_set_rcvbuf(sock->sk, NEEDED_RMEM);
|
||||
sock_set_mark(sock->sk, dlm_config.ci_mark);
|
||||
sctp_sock_set_nodelay(sock->sk);
|
||||
|
||||
add_listen_sock(sock, con);
|
||||
|
||||
/* Bind to all addresses. */
|
||||
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 out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int tcp_listen_for_all(void)
|
||||
{
|
||||
/* We don't support multi-homed hosts */
|
||||
if (dlm_local_count > 1) {
|
||||
log_print("TCP protocol can't handle multi-homed hosts, "
|
||||
"try SCTP");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_print("Using TCP for communications");
|
||||
|
||||
return tcp_create_listen_sock(&listen_con, dlm_local_addr[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct writequeue_entry *new_writequeue_entry(struct connection *con,
|
||||
gfp_t allocation)
|
||||
{
|
||||
@ -1959,13 +1856,112 @@ void dlm_lowcomms_stop(void)
|
||||
dlm_proto_ops = NULL;
|
||||
}
|
||||
|
||||
static int dlm_listen_for_all(void)
|
||||
{
|
||||
struct socket *sock;
|
||||
int result;
|
||||
|
||||
log_print("Using %s for communications",
|
||||
dlm_proto_ops->name);
|
||||
|
||||
if (dlm_proto_ops->listen_validate) {
|
||||
result = dlm_proto_ops->listen_validate();
|
||||
if (result < 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
|
||||
SOCK_STREAM, dlm_proto_ops->proto, &sock);
|
||||
if (result < 0) {
|
||||
log_print("Can't create comms socket, check SCTP is loaded");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sock_set_mark(sock->sk, dlm_config.ci_mark);
|
||||
dlm_proto_ops->listen_sockopts(sock);
|
||||
|
||||
result = dlm_proto_ops->listen_bind(sock);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
save_listen_callbacks(sock);
|
||||
add_listen_sock(sock, &listen_con);
|
||||
|
||||
INIT_WORK(&listen_con.rwork, process_listen_recv_socket);
|
||||
result = sock->ops->listen(sock, 5);
|
||||
if (result < 0) {
|
||||
dlm_close_sock(&listen_con.sock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
sock_release(sock);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int dlm_tcp_listen_validate(void)
|
||||
{
|
||||
/* We don't support multi-homed hosts */
|
||||
if (dlm_local_count > 1) {
|
||||
log_print("TCP protocol can't handle multi-homed hosts, try SCTP");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dlm_tcp_sockopts(struct socket *sock)
|
||||
{
|
||||
/* Turn off Nagle's algorithm */
|
||||
tcp_sock_set_nodelay(sock->sk);
|
||||
}
|
||||
|
||||
static void dlm_tcp_listen_sockopts(struct socket *sock)
|
||||
{
|
||||
dlm_tcp_sockopts(sock);
|
||||
sock_set_reuseaddr(sock->sk);
|
||||
}
|
||||
|
||||
static int dlm_tcp_listen_bind(struct socket *sock)
|
||||
{
|
||||
int addr_len;
|
||||
|
||||
/* Bind to our port */
|
||||
make_sockaddr(dlm_local_addr[0], dlm_config.ci_tcp_port, &addr_len);
|
||||
return sock->ops->bind(sock, (struct sockaddr *)dlm_local_addr[0],
|
||||
addr_len);
|
||||
}
|
||||
|
||||
static const struct dlm_proto_ops dlm_tcp_ops = {
|
||||
.name = "TCP",
|
||||
.proto = IPPROTO_TCP,
|
||||
.listen_validate = dlm_tcp_listen_validate,
|
||||
.listen_sockopts = dlm_tcp_listen_sockopts,
|
||||
.listen_bind = dlm_tcp_listen_bind,
|
||||
.connect_action = tcp_connect_to_sock,
|
||||
.shutdown_action = dlm_tcp_shutdown,
|
||||
.eof_condition = tcp_eof_condition,
|
||||
};
|
||||
|
||||
static int dlm_sctp_bind_listen(struct socket *sock)
|
||||
{
|
||||
return sctp_bind_addrs(sock, dlm_config.ci_tcp_port);
|
||||
}
|
||||
|
||||
static void dlm_sctp_sockopts(struct socket *sock)
|
||||
{
|
||||
/* Turn off Nagle's algorithm */
|
||||
sctp_sock_set_nodelay(sock->sk);
|
||||
sock_set_rcvbuf(sock->sk, NEEDED_RMEM);
|
||||
}
|
||||
|
||||
static const struct dlm_proto_ops dlm_sctp_ops = {
|
||||
.name = "SCTP",
|
||||
.proto = IPPROTO_SCTP,
|
||||
.listen_sockopts = dlm_sctp_sockopts,
|
||||
.listen_bind = dlm_sctp_bind_listen,
|
||||
.connect_action = sctp_connect_to_sock,
|
||||
};
|
||||
|
||||
@ -1996,24 +1992,26 @@ int dlm_lowcomms_start(void)
|
||||
switch (dlm_config.ci_protocol) {
|
||||
case DLM_PROTO_TCP:
|
||||
dlm_proto_ops = &dlm_tcp_ops;
|
||||
error = tcp_listen_for_all();
|
||||
break;
|
||||
case DLM_PROTO_SCTP:
|
||||
dlm_proto_ops = &dlm_sctp_ops;
|
||||
error = sctp_listen_for_all(&listen_con);
|
||||
break;
|
||||
default:
|
||||
log_print("Invalid protocol identifier %d set",
|
||||
dlm_config.ci_protocol);
|
||||
error = -EINVAL;
|
||||
break;
|
||||
goto fail_proto_ops;
|
||||
}
|
||||
|
||||
error = dlm_listen_for_all();
|
||||
if (error)
|
||||
goto fail_unlisten;
|
||||
goto fail_listen;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unlisten:
|
||||
fail_listen:
|
||||
dlm_proto_ops = NULL;
|
||||
fail_proto_ops:
|
||||
dlm_allow_conn = 0;
|
||||
dlm_close_sock(&listen_con.sock);
|
||||
work_stop();
|
||||
|
Loading…
x
Reference in New Issue
Block a user