diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2006-12-06 23:35:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:30 -0500 |
commit | ed07536ed6731775219c1df7fa26a7588753e693 (patch) | |
tree | c539d80fe50f28d4e294850bb33be810f46fd515 | |
parent | b9d85b08c689dbf54b9943a02f73cb54c2b0fccf (diff) |
[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>
-rw-r--r-- | include/net/sock.h | 19 | ||||
-rw-r--r-- | kernel/lockdep.c | 1 | ||||
-rw-r--r-- | net/core/sock.c | 23 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 31 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 31 |
5 files changed, 87 insertions, 18 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 730899ce516..03684e702d1 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -746,6 +746,25 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size) | |||
746 | */ | 746 | */ |
747 | #define sock_owned_by_user(sk) ((sk)->sk_lock.owner) | 747 | #define sock_owned_by_user(sk) ((sk)->sk_lock.owner) |
748 | 748 | ||
749 | /* | ||
750 | * Macro so as to not evaluate some arguments when | ||
751 | * lockdep is not enabled. | ||
752 | * | ||
753 | * Mark both the sk_lock and the sk_lock.slock as a | ||
754 | * per-address-family lock class. | ||
755 | */ | ||
756 | #define sock_lock_init_class_and_name(sk, sname, skey, name, key) \ | ||
757 | do { \ | ||
758 | sk->sk_lock.owner = NULL; \ | ||
759 | init_waitqueue_head(&sk->sk_lock.wq); \ | ||
760 | spin_lock_init(&(sk)->sk_lock.slock); \ | ||
761 | debug_check_no_locks_freed((void *)&(sk)->sk_lock, \ | ||
762 | sizeof((sk)->sk_lock)); \ | ||
763 | lockdep_set_class_and_name(&(sk)->sk_lock.slock, \ | ||
764 | (skey), (sname)); \ | ||
765 | lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ | ||
766 | } while (0) | ||
767 | |||
749 | extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass)); | 768 | extern void FASTCALL(lock_sock_nested(struct sock *sk, int subclass)); |
750 | 769 | ||
751 | static inline void lock_sock(struct sock *sk) | 770 | static inline void lock_sock(struct sock *sk) |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index c9fefdb1a7d..e33f6207f5b 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -2645,6 +2645,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) | |||
2645 | } | 2645 | } |
2646 | local_irq_restore(flags); | 2646 | local_irq_restore(flags); |
2647 | } | 2647 | } |
2648 | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); | ||
2648 | 2649 | ||
2649 | static void print_held_locks_bug(struct task_struct *curr) | 2650 | static void print_held_locks_bug(struct task_struct *curr) |
2650 | { | 2651 | { |
diff --git a/net/core/sock.c b/net/core/sock.c index 4a432da441e..0ed5b4f0bc4 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -810,24 +810,11 @@ lenout: | |||
810 | */ | 810 | */ |
811 | static void inline sock_lock_init(struct sock *sk) | 811 | static void inline sock_lock_init(struct sock *sk) |
812 | { | 812 | { |
813 | spin_lock_init(&sk->sk_lock.slock); | 813 | sock_lock_init_class_and_name(sk, |
814 | sk->sk_lock.owner = NULL; | 814 | af_family_slock_key_strings[sk->sk_family], |
815 | init_waitqueue_head(&sk->sk_lock.wq); | 815 | af_family_slock_keys + sk->sk_family, |
816 | /* | 816 | af_family_key_strings[sk->sk_family], |
817 | * Make sure we are not reinitializing a held lock: | 817 | af_family_keys + sk->sk_family); |
818 | */ | ||
819 | debug_check_no_locks_freed((void *)&sk->sk_lock, sizeof(sk->sk_lock)); | ||
820 | |||
821 | /* | ||
822 | * Mark both the sk_lock and the sk_lock.slock as a | ||
823 | * per-address-family lock class: | ||
824 | */ | ||
825 | lockdep_set_class_and_name(&sk->sk_lock.slock, | ||
826 | af_family_slock_keys + sk->sk_family, | ||
827 | af_family_slock_key_strings[sk->sk_family]); | ||
828 | lockdep_init_map(&sk->sk_lock.dep_map, | ||
829 | af_family_key_strings[sk->sk_family], | ||
830 | af_family_keys + sk->sk_family, 0); | ||
831 | } | 818 | } |
832 | 819 | ||
833 | /** | 820 | /** |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 1c68956824e..99f54fb6d66 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -85,6 +85,35 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req); | |||
85 | */ | 85 | */ |
86 | static int svc_conn_age_period = 6*60; | 86 | static int svc_conn_age_period = 6*60; |
87 | 87 | ||
88 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
89 | static struct lock_class_key svc_key[2]; | ||
90 | static struct lock_class_key svc_slock_key[2]; | ||
91 | |||
92 | static inline void svc_reclassify_socket(struct socket *sock) | ||
93 | { | ||
94 | struct sock *sk = sock->sk; | ||
95 | BUG_ON(sk->sk_lock.owner != NULL); | ||
96 | switch (sk->sk_family) { | ||
97 | case AF_INET: | ||
98 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", | ||
99 | &svc_slock_key[0], "sk_lock-AF_INET-NFSD", &svc_key[0]); | ||
100 | break; | ||
101 | |||
102 | case AF_INET6: | ||
103 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFSD", | ||
104 | &svc_slock_key[1], "sk_lock-AF_INET6-NFSD", &svc_key[1]); | ||
105 | break; | ||
106 | |||
107 | default: | ||
108 | BUG(); | ||
109 | } | ||
110 | } | ||
111 | #else | ||
112 | static inline void svc_reclassify_socket(struct socket *sock) | ||
113 | { | ||
114 | } | ||
115 | #endif | ||
116 | |||
88 | /* | 117 | /* |
89 | * Queue up an idle server thread. Must have pool->sp_lock held. | 118 | * Queue up an idle server thread. Must have pool->sp_lock held. |
90 | * Note: this is really a stack rather than a queue, so that we only | 119 | * 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) | |||
1557 | if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0) | 1586 | if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0) |
1558 | return error; | 1587 | return error; |
1559 | 1588 | ||
1589 | svc_reclassify_socket(sock); | ||
1590 | |||
1560 | if (type == SOCK_STREAM) | 1591 | if (type == SOCK_STREAM) |
1561 | sock->sk->sk_reuse = 1; /* allow address reuse */ | 1592 | sock->sk->sk_reuse = 1; /* allow address reuse */ |
1562 | error = kernel_bind(sock, (struct sockaddr *) sin, | 1593 | error = kernel_bind(sock, (struct sockaddr *) sin, |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index cfe3c15be94..2fc4a312326 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1058,6 +1058,35 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) | |||
1058 | return err; | 1058 | return err; |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
1062 | static struct lock_class_key xs_key[2]; | ||
1063 | static struct lock_class_key xs_slock_key[2]; | ||
1064 | |||
1065 | static inline void xs_reclassify_socket(struct socket *sock) | ||
1066 | { | ||
1067 | struct sock *sk = sock->sk; | ||
1068 | BUG_ON(sk->sk_lock.owner != NULL); | ||
1069 | switch (sk->sk_family) { | ||
1070 | case AF_INET: | ||
1071 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS", | ||
1072 | &xs_slock_key[0], "sk_lock-AF_INET-NFS", &xs_key[0]); | ||
1073 | break; | ||
1074 | |||
1075 | case AF_INET6: | ||
1076 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFS", | ||
1077 | &xs_slock_key[1], "sk_lock-AF_INET6-NFS", &xs_key[1]); | ||
1078 | break; | ||
1079 | |||
1080 | default: | ||
1081 | BUG(); | ||
1082 | } | ||
1083 | } | ||
1084 | #else | ||
1085 | static inline void xs_reclassify_socket(struct socket *sock) | ||
1086 | { | ||
1087 | } | ||
1088 | #endif | ||
1089 | |||
1061 | /** | 1090 | /** |
1062 | * xs_udp_connect_worker - set up a UDP socket | 1091 | * xs_udp_connect_worker - set up a UDP socket |
1063 | * @work: RPC transport to connect | 1092 | * @work: RPC transport to connect |
@@ -1081,6 +1110,7 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1081 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1110 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
1082 | goto out; | 1111 | goto out; |
1083 | } | 1112 | } |
1113 | xs_reclassify_socket(sock); | ||
1084 | 1114 | ||
1085 | if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { | 1115 | if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { |
1086 | sock_release(sock); | 1116 | sock_release(sock); |
@@ -1165,6 +1195,7 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1165 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | 1195 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); |
1166 | goto out; | 1196 | goto out; |
1167 | } | 1197 | } |
1198 | xs_reclassify_socket(sock); | ||
1168 | 1199 | ||
1169 | if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { | 1200 | if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { |
1170 | sock_release(sock); | 1201 | sock_release(sock); |