diff options
Diffstat (limited to 'net/rds/recv.c')
-rw-r--r-- | net/rds/recv.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/net/rds/recv.c b/net/rds/recv.c index cbfabdf3ff48..9d0666e5fe35 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
@@ -120,6 +120,36 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk, | |||
120 | /* do nothing if no change in cong state */ | 120 | /* do nothing if no change in cong state */ |
121 | } | 121 | } |
122 | 122 | ||
123 | static void rds_conn_peer_gen_update(struct rds_connection *conn, | ||
124 | u32 peer_gen_num) | ||
125 | { | ||
126 | int i; | ||
127 | struct rds_message *rm, *tmp; | ||
128 | unsigned long flags; | ||
129 | |||
130 | WARN_ON(conn->c_trans->t_type != RDS_TRANS_TCP); | ||
131 | if (peer_gen_num != 0) { | ||
132 | if (conn->c_peer_gen_num != 0 && | ||
133 | peer_gen_num != conn->c_peer_gen_num) { | ||
134 | for (i = 0; i < RDS_MPATH_WORKERS; i++) { | ||
135 | struct rds_conn_path *cp; | ||
136 | |||
137 | cp = &conn->c_path[i]; | ||
138 | spin_lock_irqsave(&cp->cp_lock, flags); | ||
139 | cp->cp_next_tx_seq = 1; | ||
140 | cp->cp_next_rx_seq = 0; | ||
141 | list_for_each_entry_safe(rm, tmp, | ||
142 | &cp->cp_retrans, | ||
143 | m_conn_item) { | ||
144 | set_bit(RDS_MSG_FLUSH, &rm->m_flags); | ||
145 | } | ||
146 | spin_unlock_irqrestore(&cp->cp_lock, flags); | ||
147 | } | ||
148 | } | ||
149 | conn->c_peer_gen_num = peer_gen_num; | ||
150 | } | ||
151 | } | ||
152 | |||
123 | /* | 153 | /* |
124 | * Process all extension headers that come with this message. | 154 | * Process all extension headers that come with this message. |
125 | */ | 155 | */ |
@@ -163,7 +193,9 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr, | |||
163 | union { | 193 | union { |
164 | struct rds_ext_header_version version; | 194 | struct rds_ext_header_version version; |
165 | u16 rds_npaths; | 195 | u16 rds_npaths; |
196 | u32 rds_gen_num; | ||
166 | } buffer; | 197 | } buffer; |
198 | u32 new_peer_gen_num = 0; | ||
167 | 199 | ||
168 | while (1) { | 200 | while (1) { |
169 | len = sizeof(buffer); | 201 | len = sizeof(buffer); |
@@ -176,6 +208,9 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr, | |||
176 | conn->c_npaths = min_t(int, RDS_MPATH_WORKERS, | 208 | conn->c_npaths = min_t(int, RDS_MPATH_WORKERS, |
177 | buffer.rds_npaths); | 209 | buffer.rds_npaths); |
178 | break; | 210 | break; |
211 | case RDS_EXTHDR_GEN_NUM: | ||
212 | new_peer_gen_num = buffer.rds_gen_num; | ||
213 | break; | ||
179 | default: | 214 | default: |
180 | pr_warn_ratelimited("ignoring unknown exthdr type " | 215 | pr_warn_ratelimited("ignoring unknown exthdr type " |
181 | "0x%x\n", type); | 216 | "0x%x\n", type); |
@@ -183,6 +218,7 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr, | |||
183 | } | 218 | } |
184 | /* if RDS_EXTHDR_NPATHS was not found, default to a single-path */ | 219 | /* if RDS_EXTHDR_NPATHS was not found, default to a single-path */ |
185 | conn->c_npaths = max_t(int, conn->c_npaths, 1); | 220 | conn->c_npaths = max_t(int, conn->c_npaths, 1); |
221 | rds_conn_peer_gen_update(conn, new_peer_gen_num); | ||
186 | } | 222 | } |
187 | 223 | ||
188 | /* rds_start_mprds() will synchronously start multiple paths when appropriate. | 224 | /* rds_start_mprds() will synchronously start multiple paths when appropriate. |