On Wed, Feb 10, 2016 at 7:55 PM, Bob Peterson <rpete...@redhat.com> wrote:
> This patch adds write_lock_bh locking to several places in the code
> that save and restore the socket callbacks.
>
> Signed-off-by: Bob Peterson <rpete...@redhat.com>
> ---
>  fs/dlm/lowcomms.c | 35 ++++++++++++++++++++++++++---------
>  1 file changed, 26 insertions(+), 9 deletions(-)
>
> diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
> index ec5087a..4e82285 100644
> --- a/fs/dlm/lowcomms.c
> +++ b/fs/dlm/lowcomms.c
> @@ -467,10 +467,17 @@ int dlm_lowcomms_connect_node(int nodeid)
>
>  static void lowcomms_error_report(struct sock *sk)
>  {
> -       struct connection *con = sock2con(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 "

This doesn't apply cleanly to anymore, but is trivial to adapt.

> @@ -500,22 +507,29 @@ 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;
> +       sk->sk_data_ready = lowcomms_data_ready;
> +       sk->sk_write_space = lowcomms_write_space;
> +       sk->sk_state_change = lowcomms_state_change;
> +       sk->sk_user_data = con;
> +       sk->sk_allocation = GFP_NOFS;
> +       con->orig_error_report = sk->sk_error_report;
> +       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
> @@ -1274,6 +1288,7 @@ 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;
>         con->sock = sock;
> @@ -1281,6 +1296,8 @@ static int sctp_listen_for_all(void)
>         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;
> --
> 2.5.0
>

Reviewed-by: Andreas Gruenbacher <agrue...@redhat.com>

Reply via email to