From: Bob Peterson <rpeterso@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [DLM PATCH] DLM: save / restore all socket callbacks
Date: Tue, 26 Jan 2016 12:57:41 -0500 (EST) [thread overview]
Message-ID: <1244929267.15846120.1453831061604.JavaMail.zimbra@redhat.com> (raw)
In-Reply-To: <2116520443.15845809.1453831014524.JavaMail.zimbra@redhat.com>
Hi,
Before this patch, DLM was saving off the original error report
callback before setting its own, but it never restored it. Instead,
we should be saving off all four socket callbacks before changing
them, and then restore them once we're done.
Regards,
Bob Peterson
Red Hat File Systems
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index dc9ae6d..f9eb366 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -124,7 +124,10 @@ struct connection {
struct connection *othercon;
struct work_struct rwork; /* Receive workqueue */
struct work_struct swork; /* Send workqueue */
- void (*orig_error_report)(struct sock *sk);
+ void (*orig_error_report)(struct sock *);
+ void (*orig_data_ready)(struct sock *);
+ void (*orig_state_change)(struct sock *);
+ void (*orig_write_space)(struct sock *);
};
#define sock2con(x) ((struct connection *)(x)->sk_user_data)
@@ -465,12 +468,43 @@ int dlm_lowcomms_connect_node(int nodeid)
return 0;
}
-static void lowcomms_error_report(struct sock *sk)
+static void save_old_callbacks(struct sock *sk)
+{
+ struct connection *con = sock2con(sk);
+
+ if (sk->sk_error_report) {
+ con->orig_data_ready = sk->sk_data_ready;
+ con->orig_state_change = sk->sk_state_change;
+ con->orig_write_space = sk->sk_write_space;
+ con->orig_error_report = sk->sk_error_report;
+ }
+}
+
+static void restore_old_callbacks(struct sock *sk)
{
struct connection *con = sock2con(sk);
+
+ if (con->orig_error_report) {
+ sk->sk_data_ready = con->orig_data_ready;
+ sk->sk_state_change = con->orig_state_change;
+ sk->sk_write_space = con->orig_write_space;
+ sk->sk_error_report = con->orig_error_report;
+ }
+}
+
+static void lowcomms_error_report(struct sock *sk)
+{
+ struct connection *con;
struct sockaddr_storage saddr;
int buflen;
+ void (*orig_report)(struct sock *) = NULL;
+
+ read_lock_bh(&sk->sk_callback_lock);
+ con = sock2con(sk);
+ if (con == NULL)
+ goto out;
+ orig_report = con->orig_error_report;
if (con->sock == NULL ||
kernel_getpeername(con->sock, (struct sockaddr *)&saddr, &buflen)) {
printk_ratelimited(KERN_ERR "dlm: node %d: socket error "
@@ -478,7 +512,6 @@ static void lowcomms_error_report(struct sock *sk)
"sk_err=%d/%d\n", dlm_our_nodeid(),
con->nodeid, dlm_config.ci_tcp_port,
sk->sk_err, sk->sk_err_soft);
- return;
} else if (saddr.ss_family == AF_INET) {
struct sockaddr_in *sin4 = (struct sockaddr_in *)&saddr;
@@ -501,22 +534,31 @@ static void lowcomms_error_report(struct sock *sk)
dlm_config.ci_tcp_port, sk->sk_err,
sk->sk_err_soft);
}
- con->orig_error_report(sk);
+out:
+ read_unlock_bh(&sk->sk_callback_lock);
+ if (orig_report)
+ orig_report(sk);
}
/* Make a socket active */
static void add_sock(struct socket *sock, struct connection *con)
{
+ struct sock *sk = sock->sk;
+
+ write_lock_bh(&sk->sk_callback_lock);
con->sock = sock;
- /* Install a data_ready callback */
- con->sock->sk->sk_data_ready = lowcomms_data_ready;
- con->sock->sk->sk_write_space = lowcomms_write_space;
- con->sock->sk->sk_state_change = lowcomms_state_change;
- con->sock->sk->sk_user_data = con;
- con->sock->sk->sk_allocation = GFP_NOFS;
- con->orig_error_report = con->sock->sk->sk_error_report;
- con->sock->sk->sk_error_report = lowcomms_error_report;
+ if (sk->sk_error_report != lowcomms_error_report) {
+ sk->sk_user_data = con;
+ save_old_callbacks(sk);
+ /* Install a data_ready callback */
+ sk->sk_data_ready = lowcomms_data_ready;
+ sk->sk_write_space = lowcomms_write_space;
+ sk->sk_state_change = lowcomms_state_change;
+ sk->sk_allocation = GFP_NOFS;
+ sk->sk_error_report = lowcomms_error_report;
+ }
+ write_unlock_bh(&sk->sk_callback_lock);
}
/* Add the port number to an IPv6 or 4 sockaddr and return the address
@@ -551,6 +593,13 @@ static void close_connection(struct connection *con, bool and_other,
mutex_lock(&con->sock_mutex);
if (con->sock) {
+ struct sock *sk = con->sock->sk;
+
+ if (sk) {
+ write_lock_bh(&sk->sk_callback_lock);
+ restore_old_callbacks(sk);
+ write_unlock_bh(&sk->sk_callback_lock);
+ }
sock_release(con->sock);
con->sock = NULL;
}
@@ -1131,6 +1180,10 @@ static void tcp_connect_to_sock(struct connection *con)
if (result == 0)
goto out;
+ write_lock_bh(&sock->sk->sk_callback_lock);
+ restore_old_callbacks(sock->sk);
+ write_unlock_bh(&sock->sk->sk_callback_lock);
+
out_err:
if (con->sock) {
sock_release(con->sock);
@@ -1273,13 +1326,19 @@ static int sctp_listen_for_all(void)
if (result < 0)
log_print("Could not set SCTP NODELAY error %d\n", result);
+ write_lock_bh(&sock->sk->sk_callback_lock);
/* Init con struct */
sock->sk->sk_user_data = con;
+
+ save_old_callbacks(sock->sk);
+
con->sock = sock;
con->sock->sk->sk_data_ready = lowcomms_data_ready;
con->rx_action = sctp_accept_from_sock;
con->connect_action = sctp_connect_to_sock;
+ write_unlock_bh(&sock->sk->sk_callback_lock);
+
/* Bind to all addresses. */
if (sctp_bind_addrs(con, dlm_config.ci_tcp_port))
goto create_delsock;
@@ -1293,6 +1352,9 @@ static int sctp_listen_for_all(void)
return 0;
create_delsock:
+ write_lock_bh(&sock->sk->sk_callback_lock);
+ restore_old_callbacks(sock->sk);
+ write_unlock_bh(&sock->sk->sk_callback_lock);
sock_release(sock);
con->sock = NULL;
out:
next parent reply other threads:[~2016-01-26 17:57 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <2116520443.15845809.1453831014524.JavaMail.zimbra@redhat.com>
2016-01-26 17:57 ` Bob Peterson [this message]
2016-01-26 20:04 ` [Cluster-devel] [DLM PATCH] DLM: save / restore all socket callbacks Steven Whitehouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1244929267.15846120.1453831061604.JavaMail.zimbra@redhat.com \
--to=rpeterso@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.