tun/tap: use ptr_ring instead of skb_array
authorJason Wang <jasowang@redhat.com>
Thu, 4 Jan 2018 03:14:27 +0000 (11:14 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Jan 2018 15:56:10 +0000 (10:56 -0500)
This patch switches to use ptr_ring instead of skb_array. This will be
used to enqueue different types of pointers by encoding type into
lower bits.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/tap.c
drivers/net/tun.c
drivers/vhost/net.c
include/linux/if_tap.h
include/linux/if_tun.h

index 0a886fd..7c38659 100644 (file)
@@ -330,7 +330,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
        if (!q)
                return RX_HANDLER_PASS;
 
-       if (__skb_array_full(&q->skb_array))
+       if (__ptr_ring_full(&q->ring))
                goto drop;
 
        skb_push(skb, ETH_HLEN);
@@ -348,7 +348,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
                        goto drop;
 
                if (!segs) {
-                       if (skb_array_produce(&q->skb_array, skb))
+                       if (ptr_ring_produce(&q->ring, skb))
                                goto drop;
                        goto wake_up;
                }
@@ -358,7 +358,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
                        struct sk_buff *nskb = segs->next;
 
                        segs->next = NULL;
-                       if (skb_array_produce(&q->skb_array, segs)) {
+                       if (ptr_ring_produce(&q->ring, segs)) {
                                kfree_skb(segs);
                                kfree_skb_list(nskb);
                                break;
@@ -375,7 +375,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
                    !(features & NETIF_F_CSUM_MASK) &&
                    skb_checksum_help(skb))
                        goto drop;
-               if (skb_array_produce(&q->skb_array, skb))
+               if (ptr_ring_produce(&q->ring, skb))
                        goto drop;
        }
 
@@ -497,7 +497,7 @@ static void tap_sock_destruct(struct sock *sk)
 {
        struct tap_queue *q = container_of(sk, struct tap_queue, sk);
 
-       skb_array_cleanup(&q->skb_array);
+       ptr_ring_cleanup(&q->ring, __skb_array_destroy_skb);
 }
 
 static int tap_open(struct inode *inode, struct file *file)
@@ -517,7 +517,7 @@ static int tap_open(struct inode *inode, struct file *file)
                                             &tap_proto, 0);
        if (!q)
                goto err;
-       if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL)) {
+       if (ptr_ring_init(&q->ring, tap->dev->tx_queue_len, GFP_KERNEL)) {
                sk_free(&q->sk);
                goto err;
        }
@@ -546,7 +546,7 @@ static int tap_open(struct inode *inode, struct file *file)
 
        err = tap_set_queue(tap, file, q);
        if (err) {
-               /* tap_sock_destruct() will take care of freeing skb_array */
+               /* tap_sock_destruct() will take care of freeing ptr_ring */
                goto err_put;
        }
 
@@ -583,7 +583,7 @@ static unsigned int tap_poll(struct file *file, poll_table *wait)
        mask = 0;
        poll_wait(file, &q->wq.wait, wait);
 
-       if (!skb_array_empty(&q->skb_array))
+       if (!ptr_ring_empty(&q->ring))
                mask |= POLLIN | POLLRDNORM;
 
        if (sock_writeable(&q->sk) ||
@@ -844,7 +844,7 @@ static ssize_t tap_do_read(struct tap_queue *q,
                                        TASK_INTERRUPTIBLE);
 
                /* Read frames from the queue */
-               skb = skb_array_consume(&q->skb_array);
+               skb = ptr_ring_consume(&q->ring);
                if (skb)
                        break;
                if (noblock) {
@@ -1176,7 +1176,7 @@ static int tap_peek_len(struct socket *sock)
 {
        struct tap_queue *q = container_of(sock, struct tap_queue,
                                               sock);
-       return skb_array_peek_len(&q->skb_array);
+       return PTR_RING_PEEK_CALL(&q->ring, __skb_array_len_with_tag);
 }
 
 /* Ops structure to mimic raw sockets with tun */
@@ -1202,7 +1202,7 @@ struct socket *tap_get_socket(struct file *file)
 }
 EXPORT_SYMBOL_GPL(tap_get_socket);
 
-struct skb_array *tap_get_skb_array(struct file *file)
+struct ptr_ring *tap_get_ptr_ring(struct file *file)
 {
        struct tap_queue *q;
 
@@ -1211,29 +1211,30 @@ struct skb_array *tap_get_skb_array(struct file *file)
        q = file->private_data;
        if (!q)
                return ERR_PTR(-EBADFD);
-       return &q->skb_array;
+       return &q->ring;
 }
-EXPORT_SYMBOL_GPL(tap_get_skb_array);
+EXPORT_SYMBOL_GPL(tap_get_ptr_ring);
 
 int tap_queue_resize(struct tap_dev *tap)
 {
        struct net_device *dev = tap->dev;
        struct tap_queue *q;
-       struct skb_array **arrays;
+       struct ptr_ring **rings;
        int n = tap->numqueues;
        int ret, i = 0;
 
-       arrays = kmalloc_array(n, sizeof(*arrays), GFP_KERNEL);
-       if (!arrays)
+       rings = kmalloc_array(n, sizeof(*rings), GFP_KERNEL);
+       if (!rings)
                return -ENOMEM;
 
        list_for_each_entry(q, &tap->queue_list, next)
-               arrays[i++] = &q->skb_array;
+               rings[i++] = &q->ring;
 
-       ret = skb_array_resize_multiple(arrays, n,
-                                       dev->tx_queue_len, GFP_KERNEL);
+       ret = ptr_ring_resize_multiple(rings, n,
+                                      dev->tx_queue_len, GFP_KERNEL,
+                                      __skb_array_destroy_skb);
 
-       kfree(arrays);
+       kfree(rings);
        return ret;
 }
 EXPORT_SYMBOL_GPL(tap_queue_resize);
index e7c5f4b..b8e39c6 100644 (file)
@@ -179,7 +179,7 @@ struct tun_file {
        struct mutex napi_mutex;        /* Protects access to the above napi */
        struct list_head next;
        struct tun_struct *detached;
-       struct skb_array tx_array;
+       struct ptr_ring tx_ring;
        struct xdp_rxq_info xdp_rxq;
 };
 
@@ -635,7 +635,7 @@ static void tun_queue_purge(struct tun_file *tfile)
 {
        struct sk_buff *skb;
 
-       while ((skb = skb_array_consume(&tfile->tx_array)) != NULL)
+       while ((skb = ptr_ring_consume(&tfile->tx_ring)) != NULL)
                kfree_skb(skb);
 
        skb_queue_purge(&tfile->sk.sk_write_queue);
@@ -689,7 +689,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                                unregister_netdevice(tun->dev);
                }
                if (tun) {
-                       skb_array_cleanup(&tfile->tx_array);
+                       ptr_ring_cleanup(&tfile->tx_ring,
+                                        __skb_array_destroy_skb);
                        xdp_rxq_info_unreg(&tfile->xdp_rxq);
                }
                sock_put(&tfile->sk);
@@ -782,7 +783,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
        }
 
        if (!tfile->detached &&
-           skb_array_init(&tfile->tx_array, dev->tx_queue_len, GFP_KERNEL)) {
+           ptr_ring_init(&tfile->tx_ring, dev->tx_queue_len, GFP_KERNEL)) {
                err = -ENOMEM;
                goto out;
        }
@@ -1048,7 +1049,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 
        nf_reset(skb);
 
-       if (skb_array_produce(&tfile->tx_array, skb))
+       if (ptr_ring_produce(&tfile->tx_ring, skb))
                goto drop;
 
        /* Notify and wake up reader process */
@@ -1316,7 +1317,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, sk_sleep(sk), wait);
 
-       if (!skb_array_empty(&tfile->tx_array))
+       if (!ptr_ring_empty(&tfile->tx_ring))
                mask |= POLLIN | POLLRDNORM;
 
        if (tun->dev->flags & IFF_UP &&
@@ -1966,7 +1967,7 @@ static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
        struct sk_buff *skb = NULL;
        int error = 0;
 
-       skb = skb_array_consume(&tfile->tx_array);
+       skb = ptr_ring_consume(&tfile->tx_ring);
        if (skb)
                goto out;
        if (noblock) {
@@ -1978,7 +1979,7 @@ static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
        current->state = TASK_INTERRUPTIBLE;
 
        while (1) {
-               skb = skb_array_consume(&tfile->tx_array);
+               skb = ptr_ring_consume(&tfile->tx_ring);
                if (skb)
                        break;
                if (signal_pending(current)) {
@@ -2208,7 +2209,7 @@ static int tun_peek_len(struct socket *sock)
        if (!tun)
                return 0;
 
-       ret = skb_array_peek_len(&tfile->tx_array);
+       ret = PTR_RING_PEEK_CALL(&tfile->tx_ring, __skb_array_len_with_tag);
        tun_put(tun);
 
        return ret;
@@ -3114,25 +3115,26 @@ static int tun_queue_resize(struct tun_struct *tun)
 {
        struct net_device *dev = tun->dev;
        struct tun_file *tfile;
-       struct skb_array **arrays;
+       struct ptr_ring **rings;
        int n = tun->numqueues + tun->numdisabled;
        int ret, i;
 
-       arrays = kmalloc_array(n, sizeof(*arrays), GFP_KERNEL);
-       if (!arrays)
+       rings = kmalloc_array(n, sizeof(*rings), GFP_KERNEL);
+       if (!rings)
                return -ENOMEM;
 
        for (i = 0; i < tun->numqueues; i++) {
                tfile = rtnl_dereference(tun->tfiles[i]);
-               arrays[i] = &tfile->tx_array;
+               rings[i] = &tfile->tx_ring;
        }
        list_for_each_entry(tfile, &tun->disabled, next)
-               arrays[i++] = &tfile->tx_array;
+               rings[i++] = &tfile->tx_ring;
 
-       ret = skb_array_resize_multiple(arrays, n,
-                                       dev->tx_queue_len, GFP_KERNEL);
+       ret = ptr_ring_resize_multiple(rings, n,
+                                      dev->tx_queue_len, GFP_KERNEL,
+                                      __skb_array_destroy_skb);
 
-       kfree(arrays);
+       kfree(rings);
        return ret;
 }
 
@@ -3218,7 +3220,7 @@ struct socket *tun_get_socket(struct file *file)
 }
 EXPORT_SYMBOL_GPL(tun_get_socket);
 
-struct skb_array *tun_get_skb_array(struct file *file)
+struct ptr_ring *tun_get_tx_ring(struct file *file)
 {
        struct tun_file *tfile;
 
@@ -3227,9 +3229,9 @@ struct skb_array *tun_get_skb_array(struct file *file)
        tfile = file->private_data;
        if (!tfile)
                return ERR_PTR(-EBADFD);
-       return &tfile->tx_array;
+       return &tfile->tx_ring;
 }
-EXPORT_SYMBOL_GPL(tun_get_skb_array);
+EXPORT_SYMBOL_GPL(tun_get_tx_ring);
 
 module_init(tun_init);
 module_exit(tun_cleanup);
index c7bdeb6..c316555 100644 (file)
@@ -89,7 +89,7 @@ struct vhost_net_ubuf_ref {
 
 #define VHOST_RX_BATCH 64
 struct vhost_net_buf {
-       struct sk_buff **queue;
+       void **queue;
        int tail;
        int head;
 };
@@ -108,7 +108,7 @@ struct vhost_net_virtqueue {
        /* Reference counting for outstanding ubufs.
         * Protected by vq mutex. Writers must also take device mutex. */
        struct vhost_net_ubuf_ref *ubufs;
-       struct skb_array *rx_array;
+       struct ptr_ring *rx_ring;
        struct vhost_net_buf rxq;
 };
 
@@ -158,7 +158,7 @@ static int vhost_net_buf_produce(struct vhost_net_virtqueue *nvq)
        struct vhost_net_buf *rxq = &nvq->rxq;
 
        rxq->head = 0;
-       rxq->tail = skb_array_consume_batched(nvq->rx_array, rxq->queue,
+       rxq->tail = ptr_ring_consume_batched(nvq->rx_ring, rxq->queue,
                                              VHOST_RX_BATCH);
        return rxq->tail;
 }
@@ -167,9 +167,10 @@ static void vhost_net_buf_unproduce(struct vhost_net_virtqueue *nvq)
 {
        struct vhost_net_buf *rxq = &nvq->rxq;
 
-       if (nvq->rx_array && !vhost_net_buf_is_empty(rxq)) {
-               skb_array_unconsume(nvq->rx_array, rxq->queue + rxq->head,
-                                   vhost_net_buf_get_size(rxq));
+       if (nvq->rx_ring && !vhost_net_buf_is_empty(rxq)) {
+               ptr_ring_unconsume(nvq->rx_ring, rxq->queue + rxq->head,
+                                  vhost_net_buf_get_size(rxq),
+                                  __skb_array_destroy_skb);
                rxq->head = rxq->tail = 0;
        }
 }
@@ -583,7 +584,7 @@ static int peek_head_len(struct vhost_net_virtqueue *rvq, struct sock *sk)
        int len = 0;
        unsigned long flags;
 
-       if (rvq->rx_array)
+       if (rvq->rx_ring)
                return vhost_net_buf_peek(rvq);
 
        spin_lock_irqsave(&sk->sk_receive_queue.lock, flags);
@@ -790,7 +791,7 @@ static void handle_rx(struct vhost_net *net)
                         * they refilled. */
                        goto out;
                }
-               if (nvq->rx_array)
+               if (nvq->rx_ring)
                        msg.msg_control = vhost_net_buf_consume(&nvq->rxq);
                /* On overrun, truncate and discard */
                if (unlikely(headcount > UIO_MAXIOV)) {
@@ -896,7 +897,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
        struct vhost_net *n;
        struct vhost_dev *dev;
        struct vhost_virtqueue **vqs;
-       struct sk_buff **queue;
+       void **queue;
        int i;
 
        n = kvmalloc(sizeof *n, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
@@ -908,7 +909,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
                return -ENOMEM;
        }
 
-       queue = kmalloc_array(VHOST_RX_BATCH, sizeof(struct sk_buff *),
+       queue = kmalloc_array(VHOST_RX_BATCH, sizeof(void *),
                              GFP_KERNEL);
        if (!queue) {
                kfree(vqs);
@@ -1046,23 +1047,23 @@ err:
        return ERR_PTR(r);
 }
 
-static struct skb_array *get_tap_skb_array(int fd)
+static struct ptr_ring *get_tap_ptr_ring(int fd)
 {
-       struct skb_array *array;
+       struct ptr_ring *ring;
        struct file *file = fget(fd);
 
        if (!file)
                return NULL;
-       array = tun_get_skb_array(file);
-       if (!IS_ERR(array))
+       ring = tun_get_tx_ring(file);
+       if (!IS_ERR(ring))
                goto out;
-       array = tap_get_skb_array(file);
-       if (!IS_ERR(array))
+       ring = tap_get_ptr_ring(file);
+       if (!IS_ERR(ring))
                goto out;
-       array = NULL;
+       ring = NULL;
 out:
        fput(file);
-       return array;
+       return ring;
 }
 
 static struct socket *get_tap_socket(int fd)
@@ -1143,7 +1144,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
                vq->private_data = sock;
                vhost_net_buf_unproduce(nvq);
                if (index == VHOST_NET_VQ_RX)
-                       nvq->rx_array = get_tap_skb_array(fd);
+                       nvq->rx_ring = get_tap_ptr_ring(fd);
                r = vhost_vq_init_access(vq);
                if (r)
                        goto err_used;
index 3ecef57..8e66866 100644 (file)
@@ -4,7 +4,7 @@
 
 #if IS_ENABLED(CONFIG_TAP)
 struct socket *tap_get_socket(struct file *);
-struct skb_array *tap_get_skb_array(struct file *file);
+struct ptr_ring *tap_get_ptr_ring(struct file *file);
 #else
 #include <linux/err.h>
 #include <linux/errno.h>
@@ -14,7 +14,7 @@ static inline struct socket *tap_get_socket(struct file *f)
 {
        return ERR_PTR(-EINVAL);
 }
-static inline struct skb_array *tap_get_skb_array(struct file *f)
+static inline struct ptr_ring *tap_get_ptr_ring(struct file *f)
 {
        return ERR_PTR(-EINVAL);
 }
@@ -70,7 +70,7 @@ struct tap_queue {
        u16 queue_index;
        bool enabled;
        struct list_head next;
-       struct skb_array skb_array;
+       struct ptr_ring ring;
 };
 
 rx_handler_result_t tap_handle_frame(struct sk_buff **pskb);
index bf9bdf4..bdee9b8 100644 (file)
@@ -19,7 +19,7 @@
 
 #if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE)
 struct socket *tun_get_socket(struct file *);
-struct skb_array *tun_get_skb_array(struct file *file);
+struct ptr_ring *tun_get_tx_ring(struct file *file);
 #else
 #include <linux/err.h>
 #include <linux/errno.h>
@@ -29,7 +29,7 @@ static inline struct socket *tun_get_socket(struct file *f)
 {
        return ERR_PTR(-EINVAL);
 }
-static inline struct skb_array *tun_get_skb_array(struct file *f)
+static inline struct ptr_ring *tun_get_tx_ring(struct file *f)
 {
        return ERR_PTR(-EINVAL);
 }