diff options
Diffstat (limited to 'net/xdp/xsk.c')
| -rw-r--r-- | net/xdp/xsk.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index a03268454a27..85e4fe4f18cc 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c | |||
| @@ -366,7 +366,6 @@ static int xsk_release(struct socket *sock) | |||
| 366 | 366 | ||
| 367 | xskq_destroy(xs->rx); | 367 | xskq_destroy(xs->rx); |
| 368 | xskq_destroy(xs->tx); | 368 | xskq_destroy(xs->tx); |
| 369 | xdp_put_umem(xs->umem); | ||
| 370 | 369 | ||
| 371 | sock_orphan(sk); | 370 | sock_orphan(sk); |
| 372 | sock->sk = NULL; | 371 | sock->sk = NULL; |
| @@ -669,6 +668,8 @@ static int xsk_mmap(struct file *file, struct socket *sock, | |||
| 669 | if (!umem) | 668 | if (!umem) |
| 670 | return -EINVAL; | 669 | return -EINVAL; |
| 671 | 670 | ||
| 671 | /* Matches the smp_wmb() in XDP_UMEM_REG */ | ||
| 672 | smp_rmb(); | ||
| 672 | if (offset == XDP_UMEM_PGOFF_FILL_RING) | 673 | if (offset == XDP_UMEM_PGOFF_FILL_RING) |
| 673 | q = READ_ONCE(umem->fq); | 674 | q = READ_ONCE(umem->fq); |
| 674 | else if (offset == XDP_UMEM_PGOFF_COMPLETION_RING) | 675 | else if (offset == XDP_UMEM_PGOFF_COMPLETION_RING) |
| @@ -678,6 +679,8 @@ static int xsk_mmap(struct file *file, struct socket *sock, | |||
| 678 | if (!q) | 679 | if (!q) |
| 679 | return -EINVAL; | 680 | return -EINVAL; |
| 680 | 681 | ||
| 682 | /* Matches the smp_wmb() in xsk_init_queue */ | ||
| 683 | smp_rmb(); | ||
| 681 | qpg = virt_to_head_page(q->ring); | 684 | qpg = virt_to_head_page(q->ring); |
| 682 | if (size > (PAGE_SIZE << compound_order(qpg))) | 685 | if (size > (PAGE_SIZE << compound_order(qpg))) |
| 683 | return -EINVAL; | 686 | return -EINVAL; |
| @@ -714,6 +717,18 @@ static const struct proto_ops xsk_proto_ops = { | |||
| 714 | .sendpage = sock_no_sendpage, | 717 | .sendpage = sock_no_sendpage, |
| 715 | }; | 718 | }; |
| 716 | 719 | ||
| 720 | static void xsk_destruct(struct sock *sk) | ||
| 721 | { | ||
| 722 | struct xdp_sock *xs = xdp_sk(sk); | ||
| 723 | |||
| 724 | if (!sock_flag(sk, SOCK_DEAD)) | ||
| 725 | return; | ||
| 726 | |||
| 727 | xdp_put_umem(xs->umem); | ||
| 728 | |||
| 729 | sk_refcnt_debug_dec(sk); | ||
| 730 | } | ||
| 731 | |||
| 717 | static int xsk_create(struct net *net, struct socket *sock, int protocol, | 732 | static int xsk_create(struct net *net, struct socket *sock, int protocol, |
| 718 | int kern) | 733 | int kern) |
| 719 | { | 734 | { |
| @@ -740,6 +755,9 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol, | |||
| 740 | 755 | ||
| 741 | sk->sk_family = PF_XDP; | 756 | sk->sk_family = PF_XDP; |
| 742 | 757 | ||
| 758 | sk->sk_destruct = xsk_destruct; | ||
| 759 | sk_refcnt_debug_inc(sk); | ||
| 760 | |||
| 743 | sock_set_flag(sk, SOCK_RCU_FREE); | 761 | sock_set_flag(sk, SOCK_RCU_FREE); |
| 744 | 762 | ||
| 745 | xs = xdp_sk(sk); | 763 | xs = xdp_sk(sk); |
