mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 07:00:48 +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 {
|
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 */
|
/* What to do to connect */
|
||||||
void (*connect_action)(struct connection *con);
|
void (*connect_action)(struct connection *con);
|
||||||
/* What to do to shutdown */
|
/* What to do to shutdown */
|
||||||
@ -1327,59 +1334,6 @@ out:
|
|||||||
return;
|
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 */
|
/* Get local addresses */
|
||||||
static void init_local(void)
|
static void init_local(void)
|
||||||
{
|
{
|
||||||
@ -1406,63 +1360,6 @@ static void deinit_local(void)
|
|||||||
kfree(dlm_local_addr[i]);
|
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,
|
static struct writequeue_entry *new_writequeue_entry(struct connection *con,
|
||||||
gfp_t allocation)
|
gfp_t allocation)
|
||||||
{
|
{
|
||||||
@ -1959,13 +1856,112 @@ void dlm_lowcomms_stop(void)
|
|||||||
dlm_proto_ops = NULL;
|
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 = {
|
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,
|
.connect_action = tcp_connect_to_sock,
|
||||||
.shutdown_action = dlm_tcp_shutdown,
|
.shutdown_action = dlm_tcp_shutdown,
|
||||||
.eof_condition = tcp_eof_condition,
|
.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 = {
|
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,
|
.connect_action = sctp_connect_to_sock,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1996,24 +1992,26 @@ int dlm_lowcomms_start(void)
|
|||||||
switch (dlm_config.ci_protocol) {
|
switch (dlm_config.ci_protocol) {
|
||||||
case DLM_PROTO_TCP:
|
case DLM_PROTO_TCP:
|
||||||
dlm_proto_ops = &dlm_tcp_ops;
|
dlm_proto_ops = &dlm_tcp_ops;
|
||||||
error = tcp_listen_for_all();
|
|
||||||
break;
|
break;
|
||||||
case DLM_PROTO_SCTP:
|
case DLM_PROTO_SCTP:
|
||||||
dlm_proto_ops = &dlm_sctp_ops;
|
dlm_proto_ops = &dlm_sctp_ops;
|
||||||
error = sctp_listen_for_all(&listen_con);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_print("Invalid protocol identifier %d set",
|
log_print("Invalid protocol identifier %d set",
|
||||||
dlm_config.ci_protocol);
|
dlm_config.ci_protocol);
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
break;
|
goto fail_proto_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = dlm_listen_for_all();
|
||||||
if (error)
|
if (error)
|
||||||
goto fail_unlisten;
|
goto fail_listen;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_unlisten:
|
fail_listen:
|
||||||
|
dlm_proto_ops = NULL;
|
||||||
|
fail_proto_ops:
|
||||||
dlm_allow_conn = 0;
|
dlm_allow_conn = 0;
|
||||||
dlm_close_sock(&listen_con.sock);
|
dlm_close_sock(&listen_con.sock);
|
||||||
work_stop();
|
work_stop();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user