diff options
Diffstat (limited to 'net/ipv4/tcp_ulp.c')
| -rw-r--r-- | net/ipv4/tcp_ulp.c | 75 | 
1 files changed, 18 insertions, 57 deletions
| diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c index a5995bb2eaca..95df7f7f6328 100644 --- a/net/ipv4/tcp_ulp.c +++ b/net/ipv4/tcp_ulp.c @@ -6,7 +6,7 @@   *   */ -#include<linux/module.h> +#include <linux/module.h>  #include <linux/mm.h>  #include <linux/types.h>  #include <linux/list.h> @@ -29,18 +29,6 @@ static struct tcp_ulp_ops *tcp_ulp_find(const char *name)  	return NULL;  } -static struct tcp_ulp_ops *tcp_ulp_find_id(const int ulp) -{ -	struct tcp_ulp_ops *e; - -	list_for_each_entry_rcu(e, &tcp_ulp_list, list) { -		if (e->uid == ulp) -			return e; -	} - -	return NULL; -} -  static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)  {  	const struct tcp_ulp_ops *ulp = NULL; @@ -63,18 +51,6 @@ static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)  	return ulp;  } -static const struct tcp_ulp_ops *__tcp_ulp_lookup(const int uid) -{ -	const struct tcp_ulp_ops *ulp; - -	rcu_read_lock(); -	ulp = tcp_ulp_find_id(uid); -	if (!ulp || !try_module_get(ulp->owner)) -		ulp = NULL; -	rcu_read_unlock(); -	return ulp; -} -  /* Attach new upper layer protocol to the list   * of available protocols.   */ @@ -123,6 +99,10 @@ void tcp_cleanup_ulp(struct sock *sk)  {  	struct inet_connection_sock *icsk = inet_csk(sk); +	/* No sock_owned_by_me() check here as at the time the +	 * stack calls this function, the socket is dead and +	 * about to be destroyed. +	 */  	if (!icsk->icsk_ulp_ops)  		return; @@ -133,54 +113,35 @@ void tcp_cleanup_ulp(struct sock *sk)  	icsk->icsk_ulp_ops = NULL;  } -/* Change upper layer protocol for socket */ -int tcp_set_ulp(struct sock *sk, const char *name) +static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)  {  	struct inet_connection_sock *icsk = inet_csk(sk); -	const struct tcp_ulp_ops *ulp_ops; -	int err = 0; +	int err; +	err = -EEXIST;  	if (icsk->icsk_ulp_ops) -		return -EEXIST; - -	ulp_ops = __tcp_ulp_find_autoload(name); -	if (!ulp_ops) -		return -ENOENT; - -	if (!ulp_ops->user_visible) { -		module_put(ulp_ops->owner); -		return -ENOENT; -	} +		goto out_err;  	err = ulp_ops->init(sk); -	if (err) { -		module_put(ulp_ops->owner); -		return err; -	} +	if (err) +		goto out_err;  	icsk->icsk_ulp_ops = ulp_ops;  	return 0; +out_err: +	module_put(ulp_ops->owner); +	return err;  } -int tcp_set_ulp_id(struct sock *sk, int ulp) +int tcp_set_ulp(struct sock *sk, const char *name)  { -	struct inet_connection_sock *icsk = inet_csk(sk);  	const struct tcp_ulp_ops *ulp_ops; -	int err; -	if (icsk->icsk_ulp_ops) -		return -EEXIST; +	sock_owned_by_me(sk); -	ulp_ops = __tcp_ulp_lookup(ulp); +	ulp_ops = __tcp_ulp_find_autoload(name);  	if (!ulp_ops)  		return -ENOENT; -	err = ulp_ops->init(sk); -	if (err) { -		module_put(ulp_ops->owner); -		return err; -	} - -	icsk->icsk_ulp_ops = ulp_ops; -	return 0; +	return __tcp_set_ulp(sk, ulp_ops);  } | 
