|
146 | 146 | static DEFINE_MUTEX(proto_list_mutex); |
147 | 147 | static LIST_HEAD(proto_list); |
148 | 148 |
|
| 149 | +static void sock_def_write_space_wfree(struct sock *sk); |
| 150 | +static void sock_def_write_space(struct sock *sk); |
| 151 | + |
149 | 152 | /** |
150 | 153 | * sk_ns_capable - General socket capability test |
151 | 154 | * @sk: Socket to use a capability on or through |
@@ -2324,8 +2327,20 @@ void sock_wfree(struct sk_buff *skb) |
2324 | 2327 | { |
2325 | 2328 | struct sock *sk = skb->sk; |
2326 | 2329 | unsigned int len = skb->truesize; |
| 2330 | + bool free; |
2327 | 2331 |
|
2328 | 2332 | if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) { |
| 2333 | + if (sock_flag(sk, SOCK_RCU_FREE) && |
| 2334 | + sk->sk_write_space == sock_def_write_space) { |
| 2335 | + rcu_read_lock(); |
| 2336 | + free = refcount_sub_and_test(len, &sk->sk_wmem_alloc); |
| 2337 | + sock_def_write_space_wfree(sk); |
| 2338 | + rcu_read_unlock(); |
| 2339 | + if (unlikely(free)) |
| 2340 | + __sk_free(sk); |
| 2341 | + return; |
| 2342 | + } |
| 2343 | + |
2329 | 2344 | /* |
2330 | 2345 | * Keep a reference on sk_wmem_alloc, this will be released |
2331 | 2346 | * after sk_write_space() call |
@@ -3191,20 +3206,42 @@ static void sock_def_write_space(struct sock *sk) |
3191 | 3206 | /* Do not wake up a writer until he can make "significant" |
3192 | 3207 | * progress. --DaveM |
3193 | 3208 | */ |
3194 | | - if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= READ_ONCE(sk->sk_sndbuf)) { |
| 3209 | + if (sock_writeable(sk)) { |
3195 | 3210 | wq = rcu_dereference(sk->sk_wq); |
3196 | 3211 | if (skwq_has_sleeper(wq)) |
3197 | 3212 | wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | |
3198 | 3213 | EPOLLWRNORM | EPOLLWRBAND); |
3199 | 3214 |
|
3200 | 3215 | /* Should agree with poll, otherwise some programs break */ |
3201 | | - if (sock_writeable(sk)) |
3202 | | - sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 3216 | + sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
3203 | 3217 | } |
3204 | 3218 |
|
3205 | 3219 | rcu_read_unlock(); |
3206 | 3220 | } |
3207 | 3221 |
|
| 3222 | +/* An optimised version of sock_def_write_space(), should only be called |
| 3223 | + * for SOCK_RCU_FREE sockets under RCU read section and after putting |
| 3224 | + * ->sk_wmem_alloc. |
| 3225 | + */ |
| 3226 | +static void sock_def_write_space_wfree(struct sock *sk) |
| 3227 | +{ |
| 3228 | + /* Do not wake up a writer until he can make "significant" |
| 3229 | + * progress. --DaveM |
| 3230 | + */ |
| 3231 | + if (sock_writeable(sk)) { |
| 3232 | + struct socket_wq *wq = rcu_dereference(sk->sk_wq); |
| 3233 | + |
| 3234 | + /* rely on refcount_sub from sock_wfree() */ |
| 3235 | + smp_mb__after_atomic(); |
| 3236 | + if (wq && waitqueue_active(&wq->wait)) |
| 3237 | + wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | |
| 3238 | + EPOLLWRNORM | EPOLLWRBAND); |
| 3239 | + |
| 3240 | + /* Should agree with poll, otherwise some programs break */ |
| 3241 | + sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 3242 | + } |
| 3243 | +} |
| 3244 | + |
3208 | 3245 | static void sock_def_destruct(struct sock *sk) |
3209 | 3246 | { |
3210 | 3247 | } |
|
0 commit comments