diff options
author | David S. Miller <davem@davemloft.net> | 2016-02-01 21:44:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-02-01 21:44:07 -0500 |
commit | b45efa30a626e915192a6c548cd8642379cd47cc (patch) | |
tree | 90d8b43ebceb850b0e7852d75283aebbd2abbc00 /net | |
parent | 7a26019fdecdb45ff784ae4e3b7e0cc9045100ca (diff) | |
parent | 34229b277480f46c1e9a19f027f30b074512e68b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net')
92 files changed, 1388 insertions, 1010 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index bced8c074c12..7bc2208b6cc4 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -108,9 +108,7 @@ struct p9_poll_wait { | |||
108 | * @unsent_req_list: accounting for requests that haven't been sent | 108 | * @unsent_req_list: accounting for requests that haven't been sent |
109 | * @req: current request being processed (if any) | 109 | * @req: current request being processed (if any) |
110 | * @tmp_buf: temporary buffer to read in header | 110 | * @tmp_buf: temporary buffer to read in header |
111 | * @rsize: amount to read for current frame | 111 | * @rc: temporary fcall for reading current frame |
112 | * @rpos: read position in current frame | ||
113 | * @rbuf: current read buffer | ||
114 | * @wpos: write position for current frame | 112 | * @wpos: write position for current frame |
115 | * @wsize: amount of data to write for current frame | 113 | * @wsize: amount of data to write for current frame |
116 | * @wbuf: current write buffer | 114 | * @wbuf: current write buffer |
@@ -131,9 +129,7 @@ struct p9_conn { | |||
131 | struct list_head unsent_req_list; | 129 | struct list_head unsent_req_list; |
132 | struct p9_req_t *req; | 130 | struct p9_req_t *req; |
133 | char tmp_buf[7]; | 131 | char tmp_buf[7]; |
134 | int rsize; | 132 | struct p9_fcall rc; |
135 | int rpos; | ||
136 | char *rbuf; | ||
137 | int wpos; | 133 | int wpos; |
138 | int wsize; | 134 | int wsize; |
139 | char *wbuf; | 135 | char *wbuf; |
@@ -305,69 +301,77 @@ static void p9_read_work(struct work_struct *work) | |||
305 | if (m->err < 0) | 301 | if (m->err < 0) |
306 | return; | 302 | return; |
307 | 303 | ||
308 | p9_debug(P9_DEBUG_TRANS, "start mux %p pos %d\n", m, m->rpos); | 304 | p9_debug(P9_DEBUG_TRANS, "start mux %p pos %zd\n", m, m->rc.offset); |
309 | 305 | ||
310 | if (!m->rbuf) { | 306 | if (!m->rc.sdata) { |
311 | m->rbuf = m->tmp_buf; | 307 | m->rc.sdata = m->tmp_buf; |
312 | m->rpos = 0; | 308 | m->rc.offset = 0; |
313 | m->rsize = 7; /* start by reading header */ | 309 | m->rc.capacity = 7; /* start by reading header */ |
314 | } | 310 | } |
315 | 311 | ||
316 | clear_bit(Rpending, &m->wsched); | 312 | clear_bit(Rpending, &m->wsched); |
317 | p9_debug(P9_DEBUG_TRANS, "read mux %p pos %d size: %d = %d\n", | 313 | p9_debug(P9_DEBUG_TRANS, "read mux %p pos %zd size: %zd = %zd\n", |
318 | m, m->rpos, m->rsize, m->rsize-m->rpos); | 314 | m, m->rc.offset, m->rc.capacity, |
319 | err = p9_fd_read(m->client, m->rbuf + m->rpos, | 315 | m->rc.capacity - m->rc.offset); |
320 | m->rsize - m->rpos); | 316 | err = p9_fd_read(m->client, m->rc.sdata + m->rc.offset, |
317 | m->rc.capacity - m->rc.offset); | ||
321 | p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err); | 318 | p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err); |
322 | if (err == -EAGAIN) { | 319 | if (err == -EAGAIN) |
323 | goto end_clear; | 320 | goto end_clear; |
324 | } | ||
325 | 321 | ||
326 | if (err <= 0) | 322 | if (err <= 0) |
327 | goto error; | 323 | goto error; |
328 | 324 | ||
329 | m->rpos += err; | 325 | m->rc.offset += err; |
330 | 326 | ||
331 | if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */ | 327 | /* header read in */ |
332 | u16 tag; | 328 | if ((!m->req) && (m->rc.offset == m->rc.capacity)) { |
333 | p9_debug(P9_DEBUG_TRANS, "got new header\n"); | 329 | p9_debug(P9_DEBUG_TRANS, "got new header\n"); |
334 | 330 | ||
335 | n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */ | 331 | err = p9_parse_header(&m->rc, NULL, NULL, NULL, 0); |
336 | if (n >= m->client->msize) { | 332 | if (err) { |
333 | p9_debug(P9_DEBUG_ERROR, | ||
334 | "error parsing header: %d\n", err); | ||
335 | goto error; | ||
336 | } | ||
337 | |||
338 | if (m->rc.size >= m->client->msize) { | ||
337 | p9_debug(P9_DEBUG_ERROR, | 339 | p9_debug(P9_DEBUG_ERROR, |
338 | "requested packet size too big: %d\n", n); | 340 | "requested packet size too big: %d\n", |
341 | m->rc.size); | ||
339 | err = -EIO; | 342 | err = -EIO; |
340 | goto error; | 343 | goto error; |
341 | } | 344 | } |
342 | 345 | ||
343 | tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */ | ||
344 | p9_debug(P9_DEBUG_TRANS, | 346 | p9_debug(P9_DEBUG_TRANS, |
345 | "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); | 347 | "mux %p pkt: size: %d bytes tag: %d\n", |
348 | m, m->rc.size, m->rc.tag); | ||
346 | 349 | ||
347 | m->req = p9_tag_lookup(m->client, tag); | 350 | m->req = p9_tag_lookup(m->client, m->rc.tag); |
348 | if (!m->req || (m->req->status != REQ_STATUS_SENT)) { | 351 | if (!m->req || (m->req->status != REQ_STATUS_SENT)) { |
349 | p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", | 352 | p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", |
350 | tag); | 353 | m->rc.tag); |
351 | err = -EIO; | 354 | err = -EIO; |
352 | goto error; | 355 | goto error; |
353 | } | 356 | } |
354 | 357 | ||
355 | if (m->req->rc == NULL) { | 358 | if (m->req->rc == NULL) { |
356 | m->req->rc = kmalloc(sizeof(struct p9_fcall) + | 359 | p9_debug(P9_DEBUG_ERROR, |
357 | m->client->msize, GFP_NOFS); | 360 | "No recv fcall for tag %d (req %p), disconnecting!\n", |
358 | if (!m->req->rc) { | 361 | m->rc.tag, m->req); |
359 | m->req = NULL; | 362 | m->req = NULL; |
360 | err = -ENOMEM; | 363 | err = -EIO; |
361 | goto error; | 364 | goto error; |
362 | } | ||
363 | } | 365 | } |
364 | m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall); | 366 | m->rc.sdata = (char *)m->req->rc + sizeof(struct p9_fcall); |
365 | memcpy(m->rbuf, m->tmp_buf, m->rsize); | 367 | memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity); |
366 | m->rsize = n; | 368 | m->rc.capacity = m->rc.size; |
367 | } | 369 | } |
368 | 370 | ||
369 | /* not an else because some packets (like clunk) have no payload */ | 371 | /* packet is read in |
370 | if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ | 372 | * not an else because some packets (like clunk) have no payload |
373 | */ | ||
374 | if ((m->req) && (m->rc.offset == m->rc.capacity)) { | ||
371 | p9_debug(P9_DEBUG_TRANS, "got new packet\n"); | 375 | p9_debug(P9_DEBUG_TRANS, "got new packet\n"); |
372 | spin_lock(&m->client->lock); | 376 | spin_lock(&m->client->lock); |
373 | if (m->req->status != REQ_STATUS_ERROR) | 377 | if (m->req->status != REQ_STATUS_ERROR) |
@@ -375,9 +379,9 @@ static void p9_read_work(struct work_struct *work) | |||
375 | list_del(&m->req->req_list); | 379 | list_del(&m->req->req_list); |
376 | spin_unlock(&m->client->lock); | 380 | spin_unlock(&m->client->lock); |
377 | p9_client_cb(m->client, m->req, status); | 381 | p9_client_cb(m->client, m->req, status); |
378 | m->rbuf = NULL; | 382 | m->rc.sdata = NULL; |
379 | m->rpos = 0; | 383 | m->rc.offset = 0; |
380 | m->rsize = 0; | 384 | m->rc.capacity = 0; |
381 | m->req = NULL; | 385 | m->req = NULL; |
382 | } | 386 | } |
383 | 387 | ||
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 199bc76202d2..4acb1d5417aa 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -658,7 +658,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) | |||
658 | mutex_unlock(&virtio_9p_lock); | 658 | mutex_unlock(&virtio_9p_lock); |
659 | 659 | ||
660 | if (!found) { | 660 | if (!found) { |
661 | pr_err("no channels available\n"); | 661 | pr_err("no channels available for device %s\n", devname); |
662 | return ret; | 662 | return ret; |
663 | } | 663 | } |
664 | 664 | ||
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index d5d71ac96c8a..c24c481b666f 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -127,21 +127,17 @@ batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw) | |||
127 | } | 127 | } |
128 | 128 | ||
129 | /* finally deinitialize the claim */ | 129 | /* finally deinitialize the claim */ |
130 | static void batadv_claim_free_rcu(struct rcu_head *rcu) | 130 | static void batadv_claim_release(struct batadv_bla_claim *claim) |
131 | { | 131 | { |
132 | struct batadv_bla_claim *claim; | ||
133 | |||
134 | claim = container_of(rcu, struct batadv_bla_claim, rcu); | ||
135 | |||
136 | batadv_backbone_gw_free_ref(claim->backbone_gw); | 132 | batadv_backbone_gw_free_ref(claim->backbone_gw); |
137 | kfree(claim); | 133 | kfree_rcu(claim, rcu); |
138 | } | 134 | } |
139 | 135 | ||
140 | /* free a claim, call claim_free_rcu if its the last reference */ | 136 | /* free a claim, call claim_free_rcu if its the last reference */ |
141 | static void batadv_claim_free_ref(struct batadv_bla_claim *claim) | 137 | static void batadv_claim_free_ref(struct batadv_bla_claim *claim) |
142 | { | 138 | { |
143 | if (atomic_dec_and_test(&claim->refcount)) | 139 | if (atomic_dec_and_test(&claim->refcount)) |
144 | call_rcu(&claim->rcu, batadv_claim_free_rcu); | 140 | batadv_claim_release(claim); |
145 | } | 141 | } |
146 | 142 | ||
147 | /** | 143 | /** |
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index 5a31420513e1..7b12ea8ea29d 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h | |||
@@ -75,18 +75,6 @@ batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) | |||
75 | call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); | 75 | call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); |
76 | } | 76 | } |
77 | 77 | ||
78 | /** | ||
79 | * batadv_hardif_free_ref_now - decrement the hard interface refcounter and | ||
80 | * possibly free it (without rcu callback) | ||
81 | * @hard_iface: the hard interface to free | ||
82 | */ | ||
83 | static inline void | ||
84 | batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface) | ||
85 | { | ||
86 | if (atomic_dec_and_test(&hard_iface->refcount)) | ||
87 | batadv_hardif_free_rcu(&hard_iface->rcu); | ||
88 | } | ||
89 | |||
90 | static inline struct batadv_hard_iface * | 78 | static inline struct batadv_hard_iface * |
91 | batadv_primary_if_get_selected(struct batadv_priv *bat_priv) | 79 | batadv_primary_if_get_selected(struct batadv_priv *bat_priv) |
92 | { | 80 | { |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index c98b0ab85449..cc63b44f0d2e 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
@@ -203,28 +203,25 @@ void batadv_nc_init_orig(struct batadv_orig_node *orig_node) | |||
203 | } | 203 | } |
204 | 204 | ||
205 | /** | 205 | /** |
206 | * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove | 206 | * batadv_nc_node_release - release nc_node from lists and queue for free after |
207 | * its refcount on the orig_node | 207 | * rcu grace period |
208 | * @rcu: rcu pointer of the nc node | 208 | * @nc_node: the nc node to free |
209 | */ | 209 | */ |
210 | static void batadv_nc_node_free_rcu(struct rcu_head *rcu) | 210 | static void batadv_nc_node_release(struct batadv_nc_node *nc_node) |
211 | { | 211 | { |
212 | struct batadv_nc_node *nc_node; | ||
213 | |||
214 | nc_node = container_of(rcu, struct batadv_nc_node, rcu); | ||
215 | batadv_orig_node_free_ref(nc_node->orig_node); | 212 | batadv_orig_node_free_ref(nc_node->orig_node); |
216 | kfree(nc_node); | 213 | kfree_rcu(nc_node, rcu); |
217 | } | 214 | } |
218 | 215 | ||
219 | /** | 216 | /** |
220 | * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly | 217 | * batadv_nc_node_free_ref - decrement the nc node refcounter and possibly |
221 | * frees it | 218 | * release it |
222 | * @nc_node: the nc node to free | 219 | * @nc_node: the nc node to free |
223 | */ | 220 | */ |
224 | static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) | 221 | static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) |
225 | { | 222 | { |
226 | if (atomic_dec_and_test(&nc_node->refcount)) | 223 | if (atomic_dec_and_test(&nc_node->refcount)) |
227 | call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu); | 224 | batadv_nc_node_release(nc_node); |
228 | } | 225 | } |
229 | 226 | ||
230 | /** | 227 | /** |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ae6d18cafc5a..fe578f75c391 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -163,148 +163,101 @@ err: | |||
163 | } | 163 | } |
164 | 164 | ||
165 | /** | 165 | /** |
166 | * batadv_neigh_ifinfo_free_rcu - free the neigh_ifinfo object | 166 | * batadv_neigh_ifinfo_release - release neigh_ifinfo from lists and queue for |
167 | * @rcu: rcu pointer of the neigh_ifinfo object | 167 | * free after rcu grace period |
168 | */ | ||
169 | static void batadv_neigh_ifinfo_free_rcu(struct rcu_head *rcu) | ||
170 | { | ||
171 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
172 | |||
173 | neigh_ifinfo = container_of(rcu, struct batadv_neigh_ifinfo, rcu); | ||
174 | |||
175 | if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) | ||
176 | batadv_hardif_free_ref_now(neigh_ifinfo->if_outgoing); | ||
177 | |||
178 | kfree(neigh_ifinfo); | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * batadv_neigh_ifinfo_free_now - decrement the refcounter and possibly free | ||
183 | * the neigh_ifinfo (without rcu callback) | ||
184 | * @neigh_ifinfo: the neigh_ifinfo object to release | 168 | * @neigh_ifinfo: the neigh_ifinfo object to release |
185 | */ | 169 | */ |
186 | static void | 170 | static void |
187 | batadv_neigh_ifinfo_free_ref_now(struct batadv_neigh_ifinfo *neigh_ifinfo) | 171 | batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo) |
188 | { | 172 | { |
189 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) | 173 | if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) |
190 | batadv_neigh_ifinfo_free_rcu(&neigh_ifinfo->rcu); | 174 | batadv_hardif_free_ref(neigh_ifinfo->if_outgoing); |
175 | |||
176 | kfree_rcu(neigh_ifinfo, rcu); | ||
191 | } | 177 | } |
192 | 178 | ||
193 | /** | 179 | /** |
194 | * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly free | 180 | * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly release |
195 | * the neigh_ifinfo | 181 | * the neigh_ifinfo |
196 | * @neigh_ifinfo: the neigh_ifinfo object to release | 182 | * @neigh_ifinfo: the neigh_ifinfo object to release |
197 | */ | 183 | */ |
198 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) | 184 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) |
199 | { | 185 | { |
200 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) | 186 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) |
201 | call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu); | 187 | batadv_neigh_ifinfo_release(neigh_ifinfo); |
202 | } | 188 | } |
203 | 189 | ||
204 | /** | 190 | /** |
205 | * batadv_hardif_neigh_free_rcu - free the hardif neigh_node | 191 | * batadv_hardif_neigh_release - release hardif neigh node from lists and |
206 | * @rcu: rcu pointer of the neigh_node | 192 | * queue for free after rcu grace period |
207 | */ | ||
208 | static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) | ||
209 | { | ||
210 | struct batadv_hardif_neigh_node *hardif_neigh; | ||
211 | |||
212 | hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu); | ||
213 | |||
214 | batadv_hardif_free_ref_now(hardif_neigh->if_incoming); | ||
215 | kfree(hardif_neigh); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * batadv_hardif_neigh_free_now - decrement the hardif neighbors refcounter | ||
220 | * and possibly free it (without rcu callback) | ||
221 | * @hardif_neigh: hardif neigh neighbor to free | 193 | * @hardif_neigh: hardif neigh neighbor to free |
222 | */ | 194 | */ |
223 | static void | 195 | static void |
224 | batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) | 196 | batadv_hardif_neigh_release(struct batadv_hardif_neigh_node *hardif_neigh) |
225 | { | 197 | { |
226 | if (atomic_dec_and_test(&hardif_neigh->refcount)) { | 198 | spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); |
227 | spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); | 199 | hlist_del_init_rcu(&hardif_neigh->list); |
228 | hlist_del_init_rcu(&hardif_neigh->list); | 200 | spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); |
229 | spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); | ||
230 | 201 | ||
231 | batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu); | 202 | batadv_hardif_free_ref(hardif_neigh->if_incoming); |
232 | } | 203 | kfree_rcu(hardif_neigh, rcu); |
233 | } | 204 | } |
234 | 205 | ||
235 | /** | 206 | /** |
236 | * batadv_hardif_neigh_free_ref - decrement the hardif neighbors refcounter | 207 | * batadv_hardif_neigh_free_ref - decrement the hardif neighbors refcounter |
237 | * and possibly free it | 208 | * and possibly release it |
238 | * @hardif_neigh: hardif neigh neighbor to free | 209 | * @hardif_neigh: hardif neigh neighbor to free |
239 | */ | 210 | */ |
240 | void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) | 211 | void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) |
241 | { | 212 | { |
242 | if (atomic_dec_and_test(&hardif_neigh->refcount)) { | 213 | if (atomic_dec_and_test(&hardif_neigh->refcount)) |
243 | spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); | 214 | batadv_hardif_neigh_release(hardif_neigh); |
244 | hlist_del_init_rcu(&hardif_neigh->list); | ||
245 | spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); | ||
246 | |||
247 | call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu); | ||
248 | } | ||
249 | } | 215 | } |
250 | 216 | ||
251 | /** | 217 | /** |
252 | * batadv_neigh_node_free_rcu - free the neigh_node | 218 | * batadv_neigh_node_release - release neigh_node from lists and queue for |
253 | * @rcu: rcu pointer of the neigh_node | 219 | * free after rcu grace period |
220 | * @neigh_node: neigh neighbor to free | ||
254 | */ | 221 | */ |
255 | static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) | 222 | static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node) |
256 | { | 223 | { |
257 | struct hlist_node *node_tmp; | 224 | struct hlist_node *node_tmp; |
258 | struct batadv_neigh_node *neigh_node; | ||
259 | struct batadv_hardif_neigh_node *hardif_neigh; | 225 | struct batadv_hardif_neigh_node *hardif_neigh; |
260 | struct batadv_neigh_ifinfo *neigh_ifinfo; | 226 | struct batadv_neigh_ifinfo *neigh_ifinfo; |
261 | struct batadv_algo_ops *bao; | 227 | struct batadv_algo_ops *bao; |
262 | 228 | ||
263 | neigh_node = container_of(rcu, struct batadv_neigh_node, rcu); | ||
264 | bao = neigh_node->orig_node->bat_priv->bat_algo_ops; | 229 | bao = neigh_node->orig_node->bat_priv->bat_algo_ops; |
265 | 230 | ||
266 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, | 231 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, |
267 | &neigh_node->ifinfo_list, list) { | 232 | &neigh_node->ifinfo_list, list) { |
268 | batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); | 233 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); |
269 | } | 234 | } |
270 | 235 | ||
271 | hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming, | 236 | hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming, |
272 | neigh_node->addr); | 237 | neigh_node->addr); |
273 | if (hardif_neigh) { | 238 | if (hardif_neigh) { |
274 | /* batadv_hardif_neigh_get() increases refcount too */ | 239 | /* batadv_hardif_neigh_get() increases refcount too */ |
275 | batadv_hardif_neigh_free_now(hardif_neigh); | 240 | batadv_hardif_neigh_free_ref(hardif_neigh); |
276 | batadv_hardif_neigh_free_now(hardif_neigh); | 241 | batadv_hardif_neigh_free_ref(hardif_neigh); |
277 | } | 242 | } |
278 | 243 | ||
279 | if (bao->bat_neigh_free) | 244 | if (bao->bat_neigh_free) |
280 | bao->bat_neigh_free(neigh_node); | 245 | bao->bat_neigh_free(neigh_node); |
281 | 246 | ||
282 | batadv_hardif_free_ref_now(neigh_node->if_incoming); | 247 | batadv_hardif_free_ref(neigh_node->if_incoming); |
283 | 248 | ||
284 | kfree(neigh_node); | 249 | kfree_rcu(neigh_node, rcu); |
285 | } | ||
286 | |||
287 | /** | ||
288 | * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter | ||
289 | * and possibly free it (without rcu callback) | ||
290 | * @neigh_node: neigh neighbor to free | ||
291 | */ | ||
292 | static void | ||
293 | batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node) | ||
294 | { | ||
295 | if (atomic_dec_and_test(&neigh_node->refcount)) | ||
296 | batadv_neigh_node_free_rcu(&neigh_node->rcu); | ||
297 | } | 250 | } |
298 | 251 | ||
299 | /** | 252 | /** |
300 | * batadv_neigh_node_free_ref - decrement the neighbors refcounter | 253 | * batadv_neigh_node_free_ref - decrement the neighbors refcounter |
301 | * and possibly free it | 254 | * and possibly release it |
302 | * @neigh_node: neigh neighbor to free | 255 | * @neigh_node: neigh neighbor to free |
303 | */ | 256 | */ |
304 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) | 257 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) |
305 | { | 258 | { |
306 | if (atomic_dec_and_test(&neigh_node->refcount)) | 259 | if (atomic_dec_and_test(&neigh_node->refcount)) |
307 | call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu); | 260 | batadv_neigh_node_release(neigh_node); |
308 | } | 261 | } |
309 | 262 | ||
310 | /** | 263 | /** |
@@ -733,108 +686,99 @@ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset) | |||
733 | } | 686 | } |
734 | 687 | ||
735 | /** | 688 | /** |
736 | * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object | 689 | * batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for |
737 | * @rcu: rcu pointer of the orig_ifinfo object | 690 | * free after rcu grace period |
691 | * @orig_ifinfo: the orig_ifinfo object to release | ||
738 | */ | 692 | */ |
739 | static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) | 693 | static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo) |
740 | { | 694 | { |
741 | struct batadv_orig_ifinfo *orig_ifinfo; | ||
742 | struct batadv_neigh_node *router; | 695 | struct batadv_neigh_node *router; |
743 | 696 | ||
744 | orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); | ||
745 | |||
746 | if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) | 697 | if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) |
747 | batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); | 698 | batadv_hardif_free_ref(orig_ifinfo->if_outgoing); |
748 | 699 | ||
749 | /* this is the last reference to this object */ | 700 | /* this is the last reference to this object */ |
750 | router = rcu_dereference_protected(orig_ifinfo->router, true); | 701 | router = rcu_dereference_protected(orig_ifinfo->router, true); |
751 | if (router) | 702 | if (router) |
752 | batadv_neigh_node_free_ref_now(router); | 703 | batadv_neigh_node_free_ref(router); |
753 | kfree(orig_ifinfo); | 704 | |
705 | kfree_rcu(orig_ifinfo, rcu); | ||
754 | } | 706 | } |
755 | 707 | ||
756 | /** | 708 | /** |
757 | * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free | 709 | * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly release |
758 | * the orig_ifinfo (without rcu callback) | 710 | * the orig_ifinfo |
759 | * @orig_ifinfo: the orig_ifinfo object to release | 711 | * @orig_ifinfo: the orig_ifinfo object to release |
760 | */ | 712 | */ |
761 | static void | 713 | void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) |
762 | batadv_orig_ifinfo_free_ref_now(struct batadv_orig_ifinfo *orig_ifinfo) | ||
763 | { | 714 | { |
764 | if (atomic_dec_and_test(&orig_ifinfo->refcount)) | 715 | if (atomic_dec_and_test(&orig_ifinfo->refcount)) |
765 | batadv_orig_ifinfo_free_rcu(&orig_ifinfo->rcu); | 716 | batadv_orig_ifinfo_release(orig_ifinfo); |
766 | } | 717 | } |
767 | 718 | ||
768 | /** | 719 | /** |
769 | * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free | 720 | * batadv_orig_node_free_rcu - free the orig_node |
770 | * the orig_ifinfo | 721 | * @rcu: rcu pointer of the orig_node |
771 | * @orig_ifinfo: the orig_ifinfo object to release | ||
772 | */ | 722 | */ |
773 | void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) | 723 | static void batadv_orig_node_free_rcu(struct rcu_head *rcu) |
774 | { | 724 | { |
775 | if (atomic_dec_and_test(&orig_ifinfo->refcount)) | 725 | struct batadv_orig_node *orig_node; |
776 | call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu); | 726 | |
727 | orig_node = container_of(rcu, struct batadv_orig_node, rcu); | ||
728 | |||
729 | batadv_mcast_purge_orig(orig_node); | ||
730 | |||
731 | batadv_frag_purge_orig(orig_node, NULL); | ||
732 | |||
733 | if (orig_node->bat_priv->bat_algo_ops->bat_orig_free) | ||
734 | orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node); | ||
735 | |||
736 | kfree(orig_node->tt_buff); | ||
737 | kfree(orig_node); | ||
777 | } | 738 | } |
778 | 739 | ||
779 | static void batadv_orig_node_free_rcu(struct rcu_head *rcu) | 740 | /** |
741 | * batadv_orig_node_release - release orig_node from lists and queue for | ||
742 | * free after rcu grace period | ||
743 | * @orig_node: the orig node to free | ||
744 | */ | ||
745 | static void batadv_orig_node_release(struct batadv_orig_node *orig_node) | ||
780 | { | 746 | { |
781 | struct hlist_node *node_tmp; | 747 | struct hlist_node *node_tmp; |
782 | struct batadv_neigh_node *neigh_node; | 748 | struct batadv_neigh_node *neigh_node; |
783 | struct batadv_orig_node *orig_node; | ||
784 | struct batadv_orig_ifinfo *orig_ifinfo; | 749 | struct batadv_orig_ifinfo *orig_ifinfo; |
785 | 750 | ||
786 | orig_node = container_of(rcu, struct batadv_orig_node, rcu); | ||
787 | |||
788 | spin_lock_bh(&orig_node->neigh_list_lock); | 751 | spin_lock_bh(&orig_node->neigh_list_lock); |
789 | 752 | ||
790 | /* for all neighbors towards this originator ... */ | 753 | /* for all neighbors towards this originator ... */ |
791 | hlist_for_each_entry_safe(neigh_node, node_tmp, | 754 | hlist_for_each_entry_safe(neigh_node, node_tmp, |
792 | &orig_node->neigh_list, list) { | 755 | &orig_node->neigh_list, list) { |
793 | hlist_del_rcu(&neigh_node->list); | 756 | hlist_del_rcu(&neigh_node->list); |
794 | batadv_neigh_node_free_ref_now(neigh_node); | 757 | batadv_neigh_node_free_ref(neigh_node); |
795 | } | 758 | } |
796 | 759 | ||
797 | hlist_for_each_entry_safe(orig_ifinfo, node_tmp, | 760 | hlist_for_each_entry_safe(orig_ifinfo, node_tmp, |
798 | &orig_node->ifinfo_list, list) { | 761 | &orig_node->ifinfo_list, list) { |
799 | hlist_del_rcu(&orig_ifinfo->list); | 762 | hlist_del_rcu(&orig_ifinfo->list); |
800 | batadv_orig_ifinfo_free_ref_now(orig_ifinfo); | 763 | batadv_orig_ifinfo_free_ref(orig_ifinfo); |
801 | } | 764 | } |
802 | spin_unlock_bh(&orig_node->neigh_list_lock); | 765 | spin_unlock_bh(&orig_node->neigh_list_lock); |
803 | 766 | ||
804 | batadv_mcast_purge_orig(orig_node); | ||
805 | |||
806 | /* Free nc_nodes */ | 767 | /* Free nc_nodes */ |
807 | batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); | 768 | batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); |
808 | 769 | ||
809 | batadv_frag_purge_orig(orig_node, NULL); | 770 | call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); |
810 | |||
811 | if (orig_node->bat_priv->bat_algo_ops->bat_orig_free) | ||
812 | orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node); | ||
813 | |||
814 | kfree(orig_node->tt_buff); | ||
815 | kfree(orig_node); | ||
816 | } | 771 | } |
817 | 772 | ||
818 | /** | 773 | /** |
819 | * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly | 774 | * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly |
820 | * schedule an rcu callback for freeing it | 775 | * release it |
821 | * @orig_node: the orig node to free | 776 | * @orig_node: the orig node to free |
822 | */ | 777 | */ |
823 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) | 778 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) |
824 | { | 779 | { |
825 | if (atomic_dec_and_test(&orig_node->refcount)) | 780 | if (atomic_dec_and_test(&orig_node->refcount)) |
826 | call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); | 781 | batadv_orig_node_release(orig_node); |
827 | } | ||
828 | |||
829 | /** | ||
830 | * batadv_orig_node_free_ref_now - decrement the orig node refcounter and | ||
831 | * possibly free it (without rcu callback) | ||
832 | * @orig_node: the orig node to free | ||
833 | */ | ||
834 | void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node) | ||
835 | { | ||
836 | if (atomic_dec_and_test(&orig_node->refcount)) | ||
837 | batadv_orig_node_free_rcu(&orig_node->rcu); | ||
838 | } | 782 | } |
839 | 783 | ||
840 | void batadv_originator_free(struct batadv_priv *bat_priv) | 784 | void batadv_originator_free(struct batadv_priv *bat_priv) |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 29557753d552..cf0730414ed2 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -38,7 +38,6 @@ int batadv_originator_init(struct batadv_priv *bat_priv); | |||
38 | void batadv_originator_free(struct batadv_priv *bat_priv); | 38 | void batadv_originator_free(struct batadv_priv *bat_priv); |
39 | void batadv_purge_orig_ref(struct batadv_priv *bat_priv); | 39 | void batadv_purge_orig_ref(struct batadv_priv *bat_priv); |
40 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); | 40 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); |
41 | void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); | ||
42 | struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | 41 | struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, |
43 | const u8 *addr); | 42 | const u8 *addr); |
44 | struct batadv_hardif_neigh_node * | 43 | struct batadv_hardif_neigh_node * |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index a22080c53401..cdfc85fa2743 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -240,20 +240,6 @@ int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, | |||
240 | return count; | 240 | return count; |
241 | } | 241 | } |
242 | 242 | ||
243 | static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) | ||
244 | { | ||
245 | struct batadv_tt_orig_list_entry *orig_entry; | ||
246 | |||
247 | orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu); | ||
248 | |||
249 | /* We are in an rcu callback here, therefore we cannot use | ||
250 | * batadv_orig_node_free_ref() and its call_rcu(): | ||
251 | * An rcu_barrier() wouldn't wait for that to finish | ||
252 | */ | ||
253 | batadv_orig_node_free_ref_now(orig_entry->orig_node); | ||
254 | kfree(orig_entry); | ||
255 | } | ||
256 | |||
257 | /** | 243 | /** |
258 | * batadv_tt_local_size_mod - change the size by v of the local table identified | 244 | * batadv_tt_local_size_mod - change the size by v of the local table identified |
259 | * by vid | 245 | * by vid |
@@ -349,13 +335,25 @@ static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node, | |||
349 | batadv_tt_global_size_mod(orig_node, vid, -1); | 335 | batadv_tt_global_size_mod(orig_node, vid, -1); |
350 | } | 336 | } |
351 | 337 | ||
338 | /** | ||
339 | * batadv_tt_orig_list_entry_release - release tt orig entry from lists and | ||
340 | * queue for free after rcu grace period | ||
341 | * @orig_entry: tt orig entry to be free'd | ||
342 | */ | ||
343 | static void | ||
344 | batadv_tt_orig_list_entry_release(struct batadv_tt_orig_list_entry *orig_entry) | ||
345 | { | ||
346 | batadv_orig_node_free_ref(orig_entry->orig_node); | ||
347 | kfree_rcu(orig_entry, rcu); | ||
348 | } | ||
349 | |||
352 | static void | 350 | static void |
353 | batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) | 351 | batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) |
354 | { | 352 | { |
355 | if (!atomic_dec_and_test(&orig_entry->refcount)) | 353 | if (!atomic_dec_and_test(&orig_entry->refcount)) |
356 | return; | 354 | return; |
357 | 355 | ||
358 | call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); | 356 | batadv_tt_orig_list_entry_release(orig_entry); |
359 | } | 357 | } |
360 | 358 | ||
361 | /** | 359 | /** |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index d040365ba98e..8a4cc2f7f0db 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -307,6 +307,9 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
307 | 307 | ||
308 | /* check that it's our buffer */ | 308 | /* check that it's our buffer */ |
309 | if (lowpan_is_ipv6(*skb_network_header(skb))) { | 309 | if (lowpan_is_ipv6(*skb_network_header(skb))) { |
310 | /* Pull off the 1-byte of 6lowpan header. */ | ||
311 | skb_pull(skb, 1); | ||
312 | |||
310 | /* Copy the packet so that the IPv6 header is | 313 | /* Copy the packet so that the IPv6 header is |
311 | * properly aligned. | 314 | * properly aligned. |
312 | */ | 315 | */ |
@@ -317,6 +320,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
317 | 320 | ||
318 | local_skb->protocol = htons(ETH_P_IPV6); | 321 | local_skb->protocol = htons(ETH_P_IPV6); |
319 | local_skb->pkt_type = PACKET_HOST; | 322 | local_skb->pkt_type = PACKET_HOST; |
323 | local_skb->dev = dev; | ||
320 | 324 | ||
321 | skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); | 325 | skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); |
322 | 326 | ||
@@ -335,6 +339,8 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
335 | if (!local_skb) | 339 | if (!local_skb) |
336 | goto drop; | 340 | goto drop; |
337 | 341 | ||
342 | local_skb->dev = dev; | ||
343 | |||
338 | ret = iphc_decompress(local_skb, dev, chan); | 344 | ret = iphc_decompress(local_skb, dev, chan); |
339 | if (ret < 0) { | 345 | if (ret < 0) { |
340 | kfree_skb(local_skb); | 346 | kfree_skb(local_skb); |
@@ -343,7 +349,6 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
343 | 349 | ||
344 | local_skb->protocol = htons(ETH_P_IPV6); | 350 | local_skb->protocol = htons(ETH_P_IPV6); |
345 | local_skb->pkt_type = PACKET_HOST; | 351 | local_skb->pkt_type = PACKET_HOST; |
346 | local_skb->dev = dev; | ||
347 | 352 | ||
348 | if (give_skb_to_upper(local_skb, dev) | 353 | if (give_skb_to_upper(local_skb, dev) |
349 | != NET_RX_SUCCESS) { | 354 | != NET_RX_SUCCESS) { |
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 41b5f3813f02..c78ee2dc9323 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -688,21 +688,29 @@ static u8 update_white_list(struct hci_request *req) | |||
688 | * command to remove it from the controller. | 688 | * command to remove it from the controller. |
689 | */ | 689 | */ |
690 | list_for_each_entry(b, &hdev->le_white_list, list) { | 690 | list_for_each_entry(b, &hdev->le_white_list, list) { |
691 | struct hci_cp_le_del_from_white_list cp; | 691 | /* If the device is neither in pend_le_conns nor |
692 | * pend_le_reports then remove it from the whitelist. | ||
693 | */ | ||
694 | if (!hci_pend_le_action_lookup(&hdev->pend_le_conns, | ||
695 | &b->bdaddr, b->bdaddr_type) && | ||
696 | !hci_pend_le_action_lookup(&hdev->pend_le_reports, | ||
697 | &b->bdaddr, b->bdaddr_type)) { | ||
698 | struct hci_cp_le_del_from_white_list cp; | ||
699 | |||
700 | cp.bdaddr_type = b->bdaddr_type; | ||
701 | bacpy(&cp.bdaddr, &b->bdaddr); | ||
692 | 702 | ||
693 | if (hci_pend_le_action_lookup(&hdev->pend_le_conns, | 703 | hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, |
694 | &b->bdaddr, b->bdaddr_type) || | 704 | sizeof(cp), &cp); |
695 | hci_pend_le_action_lookup(&hdev->pend_le_reports, | ||
696 | &b->bdaddr, b->bdaddr_type)) { | ||
697 | white_list_entries++; | ||
698 | continue; | 705 | continue; |
699 | } | 706 | } |
700 | 707 | ||
701 | cp.bdaddr_type = b->bdaddr_type; | 708 | if (hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) { |
702 | bacpy(&cp.bdaddr, &b->bdaddr); | 709 | /* White list can not be used with RPAs */ |
710 | return 0x00; | ||
711 | } | ||
703 | 712 | ||
704 | hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, | 713 | white_list_entries++; |
705 | sizeof(cp), &cp); | ||
706 | } | 714 | } |
707 | 715 | ||
708 | /* Since all no longer valid white list entries have been | 716 | /* Since all no longer valid white list entries have been |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 39a5149f3010..eb4f5f24cbe3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -197,10 +197,20 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) | |||
197 | chan->sport = psm; | 197 | chan->sport = psm; |
198 | err = 0; | 198 | err = 0; |
199 | } else { | 199 | } else { |
200 | u16 p; | 200 | u16 p, start, end, incr; |
201 | |||
202 | if (chan->src_type == BDADDR_BREDR) { | ||
203 | start = L2CAP_PSM_DYN_START; | ||
204 | end = L2CAP_PSM_AUTO_END; | ||
205 | incr = 2; | ||
206 | } else { | ||
207 | start = L2CAP_PSM_LE_DYN_START; | ||
208 | end = L2CAP_PSM_LE_DYN_END; | ||
209 | incr = 1; | ||
210 | } | ||
201 | 211 | ||
202 | err = -EINVAL; | 212 | err = -EINVAL; |
203 | for (p = 0x1001; p < 0x1100; p += 2) | 213 | for (p = start; p <= end; p += incr) |
204 | if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { | 214 | if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { |
205 | chan->psm = cpu_to_le16(p); | 215 | chan->psm = cpu_to_le16(p); |
206 | chan->sport = cpu_to_le16(p); | 216 | chan->sport = cpu_to_le16(p); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1bb551527044..e4cae72895a7 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -58,7 +58,7 @@ static int l2cap_validate_bredr_psm(u16 psm) | |||
58 | return -EINVAL; | 58 | return -EINVAL; |
59 | 59 | ||
60 | /* Restrict usage of well-known PSMs */ | 60 | /* Restrict usage of well-known PSMs */ |
61 | if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) | 61 | if (psm < L2CAP_PSM_DYN_START && !capable(CAP_NET_BIND_SERVICE)) |
62 | return -EACCES; | 62 | return -EACCES; |
63 | 63 | ||
64 | return 0; | 64 | return 0; |
@@ -67,11 +67,11 @@ static int l2cap_validate_bredr_psm(u16 psm) | |||
67 | static int l2cap_validate_le_psm(u16 psm) | 67 | static int l2cap_validate_le_psm(u16 psm) |
68 | { | 68 | { |
69 | /* Valid LE_PSM ranges are defined only until 0x00ff */ | 69 | /* Valid LE_PSM ranges are defined only until 0x00ff */ |
70 | if (psm > 0x00ff) | 70 | if (psm > L2CAP_PSM_LE_DYN_END) |
71 | return -EINVAL; | 71 | return -EINVAL; |
72 | 72 | ||
73 | /* Restrict fixed, SIG assigned PSM values to CAP_NET_BIND_SERVICE */ | 73 | /* Restrict fixed, SIG assigned PSM values to CAP_NET_BIND_SERVICE */ |
74 | if (psm <= 0x007f && !capable(CAP_NET_BIND_SERVICE)) | 74 | if (psm < L2CAP_PSM_LE_DYN_START && !capable(CAP_NET_BIND_SERVICE)) |
75 | return -EACCES; | 75 | return -EACCES; |
76 | 76 | ||
77 | return 0; | 77 | return 0; |
@@ -125,6 +125,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
125 | goto done; | 125 | goto done; |
126 | } | 126 | } |
127 | 127 | ||
128 | bacpy(&chan->src, &la.l2_bdaddr); | ||
129 | chan->src_type = la.l2_bdaddr_type; | ||
130 | |||
128 | if (la.l2_cid) | 131 | if (la.l2_cid) |
129 | err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid)); | 132 | err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid)); |
130 | else | 133 | else |
@@ -156,9 +159,6 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
156 | break; | 159 | break; |
157 | } | 160 | } |
158 | 161 | ||
159 | bacpy(&chan->src, &la.l2_bdaddr); | ||
160 | chan->src_type = la.l2_bdaddr_type; | ||
161 | |||
162 | if (chan->psm && bdaddr_type_is_le(chan->src_type)) | 162 | if (chan->psm && bdaddr_type_is_le(chan->src_type)) |
163 | chan->mode = L2CAP_MODE_LE_FLOWCTL; | 163 | chan->mode = L2CAP_MODE_LE_FLOWCTL; |
164 | 164 | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index ffed8a1d4f27..4b175df35184 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -1072,22 +1072,6 @@ static void smp_notify_keys(struct l2cap_conn *conn) | |||
1072 | hcon->dst_type = smp->remote_irk->addr_type; | 1072 | hcon->dst_type = smp->remote_irk->addr_type; |
1073 | queue_work(hdev->workqueue, &conn->id_addr_update_work); | 1073 | queue_work(hdev->workqueue, &conn->id_addr_update_work); |
1074 | } | 1074 | } |
1075 | |||
1076 | /* When receiving an indentity resolving key for | ||
1077 | * a remote device that does not use a resolvable | ||
1078 | * private address, just remove the key so that | ||
1079 | * it is possible to use the controller white | ||
1080 | * list for scanning. | ||
1081 | * | ||
1082 | * Userspace will have been told to not store | ||
1083 | * this key at this point. So it is safe to | ||
1084 | * just remove it. | ||
1085 | */ | ||
1086 | if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) { | ||
1087 | list_del_rcu(&smp->remote_irk->list); | ||
1088 | kfree_rcu(smp->remote_irk, rcu); | ||
1089 | smp->remote_irk = NULL; | ||
1090 | } | ||
1091 | } | 1075 | } |
1092 | 1076 | ||
1093 | if (smp->csrk) { | 1077 | if (smp->csrk) { |
diff --git a/net/bridge/br.c b/net/bridge/br.c index a1abe4936fe1..3addc05b9a16 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -121,6 +121,7 @@ static struct notifier_block br_device_notifier = { | |||
121 | .notifier_call = br_device_event | 121 | .notifier_call = br_device_event |
122 | }; | 122 | }; |
123 | 123 | ||
124 | /* called with RTNL */ | ||
124 | static int br_switchdev_event(struct notifier_block *unused, | 125 | static int br_switchdev_event(struct notifier_block *unused, |
125 | unsigned long event, void *ptr) | 126 | unsigned long event, void *ptr) |
126 | { | 127 | { |
@@ -130,7 +131,6 @@ static int br_switchdev_event(struct notifier_block *unused, | |||
130 | struct switchdev_notifier_fdb_info *fdb_info; | 131 | struct switchdev_notifier_fdb_info *fdb_info; |
131 | int err = NOTIFY_DONE; | 132 | int err = NOTIFY_DONE; |
132 | 133 | ||
133 | rtnl_lock(); | ||
134 | p = br_port_get_rtnl(dev); | 134 | p = br_port_get_rtnl(dev); |
135 | if (!p) | 135 | if (!p) |
136 | goto out; | 136 | goto out; |
@@ -155,7 +155,6 @@ static int br_switchdev_event(struct notifier_block *unused, | |||
155 | } | 155 | } |
156 | 156 | ||
157 | out: | 157 | out: |
158 | rtnl_unlock(); | ||
159 | return err; | 158 | return err; |
160 | } | 159 | } |
161 | 160 | ||
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 10d87753ed87..9e43a315e662 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -152,7 +152,6 @@ static int process_one_ticket(struct ceph_auth_client *ac, | |||
152 | void *ticket_buf = NULL; | 152 | void *ticket_buf = NULL; |
153 | void *tp, *tpend; | 153 | void *tp, *tpend; |
154 | void **ptp; | 154 | void **ptp; |
155 | struct ceph_timespec new_validity; | ||
156 | struct ceph_crypto_key new_session_key; | 155 | struct ceph_crypto_key new_session_key; |
157 | struct ceph_buffer *new_ticket_blob; | 156 | struct ceph_buffer *new_ticket_blob; |
158 | unsigned long new_expires, new_renew_after; | 157 | unsigned long new_expires, new_renew_after; |
@@ -193,8 +192,8 @@ static int process_one_ticket(struct ceph_auth_client *ac, | |||
193 | if (ret) | 192 | if (ret) |
194 | goto out; | 193 | goto out; |
195 | 194 | ||
196 | ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); | 195 | ceph_decode_timespec(&validity, dp); |
197 | ceph_decode_timespec(&validity, &new_validity); | 196 | dp += sizeof(struct ceph_timespec); |
198 | new_expires = get_seconds() + validity.tv_sec; | 197 | new_expires = get_seconds() + validity.tv_sec; |
199 | new_renew_after = new_expires - (validity.tv_sec / 4); | 198 | new_renew_after = new_expires - (validity.tv_sec / 4); |
200 | dout(" expires=%lu renew_after=%lu\n", new_expires, | 199 | dout(" expires=%lu renew_after=%lu\n", new_expires, |
@@ -233,10 +232,10 @@ static int process_one_ticket(struct ceph_auth_client *ac, | |||
233 | ceph_buffer_put(th->ticket_blob); | 232 | ceph_buffer_put(th->ticket_blob); |
234 | th->session_key = new_session_key; | 233 | th->session_key = new_session_key; |
235 | th->ticket_blob = new_ticket_blob; | 234 | th->ticket_blob = new_ticket_blob; |
236 | th->validity = new_validity; | ||
237 | th->secret_id = new_secret_id; | 235 | th->secret_id = new_secret_id; |
238 | th->expires = new_expires; | 236 | th->expires = new_expires; |
239 | th->renew_after = new_renew_after; | 237 | th->renew_after = new_renew_after; |
238 | th->have_key = true; | ||
240 | dout(" got ticket service %d (%s) secret_id %lld len %d\n", | 239 | dout(" got ticket service %d (%s) secret_id %lld len %d\n", |
241 | type, ceph_entity_type_name(type), th->secret_id, | 240 | type, ceph_entity_type_name(type), th->secret_id, |
242 | (int)th->ticket_blob->vec.iov_len); | 241 | (int)th->ticket_blob->vec.iov_len); |
@@ -384,6 +383,24 @@ bad: | |||
384 | return -ERANGE; | 383 | return -ERANGE; |
385 | } | 384 | } |
386 | 385 | ||
386 | static bool need_key(struct ceph_x_ticket_handler *th) | ||
387 | { | ||
388 | if (!th->have_key) | ||
389 | return true; | ||
390 | |||
391 | return get_seconds() >= th->renew_after; | ||
392 | } | ||
393 | |||
394 | static bool have_key(struct ceph_x_ticket_handler *th) | ||
395 | { | ||
396 | if (th->have_key) { | ||
397 | if (get_seconds() >= th->expires) | ||
398 | th->have_key = false; | ||
399 | } | ||
400 | |||
401 | return th->have_key; | ||
402 | } | ||
403 | |||
387 | static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed) | 404 | static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed) |
388 | { | 405 | { |
389 | int want = ac->want_keys; | 406 | int want = ac->want_keys; |
@@ -402,20 +419,18 @@ static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed) | |||
402 | continue; | 419 | continue; |
403 | 420 | ||
404 | th = get_ticket_handler(ac, service); | 421 | th = get_ticket_handler(ac, service); |
405 | |||
406 | if (IS_ERR(th)) { | 422 | if (IS_ERR(th)) { |
407 | *pneed |= service; | 423 | *pneed |= service; |
408 | continue; | 424 | continue; |
409 | } | 425 | } |
410 | 426 | ||
411 | if (get_seconds() >= th->renew_after) | 427 | if (need_key(th)) |
412 | *pneed |= service; | 428 | *pneed |= service; |
413 | if (get_seconds() >= th->expires) | 429 | if (!have_key(th)) |
414 | xi->have_keys &= ~service; | 430 | xi->have_keys &= ~service; |
415 | } | 431 | } |
416 | } | 432 | } |
417 | 433 | ||
418 | |||
419 | static int ceph_x_build_request(struct ceph_auth_client *ac, | 434 | static int ceph_x_build_request(struct ceph_auth_client *ac, |
420 | void *buf, void *end) | 435 | void *buf, void *end) |
421 | { | 436 | { |
@@ -667,14 +682,26 @@ static void ceph_x_destroy(struct ceph_auth_client *ac) | |||
667 | ac->private = NULL; | 682 | ac->private = NULL; |
668 | } | 683 | } |
669 | 684 | ||
670 | static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac, | 685 | static void invalidate_ticket(struct ceph_auth_client *ac, int peer_type) |
671 | int peer_type) | ||
672 | { | 686 | { |
673 | struct ceph_x_ticket_handler *th; | 687 | struct ceph_x_ticket_handler *th; |
674 | 688 | ||
675 | th = get_ticket_handler(ac, peer_type); | 689 | th = get_ticket_handler(ac, peer_type); |
676 | if (!IS_ERR(th)) | 690 | if (!IS_ERR(th)) |
677 | memset(&th->validity, 0, sizeof(th->validity)); | 691 | th->have_key = false; |
692 | } | ||
693 | |||
694 | static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac, | ||
695 | int peer_type) | ||
696 | { | ||
697 | /* | ||
698 | * We are to invalidate a service ticket in the hopes of | ||
699 | * getting a new, hopefully more valid, one. But, we won't get | ||
700 | * it unless our AUTH ticket is good, so invalidate AUTH ticket | ||
701 | * as well, just in case. | ||
702 | */ | ||
703 | invalidate_ticket(ac, peer_type); | ||
704 | invalidate_ticket(ac, CEPH_ENTITY_TYPE_AUTH); | ||
678 | } | 705 | } |
679 | 706 | ||
680 | static int calcu_signature(struct ceph_x_authorizer *au, | 707 | static int calcu_signature(struct ceph_x_authorizer *au, |
diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h index e8b7c6917d47..40b1a3cf7397 100644 --- a/net/ceph/auth_x.h +++ b/net/ceph/auth_x.h | |||
@@ -16,7 +16,7 @@ struct ceph_x_ticket_handler { | |||
16 | unsigned int service; | 16 | unsigned int service; |
17 | 17 | ||
18 | struct ceph_crypto_key session_key; | 18 | struct ceph_crypto_key session_key; |
19 | struct ceph_timespec validity; | 19 | bool have_key; |
20 | 20 | ||
21 | u64 secret_id; | 21 | u64 secret_id; |
22 | struct ceph_buffer *ticket_blob; | 22 | struct ceph_buffer *ticket_blob; |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9981039ef4ff..9cfedf565f5b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -23,9 +23,6 @@ | |||
23 | #include <linux/ceph/pagelist.h> | 23 | #include <linux/ceph/pagelist.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | 25 | ||
26 | #define list_entry_next(pos, member) \ | ||
27 | list_entry(pos->member.next, typeof(*pos), member) | ||
28 | |||
29 | /* | 26 | /* |
30 | * Ceph uses the messenger to exchange ceph_msg messages with other | 27 | * Ceph uses the messenger to exchange ceph_msg messages with other |
31 | * hosts in the system. The messenger provides ordered and reliable | 28 | * hosts in the system. The messenger provides ordered and reliable |
@@ -672,6 +669,8 @@ static void reset_connection(struct ceph_connection *con) | |||
672 | } | 669 | } |
673 | con->in_seq = 0; | 670 | con->in_seq = 0; |
674 | con->in_seq_acked = 0; | 671 | con->in_seq_acked = 0; |
672 | |||
673 | con->out_skip = 0; | ||
675 | } | 674 | } |
676 | 675 | ||
677 | /* | 676 | /* |
@@ -771,6 +770,8 @@ static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt) | |||
771 | 770 | ||
772 | static void con_out_kvec_reset(struct ceph_connection *con) | 771 | static void con_out_kvec_reset(struct ceph_connection *con) |
773 | { | 772 | { |
773 | BUG_ON(con->out_skip); | ||
774 | |||
774 | con->out_kvec_left = 0; | 775 | con->out_kvec_left = 0; |
775 | con->out_kvec_bytes = 0; | 776 | con->out_kvec_bytes = 0; |
776 | con->out_kvec_cur = &con->out_kvec[0]; | 777 | con->out_kvec_cur = &con->out_kvec[0]; |
@@ -779,9 +780,9 @@ static void con_out_kvec_reset(struct ceph_connection *con) | |||
779 | static void con_out_kvec_add(struct ceph_connection *con, | 780 | static void con_out_kvec_add(struct ceph_connection *con, |
780 | size_t size, void *data) | 781 | size_t size, void *data) |
781 | { | 782 | { |
782 | int index; | 783 | int index = con->out_kvec_left; |
783 | 784 | ||
784 | index = con->out_kvec_left; | 785 | BUG_ON(con->out_skip); |
785 | BUG_ON(index >= ARRAY_SIZE(con->out_kvec)); | 786 | BUG_ON(index >= ARRAY_SIZE(con->out_kvec)); |
786 | 787 | ||
787 | con->out_kvec[index].iov_len = size; | 788 | con->out_kvec[index].iov_len = size; |
@@ -790,6 +791,27 @@ static void con_out_kvec_add(struct ceph_connection *con, | |||
790 | con->out_kvec_bytes += size; | 791 | con->out_kvec_bytes += size; |
791 | } | 792 | } |
792 | 793 | ||
794 | /* | ||
795 | * Chop off a kvec from the end. Return residual number of bytes for | ||
796 | * that kvec, i.e. how many bytes would have been written if the kvec | ||
797 | * hadn't been nuked. | ||
798 | */ | ||
799 | static int con_out_kvec_skip(struct ceph_connection *con) | ||
800 | { | ||
801 | int off = con->out_kvec_cur - con->out_kvec; | ||
802 | int skip = 0; | ||
803 | |||
804 | if (con->out_kvec_bytes > 0) { | ||
805 | skip = con->out_kvec[off + con->out_kvec_left - 1].iov_len; | ||
806 | BUG_ON(con->out_kvec_bytes < skip); | ||
807 | BUG_ON(!con->out_kvec_left); | ||
808 | con->out_kvec_bytes -= skip; | ||
809 | con->out_kvec_left--; | ||
810 | } | ||
811 | |||
812 | return skip; | ||
813 | } | ||
814 | |||
793 | #ifdef CONFIG_BLOCK | 815 | #ifdef CONFIG_BLOCK |
794 | 816 | ||
795 | /* | 817 | /* |
@@ -1042,7 +1064,7 @@ static bool ceph_msg_data_pagelist_advance(struct ceph_msg_data_cursor *cursor, | |||
1042 | /* Move on to the next page */ | 1064 | /* Move on to the next page */ |
1043 | 1065 | ||
1044 | BUG_ON(list_is_last(&cursor->page->lru, &pagelist->head)); | 1066 | BUG_ON(list_is_last(&cursor->page->lru, &pagelist->head)); |
1045 | cursor->page = list_entry_next(cursor->page, lru); | 1067 | cursor->page = list_next_entry(cursor->page, lru); |
1046 | cursor->last_piece = cursor->resid <= PAGE_SIZE; | 1068 | cursor->last_piece = cursor->resid <= PAGE_SIZE; |
1047 | 1069 | ||
1048 | return true; | 1070 | return true; |
@@ -1166,7 +1188,7 @@ static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor, | |||
1166 | if (!cursor->resid && cursor->total_resid) { | 1188 | if (!cursor->resid && cursor->total_resid) { |
1167 | WARN_ON(!cursor->last_piece); | 1189 | WARN_ON(!cursor->last_piece); |
1168 | BUG_ON(list_is_last(&cursor->data->links, cursor->data_head)); | 1190 | BUG_ON(list_is_last(&cursor->data->links, cursor->data_head)); |
1169 | cursor->data = list_entry_next(cursor->data, links); | 1191 | cursor->data = list_next_entry(cursor->data, links); |
1170 | __ceph_msg_data_cursor_init(cursor); | 1192 | __ceph_msg_data_cursor_init(cursor); |
1171 | new_piece = true; | 1193 | new_piece = true; |
1172 | } | 1194 | } |
@@ -1197,7 +1219,6 @@ static void prepare_write_message_footer(struct ceph_connection *con) | |||
1197 | m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; | 1219 | m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; |
1198 | 1220 | ||
1199 | dout("prepare_write_message_footer %p\n", con); | 1221 | dout("prepare_write_message_footer %p\n", con); |
1200 | con->out_kvec_is_msg = true; | ||
1201 | con->out_kvec[v].iov_base = &m->footer; | 1222 | con->out_kvec[v].iov_base = &m->footer; |
1202 | if (con->peer_features & CEPH_FEATURE_MSG_AUTH) { | 1223 | if (con->peer_features & CEPH_FEATURE_MSG_AUTH) { |
1203 | if (con->ops->sign_message) | 1224 | if (con->ops->sign_message) |
@@ -1225,7 +1246,6 @@ static void prepare_write_message(struct ceph_connection *con) | |||
1225 | u32 crc; | 1246 | u32 crc; |
1226 | 1247 | ||
1227 | con_out_kvec_reset(con); | 1248 | con_out_kvec_reset(con); |
1228 | con->out_kvec_is_msg = true; | ||
1229 | con->out_msg_done = false; | 1249 | con->out_msg_done = false; |
1230 | 1250 | ||
1231 | /* Sneak an ack in there first? If we can get it into the same | 1251 | /* Sneak an ack in there first? If we can get it into the same |
@@ -1265,18 +1285,19 @@ static void prepare_write_message(struct ceph_connection *con) | |||
1265 | 1285 | ||
1266 | /* tag + hdr + front + middle */ | 1286 | /* tag + hdr + front + middle */ |
1267 | con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); | 1287 | con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); |
1268 | con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); | 1288 | con_out_kvec_add(con, sizeof(con->out_hdr), &con->out_hdr); |
1269 | con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); | 1289 | con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); |
1270 | 1290 | ||
1271 | if (m->middle) | 1291 | if (m->middle) |
1272 | con_out_kvec_add(con, m->middle->vec.iov_len, | 1292 | con_out_kvec_add(con, m->middle->vec.iov_len, |
1273 | m->middle->vec.iov_base); | 1293 | m->middle->vec.iov_base); |
1274 | 1294 | ||
1275 | /* fill in crc (except data pages), footer */ | 1295 | /* fill in hdr crc and finalize hdr */ |
1276 | crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); | 1296 | crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); |
1277 | con->out_msg->hdr.crc = cpu_to_le32(crc); | 1297 | con->out_msg->hdr.crc = cpu_to_le32(crc); |
1278 | con->out_msg->footer.flags = 0; | 1298 | memcpy(&con->out_hdr, &con->out_msg->hdr, sizeof(con->out_hdr)); |
1279 | 1299 | ||
1300 | /* fill in front and middle crc, footer */ | ||
1280 | crc = crc32c(0, m->front.iov_base, m->front.iov_len); | 1301 | crc = crc32c(0, m->front.iov_base, m->front.iov_len); |
1281 | con->out_msg->footer.front_crc = cpu_to_le32(crc); | 1302 | con->out_msg->footer.front_crc = cpu_to_le32(crc); |
1282 | if (m->middle) { | 1303 | if (m->middle) { |
@@ -1288,6 +1309,7 @@ static void prepare_write_message(struct ceph_connection *con) | |||
1288 | dout("%s front_crc %u middle_crc %u\n", __func__, | 1309 | dout("%s front_crc %u middle_crc %u\n", __func__, |
1289 | le32_to_cpu(con->out_msg->footer.front_crc), | 1310 | le32_to_cpu(con->out_msg->footer.front_crc), |
1290 | le32_to_cpu(con->out_msg->footer.middle_crc)); | 1311 | le32_to_cpu(con->out_msg->footer.middle_crc)); |
1312 | con->out_msg->footer.flags = 0; | ||
1291 | 1313 | ||
1292 | /* is there a data payload? */ | 1314 | /* is there a data payload? */ |
1293 | con->out_msg->footer.data_crc = 0; | 1315 | con->out_msg->footer.data_crc = 0; |
@@ -1492,7 +1514,6 @@ static int write_partial_kvec(struct ceph_connection *con) | |||
1492 | } | 1514 | } |
1493 | } | 1515 | } |
1494 | con->out_kvec_left = 0; | 1516 | con->out_kvec_left = 0; |
1495 | con->out_kvec_is_msg = false; | ||
1496 | ret = 1; | 1517 | ret = 1; |
1497 | out: | 1518 | out: |
1498 | dout("write_partial_kvec %p %d left in %d kvecs ret = %d\n", con, | 1519 | dout("write_partial_kvec %p %d left in %d kvecs ret = %d\n", con, |
@@ -1584,6 +1605,7 @@ static int write_partial_skip(struct ceph_connection *con) | |||
1584 | { | 1605 | { |
1585 | int ret; | 1606 | int ret; |
1586 | 1607 | ||
1608 | dout("%s %p %d left\n", __func__, con, con->out_skip); | ||
1587 | while (con->out_skip > 0) { | 1609 | while (con->out_skip > 0) { |
1588 | size_t size = min(con->out_skip, (int) PAGE_CACHE_SIZE); | 1610 | size_t size = min(con->out_skip, (int) PAGE_CACHE_SIZE); |
1589 | 1611 | ||
@@ -2506,13 +2528,13 @@ more: | |||
2506 | 2528 | ||
2507 | more_kvec: | 2529 | more_kvec: |
2508 | /* kvec data queued? */ | 2530 | /* kvec data queued? */ |
2509 | if (con->out_skip) { | 2531 | if (con->out_kvec_left) { |
2510 | ret = write_partial_skip(con); | 2532 | ret = write_partial_kvec(con); |
2511 | if (ret <= 0) | 2533 | if (ret <= 0) |
2512 | goto out; | 2534 | goto out; |
2513 | } | 2535 | } |
2514 | if (con->out_kvec_left) { | 2536 | if (con->out_skip) { |
2515 | ret = write_partial_kvec(con); | 2537 | ret = write_partial_skip(con); |
2516 | if (ret <= 0) | 2538 | if (ret <= 0) |
2517 | goto out; | 2539 | goto out; |
2518 | } | 2540 | } |
@@ -2805,13 +2827,17 @@ static bool con_backoff(struct ceph_connection *con) | |||
2805 | 2827 | ||
2806 | static void con_fault_finish(struct ceph_connection *con) | 2828 | static void con_fault_finish(struct ceph_connection *con) |
2807 | { | 2829 | { |
2830 | dout("%s %p\n", __func__, con); | ||
2831 | |||
2808 | /* | 2832 | /* |
2809 | * in case we faulted due to authentication, invalidate our | 2833 | * in case we faulted due to authentication, invalidate our |
2810 | * current tickets so that we can get new ones. | 2834 | * current tickets so that we can get new ones. |
2811 | */ | 2835 | */ |
2812 | if (con->auth_retry && con->ops->invalidate_authorizer) { | 2836 | if (con->auth_retry) { |
2813 | dout("calling invalidate_authorizer()\n"); | 2837 | dout("auth_retry %d, invalidating\n", con->auth_retry); |
2814 | con->ops->invalidate_authorizer(con); | 2838 | if (con->ops->invalidate_authorizer) |
2839 | con->ops->invalidate_authorizer(con); | ||
2840 | con->auth_retry = 0; | ||
2815 | } | 2841 | } |
2816 | 2842 | ||
2817 | if (con->ops->fault) | 2843 | if (con->ops->fault) |
@@ -3050,16 +3076,31 @@ void ceph_msg_revoke(struct ceph_msg *msg) | |||
3050 | ceph_msg_put(msg); | 3076 | ceph_msg_put(msg); |
3051 | } | 3077 | } |
3052 | if (con->out_msg == msg) { | 3078 | if (con->out_msg == msg) { |
3053 | dout("%s %p msg %p - was sending\n", __func__, con, msg); | 3079 | BUG_ON(con->out_skip); |
3054 | con->out_msg = NULL; | 3080 | /* footer */ |
3055 | if (con->out_kvec_is_msg) { | 3081 | if (con->out_msg_done) { |
3056 | con->out_skip = con->out_kvec_bytes; | 3082 | con->out_skip += con_out_kvec_skip(con); |
3057 | con->out_kvec_is_msg = false; | 3083 | } else { |
3084 | BUG_ON(!msg->data_length); | ||
3085 | if (con->peer_features & CEPH_FEATURE_MSG_AUTH) | ||
3086 | con->out_skip += sizeof(msg->footer); | ||
3087 | else | ||
3088 | con->out_skip += sizeof(msg->old_footer); | ||
3058 | } | 3089 | } |
3090 | /* data, middle, front */ | ||
3091 | if (msg->data_length) | ||
3092 | con->out_skip += msg->cursor.total_resid; | ||
3093 | if (msg->middle) | ||
3094 | con->out_skip += con_out_kvec_skip(con); | ||
3095 | con->out_skip += con_out_kvec_skip(con); | ||
3096 | |||
3097 | dout("%s %p msg %p - was sending, will write %d skip %d\n", | ||
3098 | __func__, con, msg, con->out_kvec_bytes, con->out_skip); | ||
3059 | msg->hdr.seq = 0; | 3099 | msg->hdr.seq = 0; |
3060 | 3100 | con->out_msg = NULL; | |
3061 | ceph_msg_put(msg); | 3101 | ceph_msg_put(msg); |
3062 | } | 3102 | } |
3103 | |||
3063 | mutex_unlock(&con->mutex); | 3104 | mutex_unlock(&con->mutex); |
3064 | } | 3105 | } |
3065 | 3106 | ||
@@ -3361,9 +3402,7 @@ static void ceph_msg_free(struct ceph_msg *m) | |||
3361 | static void ceph_msg_release(struct kref *kref) | 3402 | static void ceph_msg_release(struct kref *kref) |
3362 | { | 3403 | { |
3363 | struct ceph_msg *m = container_of(kref, struct ceph_msg, kref); | 3404 | struct ceph_msg *m = container_of(kref, struct ceph_msg, kref); |
3364 | LIST_HEAD(data); | 3405 | struct ceph_msg_data *data, *next; |
3365 | struct list_head *links; | ||
3366 | struct list_head *next; | ||
3367 | 3406 | ||
3368 | dout("%s %p\n", __func__, m); | 3407 | dout("%s %p\n", __func__, m); |
3369 | WARN_ON(!list_empty(&m->list_head)); | 3408 | WARN_ON(!list_empty(&m->list_head)); |
@@ -3376,12 +3415,8 @@ static void ceph_msg_release(struct kref *kref) | |||
3376 | m->middle = NULL; | 3415 | m->middle = NULL; |
3377 | } | 3416 | } |
3378 | 3417 | ||
3379 | list_splice_init(&m->data, &data); | 3418 | list_for_each_entry_safe(data, next, &m->data, links) { |
3380 | list_for_each_safe(links, next, &data) { | 3419 | list_del_init(&data->links); |
3381 | struct ceph_msg_data *data; | ||
3382 | |||
3383 | data = list_entry(links, struct ceph_msg_data, links); | ||
3384 | list_del_init(links); | ||
3385 | ceph_msg_data_destroy(data); | 3420 | ceph_msg_data_destroy(data); |
3386 | } | 3421 | } |
3387 | m->data_length = 0; | 3422 | m->data_length = 0; |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index edda01626a45..de85dddc3dc0 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -364,10 +364,6 @@ static bool have_debugfs_info(struct ceph_mon_client *monc) | |||
364 | return monc->client->have_fsid && monc->auth->global_id > 0; | 364 | return monc->client->have_fsid && monc->auth->global_id > 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | /* | ||
368 | * The monitor responds with mount ack indicate mount success. The | ||
369 | * included client ticket allows the client to talk to MDSs and OSDs. | ||
370 | */ | ||
371 | static void ceph_monc_handle_map(struct ceph_mon_client *monc, | 367 | static void ceph_monc_handle_map(struct ceph_mon_client *monc, |
372 | struct ceph_msg *msg) | 368 | struct ceph_msg *msg) |
373 | { | 369 | { |
diff --git a/net/core/dev.c b/net/core/dev.c index cc9e3652cf93..8cba3d852f25 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4351,6 +4351,7 @@ static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb) | |||
4351 | 4351 | ||
4352 | diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev; | 4352 | diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev; |
4353 | diffs |= p->vlan_tci ^ skb->vlan_tci; | 4353 | diffs |= p->vlan_tci ^ skb->vlan_tci; |
4354 | diffs |= skb_metadata_dst_cmp(p, skb); | ||
4354 | if (maclen == ETH_HLEN) | 4355 | if (maclen == ETH_HLEN) |
4355 | diffs |= compare_ether_header(skb_mac_header(p), | 4356 | diffs |= compare_ether_header(skb_mac_header(p), |
4356 | skb_mac_header(skb)); | 4357 | skb_mac_header(skb)); |
@@ -4548,10 +4549,12 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) | |||
4548 | break; | 4549 | break; |
4549 | 4550 | ||
4550 | case GRO_MERGED_FREE: | 4551 | case GRO_MERGED_FREE: |
4551 | if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) | 4552 | if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) { |
4553 | skb_dst_drop(skb); | ||
4552 | kmem_cache_free(skbuff_head_cache, skb); | 4554 | kmem_cache_free(skbuff_head_cache, skb); |
4553 | else | 4555 | } else { |
4554 | __kfree_skb(skb); | 4556 | __kfree_skb(skb); |
4557 | } | ||
4555 | break; | 4558 | break; |
4556 | 4559 | ||
4557 | case GRO_HELD: | 4560 | case GRO_HELD: |
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c index 1df98c557440..e92b759d906c 100644 --- a/net/core/sock_reuseport.c +++ b/net/core/sock_reuseport.c | |||
@@ -93,10 +93,17 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse) | |||
93 | * @sk2: Socket belonging to the existing reuseport group. | 93 | * @sk2: Socket belonging to the existing reuseport group. |
94 | * May return ENOMEM and not add socket to group under memory pressure. | 94 | * May return ENOMEM and not add socket to group under memory pressure. |
95 | */ | 95 | */ |
96 | int reuseport_add_sock(struct sock *sk, const struct sock *sk2) | 96 | int reuseport_add_sock(struct sock *sk, struct sock *sk2) |
97 | { | 97 | { |
98 | struct sock_reuseport *reuse; | 98 | struct sock_reuseport *reuse; |
99 | 99 | ||
100 | if (!rcu_access_pointer(sk2->sk_reuseport_cb)) { | ||
101 | int err = reuseport_alloc(sk2); | ||
102 | |||
103 | if (err) | ||
104 | return err; | ||
105 | } | ||
106 | |||
100 | spin_lock_bh(&reuseport_lock); | 107 | spin_lock_bh(&reuseport_lock); |
101 | reuse = rcu_dereference_protected(sk2->sk_reuseport_cb, | 108 | reuse = rcu_dereference_protected(sk2->sk_reuseport_cb, |
102 | lockdep_is_held(&reuseport_lock)), | 109 | lockdep_is_held(&reuseport_lock)), |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index c22920525e5d..775824720b6b 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -353,6 +353,7 @@ config INET_ESP | |||
353 | select CRYPTO_CBC | 353 | select CRYPTO_CBC |
354 | select CRYPTO_SHA1 | 354 | select CRYPTO_SHA1 |
355 | select CRYPTO_DES | 355 | select CRYPTO_DES |
356 | select CRYPTO_ECHAINIV | ||
356 | ---help--- | 357 | ---help--- |
357 | Support for IPsec ESP. | 358 | Support for IPsec ESP. |
358 | 359 | ||
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index c29809f765dc..62c049b647e9 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -56,7 +56,6 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o | |||
56 | obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o | 56 | obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o |
57 | obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o | 57 | obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o |
58 | obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o | 58 | obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o |
59 | obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o | ||
60 | obj-$(CONFIG_NETLABEL) += cipso_ipv4.o | 59 | obj-$(CONFIG_NETLABEL) += cipso_ipv4.o |
61 | 60 | ||
62 | obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ | 61 | obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 744e5936c10d..d07fc076bea0 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -289,10 +289,8 @@ static void __node_free_rcu(struct rcu_head *head) | |||
289 | 289 | ||
290 | if (!n->tn_bits) | 290 | if (!n->tn_bits) |
291 | kmem_cache_free(trie_leaf_kmem, n); | 291 | kmem_cache_free(trie_leaf_kmem, n); |
292 | else if (n->tn_bits <= TNODE_KMALLOC_MAX) | ||
293 | kfree(n); | ||
294 | else | 292 | else |
295 | vfree(n); | 293 | kvfree(n); |
296 | } | 294 | } |
297 | 295 | ||
298 | #define node_free(n) call_rcu(&tn_info(n)->rcu, __node_free_rcu) | 296 | #define node_free(n) call_rcu(&tn_info(n)->rcu, __node_free_rcu) |
@@ -1396,9 +1394,10 @@ found: | |||
1396 | struct fib_info *fi = fa->fa_info; | 1394 | struct fib_info *fi = fa->fa_info; |
1397 | int nhsel, err; | 1395 | int nhsel, err; |
1398 | 1396 | ||
1399 | if ((index >= (1ul << fa->fa_slen)) && | 1397 | if ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen < KEYLENGTH)) { |
1400 | ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen != KEYLENGTH))) | 1398 | if (index >= (1ul << fa->fa_slen)) |
1401 | continue; | 1399 | continue; |
1400 | } | ||
1402 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) | 1401 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) |
1403 | continue; | 1402 | continue; |
1404 | if (fi->fib_dead) | 1403 | if (fi->fib_dead) |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 8bb8e7ad8548..6029157a19ed 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -361,13 +361,20 @@ struct sock *inet_diag_find_one_icsk(struct net *net, | |||
361 | req->id.idiag_dport, req->id.idiag_src[0], | 361 | req->id.idiag_dport, req->id.idiag_src[0], |
362 | req->id.idiag_sport, req->id.idiag_if); | 362 | req->id.idiag_sport, req->id.idiag_if); |
363 | #if IS_ENABLED(CONFIG_IPV6) | 363 | #if IS_ENABLED(CONFIG_IPV6) |
364 | else if (req->sdiag_family == AF_INET6) | 364 | else if (req->sdiag_family == AF_INET6) { |
365 | sk = inet6_lookup(net, hashinfo, | 365 | if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) && |
366 | (struct in6_addr *)req->id.idiag_dst, | 366 | ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src)) |
367 | req->id.idiag_dport, | 367 | sk = inet_lookup(net, hashinfo, req->id.idiag_dst[3], |
368 | (struct in6_addr *)req->id.idiag_src, | 368 | req->id.idiag_dport, req->id.idiag_src[3], |
369 | req->id.idiag_sport, | 369 | req->id.idiag_sport, req->id.idiag_if); |
370 | req->id.idiag_if); | 370 | else |
371 | sk = inet6_lookup(net, hashinfo, | ||
372 | (struct in6_addr *)req->id.idiag_dst, | ||
373 | req->id.idiag_dport, | ||
374 | (struct in6_addr *)req->id.idiag_src, | ||
375 | req->id.idiag_sport, | ||
376 | req->id.idiag_if); | ||
377 | } | ||
371 | #endif | 378 | #endif |
372 | else | 379 | else |
373 | return ERR_PTR(-EINVAL); | 380 | return ERR_PTR(-EINVAL); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 3f00810b7288..187c6fcc3027 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -661,6 +661,7 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user) | |||
661 | struct ipq *qp; | 661 | struct ipq *qp; |
662 | 662 | ||
663 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); | 663 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); |
664 | skb_orphan(skb); | ||
664 | 665 | ||
665 | /* Lookup (or create) queue header */ | 666 | /* Lookup (or create) queue header */ |
666 | qp = ip_find(net, ip_hdr(skb), user, vif); | 667 | qp = ip_find(net, ip_hdr(skb), user, vif); |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index b1209b63381f..d77eb0c3b684 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -316,7 +316,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
316 | const struct iphdr *iph = ip_hdr(skb); | 316 | const struct iphdr *iph = ip_hdr(skb); |
317 | struct rtable *rt; | 317 | struct rtable *rt; |
318 | 318 | ||
319 | if (sysctl_ip_early_demux && !skb_dst(skb) && !skb->sk) { | 319 | if (sysctl_ip_early_demux && |
320 | !skb_dst(skb) && | ||
321 | !skb->sk && | ||
322 | !ip_is_fragment(iph)) { | ||
320 | const struct net_protocol *ipprot; | 323 | const struct net_protocol *ipprot; |
321 | int protocol = iph->protocol; | 324 | int protocol = iph->protocol; |
322 | 325 | ||
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 67f7c9de0b16..2ed9dd2b5f2f 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -143,7 +143,11 @@ static char dhcp_client_identifier[253] __initdata; | |||
143 | 143 | ||
144 | /* Persistent data: */ | 144 | /* Persistent data: */ |
145 | 145 | ||
146 | #ifdef IPCONFIG_DYNAMIC | ||
146 | static int ic_proto_used; /* Protocol used, if any */ | 147 | static int ic_proto_used; /* Protocol used, if any */ |
148 | #else | ||
149 | #define ic_proto_used 0 | ||
150 | #endif | ||
147 | static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ | 151 | static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ |
148 | static u8 ic_domain[64]; /* DNS (not NIS) domain name */ | 152 | static u8 ic_domain[64]; /* DNS (not NIS) domain name */ |
149 | 153 | ||
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 6fb869f646bf..a04dee536b8e 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c | |||
@@ -27,8 +27,6 @@ static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb, | |||
27 | { | 27 | { |
28 | int err; | 28 | int err; |
29 | 29 | ||
30 | skb_orphan(skb); | ||
31 | |||
32 | local_bh_disable(); | 30 | local_bh_disable(); |
33 | err = ip_defrag(net, skb, user); | 31 | err = ip_defrag(net, skb, user); |
34 | local_bh_enable(); | 32 | local_bh_enable(); |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 46ce410703b1..4d367b4139a3 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <net/cipso_ipv4.h> | 24 | #include <net/cipso_ipv4.h> |
25 | #include <net/inet_frag.h> | 25 | #include <net/inet_frag.h> |
26 | #include <net/ping.h> | 26 | #include <net/ping.h> |
27 | #include <net/tcp_memcontrol.h> | ||
28 | 27 | ||
29 | static int zero; | 28 | static int zero; |
30 | static int one = 1; | 29 | static int one = 1; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fd17eec93525..19746b3fcbbe 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -279,6 +279,7 @@ | |||
279 | 279 | ||
280 | #include <asm/uaccess.h> | 280 | #include <asm/uaccess.h> |
281 | #include <asm/ioctls.h> | 281 | #include <asm/ioctls.h> |
282 | #include <asm/unaligned.h> | ||
282 | #include <net/busy_poll.h> | 283 | #include <net/busy_poll.h> |
283 | 284 | ||
284 | int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; | 285 | int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; |
@@ -2638,6 +2639,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2638 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2639 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2639 | u32 now = tcp_time_stamp; | 2640 | u32 now = tcp_time_stamp; |
2640 | unsigned int start; | 2641 | unsigned int start; |
2642 | u64 rate64; | ||
2641 | u32 rate; | 2643 | u32 rate; |
2642 | 2644 | ||
2643 | memset(info, 0, sizeof(*info)); | 2645 | memset(info, 0, sizeof(*info)); |
@@ -2703,15 +2705,17 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2703 | info->tcpi_total_retrans = tp->total_retrans; | 2705 | info->tcpi_total_retrans = tp->total_retrans; |
2704 | 2706 | ||
2705 | rate = READ_ONCE(sk->sk_pacing_rate); | 2707 | rate = READ_ONCE(sk->sk_pacing_rate); |
2706 | info->tcpi_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2708 | rate64 = rate != ~0U ? rate : ~0ULL; |
2709 | put_unaligned(rate64, &info->tcpi_pacing_rate); | ||
2707 | 2710 | ||
2708 | rate = READ_ONCE(sk->sk_max_pacing_rate); | 2711 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
2709 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2712 | rate64 = rate != ~0U ? rate : ~0ULL; |
2713 | put_unaligned(rate64, &info->tcpi_max_pacing_rate); | ||
2710 | 2714 | ||
2711 | do { | 2715 | do { |
2712 | start = u64_stats_fetch_begin_irq(&tp->syncp); | 2716 | start = u64_stats_fetch_begin_irq(&tp->syncp); |
2713 | info->tcpi_bytes_acked = tp->bytes_acked; | 2717 | put_unaligned(tp->bytes_acked, &info->tcpi_bytes_acked); |
2714 | info->tcpi_bytes_received = tp->bytes_received; | 2718 | put_unaligned(tp->bytes_received, &info->tcpi_bytes_received); |
2715 | } while (u64_stats_fetch_retry_irq(&tp->syncp, start)); | 2719 | } while (u64_stats_fetch_retry_irq(&tp->syncp, start)); |
2716 | info->tcpi_segs_out = tp->segs_out; | 2720 | info->tcpi_segs_out = tp->segs_out; |
2717 | info->tcpi_segs_in = tp->segs_in; | 2721 | info->tcpi_segs_in = tp->segs_in; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0003d409fec5..1c2a73406261 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2164,8 +2164,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) | |||
2164 | { | 2164 | { |
2165 | struct tcp_sock *tp = tcp_sk(sk); | 2165 | struct tcp_sock *tp = tcp_sk(sk); |
2166 | struct sk_buff *skb; | 2166 | struct sk_buff *skb; |
2167 | int cnt, oldcnt; | 2167 | int cnt, oldcnt, lost; |
2168 | int err; | ||
2169 | unsigned int mss; | 2168 | unsigned int mss; |
2170 | /* Use SACK to deduce losses of new sequences sent during recovery */ | 2169 | /* Use SACK to deduce losses of new sequences sent during recovery */ |
2171 | const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; | 2170 | const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; |
@@ -2205,9 +2204,10 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) | |||
2205 | break; | 2204 | break; |
2206 | 2205 | ||
2207 | mss = tcp_skb_mss(skb); | 2206 | mss = tcp_skb_mss(skb); |
2208 | err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, | 2207 | /* If needed, chop off the prefix to mark as lost. */ |
2209 | mss, GFP_ATOMIC); | 2208 | lost = (packets - oldcnt) * mss; |
2210 | if (err < 0) | 2209 | if (lost < skb->len && |
2210 | tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0) | ||
2211 | break; | 2211 | break; |
2212 | cnt = packets; | 2212 | cnt = packets; |
2213 | } | 2213 | } |
@@ -2366,8 +2366,6 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss) | |||
2366 | tp->snd_ssthresh = tp->prior_ssthresh; | 2366 | tp->snd_ssthresh = tp->prior_ssthresh; |
2367 | tcp_ecn_withdraw_cwr(tp); | 2367 | tcp_ecn_withdraw_cwr(tp); |
2368 | } | 2368 | } |
2369 | } else { | ||
2370 | tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh); | ||
2371 | } | 2369 | } |
2372 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2370 | tp->snd_cwnd_stamp = tcp_time_stamp; |
2373 | tp->undo_marker = 0; | 2371 | tp->undo_marker = 0; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c7d1fb50f381..a4d523709ab3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <net/timewait_sock.h> | 73 | #include <net/timewait_sock.h> |
74 | #include <net/xfrm.h> | 74 | #include <net/xfrm.h> |
75 | #include <net/secure_seq.h> | 75 | #include <net/secure_seq.h> |
76 | #include <net/tcp_memcontrol.h> | ||
77 | #include <net/busy_poll.h> | 76 | #include <net/busy_poll.h> |
78 | 77 | ||
79 | #include <linux/inet.h> | 78 | #include <linux/inet.h> |
@@ -708,7 +707,8 @@ release_sk1: | |||
708 | outside socket context is ugly, certainly. What can I do? | 707 | outside socket context is ugly, certainly. What can I do? |
709 | */ | 708 | */ |
710 | 709 | ||
711 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 710 | static void tcp_v4_send_ack(struct net *net, |
711 | struct sk_buff *skb, u32 seq, u32 ack, | ||
712 | u32 win, u32 tsval, u32 tsecr, int oif, | 712 | u32 win, u32 tsval, u32 tsecr, int oif, |
713 | struct tcp_md5sig_key *key, | 713 | struct tcp_md5sig_key *key, |
714 | int reply_flags, u8 tos) | 714 | int reply_flags, u8 tos) |
@@ -723,7 +723,6 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
723 | ]; | 723 | ]; |
724 | } rep; | 724 | } rep; |
725 | struct ip_reply_arg arg; | 725 | struct ip_reply_arg arg; |
726 | struct net *net = dev_net(skb_dst(skb)->dev); | ||
727 | 726 | ||
728 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 727 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
729 | memset(&arg, 0, sizeof(arg)); | 728 | memset(&arg, 0, sizeof(arg)); |
@@ -785,7 +784,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
785 | struct inet_timewait_sock *tw = inet_twsk(sk); | 784 | struct inet_timewait_sock *tw = inet_twsk(sk); |
786 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 785 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
787 | 786 | ||
788 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 787 | tcp_v4_send_ack(sock_net(sk), skb, |
788 | tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | ||
789 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 789 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
790 | tcp_time_stamp + tcptw->tw_ts_offset, | 790 | tcp_time_stamp + tcptw->tw_ts_offset, |
791 | tcptw->tw_ts_recent, | 791 | tcptw->tw_ts_recent, |
@@ -804,8 +804,10 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, | |||
804 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV | 804 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV |
805 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. | 805 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. |
806 | */ | 806 | */ |
807 | tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? | 807 | u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : |
808 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, | 808 | tcp_sk(sk)->snd_nxt; |
809 | |||
810 | tcp_v4_send_ack(sock_net(sk), skb, seq, | ||
809 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, | 811 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, |
810 | tcp_time_stamp, | 812 | tcp_time_stamp, |
811 | req->ts_recent, | 813 | req->ts_recent, |
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c deleted file mode 100644 index 18bc7f745e9c..000000000000 --- a/net/ipv4/tcp_memcontrol.c +++ /dev/null | |||
@@ -1,200 +0,0 @@ | |||
1 | #include <net/tcp.h> | ||
2 | #include <net/tcp_memcontrol.h> | ||
3 | #include <net/sock.h> | ||
4 | #include <net/ip.h> | ||
5 | #include <linux/nsproxy.h> | ||
6 | #include <linux/memcontrol.h> | ||
7 | #include <linux/module.h> | ||
8 | |||
9 | int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss) | ||
10 | { | ||
11 | struct mem_cgroup *parent = parent_mem_cgroup(memcg); | ||
12 | struct page_counter *counter_parent = NULL; | ||
13 | /* | ||
14 | * The root cgroup does not use page_counters, but rather, | ||
15 | * rely on the data already collected by the network | ||
16 | * subsystem | ||
17 | */ | ||
18 | if (memcg == root_mem_cgroup) | ||
19 | return 0; | ||
20 | |||
21 | memcg->tcp_mem.memory_pressure = 0; | ||
22 | |||
23 | if (parent) | ||
24 | counter_parent = &parent->tcp_mem.memory_allocated; | ||
25 | |||
26 | page_counter_init(&memcg->tcp_mem.memory_allocated, counter_parent); | ||
27 | |||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | void tcp_destroy_cgroup(struct mem_cgroup *memcg) | ||
32 | { | ||
33 | if (memcg == root_mem_cgroup) | ||
34 | return; | ||
35 | |||
36 | if (memcg->tcp_mem.active) | ||
37 | static_branch_dec(&memcg_sockets_enabled_key); | ||
38 | } | ||
39 | |||
40 | static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages) | ||
41 | { | ||
42 | int ret; | ||
43 | |||
44 | if (memcg == root_mem_cgroup) | ||
45 | return -EINVAL; | ||
46 | |||
47 | ret = page_counter_limit(&memcg->tcp_mem.memory_allocated, nr_pages); | ||
48 | if (ret) | ||
49 | return ret; | ||
50 | |||
51 | if (!memcg->tcp_mem.active) { | ||
52 | /* | ||
53 | * The active flag needs to be written after the static_key | ||
54 | * update. This is what guarantees that the socket activation | ||
55 | * function is the last one to run. See sock_update_memcg() for | ||
56 | * details, and note that we don't mark any socket as belonging | ||
57 | * to this memcg until that flag is up. | ||
58 | * | ||
59 | * We need to do this, because static_keys will span multiple | ||
60 | * sites, but we can't control their order. If we mark a socket | ||
61 | * as accounted, but the accounting functions are not patched in | ||
62 | * yet, we'll lose accounting. | ||
63 | * | ||
64 | * We never race with the readers in sock_update_memcg(), | ||
65 | * because when this value change, the code to process it is not | ||
66 | * patched in yet. | ||
67 | */ | ||
68 | static_branch_inc(&memcg_sockets_enabled_key); | ||
69 | memcg->tcp_mem.active = true; | ||
70 | } | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | enum { | ||
76 | RES_USAGE, | ||
77 | RES_LIMIT, | ||
78 | RES_MAX_USAGE, | ||
79 | RES_FAILCNT, | ||
80 | }; | ||
81 | |||
82 | static DEFINE_MUTEX(tcp_limit_mutex); | ||
83 | |||
84 | static ssize_t tcp_cgroup_write(struct kernfs_open_file *of, | ||
85 | char *buf, size_t nbytes, loff_t off) | ||
86 | { | ||
87 | struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of)); | ||
88 | unsigned long nr_pages; | ||
89 | int ret = 0; | ||
90 | |||
91 | buf = strstrip(buf); | ||
92 | |||
93 | switch (of_cft(of)->private) { | ||
94 | case RES_LIMIT: | ||
95 | /* see memcontrol.c */ | ||
96 | ret = page_counter_memparse(buf, "-1", &nr_pages); | ||
97 | if (ret) | ||
98 | break; | ||
99 | mutex_lock(&tcp_limit_mutex); | ||
100 | ret = tcp_update_limit(memcg, nr_pages); | ||
101 | mutex_unlock(&tcp_limit_mutex); | ||
102 | break; | ||
103 | default: | ||
104 | ret = -EINVAL; | ||
105 | break; | ||
106 | } | ||
107 | return ret ?: nbytes; | ||
108 | } | ||
109 | |||
110 | static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) | ||
111 | { | ||
112 | struct mem_cgroup *memcg = mem_cgroup_from_css(css); | ||
113 | u64 val; | ||
114 | |||
115 | switch (cft->private) { | ||
116 | case RES_LIMIT: | ||
117 | if (memcg == root_mem_cgroup) | ||
118 | val = PAGE_COUNTER_MAX; | ||
119 | else | ||
120 | val = memcg->tcp_mem.memory_allocated.limit; | ||
121 | val *= PAGE_SIZE; | ||
122 | break; | ||
123 | case RES_USAGE: | ||
124 | if (memcg == root_mem_cgroup) | ||
125 | val = atomic_long_read(&tcp_memory_allocated); | ||
126 | else | ||
127 | val = page_counter_read(&memcg->tcp_mem.memory_allocated); | ||
128 | val *= PAGE_SIZE; | ||
129 | break; | ||
130 | case RES_FAILCNT: | ||
131 | if (memcg == root_mem_cgroup) | ||
132 | return 0; | ||
133 | val = memcg->tcp_mem.memory_allocated.failcnt; | ||
134 | break; | ||
135 | case RES_MAX_USAGE: | ||
136 | if (memcg == root_mem_cgroup) | ||
137 | return 0; | ||
138 | val = memcg->tcp_mem.memory_allocated.watermark; | ||
139 | val *= PAGE_SIZE; | ||
140 | break; | ||
141 | default: | ||
142 | BUG(); | ||
143 | } | ||
144 | return val; | ||
145 | } | ||
146 | |||
147 | static ssize_t tcp_cgroup_reset(struct kernfs_open_file *of, | ||
148 | char *buf, size_t nbytes, loff_t off) | ||
149 | { | ||
150 | struct mem_cgroup *memcg; | ||
151 | |||
152 | memcg = mem_cgroup_from_css(of_css(of)); | ||
153 | if (memcg == root_mem_cgroup) | ||
154 | return nbytes; | ||
155 | |||
156 | switch (of_cft(of)->private) { | ||
157 | case RES_MAX_USAGE: | ||
158 | page_counter_reset_watermark(&memcg->tcp_mem.memory_allocated); | ||
159 | break; | ||
160 | case RES_FAILCNT: | ||
161 | memcg->tcp_mem.memory_allocated.failcnt = 0; | ||
162 | break; | ||
163 | } | ||
164 | |||
165 | return nbytes; | ||
166 | } | ||
167 | |||
168 | static struct cftype tcp_files[] = { | ||
169 | { | ||
170 | .name = "kmem.tcp.limit_in_bytes", | ||
171 | .write = tcp_cgroup_write, | ||
172 | .read_u64 = tcp_cgroup_read, | ||
173 | .private = RES_LIMIT, | ||
174 | }, | ||
175 | { | ||
176 | .name = "kmem.tcp.usage_in_bytes", | ||
177 | .read_u64 = tcp_cgroup_read, | ||
178 | .private = RES_USAGE, | ||
179 | }, | ||
180 | { | ||
181 | .name = "kmem.tcp.failcnt", | ||
182 | .private = RES_FAILCNT, | ||
183 | .write = tcp_cgroup_reset, | ||
184 | .read_u64 = tcp_cgroup_read, | ||
185 | }, | ||
186 | { | ||
187 | .name = "kmem.tcp.max_usage_in_bytes", | ||
188 | .private = RES_MAX_USAGE, | ||
189 | .write = tcp_cgroup_reset, | ||
190 | .read_u64 = tcp_cgroup_read, | ||
191 | }, | ||
192 | { } /* terminate */ | ||
193 | }; | ||
194 | |||
195 | static int __init tcp_memcontrol_init(void) | ||
196 | { | ||
197 | WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys, tcp_files)); | ||
198 | return 0; | ||
199 | } | ||
200 | __initcall(tcp_memcontrol_init); | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index dc45b538e237..be0b21852b13 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -499,6 +499,7 @@ static struct sock *udp4_lib_lookup2(struct net *net, | |||
499 | struct sock *sk, *result; | 499 | struct sock *sk, *result; |
500 | struct hlist_nulls_node *node; | 500 | struct hlist_nulls_node *node; |
501 | int score, badness, matches = 0, reuseport = 0; | 501 | int score, badness, matches = 0, reuseport = 0; |
502 | bool select_ok = true; | ||
502 | u32 hash = 0; | 503 | u32 hash = 0; |
503 | 504 | ||
504 | begin: | 505 | begin: |
@@ -512,14 +513,18 @@ begin: | |||
512 | badness = score; | 513 | badness = score; |
513 | reuseport = sk->sk_reuseport; | 514 | reuseport = sk->sk_reuseport; |
514 | if (reuseport) { | 515 | if (reuseport) { |
515 | struct sock *sk2; | ||
516 | hash = udp_ehashfn(net, daddr, hnum, | 516 | hash = udp_ehashfn(net, daddr, hnum, |
517 | saddr, sport); | 517 | saddr, sport); |
518 | sk2 = reuseport_select_sock(sk, hash, skb, | 518 | if (select_ok) { |
519 | sizeof(struct udphdr)); | 519 | struct sock *sk2; |
520 | if (sk2) { | 520 | |
521 | result = sk2; | 521 | sk2 = reuseport_select_sock(sk, hash, skb, |
522 | goto found; | 522 | sizeof(struct udphdr)); |
523 | if (sk2) { | ||
524 | result = sk2; | ||
525 | select_ok = false; | ||
526 | goto found; | ||
527 | } | ||
523 | } | 528 | } |
524 | matches = 1; | 529 | matches = 1; |
525 | } | 530 | } |
@@ -563,6 +568,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
563 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); | 568 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); |
564 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; | 569 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; |
565 | int score, badness, matches = 0, reuseport = 0; | 570 | int score, badness, matches = 0, reuseport = 0; |
571 | bool select_ok = true; | ||
566 | u32 hash = 0; | 572 | u32 hash = 0; |
567 | 573 | ||
568 | rcu_read_lock(); | 574 | rcu_read_lock(); |
@@ -601,14 +607,18 @@ begin: | |||
601 | badness = score; | 607 | badness = score; |
602 | reuseport = sk->sk_reuseport; | 608 | reuseport = sk->sk_reuseport; |
603 | if (reuseport) { | 609 | if (reuseport) { |
604 | struct sock *sk2; | ||
605 | hash = udp_ehashfn(net, daddr, hnum, | 610 | hash = udp_ehashfn(net, daddr, hnum, |
606 | saddr, sport); | 611 | saddr, sport); |
607 | sk2 = reuseport_select_sock(sk, hash, skb, | 612 | if (select_ok) { |
613 | struct sock *sk2; | ||
614 | |||
615 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
608 | sizeof(struct udphdr)); | 616 | sizeof(struct udphdr)); |
609 | if (sk2) { | 617 | if (sk2) { |
610 | result = sk2; | 618 | result = sk2; |
611 | goto found; | 619 | select_ok = false; |
620 | goto found; | ||
621 | } | ||
612 | } | 622 | } |
613 | matches = 1; | 623 | matches = 1; |
614 | } | 624 | } |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index bb7dabe2ebbf..40c897515ddc 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -69,6 +69,7 @@ config INET6_ESP | |||
69 | select CRYPTO_CBC | 69 | select CRYPTO_CBC |
70 | select CRYPTO_SHA1 | 70 | select CRYPTO_SHA1 |
71 | select CRYPTO_DES | 71 | select CRYPTO_DES |
72 | select CRYPTO_ECHAINIV | ||
72 | ---help--- | 73 | ---help--- |
73 | Support for IPsec ESP. | 74 | Support for IPsec ESP. |
74 | 75 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 517c55b01ba8..428162155280 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -162,6 +162,9 @@ ipv4_connected: | |||
162 | fl6.fl6_dport = inet->inet_dport; | 162 | fl6.fl6_dport = inet->inet_dport; |
163 | fl6.fl6_sport = inet->inet_sport; | 163 | fl6.fl6_sport = inet->inet_sport; |
164 | 164 | ||
165 | if (!fl6.flowi6_oif) | ||
166 | fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; | ||
167 | |||
165 | if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST)) | 168 | if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST)) |
166 | fl6.flowi6_oif = np->mcast_oif; | 169 | fl6.flowi6_oif = np->mcast_oif; |
167 | 170 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 23de98f976d5..a163102f1803 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -909,6 +909,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, | |||
909 | struct rt6_info *rt; | 909 | struct rt6_info *rt; |
910 | #endif | 910 | #endif |
911 | int err; | 911 | int err; |
912 | int flags = 0; | ||
912 | 913 | ||
913 | /* The correct way to handle this would be to do | 914 | /* The correct way to handle this would be to do |
914 | * ip6_route_get_saddr, and then ip6_route_output; however, | 915 | * ip6_route_get_saddr, and then ip6_route_output; however, |
@@ -940,10 +941,13 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, | |||
940 | dst_release(*dst); | 941 | dst_release(*dst); |
941 | *dst = NULL; | 942 | *dst = NULL; |
942 | } | 943 | } |
944 | |||
945 | if (fl6->flowi6_oif) | ||
946 | flags |= RT6_LOOKUP_F_IFACE; | ||
943 | } | 947 | } |
944 | 948 | ||
945 | if (!*dst) | 949 | if (!*dst) |
946 | *dst = ip6_route_output(net, sk, fl6); | 950 | *dst = ip6_route_output_flags(net, sk, fl6, flags); |
947 | 951 | ||
948 | err = (*dst)->error; | 952 | err = (*dst)->error; |
949 | if (err) | 953 | if (err) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3c8834bc822d..ed446639219c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1183,11 +1183,10 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table | |||
1183 | return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); | 1183 | return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk, | 1186 | struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, |
1187 | struct flowi6 *fl6) | 1187 | struct flowi6 *fl6, int flags) |
1188 | { | 1188 | { |
1189 | struct dst_entry *dst; | 1189 | struct dst_entry *dst; |
1190 | int flags = 0; | ||
1191 | bool any_src; | 1190 | bool any_src; |
1192 | 1191 | ||
1193 | dst = l3mdev_rt6_dst_by_oif(net, fl6); | 1192 | dst = l3mdev_rt6_dst_by_oif(net, fl6); |
@@ -1208,7 +1207,7 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk, | |||
1208 | 1207 | ||
1209 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output); | 1208 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output); |
1210 | } | 1209 | } |
1211 | EXPORT_SYMBOL(ip6_route_output); | 1210 | EXPORT_SYMBOL_GPL(ip6_route_output_flags); |
1212 | 1211 | ||
1213 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) | 1212 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
1214 | { | 1213 | { |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e794ef66a401..2066d1c25a11 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -201,14 +201,14 @@ static int ipip6_tunnel_create(struct net_device *dev) | |||
201 | if ((__force u16)t->parms.i_flags & SIT_ISATAP) | 201 | if ((__force u16)t->parms.i_flags & SIT_ISATAP) |
202 | dev->priv_flags |= IFF_ISATAP; | 202 | dev->priv_flags |= IFF_ISATAP; |
203 | 203 | ||
204 | dev->rtnl_link_ops = &sit_link_ops; | ||
205 | |||
204 | err = register_netdevice(dev); | 206 | err = register_netdevice(dev); |
205 | if (err < 0) | 207 | if (err < 0) |
206 | goto out; | 208 | goto out; |
207 | 209 | ||
208 | ipip6_tunnel_clone_6rd(dev, sitn); | 210 | ipip6_tunnel_clone_6rd(dev, sitn); |
209 | 211 | ||
210 | dev->rtnl_link_ops = &sit_link_ops; | ||
211 | |||
212 | dev_hold(dev); | 212 | dev_hold(dev); |
213 | 213 | ||
214 | ipip6_tunnel_link(sitn, t); | 214 | ipip6_tunnel_link(sitn, t); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4ad8edb46f7c..006396e31cb0 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -61,7 +61,6 @@ | |||
61 | #include <net/timewait_sock.h> | 61 | #include <net/timewait_sock.h> |
62 | #include <net/inet_common.h> | 62 | #include <net/inet_common.h> |
63 | #include <net/secure_seq.h> | 63 | #include <net/secure_seq.h> |
64 | #include <net/tcp_memcontrol.h> | ||
65 | #include <net/busy_poll.h> | 64 | #include <net/busy_poll.h> |
66 | 65 | ||
67 | #include <linux/proc_fs.h> | 66 | #include <linux/proc_fs.h> |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5d2c2afffe7b..22e28a44e3c8 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -257,6 +257,7 @@ static struct sock *udp6_lib_lookup2(struct net *net, | |||
257 | struct sock *sk, *result; | 257 | struct sock *sk, *result; |
258 | struct hlist_nulls_node *node; | 258 | struct hlist_nulls_node *node; |
259 | int score, badness, matches = 0, reuseport = 0; | 259 | int score, badness, matches = 0, reuseport = 0; |
260 | bool select_ok = true; | ||
260 | u32 hash = 0; | 261 | u32 hash = 0; |
261 | 262 | ||
262 | begin: | 263 | begin: |
@@ -270,14 +271,18 @@ begin: | |||
270 | badness = score; | 271 | badness = score; |
271 | reuseport = sk->sk_reuseport; | 272 | reuseport = sk->sk_reuseport; |
272 | if (reuseport) { | 273 | if (reuseport) { |
273 | struct sock *sk2; | ||
274 | hash = udp6_ehashfn(net, daddr, hnum, | 274 | hash = udp6_ehashfn(net, daddr, hnum, |
275 | saddr, sport); | 275 | saddr, sport); |
276 | sk2 = reuseport_select_sock(sk, hash, skb, | 276 | if (select_ok) { |
277 | sizeof(struct udphdr)); | 277 | struct sock *sk2; |
278 | if (sk2) { | 278 | |
279 | result = sk2; | 279 | sk2 = reuseport_select_sock(sk, hash, skb, |
280 | goto found; | 280 | sizeof(struct udphdr)); |
281 | if (sk2) { | ||
282 | result = sk2; | ||
283 | select_ok = false; | ||
284 | goto found; | ||
285 | } | ||
281 | } | 286 | } |
282 | matches = 1; | 287 | matches = 1; |
283 | } | 288 | } |
@@ -321,6 +326,7 @@ struct sock *__udp6_lib_lookup(struct net *net, | |||
321 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); | 326 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); |
322 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; | 327 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; |
323 | int score, badness, matches = 0, reuseport = 0; | 328 | int score, badness, matches = 0, reuseport = 0; |
329 | bool select_ok = true; | ||
324 | u32 hash = 0; | 330 | u32 hash = 0; |
325 | 331 | ||
326 | rcu_read_lock(); | 332 | rcu_read_lock(); |
@@ -358,14 +364,18 @@ begin: | |||
358 | badness = score; | 364 | badness = score; |
359 | reuseport = sk->sk_reuseport; | 365 | reuseport = sk->sk_reuseport; |
360 | if (reuseport) { | 366 | if (reuseport) { |
361 | struct sock *sk2; | ||
362 | hash = udp6_ehashfn(net, daddr, hnum, | 367 | hash = udp6_ehashfn(net, daddr, hnum, |
363 | saddr, sport); | 368 | saddr, sport); |
364 | sk2 = reuseport_select_sock(sk, hash, skb, | 369 | if (select_ok) { |
370 | struct sock *sk2; | ||
371 | |||
372 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
365 | sizeof(struct udphdr)); | 373 | sizeof(struct udphdr)); |
366 | if (sk2) { | 374 | if (sk2) { |
367 | result = sk2; | 375 | result = sk2; |
368 | goto found; | 376 | select_ok = false; |
377 | goto found; | ||
378 | } | ||
369 | } | 379 | } |
370 | matches = 1; | 380 | matches = 1; |
371 | } | 381 | } |
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index 3c4caa60c926..5728e76ca6d5 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c | |||
@@ -134,11 +134,10 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) | |||
134 | return -1; | 134 | return -1; |
135 | } | 135 | } |
136 | skb_put(skb, count); | 136 | skb_put(skb, count); |
137 | pr_debug("%s(), skb->len=%d\n", __func__, skb->len); | ||
137 | 138 | ||
138 | spin_unlock_irqrestore(&self->spinlock, flags); | 139 | spin_unlock_irqrestore(&self->spinlock, flags); |
139 | 140 | ||
140 | pr_debug("%s(), skb->len=%d\n", __func__ , skb->len); | ||
141 | |||
142 | if (flush) { | 141 | if (flush) { |
143 | /* ircomm_tty_do_softint will take care of the rest */ | 142 | /* ircomm_tty_do_softint will take care of the rest */ |
144 | schedule_work(&self->tqueue); | 143 | schedule_work(&self->tqueue); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index ef50a94d3eb7..fc3598a922b0 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -708,6 +708,9 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
708 | if (!addr || addr->sa_family != AF_IUCV) | 708 | if (!addr || addr->sa_family != AF_IUCV) |
709 | return -EINVAL; | 709 | return -EINVAL; |
710 | 710 | ||
711 | if (addr_len < sizeof(struct sockaddr_iucv)) | ||
712 | return -EINVAL; | ||
713 | |||
711 | lock_sock(sk); | 714 | lock_sock(sk); |
712 | if (sk->sk_state != IUCV_OPEN) { | 715 | if (sk->sk_state != IUCV_OPEN) { |
713 | err = -EBADFD; | 716 | err = -EBADFD; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index abbdff03ce92..3e24d0ddb51b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -91,7 +91,7 @@ static const struct file_operations reset_ops = { | |||
91 | }; | 91 | }; |
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { | 94 | static const char *hw_flag_names[] = { |
95 | #define FLAG(F) [IEEE80211_HW_##F] = #F | 95 | #define FLAG(F) [IEEE80211_HW_##F] = #F |
96 | FLAG(HAS_RATE_CONTROL), | 96 | FLAG(HAS_RATE_CONTROL), |
97 | FLAG(RX_INCLUDES_FCS), | 97 | FLAG(RX_INCLUDES_FCS), |
@@ -126,9 +126,6 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { | |||
126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), | 126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), |
127 | FLAG(BEACON_TX_STATUS), | 127 | FLAG(BEACON_TX_STATUS), |
128 | FLAG(NEEDS_UNIQUE_STA_ADDR), | 128 | FLAG(NEEDS_UNIQUE_STA_ADDR), |
129 | |||
130 | /* keep last for the build bug below */ | ||
131 | (void *)0x1 | ||
132 | #undef FLAG | 129 | #undef FLAG |
133 | }; | 130 | }; |
134 | 131 | ||
@@ -148,7 +145,7 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
148 | /* fail compilation if somebody adds or removes | 145 | /* fail compilation if somebody adds or removes |
149 | * a flag without updating the name array above | 146 | * a flag without updating the name array above |
150 | */ | 147 | */ |
151 | BUILD_BUG_ON(hw_flag_names[NUM_IEEE80211_HW_FLAGS] != (void *)0x1); | 148 | BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS); |
152 | 149 | ||
153 | for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) { | 150 | for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) { |
154 | if (test_bit(i, local->hw.flags)) | 151 | if (test_bit(i, local->hw.flags)) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f7fc0e00497f..978d3bc31df7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1733,7 +1733,6 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
1733 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1733 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1734 | continue; | 1734 | continue; |
1735 | sdata->u.ibss.last_scan_completed = jiffies; | 1735 | sdata->u.ibss.last_scan_completed = jiffies; |
1736 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
1737 | } | 1736 | } |
1738 | mutex_unlock(&local->iflist_mtx); | 1737 | mutex_unlock(&local->iflist_mtx); |
1739 | } | 1738 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6bcf0faa4a89..8190bf27ebff 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -248,6 +248,7 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
248 | 248 | ||
249 | /* wait for scan work complete */ | 249 | /* wait for scan work complete */ |
250 | flush_workqueue(local->workqueue); | 250 | flush_workqueue(local->workqueue); |
251 | flush_work(&local->sched_scan_stopped_work); | ||
251 | 252 | ||
252 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | 253 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), |
253 | "%s called with hardware scan in progress\n", __func__); | 254 | "%s called with hardware scan in progress\n", __func__); |
@@ -256,6 +257,11 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
256 | list_for_each_entry(sdata, &local->interfaces, list) | 257 | list_for_each_entry(sdata, &local->interfaces, list) |
257 | flush_delayed_work(&sdata->dec_tailroom_needed_wk); | 258 | flush_delayed_work(&sdata->dec_tailroom_needed_wk); |
258 | ieee80211_scan_cancel(local); | 259 | ieee80211_scan_cancel(local); |
260 | |||
261 | /* make sure any new ROC will consider local->in_reconfig */ | ||
262 | flush_delayed_work(&local->roc_work); | ||
263 | flush_work(&local->hw_roc_done); | ||
264 | |||
259 | ieee80211_reconfig(local); | 265 | ieee80211_reconfig(local); |
260 | rtnl_unlock(); | 266 | rtnl_unlock(); |
261 | } | 267 | } |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index fa28500f28fd..6f85b6ab8e51 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -1370,17 +1370,6 @@ out: | |||
1370 | sdata_unlock(sdata); | 1370 | sdata_unlock(sdata); |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | ||
1374 | { | ||
1375 | struct ieee80211_sub_if_data *sdata; | ||
1376 | |||
1377 | rcu_read_lock(); | ||
1378 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
1379 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
1380 | ieee80211_sdata_running(sdata)) | ||
1381 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
1382 | rcu_read_unlock(); | ||
1383 | } | ||
1384 | 1373 | ||
1385 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | 1374 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) |
1386 | { | 1375 | { |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index a1596344c3ba..4a8019f79fb2 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | |||
362 | return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; | 362 | return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; |
363 | } | 363 | } |
364 | 364 | ||
365 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); | ||
366 | |||
367 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | 365 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); |
368 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | 366 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); |
369 | void ieee80211s_stop(void); | 367 | void ieee80211s_stop(void); |
370 | #else | 368 | #else |
371 | static inline void | ||
372 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | ||
373 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | 369 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) |
374 | { return false; } | 370 | { return false; } |
375 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | 371 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1c342e2592c4..bfbb1acafdd1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -4005,8 +4005,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
4005 | if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) | 4005 | if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) |
4006 | ieee80211_queue_work(&sdata->local->hw, | 4006 | ieee80211_queue_work(&sdata->local->hw, |
4007 | &sdata->u.mgd.monitor_work); | 4007 | &sdata->u.mgd.monitor_work); |
4008 | /* and do all the other regular work too */ | ||
4009 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | ||
4010 | } | 4008 | } |
4011 | } | 4009 | } |
4012 | 4010 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 8b2f4eaac2ba..55a9c5b94ce1 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -252,14 +252,11 @@ static bool ieee80211_recalc_sw_work(struct ieee80211_local *local, | |||
252 | static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, | 252 | static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, |
253 | unsigned long start_time) | 253 | unsigned long start_time) |
254 | { | 254 | { |
255 | struct ieee80211_local *local = roc->sdata->local; | ||
256 | |||
257 | if (WARN_ON(roc->notified)) | 255 | if (WARN_ON(roc->notified)) |
258 | return; | 256 | return; |
259 | 257 | ||
260 | roc->start_time = start_time; | 258 | roc->start_time = start_time; |
261 | roc->started = true; | 259 | roc->started = true; |
262 | roc->hw_begun = true; | ||
263 | 260 | ||
264 | if (roc->mgmt_tx_cookie) { | 261 | if (roc->mgmt_tx_cookie) { |
265 | if (!WARN_ON(!roc->frame)) { | 262 | if (!WARN_ON(!roc->frame)) { |
@@ -274,9 +271,6 @@ static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, | |||
274 | } | 271 | } |
275 | 272 | ||
276 | roc->notified = true; | 273 | roc->notified = true; |
277 | |||
278 | if (!local->ops->remain_on_channel) | ||
279 | ieee80211_recalc_sw_work(local, start_time); | ||
280 | } | 274 | } |
281 | 275 | ||
282 | static void ieee80211_hw_roc_start(struct work_struct *work) | 276 | static void ieee80211_hw_roc_start(struct work_struct *work) |
@@ -291,6 +285,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work) | |||
291 | if (!roc->started) | 285 | if (!roc->started) |
292 | break; | 286 | break; |
293 | 287 | ||
288 | roc->hw_begun = true; | ||
294 | ieee80211_handle_roc_started(roc, local->hw_roc_start_time); | 289 | ieee80211_handle_roc_started(roc, local->hw_roc_start_time); |
295 | } | 290 | } |
296 | 291 | ||
@@ -413,6 +408,10 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
413 | return; | 408 | return; |
414 | } | 409 | } |
415 | 410 | ||
411 | /* defer roc if driver is not started (i.e. during reconfig) */ | ||
412 | if (local->in_reconfig) | ||
413 | return; | ||
414 | |||
416 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | 415 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, |
417 | list); | 416 | list); |
418 | 417 | ||
@@ -534,8 +533,10 @@ ieee80211_coalesce_hw_started_roc(struct ieee80211_local *local, | |||
534 | * begin, otherwise they'll both be marked properly by the work | 533 | * begin, otherwise they'll both be marked properly by the work |
535 | * struct that runs once the driver notifies us of the beginning | 534 | * struct that runs once the driver notifies us of the beginning |
536 | */ | 535 | */ |
537 | if (cur_roc->hw_begun) | 536 | if (cur_roc->hw_begun) { |
537 | new_roc->hw_begun = true; | ||
538 | ieee80211_handle_roc_started(new_roc, now); | 538 | ieee80211_handle_roc_started(new_roc, now); |
539 | } | ||
539 | 540 | ||
540 | return true; | 541 | return true; |
541 | } | 542 | } |
@@ -658,6 +659,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
658 | queued = true; | 659 | queued = true; |
659 | roc->on_channel = tmp->on_channel; | 660 | roc->on_channel = tmp->on_channel; |
660 | ieee80211_handle_roc_started(roc, now); | 661 | ieee80211_handle_roc_started(roc, now); |
662 | ieee80211_recalc_sw_work(local, now); | ||
661 | break; | 663 | break; |
662 | } | 664 | } |
663 | 665 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a413e52f7691..ae980ce8daff 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
314 | bool was_scanning = local->scanning; | 314 | bool was_scanning = local->scanning; |
315 | struct cfg80211_scan_request *scan_req; | 315 | struct cfg80211_scan_request *scan_req; |
316 | struct ieee80211_sub_if_data *scan_sdata; | 316 | struct ieee80211_sub_if_data *scan_sdata; |
317 | struct ieee80211_sub_if_data *sdata; | ||
317 | 318 | ||
318 | lockdep_assert_held(&local->mtx); | 319 | lockdep_assert_held(&local->mtx); |
319 | 320 | ||
@@ -373,7 +374,16 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
373 | 374 | ||
374 | ieee80211_mlme_notify_scan_completed(local); | 375 | ieee80211_mlme_notify_scan_completed(local); |
375 | ieee80211_ibss_notify_scan_completed(local); | 376 | ieee80211_ibss_notify_scan_completed(local); |
376 | ieee80211_mesh_notify_scan_completed(local); | 377 | |
378 | /* Requeue all the work that might have been ignored while | ||
379 | * the scan was in progress; if there was none this will | ||
380 | * just be a no-op for the particular interface. | ||
381 | */ | ||
382 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
383 | if (ieee80211_sdata_running(sdata)) | ||
384 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | ||
385 | } | ||
386 | |||
377 | if (was_scanning) | 387 | if (was_scanning) |
378 | ieee80211_start_next_roc(local); | 388 | ieee80211_start_next_roc(local); |
379 | } | 389 | } |
@@ -1213,6 +1223,14 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) | |||
1213 | 1223 | ||
1214 | trace_api_sched_scan_stopped(local); | 1224 | trace_api_sched_scan_stopped(local); |
1215 | 1225 | ||
1226 | /* | ||
1227 | * this shouldn't really happen, so for simplicity | ||
1228 | * simply ignore it, and let mac80211 reconfigure | ||
1229 | * the sched scan later on. | ||
1230 | */ | ||
1231 | if (local->in_reconfig) | ||
1232 | return; | ||
1233 | |||
1216 | schedule_work(&local->sched_scan_stopped_work); | 1234 | schedule_work(&local->sched_scan_stopped_work); |
1217 | } | 1235 | } |
1218 | EXPORT_SYMBOL(ieee80211_sched_scan_stopped); | 1236 | EXPORT_SYMBOL(ieee80211_sched_scan_stopped); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4402ad5b27d1..a4a4f89d3ba0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1453,7 +1453,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1453 | 1453 | ||
1454 | more_data = ieee80211_sta_ps_more_data(sta, ignored_acs, reason, driver_release_tids); | 1454 | more_data = ieee80211_sta_ps_more_data(sta, ignored_acs, reason, driver_release_tids); |
1455 | 1455 | ||
1456 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) | 1456 | if (driver_release_tids && reason == IEEE80211_FRAME_RELEASE_PSPOLL) |
1457 | driver_release_tids = | 1457 | driver_release_tids = |
1458 | BIT(find_highest_prio_tid(driver_release_tids)); | 1458 | BIT(find_highest_prio_tid(driver_release_tids)); |
1459 | 1459 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 5bad05e9af90..6101deb805a8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -51,6 +51,11 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
51 | struct ieee80211_hdr *hdr = (void *)skb->data; | 51 | struct ieee80211_hdr *hdr = (void *)skb->data; |
52 | int ac; | 52 | int ac; |
53 | 53 | ||
54 | if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) { | ||
55 | ieee80211_free_txskb(&local->hw, skb); | ||
56 | return; | ||
57 | } | ||
58 | |||
54 | /* | 59 | /* |
55 | * This skb 'survived' a round-trip through the driver, and | 60 | * This skb 'survived' a round-trip through the driver, and |
56 | * hopefully the driver didn't mangle it too badly. However, | 61 | * hopefully the driver didn't mangle it too badly. However, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3943d4bf289c..58f58bd5202f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -2043,16 +2043,26 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2043 | */ | 2043 | */ |
2044 | if (sched_scan_req->n_scan_plans > 1 || | 2044 | if (sched_scan_req->n_scan_plans > 1 || |
2045 | __ieee80211_request_sched_scan_start(sched_scan_sdata, | 2045 | __ieee80211_request_sched_scan_start(sched_scan_sdata, |
2046 | sched_scan_req)) | 2046 | sched_scan_req)) { |
2047 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); | ||
2048 | RCU_INIT_POINTER(local->sched_scan_req, NULL); | ||
2047 | sched_scan_stopped = true; | 2049 | sched_scan_stopped = true; |
2050 | } | ||
2048 | mutex_unlock(&local->mtx); | 2051 | mutex_unlock(&local->mtx); |
2049 | 2052 | ||
2050 | if (sched_scan_stopped) | 2053 | if (sched_scan_stopped) |
2051 | cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy); | 2054 | cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy); |
2052 | 2055 | ||
2053 | wake_up: | 2056 | wake_up: |
2054 | local->in_reconfig = false; | 2057 | if (local->in_reconfig) { |
2055 | barrier(); | 2058 | local->in_reconfig = false; |
2059 | barrier(); | ||
2060 | |||
2061 | /* Restart deferred ROCs */ | ||
2062 | mutex_lock(&local->mtx); | ||
2063 | ieee80211_start_next_roc(local); | ||
2064 | mutex_unlock(&local->mtx); | ||
2065 | } | ||
2056 | 2066 | ||
2057 | if (local->monitors == local->open_count && local->monitors > 0) | 2067 | if (local->monitors == local->open_count && local->monitors > 0) |
2058 | ieee80211_add_virtual_monitor(local); | 2068 | ieee80211_add_virtual_monitor(local); |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index 43d8c9896fa3..f0f688db6213 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
@@ -164,8 +164,6 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
164 | }; | 164 | }; |
165 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); | 165 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); |
166 | 166 | ||
167 | if (e.cidr == 0) | ||
168 | return -EINVAL; | ||
169 | if (adt == IPSET_TEST) | 167 | if (adt == IPSET_TEST) |
170 | e.cidr = HOST_MASK; | 168 | e.cidr = HOST_MASK; |
171 | 169 | ||
@@ -377,8 +375,6 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
377 | }; | 375 | }; |
378 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); | 376 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); |
379 | 377 | ||
380 | if (e.cidr == 0) | ||
381 | return -EINVAL; | ||
382 | if (adt == IPSET_TEST) | 378 | if (adt == IPSET_TEST) |
383 | e.cidr = HOST_MASK; | 379 | e.cidr = HOST_MASK; |
384 | 380 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 3cb3cb831591..58882de06bd7 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -66,6 +66,21 @@ EXPORT_SYMBOL_GPL(nf_conntrack_locks); | |||
66 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock); | 66 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock); |
67 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); | 67 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); |
68 | 68 | ||
69 | static __read_mostly spinlock_t nf_conntrack_locks_all_lock; | ||
70 | static __read_mostly bool nf_conntrack_locks_all; | ||
71 | |||
72 | void nf_conntrack_lock(spinlock_t *lock) __acquires(lock) | ||
73 | { | ||
74 | spin_lock(lock); | ||
75 | while (unlikely(nf_conntrack_locks_all)) { | ||
76 | spin_unlock(lock); | ||
77 | spin_lock(&nf_conntrack_locks_all_lock); | ||
78 | spin_unlock(&nf_conntrack_locks_all_lock); | ||
79 | spin_lock(lock); | ||
80 | } | ||
81 | } | ||
82 | EXPORT_SYMBOL_GPL(nf_conntrack_lock); | ||
83 | |||
69 | static void nf_conntrack_double_unlock(unsigned int h1, unsigned int h2) | 84 | static void nf_conntrack_double_unlock(unsigned int h1, unsigned int h2) |
70 | { | 85 | { |
71 | h1 %= CONNTRACK_LOCKS; | 86 | h1 %= CONNTRACK_LOCKS; |
@@ -82,12 +97,12 @@ static bool nf_conntrack_double_lock(struct net *net, unsigned int h1, | |||
82 | h1 %= CONNTRACK_LOCKS; | 97 | h1 %= CONNTRACK_LOCKS; |
83 | h2 %= CONNTRACK_LOCKS; | 98 | h2 %= CONNTRACK_LOCKS; |
84 | if (h1 <= h2) { | 99 | if (h1 <= h2) { |
85 | spin_lock(&nf_conntrack_locks[h1]); | 100 | nf_conntrack_lock(&nf_conntrack_locks[h1]); |
86 | if (h1 != h2) | 101 | if (h1 != h2) |
87 | spin_lock_nested(&nf_conntrack_locks[h2], | 102 | spin_lock_nested(&nf_conntrack_locks[h2], |
88 | SINGLE_DEPTH_NESTING); | 103 | SINGLE_DEPTH_NESTING); |
89 | } else { | 104 | } else { |
90 | spin_lock(&nf_conntrack_locks[h2]); | 105 | nf_conntrack_lock(&nf_conntrack_locks[h2]); |
91 | spin_lock_nested(&nf_conntrack_locks[h1], | 106 | spin_lock_nested(&nf_conntrack_locks[h1], |
92 | SINGLE_DEPTH_NESTING); | 107 | SINGLE_DEPTH_NESTING); |
93 | } | 108 | } |
@@ -102,16 +117,19 @@ static void nf_conntrack_all_lock(void) | |||
102 | { | 117 | { |
103 | int i; | 118 | int i; |
104 | 119 | ||
105 | for (i = 0; i < CONNTRACK_LOCKS; i++) | 120 | spin_lock(&nf_conntrack_locks_all_lock); |
106 | spin_lock_nested(&nf_conntrack_locks[i], i); | 121 | nf_conntrack_locks_all = true; |
122 | |||
123 | for (i = 0; i < CONNTRACK_LOCKS; i++) { | ||
124 | spin_lock(&nf_conntrack_locks[i]); | ||
125 | spin_unlock(&nf_conntrack_locks[i]); | ||
126 | } | ||
107 | } | 127 | } |
108 | 128 | ||
109 | static void nf_conntrack_all_unlock(void) | 129 | static void nf_conntrack_all_unlock(void) |
110 | { | 130 | { |
111 | int i; | 131 | nf_conntrack_locks_all = false; |
112 | 132 | spin_unlock(&nf_conntrack_locks_all_lock); | |
113 | for (i = 0; i < CONNTRACK_LOCKS; i++) | ||
114 | spin_unlock(&nf_conntrack_locks[i]); | ||
115 | } | 133 | } |
116 | 134 | ||
117 | unsigned int nf_conntrack_htable_size __read_mostly; | 135 | unsigned int nf_conntrack_htable_size __read_mostly; |
@@ -757,7 +775,7 @@ restart: | |||
757 | hash = hash_bucket(_hash, net); | 775 | hash = hash_bucket(_hash, net); |
758 | for (; i < net->ct.htable_size; i++) { | 776 | for (; i < net->ct.htable_size; i++) { |
759 | lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS]; | 777 | lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS]; |
760 | spin_lock(lockp); | 778 | nf_conntrack_lock(lockp); |
761 | if (read_seqcount_retry(&net->ct.generation, sequence)) { | 779 | if (read_seqcount_retry(&net->ct.generation, sequence)) { |
762 | spin_unlock(lockp); | 780 | spin_unlock(lockp); |
763 | goto restart; | 781 | goto restart; |
@@ -1382,7 +1400,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), | |||
1382 | for (; *bucket < net->ct.htable_size; (*bucket)++) { | 1400 | for (; *bucket < net->ct.htable_size; (*bucket)++) { |
1383 | lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS]; | 1401 | lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS]; |
1384 | local_bh_disable(); | 1402 | local_bh_disable(); |
1385 | spin_lock(lockp); | 1403 | nf_conntrack_lock(lockp); |
1386 | if (*bucket < net->ct.htable_size) { | 1404 | if (*bucket < net->ct.htable_size) { |
1387 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { | 1405 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { |
1388 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 1406 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index bd9d31537905..3b40ec575cd5 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -425,7 +425,7 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, | |||
425 | } | 425 | } |
426 | local_bh_disable(); | 426 | local_bh_disable(); |
427 | for (i = 0; i < net->ct.htable_size; i++) { | 427 | for (i = 0; i < net->ct.htable_size; i++) { |
428 | spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | 428 | nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); |
429 | if (i < net->ct.htable_size) { | 429 | if (i < net->ct.htable_size) { |
430 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) | 430 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) |
431 | unhelp(h, me); | 431 | unhelp(h, me); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index dbb1bb3edb45..355e8552fd5b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -840,7 +840,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
840 | for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) { | 840 | for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) { |
841 | restart: | 841 | restart: |
842 | lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS]; | 842 | lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS]; |
843 | spin_lock(lockp); | 843 | nf_conntrack_lock(lockp); |
844 | if (cb->args[0] >= net->ct.htable_size) { | 844 | if (cb->args[0] >= net->ct.htable_size) { |
845 | spin_unlock(lockp); | 845 | spin_unlock(lockp); |
846 | goto out; | 846 | goto out; |
diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c index b6605e000801..5eefe4a355c6 100644 --- a/net/netfilter/nf_tables_netdev.c +++ b/net/netfilter/nf_tables_netdev.c | |||
@@ -224,12 +224,12 @@ static int __init nf_tables_netdev_init(void) | |||
224 | 224 | ||
225 | nft_register_chain_type(&nft_filter_chain_netdev); | 225 | nft_register_chain_type(&nft_filter_chain_netdev); |
226 | ret = register_pernet_subsys(&nf_tables_netdev_net_ops); | 226 | ret = register_pernet_subsys(&nf_tables_netdev_net_ops); |
227 | if (ret < 0) | 227 | if (ret < 0) { |
228 | nft_unregister_chain_type(&nft_filter_chain_netdev); | 228 | nft_unregister_chain_type(&nft_filter_chain_netdev); |
229 | 229 | return ret; | |
230 | } | ||
230 | register_netdevice_notifier(&nf_tables_netdev_notifier); | 231 | register_netdevice_notifier(&nf_tables_netdev_notifier); |
231 | 232 | return 0; | |
232 | return ret; | ||
233 | } | 233 | } |
234 | 234 | ||
235 | static void __exit nf_tables_netdev_exit(void) | 235 | static void __exit nf_tables_netdev_exit(void) |
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 5d010f27ac01..94837d236ab0 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c | |||
@@ -307,12 +307,12 @@ static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout) | |||
307 | 307 | ||
308 | local_bh_disable(); | 308 | local_bh_disable(); |
309 | for (i = 0; i < net->ct.htable_size; i++) { | 309 | for (i = 0; i < net->ct.htable_size; i++) { |
310 | spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | 310 | nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); |
311 | if (i < net->ct.htable_size) { | 311 | if (i < net->ct.htable_size) { |
312 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) | 312 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) |
313 | untimeout(h, timeout); | 313 | untimeout(h, timeout); |
314 | } | 314 | } |
315 | spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | 315 | nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); |
316 | } | 316 | } |
317 | local_bh_enable(); | 317 | local_bh_enable(); |
318 | } | 318 | } |
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index 383c17138399..b78c28ba465f 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c | |||
@@ -46,16 +46,14 @@ static void nft_byteorder_eval(const struct nft_expr *expr, | |||
46 | switch (priv->op) { | 46 | switch (priv->op) { |
47 | case NFT_BYTEORDER_NTOH: | 47 | case NFT_BYTEORDER_NTOH: |
48 | for (i = 0; i < priv->len / 8; i++) { | 48 | for (i = 0; i < priv->len / 8; i++) { |
49 | src64 = get_unaligned_be64(&src[i]); | 49 | src64 = get_unaligned((u64 *)&src[i]); |
50 | src64 = be64_to_cpu((__force __be64)src64); | ||
51 | put_unaligned_be64(src64, &dst[i]); | 50 | put_unaligned_be64(src64, &dst[i]); |
52 | } | 51 | } |
53 | break; | 52 | break; |
54 | case NFT_BYTEORDER_HTON: | 53 | case NFT_BYTEORDER_HTON: |
55 | for (i = 0; i < priv->len / 8; i++) { | 54 | for (i = 0; i < priv->len / 8; i++) { |
56 | src64 = get_unaligned_be64(&src[i]); | 55 | src64 = get_unaligned_be64(&src[i]); |
57 | src64 = (__force u64)cpu_to_be64(src64); | 56 | put_unaligned(src64, (u64 *)&dst[i]); |
58 | put_unaligned_be64(src64, &dst[i]); | ||
59 | } | 57 | } |
60 | break; | 58 | break; |
61 | } | 59 | } |
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index a0eb2161e3ef..d4a4619fcebc 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
@@ -127,6 +127,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
127 | NF_CT_LABELS_MAX_SIZE - size); | 127 | NF_CT_LABELS_MAX_SIZE - size); |
128 | return; | 128 | return; |
129 | } | 129 | } |
130 | #endif | ||
130 | case NFT_CT_BYTES: /* fallthrough */ | 131 | case NFT_CT_BYTES: /* fallthrough */ |
131 | case NFT_CT_PKTS: { | 132 | case NFT_CT_PKTS: { |
132 | const struct nf_conn_acct *acct = nf_conn_acct_find(ct); | 133 | const struct nf_conn_acct *acct = nf_conn_acct_find(ct); |
@@ -138,7 +139,6 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
138 | memcpy(dest, &count, sizeof(count)); | 139 | memcpy(dest, &count, sizeof(count)); |
139 | return; | 140 | return; |
140 | } | 141 | } |
141 | #endif | ||
142 | default: | 142 | default: |
143 | break; | 143 | break; |
144 | } | 144 | } |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index b7c43def0dc6..e118397254af 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -228,7 +228,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
228 | { | 228 | { |
229 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 229 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
230 | u8 nexthdr; | 230 | u8 nexthdr; |
231 | __be16 frag_off; | 231 | __be16 frag_off, oldlen, newlen; |
232 | int tcphoff; | 232 | int tcphoff; |
233 | int ret; | 233 | int ret; |
234 | 234 | ||
@@ -244,7 +244,12 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
244 | return NF_DROP; | 244 | return NF_DROP; |
245 | if (ret > 0) { | 245 | if (ret > 0) { |
246 | ipv6h = ipv6_hdr(skb); | 246 | ipv6h = ipv6_hdr(skb); |
247 | ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); | 247 | oldlen = ipv6h->payload_len; |
248 | newlen = htons(ntohs(oldlen) + ret); | ||
249 | if (skb->ip_summed == CHECKSUM_COMPLETE) | ||
250 | skb->csum = csum_add(csum_sub(skb->csum, oldlen), | ||
251 | newlen); | ||
252 | ipv6h->payload_len = newlen; | ||
248 | } | 253 | } |
249 | return XT_CONTINUE; | 254 | return XT_CONTINUE; |
250 | } | 255 | } |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 81dc1bb6e016..f1ffb34e253f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -2831,7 +2831,8 @@ static int netlink_dump(struct sock *sk) | |||
2831 | * reasonable static buffer based on the expected largest dump of a | 2831 | * reasonable static buffer based on the expected largest dump of a |
2832 | * single netdev. The outcome is MSG_TRUNC error. | 2832 | * single netdev. The outcome is MSG_TRUNC error. |
2833 | */ | 2833 | */ |
2834 | skb_reserve(skb, skb_tailroom(skb) - alloc_size); | 2834 | if (!netlink_rx_is_mmaped(sk)) |
2835 | skb_reserve(skb, skb_tailroom(skb) - alloc_size); | ||
2835 | netlink_skb_set_owner_r(skb, sk); | 2836 | netlink_skb_set_owner_r(skb, sk); |
2836 | 2837 | ||
2837 | len = cb->dump(skb, cb); | 2838 | len = cb->dump(skb, cb); |
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index c88d0f2d3e01..2d59df521915 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -1160,17 +1160,26 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb, | |||
1160 | const struct sw_flow_actions *acts, | 1160 | const struct sw_flow_actions *acts, |
1161 | struct sw_flow_key *key) | 1161 | struct sw_flow_key *key) |
1162 | { | 1162 | { |
1163 | int level = this_cpu_read(exec_actions_level); | 1163 | static const int ovs_recursion_limit = 5; |
1164 | int err; | 1164 | int err, level; |
1165 | |||
1166 | level = __this_cpu_inc_return(exec_actions_level); | ||
1167 | if (unlikely(level > ovs_recursion_limit)) { | ||
1168 | net_crit_ratelimited("ovs: recursion limit reached on datapath %s, probable configuration error\n", | ||
1169 | ovs_dp_name(dp)); | ||
1170 | kfree_skb(skb); | ||
1171 | err = -ENETDOWN; | ||
1172 | goto out; | ||
1173 | } | ||
1165 | 1174 | ||
1166 | this_cpu_inc(exec_actions_level); | ||
1167 | err = do_execute_actions(dp, skb, key, | 1175 | err = do_execute_actions(dp, skb, key, |
1168 | acts->actions, acts->actions_len); | 1176 | acts->actions, acts->actions_len); |
1169 | 1177 | ||
1170 | if (!level) | 1178 | if (level == 1) |
1171 | process_deferred_actions(dp); | 1179 | process_deferred_actions(dp); |
1172 | 1180 | ||
1173 | this_cpu_dec(exec_actions_level); | 1181 | out: |
1182 | __this_cpu_dec(exec_actions_level); | ||
1174 | return err; | 1183 | return err; |
1175 | } | 1184 | } |
1176 | 1185 | ||
diff --git a/net/rds/ib.c b/net/rds/ib.c index f222885ac0c7..9481d55ff6cb 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c | |||
@@ -122,44 +122,34 @@ void rds_ib_dev_put(struct rds_ib_device *rds_ibdev) | |||
122 | static void rds_ib_add_one(struct ib_device *device) | 122 | static void rds_ib_add_one(struct ib_device *device) |
123 | { | 123 | { |
124 | struct rds_ib_device *rds_ibdev; | 124 | struct rds_ib_device *rds_ibdev; |
125 | struct ib_device_attr *dev_attr; | ||
126 | 125 | ||
127 | /* Only handle IB (no iWARP) devices */ | 126 | /* Only handle IB (no iWARP) devices */ |
128 | if (device->node_type != RDMA_NODE_IB_CA) | 127 | if (device->node_type != RDMA_NODE_IB_CA) |
129 | return; | 128 | return; |
130 | 129 | ||
131 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); | ||
132 | if (!dev_attr) | ||
133 | return; | ||
134 | |||
135 | if (ib_query_device(device, dev_attr)) { | ||
136 | rdsdebug("Query device failed for %s\n", device->name); | ||
137 | goto free_attr; | ||
138 | } | ||
139 | |||
140 | rds_ibdev = kzalloc_node(sizeof(struct rds_ib_device), GFP_KERNEL, | 130 | rds_ibdev = kzalloc_node(sizeof(struct rds_ib_device), GFP_KERNEL, |
141 | ibdev_to_node(device)); | 131 | ibdev_to_node(device)); |
142 | if (!rds_ibdev) | 132 | if (!rds_ibdev) |
143 | goto free_attr; | 133 | return; |
144 | 134 | ||
145 | spin_lock_init(&rds_ibdev->spinlock); | 135 | spin_lock_init(&rds_ibdev->spinlock); |
146 | atomic_set(&rds_ibdev->refcount, 1); | 136 | atomic_set(&rds_ibdev->refcount, 1); |
147 | INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free); | 137 | INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free); |
148 | 138 | ||
149 | rds_ibdev->max_wrs = dev_attr->max_qp_wr; | 139 | rds_ibdev->max_wrs = device->attrs.max_qp_wr; |
150 | rds_ibdev->max_sge = min(dev_attr->max_sge, RDS_IB_MAX_SGE); | 140 | rds_ibdev->max_sge = min(device->attrs.max_sge, RDS_IB_MAX_SGE); |
151 | 141 | ||
152 | rds_ibdev->fmr_max_remaps = dev_attr->max_map_per_fmr?: 32; | 142 | rds_ibdev->fmr_max_remaps = device->attrs.max_map_per_fmr?: 32; |
153 | rds_ibdev->max_1m_fmrs = dev_attr->max_mr ? | 143 | rds_ibdev->max_1m_fmrs = device->attrs.max_mr ? |
154 | min_t(unsigned int, (dev_attr->max_mr / 2), | 144 | min_t(unsigned int, (device->attrs.max_mr / 2), |
155 | rds_ib_fmr_1m_pool_size) : rds_ib_fmr_1m_pool_size; | 145 | rds_ib_fmr_1m_pool_size) : rds_ib_fmr_1m_pool_size; |
156 | 146 | ||
157 | rds_ibdev->max_8k_fmrs = dev_attr->max_mr ? | 147 | rds_ibdev->max_8k_fmrs = device->attrs.max_mr ? |
158 | min_t(unsigned int, ((dev_attr->max_mr / 2) * RDS_MR_8K_SCALE), | 148 | min_t(unsigned int, ((device->attrs.max_mr / 2) * RDS_MR_8K_SCALE), |
159 | rds_ib_fmr_8k_pool_size) : rds_ib_fmr_8k_pool_size; | 149 | rds_ib_fmr_8k_pool_size) : rds_ib_fmr_8k_pool_size; |
160 | 150 | ||
161 | rds_ibdev->max_initiator_depth = dev_attr->max_qp_init_rd_atom; | 151 | rds_ibdev->max_initiator_depth = device->attrs.max_qp_init_rd_atom; |
162 | rds_ibdev->max_responder_resources = dev_attr->max_qp_rd_atom; | 152 | rds_ibdev->max_responder_resources = device->attrs.max_qp_rd_atom; |
163 | 153 | ||
164 | rds_ibdev->dev = device; | 154 | rds_ibdev->dev = device; |
165 | rds_ibdev->pd = ib_alloc_pd(device); | 155 | rds_ibdev->pd = ib_alloc_pd(device); |
@@ -183,7 +173,7 @@ static void rds_ib_add_one(struct ib_device *device) | |||
183 | } | 173 | } |
184 | 174 | ||
185 | rdsdebug("RDS/IB: max_mr = %d, max_wrs = %d, max_sge = %d, fmr_max_remaps = %d, max_1m_fmrs = %d, max_8k_fmrs = %d\n", | 175 | rdsdebug("RDS/IB: max_mr = %d, max_wrs = %d, max_sge = %d, fmr_max_remaps = %d, max_1m_fmrs = %d, max_8k_fmrs = %d\n", |
186 | dev_attr->max_fmr, rds_ibdev->max_wrs, rds_ibdev->max_sge, | 176 | device->attrs.max_fmr, rds_ibdev->max_wrs, rds_ibdev->max_sge, |
187 | rds_ibdev->fmr_max_remaps, rds_ibdev->max_1m_fmrs, | 177 | rds_ibdev->fmr_max_remaps, rds_ibdev->max_1m_fmrs, |
188 | rds_ibdev->max_8k_fmrs); | 178 | rds_ibdev->max_8k_fmrs); |
189 | 179 | ||
@@ -202,8 +192,6 @@ static void rds_ib_add_one(struct ib_device *device) | |||
202 | 192 | ||
203 | put_dev: | 193 | put_dev: |
204 | rds_ib_dev_put(rds_ibdev); | 194 | rds_ib_dev_put(rds_ibdev); |
205 | free_attr: | ||
206 | kfree(dev_attr); | ||
207 | } | 195 | } |
208 | 196 | ||
209 | /* | 197 | /* |
diff --git a/net/rds/iw.c b/net/rds/iw.c index 576f1825fc55..f4a9fff829e0 100644 --- a/net/rds/iw.c +++ b/net/rds/iw.c | |||
@@ -60,30 +60,20 @@ LIST_HEAD(iw_nodev_conns); | |||
60 | static void rds_iw_add_one(struct ib_device *device) | 60 | static void rds_iw_add_one(struct ib_device *device) |
61 | { | 61 | { |
62 | struct rds_iw_device *rds_iwdev; | 62 | struct rds_iw_device *rds_iwdev; |
63 | struct ib_device_attr *dev_attr; | ||
64 | 63 | ||
65 | /* Only handle iwarp devices */ | 64 | /* Only handle iwarp devices */ |
66 | if (device->node_type != RDMA_NODE_RNIC) | 65 | if (device->node_type != RDMA_NODE_RNIC) |
67 | return; | 66 | return; |
68 | 67 | ||
69 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); | ||
70 | if (!dev_attr) | ||
71 | return; | ||
72 | |||
73 | if (ib_query_device(device, dev_attr)) { | ||
74 | rdsdebug("Query device failed for %s\n", device->name); | ||
75 | goto free_attr; | ||
76 | } | ||
77 | |||
78 | rds_iwdev = kmalloc(sizeof *rds_iwdev, GFP_KERNEL); | 68 | rds_iwdev = kmalloc(sizeof *rds_iwdev, GFP_KERNEL); |
79 | if (!rds_iwdev) | 69 | if (!rds_iwdev) |
80 | goto free_attr; | 70 | return; |
81 | 71 | ||
82 | spin_lock_init(&rds_iwdev->spinlock); | 72 | spin_lock_init(&rds_iwdev->spinlock); |
83 | 73 | ||
84 | rds_iwdev->dma_local_lkey = !!(dev_attr->device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY); | 74 | rds_iwdev->dma_local_lkey = !!(device->attrs.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY); |
85 | rds_iwdev->max_wrs = dev_attr->max_qp_wr; | 75 | rds_iwdev->max_wrs = device->attrs.max_qp_wr; |
86 | rds_iwdev->max_sge = min(dev_attr->max_sge, RDS_IW_MAX_SGE); | 76 | rds_iwdev->max_sge = min(device->attrs.max_sge, RDS_IW_MAX_SGE); |
87 | 77 | ||
88 | rds_iwdev->dev = device; | 78 | rds_iwdev->dev = device; |
89 | rds_iwdev->pd = ib_alloc_pd(device); | 79 | rds_iwdev->pd = ib_alloc_pd(device); |
@@ -111,8 +101,7 @@ static void rds_iw_add_one(struct ib_device *device) | |||
111 | list_add_tail(&rds_iwdev->list, &rds_iw_devices); | 101 | list_add_tail(&rds_iwdev->list, &rds_iw_devices); |
112 | 102 | ||
113 | ib_set_client_data(device, &rds_iw_client, rds_iwdev); | 103 | ib_set_client_data(device, &rds_iw_client, rds_iwdev); |
114 | 104 | return; | |
115 | goto free_attr; | ||
116 | 105 | ||
117 | err_mr: | 106 | err_mr: |
118 | if (rds_iwdev->mr) | 107 | if (rds_iwdev->mr) |
@@ -121,8 +110,6 @@ err_pd: | |||
121 | ib_dealloc_pd(rds_iwdev->pd); | 110 | ib_dealloc_pd(rds_iwdev->pd); |
122 | free_dev: | 111 | free_dev: |
123 | kfree(rds_iwdev); | 112 | kfree(rds_iwdev); |
124 | free_attr: | ||
125 | kfree(dev_attr); | ||
126 | } | 113 | } |
127 | 114 | ||
128 | static void rds_iw_remove_one(struct ib_device *device, void *client_data) | 115 | static void rds_iw_remove_one(struct ib_device *device, void *client_data) |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index f53bf3b6558b..cf5b69ab1829 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -1095,17 +1095,6 @@ static unsigned int rfkill_fop_poll(struct file *file, poll_table *wait) | |||
1095 | return res; | 1095 | return res; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | static bool rfkill_readable(struct rfkill_data *data) | ||
1099 | { | ||
1100 | bool r; | ||
1101 | |||
1102 | mutex_lock(&data->mtx); | ||
1103 | r = !list_empty(&data->events); | ||
1104 | mutex_unlock(&data->mtx); | ||
1105 | |||
1106 | return r; | ||
1107 | } | ||
1108 | |||
1109 | static ssize_t rfkill_fop_read(struct file *file, char __user *buf, | 1098 | static ssize_t rfkill_fop_read(struct file *file, char __user *buf, |
1110 | size_t count, loff_t *pos) | 1099 | size_t count, loff_t *pos) |
1111 | { | 1100 | { |
@@ -1122,8 +1111,11 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf, | |||
1122 | goto out; | 1111 | goto out; |
1123 | } | 1112 | } |
1124 | mutex_unlock(&data->mtx); | 1113 | mutex_unlock(&data->mtx); |
1114 | /* since we re-check and it just compares pointers, | ||
1115 | * using !list_empty() without locking isn't a problem | ||
1116 | */ | ||
1125 | ret = wait_event_interruptible(data->read_wait, | 1117 | ret = wait_event_interruptible(data->read_wait, |
1126 | rfkill_readable(data)); | 1118 | !list_empty(&data->events)); |
1127 | mutex_lock(&data->mtx); | 1119 | mutex_lock(&data->mtx); |
1128 | 1120 | ||
1129 | if (ret) | 1121 | if (ret) |
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index f26bdea875c1..a1cd778240cd 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
@@ -403,6 +403,8 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) | |||
403 | if (len <= cl->deficit) { | 403 | if (len <= cl->deficit) { |
404 | cl->deficit -= len; | 404 | cl->deficit -= len; |
405 | skb = qdisc_dequeue_peeked(cl->qdisc); | 405 | skb = qdisc_dequeue_peeked(cl->qdisc); |
406 | if (unlikely(skb == NULL)) | ||
407 | goto out; | ||
406 | if (cl->qdisc->q.qlen == 0) | 408 | if (cl->qdisc->q.qlen == 0) |
407 | list_del(&cl->alist); | 409 | list_del(&cl->alist); |
408 | 410 | ||
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 52838eaa1582..2522a6175291 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -333,7 +333,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc( | |||
333 | if (!ep->base.bind_addr.port) | 333 | if (!ep->base.bind_addr.port) |
334 | goto out; | 334 | goto out; |
335 | t = sctp_epaddr_lookup_transport(ep, paddr); | 335 | t = sctp_epaddr_lookup_transport(ep, paddr); |
336 | if (!t || t->asoc->temp) | 336 | if (!t) |
337 | goto out; | 337 | goto out; |
338 | 338 | ||
339 | *transport = t; | 339 | *transport = t; |
diff --git a/net/sctp/input.c b/net/sctp/input.c index b9a536b52da2..49d2cc751386 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -874,6 +874,9 @@ void sctp_hash_transport(struct sctp_transport *t) | |||
874 | { | 874 | { |
875 | struct sctp_hash_cmp_arg arg; | 875 | struct sctp_hash_cmp_arg arg; |
876 | 876 | ||
877 | if (t->asoc->temp) | ||
878 | return; | ||
879 | |||
877 | arg.ep = t->asoc->ep; | 880 | arg.ep = t->asoc->ep; |
878 | arg.paddr = &t->ipaddr; | 881 | arg.paddr = &t->ipaddr; |
879 | arg.net = sock_net(t->asoc->base.sk); | 882 | arg.net = sock_net(t->asoc->base.sk); |
@@ -886,6 +889,9 @@ reinsert: | |||
886 | 889 | ||
887 | void sctp_unhash_transport(struct sctp_transport *t) | 890 | void sctp_unhash_transport(struct sctp_transport *t) |
888 | { | 891 | { |
892 | if (t->asoc->temp) | ||
893 | return; | ||
894 | |||
889 | rhashtable_remove_fast(&sctp_transport_hashtable, &t->node, | 895 | rhashtable_remove_fast(&sctp_transport_hashtable, &t->node, |
890 | sctp_hash_params); | 896 | sctp_hash_params); |
891 | } | 897 | } |
@@ -929,15 +935,22 @@ static struct sctp_association *__sctp_lookup_association( | |||
929 | struct sctp_transport **pt) | 935 | struct sctp_transport **pt) |
930 | { | 936 | { |
931 | struct sctp_transport *t; | 937 | struct sctp_transport *t; |
938 | struct sctp_association *asoc = NULL; | ||
932 | 939 | ||
940 | rcu_read_lock(); | ||
933 | t = sctp_addrs_lookup_transport(net, local, peer); | 941 | t = sctp_addrs_lookup_transport(net, local, peer); |
934 | if (!t || t->dead || t->asoc->temp) | 942 | if (!t || !sctp_transport_hold(t)) |
935 | return NULL; | 943 | goto out; |
936 | 944 | ||
937 | sctp_association_hold(t->asoc); | 945 | asoc = t->asoc; |
946 | sctp_association_hold(asoc); | ||
938 | *pt = t; | 947 | *pt = t; |
939 | 948 | ||
940 | return t->asoc; | 949 | sctp_transport_put(t); |
950 | |||
951 | out: | ||
952 | rcu_read_unlock(); | ||
953 | return asoc; | ||
941 | } | 954 | } |
942 | 955 | ||
943 | /* Look up an association. protected by RCU read lock */ | 956 | /* Look up an association. protected by RCU read lock */ |
@@ -949,9 +962,7 @@ struct sctp_association *sctp_lookup_association(struct net *net, | |||
949 | { | 962 | { |
950 | struct sctp_association *asoc; | 963 | struct sctp_association *asoc; |
951 | 964 | ||
952 | rcu_read_lock(); | ||
953 | asoc = __sctp_lookup_association(net, laddr, paddr, transportp); | 965 | asoc = __sctp_lookup_association(net, laddr, paddr, transportp); |
954 | rcu_read_unlock(); | ||
955 | 966 | ||
956 | return asoc; | 967 | return asoc; |
957 | } | 968 | } |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 684c5b31563b..ded7d931a6a5 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -165,8 +165,6 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa | |||
165 | list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list, | 165 | list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list, |
166 | transports) { | 166 | transports) { |
167 | addr = &transport->ipaddr; | 167 | addr = &transport->ipaddr; |
168 | if (transport->dead) | ||
169 | continue; | ||
170 | 168 | ||
171 | af = sctp_get_af_specific(addr->sa.sa_family); | 169 | af = sctp_get_af_specific(addr->sa.sa_family); |
172 | if (af->cmp_addr(addr, primary)) { | 170 | if (af->cmp_addr(addr, primary)) { |
@@ -380,6 +378,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
380 | } | 378 | } |
381 | 379 | ||
382 | transport = (struct sctp_transport *)v; | 380 | transport = (struct sctp_transport *)v; |
381 | if (!sctp_transport_hold(transport)) | ||
382 | return 0; | ||
383 | assoc = transport->asoc; | 383 | assoc = transport->asoc; |
384 | epb = &assoc->base; | 384 | epb = &assoc->base; |
385 | sk = epb->sk; | 385 | sk = epb->sk; |
@@ -412,6 +412,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
412 | sk->sk_rcvbuf); | 412 | sk->sk_rcvbuf); |
413 | seq_printf(seq, "\n"); | 413 | seq_printf(seq, "\n"); |
414 | 414 | ||
415 | sctp_transport_put(transport); | ||
416 | |||
415 | return 0; | 417 | return 0; |
416 | } | 418 | } |
417 | 419 | ||
@@ -489,12 +491,12 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | |||
489 | } | 491 | } |
490 | 492 | ||
491 | tsp = (struct sctp_transport *)v; | 493 | tsp = (struct sctp_transport *)v; |
494 | if (!sctp_transport_hold(tsp)) | ||
495 | return 0; | ||
492 | assoc = tsp->asoc; | 496 | assoc = tsp->asoc; |
493 | 497 | ||
494 | list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, | 498 | list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, |
495 | transports) { | 499 | transports) { |
496 | if (tsp->dead) | ||
497 | continue; | ||
498 | /* | 500 | /* |
499 | * The remote address (ADDR) | 501 | * The remote address (ADDR) |
500 | */ | 502 | */ |
@@ -544,6 +546,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | |||
544 | seq_printf(seq, "\n"); | 546 | seq_printf(seq, "\n"); |
545 | } | 547 | } |
546 | 548 | ||
549 | sctp_transport_put(tsp); | ||
550 | |||
547 | return 0; | 551 | return 0; |
548 | } | 552 | } |
549 | 553 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 2e21384697c2..b5327bb77458 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -259,12 +259,6 @@ void sctp_generate_t3_rtx_event(unsigned long peer) | |||
259 | goto out_unlock; | 259 | goto out_unlock; |
260 | } | 260 | } |
261 | 261 | ||
262 | /* Is this transport really dead and just waiting around for | ||
263 | * the timer to let go of the reference? | ||
264 | */ | ||
265 | if (transport->dead) | ||
266 | goto out_unlock; | ||
267 | |||
268 | /* Run through the state machine. */ | 262 | /* Run through the state machine. */ |
269 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, | 263 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, |
270 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX), | 264 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX), |
@@ -380,12 +374,6 @@ void sctp_generate_heartbeat_event(unsigned long data) | |||
380 | goto out_unlock; | 374 | goto out_unlock; |
381 | } | 375 | } |
382 | 376 | ||
383 | /* Is this structure just waiting around for us to actually | ||
384 | * get destroyed? | ||
385 | */ | ||
386 | if (transport->dead) | ||
387 | goto out_unlock; | ||
388 | |||
389 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, | 377 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, |
390 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT), | 378 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT), |
391 | asoc->state, asoc->ep, asoc, | 379 | asoc->state, asoc->ep, asoc, |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9bb80ec4c08f..5ca2ebfe0be8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -6636,6 +6636,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) | |||
6636 | 6636 | ||
6637 | if (cmsgs->srinfo->sinfo_flags & | 6637 | if (cmsgs->srinfo->sinfo_flags & |
6638 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | | 6638 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
6639 | SCTP_SACK_IMMEDIATELY | | ||
6639 | SCTP_ABORT | SCTP_EOF)) | 6640 | SCTP_ABORT | SCTP_EOF)) |
6640 | return -EINVAL; | 6641 | return -EINVAL; |
6641 | break; | 6642 | break; |
@@ -6659,6 +6660,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) | |||
6659 | 6660 | ||
6660 | if (cmsgs->sinfo->snd_flags & | 6661 | if (cmsgs->sinfo->snd_flags & |
6661 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | | 6662 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
6663 | SCTP_SACK_IMMEDIATELY | | ||
6662 | SCTP_ABORT | SCTP_EOF)) | 6664 | SCTP_ABORT | SCTP_EOF)) |
6663 | return -EINVAL; | 6665 | return -EINVAL; |
6664 | break; | 6666 | break; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index aab9e3f29755..a431c14044a4 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -132,8 +132,6 @@ fail: | |||
132 | */ | 132 | */ |
133 | void sctp_transport_free(struct sctp_transport *transport) | 133 | void sctp_transport_free(struct sctp_transport *transport) |
134 | { | 134 | { |
135 | transport->dead = 1; | ||
136 | |||
137 | /* Try to delete the heartbeat timer. */ | 135 | /* Try to delete the heartbeat timer. */ |
138 | if (del_timer(&transport->hb_timer)) | 136 | if (del_timer(&transport->hb_timer)) |
139 | sctp_transport_put(transport); | 137 | sctp_transport_put(transport); |
@@ -169,7 +167,7 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head) | |||
169 | */ | 167 | */ |
170 | static void sctp_transport_destroy(struct sctp_transport *transport) | 168 | static void sctp_transport_destroy(struct sctp_transport *transport) |
171 | { | 169 | { |
172 | if (unlikely(!transport->dead)) { | 170 | if (unlikely(atomic_read(&transport->refcnt))) { |
173 | WARN(1, "Attempt to destroy undead transport %p!\n", transport); | 171 | WARN(1, "Attempt to destroy undead transport %p!\n", transport); |
174 | return; | 172 | return; |
175 | } | 173 | } |
@@ -296,9 +294,9 @@ void sctp_transport_route(struct sctp_transport *transport, | |||
296 | } | 294 | } |
297 | 295 | ||
298 | /* Hold a reference to a transport. */ | 296 | /* Hold a reference to a transport. */ |
299 | void sctp_transport_hold(struct sctp_transport *transport) | 297 | int sctp_transport_hold(struct sctp_transport *transport) |
300 | { | 298 | { |
301 | atomic_inc(&transport->refcnt); | 299 | return atomic_add_unless(&transport->refcnt, 1, 0); |
302 | } | 300 | } |
303 | 301 | ||
304 | /* Release a reference to a transport and clean up | 302 | /* Release a reference to a transport and clean up |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 5e4f815c2b34..2b32fd602669 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -771,7 +771,7 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, | |||
771 | if (count == 0) | 771 | if (count == 0) |
772 | return 0; | 772 | return 0; |
773 | 773 | ||
774 | mutex_lock(&inode->i_mutex); /* protect against multiple concurrent | 774 | inode_lock(inode); /* protect against multiple concurrent |
775 | * readers on this file */ | 775 | * readers on this file */ |
776 | again: | 776 | again: |
777 | spin_lock(&queue_lock); | 777 | spin_lock(&queue_lock); |
@@ -784,7 +784,7 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, | |||
784 | } | 784 | } |
785 | if (rp->q.list.next == &cd->queue) { | 785 | if (rp->q.list.next == &cd->queue) { |
786 | spin_unlock(&queue_lock); | 786 | spin_unlock(&queue_lock); |
787 | mutex_unlock(&inode->i_mutex); | 787 | inode_unlock(inode); |
788 | WARN_ON_ONCE(rp->offset); | 788 | WARN_ON_ONCE(rp->offset); |
789 | return 0; | 789 | return 0; |
790 | } | 790 | } |
@@ -838,7 +838,7 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, | |||
838 | } | 838 | } |
839 | if (err == -EAGAIN) | 839 | if (err == -EAGAIN) |
840 | goto again; | 840 | goto again; |
841 | mutex_unlock(&inode->i_mutex); | 841 | inode_unlock(inode); |
842 | return err ? err : count; | 842 | return err ? err : count; |
843 | } | 843 | } |
844 | 844 | ||
@@ -909,9 +909,9 @@ static ssize_t cache_write(struct file *filp, const char __user *buf, | |||
909 | if (!cd->cache_parse) | 909 | if (!cd->cache_parse) |
910 | goto out; | 910 | goto out; |
911 | 911 | ||
912 | mutex_lock(&inode->i_mutex); | 912 | inode_lock(inode); |
913 | ret = cache_downcall(mapping, buf, count, cd); | 913 | ret = cache_downcall(mapping, buf, count, cd); |
914 | mutex_unlock(&inode->i_mutex); | 914 | inode_unlock(inode); |
915 | out: | 915 | out: |
916 | return ret; | 916 | return ret; |
917 | } | 917 | } |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 14f45bf0410c..31789ef3e614 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -172,7 +172,7 @@ rpc_close_pipes(struct inode *inode) | |||
172 | int need_release; | 172 | int need_release; |
173 | LIST_HEAD(free_list); | 173 | LIST_HEAD(free_list); |
174 | 174 | ||
175 | mutex_lock(&inode->i_mutex); | 175 | inode_lock(inode); |
176 | spin_lock(&pipe->lock); | 176 | spin_lock(&pipe->lock); |
177 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; | 177 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; |
178 | pipe->nreaders = 0; | 178 | pipe->nreaders = 0; |
@@ -188,7 +188,7 @@ rpc_close_pipes(struct inode *inode) | |||
188 | cancel_delayed_work_sync(&pipe->queue_timeout); | 188 | cancel_delayed_work_sync(&pipe->queue_timeout); |
189 | rpc_inode_setowner(inode, NULL); | 189 | rpc_inode_setowner(inode, NULL); |
190 | RPC_I(inode)->pipe = NULL; | 190 | RPC_I(inode)->pipe = NULL; |
191 | mutex_unlock(&inode->i_mutex); | 191 | inode_unlock(inode); |
192 | } | 192 | } |
193 | 193 | ||
194 | static struct inode * | 194 | static struct inode * |
@@ -221,7 +221,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp) | |||
221 | int first_open; | 221 | int first_open; |
222 | int res = -ENXIO; | 222 | int res = -ENXIO; |
223 | 223 | ||
224 | mutex_lock(&inode->i_mutex); | 224 | inode_lock(inode); |
225 | pipe = RPC_I(inode)->pipe; | 225 | pipe = RPC_I(inode)->pipe; |
226 | if (pipe == NULL) | 226 | if (pipe == NULL) |
227 | goto out; | 227 | goto out; |
@@ -237,7 +237,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp) | |||
237 | pipe->nwriters++; | 237 | pipe->nwriters++; |
238 | res = 0; | 238 | res = 0; |
239 | out: | 239 | out: |
240 | mutex_unlock(&inode->i_mutex); | 240 | inode_unlock(inode); |
241 | return res; | 241 | return res; |
242 | } | 242 | } |
243 | 243 | ||
@@ -248,7 +248,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
248 | struct rpc_pipe_msg *msg; | 248 | struct rpc_pipe_msg *msg; |
249 | int last_close; | 249 | int last_close; |
250 | 250 | ||
251 | mutex_lock(&inode->i_mutex); | 251 | inode_lock(inode); |
252 | pipe = RPC_I(inode)->pipe; | 252 | pipe = RPC_I(inode)->pipe; |
253 | if (pipe == NULL) | 253 | if (pipe == NULL) |
254 | goto out; | 254 | goto out; |
@@ -278,7 +278,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
278 | if (last_close && pipe->ops->release_pipe) | 278 | if (last_close && pipe->ops->release_pipe) |
279 | pipe->ops->release_pipe(inode); | 279 | pipe->ops->release_pipe(inode); |
280 | out: | 280 | out: |
281 | mutex_unlock(&inode->i_mutex); | 281 | inode_unlock(inode); |
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
@@ -290,7 +290,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
290 | struct rpc_pipe_msg *msg; | 290 | struct rpc_pipe_msg *msg; |
291 | int res = 0; | 291 | int res = 0; |
292 | 292 | ||
293 | mutex_lock(&inode->i_mutex); | 293 | inode_lock(inode); |
294 | pipe = RPC_I(inode)->pipe; | 294 | pipe = RPC_I(inode)->pipe; |
295 | if (pipe == NULL) { | 295 | if (pipe == NULL) { |
296 | res = -EPIPE; | 296 | res = -EPIPE; |
@@ -322,7 +322,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
322 | pipe->ops->destroy_msg(msg); | 322 | pipe->ops->destroy_msg(msg); |
323 | } | 323 | } |
324 | out_unlock: | 324 | out_unlock: |
325 | mutex_unlock(&inode->i_mutex); | 325 | inode_unlock(inode); |
326 | return res; | 326 | return res; |
327 | } | 327 | } |
328 | 328 | ||
@@ -332,11 +332,11 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of | |||
332 | struct inode *inode = file_inode(filp); | 332 | struct inode *inode = file_inode(filp); |
333 | int res; | 333 | int res; |
334 | 334 | ||
335 | mutex_lock(&inode->i_mutex); | 335 | inode_lock(inode); |
336 | res = -EPIPE; | 336 | res = -EPIPE; |
337 | if (RPC_I(inode)->pipe != NULL) | 337 | if (RPC_I(inode)->pipe != NULL) |
338 | res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len); | 338 | res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len); |
339 | mutex_unlock(&inode->i_mutex); | 339 | inode_unlock(inode); |
340 | return res; | 340 | return res; |
341 | } | 341 | } |
342 | 342 | ||
@@ -349,12 +349,12 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | |||
349 | 349 | ||
350 | poll_wait(filp, &rpci->waitq, wait); | 350 | poll_wait(filp, &rpci->waitq, wait); |
351 | 351 | ||
352 | mutex_lock(&inode->i_mutex); | 352 | inode_lock(inode); |
353 | if (rpci->pipe == NULL) | 353 | if (rpci->pipe == NULL) |
354 | mask |= POLLERR | POLLHUP; | 354 | mask |= POLLERR | POLLHUP; |
355 | else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) | 355 | else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) |
356 | mask |= POLLIN | POLLRDNORM; | 356 | mask |= POLLIN | POLLRDNORM; |
357 | mutex_unlock(&inode->i_mutex); | 357 | inode_unlock(inode); |
358 | return mask; | 358 | return mask; |
359 | } | 359 | } |
360 | 360 | ||
@@ -367,10 +367,10 @@ rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
367 | 367 | ||
368 | switch (cmd) { | 368 | switch (cmd) { |
369 | case FIONREAD: | 369 | case FIONREAD: |
370 | mutex_lock(&inode->i_mutex); | 370 | inode_lock(inode); |
371 | pipe = RPC_I(inode)->pipe; | 371 | pipe = RPC_I(inode)->pipe; |
372 | if (pipe == NULL) { | 372 | if (pipe == NULL) { |
373 | mutex_unlock(&inode->i_mutex); | 373 | inode_unlock(inode); |
374 | return -EPIPE; | 374 | return -EPIPE; |
375 | } | 375 | } |
376 | spin_lock(&pipe->lock); | 376 | spin_lock(&pipe->lock); |
@@ -381,7 +381,7 @@ rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
381 | len += msg->len - msg->copied; | 381 | len += msg->len - msg->copied; |
382 | } | 382 | } |
383 | spin_unlock(&pipe->lock); | 383 | spin_unlock(&pipe->lock); |
384 | mutex_unlock(&inode->i_mutex); | 384 | inode_unlock(inode); |
385 | return put_user(len, (int __user *)arg); | 385 | return put_user(len, (int __user *)arg); |
386 | default: | 386 | default: |
387 | return -EINVAL; | 387 | return -EINVAL; |
@@ -617,9 +617,9 @@ int rpc_rmdir(struct dentry *dentry) | |||
617 | 617 | ||
618 | parent = dget_parent(dentry); | 618 | parent = dget_parent(dentry); |
619 | dir = d_inode(parent); | 619 | dir = d_inode(parent); |
620 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 620 | inode_lock_nested(dir, I_MUTEX_PARENT); |
621 | error = __rpc_rmdir(dir, dentry); | 621 | error = __rpc_rmdir(dir, dentry); |
622 | mutex_unlock(&dir->i_mutex); | 622 | inode_unlock(dir); |
623 | dput(parent); | 623 | dput(parent); |
624 | return error; | 624 | return error; |
625 | } | 625 | } |
@@ -701,9 +701,9 @@ static void rpc_depopulate(struct dentry *parent, | |||
701 | { | 701 | { |
702 | struct inode *dir = d_inode(parent); | 702 | struct inode *dir = d_inode(parent); |
703 | 703 | ||
704 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD); | 704 | inode_lock_nested(dir, I_MUTEX_CHILD); |
705 | __rpc_depopulate(parent, files, start, eof); | 705 | __rpc_depopulate(parent, files, start, eof); |
706 | mutex_unlock(&dir->i_mutex); | 706 | inode_unlock(dir); |
707 | } | 707 | } |
708 | 708 | ||
709 | static int rpc_populate(struct dentry *parent, | 709 | static int rpc_populate(struct dentry *parent, |
@@ -715,7 +715,7 @@ static int rpc_populate(struct dentry *parent, | |||
715 | struct dentry *dentry; | 715 | struct dentry *dentry; |
716 | int i, err; | 716 | int i, err; |
717 | 717 | ||
718 | mutex_lock(&dir->i_mutex); | 718 | inode_lock(dir); |
719 | for (i = start; i < eof; i++) { | 719 | for (i = start; i < eof; i++) { |
720 | dentry = __rpc_lookup_create_exclusive(parent, files[i].name); | 720 | dentry = __rpc_lookup_create_exclusive(parent, files[i].name); |
721 | err = PTR_ERR(dentry); | 721 | err = PTR_ERR(dentry); |
@@ -739,11 +739,11 @@ static int rpc_populate(struct dentry *parent, | |||
739 | if (err != 0) | 739 | if (err != 0) |
740 | goto out_bad; | 740 | goto out_bad; |
741 | } | 741 | } |
742 | mutex_unlock(&dir->i_mutex); | 742 | inode_unlock(dir); |
743 | return 0; | 743 | return 0; |
744 | out_bad: | 744 | out_bad: |
745 | __rpc_depopulate(parent, files, start, eof); | 745 | __rpc_depopulate(parent, files, start, eof); |
746 | mutex_unlock(&dir->i_mutex); | 746 | inode_unlock(dir); |
747 | printk(KERN_WARNING "%s: %s failed to populate directory %pd\n", | 747 | printk(KERN_WARNING "%s: %s failed to populate directory %pd\n", |
748 | __FILE__, __func__, parent); | 748 | __FILE__, __func__, parent); |
749 | return err; | 749 | return err; |
@@ -757,7 +757,7 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent, | |||
757 | struct inode *dir = d_inode(parent); | 757 | struct inode *dir = d_inode(parent); |
758 | int error; | 758 | int error; |
759 | 759 | ||
760 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 760 | inode_lock_nested(dir, I_MUTEX_PARENT); |
761 | dentry = __rpc_lookup_create_exclusive(parent, name); | 761 | dentry = __rpc_lookup_create_exclusive(parent, name); |
762 | if (IS_ERR(dentry)) | 762 | if (IS_ERR(dentry)) |
763 | goto out; | 763 | goto out; |
@@ -770,7 +770,7 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent, | |||
770 | goto err_rmdir; | 770 | goto err_rmdir; |
771 | } | 771 | } |
772 | out: | 772 | out: |
773 | mutex_unlock(&dir->i_mutex); | 773 | inode_unlock(dir); |
774 | return dentry; | 774 | return dentry; |
775 | err_rmdir: | 775 | err_rmdir: |
776 | __rpc_rmdir(dir, dentry); | 776 | __rpc_rmdir(dir, dentry); |
@@ -788,11 +788,11 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
788 | 788 | ||
789 | parent = dget_parent(dentry); | 789 | parent = dget_parent(dentry); |
790 | dir = d_inode(parent); | 790 | dir = d_inode(parent); |
791 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 791 | inode_lock_nested(dir, I_MUTEX_PARENT); |
792 | if (depopulate != NULL) | 792 | if (depopulate != NULL) |
793 | depopulate(dentry); | 793 | depopulate(dentry); |
794 | error = __rpc_rmdir(dir, dentry); | 794 | error = __rpc_rmdir(dir, dentry); |
795 | mutex_unlock(&dir->i_mutex); | 795 | inode_unlock(dir); |
796 | dput(parent); | 796 | dput(parent); |
797 | return error; | 797 | return error; |
798 | } | 798 | } |
@@ -828,7 +828,7 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, | |||
828 | if (pipe->ops->downcall == NULL) | 828 | if (pipe->ops->downcall == NULL) |
829 | umode &= ~S_IWUGO; | 829 | umode &= ~S_IWUGO; |
830 | 830 | ||
831 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 831 | inode_lock_nested(dir, I_MUTEX_PARENT); |
832 | dentry = __rpc_lookup_create_exclusive(parent, name); | 832 | dentry = __rpc_lookup_create_exclusive(parent, name); |
833 | if (IS_ERR(dentry)) | 833 | if (IS_ERR(dentry)) |
834 | goto out; | 834 | goto out; |
@@ -837,7 +837,7 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, | |||
837 | if (err) | 837 | if (err) |
838 | goto out_err; | 838 | goto out_err; |
839 | out: | 839 | out: |
840 | mutex_unlock(&dir->i_mutex); | 840 | inode_unlock(dir); |
841 | return dentry; | 841 | return dentry; |
842 | out_err: | 842 | out_err: |
843 | dentry = ERR_PTR(err); | 843 | dentry = ERR_PTR(err); |
@@ -865,9 +865,9 @@ rpc_unlink(struct dentry *dentry) | |||
865 | 865 | ||
866 | parent = dget_parent(dentry); | 866 | parent = dget_parent(dentry); |
867 | dir = d_inode(parent); | 867 | dir = d_inode(parent); |
868 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 868 | inode_lock_nested(dir, I_MUTEX_PARENT); |
869 | error = __rpc_rmpipe(dir, dentry); | 869 | error = __rpc_rmpipe(dir, dentry); |
870 | mutex_unlock(&dir->i_mutex); | 870 | inode_unlock(dir); |
871 | dput(parent); | 871 | dput(parent); |
872 | return error; | 872 | return error; |
873 | } | 873 | } |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 2e98f4a243e5..37edea6fa92d 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1425,3 +1425,4 @@ void xprt_put(struct rpc_xprt *xprt) | |||
1425 | if (atomic_dec_and_test(&xprt->count)) | 1425 | if (atomic_dec_and_test(&xprt->count)) |
1426 | xprt_destroy(xprt); | 1426 | xprt_destroy(xprt); |
1427 | } | 1427 | } |
1428 | EXPORT_SYMBOL_GPL(xprt_put); | ||
diff --git a/net/sunrpc/xprtrdma/Makefile b/net/sunrpc/xprtrdma/Makefile index 33f99d3004f2..dc9f3b513a05 100644 --- a/net/sunrpc/xprtrdma/Makefile +++ b/net/sunrpc/xprtrdma/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_SUNRPC_XPRT_RDMA) += rpcrdma.o | |||
2 | 2 | ||
3 | rpcrdma-y := transport.o rpc_rdma.o verbs.o \ | 3 | rpcrdma-y := transport.o rpc_rdma.o verbs.o \ |
4 | fmr_ops.o frwr_ops.o physical_ops.o \ | 4 | fmr_ops.o frwr_ops.o physical_ops.o \ |
5 | svc_rdma.o svc_rdma_transport.o \ | 5 | svc_rdma.o svc_rdma_backchannel.o svc_rdma_transport.o \ |
6 | svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o \ | 6 | svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o \ |
7 | module.o | 7 | module.o |
8 | rpcrdma-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel.o | 8 | rpcrdma-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel.o |
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index c6836844bd0e..e16567389e28 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -190,12 +190,11 @@ static int | |||
190 | frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, | 190 | frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, |
191 | struct rpcrdma_create_data_internal *cdata) | 191 | struct rpcrdma_create_data_internal *cdata) |
192 | { | 192 | { |
193 | struct ib_device_attr *devattr = &ia->ri_devattr; | ||
194 | int depth, delta; | 193 | int depth, delta; |
195 | 194 | ||
196 | ia->ri_max_frmr_depth = | 195 | ia->ri_max_frmr_depth = |
197 | min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS, | 196 | min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS, |
198 | devattr->max_fast_reg_page_list_len); | 197 | ia->ri_device->attrs.max_fast_reg_page_list_len); |
199 | dprintk("RPC: %s: device's max FR page list len = %u\n", | 198 | dprintk("RPC: %s: device's max FR page list len = %u\n", |
200 | __func__, ia->ri_max_frmr_depth); | 199 | __func__, ia->ri_max_frmr_depth); |
201 | 200 | ||
@@ -222,8 +221,8 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, | |||
222 | } | 221 | } |
223 | 222 | ||
224 | ep->rep_attr.cap.max_send_wr *= depth; | 223 | ep->rep_attr.cap.max_send_wr *= depth; |
225 | if (ep->rep_attr.cap.max_send_wr > devattr->max_qp_wr) { | 224 | if (ep->rep_attr.cap.max_send_wr > ia->ri_device->attrs.max_qp_wr) { |
226 | cdata->max_requests = devattr->max_qp_wr / depth; | 225 | cdata->max_requests = ia->ri_device->attrs.max_qp_wr / depth; |
227 | if (!cdata->max_requests) | 226 | if (!cdata->max_requests) |
228 | return -EINVAL; | 227 | return -EINVAL; |
229 | ep->rep_attr.cap.max_send_wr = cdata->max_requests * | 228 | ep->rep_attr.cap.max_send_wr = cdata->max_requests * |
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c index 1b7051bdbdc8..c846ca9f1eba 100644 --- a/net/sunrpc/xprtrdma/svc_rdma.c +++ b/net/sunrpc/xprtrdma/svc_rdma.c | |||
@@ -55,6 +55,7 @@ unsigned int svcrdma_ord = RPCRDMA_ORD; | |||
55 | static unsigned int min_ord = 1; | 55 | static unsigned int min_ord = 1; |
56 | static unsigned int max_ord = 4096; | 56 | static unsigned int max_ord = 4096; |
57 | unsigned int svcrdma_max_requests = RPCRDMA_MAX_REQUESTS; | 57 | unsigned int svcrdma_max_requests = RPCRDMA_MAX_REQUESTS; |
58 | unsigned int svcrdma_max_bc_requests = RPCRDMA_MAX_BC_REQUESTS; | ||
58 | static unsigned int min_max_requests = 4; | 59 | static unsigned int min_max_requests = 4; |
59 | static unsigned int max_max_requests = 16384; | 60 | static unsigned int max_max_requests = 16384; |
60 | unsigned int svcrdma_max_req_size = RPCRDMA_MAX_REQ_SIZE; | 61 | unsigned int svcrdma_max_req_size = RPCRDMA_MAX_REQ_SIZE; |
@@ -71,10 +72,6 @@ atomic_t rdma_stat_rq_prod; | |||
71 | atomic_t rdma_stat_sq_poll; | 72 | atomic_t rdma_stat_sq_poll; |
72 | atomic_t rdma_stat_sq_prod; | 73 | atomic_t rdma_stat_sq_prod; |
73 | 74 | ||
74 | /* Temporary NFS request map and context caches */ | ||
75 | struct kmem_cache *svc_rdma_map_cachep; | ||
76 | struct kmem_cache *svc_rdma_ctxt_cachep; | ||
77 | |||
78 | struct workqueue_struct *svc_rdma_wq; | 75 | struct workqueue_struct *svc_rdma_wq; |
79 | 76 | ||
80 | /* | 77 | /* |
@@ -243,17 +240,16 @@ void svc_rdma_cleanup(void) | |||
243 | svc_unreg_xprt_class(&svc_rdma_bc_class); | 240 | svc_unreg_xprt_class(&svc_rdma_bc_class); |
244 | #endif | 241 | #endif |
245 | svc_unreg_xprt_class(&svc_rdma_class); | 242 | svc_unreg_xprt_class(&svc_rdma_class); |
246 | kmem_cache_destroy(svc_rdma_map_cachep); | ||
247 | kmem_cache_destroy(svc_rdma_ctxt_cachep); | ||
248 | } | 243 | } |
249 | 244 | ||
250 | int svc_rdma_init(void) | 245 | int svc_rdma_init(void) |
251 | { | 246 | { |
252 | dprintk("SVCRDMA Module Init, register RPC RDMA transport\n"); | 247 | dprintk("SVCRDMA Module Init, register RPC RDMA transport\n"); |
253 | dprintk("\tsvcrdma_ord : %d\n", svcrdma_ord); | 248 | dprintk("\tsvcrdma_ord : %d\n", svcrdma_ord); |
254 | dprintk("\tmax_requests : %d\n", svcrdma_max_requests); | 249 | dprintk("\tmax_requests : %u\n", svcrdma_max_requests); |
255 | dprintk("\tsq_depth : %d\n", | 250 | dprintk("\tsq_depth : %u\n", |
256 | svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT); | 251 | svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT); |
252 | dprintk("\tmax_bc_requests : %u\n", svcrdma_max_bc_requests); | ||
257 | dprintk("\tmax_inline : %d\n", svcrdma_max_req_size); | 253 | dprintk("\tmax_inline : %d\n", svcrdma_max_req_size); |
258 | 254 | ||
259 | svc_rdma_wq = alloc_workqueue("svc_rdma", 0, 0); | 255 | svc_rdma_wq = alloc_workqueue("svc_rdma", 0, 0); |
@@ -264,39 +260,10 @@ int svc_rdma_init(void) | |||
264 | svcrdma_table_header = | 260 | svcrdma_table_header = |
265 | register_sysctl_table(svcrdma_root_table); | 261 | register_sysctl_table(svcrdma_root_table); |
266 | 262 | ||
267 | /* Create the temporary map cache */ | ||
268 | svc_rdma_map_cachep = kmem_cache_create("svc_rdma_map_cache", | ||
269 | sizeof(struct svc_rdma_req_map), | ||
270 | 0, | ||
271 | SLAB_HWCACHE_ALIGN, | ||
272 | NULL); | ||
273 | if (!svc_rdma_map_cachep) { | ||
274 | printk(KERN_INFO "Could not allocate map cache.\n"); | ||
275 | goto err0; | ||
276 | } | ||
277 | |||
278 | /* Create the temporary context cache */ | ||
279 | svc_rdma_ctxt_cachep = | ||
280 | kmem_cache_create("svc_rdma_ctxt_cache", | ||
281 | sizeof(struct svc_rdma_op_ctxt), | ||
282 | 0, | ||
283 | SLAB_HWCACHE_ALIGN, | ||
284 | NULL); | ||
285 | if (!svc_rdma_ctxt_cachep) { | ||
286 | printk(KERN_INFO "Could not allocate WR ctxt cache.\n"); | ||
287 | goto err1; | ||
288 | } | ||
289 | |||
290 | /* Register RDMA with the SVC transport switch */ | 263 | /* Register RDMA with the SVC transport switch */ |
291 | svc_reg_xprt_class(&svc_rdma_class); | 264 | svc_reg_xprt_class(&svc_rdma_class); |
292 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 265 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) |
293 | svc_reg_xprt_class(&svc_rdma_bc_class); | 266 | svc_reg_xprt_class(&svc_rdma_bc_class); |
294 | #endif | 267 | #endif |
295 | return 0; | 268 | return 0; |
296 | err1: | ||
297 | kmem_cache_destroy(svc_rdma_map_cachep); | ||
298 | err0: | ||
299 | unregister_sysctl_table(svcrdma_table_header); | ||
300 | destroy_workqueue(svc_rdma_wq); | ||
301 | return -ENOMEM; | ||
302 | } | 269 | } |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c new file mode 100644 index 000000000000..65a7c232a345 --- /dev/null +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Oracle. All rights reserved. | ||
3 | * | ||
4 | * Support for backward direction RPCs on RPC/RDMA (server-side). | ||
5 | */ | ||
6 | |||
7 | #include <linux/sunrpc/svc_rdma.h> | ||
8 | #include "xprt_rdma.h" | ||
9 | |||
10 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | ||
11 | |||
12 | #undef SVCRDMA_BACKCHANNEL_DEBUG | ||
13 | |||
14 | int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, struct rpcrdma_msg *rmsgp, | ||
15 | struct xdr_buf *rcvbuf) | ||
16 | { | ||
17 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
18 | struct kvec *dst, *src = &rcvbuf->head[0]; | ||
19 | struct rpc_rqst *req; | ||
20 | unsigned long cwnd; | ||
21 | u32 credits; | ||
22 | size_t len; | ||
23 | __be32 xid; | ||
24 | __be32 *p; | ||
25 | int ret; | ||
26 | |||
27 | p = (__be32 *)src->iov_base; | ||
28 | len = src->iov_len; | ||
29 | xid = rmsgp->rm_xid; | ||
30 | |||
31 | #ifdef SVCRDMA_BACKCHANNEL_DEBUG | ||
32 | pr_info("%s: xid=%08x, length=%zu\n", | ||
33 | __func__, be32_to_cpu(xid), len); | ||
34 | pr_info("%s: RPC/RDMA: %*ph\n", | ||
35 | __func__, (int)RPCRDMA_HDRLEN_MIN, rmsgp); | ||
36 | pr_info("%s: RPC: %*ph\n", | ||
37 | __func__, (int)len, p); | ||
38 | #endif | ||
39 | |||
40 | ret = -EAGAIN; | ||
41 | if (src->iov_len < 24) | ||
42 | goto out_shortreply; | ||
43 | |||
44 | spin_lock_bh(&xprt->transport_lock); | ||
45 | req = xprt_lookup_rqst(xprt, xid); | ||
46 | if (!req) | ||
47 | goto out_notfound; | ||
48 | |||
49 | dst = &req->rq_private_buf.head[0]; | ||
50 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf)); | ||
51 | if (dst->iov_len < len) | ||
52 | goto out_unlock; | ||
53 | memcpy(dst->iov_base, p, len); | ||
54 | |||
55 | credits = be32_to_cpu(rmsgp->rm_credit); | ||
56 | if (credits == 0) | ||
57 | credits = 1; /* don't deadlock */ | ||
58 | else if (credits > r_xprt->rx_buf.rb_bc_max_requests) | ||
59 | credits = r_xprt->rx_buf.rb_bc_max_requests; | ||
60 | |||
61 | cwnd = xprt->cwnd; | ||
62 | xprt->cwnd = credits << RPC_CWNDSHIFT; | ||
63 | if (xprt->cwnd > cwnd) | ||
64 | xprt_release_rqst_cong(req->rq_task); | ||
65 | |||
66 | ret = 0; | ||
67 | xprt_complete_rqst(req->rq_task, rcvbuf->len); | ||
68 | rcvbuf->len = 0; | ||
69 | |||
70 | out_unlock: | ||
71 | spin_unlock_bh(&xprt->transport_lock); | ||
72 | out: | ||
73 | return ret; | ||
74 | |||
75 | out_shortreply: | ||
76 | dprintk("svcrdma: short bc reply: xprt=%p, len=%zu\n", | ||
77 | xprt, src->iov_len); | ||
78 | goto out; | ||
79 | |||
80 | out_notfound: | ||
81 | dprintk("svcrdma: unrecognized bc reply: xprt=%p, xid=%08x\n", | ||
82 | xprt, be32_to_cpu(xid)); | ||
83 | |||
84 | goto out_unlock; | ||
85 | } | ||
86 | |||
87 | /* Send a backwards direction RPC call. | ||
88 | * | ||
89 | * Caller holds the connection's mutex and has already marshaled | ||
90 | * the RPC/RDMA request. | ||
91 | * | ||
92 | * This is similar to svc_rdma_reply, but takes an rpc_rqst | ||
93 | * instead, does not support chunks, and avoids blocking memory | ||
94 | * allocation. | ||
95 | * | ||
96 | * XXX: There is still an opportunity to block in svc_rdma_send() | ||
97 | * if there are no SQ entries to post the Send. This may occur if | ||
98 | * the adapter has a small maximum SQ depth. | ||
99 | */ | ||
100 | static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma, | ||
101 | struct rpc_rqst *rqst) | ||
102 | { | ||
103 | struct xdr_buf *sndbuf = &rqst->rq_snd_buf; | ||
104 | struct svc_rdma_op_ctxt *ctxt; | ||
105 | struct svc_rdma_req_map *vec; | ||
106 | struct ib_send_wr send_wr; | ||
107 | int ret; | ||
108 | |||
109 | vec = svc_rdma_get_req_map(rdma); | ||
110 | ret = svc_rdma_map_xdr(rdma, sndbuf, vec); | ||
111 | if (ret) | ||
112 | goto out_err; | ||
113 | |||
114 | /* Post a recv buffer to handle the reply for this request. */ | ||
115 | ret = svc_rdma_post_recv(rdma, GFP_NOIO); | ||
116 | if (ret) { | ||
117 | pr_err("svcrdma: Failed to post bc receive buffer, err=%d.\n", | ||
118 | ret); | ||
119 | pr_err("svcrdma: closing transport %p.\n", rdma); | ||
120 | set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); | ||
121 | ret = -ENOTCONN; | ||
122 | goto out_err; | ||
123 | } | ||
124 | |||
125 | ctxt = svc_rdma_get_context(rdma); | ||
126 | ctxt->pages[0] = virt_to_page(rqst->rq_buffer); | ||
127 | ctxt->count = 1; | ||
128 | |||
129 | ctxt->wr_op = IB_WR_SEND; | ||
130 | ctxt->direction = DMA_TO_DEVICE; | ||
131 | ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey; | ||
132 | ctxt->sge[0].length = sndbuf->len; | ||
133 | ctxt->sge[0].addr = | ||
134 | ib_dma_map_page(rdma->sc_cm_id->device, ctxt->pages[0], 0, | ||
135 | sndbuf->len, DMA_TO_DEVICE); | ||
136 | if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr)) { | ||
137 | ret = -EIO; | ||
138 | goto out_unmap; | ||
139 | } | ||
140 | atomic_inc(&rdma->sc_dma_used); | ||
141 | |||
142 | memset(&send_wr, 0, sizeof(send_wr)); | ||
143 | send_wr.wr_id = (unsigned long)ctxt; | ||
144 | send_wr.sg_list = ctxt->sge; | ||
145 | send_wr.num_sge = 1; | ||
146 | send_wr.opcode = IB_WR_SEND; | ||
147 | send_wr.send_flags = IB_SEND_SIGNALED; | ||
148 | |||
149 | ret = svc_rdma_send(rdma, &send_wr); | ||
150 | if (ret) { | ||
151 | ret = -EIO; | ||
152 | goto out_unmap; | ||
153 | } | ||
154 | |||
155 | out_err: | ||
156 | svc_rdma_put_req_map(rdma, vec); | ||
157 | dprintk("svcrdma: %s returns %d\n", __func__, ret); | ||
158 | return ret; | ||
159 | |||
160 | out_unmap: | ||
161 | svc_rdma_unmap_dma(ctxt); | ||
162 | svc_rdma_put_context(ctxt, 1); | ||
163 | goto out_err; | ||
164 | } | ||
165 | |||
166 | /* Server-side transport endpoint wants a whole page for its send | ||
167 | * buffer. The client RPC code constructs the RPC header in this | ||
168 | * buffer before it invokes ->send_request. | ||
169 | * | ||
170 | * Returns NULL if there was a temporary allocation failure. | ||
171 | */ | ||
172 | static void * | ||
173 | xprt_rdma_bc_allocate(struct rpc_task *task, size_t size) | ||
174 | { | ||
175 | struct rpc_rqst *rqst = task->tk_rqstp; | ||
176 | struct svc_xprt *sxprt = rqst->rq_xprt->bc_xprt; | ||
177 | struct svcxprt_rdma *rdma; | ||
178 | struct page *page; | ||
179 | |||
180 | rdma = container_of(sxprt, struct svcxprt_rdma, sc_xprt); | ||
181 | |||
182 | /* Prevent an infinite loop: try to make this case work */ | ||
183 | if (size > PAGE_SIZE) | ||
184 | WARN_ONCE(1, "svcrdma: large bc buffer request (size %zu)\n", | ||
185 | size); | ||
186 | |||
187 | page = alloc_page(RPCRDMA_DEF_GFP); | ||
188 | if (!page) | ||
189 | return NULL; | ||
190 | |||
191 | return page_address(page); | ||
192 | } | ||
193 | |||
194 | static void | ||
195 | xprt_rdma_bc_free(void *buffer) | ||
196 | { | ||
197 | /* No-op: ctxt and page have already been freed. */ | ||
198 | } | ||
199 | |||
200 | static int | ||
201 | rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst) | ||
202 | { | ||
203 | struct rpc_xprt *xprt = rqst->rq_xprt; | ||
204 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
205 | struct rpcrdma_msg *headerp = (struct rpcrdma_msg *)rqst->rq_buffer; | ||
206 | int rc; | ||
207 | |||
208 | /* Space in the send buffer for an RPC/RDMA header is reserved | ||
209 | * via xprt->tsh_size. | ||
210 | */ | ||
211 | headerp->rm_xid = rqst->rq_xid; | ||
212 | headerp->rm_vers = rpcrdma_version; | ||
213 | headerp->rm_credit = cpu_to_be32(r_xprt->rx_buf.rb_bc_max_requests); | ||
214 | headerp->rm_type = rdma_msg; | ||
215 | headerp->rm_body.rm_chunks[0] = xdr_zero; | ||
216 | headerp->rm_body.rm_chunks[1] = xdr_zero; | ||
217 | headerp->rm_body.rm_chunks[2] = xdr_zero; | ||
218 | |||
219 | #ifdef SVCRDMA_BACKCHANNEL_DEBUG | ||
220 | pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer); | ||
221 | #endif | ||
222 | |||
223 | rc = svc_rdma_bc_sendto(rdma, rqst); | ||
224 | if (rc) | ||
225 | goto drop_connection; | ||
226 | return rc; | ||
227 | |||
228 | drop_connection: | ||
229 | dprintk("svcrdma: failed to send bc call\n"); | ||
230 | xprt_disconnect_done(xprt); | ||
231 | return -ENOTCONN; | ||
232 | } | ||
233 | |||
234 | /* Send an RPC call on the passive end of a transport | ||
235 | * connection. | ||
236 | */ | ||
237 | static int | ||
238 | xprt_rdma_bc_send_request(struct rpc_task *task) | ||
239 | { | ||
240 | struct rpc_rqst *rqst = task->tk_rqstp; | ||
241 | struct svc_xprt *sxprt = rqst->rq_xprt->bc_xprt; | ||
242 | struct svcxprt_rdma *rdma; | ||
243 | int ret; | ||
244 | |||
245 | dprintk("svcrdma: sending bc call with xid: %08x\n", | ||
246 | be32_to_cpu(rqst->rq_xid)); | ||
247 | |||
248 | if (!mutex_trylock(&sxprt->xpt_mutex)) { | ||
249 | rpc_sleep_on(&sxprt->xpt_bc_pending, task, NULL); | ||
250 | if (!mutex_trylock(&sxprt->xpt_mutex)) | ||
251 | return -EAGAIN; | ||
252 | rpc_wake_up_queued_task(&sxprt->xpt_bc_pending, task); | ||
253 | } | ||
254 | |||
255 | ret = -ENOTCONN; | ||
256 | rdma = container_of(sxprt, struct svcxprt_rdma, sc_xprt); | ||
257 | if (!test_bit(XPT_DEAD, &sxprt->xpt_flags)) | ||
258 | ret = rpcrdma_bc_send_request(rdma, rqst); | ||
259 | |||
260 | mutex_unlock(&sxprt->xpt_mutex); | ||
261 | |||
262 | if (ret < 0) | ||
263 | return ret; | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static void | ||
268 | xprt_rdma_bc_close(struct rpc_xprt *xprt) | ||
269 | { | ||
270 | dprintk("svcrdma: %s: xprt %p\n", __func__, xprt); | ||
271 | } | ||
272 | |||
273 | static void | ||
274 | xprt_rdma_bc_put(struct rpc_xprt *xprt) | ||
275 | { | ||
276 | dprintk("svcrdma: %s: xprt %p\n", __func__, xprt); | ||
277 | |||
278 | xprt_free(xprt); | ||
279 | module_put(THIS_MODULE); | ||
280 | } | ||
281 | |||
282 | static struct rpc_xprt_ops xprt_rdma_bc_procs = { | ||
283 | .reserve_xprt = xprt_reserve_xprt_cong, | ||
284 | .release_xprt = xprt_release_xprt_cong, | ||
285 | .alloc_slot = xprt_alloc_slot, | ||
286 | .release_request = xprt_release_rqst_cong, | ||
287 | .buf_alloc = xprt_rdma_bc_allocate, | ||
288 | .buf_free = xprt_rdma_bc_free, | ||
289 | .send_request = xprt_rdma_bc_send_request, | ||
290 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | ||
291 | .close = xprt_rdma_bc_close, | ||
292 | .destroy = xprt_rdma_bc_put, | ||
293 | .print_stats = xprt_rdma_print_stats | ||
294 | }; | ||
295 | |||
296 | static const struct rpc_timeout xprt_rdma_bc_timeout = { | ||
297 | .to_initval = 60 * HZ, | ||
298 | .to_maxval = 60 * HZ, | ||
299 | }; | ||
300 | |||
301 | /* It shouldn't matter if the number of backchannel session slots | ||
302 | * doesn't match the number of RPC/RDMA credits. That just means | ||
303 | * one or the other will have extra slots that aren't used. | ||
304 | */ | ||
305 | static struct rpc_xprt * | ||
306 | xprt_setup_rdma_bc(struct xprt_create *args) | ||
307 | { | ||
308 | struct rpc_xprt *xprt; | ||
309 | struct rpcrdma_xprt *new_xprt; | ||
310 | |||
311 | if (args->addrlen > sizeof(xprt->addr)) { | ||
312 | dprintk("RPC: %s: address too large\n", __func__); | ||
313 | return ERR_PTR(-EBADF); | ||
314 | } | ||
315 | |||
316 | xprt = xprt_alloc(args->net, sizeof(*new_xprt), | ||
317 | RPCRDMA_MAX_BC_REQUESTS, | ||
318 | RPCRDMA_MAX_BC_REQUESTS); | ||
319 | if (!xprt) { | ||
320 | dprintk("RPC: %s: couldn't allocate rpc_xprt\n", | ||
321 | __func__); | ||
322 | return ERR_PTR(-ENOMEM); | ||
323 | } | ||
324 | |||
325 | xprt->timeout = &xprt_rdma_bc_timeout; | ||
326 | xprt_set_bound(xprt); | ||
327 | xprt_set_connected(xprt); | ||
328 | xprt->bind_timeout = RPCRDMA_BIND_TO; | ||
329 | xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO; | ||
330 | xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; | ||
331 | |||
332 | xprt->prot = XPRT_TRANSPORT_BC_RDMA; | ||
333 | xprt->tsh_size = RPCRDMA_HDRLEN_MIN / sizeof(__be32); | ||
334 | xprt->ops = &xprt_rdma_bc_procs; | ||
335 | |||
336 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); | ||
337 | xprt->addrlen = args->addrlen; | ||
338 | xprt_rdma_format_addresses(xprt, (struct sockaddr *)&xprt->addr); | ||
339 | xprt->resvport = 0; | ||
340 | |||
341 | xprt->max_payload = xprt_rdma_max_inline_read; | ||
342 | |||
343 | new_xprt = rpcx_to_rdmax(xprt); | ||
344 | new_xprt->rx_buf.rb_bc_max_requests = xprt->max_reqs; | ||
345 | |||
346 | xprt_get(xprt); | ||
347 | args->bc_xprt->xpt_bc_xprt = xprt; | ||
348 | xprt->bc_xprt = args->bc_xprt; | ||
349 | |||
350 | if (!try_module_get(THIS_MODULE)) | ||
351 | goto out_fail; | ||
352 | |||
353 | /* Final put for backchannel xprt is in __svc_rdma_free */ | ||
354 | xprt_get(xprt); | ||
355 | return xprt; | ||
356 | |||
357 | out_fail: | ||
358 | xprt_rdma_free_addresses(xprt); | ||
359 | args->bc_xprt->xpt_bc_xprt = NULL; | ||
360 | xprt_put(xprt); | ||
361 | xprt_free(xprt); | ||
362 | return ERR_PTR(-EINVAL); | ||
363 | } | ||
364 | |||
365 | struct xprt_class xprt_rdma_bc = { | ||
366 | .list = LIST_HEAD_INIT(xprt_rdma_bc.list), | ||
367 | .name = "rdma backchannel", | ||
368 | .owner = THIS_MODULE, | ||
369 | .ident = XPRT_TRANSPORT_BC_RDMA, | ||
370 | .setup = xprt_setup_rdma_bc, | ||
371 | }; | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index ff4f01e527ec..c8b8a8b4181e 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -144,6 +144,7 @@ int rdma_read_chunk_lcl(struct svcxprt_rdma *xprt, | |||
144 | 144 | ||
145 | head->arg.pages[pg_no] = rqstp->rq_arg.pages[pg_no]; | 145 | head->arg.pages[pg_no] = rqstp->rq_arg.pages[pg_no]; |
146 | head->arg.page_len += len; | 146 | head->arg.page_len += len; |
147 | |||
147 | head->arg.len += len; | 148 | head->arg.len += len; |
148 | if (!pg_off) | 149 | if (!pg_off) |
149 | head->count++; | 150 | head->count++; |
@@ -160,8 +161,7 @@ int rdma_read_chunk_lcl(struct svcxprt_rdma *xprt, | |||
160 | goto err; | 161 | goto err; |
161 | atomic_inc(&xprt->sc_dma_used); | 162 | atomic_inc(&xprt->sc_dma_used); |
162 | 163 | ||
163 | /* The lkey here is either a local dma lkey or a dma_mr lkey */ | 164 | ctxt->sge[pno].lkey = xprt->sc_pd->local_dma_lkey; |
164 | ctxt->sge[pno].lkey = xprt->sc_dma_lkey; | ||
165 | ctxt->sge[pno].length = len; | 165 | ctxt->sge[pno].length = len; |
166 | ctxt->count++; | 166 | ctxt->count++; |
167 | 167 | ||
@@ -567,6 +567,38 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
567 | return ret; | 567 | return ret; |
568 | } | 568 | } |
569 | 569 | ||
570 | /* By convention, backchannel calls arrive via rdma_msg type | ||
571 | * messages, and never populate the chunk lists. This makes | ||
572 | * the RPC/RDMA header small and fixed in size, so it is | ||
573 | * straightforward to check the RPC header's direction field. | ||
574 | */ | ||
575 | static bool | ||
576 | svc_rdma_is_backchannel_reply(struct svc_xprt *xprt, struct rpcrdma_msg *rmsgp) | ||
577 | { | ||
578 | __be32 *p = (__be32 *)rmsgp; | ||
579 | |||
580 | if (!xprt->xpt_bc_xprt) | ||
581 | return false; | ||
582 | |||
583 | if (rmsgp->rm_type != rdma_msg) | ||
584 | return false; | ||
585 | if (rmsgp->rm_body.rm_chunks[0] != xdr_zero) | ||
586 | return false; | ||
587 | if (rmsgp->rm_body.rm_chunks[1] != xdr_zero) | ||
588 | return false; | ||
589 | if (rmsgp->rm_body.rm_chunks[2] != xdr_zero) | ||
590 | return false; | ||
591 | |||
592 | /* sanity */ | ||
593 | if (p[7] != rmsgp->rm_xid) | ||
594 | return false; | ||
595 | /* call direction */ | ||
596 | if (p[8] == cpu_to_be32(RPC_CALL)) | ||
597 | return false; | ||
598 | |||
599 | return true; | ||
600 | } | ||
601 | |||
570 | /* | 602 | /* |
571 | * Set up the rqstp thread context to point to the RQ buffer. If | 603 | * Set up the rqstp thread context to point to the RQ buffer. If |
572 | * necessary, pull additional data from the client with an RDMA_READ | 604 | * necessary, pull additional data from the client with an RDMA_READ |
@@ -632,6 +664,15 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) | |||
632 | goto close_out; | 664 | goto close_out; |
633 | } | 665 | } |
634 | 666 | ||
667 | if (svc_rdma_is_backchannel_reply(xprt, rmsgp)) { | ||
668 | ret = svc_rdma_handle_bc_reply(xprt->xpt_bc_xprt, rmsgp, | ||
669 | &rqstp->rq_arg); | ||
670 | svc_rdma_put_context(ctxt, 0); | ||
671 | if (ret) | ||
672 | goto repost; | ||
673 | return ret; | ||
674 | } | ||
675 | |||
635 | /* Read read-list data. */ | 676 | /* Read read-list data. */ |
636 | ret = rdma_read_chunks(rdma_xprt, rmsgp, rqstp, ctxt); | 677 | ret = rdma_read_chunks(rdma_xprt, rmsgp, rqstp, ctxt); |
637 | if (ret > 0) { | 678 | if (ret > 0) { |
@@ -668,4 +709,15 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) | |||
668 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | 709 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
669 | defer: | 710 | defer: |
670 | return 0; | 711 | return 0; |
712 | |||
713 | repost: | ||
714 | ret = svc_rdma_post_recv(rdma_xprt, GFP_KERNEL); | ||
715 | if (ret) { | ||
716 | pr_err("svcrdma: could not post a receive buffer, err=%d.\n", | ||
717 | ret); | ||
718 | pr_err("svcrdma: closing transport %p.\n", rdma_xprt); | ||
719 | set_bit(XPT_CLOSE, &rdma_xprt->sc_xprt.xpt_flags); | ||
720 | ret = -ENOTCONN; | ||
721 | } | ||
722 | return ret; | ||
671 | } | 723 | } |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 969a1ab75fc3..df57f3ce6cd2 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
@@ -50,9 +50,9 @@ | |||
50 | 50 | ||
51 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 51 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
52 | 52 | ||
53 | static int map_xdr(struct svcxprt_rdma *xprt, | 53 | int svc_rdma_map_xdr(struct svcxprt_rdma *xprt, |
54 | struct xdr_buf *xdr, | 54 | struct xdr_buf *xdr, |
55 | struct svc_rdma_req_map *vec) | 55 | struct svc_rdma_req_map *vec) |
56 | { | 56 | { |
57 | int sge_no; | 57 | int sge_no; |
58 | u32 sge_bytes; | 58 | u32 sge_bytes; |
@@ -62,7 +62,7 @@ static int map_xdr(struct svcxprt_rdma *xprt, | |||
62 | 62 | ||
63 | if (xdr->len != | 63 | if (xdr->len != |
64 | (xdr->head[0].iov_len + xdr->page_len + xdr->tail[0].iov_len)) { | 64 | (xdr->head[0].iov_len + xdr->page_len + xdr->tail[0].iov_len)) { |
65 | pr_err("svcrdma: map_xdr: XDR buffer length error\n"); | 65 | pr_err("svcrdma: %s: XDR buffer length error\n", __func__); |
66 | return -EIO; | 66 | return -EIO; |
67 | } | 67 | } |
68 | 68 | ||
@@ -97,9 +97,9 @@ static int map_xdr(struct svcxprt_rdma *xprt, | |||
97 | sge_no++; | 97 | sge_no++; |
98 | } | 98 | } |
99 | 99 | ||
100 | dprintk("svcrdma: map_xdr: sge_no %d page_no %d " | 100 | dprintk("svcrdma: %s: sge_no %d page_no %d " |
101 | "page_base %u page_len %u head_len %zu tail_len %zu\n", | 101 | "page_base %u page_len %u head_len %zu tail_len %zu\n", |
102 | sge_no, page_no, xdr->page_base, xdr->page_len, | 102 | __func__, sge_no, page_no, xdr->page_base, xdr->page_len, |
103 | xdr->head[0].iov_len, xdr->tail[0].iov_len); | 103 | xdr->head[0].iov_len, xdr->tail[0].iov_len); |
104 | 104 | ||
105 | vec->count = sge_no; | 105 | vec->count = sge_no; |
@@ -265,7 +265,7 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp, | |||
265 | sge[sge_no].addr)) | 265 | sge[sge_no].addr)) |
266 | goto err; | 266 | goto err; |
267 | atomic_inc(&xprt->sc_dma_used); | 267 | atomic_inc(&xprt->sc_dma_used); |
268 | sge[sge_no].lkey = xprt->sc_dma_lkey; | 268 | sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey; |
269 | ctxt->count++; | 269 | ctxt->count++; |
270 | sge_off = 0; | 270 | sge_off = 0; |
271 | sge_no++; | 271 | sge_no++; |
@@ -465,7 +465,7 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
465 | int ret; | 465 | int ret; |
466 | 466 | ||
467 | /* Post a recv buffer to handle another request. */ | 467 | /* Post a recv buffer to handle another request. */ |
468 | ret = svc_rdma_post_recv(rdma); | 468 | ret = svc_rdma_post_recv(rdma, GFP_KERNEL); |
469 | if (ret) { | 469 | if (ret) { |
470 | printk(KERN_INFO | 470 | printk(KERN_INFO |
471 | "svcrdma: could not post a receive buffer, err=%d." | 471 | "svcrdma: could not post a receive buffer, err=%d." |
@@ -480,7 +480,7 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
480 | ctxt->count = 1; | 480 | ctxt->count = 1; |
481 | 481 | ||
482 | /* Prepare the SGE for the RPCRDMA Header */ | 482 | /* Prepare the SGE for the RPCRDMA Header */ |
483 | ctxt->sge[0].lkey = rdma->sc_dma_lkey; | 483 | ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey; |
484 | ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp); | 484 | ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp); |
485 | ctxt->sge[0].addr = | 485 | ctxt->sge[0].addr = |
486 | ib_dma_map_page(rdma->sc_cm_id->device, page, 0, | 486 | ib_dma_map_page(rdma->sc_cm_id->device, page, 0, |
@@ -504,7 +504,7 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
504 | ctxt->sge[sge_no].addr)) | 504 | ctxt->sge[sge_no].addr)) |
505 | goto err; | 505 | goto err; |
506 | atomic_inc(&rdma->sc_dma_used); | 506 | atomic_inc(&rdma->sc_dma_used); |
507 | ctxt->sge[sge_no].lkey = rdma->sc_dma_lkey; | 507 | ctxt->sge[sge_no].lkey = rdma->sc_pd->local_dma_lkey; |
508 | ctxt->sge[sge_no].length = sge_bytes; | 508 | ctxt->sge[sge_no].length = sge_bytes; |
509 | } | 509 | } |
510 | if (byte_count != 0) { | 510 | if (byte_count != 0) { |
@@ -591,14 +591,17 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) | |||
591 | /* Build an req vec for the XDR */ | 591 | /* Build an req vec for the XDR */ |
592 | ctxt = svc_rdma_get_context(rdma); | 592 | ctxt = svc_rdma_get_context(rdma); |
593 | ctxt->direction = DMA_TO_DEVICE; | 593 | ctxt->direction = DMA_TO_DEVICE; |
594 | vec = svc_rdma_get_req_map(); | 594 | vec = svc_rdma_get_req_map(rdma); |
595 | ret = map_xdr(rdma, &rqstp->rq_res, vec); | 595 | ret = svc_rdma_map_xdr(rdma, &rqstp->rq_res, vec); |
596 | if (ret) | 596 | if (ret) |
597 | goto err0; | 597 | goto err0; |
598 | inline_bytes = rqstp->rq_res.len; | 598 | inline_bytes = rqstp->rq_res.len; |
599 | 599 | ||
600 | /* Create the RDMA response header */ | 600 | /* Create the RDMA response header */ |
601 | res_page = alloc_page(GFP_KERNEL | __GFP_NOFAIL); | 601 | ret = -ENOMEM; |
602 | res_page = alloc_page(GFP_KERNEL); | ||
603 | if (!res_page) | ||
604 | goto err0; | ||
602 | rdma_resp = page_address(res_page); | 605 | rdma_resp = page_address(res_page); |
603 | reply_ary = svc_rdma_get_reply_array(rdma_argp); | 606 | reply_ary = svc_rdma_get_reply_array(rdma_argp); |
604 | if (reply_ary) | 607 | if (reply_ary) |
@@ -630,14 +633,14 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) | |||
630 | 633 | ||
631 | ret = send_reply(rdma, rqstp, res_page, rdma_resp, ctxt, vec, | 634 | ret = send_reply(rdma, rqstp, res_page, rdma_resp, ctxt, vec, |
632 | inline_bytes); | 635 | inline_bytes); |
633 | svc_rdma_put_req_map(vec); | 636 | svc_rdma_put_req_map(rdma, vec); |
634 | dprintk("svcrdma: send_reply returns %d\n", ret); | 637 | dprintk("svcrdma: send_reply returns %d\n", ret); |
635 | return ret; | 638 | return ret; |
636 | 639 | ||
637 | err1: | 640 | err1: |
638 | put_page(res_page); | 641 | put_page(res_page); |
639 | err0: | 642 | err0: |
640 | svc_rdma_put_req_map(vec); | 643 | svc_rdma_put_req_map(rdma, vec); |
641 | svc_rdma_put_context(ctxt, 0); | 644 | svc_rdma_put_context(ctxt, 0); |
642 | return ret; | 645 | return ret; |
643 | } | 646 | } |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index b348b4adef29..5763825d09bf 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -153,18 +153,76 @@ static void svc_rdma_bc_free(struct svc_xprt *xprt) | |||
153 | } | 153 | } |
154 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 154 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
155 | 155 | ||
156 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) | 156 | static struct svc_rdma_op_ctxt *alloc_ctxt(struct svcxprt_rdma *xprt, |
157 | gfp_t flags) | ||
157 | { | 158 | { |
158 | struct svc_rdma_op_ctxt *ctxt; | 159 | struct svc_rdma_op_ctxt *ctxt; |
159 | 160 | ||
160 | ctxt = kmem_cache_alloc(svc_rdma_ctxt_cachep, | 161 | ctxt = kmalloc(sizeof(*ctxt), flags); |
161 | GFP_KERNEL | __GFP_NOFAIL); | 162 | if (ctxt) { |
162 | ctxt->xprt = xprt; | 163 | ctxt->xprt = xprt; |
163 | INIT_LIST_HEAD(&ctxt->dto_q); | 164 | INIT_LIST_HEAD(&ctxt->free); |
165 | INIT_LIST_HEAD(&ctxt->dto_q); | ||
166 | } | ||
167 | return ctxt; | ||
168 | } | ||
169 | |||
170 | static bool svc_rdma_prealloc_ctxts(struct svcxprt_rdma *xprt) | ||
171 | { | ||
172 | unsigned int i; | ||
173 | |||
174 | /* Each RPC/RDMA credit can consume a number of send | ||
175 | * and receive WQEs. One ctxt is allocated for each. | ||
176 | */ | ||
177 | i = xprt->sc_sq_depth + xprt->sc_rq_depth; | ||
178 | |||
179 | while (i--) { | ||
180 | struct svc_rdma_op_ctxt *ctxt; | ||
181 | |||
182 | ctxt = alloc_ctxt(xprt, GFP_KERNEL); | ||
183 | if (!ctxt) { | ||
184 | dprintk("svcrdma: No memory for RDMA ctxt\n"); | ||
185 | return false; | ||
186 | } | ||
187 | list_add(&ctxt->free, &xprt->sc_ctxts); | ||
188 | } | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) | ||
193 | { | ||
194 | struct svc_rdma_op_ctxt *ctxt = NULL; | ||
195 | |||
196 | spin_lock_bh(&xprt->sc_ctxt_lock); | ||
197 | xprt->sc_ctxt_used++; | ||
198 | if (list_empty(&xprt->sc_ctxts)) | ||
199 | goto out_empty; | ||
200 | |||
201 | ctxt = list_first_entry(&xprt->sc_ctxts, | ||
202 | struct svc_rdma_op_ctxt, free); | ||
203 | list_del_init(&ctxt->free); | ||
204 | spin_unlock_bh(&xprt->sc_ctxt_lock); | ||
205 | |||
206 | out: | ||
164 | ctxt->count = 0; | 207 | ctxt->count = 0; |
165 | ctxt->frmr = NULL; | 208 | ctxt->frmr = NULL; |
166 | atomic_inc(&xprt->sc_ctxt_used); | ||
167 | return ctxt; | 209 | return ctxt; |
210 | |||
211 | out_empty: | ||
212 | /* Either pre-allocation missed the mark, or send | ||
213 | * queue accounting is broken. | ||
214 | */ | ||
215 | spin_unlock_bh(&xprt->sc_ctxt_lock); | ||
216 | |||
217 | ctxt = alloc_ctxt(xprt, GFP_NOIO); | ||
218 | if (ctxt) | ||
219 | goto out; | ||
220 | |||
221 | spin_lock_bh(&xprt->sc_ctxt_lock); | ||
222 | xprt->sc_ctxt_used--; | ||
223 | spin_unlock_bh(&xprt->sc_ctxt_lock); | ||
224 | WARN_ONCE(1, "svcrdma: empty RDMA ctxt list?\n"); | ||
225 | return NULL; | ||
168 | } | 226 | } |
169 | 227 | ||
170 | void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt) | 228 | void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt) |
@@ -174,11 +232,11 @@ void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt) | |||
174 | for (i = 0; i < ctxt->count && ctxt->sge[i].length; i++) { | 232 | for (i = 0; i < ctxt->count && ctxt->sge[i].length; i++) { |
175 | /* | 233 | /* |
176 | * Unmap the DMA addr in the SGE if the lkey matches | 234 | * Unmap the DMA addr in the SGE if the lkey matches |
177 | * the sc_dma_lkey, otherwise, ignore it since it is | 235 | * the local_dma_lkey, otherwise, ignore it since it is |
178 | * an FRMR lkey and will be unmapped later when the | 236 | * an FRMR lkey and will be unmapped later when the |
179 | * last WR that uses it completes. | 237 | * last WR that uses it completes. |
180 | */ | 238 | */ |
181 | if (ctxt->sge[i].lkey == xprt->sc_dma_lkey) { | 239 | if (ctxt->sge[i].lkey == xprt->sc_pd->local_dma_lkey) { |
182 | atomic_dec(&xprt->sc_dma_used); | 240 | atomic_dec(&xprt->sc_dma_used); |
183 | ib_dma_unmap_page(xprt->sc_cm_id->device, | 241 | ib_dma_unmap_page(xprt->sc_cm_id->device, |
184 | ctxt->sge[i].addr, | 242 | ctxt->sge[i].addr, |
@@ -190,35 +248,108 @@ void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt) | |||
190 | 248 | ||
191 | void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages) | 249 | void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages) |
192 | { | 250 | { |
193 | struct svcxprt_rdma *xprt; | 251 | struct svcxprt_rdma *xprt = ctxt->xprt; |
194 | int i; | 252 | int i; |
195 | 253 | ||
196 | xprt = ctxt->xprt; | ||
197 | if (free_pages) | 254 | if (free_pages) |
198 | for (i = 0; i < ctxt->count; i++) | 255 | for (i = 0; i < ctxt->count; i++) |
199 | put_page(ctxt->pages[i]); | 256 | put_page(ctxt->pages[i]); |
200 | 257 | ||
201 | kmem_cache_free(svc_rdma_ctxt_cachep, ctxt); | 258 | spin_lock_bh(&xprt->sc_ctxt_lock); |
202 | atomic_dec(&xprt->sc_ctxt_used); | 259 | xprt->sc_ctxt_used--; |
260 | list_add(&ctxt->free, &xprt->sc_ctxts); | ||
261 | spin_unlock_bh(&xprt->sc_ctxt_lock); | ||
203 | } | 262 | } |
204 | 263 | ||
205 | /* | 264 | static void svc_rdma_destroy_ctxts(struct svcxprt_rdma *xprt) |
206 | * Temporary NFS req mappings are shared across all transport | 265 | { |
207 | * instances. These are short lived and should be bounded by the number | 266 | while (!list_empty(&xprt->sc_ctxts)) { |
208 | * of concurrent server threads * depth of the SQ. | 267 | struct svc_rdma_op_ctxt *ctxt; |
209 | */ | 268 | |
210 | struct svc_rdma_req_map *svc_rdma_get_req_map(void) | 269 | ctxt = list_first_entry(&xprt->sc_ctxts, |
270 | struct svc_rdma_op_ctxt, free); | ||
271 | list_del(&ctxt->free); | ||
272 | kfree(ctxt); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static struct svc_rdma_req_map *alloc_req_map(gfp_t flags) | ||
211 | { | 277 | { |
212 | struct svc_rdma_req_map *map; | 278 | struct svc_rdma_req_map *map; |
213 | map = kmem_cache_alloc(svc_rdma_map_cachep, | 279 | |
214 | GFP_KERNEL | __GFP_NOFAIL); | 280 | map = kmalloc(sizeof(*map), flags); |
281 | if (map) | ||
282 | INIT_LIST_HEAD(&map->free); | ||
283 | return map; | ||
284 | } | ||
285 | |||
286 | static bool svc_rdma_prealloc_maps(struct svcxprt_rdma *xprt) | ||
287 | { | ||
288 | unsigned int i; | ||
289 | |||
290 | /* One for each receive buffer on this connection. */ | ||
291 | i = xprt->sc_max_requests; | ||
292 | |||
293 | while (i--) { | ||
294 | struct svc_rdma_req_map *map; | ||
295 | |||
296 | map = alloc_req_map(GFP_KERNEL); | ||
297 | if (!map) { | ||
298 | dprintk("svcrdma: No memory for request map\n"); | ||
299 | return false; | ||
300 | } | ||
301 | list_add(&map->free, &xprt->sc_maps); | ||
302 | } | ||
303 | return true; | ||
304 | } | ||
305 | |||
306 | struct svc_rdma_req_map *svc_rdma_get_req_map(struct svcxprt_rdma *xprt) | ||
307 | { | ||
308 | struct svc_rdma_req_map *map = NULL; | ||
309 | |||
310 | spin_lock(&xprt->sc_map_lock); | ||
311 | if (list_empty(&xprt->sc_maps)) | ||
312 | goto out_empty; | ||
313 | |||
314 | map = list_first_entry(&xprt->sc_maps, | ||
315 | struct svc_rdma_req_map, free); | ||
316 | list_del_init(&map->free); | ||
317 | spin_unlock(&xprt->sc_map_lock); | ||
318 | |||
319 | out: | ||
215 | map->count = 0; | 320 | map->count = 0; |
216 | return map; | 321 | return map; |
322 | |||
323 | out_empty: | ||
324 | spin_unlock(&xprt->sc_map_lock); | ||
325 | |||
326 | /* Pre-allocation amount was incorrect */ | ||
327 | map = alloc_req_map(GFP_NOIO); | ||
328 | if (map) | ||
329 | goto out; | ||
330 | |||
331 | WARN_ONCE(1, "svcrdma: empty request map list?\n"); | ||
332 | return NULL; | ||
333 | } | ||
334 | |||
335 | void svc_rdma_put_req_map(struct svcxprt_rdma *xprt, | ||
336 | struct svc_rdma_req_map *map) | ||
337 | { | ||
338 | spin_lock(&xprt->sc_map_lock); | ||
339 | list_add(&map->free, &xprt->sc_maps); | ||
340 | spin_unlock(&xprt->sc_map_lock); | ||
217 | } | 341 | } |
218 | 342 | ||
219 | void svc_rdma_put_req_map(struct svc_rdma_req_map *map) | 343 | static void svc_rdma_destroy_maps(struct svcxprt_rdma *xprt) |
220 | { | 344 | { |
221 | kmem_cache_free(svc_rdma_map_cachep, map); | 345 | while (!list_empty(&xprt->sc_maps)) { |
346 | struct svc_rdma_req_map *map; | ||
347 | |||
348 | map = list_first_entry(&xprt->sc_maps, | ||
349 | struct svc_rdma_req_map, free); | ||
350 | list_del(&map->free); | ||
351 | kfree(map); | ||
352 | } | ||
222 | } | 353 | } |
223 | 354 | ||
224 | /* ib_cq event handler */ | 355 | /* ib_cq event handler */ |
@@ -386,46 +517,44 @@ static void rq_cq_reap(struct svcxprt_rdma *xprt) | |||
386 | static void process_context(struct svcxprt_rdma *xprt, | 517 | static void process_context(struct svcxprt_rdma *xprt, |
387 | struct svc_rdma_op_ctxt *ctxt) | 518 | struct svc_rdma_op_ctxt *ctxt) |
388 | { | 519 | { |
520 | struct svc_rdma_op_ctxt *read_hdr; | ||
521 | int free_pages = 0; | ||
522 | |||
389 | svc_rdma_unmap_dma(ctxt); | 523 | svc_rdma_unmap_dma(ctxt); |
390 | 524 | ||
391 | switch (ctxt->wr_op) { | 525 | switch (ctxt->wr_op) { |
392 | case IB_WR_SEND: | 526 | case IB_WR_SEND: |
393 | if (ctxt->frmr) | 527 | free_pages = 1; |
394 | pr_err("svcrdma: SEND: ctxt->frmr != NULL\n"); | ||
395 | svc_rdma_put_context(ctxt, 1); | ||
396 | break; | 528 | break; |
397 | 529 | ||
398 | case IB_WR_RDMA_WRITE: | 530 | case IB_WR_RDMA_WRITE: |
399 | if (ctxt->frmr) | ||
400 | pr_err("svcrdma: WRITE: ctxt->frmr != NULL\n"); | ||
401 | svc_rdma_put_context(ctxt, 0); | ||
402 | break; | 531 | break; |
403 | 532 | ||
404 | case IB_WR_RDMA_READ: | 533 | case IB_WR_RDMA_READ: |
405 | case IB_WR_RDMA_READ_WITH_INV: | 534 | case IB_WR_RDMA_READ_WITH_INV: |
406 | svc_rdma_put_frmr(xprt, ctxt->frmr); | 535 | svc_rdma_put_frmr(xprt, ctxt->frmr); |
407 | if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) { | 536 | |
408 | struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr; | 537 | if (!test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) |
409 | if (read_hdr) { | 538 | break; |
410 | spin_lock_bh(&xprt->sc_rq_dto_lock); | 539 | |
411 | set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags); | 540 | read_hdr = ctxt->read_hdr; |
412 | list_add_tail(&read_hdr->dto_q, | ||
413 | &xprt->sc_read_complete_q); | ||
414 | spin_unlock_bh(&xprt->sc_rq_dto_lock); | ||
415 | } else { | ||
416 | pr_err("svcrdma: ctxt->read_hdr == NULL\n"); | ||
417 | } | ||
418 | svc_xprt_enqueue(&xprt->sc_xprt); | ||
419 | } | ||
420 | svc_rdma_put_context(ctxt, 0); | 541 | svc_rdma_put_context(ctxt, 0); |
421 | break; | 542 | |
543 | spin_lock_bh(&xprt->sc_rq_dto_lock); | ||
544 | set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags); | ||
545 | list_add_tail(&read_hdr->dto_q, | ||
546 | &xprt->sc_read_complete_q); | ||
547 | spin_unlock_bh(&xprt->sc_rq_dto_lock); | ||
548 | svc_xprt_enqueue(&xprt->sc_xprt); | ||
549 | return; | ||
422 | 550 | ||
423 | default: | 551 | default: |
424 | printk(KERN_ERR "svcrdma: unexpected completion type, " | 552 | dprintk("svcrdma: unexpected completion opcode=%d\n", |
425 | "opcode=%d\n", | 553 | ctxt->wr_op); |
426 | ctxt->wr_op); | ||
427 | break; | 554 | break; |
428 | } | 555 | } |
556 | |||
557 | svc_rdma_put_context(ctxt, free_pages); | ||
429 | } | 558 | } |
430 | 559 | ||
431 | /* | 560 | /* |
@@ -523,19 +652,15 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv, | |||
523 | INIT_LIST_HEAD(&cma_xprt->sc_rq_dto_q); | 652 | INIT_LIST_HEAD(&cma_xprt->sc_rq_dto_q); |
524 | INIT_LIST_HEAD(&cma_xprt->sc_read_complete_q); | 653 | INIT_LIST_HEAD(&cma_xprt->sc_read_complete_q); |
525 | INIT_LIST_HEAD(&cma_xprt->sc_frmr_q); | 654 | INIT_LIST_HEAD(&cma_xprt->sc_frmr_q); |
655 | INIT_LIST_HEAD(&cma_xprt->sc_ctxts); | ||
656 | INIT_LIST_HEAD(&cma_xprt->sc_maps); | ||
526 | init_waitqueue_head(&cma_xprt->sc_send_wait); | 657 | init_waitqueue_head(&cma_xprt->sc_send_wait); |
527 | 658 | ||
528 | spin_lock_init(&cma_xprt->sc_lock); | 659 | spin_lock_init(&cma_xprt->sc_lock); |
529 | spin_lock_init(&cma_xprt->sc_rq_dto_lock); | 660 | spin_lock_init(&cma_xprt->sc_rq_dto_lock); |
530 | spin_lock_init(&cma_xprt->sc_frmr_q_lock); | 661 | spin_lock_init(&cma_xprt->sc_frmr_q_lock); |
531 | 662 | spin_lock_init(&cma_xprt->sc_ctxt_lock); | |
532 | cma_xprt->sc_ord = svcrdma_ord; | 663 | spin_lock_init(&cma_xprt->sc_map_lock); |
533 | |||
534 | cma_xprt->sc_max_req_size = svcrdma_max_req_size; | ||
535 | cma_xprt->sc_max_requests = svcrdma_max_requests; | ||
536 | cma_xprt->sc_sq_depth = svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT; | ||
537 | atomic_set(&cma_xprt->sc_sq_count, 0); | ||
538 | atomic_set(&cma_xprt->sc_ctxt_used, 0); | ||
539 | 664 | ||
540 | if (listener) | 665 | if (listener) |
541 | set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags); | 666 | set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags); |
@@ -543,7 +668,7 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv, | |||
543 | return cma_xprt; | 668 | return cma_xprt; |
544 | } | 669 | } |
545 | 670 | ||
546 | int svc_rdma_post_recv(struct svcxprt_rdma *xprt) | 671 | int svc_rdma_post_recv(struct svcxprt_rdma *xprt, gfp_t flags) |
547 | { | 672 | { |
548 | struct ib_recv_wr recv_wr, *bad_recv_wr; | 673 | struct ib_recv_wr recv_wr, *bad_recv_wr; |
549 | struct svc_rdma_op_ctxt *ctxt; | 674 | struct svc_rdma_op_ctxt *ctxt; |
@@ -561,7 +686,9 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt) | |||
561 | pr_err("svcrdma: Too many sges (%d)\n", sge_no); | 686 | pr_err("svcrdma: Too many sges (%d)\n", sge_no); |
562 | goto err_put_ctxt; | 687 | goto err_put_ctxt; |
563 | } | 688 | } |
564 | page = alloc_page(GFP_KERNEL | __GFP_NOFAIL); | 689 | page = alloc_page(flags); |
690 | if (!page) | ||
691 | goto err_put_ctxt; | ||
565 | ctxt->pages[sge_no] = page; | 692 | ctxt->pages[sge_no] = page; |
566 | pa = ib_dma_map_page(xprt->sc_cm_id->device, | 693 | pa = ib_dma_map_page(xprt->sc_cm_id->device, |
567 | page, 0, PAGE_SIZE, | 694 | page, 0, PAGE_SIZE, |
@@ -571,7 +698,7 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt) | |||
571 | atomic_inc(&xprt->sc_dma_used); | 698 | atomic_inc(&xprt->sc_dma_used); |
572 | ctxt->sge[sge_no].addr = pa; | 699 | ctxt->sge[sge_no].addr = pa; |
573 | ctxt->sge[sge_no].length = PAGE_SIZE; | 700 | ctxt->sge[sge_no].length = PAGE_SIZE; |
574 | ctxt->sge[sge_no].lkey = xprt->sc_dma_lkey; | 701 | ctxt->sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey; |
575 | ctxt->count = sge_no + 1; | 702 | ctxt->count = sge_no + 1; |
576 | buflen += PAGE_SIZE; | 703 | buflen += PAGE_SIZE; |
577 | } | 704 | } |
@@ -886,11 +1013,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
886 | struct rdma_conn_param conn_param; | 1013 | struct rdma_conn_param conn_param; |
887 | struct ib_cq_init_attr cq_attr = {}; | 1014 | struct ib_cq_init_attr cq_attr = {}; |
888 | struct ib_qp_init_attr qp_attr; | 1015 | struct ib_qp_init_attr qp_attr; |
889 | struct ib_device_attr devattr; | 1016 | struct ib_device *dev; |
890 | int uninitialized_var(dma_mr_acc); | 1017 | unsigned int i; |
891 | int need_dma_mr = 0; | 1018 | int ret = 0; |
892 | int ret; | ||
893 | int i; | ||
894 | 1019 | ||
895 | listen_rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt); | 1020 | listen_rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt); |
896 | clear_bit(XPT_CONN, &xprt->xpt_flags); | 1021 | clear_bit(XPT_CONN, &xprt->xpt_flags); |
@@ -910,37 +1035,42 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
910 | dprintk("svcrdma: newxprt from accept queue = %p, cm_id=%p\n", | 1035 | dprintk("svcrdma: newxprt from accept queue = %p, cm_id=%p\n", |
911 | newxprt, newxprt->sc_cm_id); | 1036 | newxprt, newxprt->sc_cm_id); |
912 | 1037 | ||
913 | ret = ib_query_device(newxprt->sc_cm_id->device, &devattr); | 1038 | dev = newxprt->sc_cm_id->device; |
914 | if (ret) { | ||
915 | dprintk("svcrdma: could not query device attributes on " | ||
916 | "device %p, rc=%d\n", newxprt->sc_cm_id->device, ret); | ||
917 | goto errout; | ||
918 | } | ||
919 | 1039 | ||
920 | /* Qualify the transport resource defaults with the | 1040 | /* Qualify the transport resource defaults with the |
921 | * capabilities of this particular device */ | 1041 | * capabilities of this particular device */ |
922 | newxprt->sc_max_sge = min((size_t)devattr.max_sge, | 1042 | newxprt->sc_max_sge = min((size_t)dev->attrs.max_sge, |
923 | (size_t)RPCSVC_MAXPAGES); | 1043 | (size_t)RPCSVC_MAXPAGES); |
924 | newxprt->sc_max_sge_rd = min_t(size_t, devattr.max_sge_rd, | 1044 | newxprt->sc_max_sge_rd = min_t(size_t, dev->attrs.max_sge_rd, |
925 | RPCSVC_MAXPAGES); | 1045 | RPCSVC_MAXPAGES); |
926 | newxprt->sc_max_requests = min((size_t)devattr.max_qp_wr, | 1046 | newxprt->sc_max_req_size = svcrdma_max_req_size; |
927 | (size_t)svcrdma_max_requests); | 1047 | newxprt->sc_max_requests = min_t(u32, dev->attrs.max_qp_wr, |
928 | newxprt->sc_sq_depth = RPCRDMA_SQ_DEPTH_MULT * newxprt->sc_max_requests; | 1048 | svcrdma_max_requests); |
1049 | newxprt->sc_max_bc_requests = min_t(u32, dev->attrs.max_qp_wr, | ||
1050 | svcrdma_max_bc_requests); | ||
1051 | newxprt->sc_rq_depth = newxprt->sc_max_requests + | ||
1052 | newxprt->sc_max_bc_requests; | ||
1053 | newxprt->sc_sq_depth = RPCRDMA_SQ_DEPTH_MULT * newxprt->sc_rq_depth; | ||
1054 | |||
1055 | if (!svc_rdma_prealloc_ctxts(newxprt)) | ||
1056 | goto errout; | ||
1057 | if (!svc_rdma_prealloc_maps(newxprt)) | ||
1058 | goto errout; | ||
929 | 1059 | ||
930 | /* | 1060 | /* |
931 | * Limit ORD based on client limit, local device limit, and | 1061 | * Limit ORD based on client limit, local device limit, and |
932 | * configured svcrdma limit. | 1062 | * configured svcrdma limit. |
933 | */ | 1063 | */ |
934 | newxprt->sc_ord = min_t(size_t, devattr.max_qp_rd_atom, newxprt->sc_ord); | 1064 | newxprt->sc_ord = min_t(size_t, dev->attrs.max_qp_rd_atom, newxprt->sc_ord); |
935 | newxprt->sc_ord = min_t(size_t, svcrdma_ord, newxprt->sc_ord); | 1065 | newxprt->sc_ord = min_t(size_t, svcrdma_ord, newxprt->sc_ord); |
936 | 1066 | ||
937 | newxprt->sc_pd = ib_alloc_pd(newxprt->sc_cm_id->device); | 1067 | newxprt->sc_pd = ib_alloc_pd(dev); |
938 | if (IS_ERR(newxprt->sc_pd)) { | 1068 | if (IS_ERR(newxprt->sc_pd)) { |
939 | dprintk("svcrdma: error creating PD for connect request\n"); | 1069 | dprintk("svcrdma: error creating PD for connect request\n"); |
940 | goto errout; | 1070 | goto errout; |
941 | } | 1071 | } |
942 | cq_attr.cqe = newxprt->sc_sq_depth; | 1072 | cq_attr.cqe = newxprt->sc_sq_depth; |
943 | newxprt->sc_sq_cq = ib_create_cq(newxprt->sc_cm_id->device, | 1073 | newxprt->sc_sq_cq = ib_create_cq(dev, |
944 | sq_comp_handler, | 1074 | sq_comp_handler, |
945 | cq_event_handler, | 1075 | cq_event_handler, |
946 | newxprt, | 1076 | newxprt, |
@@ -949,8 +1079,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
949 | dprintk("svcrdma: error creating SQ CQ for connect request\n"); | 1079 | dprintk("svcrdma: error creating SQ CQ for connect request\n"); |
950 | goto errout; | 1080 | goto errout; |
951 | } | 1081 | } |
952 | cq_attr.cqe = newxprt->sc_max_requests; | 1082 | cq_attr.cqe = newxprt->sc_rq_depth; |
953 | newxprt->sc_rq_cq = ib_create_cq(newxprt->sc_cm_id->device, | 1083 | newxprt->sc_rq_cq = ib_create_cq(dev, |
954 | rq_comp_handler, | 1084 | rq_comp_handler, |
955 | cq_event_handler, | 1085 | cq_event_handler, |
956 | newxprt, | 1086 | newxprt, |
@@ -964,7 +1094,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
964 | qp_attr.event_handler = qp_event_handler; | 1094 | qp_attr.event_handler = qp_event_handler; |
965 | qp_attr.qp_context = &newxprt->sc_xprt; | 1095 | qp_attr.qp_context = &newxprt->sc_xprt; |
966 | qp_attr.cap.max_send_wr = newxprt->sc_sq_depth; | 1096 | qp_attr.cap.max_send_wr = newxprt->sc_sq_depth; |
967 | qp_attr.cap.max_recv_wr = newxprt->sc_max_requests; | 1097 | qp_attr.cap.max_recv_wr = newxprt->sc_rq_depth; |
968 | qp_attr.cap.max_send_sge = newxprt->sc_max_sge; | 1098 | qp_attr.cap.max_send_sge = newxprt->sc_max_sge; |
969 | qp_attr.cap.max_recv_sge = newxprt->sc_max_sge; | 1099 | qp_attr.cap.max_recv_sge = newxprt->sc_max_sge; |
970 | qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; | 1100 | qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; |
@@ -978,7 +1108,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
978 | " cap.max_send_sge = %d\n" | 1108 | " cap.max_send_sge = %d\n" |
979 | " cap.max_recv_sge = %d\n", | 1109 | " cap.max_recv_sge = %d\n", |
980 | newxprt->sc_cm_id, newxprt->sc_pd, | 1110 | newxprt->sc_cm_id, newxprt->sc_pd, |
981 | newxprt->sc_cm_id->device, newxprt->sc_pd->device, | 1111 | dev, newxprt->sc_pd->device, |
982 | qp_attr.cap.max_send_wr, | 1112 | qp_attr.cap.max_send_wr, |
983 | qp_attr.cap.max_recv_wr, | 1113 | qp_attr.cap.max_recv_wr, |
984 | qp_attr.cap.max_send_sge, | 1114 | qp_attr.cap.max_send_sge, |
@@ -1014,9 +1144,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
1014 | * of an RDMA_READ. IB does not. | 1144 | * of an RDMA_READ. IB does not. |
1015 | */ | 1145 | */ |
1016 | newxprt->sc_reader = rdma_read_chunk_lcl; | 1146 | newxprt->sc_reader = rdma_read_chunk_lcl; |
1017 | if (devattr.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { | 1147 | if (dev->attrs.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { |
1018 | newxprt->sc_frmr_pg_list_len = | 1148 | newxprt->sc_frmr_pg_list_len = |
1019 | devattr.max_fast_reg_page_list_len; | 1149 | dev->attrs.max_fast_reg_page_list_len; |
1020 | newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_FAST_REG; | 1150 | newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_FAST_REG; |
1021 | newxprt->sc_reader = rdma_read_chunk_frmr; | 1151 | newxprt->sc_reader = rdma_read_chunk_frmr; |
1022 | } | 1152 | } |
@@ -1024,44 +1154,16 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
1024 | /* | 1154 | /* |
1025 | * Determine if a DMA MR is required and if so, what privs are required | 1155 | * Determine if a DMA MR is required and if so, what privs are required |
1026 | */ | 1156 | */ |
1027 | if (!rdma_protocol_iwarp(newxprt->sc_cm_id->device, | 1157 | if (!rdma_protocol_iwarp(dev, newxprt->sc_cm_id->port_num) && |
1028 | newxprt->sc_cm_id->port_num) && | 1158 | !rdma_ib_or_roce(dev, newxprt->sc_cm_id->port_num)) |
1029 | !rdma_ib_or_roce(newxprt->sc_cm_id->device, | ||
1030 | newxprt->sc_cm_id->port_num)) | ||
1031 | goto errout; | 1159 | goto errout; |
1032 | 1160 | ||
1033 | if (!(newxprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG) || | 1161 | if (rdma_protocol_iwarp(dev, newxprt->sc_cm_id->port_num)) |
1034 | !(devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)) { | ||
1035 | need_dma_mr = 1; | ||
1036 | dma_mr_acc = IB_ACCESS_LOCAL_WRITE; | ||
1037 | if (rdma_protocol_iwarp(newxprt->sc_cm_id->device, | ||
1038 | newxprt->sc_cm_id->port_num) && | ||
1039 | !(newxprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG)) | ||
1040 | dma_mr_acc |= IB_ACCESS_REMOTE_WRITE; | ||
1041 | } | ||
1042 | |||
1043 | if (rdma_protocol_iwarp(newxprt->sc_cm_id->device, | ||
1044 | newxprt->sc_cm_id->port_num)) | ||
1045 | newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_READ_W_INV; | 1162 | newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_READ_W_INV; |
1046 | 1163 | ||
1047 | /* Create the DMA MR if needed, otherwise, use the DMA LKEY */ | ||
1048 | if (need_dma_mr) { | ||
1049 | /* Register all of physical memory */ | ||
1050 | newxprt->sc_phys_mr = | ||
1051 | ib_get_dma_mr(newxprt->sc_pd, dma_mr_acc); | ||
1052 | if (IS_ERR(newxprt->sc_phys_mr)) { | ||
1053 | dprintk("svcrdma: Failed to create DMA MR ret=%d\n", | ||
1054 | ret); | ||
1055 | goto errout; | ||
1056 | } | ||
1057 | newxprt->sc_dma_lkey = newxprt->sc_phys_mr->lkey; | ||
1058 | } else | ||
1059 | newxprt->sc_dma_lkey = | ||
1060 | newxprt->sc_cm_id->device->local_dma_lkey; | ||
1061 | |||
1062 | /* Post receive buffers */ | 1164 | /* Post receive buffers */ |
1063 | for (i = 0; i < newxprt->sc_max_requests; i++) { | 1165 | for (i = 0; i < newxprt->sc_rq_depth; i++) { |
1064 | ret = svc_rdma_post_recv(newxprt); | 1166 | ret = svc_rdma_post_recv(newxprt, GFP_KERNEL); |
1065 | if (ret) { | 1167 | if (ret) { |
1066 | dprintk("svcrdma: failure posting receive buffers\n"); | 1168 | dprintk("svcrdma: failure posting receive buffers\n"); |
1067 | goto errout; | 1169 | goto errout; |
@@ -1160,12 +1262,14 @@ static void __svc_rdma_free(struct work_struct *work) | |||
1160 | { | 1262 | { |
1161 | struct svcxprt_rdma *rdma = | 1263 | struct svcxprt_rdma *rdma = |
1162 | container_of(work, struct svcxprt_rdma, sc_work); | 1264 | container_of(work, struct svcxprt_rdma, sc_work); |
1163 | dprintk("svcrdma: svc_rdma_free(%p)\n", rdma); | 1265 | struct svc_xprt *xprt = &rdma->sc_xprt; |
1266 | |||
1267 | dprintk("svcrdma: %s(%p)\n", __func__, rdma); | ||
1164 | 1268 | ||
1165 | /* We should only be called from kref_put */ | 1269 | /* We should only be called from kref_put */ |
1166 | if (atomic_read(&rdma->sc_xprt.xpt_ref.refcount) != 0) | 1270 | if (atomic_read(&xprt->xpt_ref.refcount) != 0) |
1167 | pr_err("svcrdma: sc_xprt still in use? (%d)\n", | 1271 | pr_err("svcrdma: sc_xprt still in use? (%d)\n", |
1168 | atomic_read(&rdma->sc_xprt.xpt_ref.refcount)); | 1272 | atomic_read(&xprt->xpt_ref.refcount)); |
1169 | 1273 | ||
1170 | /* | 1274 | /* |
1171 | * Destroy queued, but not processed read completions. Note | 1275 | * Destroy queued, but not processed read completions. Note |
@@ -1193,15 +1297,22 @@ static void __svc_rdma_free(struct work_struct *work) | |||
1193 | } | 1297 | } |
1194 | 1298 | ||
1195 | /* Warn if we leaked a resource or under-referenced */ | 1299 | /* Warn if we leaked a resource or under-referenced */ |
1196 | if (atomic_read(&rdma->sc_ctxt_used) != 0) | 1300 | if (rdma->sc_ctxt_used != 0) |
1197 | pr_err("svcrdma: ctxt still in use? (%d)\n", | 1301 | pr_err("svcrdma: ctxt still in use? (%d)\n", |
1198 | atomic_read(&rdma->sc_ctxt_used)); | 1302 | rdma->sc_ctxt_used); |
1199 | if (atomic_read(&rdma->sc_dma_used) != 0) | 1303 | if (atomic_read(&rdma->sc_dma_used) != 0) |
1200 | pr_err("svcrdma: dma still in use? (%d)\n", | 1304 | pr_err("svcrdma: dma still in use? (%d)\n", |
1201 | atomic_read(&rdma->sc_dma_used)); | 1305 | atomic_read(&rdma->sc_dma_used)); |
1202 | 1306 | ||
1203 | /* De-allocate fastreg mr */ | 1307 | /* Final put of backchannel client transport */ |
1308 | if (xprt->xpt_bc_xprt) { | ||
1309 | xprt_put(xprt->xpt_bc_xprt); | ||
1310 | xprt->xpt_bc_xprt = NULL; | ||
1311 | } | ||
1312 | |||
1204 | rdma_dealloc_frmr_q(rdma); | 1313 | rdma_dealloc_frmr_q(rdma); |
1314 | svc_rdma_destroy_ctxts(rdma); | ||
1315 | svc_rdma_destroy_maps(rdma); | ||
1205 | 1316 | ||
1206 | /* Destroy the QP if present (not a listener) */ | 1317 | /* Destroy the QP if present (not a listener) */ |
1207 | if (rdma->sc_qp && !IS_ERR(rdma->sc_qp)) | 1318 | if (rdma->sc_qp && !IS_ERR(rdma->sc_qp)) |
@@ -1213,9 +1324,6 @@ static void __svc_rdma_free(struct work_struct *work) | |||
1213 | if (rdma->sc_rq_cq && !IS_ERR(rdma->sc_rq_cq)) | 1324 | if (rdma->sc_rq_cq && !IS_ERR(rdma->sc_rq_cq)) |
1214 | ib_destroy_cq(rdma->sc_rq_cq); | 1325 | ib_destroy_cq(rdma->sc_rq_cq); |
1215 | 1326 | ||
1216 | if (rdma->sc_phys_mr && !IS_ERR(rdma->sc_phys_mr)) | ||
1217 | ib_dereg_mr(rdma->sc_phys_mr); | ||
1218 | |||
1219 | if (rdma->sc_pd && !IS_ERR(rdma->sc_pd)) | 1327 | if (rdma->sc_pd && !IS_ERR(rdma->sc_pd)) |
1220 | ib_dealloc_pd(rdma->sc_pd); | 1328 | ib_dealloc_pd(rdma->sc_pd); |
1221 | 1329 | ||
@@ -1321,7 +1429,9 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, | |||
1321 | int length; | 1429 | int length; |
1322 | int ret; | 1430 | int ret; |
1323 | 1431 | ||
1324 | p = alloc_page(GFP_KERNEL | __GFP_NOFAIL); | 1432 | p = alloc_page(GFP_KERNEL); |
1433 | if (!p) | ||
1434 | return; | ||
1325 | va = page_address(p); | 1435 | va = page_address(p); |
1326 | 1436 | ||
1327 | /* XDR encode error */ | 1437 | /* XDR encode error */ |
@@ -1341,7 +1451,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, | |||
1341 | return; | 1451 | return; |
1342 | } | 1452 | } |
1343 | atomic_inc(&xprt->sc_dma_used); | 1453 | atomic_inc(&xprt->sc_dma_used); |
1344 | ctxt->sge[0].lkey = xprt->sc_dma_lkey; | 1454 | ctxt->sge[0].lkey = xprt->sc_pd->local_dma_lkey; |
1345 | ctxt->sge[0].length = length; | 1455 | ctxt->sge[0].length = length; |
1346 | 1456 | ||
1347 | /* Prepare SEND WR */ | 1457 | /* Prepare SEND WR */ |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 740bddcf3488..b1b009f10ea3 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -63,7 +63,7 @@ | |||
63 | */ | 63 | */ |
64 | 64 | ||
65 | static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE; | 65 | static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE; |
66 | static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; | 66 | unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; |
67 | static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; | 67 | static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; |
68 | static unsigned int xprt_rdma_inline_write_padding; | 68 | static unsigned int xprt_rdma_inline_write_padding; |
69 | static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR; | 69 | static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR; |
@@ -143,12 +143,7 @@ static struct ctl_table sunrpc_table[] = { | |||
143 | 143 | ||
144 | #endif | 144 | #endif |
145 | 145 | ||
146 | #define RPCRDMA_BIND_TO (60U * HZ) | 146 | static struct rpc_xprt_ops xprt_rdma_procs; /*forward reference */ |
147 | #define RPCRDMA_INIT_REEST_TO (5U * HZ) | ||
148 | #define RPCRDMA_MAX_REEST_TO (30U * HZ) | ||
149 | #define RPCRDMA_IDLE_DISC_TO (5U * 60 * HZ) | ||
150 | |||
151 | static struct rpc_xprt_ops xprt_rdma_procs; /* forward reference */ | ||
152 | 147 | ||
153 | static void | 148 | static void |
154 | xprt_rdma_format_addresses4(struct rpc_xprt *xprt, struct sockaddr *sap) | 149 | xprt_rdma_format_addresses4(struct rpc_xprt *xprt, struct sockaddr *sap) |
@@ -174,7 +169,7 @@ xprt_rdma_format_addresses6(struct rpc_xprt *xprt, struct sockaddr *sap) | |||
174 | xprt->address_strings[RPC_DISPLAY_NETID] = RPCBIND_NETID_RDMA6; | 169 | xprt->address_strings[RPC_DISPLAY_NETID] = RPCBIND_NETID_RDMA6; |
175 | } | 170 | } |
176 | 171 | ||
177 | static void | 172 | void |
178 | xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap) | 173 | xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap) |
179 | { | 174 | { |
180 | char buf[128]; | 175 | char buf[128]; |
@@ -203,7 +198,7 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap) | |||
203 | xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; | 198 | xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; |
204 | } | 199 | } |
205 | 200 | ||
206 | static void | 201 | void |
207 | xprt_rdma_free_addresses(struct rpc_xprt *xprt) | 202 | xprt_rdma_free_addresses(struct rpc_xprt *xprt) |
208 | { | 203 | { |
209 | unsigned int i; | 204 | unsigned int i; |
@@ -499,7 +494,7 @@ xprt_rdma_allocate(struct rpc_task *task, size_t size) | |||
499 | if (req == NULL) | 494 | if (req == NULL) |
500 | return NULL; | 495 | return NULL; |
501 | 496 | ||
502 | flags = GFP_NOIO | __GFP_NOWARN; | 497 | flags = RPCRDMA_DEF_GFP; |
503 | if (RPC_IS_SWAPPER(task)) | 498 | if (RPC_IS_SWAPPER(task)) |
504 | flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN; | 499 | flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN; |
505 | 500 | ||
@@ -642,7 +637,7 @@ drop_connection: | |||
642 | return -ENOTCONN; /* implies disconnect */ | 637 | return -ENOTCONN; /* implies disconnect */ |
643 | } | 638 | } |
644 | 639 | ||
645 | static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | 640 | void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) |
646 | { | 641 | { |
647 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | 642 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); |
648 | long idle_time = 0; | 643 | long idle_time = 0; |
@@ -743,6 +738,11 @@ void xprt_rdma_cleanup(void) | |||
743 | 738 | ||
744 | rpcrdma_destroy_wq(); | 739 | rpcrdma_destroy_wq(); |
745 | frwr_destroy_recovery_wq(); | 740 | frwr_destroy_recovery_wq(); |
741 | |||
742 | rc = xprt_unregister_transport(&xprt_rdma_bc); | ||
743 | if (rc) | ||
744 | dprintk("RPC: %s: xprt_unregister(bc) returned %i\n", | ||
745 | __func__, rc); | ||
746 | } | 746 | } |
747 | 747 | ||
748 | int xprt_rdma_init(void) | 748 | int xprt_rdma_init(void) |
@@ -766,6 +766,14 @@ int xprt_rdma_init(void) | |||
766 | return rc; | 766 | return rc; |
767 | } | 767 | } |
768 | 768 | ||
769 | rc = xprt_register_transport(&xprt_rdma_bc); | ||
770 | if (rc) { | ||
771 | xprt_unregister_transport(&xprt_rdma); | ||
772 | rpcrdma_destroy_wq(); | ||
773 | frwr_destroy_recovery_wq(); | ||
774 | return rc; | ||
775 | } | ||
776 | |||
769 | dprintk("RPCRDMA Module Init, register RPC RDMA transport\n"); | 777 | dprintk("RPCRDMA Module Init, register RPC RDMA transport\n"); |
770 | 778 | ||
771 | dprintk("Defaults:\n"); | 779 | dprintk("Defaults:\n"); |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 732c71ce5dca..878f1bfb1db9 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -462,7 +462,6 @@ int | |||
462 | rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | 462 | rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) |
463 | { | 463 | { |
464 | struct rpcrdma_ia *ia = &xprt->rx_ia; | 464 | struct rpcrdma_ia *ia = &xprt->rx_ia; |
465 | struct ib_device_attr *devattr = &ia->ri_devattr; | ||
466 | int rc; | 465 | int rc; |
467 | 466 | ||
468 | ia->ri_dma_mr = NULL; | 467 | ia->ri_dma_mr = NULL; |
@@ -482,16 +481,10 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | |||
482 | goto out2; | 481 | goto out2; |
483 | } | 482 | } |
484 | 483 | ||
485 | rc = ib_query_device(ia->ri_device, devattr); | ||
486 | if (rc) { | ||
487 | dprintk("RPC: %s: ib_query_device failed %d\n", | ||
488 | __func__, rc); | ||
489 | goto out3; | ||
490 | } | ||
491 | |||
492 | if (memreg == RPCRDMA_FRMR) { | 484 | if (memreg == RPCRDMA_FRMR) { |
493 | if (!(devattr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) || | 485 | if (!(ia->ri_device->attrs.device_cap_flags & |
494 | (devattr->max_fast_reg_page_list_len == 0)) { | 486 | IB_DEVICE_MEM_MGT_EXTENSIONS) || |
487 | (ia->ri_device->attrs.max_fast_reg_page_list_len == 0)) { | ||
495 | dprintk("RPC: %s: FRMR registration " | 488 | dprintk("RPC: %s: FRMR registration " |
496 | "not supported by HCA\n", __func__); | 489 | "not supported by HCA\n", __func__); |
497 | memreg = RPCRDMA_MTHCAFMR; | 490 | memreg = RPCRDMA_MTHCAFMR; |
@@ -566,24 +559,23 @@ int | |||
566 | rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | 559 | rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, |
567 | struct rpcrdma_create_data_internal *cdata) | 560 | struct rpcrdma_create_data_internal *cdata) |
568 | { | 561 | { |
569 | struct ib_device_attr *devattr = &ia->ri_devattr; | ||
570 | struct ib_cq *sendcq, *recvcq; | 562 | struct ib_cq *sendcq, *recvcq; |
571 | struct ib_cq_init_attr cq_attr = {}; | 563 | struct ib_cq_init_attr cq_attr = {}; |
572 | unsigned int max_qp_wr; | 564 | unsigned int max_qp_wr; |
573 | int rc, err; | 565 | int rc, err; |
574 | 566 | ||
575 | if (devattr->max_sge < RPCRDMA_MAX_IOVS) { | 567 | if (ia->ri_device->attrs.max_sge < RPCRDMA_MAX_IOVS) { |
576 | dprintk("RPC: %s: insufficient sge's available\n", | 568 | dprintk("RPC: %s: insufficient sge's available\n", |
577 | __func__); | 569 | __func__); |
578 | return -ENOMEM; | 570 | return -ENOMEM; |
579 | } | 571 | } |
580 | 572 | ||
581 | if (devattr->max_qp_wr <= RPCRDMA_BACKWARD_WRS) { | 573 | if (ia->ri_device->attrs.max_qp_wr <= RPCRDMA_BACKWARD_WRS) { |
582 | dprintk("RPC: %s: insufficient wqe's available\n", | 574 | dprintk("RPC: %s: insufficient wqe's available\n", |
583 | __func__); | 575 | __func__); |
584 | return -ENOMEM; | 576 | return -ENOMEM; |
585 | } | 577 | } |
586 | max_qp_wr = devattr->max_qp_wr - RPCRDMA_BACKWARD_WRS; | 578 | max_qp_wr = ia->ri_device->attrs.max_qp_wr - RPCRDMA_BACKWARD_WRS; |
587 | 579 | ||
588 | /* check provider's send/recv wr limits */ | 580 | /* check provider's send/recv wr limits */ |
589 | if (cdata->max_requests > max_qp_wr) | 581 | if (cdata->max_requests > max_qp_wr) |
@@ -668,11 +660,11 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | |||
668 | 660 | ||
669 | /* Client offers RDMA Read but does not initiate */ | 661 | /* Client offers RDMA Read but does not initiate */ |
670 | ep->rep_remote_cma.initiator_depth = 0; | 662 | ep->rep_remote_cma.initiator_depth = 0; |
671 | if (devattr->max_qp_rd_atom > 32) /* arbitrary but <= 255 */ | 663 | if (ia->ri_device->attrs.max_qp_rd_atom > 32) /* arbitrary but <= 255 */ |
672 | ep->rep_remote_cma.responder_resources = 32; | 664 | ep->rep_remote_cma.responder_resources = 32; |
673 | else | 665 | else |
674 | ep->rep_remote_cma.responder_resources = | 666 | ep->rep_remote_cma.responder_resources = |
675 | devattr->max_qp_rd_atom; | 667 | ia->ri_device->attrs.max_qp_rd_atom; |
676 | 668 | ||
677 | ep->rep_remote_cma.retry_count = 7; | 669 | ep->rep_remote_cma.retry_count = 7; |
678 | ep->rep_remote_cma.flow_control = 0; | 670 | ep->rep_remote_cma.flow_control = 0; |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 728101ddc44b..38fe11b09875 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -55,6 +55,11 @@ | |||
55 | #define RDMA_RESOLVE_TIMEOUT (5000) /* 5 seconds */ | 55 | #define RDMA_RESOLVE_TIMEOUT (5000) /* 5 seconds */ |
56 | #define RDMA_CONNECT_RETRY_MAX (2) /* retries if no listener backlog */ | 56 | #define RDMA_CONNECT_RETRY_MAX (2) /* retries if no listener backlog */ |
57 | 57 | ||
58 | #define RPCRDMA_BIND_TO (60U * HZ) | ||
59 | #define RPCRDMA_INIT_REEST_TO (5U * HZ) | ||
60 | #define RPCRDMA_MAX_REEST_TO (30U * HZ) | ||
61 | #define RPCRDMA_IDLE_DISC_TO (5U * 60 * HZ) | ||
62 | |||
58 | /* | 63 | /* |
59 | * Interface Adapter -- one per transport instance | 64 | * Interface Adapter -- one per transport instance |
60 | */ | 65 | */ |
@@ -68,7 +73,6 @@ struct rpcrdma_ia { | |||
68 | struct completion ri_done; | 73 | struct completion ri_done; |
69 | int ri_async_rc; | 74 | int ri_async_rc; |
70 | unsigned int ri_max_frmr_depth; | 75 | unsigned int ri_max_frmr_depth; |
71 | struct ib_device_attr ri_devattr; | ||
72 | struct ib_qp_attr ri_qp_attr; | 76 | struct ib_qp_attr ri_qp_attr; |
73 | struct ib_qp_init_attr ri_qp_init_attr; | 77 | struct ib_qp_init_attr ri_qp_init_attr; |
74 | }; | 78 | }; |
@@ -142,6 +146,8 @@ rdmab_to_msg(struct rpcrdma_regbuf *rb) | |||
142 | return (struct rpcrdma_msg *)rb->rg_base; | 146 | return (struct rpcrdma_msg *)rb->rg_base; |
143 | } | 147 | } |
144 | 148 | ||
149 | #define RPCRDMA_DEF_GFP (GFP_NOIO | __GFP_NOWARN) | ||
150 | |||
145 | /* | 151 | /* |
146 | * struct rpcrdma_rep -- this structure encapsulates state required to recv | 152 | * struct rpcrdma_rep -- this structure encapsulates state required to recv |
147 | * and complete a reply, asychronously. It needs several pieces of | 153 | * and complete a reply, asychronously. It needs several pieces of |
@@ -309,6 +315,8 @@ struct rpcrdma_buffer { | |||
309 | u32 rb_bc_srv_max_requests; | 315 | u32 rb_bc_srv_max_requests; |
310 | spinlock_t rb_reqslock; /* protect rb_allreqs */ | 316 | spinlock_t rb_reqslock; /* protect rb_allreqs */ |
311 | struct list_head rb_allreqs; | 317 | struct list_head rb_allreqs; |
318 | |||
319 | u32 rb_bc_max_requests; | ||
312 | }; | 320 | }; |
313 | #define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia) | 321 | #define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia) |
314 | 322 | ||
@@ -516,6 +524,10 @@ int rpcrdma_marshal_req(struct rpc_rqst *); | |||
516 | 524 | ||
517 | /* RPC/RDMA module init - xprtrdma/transport.c | 525 | /* RPC/RDMA module init - xprtrdma/transport.c |
518 | */ | 526 | */ |
527 | extern unsigned int xprt_rdma_max_inline_read; | ||
528 | void xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap); | ||
529 | void xprt_rdma_free_addresses(struct rpc_xprt *xprt); | ||
530 | void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq); | ||
519 | int xprt_rdma_init(void); | 531 | int xprt_rdma_init(void); |
520 | void xprt_rdma_cleanup(void); | 532 | void xprt_rdma_cleanup(void); |
521 | 533 | ||
@@ -531,11 +543,6 @@ void xprt_rdma_bc_free_rqst(struct rpc_rqst *); | |||
531 | void xprt_rdma_bc_destroy(struct rpc_xprt *, unsigned int); | 543 | void xprt_rdma_bc_destroy(struct rpc_xprt *, unsigned int); |
532 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 544 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
533 | 545 | ||
534 | /* Temporary NFS request map cache. Created in svc_rdma.c */ | 546 | extern struct xprt_class xprt_rdma_bc; |
535 | extern struct kmem_cache *svc_rdma_map_cachep; | ||
536 | /* WR context cache. Created in svc_rdma.c */ | ||
537 | extern struct kmem_cache *svc_rdma_ctxt_cachep; | ||
538 | /* Workqueue created in svc_rdma.c */ | ||
539 | extern struct workqueue_struct *svc_rdma_wq; | ||
540 | 547 | ||
541 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ | 548 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index ebc661d3b6e3..47f7da58a7f0 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/if_vlan.h> | 22 | #include <linux/if_vlan.h> |
23 | #include <linux/rtnetlink.h> | ||
23 | #include <net/ip_fib.h> | 24 | #include <net/ip_fib.h> |
24 | #include <net/switchdev.h> | 25 | #include <net/switchdev.h> |
25 | 26 | ||
@@ -567,7 +568,6 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj, | |||
567 | } | 568 | } |
568 | EXPORT_SYMBOL_GPL(switchdev_port_obj_dump); | 569 | EXPORT_SYMBOL_GPL(switchdev_port_obj_dump); |
569 | 570 | ||
570 | static DEFINE_MUTEX(switchdev_mutex); | ||
571 | static RAW_NOTIFIER_HEAD(switchdev_notif_chain); | 571 | static RAW_NOTIFIER_HEAD(switchdev_notif_chain); |
572 | 572 | ||
573 | /** | 573 | /** |
@@ -582,9 +582,9 @@ int register_switchdev_notifier(struct notifier_block *nb) | |||
582 | { | 582 | { |
583 | int err; | 583 | int err; |
584 | 584 | ||
585 | mutex_lock(&switchdev_mutex); | 585 | rtnl_lock(); |
586 | err = raw_notifier_chain_register(&switchdev_notif_chain, nb); | 586 | err = raw_notifier_chain_register(&switchdev_notif_chain, nb); |
587 | mutex_unlock(&switchdev_mutex); | 587 | rtnl_unlock(); |
588 | return err; | 588 | return err; |
589 | } | 589 | } |
590 | EXPORT_SYMBOL_GPL(register_switchdev_notifier); | 590 | EXPORT_SYMBOL_GPL(register_switchdev_notifier); |
@@ -600,9 +600,9 @@ int unregister_switchdev_notifier(struct notifier_block *nb) | |||
600 | { | 600 | { |
601 | int err; | 601 | int err; |
602 | 602 | ||
603 | mutex_lock(&switchdev_mutex); | 603 | rtnl_lock(); |
604 | err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb); | 604 | err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb); |
605 | mutex_unlock(&switchdev_mutex); | 605 | rtnl_unlock(); |
606 | return err; | 606 | return err; |
607 | } | 607 | } |
608 | EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); | 608 | EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); |
@@ -616,16 +616,17 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); | |||
616 | * Call all network notifier blocks. This should be called by driver | 616 | * Call all network notifier blocks. This should be called by driver |
617 | * when it needs to propagate hardware event. | 617 | * when it needs to propagate hardware event. |
618 | * Return values are same as for atomic_notifier_call_chain(). | 618 | * Return values are same as for atomic_notifier_call_chain(). |
619 | * rtnl_lock must be held. | ||
619 | */ | 620 | */ |
620 | int call_switchdev_notifiers(unsigned long val, struct net_device *dev, | 621 | int call_switchdev_notifiers(unsigned long val, struct net_device *dev, |
621 | struct switchdev_notifier_info *info) | 622 | struct switchdev_notifier_info *info) |
622 | { | 623 | { |
623 | int err; | 624 | int err; |
624 | 625 | ||
626 | ASSERT_RTNL(); | ||
627 | |||
625 | info->dev = dev; | 628 | info->dev = dev; |
626 | mutex_lock(&switchdev_mutex); | ||
627 | err = raw_notifier_call_chain(&switchdev_notif_chain, val, info); | 629 | err = raw_notifier_call_chain(&switchdev_notif_chain, val, info); |
628 | mutex_unlock(&switchdev_mutex); | ||
629 | return err; | 630 | return err; |
630 | } | 631 | } |
631 | EXPORT_SYMBOL_GPL(call_switchdev_notifiers); | 632 | EXPORT_SYMBOL_GPL(call_switchdev_notifiers); |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 350cca33ee0a..69ee2eeef968 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -289,15 +289,14 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, | |||
289 | struct sockaddr_tipc *addr, void *usr_data, | 289 | struct sockaddr_tipc *addr, void *usr_data, |
290 | void *buf, size_t len) | 290 | void *buf, size_t len) |
291 | { | 291 | { |
292 | struct tipc_subscriber *subscriber = usr_data; | 292 | struct tipc_subscriber *subscrb = usr_data; |
293 | struct tipc_subscription *sub = NULL; | 293 | struct tipc_subscription *sub = NULL; |
294 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 294 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
295 | 295 | ||
296 | tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscriber, &sub); | 296 | if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub)) |
297 | if (sub) | 297 | return tipc_conn_terminate(tn->topsrv, subscrb->conid); |
298 | tipc_nametbl_subscribe(sub); | 298 | |
299 | else | 299 | tipc_nametbl_subscribe(sub); |
300 | tipc_conn_terminate(tn->topsrv, subscriber->conid); | ||
301 | } | 300 | } |
302 | 301 | ||
303 | /* Handle one request to establish a new subscriber */ | 302 | /* Handle one request to establish a new subscriber */ |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c5bf5ef2bf89..49d5093eb055 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -2339,6 +2339,7 @@ again: | |||
2339 | 2339 | ||
2340 | if (signal_pending(current)) { | 2340 | if (signal_pending(current)) { |
2341 | err = sock_intr_errno(timeo); | 2341 | err = sock_intr_errno(timeo); |
2342 | scm_destroy(&scm); | ||
2342 | goto out; | 2343 | goto out; |
2343 | } | 2344 | } |
2344 | 2345 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b0ce1c484a3..547ceecc0523 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -231,20 +231,22 @@ static const struct ieee80211_regdomain world_regdom = { | |||
231 | /* IEEE 802.11b/g, channels 1..11 */ | 231 | /* IEEE 802.11b/g, channels 1..11 */ |
232 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), | 232 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), |
233 | /* IEEE 802.11b/g, channels 12..13. */ | 233 | /* IEEE 802.11b/g, channels 12..13. */ |
234 | REG_RULE(2467-10, 2472+10, 40, 6, 20, | 234 | REG_RULE(2467-10, 2472+10, 20, 6, 20, |
235 | NL80211_RRF_NO_IR), | 235 | NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW), |
236 | /* IEEE 802.11 channel 14 - Only JP enables | 236 | /* IEEE 802.11 channel 14 - Only JP enables |
237 | * this and for 802.11b only */ | 237 | * this and for 802.11b only */ |
238 | REG_RULE(2484-10, 2484+10, 20, 6, 20, | 238 | REG_RULE(2484-10, 2484+10, 20, 6, 20, |
239 | NL80211_RRF_NO_IR | | 239 | NL80211_RRF_NO_IR | |
240 | NL80211_RRF_NO_OFDM), | 240 | NL80211_RRF_NO_OFDM), |
241 | /* IEEE 802.11a, channel 36..48 */ | 241 | /* IEEE 802.11a, channel 36..48 */ |
242 | REG_RULE(5180-10, 5240+10, 160, 6, 20, | 242 | REG_RULE(5180-10, 5240+10, 80, 6, 20, |
243 | NL80211_RRF_NO_IR), | 243 | NL80211_RRF_NO_IR | |
244 | NL80211_RRF_AUTO_BW), | ||
244 | 245 | ||
245 | /* IEEE 802.11a, channel 52..64 - DFS required */ | 246 | /* IEEE 802.11a, channel 52..64 - DFS required */ |
246 | REG_RULE(5260-10, 5320+10, 160, 6, 20, | 247 | REG_RULE(5260-10, 5320+10, 80, 6, 20, |
247 | NL80211_RRF_NO_IR | | 248 | NL80211_RRF_NO_IR | |
249 | NL80211_RRF_AUTO_BW | | ||
248 | NL80211_RRF_DFS), | 250 | NL80211_RRF_DFS), |
249 | 251 | ||
250 | /* IEEE 802.11a, channel 100..144 - DFS required */ | 252 | /* IEEE 802.11a, channel 100..144 - DFS required */ |
@@ -2745,7 +2747,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2745 | const struct ieee80211_power_rule *power_rule = NULL; | 2747 | const struct ieee80211_power_rule *power_rule = NULL; |
2746 | char bw[32], cac_time[32]; | 2748 | char bw[32], cac_time[32]; |
2747 | 2749 | ||
2748 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n"); | 2750 | pr_debug(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n"); |
2749 | 2751 | ||
2750 | for (i = 0; i < rd->n_reg_rules; i++) { | 2752 | for (i = 0; i < rd->n_reg_rules; i++) { |
2751 | reg_rule = &rd->reg_rules[i]; | 2753 | reg_rule = &rd->reg_rules[i]; |
@@ -2772,7 +2774,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2772 | * in certain regions | 2774 | * in certain regions |
2773 | */ | 2775 | */ |
2774 | if (power_rule->max_antenna_gain) | 2776 | if (power_rule->max_antenna_gain) |
2775 | pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n", | 2777 | pr_debug(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n", |
2776 | freq_range->start_freq_khz, | 2778 | freq_range->start_freq_khz, |
2777 | freq_range->end_freq_khz, | 2779 | freq_range->end_freq_khz, |
2778 | bw, | 2780 | bw, |
@@ -2780,7 +2782,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2780 | power_rule->max_eirp, | 2782 | power_rule->max_eirp, |
2781 | cac_time); | 2783 | cac_time); |
2782 | else | 2784 | else |
2783 | pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n", | 2785 | pr_debug(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n", |
2784 | freq_range->start_freq_khz, | 2786 | freq_range->start_freq_khz, |
2785 | freq_range->end_freq_khz, | 2787 | freq_range->end_freq_khz, |
2786 | bw, | 2788 | bw, |
@@ -2813,35 +2815,35 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
2813 | struct cfg80211_registered_device *rdev; | 2815 | struct cfg80211_registered_device *rdev; |
2814 | rdev = cfg80211_rdev_by_wiphy_idx(lr->wiphy_idx); | 2816 | rdev = cfg80211_rdev_by_wiphy_idx(lr->wiphy_idx); |
2815 | if (rdev) { | 2817 | if (rdev) { |
2816 | pr_info("Current regulatory domain updated by AP to: %c%c\n", | 2818 | pr_debug("Current regulatory domain updated by AP to: %c%c\n", |
2817 | rdev->country_ie_alpha2[0], | 2819 | rdev->country_ie_alpha2[0], |
2818 | rdev->country_ie_alpha2[1]); | 2820 | rdev->country_ie_alpha2[1]); |
2819 | } else | 2821 | } else |
2820 | pr_info("Current regulatory domain intersected:\n"); | 2822 | pr_debug("Current regulatory domain intersected:\n"); |
2821 | } else | 2823 | } else |
2822 | pr_info("Current regulatory domain intersected:\n"); | 2824 | pr_debug("Current regulatory domain intersected:\n"); |
2823 | } else if (is_world_regdom(rd->alpha2)) { | 2825 | } else if (is_world_regdom(rd->alpha2)) { |
2824 | pr_info("World regulatory domain updated:\n"); | 2826 | pr_debug("World regulatory domain updated:\n"); |
2825 | } else { | 2827 | } else { |
2826 | if (is_unknown_alpha2(rd->alpha2)) | 2828 | if (is_unknown_alpha2(rd->alpha2)) |
2827 | pr_info("Regulatory domain changed to driver built-in settings (unknown country)\n"); | 2829 | pr_debug("Regulatory domain changed to driver built-in settings (unknown country)\n"); |
2828 | else { | 2830 | else { |
2829 | if (reg_request_cell_base(lr)) | 2831 | if (reg_request_cell_base(lr)) |
2830 | pr_info("Regulatory domain changed to country: %c%c by Cell Station\n", | 2832 | pr_debug("Regulatory domain changed to country: %c%c by Cell Station\n", |
2831 | rd->alpha2[0], rd->alpha2[1]); | 2833 | rd->alpha2[0], rd->alpha2[1]); |
2832 | else | 2834 | else |
2833 | pr_info("Regulatory domain changed to country: %c%c\n", | 2835 | pr_debug("Regulatory domain changed to country: %c%c\n", |
2834 | rd->alpha2[0], rd->alpha2[1]); | 2836 | rd->alpha2[0], rd->alpha2[1]); |
2835 | } | 2837 | } |
2836 | } | 2838 | } |
2837 | 2839 | ||
2838 | pr_info(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region)); | 2840 | pr_debug(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region)); |
2839 | print_rd_rules(rd); | 2841 | print_rd_rules(rd); |
2840 | } | 2842 | } |
2841 | 2843 | ||
2842 | static void print_regdomain_info(const struct ieee80211_regdomain *rd) | 2844 | static void print_regdomain_info(const struct ieee80211_regdomain *rd) |
2843 | { | 2845 | { |
2844 | pr_info("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]); | 2846 | pr_debug("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]); |
2845 | print_rd_rules(rd); | 2847 | print_rd_rules(rd); |
2846 | } | 2848 | } |
2847 | 2849 | ||
@@ -2862,7 +2864,8 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd, | |||
2862 | return -EALREADY; | 2864 | return -EALREADY; |
2863 | 2865 | ||
2864 | if (!is_valid_rd(rd)) { | 2866 | if (!is_valid_rd(rd)) { |
2865 | pr_err("Invalid regulatory domain detected:\n"); | 2867 | pr_err("Invalid regulatory domain detected: %c%c\n", |
2868 | rd->alpha2[0], rd->alpha2[1]); | ||
2866 | print_regdomain_info(rd); | 2869 | print_regdomain_info(rd); |
2867 | return -EINVAL; | 2870 | return -EINVAL; |
2868 | } | 2871 | } |
@@ -2898,7 +2901,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd, | |||
2898 | return -EALREADY; | 2901 | return -EALREADY; |
2899 | 2902 | ||
2900 | if (!is_valid_rd(rd)) { | 2903 | if (!is_valid_rd(rd)) { |
2901 | pr_err("Invalid regulatory domain detected:\n"); | 2904 | pr_err("Invalid regulatory domain detected: %c%c\n", |
2905 | rd->alpha2[0], rd->alpha2[1]); | ||
2902 | print_regdomain_info(rd); | 2906 | print_regdomain_info(rd); |
2903 | return -EINVAL; | 2907 | return -EINVAL; |
2904 | } | 2908 | } |
@@ -2956,7 +2960,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
2956 | */ | 2960 | */ |
2957 | 2961 | ||
2958 | if (!is_valid_rd(rd)) { | 2962 | if (!is_valid_rd(rd)) { |
2959 | pr_err("Invalid regulatory domain detected:\n"); | 2963 | pr_err("Invalid regulatory domain detected: %c%c\n", |
2964 | rd->alpha2[0], rd->alpha2[1]); | ||
2960 | print_regdomain_info(rd); | 2965 | print_regdomain_info(rd); |
2961 | return -EINVAL; | 2966 | return -EINVAL; |
2962 | } | 2967 | } |