Skip to content

Commit

Permalink
[PATCH] lockdep: annotate nfs/nfsd in-kernel sockets
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Peter Zijlstra authored and Linus Torvalds committed Dec 7, 2006
1 parent b9d85b0 commit ed07536
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 18 deletions.
19 changes: 19 additions & 0 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions kernel/lockdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
23 changes: 5 additions & 18 deletions net/core/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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);
sock_lock_init_class_and_name(sk,
af_family_slock_key_strings[sk->sk_family],
af_family_slock_keys + sk->sk_family,
af_family_key_strings[sk->sk_family],
af_family_keys + sk->sk_family);
}

/**
Expand Down
31 changes: 31 additions & 0 deletions net/sunrpc/svcsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
31 changes: 31 additions & 0 deletions net/sunrpc/xprtsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ed07536

Please sign in to comment.