Skip to content

Commit e9d09ba

Browse files
Paolo Abenidavem330
Paolo Abeni
authored andcommitted
mptcp: avoid atomic bit manipulation when possible
Currently the msk->flags bitmask carries both state for the mptcp_release_cb() - mostly touched under the mptcp data lock - and others state info touched even outside such lock scope. As a consequence, msk->flags is always manipulated with atomic operations. This change splits such bitmask in two separate fields, so that we use plain bit operations when touching the cb-related info. The MPTCP_PUSH_PENDING bit needs additional care, as it is the only CB related field currently accessed either under the mptcp data lock or the mptcp socket lock. Let's add another mask just for such bit's sake. Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3e50149 commit e9d09ba

File tree

3 files changed

+38
-31
lines changed

3 files changed

+38
-31
lines changed

net/mptcp/protocol.c

+25-22
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk)
763763
if (!sock_owned_by_user(sk))
764764
__mptcp_error_report(sk);
765765
else
766-
set_bit(MPTCP_ERROR_REPORT, &msk->flags);
766+
__set_bit(MPTCP_ERROR_REPORT, &msk->cb_flags);
767767
}
768768

769769
/* If the moves have caught up with the DATA_FIN sequence number
@@ -1517,9 +1517,8 @@ static void mptcp_update_post_push(struct mptcp_sock *msk,
15171517

15181518
void mptcp_check_and_set_pending(struct sock *sk)
15191519
{
1520-
if (mptcp_send_head(sk) &&
1521-
!test_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags))
1522-
set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags);
1520+
if (mptcp_send_head(sk))
1521+
mptcp_sk(sk)->push_pending |= BIT(MPTCP_PUSH_PENDING);
15231522
}
15241523

15251524
void __mptcp_push_pending(struct sock *sk, unsigned int flags)
@@ -2134,7 +2133,7 @@ static void mptcp_retransmit_timer(struct timer_list *t)
21342133
mptcp_schedule_work(sk);
21352134
} else {
21362135
/* delegate our work to tcp_release_cb() */
2137-
set_bit(MPTCP_RETRANSMIT, &msk->flags);
2136+
__set_bit(MPTCP_RETRANSMIT, &msk->cb_flags);
21382137
}
21392138
bh_unlock_sock(sk);
21402139
sock_put(sk);
@@ -2840,7 +2839,9 @@ static int mptcp_disconnect(struct sock *sk, int flags)
28402839

28412840
mptcp_destroy_common(msk);
28422841
msk->last_snd = NULL;
2843-
msk->flags = 0;
2842+
WRITE_ONCE(msk->flags, 0);
2843+
msk->cb_flags = 0;
2844+
msk->push_pending = 0;
28442845
msk->recovery = false;
28452846
msk->can_ack = false;
28462847
msk->fully_established = false;
@@ -3021,7 +3022,7 @@ void __mptcp_data_acked(struct sock *sk)
30213022
if (!sock_owned_by_user(sk))
30223023
__mptcp_clean_una(sk);
30233024
else
3024-
set_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->flags);
3025+
__set_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->cb_flags);
30253026

30263027
if (mptcp_pending_data_fin_ack(sk))
30273028
mptcp_schedule_work(sk);
@@ -3040,22 +3041,23 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk)
30403041
else if (xmit_ssk)
30413042
mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), MPTCP_DELEGATE_SEND);
30423043
} else {
3043-
set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags);
3044+
__set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
30443045
}
30453046
}
30463047

3048+
#define MPTCP_FLAGS_PROCESS_CTX_NEED (BIT(MPTCP_PUSH_PENDING) | \
3049+
BIT(MPTCP_RETRANSMIT) | \
3050+
BIT(MPTCP_FLUSH_JOIN_LIST))
3051+
30473052
/* processes deferred events and flush wmem */
30483053
static void mptcp_release_cb(struct sock *sk)
3054+
__must_hold(&sk->sk_lock.slock)
30493055
{
3056+
struct mptcp_sock *msk = mptcp_sk(sk);
3057+
30503058
for (;;) {
3051-
unsigned long flags = 0;
3052-
3053-
if (test_and_clear_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags))
3054-
flags |= BIT(MPTCP_PUSH_PENDING);
3055-
if (test_and_clear_bit(MPTCP_RETRANSMIT, &mptcp_sk(sk)->flags))
3056-
flags |= BIT(MPTCP_RETRANSMIT);
3057-
if (test_and_clear_bit(MPTCP_FLUSH_JOIN_LIST, &mptcp_sk(sk)->flags))
3058-
flags |= BIT(MPTCP_FLUSH_JOIN_LIST);
3059+
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
3060+
msk->push_pending;
30593061
if (!flags)
30603062
break;
30613063

@@ -3066,7 +3068,8 @@ static void mptcp_release_cb(struct sock *sk)
30663068
* datapath acquires the msk socket spinlock while helding
30673069
* the subflow socket lock
30683070
*/
3069-
3071+
msk->push_pending = 0;
3072+
msk->cb_flags &= ~flags;
30703073
spin_unlock_bh(&sk->sk_lock.slock);
30713074
if (flags & BIT(MPTCP_FLUSH_JOIN_LIST))
30723075
__mptcp_flush_join_list(sk);
@@ -3082,11 +3085,11 @@ static void mptcp_release_cb(struct sock *sk)
30823085
/* be sure to set the current sk state before tacking actions
30833086
* depending on sk_state
30843087
*/
3085-
if (test_and_clear_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->flags))
3088+
if (__test_and_clear_bit(MPTCP_CONNECTED, &msk->cb_flags))
30863089
__mptcp_set_connected(sk);
3087-
if (test_and_clear_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->flags))
3090+
if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags))
30883091
__mptcp_clean_una_wakeup(sk);
3089-
if (test_and_clear_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags))
3092+
if (__test_and_clear_bit(MPTCP_ERROR_REPORT, &msk->cb_flags))
30903093
__mptcp_error_report(sk);
30913094

30923095
__mptcp_update_rmem(sk);
@@ -3128,7 +3131,7 @@ void mptcp_subflow_process_delegated(struct sock *ssk)
31283131
if (!sock_owned_by_user(sk))
31293132
__mptcp_subflow_push_pending(sk, ssk);
31303133
else
3131-
set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags);
3134+
__set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
31323135
mptcp_data_unlock(sk);
31333136
mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND);
31343137
}
@@ -3247,7 +3250,7 @@ bool mptcp_finish_join(struct sock *ssk)
32473250
} else {
32483251
sock_hold(ssk);
32493252
list_add_tail(&subflow->node, &msk->join_list);
3250-
set_bit(MPTCP_FLUSH_JOIN_LIST, &msk->flags);
3253+
__set_bit(MPTCP_FLUSH_JOIN_LIST, &msk->cb_flags);
32513254
}
32523255
mptcp_data_unlock(parent);
32533256

net/mptcp/protocol.h

+11-7
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,20 @@
110110
/* MPTCP TCPRST flags */
111111
#define MPTCP_RST_TRANSIENT BIT(0)
112112

113-
/* MPTCP socket flags */
113+
/* MPTCP socket atomic flags */
114114
#define MPTCP_NOSPACE 1
115115
#define MPTCP_WORK_RTX 2
116116
#define MPTCP_WORK_EOF 3
117117
#define MPTCP_FALLBACK_DONE 4
118118
#define MPTCP_WORK_CLOSE_SUBFLOW 5
119-
#define MPTCP_PUSH_PENDING 6
120-
#define MPTCP_CLEAN_UNA 7
121-
#define MPTCP_ERROR_REPORT 8
122-
#define MPTCP_RETRANSMIT 9
123-
#define MPTCP_FLUSH_JOIN_LIST 10
124-
#define MPTCP_CONNECTED 11
119+
120+
/* MPTCP socket release cb flags */
121+
#define MPTCP_PUSH_PENDING 1
122+
#define MPTCP_CLEAN_UNA 2
123+
#define MPTCP_ERROR_REPORT 3
124+
#define MPTCP_RETRANSMIT 4
125+
#define MPTCP_FLUSH_JOIN_LIST 5
126+
#define MPTCP_CONNECTED 6
125127

126128
static inline bool before64(__u64 seq1, __u64 seq2)
127129
{
@@ -250,6 +252,8 @@ struct mptcp_sock {
250252
u32 token;
251253
int rmem_released;
252254
unsigned long flags;
255+
unsigned long cb_flags;
256+
unsigned long push_pending;
253257
bool recovery; /* closing subflow write queue reinjected */
254258
bool can_ack;
255259
bool fully_established;

net/mptcp/subflow.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ static void mptcp_set_connected(struct sock *sk)
388388
if (!sock_owned_by_user(sk))
389389
__mptcp_set_connected(sk);
390390
else
391-
set_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->flags);
391+
__set_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->cb_flags);
392392
mptcp_data_unlock(sk);
393393
}
394394

@@ -1274,7 +1274,7 @@ static void subflow_error_report(struct sock *ssk)
12741274
if (!sock_owned_by_user(sk))
12751275
__mptcp_error_report(sk);
12761276
else
1277-
set_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags);
1277+
__set_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->cb_flags);
12781278
mptcp_data_unlock(sk);
12791279
}
12801280

0 commit comments

Comments
 (0)