|
@@ -384,8 +384,10 @@ struct sock {
|
|
|
int sk_rcvbuf;
|
|
|
|
|
|
struct sk_filter __rcu *sk_filter;
|
|
|
- struct socket_wq __rcu *sk_wq;
|
|
|
-
|
|
|
+ union {
|
|
|
+ struct socket_wq __rcu *sk_wq;
|
|
|
+ struct socket_wq *sk_wq_raw;
|
|
|
+ };
|
|
|
#ifdef CONFIG_XFRM
|
|
|
struct xfrm_policy *sk_policy[2];
|
|
|
#endif
|
|
@@ -2005,20 +2007,27 @@ static inline unsigned long sock_wspace(struct sock *sk)
|
|
|
return amt;
|
|
|
}
|
|
|
|
|
|
+/* Note:
|
|
|
+ * We use sk->sk_wq_raw, from contexts knowing this
|
|
|
+ * pointer is not NULL and cannot disappear/change.
|
|
|
+ */
|
|
|
static inline void sk_set_bit(int nr, struct sock *sk)
|
|
|
{
|
|
|
- set_bit(nr, &sk->sk_socket->flags);
|
|
|
+ set_bit(nr, &sk->sk_wq_raw->flags);
|
|
|
}
|
|
|
|
|
|
static inline void sk_clear_bit(int nr, struct sock *sk)
|
|
|
{
|
|
|
- clear_bit(nr, &sk->sk_socket->flags);
|
|
|
+ clear_bit(nr, &sk->sk_wq_raw->flags);
|
|
|
}
|
|
|
|
|
|
-static inline void sk_wake_async(struct sock *sk, int how, int band)
|
|
|
+static inline void sk_wake_async(const struct sock *sk, int how, int band)
|
|
|
{
|
|
|
- if (sock_flag(sk, SOCK_FASYNC))
|
|
|
- sock_wake_async(sk->sk_socket, how, band);
|
|
|
+ if (sock_flag(sk, SOCK_FASYNC)) {
|
|
|
+ rcu_read_lock();
|
|
|
+ sock_wake_async(rcu_dereference(sk->sk_wq), how, band);
|
|
|
+ rcu_read_unlock();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Since sk_{r,w}mem_alloc sums skb->truesize, even a small frame might
|