summaryrefslogtreecommitdiffstats
path: root/kernel/bpf/sockmap.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-09-05 00:33:03 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-05 00:33:03 -0400
commit36302685f59345959de96d0d70a5ad20a3a3451b (patch)
tree778b3170acd1131840823520a4664f2bba343dbe /kernel/bpf/sockmap.c
parent2fc4aa59ab470f1d5124b33c05680e2b2f2c6f65 (diff)
parent28619527b8a712590c93d0a9e24b4425b9376a8c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'kernel/bpf/sockmap.c')
-rw-r--r--kernel/bpf/sockmap.c64
1 files changed, 36 insertions, 28 deletions
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index cf5195c7c331..488ef9663c01 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -236,7 +236,7 @@ static int bpf_tcp_init(struct sock *sk)
236} 236}
237 237
238static void smap_release_sock(struct smap_psock *psock, struct sock *sock); 238static void smap_release_sock(struct smap_psock *psock, struct sock *sock);
239static int free_start_sg(struct sock *sk, struct sk_msg_buff *md); 239static int free_start_sg(struct sock *sk, struct sk_msg_buff *md, bool charge);
240 240
241static void bpf_tcp_release(struct sock *sk) 241static void bpf_tcp_release(struct sock *sk)
242{ 242{
@@ -248,7 +248,7 @@ static void bpf_tcp_release(struct sock *sk)
248 goto out; 248 goto out;
249 249
250 if (psock->cork) { 250 if (psock->cork) {
251 free_start_sg(psock->sock, psock->cork); 251 free_start_sg(psock->sock, psock->cork, true);
252 kfree(psock->cork); 252 kfree(psock->cork);
253 psock->cork = NULL; 253 psock->cork = NULL;
254 } 254 }
@@ -330,14 +330,14 @@ static void bpf_tcp_close(struct sock *sk, long timeout)
330 close_fun = psock->save_close; 330 close_fun = psock->save_close;
331 331
332 if (psock->cork) { 332 if (psock->cork) {
333 free_start_sg(psock->sock, psock->cork); 333 free_start_sg(psock->sock, psock->cork, true);
334 kfree(psock->cork); 334 kfree(psock->cork);
335 psock->cork = NULL; 335 psock->cork = NULL;
336 } 336 }
337 337
338 list_for_each_entry_safe(md, mtmp, &psock->ingress, list) { 338 list_for_each_entry_safe(md, mtmp, &psock->ingress, list) {
339 list_del(&md->list); 339 list_del(&md->list);
340 free_start_sg(psock->sock, md); 340 free_start_sg(psock->sock, md, true);
341 kfree(md); 341 kfree(md);
342 } 342 }
343 343
@@ -369,7 +369,7 @@ static void bpf_tcp_close(struct sock *sk, long timeout)
369 /* If another thread deleted this object skip deletion. 369 /* If another thread deleted this object skip deletion.
370 * The refcnt on psock may or may not be zero. 370 * The refcnt on psock may or may not be zero.
371 */ 371 */
372 if (l) { 372 if (l && l == link) {
373 hlist_del_rcu(&link->hash_node); 373 hlist_del_rcu(&link->hash_node);
374 smap_release_sock(psock, link->sk); 374 smap_release_sock(psock, link->sk);
375 free_htab_elem(htab, link); 375 free_htab_elem(htab, link);
@@ -570,14 +570,16 @@ static void free_bytes_sg(struct sock *sk, int bytes,
570 md->sg_start = i; 570 md->sg_start = i;
571} 571}
572 572
573static int free_sg(struct sock *sk, int start, struct sk_msg_buff *md) 573static int free_sg(struct sock *sk, int start,
574 struct sk_msg_buff *md, bool charge)
574{ 575{
575 struct scatterlist *sg = md->sg_data; 576 struct scatterlist *sg = md->sg_data;
576 int i = start, free = 0; 577 int i = start, free = 0;
577 578
578 while (sg[i].length) { 579 while (sg[i].length) {
579 free += sg[i].length; 580 free += sg[i].length;
580 sk_mem_uncharge(sk, sg[i].length); 581 if (charge)
582 sk_mem_uncharge(sk, sg[i].length);
581 if (!md->skb) 583 if (!md->skb)
582 put_page(sg_page(&sg[i])); 584 put_page(sg_page(&sg[i]));
583 sg[i].length = 0; 585 sg[i].length = 0;
@@ -594,9 +596,9 @@ static int free_sg(struct sock *sk, int start, struct sk_msg_buff *md)
594 return free; 596 return free;
595} 597}
596 598
597static int free_start_sg(struct sock *sk, struct sk_msg_buff *md) 599static int free_start_sg(struct sock *sk, struct sk_msg_buff *md, bool charge)
598{ 600{
599 int free = free_sg(sk, md->sg_start, md); 601 int free = free_sg(sk, md->sg_start, md, charge);
600 602
601 md->sg_start = md->sg_end; 603 md->sg_start = md->sg_end;
602 return free; 604 return free;
@@ -604,7 +606,7 @@ static int free_start_sg(struct sock *sk, struct sk_msg_buff *md)
604 606
605static int free_curr_sg(struct sock *sk, struct sk_msg_buff *md) 607static int free_curr_sg(struct sock *sk, struct sk_msg_buff *md)
606{ 608{
607 return free_sg(sk, md->sg_curr, md); 609 return free_sg(sk, md->sg_curr, md, true);
608} 610}
609 611
610static int bpf_map_msg_verdict(int _rc, struct sk_msg_buff *md) 612static int bpf_map_msg_verdict(int _rc, struct sk_msg_buff *md)
@@ -718,7 +720,7 @@ static int bpf_tcp_ingress(struct sock *sk, int apply_bytes,
718 list_add_tail(&r->list, &psock->ingress); 720 list_add_tail(&r->list, &psock->ingress);
719 sk->sk_data_ready(sk); 721 sk->sk_data_ready(sk);
720 } else { 722 } else {
721 free_start_sg(sk, r); 723 free_start_sg(sk, r, true);
722 kfree(r); 724 kfree(r);
723 } 725 }
724 726
@@ -752,14 +754,10 @@ static int bpf_tcp_sendmsg_do_redirect(struct sock *sk, int send,
752 release_sock(sk); 754 release_sock(sk);
753 } 755 }
754 smap_release_sock(psock, sk); 756 smap_release_sock(psock, sk);
755 if (unlikely(err)) 757 return err;
756 goto out;
757 return 0;
758out_rcu: 758out_rcu:
759 rcu_read_unlock(); 759 rcu_read_unlock();
760out: 760 return 0;
761 free_bytes_sg(NULL, send, md, false);
762 return err;
763} 761}
764 762
765static inline void bpf_md_init(struct smap_psock *psock) 763static inline void bpf_md_init(struct smap_psock *psock)
@@ -822,7 +820,7 @@ more_data:
822 case __SK_PASS: 820 case __SK_PASS:
823 err = bpf_tcp_push(sk, send, m, flags, true); 821 err = bpf_tcp_push(sk, send, m, flags, true);
824 if (unlikely(err)) { 822 if (unlikely(err)) {
825 *copied -= free_start_sg(sk, m); 823 *copied -= free_start_sg(sk, m, true);
826 break; 824 break;
827 } 825 }
828 826
@@ -845,16 +843,17 @@ more_data:
845 lock_sock(sk); 843 lock_sock(sk);
846 844
847 if (unlikely(err < 0)) { 845 if (unlikely(err < 0)) {
848 free_start_sg(sk, m); 846 int free = free_start_sg(sk, m, false);
847
849 psock->sg_size = 0; 848 psock->sg_size = 0;
850 if (!cork) 849 if (!cork)
851 *copied -= send; 850 *copied -= free;
852 } else { 851 } else {
853 psock->sg_size -= send; 852 psock->sg_size -= send;
854 } 853 }
855 854
856 if (cork) { 855 if (cork) {
857 free_start_sg(sk, m); 856 free_start_sg(sk, m, true);
858 psock->sg_size = 0; 857 psock->sg_size = 0;
859 kfree(m); 858 kfree(m);
860 m = NULL; 859 m = NULL;
@@ -912,6 +911,8 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
912 911
913 if (unlikely(flags & MSG_ERRQUEUE)) 912 if (unlikely(flags & MSG_ERRQUEUE))
914 return inet_recv_error(sk, msg, len, addr_len); 913 return inet_recv_error(sk, msg, len, addr_len);
914 if (!skb_queue_empty(&sk->sk_receive_queue))
915 return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
915 916
916 rcu_read_lock(); 917 rcu_read_lock();
917 psock = smap_psock_sk(sk); 918 psock = smap_psock_sk(sk);
@@ -922,9 +923,6 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
922 goto out; 923 goto out;
923 rcu_read_unlock(); 924 rcu_read_unlock();
924 925
925 if (!skb_queue_empty(&sk->sk_receive_queue))
926 return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
927
928 lock_sock(sk); 926 lock_sock(sk);
929bytes_ready: 927bytes_ready:
930 while (copied != len) { 928 while (copied != len) {
@@ -1122,7 +1120,7 @@ wait_for_memory:
1122 err = sk_stream_wait_memory(sk, &timeo); 1120 err = sk_stream_wait_memory(sk, &timeo);
1123 if (err) { 1121 if (err) {
1124 if (m && m != psock->cork) 1122 if (m && m != psock->cork)
1125 free_start_sg(sk, m); 1123 free_start_sg(sk, m, true);
1126 goto out_err; 1124 goto out_err;
1127 } 1125 }
1128 } 1126 }
@@ -1464,10 +1462,16 @@ static void smap_destroy_psock(struct rcu_head *rcu)
1464 schedule_work(&psock->gc_work); 1462 schedule_work(&psock->gc_work);
1465} 1463}
1466 1464
1465static bool psock_is_smap_sk(struct sock *sk)
1466{
1467 return inet_csk(sk)->icsk_ulp_ops == &bpf_tcp_ulp_ops;
1468}
1469
1467static void smap_release_sock(struct smap_psock *psock, struct sock *sock) 1470static void smap_release_sock(struct smap_psock *psock, struct sock *sock)
1468{ 1471{
1469 if (refcount_dec_and_test(&psock->refcnt)) { 1472 if (refcount_dec_and_test(&psock->refcnt)) {
1470 tcp_cleanup_ulp(sock); 1473 if (psock_is_smap_sk(sock))
1474 tcp_cleanup_ulp(sock);
1471 write_lock_bh(&sock->sk_callback_lock); 1475 write_lock_bh(&sock->sk_callback_lock);
1472 smap_stop_sock(psock, sock); 1476 smap_stop_sock(psock, sock);
1473 write_unlock_bh(&sock->sk_callback_lock); 1477 write_unlock_bh(&sock->sk_callback_lock);
@@ -1581,13 +1585,13 @@ static void smap_gc_work(struct work_struct *w)
1581 bpf_prog_put(psock->bpf_tx_msg); 1585 bpf_prog_put(psock->bpf_tx_msg);
1582 1586
1583 if (psock->cork) { 1587 if (psock->cork) {
1584 free_start_sg(psock->sock, psock->cork); 1588 free_start_sg(psock->sock, psock->cork, true);
1585 kfree(psock->cork); 1589 kfree(psock->cork);
1586 } 1590 }
1587 1591
1588 list_for_each_entry_safe(md, mtmp, &psock->ingress, list) { 1592 list_for_each_entry_safe(md, mtmp, &psock->ingress, list) {
1589 list_del(&md->list); 1593 list_del(&md->list);
1590 free_start_sg(psock->sock, md); 1594 free_start_sg(psock->sock, md, true);
1591 kfree(md); 1595 kfree(md);
1592 } 1596 }
1593 1597
@@ -1894,6 +1898,10 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map,
1894 * doesn't update user data. 1898 * doesn't update user data.
1895 */ 1899 */
1896 if (psock) { 1900 if (psock) {
1901 if (!psock_is_smap_sk(sock)) {
1902 err = -EBUSY;
1903 goto out_progs;
1904 }
1897 if (READ_ONCE(psock->bpf_parse) && parse) { 1905 if (READ_ONCE(psock->bpf_parse) && parse) {
1898 err = -EBUSY; 1906 err = -EBUSY;
1899 goto out_progs; 1907 goto out_progs;