mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +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)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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));
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	spin_lock_init(&sk->sk_lock.slock);
 | 
			
		||||
	sk->sk_lock.owner = NULL;
 | 
			
		||||
	init_waitqueue_head(&sk->sk_lock.wq);
 | 
			
		||||
	/*
 | 
			
		||||
	 * Make sure we are not reinitializing a held lock:
 | 
			
		||||
	 */
 | 
			
		||||
	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,
 | 
			
		||||
	sock_lock_init_class_and_name(sk,
 | 
			
		||||
			af_family_slock_key_strings[sk->sk_family],
 | 
			
		||||
			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);
 | 
			
		||||
			af_family_keys + sk->sk_family);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,6 +85,35 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req);
 | 
			
		|||
 */
 | 
			
		||||
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.
 | 
			
		||||
 * 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)
 | 
			
		||||
		return error;
 | 
			
		||||
 | 
			
		||||
	svc_reclassify_socket(sock);
 | 
			
		||||
 | 
			
		||||
	if (type == SOCK_STREAM)
 | 
			
		||||
		sock->sk->sk_reuse = 1; /* allow address reuse */
 | 
			
		||||
	error = kernel_bind(sock, (struct sockaddr *) sin,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1058,6 +1058,35 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
 | 
			
		|||
	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
 | 
			
		||||
 * @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);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	xs_reclassify_socket(sock);
 | 
			
		||||
 | 
			
		||||
	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
 | 
			
		||||
		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);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		xs_reclassify_socket(sock);
 | 
			
		||||
 | 
			
		||||
		if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
 | 
			
		||||
			sock_release(sock);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue