mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[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