aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-07-03 03:25:35 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-03 18:27:10 -0400
commita5b5bb9a053a973c23b867738c074acb3e80c0a0 (patch)
tree8eb78d458cfb309c566d6aaafb25639723920bcd
parent0afffc723c8041a005134099847ac2a2fd0316a0 (diff)
[PATCH] lockdep: annotate sk_locks
Teach sk_lock semantics to the lock validator. In the softirq path the slock has mutex_trylock()+mutex_unlock() semantics, in the process context sock_lock() case it has mutex_lock()/mutex_unlock() semantics. Thus we treat sock_owned_by_user() flagged areas as an exclusion area too, not just those areas covered by a held sk_lock.slock. Effect on non-lockdep kernels: minimal, sk_lock_sock_init() has been turned into an inline function. Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/net/sock.h20
-rw-r--r--net/core/sock.c97
2 files changed, 98 insertions, 19 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 0969fb60d6ea..324b3ea233d6 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -44,6 +44,7 @@
44#include <linux/timer.h> 44#include <linux/timer.h>
45#include <linux/cache.h> 45#include <linux/cache.h>
46#include <linux/module.h> 46#include <linux/module.h>
47#include <linux/lockdep.h>
47#include <linux/netdevice.h> 48#include <linux/netdevice.h>
48#include <linux/skbuff.h> /* struct sk_buff */ 49#include <linux/skbuff.h> /* struct sk_buff */
49#include <linux/security.h> 50#include <linux/security.h>
@@ -78,18 +79,17 @@ typedef struct {
78 spinlock_t slock; 79 spinlock_t slock;
79 struct sock_iocb *owner; 80 struct sock_iocb *owner;
80 wait_queue_head_t wq; 81 wait_queue_head_t wq;
82 /*
83 * We express the mutex-alike socket_lock semantics
84 * to the lock validator by explicitly managing
85 * the slock as a lock variant (in addition to
86 * the slock itself):
87 */
88#ifdef CONFIG_DEBUG_LOCK_ALLOC
89 struct lockdep_map dep_map;
90#endif
81} socket_lock_t; 91} socket_lock_t;
82 92
83extern struct lock_class_key af_family_keys[AF_MAX];
84
85#define sock_lock_init(__sk) \
86do { spin_lock_init(&((__sk)->sk_lock.slock)); \
87 lockdep_set_class(&(__sk)->sk_lock.slock, \
88 af_family_keys + (__sk)->sk_family); \
89 (__sk)->sk_lock.owner = NULL; \
90 init_waitqueue_head(&((__sk)->sk_lock.wq)); \
91} while(0)
92
93struct sock; 93struct sock;
94struct proto; 94struct proto;
95 95
diff --git a/net/core/sock.c b/net/core/sock.c
index 0b4d5d25b23c..51fcfbc041a7 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -133,7 +133,42 @@
133 * Each address family might have different locking rules, so we have 133 * Each address family might have different locking rules, so we have
134 * one slock key per address family: 134 * one slock key per address family:
135 */ 135 */
136struct lock_class_key af_family_keys[AF_MAX]; 136static struct lock_class_key af_family_keys[AF_MAX];
137static struct lock_class_key af_family_slock_keys[AF_MAX];
138
139#ifdef CONFIG_DEBUG_LOCK_ALLOC
140/*
141 * Make lock validator output more readable. (we pre-construct these
142 * strings build-time, so that runtime initialization of socket
143 * locks is fast):
144 */
145static const char *af_family_key_strings[AF_MAX+1] = {
146 "sk_lock-AF_UNSPEC", "sk_lock-AF_UNIX" , "sk_lock-AF_INET" ,
147 "sk_lock-AF_AX25" , "sk_lock-AF_IPX" , "sk_lock-AF_APPLETALK",
148 "sk_lock-AF_NETROM", "sk_lock-AF_BRIDGE" , "sk_lock-AF_ATMPVC" ,
149 "sk_lock-AF_X25" , "sk_lock-AF_INET6" , "sk_lock-AF_ROSE" ,
150 "sk_lock-AF_DECnet", "sk_lock-AF_NETBEUI" , "sk_lock-AF_SECURITY" ,
151 "sk_lock-AF_KEY" , "sk_lock-AF_NETLINK" , "sk_lock-AF_PACKET" ,
152 "sk_lock-AF_ASH" , "sk_lock-AF_ECONET" , "sk_lock-AF_ATMSVC" ,
153 "sk_lock-21" , "sk_lock-AF_SNA" , "sk_lock-AF_IRDA" ,
154 "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" ,
155 "sk_lock-27" , "sk_lock-28" , "sk_lock-29" ,
156 "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-AF_MAX"
157};
158static const char *af_family_slock_key_strings[AF_MAX+1] = {
159 "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" ,
160 "slock-AF_AX25" , "slock-AF_IPX" , "slock-AF_APPLETALK",
161 "slock-AF_NETROM", "slock-AF_BRIDGE" , "slock-AF_ATMPVC" ,
162 "slock-AF_X25" , "slock-AF_INET6" , "slock-AF_ROSE" ,
163 "slock-AF_DECnet", "slock-AF_NETBEUI" , "slock-AF_SECURITY" ,
164 "slock-AF_KEY" , "slock-AF_NETLINK" , "slock-AF_PACKET" ,
165 "slock-AF_ASH" , "slock-AF_ECONET" , "slock-AF_ATMSVC" ,
166 "slock-21" , "slock-AF_SNA" , "slock-AF_IRDA" ,
167 "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" ,
168 "slock-27" , "slock-28" , "slock-29" ,
169 "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_MAX"
170};
171#endif
137 172
138/* 173/*
139 * sk_callback_lock locking rules are per-address-family, 174 * sk_callback_lock locking rules are per-address-family,
@@ -249,9 +284,16 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
249 skb->dev = NULL; 284 skb->dev = NULL;
250 285
251 bh_lock_sock(sk); 286 bh_lock_sock(sk);
252 if (!sock_owned_by_user(sk)) 287 if (!sock_owned_by_user(sk)) {
288 /*
289 * trylock + unlock semantics:
290 */
291 mutex_acquire(&sk->sk_lock.dep_map, 0, 1, _RET_IP_);
292
253 rc = sk->sk_backlog_rcv(sk, skb); 293 rc = sk->sk_backlog_rcv(sk, skb);
254 else 294
295 mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
296 } else
255 sk_add_backlog(sk, skb); 297 sk_add_backlog(sk, skb);
256 bh_unlock_sock(sk); 298 bh_unlock_sock(sk);
257out: 299out:
@@ -761,6 +803,33 @@ lenout:
761 return 0; 803 return 0;
762} 804}
763 805
806/*
807 * Initialize an sk_lock.
808 *
809 * (We also register the sk_lock with the lock validator.)
810 */
811static void inline sock_lock_init(struct sock *sk)
812{
813 spin_lock_init(&sk->sk_lock.slock);
814 sk->sk_lock.owner = NULL;
815 init_waitqueue_head(&sk->sk_lock.wq);
816 /*
817 * Make sure we are not reinitializing a held lock:
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);
831}
832
764/** 833/**
765 * sk_alloc - All socket objects are allocated here 834 * sk_alloc - All socket objects are allocated here
766 * @family: protocol family 835 * @family: protocol family
@@ -1465,24 +1534,34 @@ void sock_init_data(struct socket *sock, struct sock *sk)
1465void fastcall lock_sock(struct sock *sk) 1534void fastcall lock_sock(struct sock *sk)
1466{ 1535{
1467 might_sleep(); 1536 might_sleep();
1468 spin_lock_bh(&(sk->sk_lock.slock)); 1537 spin_lock_bh(&sk->sk_lock.slock);
1469 if (sk->sk_lock.owner) 1538 if (sk->sk_lock.owner)
1470 __lock_sock(sk); 1539 __lock_sock(sk);
1471 sk->sk_lock.owner = (void *)1; 1540 sk->sk_lock.owner = (void *)1;
1472 spin_unlock_bh(&(sk->sk_lock.slock)); 1541 spin_unlock(&sk->sk_lock.slock);
1542 /*
1543 * The sk_lock has mutex_lock() semantics here:
1544 */
1545 mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_);
1546 local_bh_enable();
1473} 1547}
1474 1548
1475EXPORT_SYMBOL(lock_sock); 1549EXPORT_SYMBOL(lock_sock);
1476 1550
1477void fastcall release_sock(struct sock *sk) 1551void fastcall release_sock(struct sock *sk)
1478{ 1552{
1479 spin_lock_bh(&(sk->sk_lock.slock)); 1553 /*
1554 * The sk_lock has mutex_unlock() semantics:
1555 */
1556 mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
1557
1558 spin_lock_bh(&sk->sk_lock.slock);
1480 if (sk->sk_backlog.tail) 1559 if (sk->sk_backlog.tail)
1481 __release_sock(sk); 1560 __release_sock(sk);
1482 sk->sk_lock.owner = NULL; 1561 sk->sk_lock.owner = NULL;
1483 if (waitqueue_active(&(sk->sk_lock.wq))) 1562 if (waitqueue_active(&sk->sk_lock.wq))
1484 wake_up(&(sk->sk_lock.wq)); 1563 wake_up(&sk->sk_lock.wq);
1485 spin_unlock_bh(&(sk->sk_lock.slock)); 1564 spin_unlock_bh(&sk->sk_lock.slock);
1486} 1565}
1487EXPORT_SYMBOL(release_sock); 1566EXPORT_SYMBOL(release_sock);
1488 1567