forked from mirrors/linux
		
	[PATCH] lockdep: annotate nfs/nfsd in-kernel sockets
Stick NFS sockets in their own class to avoid some lockdep warnings. NFS sockets are never exposed to user-space, and will hence not trigger certain code paths that would otherwise pose deadlock scenarios. [akpm@osdl.org: cleanups] Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Steven Dickson <SteveD@redhat.com> Acked-by: Ingo Molnar <mingo@elte.hu> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Acked-by: Neil Brown <neilb@suse.de> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@osdl.org> [ Fixed patch corruption by quilt, pointed out by Peter Zijlstra ] Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
							parent
							
								
									b9d85b08c6
								
							
						
					
					
						commit
						ed07536ed6
					
				
					 5 changed files with 87 additions and 18 deletions
				
			
		|  | @ -746,6 +746,25 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size) | ||||||
|  */ |  */ | ||||||
| #define sock_owned_by_user(sk)	((sk)->sk_lock.owner) | #define sock_owned_by_user(sk)	((sk)->sk_lock.owner) | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Macro so as to not evaluate some arguments when | ||||||
|  |  * lockdep is not enabled. | ||||||
|  |  * | ||||||
|  |  * Mark both the sk_lock and the sk_lock.slock as a | ||||||
|  |  * per-address-family lock class. | ||||||
|  |  */ | ||||||
|  | #define sock_lock_init_class_and_name(sk, sname, skey, name, key) 	\ | ||||||
|  | do {									\ | ||||||
|  | 	sk->sk_lock.owner = NULL;					\ | ||||||
|  | 	init_waitqueue_head(&sk->sk_lock.wq);				\ | ||||||
|  | 	spin_lock_init(&(sk)->sk_lock.slock);				\ | ||||||
|  | 	debug_check_no_locks_freed((void *)&(sk)->sk_lock,		\ | ||||||
|  | 			sizeof((sk)->sk_lock));				\ | ||||||
|  | 	lockdep_set_class_and_name(&(sk)->sk_lock.slock,		\ | ||||||
|  | 		       	(skey), (sname));				\ | ||||||
|  | 	lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0);	\ | ||||||
|  | } while (0) | ||||||
|  | 
 | ||||||
| extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass)); | extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass)); | ||||||
| 
 | 
 | ||||||
| static inline void lock_sock(struct sock *sk) | static inline void lock_sock(struct sock *sk) | ||||||
|  |  | ||||||
|  | @ -2645,6 +2645,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) | ||||||
| 	} | 	} | ||||||
| 	local_irq_restore(flags); | 	local_irq_restore(flags); | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); | ||||||
| 
 | 
 | ||||||
| static void print_held_locks_bug(struct task_struct *curr) | static void print_held_locks_bug(struct task_struct *curr) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -810,24 +810,11 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | ||||||
|  */ |  */ | ||||||
| static void inline sock_lock_init(struct sock *sk) | static void inline sock_lock_init(struct sock *sk) | ||||||
| { | { | ||||||
| 	spin_lock_init(&sk->sk_lock.slock); | 	sock_lock_init_class_and_name(sk, | ||||||
| 	sk->sk_lock.owner = NULL; | 			af_family_slock_key_strings[sk->sk_family], | ||||||
| 	init_waitqueue_head(&sk->sk_lock.wq); | 			af_family_slock_keys + sk->sk_family, | ||||||
| 	/*
 | 			af_family_key_strings[sk->sk_family], | ||||||
| 	 * Make sure we are not reinitializing a held lock: | 			af_family_keys + sk->sk_family); | ||||||
| 	 */ |  | ||||||
| 	debug_check_no_locks_freed((void *)&sk->sk_lock, sizeof(sk->sk_lock)); |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * Mark both the sk_lock and the sk_lock.slock as a |  | ||||||
| 	 * per-address-family lock class: |  | ||||||
| 	 */ |  | ||||||
| 	lockdep_set_class_and_name(&sk->sk_lock.slock, |  | ||||||
| 				   af_family_slock_keys + sk->sk_family, |  | ||||||
| 				   af_family_slock_key_strings[sk->sk_family]); |  | ||||||
| 	lockdep_init_map(&sk->sk_lock.dep_map, |  | ||||||
| 			 af_family_key_strings[sk->sk_family], |  | ||||||
| 			 af_family_keys + sk->sk_family, 0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -85,6 +85,35 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req); | ||||||
|  */ |  */ | ||||||
| static int svc_conn_age_period = 6*60; | static int svc_conn_age_period = 6*60; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||||||
|  | static struct lock_class_key svc_key[2]; | ||||||
|  | static struct lock_class_key svc_slock_key[2]; | ||||||
|  | 
 | ||||||
|  | static inline void svc_reclassify_socket(struct socket *sock) | ||||||
|  | { | ||||||
|  | 	struct sock *sk = sock->sk; | ||||||
|  | 	BUG_ON(sk->sk_lock.owner != NULL); | ||||||
|  | 	switch (sk->sk_family) { | ||||||
|  | 	case AF_INET: | ||||||
|  | 		sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", | ||||||
|  | 		    &svc_slock_key[0], "sk_lock-AF_INET-NFSD", &svc_key[0]); | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case AF_INET6: | ||||||
|  | 		sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFSD", | ||||||
|  | 		    &svc_slock_key[1], "sk_lock-AF_INET6-NFSD", &svc_key[1]); | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		BUG(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | static inline void svc_reclassify_socket(struct socket *sock) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Queue up an idle server thread.  Must have pool->sp_lock held. |  * Queue up an idle server thread.  Must have pool->sp_lock held. | ||||||
|  * Note: this is really a stack rather than a queue, so that we only |  * Note: this is really a stack rather than a queue, so that we only | ||||||
|  | @ -1557,6 +1586,8 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin) | ||||||
| 	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0) | 	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0) | ||||||
| 		return error; | 		return error; | ||||||
| 
 | 
 | ||||||
|  | 	svc_reclassify_socket(sock); | ||||||
|  | 
 | ||||||
| 	if (type == SOCK_STREAM) | 	if (type == SOCK_STREAM) | ||||||
| 		sock->sk->sk_reuse = 1; /* allow address reuse */ | 		sock->sk->sk_reuse = 1; /* allow address reuse */ | ||||||
| 	error = kernel_bind(sock, (struct sockaddr *) sin, | 	error = kernel_bind(sock, (struct sockaddr *) sin, | ||||||
|  |  | ||||||
|  | @ -1058,6 +1058,35 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||||||
|  | static struct lock_class_key xs_key[2]; | ||||||
|  | static struct lock_class_key xs_slock_key[2]; | ||||||
|  | 
 | ||||||
|  | static inline void xs_reclassify_socket(struct socket *sock) | ||||||
|  | { | ||||||
|  | 	struct sock *sk = sock->sk; | ||||||
|  | 	BUG_ON(sk->sk_lock.owner != NULL); | ||||||
|  | 	switch (sk->sk_family) { | ||||||
|  | 	case AF_INET: | ||||||
|  | 		sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS", | ||||||
|  | 			&xs_slock_key[0], "sk_lock-AF_INET-NFS", &xs_key[0]); | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case AF_INET6: | ||||||
|  | 		sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFS", | ||||||
|  | 			&xs_slock_key[1], "sk_lock-AF_INET6-NFS", &xs_key[1]); | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		BUG(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | static inline void xs_reclassify_socket(struct socket *sock) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * xs_udp_connect_worker - set up a UDP socket |  * xs_udp_connect_worker - set up a UDP socket | ||||||
|  * @work: RPC transport to connect |  * @work: RPC transport to connect | ||||||
|  | @ -1081,6 +1110,7 @@ static void xs_udp_connect_worker(struct work_struct *work) | ||||||
| 		dprintk("RPC:      can't create UDP transport socket (%d).\n", -err); | 		dprintk("RPC:      can't create UDP transport socket (%d).\n", -err); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  | 	xs_reclassify_socket(sock); | ||||||
| 
 | 
 | ||||||
| 	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { | 	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { | ||||||
| 		sock_release(sock); | 		sock_release(sock); | ||||||
|  | @ -1165,6 +1195,7 @@ static void xs_tcp_connect_worker(struct work_struct *work) | ||||||
| 			dprintk("RPC:      can't create TCP transport socket (%d).\n", -err); | 			dprintk("RPC:      can't create TCP transport socket (%d).\n", -err); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | 		xs_reclassify_socket(sock); | ||||||
| 
 | 
 | ||||||
| 		if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { | 		if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { | ||||||
| 			sock_release(sock); | 			sock_release(sock); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Peter Zijlstra
						Peter Zijlstra