Commit a5b5bb9a053a973c23b867738c074acb3e80c0a0
Committed by
Linus Torvalds
1 parent
0afffc723c
Exists in
master
and in
7 other branches
[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>
Showing 2 changed files with 98 additions and 19 deletions Side-by-side Diff
include/net/sock.h
... | ... | @@ -44,6 +44,7 @@ |
44 | 44 | #include <linux/timer.h> |
45 | 45 | #include <linux/cache.h> |
46 | 46 | #include <linux/module.h> |
47 | +#include <linux/lockdep.h> | |
47 | 48 | #include <linux/netdevice.h> |
48 | 49 | #include <linux/skbuff.h> /* struct sk_buff */ |
49 | 50 | #include <linux/security.h> |
50 | 51 | |
... | ... | @@ -78,17 +79,16 @@ |
78 | 79 | spinlock_t slock; |
79 | 80 | struct sock_iocb *owner; |
80 | 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 | 91 | } socket_lock_t; |
82 | - | |
83 | -extern struct lock_class_key af_family_keys[AF_MAX]; | |
84 | - | |
85 | -#define sock_lock_init(__sk) \ | |
86 | -do { 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 | 92 | |
93 | 93 | struct sock; |
94 | 94 | struct proto; |
net/core/sock.c
... | ... | @@ -133,9 +133,44 @@ |
133 | 133 | * Each address family might have different locking rules, so we have |
134 | 134 | * one slock key per address family: |
135 | 135 | */ |
136 | -struct lock_class_key af_family_keys[AF_MAX]; | |
136 | +static struct lock_class_key af_family_keys[AF_MAX]; | |
137 | +static struct lock_class_key af_family_slock_keys[AF_MAX]; | |
137 | 138 | |
139 | +#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
138 | 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 | + */ | |
145 | +static 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 | +}; | |
158 | +static 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 | |
172 | + | |
173 | +/* | |
139 | 174 | * sk_callback_lock locking rules are per-address-family, |
140 | 175 | * so split the lock classes by using a per-AF key: |
141 | 176 | */ |
142 | 177 | |
... | ... | @@ -249,9 +284,16 @@ |
249 | 284 | skb->dev = NULL; |
250 | 285 | |
251 | 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 | 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 | 297 | sk_add_backlog(sk, skb); |
256 | 298 | bh_unlock_sock(sk); |
257 | 299 | out: |
... | ... | @@ -761,6 +803,33 @@ |
761 | 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 | + */ | |
811 | +static 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 | 834 | * sk_alloc - All socket objects are allocated here |
766 | 835 | * @family: protocol family |
767 | 836 | |
768 | 837 | |
769 | 838 | |
... | ... | @@ -1465,24 +1534,34 @@ |
1465 | 1534 | void fastcall lock_sock(struct sock *sk) |
1466 | 1535 | { |
1467 | 1536 | might_sleep(); |
1468 | - spin_lock_bh(&(sk->sk_lock.slock)); | |
1537 | + spin_lock_bh(&sk->sk_lock.slock); | |
1469 | 1538 | if (sk->sk_lock.owner) |
1470 | 1539 | __lock_sock(sk); |
1471 | 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 | |
1475 | 1549 | EXPORT_SYMBOL(lock_sock); |
1476 | 1550 | |
1477 | 1551 | void 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 | 1559 | if (sk->sk_backlog.tail) |
1481 | 1560 | __release_sock(sk); |
1482 | 1561 | sk->sk_lock.owner = NULL; |
1483 | - if (waitqueue_active(&(sk->sk_lock.wq))) | |
1484 | - wake_up(&(sk->sk_lock.wq)); | |
1485 | - spin_unlock_bh(&(sk->sk_lock.slock)); | |
1562 | + if (waitqueue_active(&sk->sk_lock.wq)) | |
1563 | + wake_up(&sk->sk_lock.wq); | |
1564 | + spin_unlock_bh(&sk->sk_lock.slock); | |
1486 | 1565 | } |
1487 | 1566 | EXPORT_SYMBOL(release_sock); |
1488 | 1567 |