diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/pktgen.c | 42 | ||||
| -rw-r--r-- | net/irda/ircomm/ircomm_tty.c | 2 | ||||
| -rw-r--r-- | net/irda/ircomm/ircomm_tty_attach.c | 6 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_core.c | 4 | ||||
| -rw-r--r-- | net/sched/sch_choke.c | 2 | ||||
| -rw-r--r-- | net/sctp/associola.c | 16 | ||||
| -rw-r--r-- | net/sctp/protocol.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/Kconfig | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 75 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 3 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_mech.c | 6 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 4 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 119 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 4 | ||||
| -rw-r--r-- | net/sunrpc/cache.c | 1 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 43 | ||||
| -rw-r--r-- | net/sunrpc/xprt.c | 61 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 14 | 
18 files changed, 305 insertions, 101 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 6048fc1da1c..5c217427a66 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2198,7 +2198,7 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)  				pkt_dev->curfl = 0; /*reset */  		}  	} else { -		flow = random32() % pkt_dev->cflows; +		flow = prandom_u32() % pkt_dev->cflows;  		pkt_dev->curfl = flow;  		if (pkt_dev->flows[flow].count > pkt_dev->lflow) { @@ -2246,7 +2246,7 @@ static void set_cur_queue_map(struct pktgen_dev *pkt_dev)  	else if (pkt_dev->queue_map_min <= pkt_dev->queue_map_max) {  		__u16 t;  		if (pkt_dev->flags & F_QUEUE_MAP_RND) { -			t = random32() % +			t = prandom_u32() %  				(pkt_dev->queue_map_max -  				 pkt_dev->queue_map_min + 1)  				+ pkt_dev->queue_map_min; @@ -2278,7 +2278,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  		__u32 tmp;  		if (pkt_dev->flags & F_MACSRC_RND) -			mc = random32() % pkt_dev->src_mac_count; +			mc = prandom_u32() % pkt_dev->src_mac_count;  		else {  			mc = pkt_dev->cur_src_mac_offset++;  			if (pkt_dev->cur_src_mac_offset >= @@ -2304,7 +2304,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  		__u32 tmp;  		if (pkt_dev->flags & F_MACDST_RND) -			mc = random32() % pkt_dev->dst_mac_count; +			mc = prandom_u32() % pkt_dev->dst_mac_count;  		else {  			mc = pkt_dev->cur_dst_mac_offset++; @@ -2331,21 +2331,21 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  		for (i = 0; i < pkt_dev->nr_labels; i++)  			if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)  				pkt_dev->labels[i] = MPLS_STACK_BOTTOM | -					     ((__force __be32)random32() & +					     ((__force __be32)prandom_u32() &  						      htonl(0x000fffff));  	}  	if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) { -		pkt_dev->vlan_id = random32() & (4096-1); +		pkt_dev->vlan_id = prandom_u32() & (4096 - 1);  	}  	if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) { -		pkt_dev->svlan_id = random32() & (4096 - 1); +		pkt_dev->svlan_id = prandom_u32() & (4096 - 1);  	}  	if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {  		if (pkt_dev->flags & F_UDPSRC_RND) -			pkt_dev->cur_udp_src = random32() % +			pkt_dev->cur_udp_src = prandom_u32() %  				(pkt_dev->udp_src_max - pkt_dev->udp_src_min)  				+ pkt_dev->udp_src_min; @@ -2358,7 +2358,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  	if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {  		if (pkt_dev->flags & F_UDPDST_RND) { -			pkt_dev->cur_udp_dst = random32() % +			pkt_dev->cur_udp_dst = prandom_u32() %  				(pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)  				+ pkt_dev->udp_dst_min;  		} else { @@ -2375,7 +2375,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  		if (imn < imx) {  			__u32 t;  			if (pkt_dev->flags & F_IPSRC_RND) -				t = random32() % (imx - imn) + imn; +				t = prandom_u32() % (imx - imn) + imn;  			else {  				t = ntohl(pkt_dev->cur_saddr);  				t++; @@ -2396,17 +2396,15 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  				__be32 s;  				if (pkt_dev->flags & F_IPDST_RND) { -					t = random32() % (imx - imn) + imn; -					s = htonl(t); - -					while (ipv4_is_loopback(s) || -					       ipv4_is_multicast(s) || -					       ipv4_is_lbcast(s) || -					       ipv4_is_zeronet(s) || -					       ipv4_is_local_multicast(s)) { -						t = random32() % (imx - imn) + imn; +					do { +						t = prandom_u32() % +							(imx - imn) + imn;  						s = htonl(t); -					} +					} while (ipv4_is_loopback(s) || +						ipv4_is_multicast(s) || +						ipv4_is_lbcast(s) || +						ipv4_is_zeronet(s) || +						ipv4_is_local_multicast(s));  					pkt_dev->cur_daddr = s;  				} else {  					t = ntohl(pkt_dev->cur_daddr); @@ -2437,7 +2435,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  			for (i = 0; i < 4; i++) {  				pkt_dev->cur_in6_daddr.s6_addr32[i] = -				    (((__force __be32)random32() | +				    (((__force __be32)prandom_u32() |  				      pkt_dev->min_in6_daddr.s6_addr32[i]) &  				     pkt_dev->max_in6_daddr.s6_addr32[i]);  			} @@ -2447,7 +2445,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)  	if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {  		__u32 t;  		if (pkt_dev->flags & F_TXSIZE_RND) { -			t = random32() % +			t = prandom_u32() %  				(pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)  				+ pkt_dev->min_pkt_size;  		} else { diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 362ba47968e..41ac7938268 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -328,7 +328,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  	spin_unlock_irqrestore(&port->lock, flags);  	while (1) { -		if (tty->termios.c_cflag & CBAUD) +		if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))  			tty_port_raise_dtr_rts(port);  		set_current_state(TASK_INTERRUPTIBLE); diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c index edab393e0c8..a2a508f5f26 100644 --- a/net/irda/ircomm/ircomm_tty_attach.c +++ b/net/irda/ircomm/ircomm_tty_attach.c @@ -997,12 +997,8 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,  			self->settings.dce = IRCOMM_DELTA_CD;  			ircomm_tty_check_modem_status(self);  		} else { -			struct tty_struct *tty = tty_port_tty_get(&self->port);  			IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ ); -			if (tty) { -				tty_hangup(tty); -				tty_kref_put(tty); -			} +			tty_port_tty_hangup(&self->port, false);  		}  		break;  	default: diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ebb81d64436..0283baedcdf 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -266,7 +266,7 @@ static void death_by_event(unsigned long ul_conntrack)  	if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) {  		/* bad luck, let's retry again */  		ecache->timeout.expires = jiffies + -			(random32() % net->ct.sysctl_events_retry_timeout); +			(prandom_u32() % net->ct.sysctl_events_retry_timeout);  		add_timer(&ecache->timeout);  		return;  	} @@ -285,7 +285,7 @@ void nf_ct_dying_timeout(struct nf_conn *ct)  	/* set a new timer to retry event delivery */  	setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);  	ecache->timeout.expires = jiffies + -		(random32() % net->ct.sysctl_events_retry_timeout); +		(prandom_u32() % net->ct.sysctl_events_retry_timeout);  	add_timer(&ecache->timeout);  }  EXPORT_SYMBOL_GPL(nf_ct_dying_timeout); diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index cc37dd52ecf..ef53ab8d0aa 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -80,7 +80,7 @@ struct choke_sched_data {  /* deliver a random number between 0 and N - 1 */  static u32 random_N(unsigned int N)  { -	return reciprocal_divide(random32(), N); +	return reciprocal_divide(prandom_u32(), N);  }  /* number of elements in queue including holes */ diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 423549a714e..91cfd8f94a1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -66,13 +66,6 @@ static void sctp_assoc_bh_rcv(struct work_struct *work);  static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);  static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc); -/* Keep track of the new idr low so that we don't re-use association id - * numbers too fast.  It is protected by they idr spin lock is in the - * range of 1 - INT_MAX. - */ -static u32 idr_low = 1; - -  /* 1st Level Abstractions. */  /* Initialize a new association from provided memory. */ @@ -1597,13 +1590,8 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)  	if (preload)  		idr_preload(gfp);  	spin_lock_bh(&sctp_assocs_id_lock); -	/* 0 is not a valid id, idr_low is always >= 1 */ -	ret = idr_alloc(&sctp_assocs_id, asoc, idr_low, 0, GFP_NOWAIT); -	if (ret >= 0) { -		idr_low = ret + 1; -		if (idr_low == INT_MAX) -			idr_low = 1; -	} +	/* 0 is not a valid assoc_id, must be >= 1 */ +	ret = idr_alloc_cyclic(&sctp_assocs_id, asoc, 1, 0, GFP_NOWAIT);  	spin_unlock_bh(&sctp_assocs_id_lock);  	if (preload)  		idr_preload_end(); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1c2e46cb919..eaee00c6113 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1403,7 +1403,7 @@ SCTP_STATIC __init int sctp_init(void)  	/* Allocate and initialize the endpoint hash table.  */  	sctp_ep_hashsize = 64; -	sctp_ep_hashtable = (struct sctp_hashbucket *) +	sctp_ep_hashtable =  		kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);  	if (!sctp_ep_hashtable) {  		pr_err("Failed endpoint_hash alloc\n"); diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 516fe2caac2..241b54f3020 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -3,6 +3,7 @@ config SUNRPC  config SUNRPC_GSS  	tristate +	select OID_REGISTRY  config SUNRPC_BACKCHANNEL  	bool @@ -24,7 +25,6 @@ config SUNRPC_XPRT_RDMA  config SUNRPC_SWAP  	bool  	depends on SUNRPC -	select NETVM  config RPCSEC_GSS_KRB5  	tristate "Secure RPC: Kerberos V mechanism" diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index f5294047df7..ed2fdd210c0 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -82,7 +82,7 @@ MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");  static u32  pseudoflavor_to_flavor(u32 flavor) { -	if (flavor >= RPC_AUTH_MAXFLAVOR) +	if (flavor > RPC_AUTH_MAXFLAVOR)  		return RPC_AUTH_GSS;  	return flavor;  } @@ -124,6 +124,79 @@ rpcauth_unregister(const struct rpc_authops *ops)  EXPORT_SYMBOL_GPL(rpcauth_unregister);  /** + * rpcauth_get_pseudoflavor - check if security flavor is supported + * @flavor: a security flavor + * @info: a GSS mech OID, quality of protection, and service value + * + * Verifies that an appropriate kernel module is available or already loaded. + * Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is + * not supported locally. + */ +rpc_authflavor_t +rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info) +{ +	const struct rpc_authops *ops; +	rpc_authflavor_t pseudoflavor; + +	ops = auth_flavors[flavor]; +	if (ops == NULL) +		request_module("rpc-auth-%u", flavor); +	spin_lock(&rpc_authflavor_lock); +	ops = auth_flavors[flavor]; +	if (ops == NULL || !try_module_get(ops->owner)) { +		spin_unlock(&rpc_authflavor_lock); +		return RPC_AUTH_MAXFLAVOR; +	} +	spin_unlock(&rpc_authflavor_lock); + +	pseudoflavor = flavor; +	if (ops->info2flavor != NULL) +		pseudoflavor = ops->info2flavor(info); + +	module_put(ops->owner); +	return pseudoflavor; +} +EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor); + +/** + * rpcauth_get_gssinfo - find GSS tuple matching a GSS pseudoflavor + * @pseudoflavor: GSS pseudoflavor to match + * @info: rpcsec_gss_info structure to fill in + * + * Returns zero and fills in "info" if pseudoflavor matches a + * supported mechanism. + */ +int +rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info) +{ +	rpc_authflavor_t flavor = pseudoflavor_to_flavor(pseudoflavor); +	const struct rpc_authops *ops; +	int result; + +	if (flavor >= RPC_AUTH_MAXFLAVOR) +		return -EINVAL; + +	ops = auth_flavors[flavor]; +	if (ops == NULL) +		request_module("rpc-auth-%u", flavor); +	spin_lock(&rpc_authflavor_lock); +	ops = auth_flavors[flavor]; +	if (ops == NULL || !try_module_get(ops->owner)) { +		spin_unlock(&rpc_authflavor_lock); +		return -ENOENT; +	} +	spin_unlock(&rpc_authflavor_lock); + +	result = -ENOENT; +	if (ops->flavor2info != NULL) +		result = ops->flavor2info(pseudoflavor, info); + +	module_put(ops->owner); +	return result; +} +EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo); + +/**   * rpcauth_list_flavors - discover registered flavors and pseudoflavors   * @array: array to fill in   * @size: size of "array" diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 5257d2982ba..51415b07174 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1641,6 +1641,8 @@ static const struct rpc_authops authgss_ops = {  	.pipes_create	= gss_pipes_dentries_create,  	.pipes_destroy	= gss_pipes_dentries_destroy,  	.list_pseudoflavors = gss_mech_list_pseudoflavors, +	.info2flavor	= gss_mech_info2flavor, +	.flavor2info	= gss_mech_flavor2info,  };  static const struct rpc_credops gss_credops = { @@ -1733,6 +1735,7 @@ static void __exit exit_rpcsec_gss(void)  	rcu_barrier(); /* Wait for completion of call_rcu()'s */  } +MODULE_ALIAS("rpc-auth-6");  MODULE_LICENSE("GPL");  module_param_named(expired_cred_retry_delay,  		   gss_expired_cred_retry_delay, diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index d3611f11a8d..33255ff889c 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -729,16 +729,19 @@ static const struct gss_api_ops gss_kerberos_ops = {  static struct pf_desc gss_kerberos_pfs[] = {  	[0] = {  		.pseudoflavor = RPC_AUTH_GSS_KRB5, +		.qop = GSS_C_QOP_DEFAULT,  		.service = RPC_GSS_SVC_NONE,  		.name = "krb5",  	},  	[1] = {  		.pseudoflavor = RPC_AUTH_GSS_KRB5I, +		.qop = GSS_C_QOP_DEFAULT,  		.service = RPC_GSS_SVC_INTEGRITY,  		.name = "krb5i",  	},  	[2] = {  		.pseudoflavor = RPC_AUTH_GSS_KRB5P, +		.qop = GSS_C_QOP_DEFAULT,  		.service = RPC_GSS_SVC_PRIVACY,  		.name = "krb5p",  	}, @@ -750,11 +753,12 @@ MODULE_ALIAS("rpc-auth-gss-krb5p");  MODULE_ALIAS("rpc-auth-gss-390003");  MODULE_ALIAS("rpc-auth-gss-390004");  MODULE_ALIAS("rpc-auth-gss-390005"); +MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");  static struct gss_api_mech gss_kerberos_mech = {  	.gm_name	= "krb5",  	.gm_owner	= THIS_MODULE, -	.gm_oid		= {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}, +	.gm_oid		= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },  	.gm_ops		= &gss_kerberos_ops,  	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),  	.gm_pfs		= gss_kerberos_pfs, diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 88edec929d7..1da52d1406f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -130,8 +130,8 @@ gss_krb5_make_confounder(char *p, u32 conflen)  	/* initialize to random value */  	if (i == 0) { -		i = random32(); -		i = (i << 32) | random32(); +		i = prandom_u32(); +		i = (i << 32) | prandom_u32();  	}  	switch (conflen) { diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index f0f4eee63a3..79881d6e68a 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -36,6 +36,7 @@  #include <linux/types.h>  #include <linux/slab.h>  #include <linux/module.h> +#include <linux/oid_registry.h>  #include <linux/sunrpc/msg_prot.h>  #include <linux/sunrpc/gss_asn1.h>  #include <linux/sunrpc/auth_gss.h> @@ -102,8 +103,13 @@ out:  	return status;  } -int -gss_mech_register(struct gss_api_mech *gm) +/** + * gss_mech_register - register a GSS mechanism + * @gm: GSS mechanism handle + * + * Returns zero if successful, or a negative errno. + */ +int gss_mech_register(struct gss_api_mech *gm)  {  	int status; @@ -116,11 +122,14 @@ gss_mech_register(struct gss_api_mech *gm)  	dprintk("RPC:       registered gss mechanism %s\n", gm->gm_name);  	return 0;  } -  EXPORT_SYMBOL_GPL(gss_mech_register); -void -gss_mech_unregister(struct gss_api_mech *gm) +/** + * gss_mech_unregister - release a GSS mechanism + * @gm: GSS mechanism handle + * + */ +void gss_mech_unregister(struct gss_api_mech *gm)  {  	spin_lock(®istered_mechs_lock);  	list_del(&gm->gm_list); @@ -128,18 +137,14 @@ gss_mech_unregister(struct gss_api_mech *gm)  	dprintk("RPC:       unregistered gss mechanism %s\n", gm->gm_name);  	gss_mech_free(gm);  } -  EXPORT_SYMBOL_GPL(gss_mech_unregister); -struct gss_api_mech * -gss_mech_get(struct gss_api_mech *gm) +static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm)  {  	__module_get(gm->gm_owner);  	return gm;  } -EXPORT_SYMBOL_GPL(gss_mech_get); -  static struct gss_api_mech *  _gss_mech_get_by_name(const char *name)  { @@ -169,12 +174,16 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)  	}  	return gm;  } -EXPORT_SYMBOL_GPL(gss_mech_get_by_name); -struct gss_api_mech * -gss_mech_get_by_OID(struct xdr_netobj *obj) +static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)  {  	struct gss_api_mech	*pos, *gm = NULL; +	char buf[32]; + +	if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0) +		return NULL; +	dprintk("RPC:       %s(%s)\n", __func__, buf); +	request_module("rpc-auth-gss-%s", buf);  	spin_lock(®istered_mechs_lock);  	list_for_each_entry(pos, ®istered_mechs, gm_list) { @@ -188,11 +197,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj)  	}  	spin_unlock(®istered_mechs_lock);  	return gm; -  } -EXPORT_SYMBOL_GPL(gss_mech_get_by_OID); -  static inline int  mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)  { @@ -237,8 +243,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)  	return gm;  } -EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); -  /**   * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors   * @array: array to fill in @@ -268,19 +272,82 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size)  	return i;  } -u32 -gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) +/** + * gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor + * @gm: GSS mechanism handle + * @qop: GSS quality-of-protection value + * @service: GSS service value + * + * Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found. + */ +rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop, +					 u32 service)  {  	int i;  	for (i = 0; i < gm->gm_pf_num; i++) { -		if (gm->gm_pfs[i].service == service) { +		if (gm->gm_pfs[i].qop == qop && +		    gm->gm_pfs[i].service == service) {  			return gm->gm_pfs[i].pseudoflavor;  		}  	} -	return RPC_AUTH_MAXFLAVOR; /* illegal value */ +	return RPC_AUTH_MAXFLAVOR; +} + +/** + * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple + * @info: a GSS mech OID, quality of protection, and service value + * + * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is + * not supported. + */ +rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info) +{ +	rpc_authflavor_t pseudoflavor; +	struct gss_api_mech *gm; + +	gm = gss_mech_get_by_OID(&info->oid); +	if (gm == NULL) +		return RPC_AUTH_MAXFLAVOR; + +	pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service); + +	gss_mech_put(gm); +	return pseudoflavor; +} + +/** + * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor + * @pseudoflavor: GSS pseudoflavor to match + * @info: rpcsec_gss_info structure to fill in + * + * Returns zero and fills in "info" if pseudoflavor matches a + * supported mechanism.  Otherwise a negative errno is returned. + */ +int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor, +			 struct rpcsec_gss_info *info) +{ +	struct gss_api_mech *gm; +	int i; + +	gm = gss_mech_get_by_pseudoflavor(pseudoflavor); +	if (gm == NULL) +		return -ENOENT; + +	for (i = 0; i < gm->gm_pf_num; i++) { +		if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) { +			memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len); +			info->oid.len = gm->gm_oid.len; +			info->qop = gm->gm_pfs[i].qop; +			info->service = gm->gm_pfs[i].service; +			gss_mech_put(gm); +			return 0; +		} +	} + +	gss_mech_put(gm); +	return -ENOENT;  } -EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor);  u32  gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) @@ -294,8 +361,6 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)  	return 0;  } -EXPORT_SYMBOL_GPL(gss_pseudoflavor_to_service); -  char *  gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)  { @@ -308,8 +373,6 @@ gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)  	return NULL;  } -EXPORT_SYMBOL_GPL(gss_service_to_auth_domain_name); -  void  gss_mech_put(struct gss_api_mech * gm)  { @@ -317,8 +380,6 @@ gss_mech_put(struct gss_api_mech * gm)  		module_put(gm->gm_owner);  } -EXPORT_SYMBOL_GPL(gss_mech_put); -  /* The mech could probably be determined from the token instead, but it's just   * as easy for now to pass it in. */  int diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 5ead6055089..c3ba570222d 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1220,7 +1220,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)  		svcdata->rsci = rsci;  		cache_get(&rsci->h);  		rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( -					rsci->mechctx->mech_type, gc->gc_svc); +					rsci->mechctx->mech_type, +					GSS_C_QOP_DEFAULT, +					gc->gc_svc);  		ret = SVC_OK;  		goto out;  	} diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 25d58e76601..ce2d180d05a 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1208,7 +1208,6 @@ EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall);   * key and content are both parsed by cache   */ -#define isodigit(c) (isdigit(c) && c <= '7')  int qword_get(char **bpp, char *dest, int bufsize)  {  	/* return bytes copied, or -1 on error */ diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d5f35f15af9..d259fa96692 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -411,6 +411,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)  	};  	char servername[48]; +	if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS) +		xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;  	/*  	 * If the caller chooses not to specify a hostname, whip  	 * up a string representation of the passed-in address. @@ -1301,6 +1303,8 @@ call_reserve(struct rpc_task *task)  	xprt_reserve(task);  } +static void call_retry_reserve(struct rpc_task *task); +  /*   * 1b.	Grok the result of xprt_reserve()   */ @@ -1342,7 +1346,7 @@ call_reserveresult(struct rpc_task *task)  	case -ENOMEM:  		rpc_delay(task, HZ >> 2);  	case -EAGAIN:	/* woken up; retry */ -		task->tk_action = call_reserve; +		task->tk_action = call_retry_reserve;  		return;  	case -EIO:	/* probably a shutdown */  		break; @@ -1355,6 +1359,19 @@ call_reserveresult(struct rpc_task *task)  }  /* + * 1c.	Retry reserving an RPC call slot + */ +static void +call_retry_reserve(struct rpc_task *task) +{ +	dprint_status(task); + +	task->tk_status  = 0; +	task->tk_action  = call_reserveresult; +	xprt_retry_reserve(task); +} + +/*   * 2.	Bind and/or refresh the credentials   */  static void @@ -1639,22 +1656,26 @@ call_connect_status(struct rpc_task *task)  	dprint_status(task); -	task->tk_status = 0; -	if (status >= 0 || status == -EAGAIN) { -		clnt->cl_stats->netreconn++; -		task->tk_action = call_transmit; -		return; -	} -  	trace_rpc_connect_status(task, status);  	switch (status) {  		/* if soft mounted, test if we've timed out */  	case -ETIMEDOUT:  		task->tk_action = call_timeout; -		break; -	default: -		rpc_exit(task, -EIO); +		return; +	case -ECONNREFUSED: +	case -ECONNRESET: +	case -ENETUNREACH: +		if (RPC_IS_SOFTCONN(task)) +			break; +		/* retry with existing socket, after a delay */ +	case 0: +	case -EAGAIN: +		task->tk_status = 0; +		clnt->cl_stats->netreconn++; +		task->tk_action = call_transmit; +		return;  	} +	rpc_exit(task, status);  }  /* diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index b7478d5e7ff..745fca3cfd3 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -948,6 +948,34 @@ void xprt_transmit(struct rpc_task *task)  	spin_unlock_bh(&xprt->transport_lock);  } +static void xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task) +{ +	set_bit(XPRT_CONGESTED, &xprt->state); +	rpc_sleep_on(&xprt->backlog, task, NULL); +} + +static void xprt_wake_up_backlog(struct rpc_xprt *xprt) +{ +	if (rpc_wake_up_next(&xprt->backlog) == NULL) +		clear_bit(XPRT_CONGESTED, &xprt->state); +} + +static bool xprt_throttle_congested(struct rpc_xprt *xprt, struct rpc_task *task) +{ +	bool ret = false; + +	if (!test_bit(XPRT_CONGESTED, &xprt->state)) +		goto out; +	spin_lock(&xprt->reserve_lock); +	if (test_bit(XPRT_CONGESTED, &xprt->state)) { +		rpc_sleep_on(&xprt->backlog, task, NULL); +		ret = true; +	} +	spin_unlock(&xprt->reserve_lock); +out: +	return ret; +} +  static struct rpc_rqst *xprt_dynamic_alloc_slot(struct rpc_xprt *xprt, gfp_t gfp_flags)  {  	struct rpc_rqst *req = ERR_PTR(-EAGAIN); @@ -992,7 +1020,7 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)  		task->tk_status = -ENOMEM;  		break;  	case -EAGAIN: -		rpc_sleep_on(&xprt->backlog, task, NULL); +		xprt_add_backlog(xprt, task);  		dprintk("RPC:       waiting for request slot\n");  	default:  		task->tk_status = -EAGAIN; @@ -1028,7 +1056,7 @@ static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)  		memset(req, 0, sizeof(*req));	/* mark unused */  		list_add(&req->rq_list, &xprt->free);  	} -	rpc_wake_up_next(&xprt->backlog); +	xprt_wake_up_backlog(xprt);  	spin_unlock(&xprt->reserve_lock);  } @@ -1092,7 +1120,8 @@ EXPORT_SYMBOL_GPL(xprt_free);   * xprt_reserve - allocate an RPC request slot   * @task: RPC task requesting a slot allocation   * - * If no more slots are available, place the task on the transport's + * If the transport is marked as being congested, or if no more + * slots are available, place the task on the transport's   * backlog queue.   */  void xprt_reserve(struct rpc_task *task) @@ -1107,6 +1136,32 @@ void xprt_reserve(struct rpc_task *task)  	task->tk_status = -EAGAIN;  	rcu_read_lock();  	xprt = rcu_dereference(task->tk_client->cl_xprt); +	if (!xprt_throttle_congested(xprt, task)) +		xprt->ops->alloc_slot(xprt, task); +	rcu_read_unlock(); +} + +/** + * xprt_retry_reserve - allocate an RPC request slot + * @task: RPC task requesting a slot allocation + * + * If no more slots are available, place the task on the transport's + * backlog queue. + * Note that the only difference with xprt_reserve is that we now + * ignore the value of the XPRT_CONGESTED flag. + */ +void xprt_retry_reserve(struct rpc_task *task) +{ +	struct rpc_xprt	*xprt; + +	task->tk_status = 0; +	if (task->tk_rqstp != NULL) +		return; + +	task->tk_timeout = 0; +	task->tk_status = -EAGAIN; +	rcu_read_lock(); +	xprt = rcu_dereference(task->tk_client->cl_xprt);  	xprt->ops->alloc_slot(xprt, task);  	rcu_read_unlock();  } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 3d02130828d..9c2825827de 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2207,10 +2207,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)  		 */  		xs_tcp_force_close(xprt);  		break; -	case -ECONNREFUSED: -	case -ECONNRESET: -	case -ENETUNREACH: -		/* retry with existing socket, after a delay */  	case 0:  	case -EINPROGRESS:  	case -EALREADY: @@ -2221,6 +2217,10 @@ static void xs_tcp_setup_socket(struct work_struct *work)  		/* Happens, for instance, if the user specified a link  		 * local IPv6 address without a scope-id.  		 */ +	case -ECONNREFUSED: +	case -ECONNRESET: +	case -ENETUNREACH: +		/* retry with existing socket, after a delay */  		goto out;  	}  out_eagain: @@ -2767,9 +2767,13 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)  	struct rpc_xprt *xprt;  	struct sock_xprt *transport;  	struct rpc_xprt *ret; +	unsigned int max_slot_table_size = xprt_max_tcp_slot_table_entries; + +	if (args->flags & XPRT_CREATE_INFINITE_SLOTS) +		max_slot_table_size = RPC_MAX_SLOT_TABLE_LIMIT;  	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries, -			xprt_max_tcp_slot_table_entries); +			max_slot_table_size);  	if (IS_ERR(xprt))  		return xprt;  	transport = container_of(xprt, struct sock_xprt, xprt);  |