Skip to content

Commit a5b5bb9

Browse files
Ingo MolnarLinus Torvalds
authored andcommitted
[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 <[email protected]> Cc: Arjan van de Ven <[email protected]> Cc: "David S. Miller" <[email protected]> Cc: Herbert Xu <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 0afffc7 commit a5b5bb9

File tree

2 files changed

+98
-19
lines changed

2 files changed

+98
-19
lines changed

include/net/sock.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <linux/timer.h>
4545
#include <linux/cache.h>
4646
#include <linux/module.h>
47+
#include <linux/lockdep.h>
4748
#include <linux/netdevice.h>
4849
#include <linux/skbuff.h> /* struct sk_buff */
4950
#include <linux/security.h>
@@ -78,18 +79,17 @@ typedef struct {
7879
spinlock_t slock;
7980
struct sock_iocb *owner;
8081
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
8191
} socket_lock_t;
8292

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-
9393
struct sock;
9494
struct proto;
9595

net/core/sock.c

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,42 @@
133133
* Each address family might have different locking rules, so we have
134134
* one slock key per address family:
135135
*/
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];
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+
*/
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
137172

138173
/*
139174
* sk_callback_lock locking rules are per-address-family,
@@ -249,9 +284,16 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
249284
skb->dev = NULL;
250285

251286
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+
253293
rc = sk->sk_backlog_rcv(sk, skb);
254-
else
294+
295+
mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
296+
} else
255297
sk_add_backlog(sk, skb);
256298
bh_unlock_sock(sk);
257299
out:
@@ -761,6 +803,33 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
761803
return 0;
762804
}
763805

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+
764833
/**
765834
* sk_alloc - All socket objects are allocated here
766835
* @family: protocol family
@@ -1465,24 +1534,34 @@ void sock_init_data(struct socket *sock, struct sock *sk)
14651534
void fastcall lock_sock(struct sock *sk)
14661535
{
14671536
might_sleep();
1468-
spin_lock_bh(&(sk->sk_lock.slock));
1537+
spin_lock_bh(&sk->sk_lock.slock);
14691538
if (sk->sk_lock.owner)
14701539
__lock_sock(sk);
14711540
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();
14731547
}
14741548

14751549
EXPORT_SYMBOL(lock_sock);
14761550

14771551
void fastcall release_sock(struct sock *sk)
14781552
{
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);
14801559
if (sk->sk_backlog.tail)
14811560
__release_sock(sk);
14821561
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);
14861565
}
14871566
EXPORT_SYMBOL(release_sock);
14881567

0 commit comments

Comments
 (0)