Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gro: remove rcu_read_lock/rcu_read_unlock from gro_receive handlers

All gro_receive() handlers are called from dev_gro_receive()
while rcu_read_lock() has been called.

There is no point stacking more rcu_read_lock()

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
fc1ca334 1aad9634

+14 -44
+1 -4
drivers/net/geneve.c
··· 517 517 518 518 type = gh->proto_type; 519 519 520 - rcu_read_lock(); 521 520 ptype = gro_find_receive_by_type(type); 522 521 if (!ptype) 523 - goto out_unlock; 522 + goto out; 524 523 525 524 skb_gro_pull(skb, gh_len); 526 525 skb_gro_postpull_rcsum(skb, gh, gh_len); 527 526 pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); 528 527 flush = 0; 529 528 530 - out_unlock: 531 - rcu_read_unlock(); 532 529 out: 533 530 skb_gro_flush_final(skb, pp, flush); 534 531
+1 -4
net/8021q/vlan_core.c
··· 476 476 477 477 type = vhdr->h_vlan_encapsulated_proto; 478 478 479 - rcu_read_lock(); 480 479 ptype = gro_find_receive_by_type(type); 481 480 if (!ptype) 482 - goto out_unlock; 481 + goto out; 483 482 484 483 flush = 0; 485 484 ··· 500 501 ipv6_gro_receive, inet_gro_receive, 501 502 head, skb); 502 503 503 - out_unlock: 504 - rcu_read_unlock(); 505 504 out: 506 505 skb_gro_flush_final(skb, pp, flush); 507 506
+1 -4
net/ethernet/eth.c
··· 436 436 437 437 type = eh->h_proto; 438 438 439 - rcu_read_lock(); 440 439 ptype = gro_find_receive_by_type(type); 441 440 if (ptype == NULL) { 442 441 flush = 1; 443 - goto out_unlock; 442 + goto out; 444 443 } 445 444 446 445 skb_gro_pull(skb, sizeof(*eh)); ··· 449 450 ipv6_gro_receive, inet_gro_receive, 450 451 head, skb); 451 452 452 - out_unlock: 453 - rcu_read_unlock(); 454 453 out: 455 454 skb_gro_flush_final(skb, pp, flush); 456 455
+4 -8
net/ipv4/af_inet.c
··· 1452 1452 1453 1453 proto = iph->protocol; 1454 1454 1455 - rcu_read_lock(); 1456 1455 ops = rcu_dereference(inet_offloads[proto]); 1457 1456 if (!ops || !ops->callbacks.gro_receive) 1458 - goto out_unlock; 1457 + goto out; 1459 1458 1460 1459 if (*(u8 *)iph != 0x45) 1461 - goto out_unlock; 1460 + goto out; 1462 1461 1463 1462 if (ip_is_fragment(iph)) 1464 - goto out_unlock; 1463 + goto out; 1465 1464 1466 1465 if (unlikely(ip_fast_csum((u8 *)iph, 5))) 1467 - goto out_unlock; 1466 + goto out; 1468 1467 1469 1468 id = ntohl(*(__be32 *)&iph->id); 1470 1469 flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); ··· 1539 1540 1540 1541 pp = indirect_call_gro_receive(tcp4_gro_receive, udp4_gro_receive, 1541 1542 ops->callbacks.gro_receive, head, skb); 1542 - 1543 - out_unlock: 1544 - rcu_read_unlock(); 1545 1543 1546 1544 out: 1547 1545 skb_gro_flush_final(skb, pp, flush);
+3 -9
net/ipv4/fou.c
··· 247 247 /* Flag this frame as already having an outer encap header */ 248 248 NAPI_GRO_CB(skb)->is_fou = 1; 249 249 250 - rcu_read_lock(); 251 250 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; 252 251 ops = rcu_dereference(offloads[proto]); 253 252 if (!ops || !ops->callbacks.gro_receive) 254 - goto out_unlock; 253 + goto out; 255 254 256 255 pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); 257 256 258 - out_unlock: 259 - rcu_read_unlock(); 260 - 257 + out: 261 258 return pp; 262 259 } 263 260 ··· 436 439 /* Flag this frame as already having an outer encap header */ 437 440 NAPI_GRO_CB(skb)->is_fou = 1; 438 441 439 - rcu_read_lock(); 440 442 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; 441 443 ops = rcu_dereference(offloads[proto]); 442 444 if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) 443 - goto out_unlock; 445 + goto out; 444 446 445 447 pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); 446 448 flush = 0; 447 449 448 - out_unlock: 449 - rcu_read_unlock(); 450 450 out: 451 451 skb_gro_flush_final_remcsum(skb, pp, flush, &grc); 452 452
+3 -6
net/ipv4/gre_offload.c
··· 163 163 164 164 type = greh->protocol; 165 165 166 - rcu_read_lock(); 167 166 ptype = gro_find_receive_by_type(type); 168 167 if (!ptype) 169 - goto out_unlock; 168 + goto out; 170 169 171 170 grehlen = GRE_HEADER_SECTION; 172 171 ··· 179 180 if (skb_gro_header_hard(skb, hlen)) { 180 181 greh = skb_gro_header_slow(skb, hlen, off); 181 182 if (unlikely(!greh)) 182 - goto out_unlock; 183 + goto out; 183 184 } 184 185 185 186 /* Don't bother verifying checksum if we're going to flush anyway. */ 186 187 if ((greh->flags & GRE_CSUM) && !NAPI_GRO_CB(skb)->flush) { 187 188 if (skb_gro_checksum_simple_validate(skb)) 188 - goto out_unlock; 189 + goto out; 189 190 190 191 skb_gro_checksum_try_convert(skb, IPPROTO_GRE, 191 192 null_compute_pseudo); ··· 229 230 pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); 230 231 flush = 0; 231 232 232 - out_unlock: 233 - rcu_read_unlock(); 234 233 out: 235 234 skb_gro_flush_final(skb, pp, flush); 236 235
-2
net/ipv4/udp_offload.c
··· 628 628 inet_gro_compute_pseudo); 629 629 skip: 630 630 NAPI_GRO_CB(skb)->is_ipv6 = 0; 631 - rcu_read_lock(); 632 631 633 632 if (static_branch_unlikely(&udp_encap_needed_key)) 634 633 sk = udp4_gro_lookup_skb(skb, uh->source, uh->dest); 635 634 636 635 pp = udp_gro_receive(head, skb, uh, sk); 637 - rcu_read_unlock(); 638 636 return pp; 639 637 640 638 flush:
+1 -5
net/ipv6/ip6_offload.c
··· 208 208 209 209 flush += ntohs(iph->payload_len) != skb_gro_len(skb); 210 210 211 - rcu_read_lock(); 212 211 proto = iph->nexthdr; 213 212 ops = rcu_dereference(inet6_offloads[proto]); 214 213 if (!ops || !ops->callbacks.gro_receive) { ··· 220 221 221 222 ops = rcu_dereference(inet6_offloads[proto]); 222 223 if (!ops || !ops->callbacks.gro_receive) 223 - goto out_unlock; 224 + goto out; 224 225 225 226 iph = ipv6_hdr(skb); 226 227 } ··· 277 278 278 279 pp = indirect_call_gro_receive_l4(tcp6_gro_receive, udp6_gro_receive, 279 280 ops->callbacks.gro_receive, head, skb); 280 - 281 - out_unlock: 282 - rcu_read_unlock(); 283 281 284 282 out: 285 283 skb_gro_flush_final(skb, pp, flush);
-2
net/ipv6/udp_offload.c
··· 145 145 146 146 skip: 147 147 NAPI_GRO_CB(skb)->is_ipv6 = 1; 148 - rcu_read_lock(); 149 148 150 149 if (static_branch_unlikely(&udpv6_encap_needed_key)) 151 150 sk = udp6_gro_lookup_skb(skb, uh->source, uh->dest); 152 151 153 152 pp = udp_gro_receive(head, skb, uh, sk); 154 - rcu_read_unlock(); 155 153 return pp; 156 154 157 155 flush: