diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-04-29 07:01:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-01 18:00:15 -0400 |
commit | 43815482370c510c569fd18edb57afcb0fa8cab6 (patch) | |
tree | 063efaae3758402b84f056438b704d1de68f7837 /drivers/net/macvtap.c | |
parent | 83d7eb2979cd3390c375470225dd2d8f2009bc70 (diff) |
net: sock_def_readable() and friends RCU conversion
sk_callback_lock rwlock actually protects sk->sk_sleep pointer, so we
need two atomic operations (and associated dirtying) per incoming
packet.
RCU conversion is pretty much needed :
1) Add a new structure, called "struct socket_wq" to hold all fields
that will need rcu_read_lock() protection (currently: a
wait_queue_head_t and a struct fasync_struct pointer).
[Future patch will add a list anchor for wakeup coalescing]
2) Attach one of such structure to each "struct socket" created in
sock_alloc_inode().
3) Respect RCU grace period when freeing a "struct socket_wq"
4) Change sk_sleep pointer in "struct sock" by sk_wq, pointer to "struct
socket_wq"
5) Change sk_sleep() function to use new sk->sk_wq instead of
sk->sk_sleep
6) Change sk_has_sleeper() to wq_has_sleeper() that must be used inside
a rcu_read_lock() section.
7) Change all sk_has_sleeper() callers to :
- Use rcu_read_lock() instead of read_lock(&sk->sk_callback_lock)
- Use wq_has_sleeper() to eventually wakeup tasks.
- Use rcu_read_unlock() instead of read_unlock(&sk->sk_callback_lock)
8) sock_wake_async() is modified to use rcu protection as well.
9) Exceptions :
macvtap, drivers/net/tun.c, af_unix use integrated "struct socket_wq"
instead of dynamically allocated ones. They dont need rcu freeing.
Some cleanups or followups are probably needed, (possible
sk_callback_lock conversion to a spinlock for example...).
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r-- | drivers/net/macvtap.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index d97e1fd234ba..1c4110df343e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -37,6 +37,7 @@ | |||
37 | struct macvtap_queue { | 37 | struct macvtap_queue { |
38 | struct sock sk; | 38 | struct sock sk; |
39 | struct socket sock; | 39 | struct socket sock; |
40 | struct socket_wq wq; | ||
40 | struct macvlan_dev *vlan; | 41 | struct macvlan_dev *vlan; |
41 | struct file *file; | 42 | struct file *file; |
42 | unsigned int flags; | 43 | unsigned int flags; |
@@ -242,12 +243,15 @@ static struct rtnl_link_ops macvtap_link_ops __read_mostly = { | |||
242 | 243 | ||
243 | static void macvtap_sock_write_space(struct sock *sk) | 244 | static void macvtap_sock_write_space(struct sock *sk) |
244 | { | 245 | { |
246 | wait_queue_head_t *wqueue; | ||
247 | |||
245 | if (!sock_writeable(sk) || | 248 | if (!sock_writeable(sk) || |
246 | !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) | 249 | !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) |
247 | return; | 250 | return; |
248 | 251 | ||
249 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) | 252 | wqueue = sk_sleep(sk); |
250 | wake_up_interruptible_poll(sk_sleep(sk), POLLOUT | POLLWRNORM | POLLWRBAND); | 253 | if (wqueue && waitqueue_active(wqueue)) |
254 | wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND); | ||
251 | } | 255 | } |
252 | 256 | ||
253 | static int macvtap_open(struct inode *inode, struct file *file) | 257 | static int macvtap_open(struct inode *inode, struct file *file) |
@@ -272,7 +276,8 @@ static int macvtap_open(struct inode *inode, struct file *file) | |||
272 | if (!q) | 276 | if (!q) |
273 | goto out; | 277 | goto out; |
274 | 278 | ||
275 | init_waitqueue_head(&q->sock.wait); | 279 | q->sock.wq = &q->wq; |
280 | init_waitqueue_head(&q->wq.wait); | ||
276 | q->sock.type = SOCK_RAW; | 281 | q->sock.type = SOCK_RAW; |
277 | q->sock.state = SS_CONNECTED; | 282 | q->sock.state = SS_CONNECTED; |
278 | q->sock.file = file; | 283 | q->sock.file = file; |
@@ -308,7 +313,7 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait) | |||
308 | goto out; | 313 | goto out; |
309 | 314 | ||
310 | mask = 0; | 315 | mask = 0; |
311 | poll_wait(file, &q->sock.wait, wait); | 316 | poll_wait(file, &q->wq.wait, wait); |
312 | 317 | ||
313 | if (!skb_queue_empty(&q->sk.sk_receive_queue)) | 318 | if (!skb_queue_empty(&q->sk.sk_receive_queue)) |
314 | mask |= POLLIN | POLLRDNORM; | 319 | mask |= POLLIN | POLLRDNORM; |