[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20151211030028.GB6367@stefanha-x1.localdomain>
Date: Fri, 11 Dec 2015 11:00:28 +0800
From: Stefan Hajnoczi <stefanha@...hat.com>
To: Alex Bennée <alex.bennee@...aro.org>
Cc: kvm@...r.kernel.org, "Michael S. Tsirkin" <mst@...hat.com>,
netdev@...r.kernel.org, virtualization@...ts.linux-foundation.org,
Matt Benjamin <mbenjamin@...hat.com>,
Asias He <asias@...hat.com>,
Christoffer Dall <christoffer.dall@...aro.org>,
matt.ma@...aro.org
Subject: Re: [PATCH v3 2/4] VSOCK: Introduce virtio-vsock.ko
On Thu, Dec 10, 2015 at 09:23:25PM +0000, Alex Bennée wrote:
> Stefan Hajnoczi <stefanha@...hat.com> writes:
>
> > From: Asias He <asias@...hat.com>
> >
> > VM sockets virtio transport implementation. This module runs in guest
> > kernel.
>
> checkpatch warns on a bunch of whitespace/tab issues.
Will fix in the next version.
> > +struct virtio_vsock {
> > + /* Virtio device */
> > + struct virtio_device *vdev;
> > + /* Virtio virtqueue */
> > + struct virtqueue *vqs[VSOCK_VQ_MAX];
> > + /* Wait queue for send pkt */
> > + wait_queue_head_t queue_wait;
> > + /* Work item to send pkt */
> > + struct work_struct tx_work;
> > + /* Work item to recv pkt */
> > + struct work_struct rx_work;
> > + /* Mutex to protect send pkt*/
> > + struct mutex tx_lock;
> > + /* Mutex to protect recv pkt*/
> > + struct mutex rx_lock;
>
> Further down I got confused by what lock was what and exactly what was
> being protected. If the receive and transmit paths touch separate things
> it might be worth re-arranging the structure to make it clearer, eg:
>
> /* The transmit path is protected by tx_lock */
> struct mutex tx_lock;
> struct work_struct tx_work;
> ..
> ..
>
> /* The receive path is protected by rx_lock */
> wait_queue_head_t queue_wait;
> ..
> ..
>
> Which might make things a little clearer. Then all the redundant
> information in the comments can be removed. I don't need to know what
> is a Virtio device, virtqueue or wait_queue etc as they are implicit in
> the structure name.
Thanks, that is a nice idea.
> > + mutex_lock(&vsock->tx_lock);
> > + while ((ret = virtqueue_add_sgs(vq, sgs, out_sg, in_sg, pkt,
> > + GFP_KERNEL)) < 0) {
> > + prepare_to_wait_exclusive(&vsock->queue_wait, &wait,
> > + TASK_UNINTERRUPTIBLE);
> > + mutex_unlock(&vsock->tx_lock);
> > + schedule();
> > + mutex_lock(&vsock->tx_lock);
> > + finish_wait(&vsock->queue_wait, &wait);
> > + }
> > + virtqueue_kick(vq);
> > + mutex_unlock(&vsock->tx_lock);
>
> What are we protecting with tx_lock here? See comments above about
> making the lock usage semantics clearer.
vq (vsock->vqs[VSOCK_VQ_TX]) is being protected. Concurrent calls to
virtqueue_add_sgs() are not allowed.
> > +
> > + return pkt_len;
> > +}
> > +
> > +static struct virtio_transport_pkt_ops virtio_ops = {
> > + .send_pkt = virtio_transport_send_pkt,
> > +};
> > +
> > +static void virtio_vsock_rx_fill(struct virtio_vsock *vsock)
> > +{
> > + int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE;
> > + struct virtio_vsock_pkt *pkt;
> > + struct scatterlist hdr, buf, *sgs[2];
> > + struct virtqueue *vq;
> > + int ret;
> > +
> > + vq = vsock->vqs[VSOCK_VQ_RX];
> > +
> > + do {
> > + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
> > + if (!pkt) {
> > + pr_debug("%s: fail to allocate pkt\n", __func__);
> > + goto out;
> > + }
> > +
> > + /* TODO: use mergeable rx buffer */
>
> TODO's should end up in merged code.
Will fix in next revision.
> > + pkt->buf = kmalloc(buf_len, GFP_KERNEL);
> > + if (!pkt->buf) {
> > + pr_debug("%s: fail to allocate pkt->buf\n", __func__);
> > + goto err;
> > + }
> > +
> > + sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr));
> > + sgs[0] = &hdr;
> > +
> > + sg_init_one(&buf, pkt->buf, buf_len);
> > + sgs[1] = &buf;
> > + ret = virtqueue_add_sgs(vq, sgs, 0, 2, pkt, GFP_KERNEL);
> > + if (ret)
> > + goto err;
> > + vsock->rx_buf_nr++;
> > + } while (vq->num_free);
> > + if (vsock->rx_buf_nr > vsock->rx_buf_max_nr)
> > + vsock->rx_buf_max_nr = vsock->rx_buf_nr;
> > +out:
> > + virtqueue_kick(vq);
> > + return;
> > +err:
> > + virtqueue_kick(vq);
> > + virtio_transport_free_pkt(pkt);
>
> You could free the pkt memory at the fail site and just have one exit path.
Okay, I agree the err label is of marginal use. Let's get rid of it.
>
> > + return;
> > +}
> > +
> > +static void virtio_transport_send_pkt_work(struct work_struct *work)
> > +{
> > + struct virtio_vsock *vsock =
> > + container_of(work, struct virtio_vsock, tx_work);
> > + struct virtio_vsock_pkt *pkt;
> > + bool added = false;
> > + struct virtqueue *vq;
> > + unsigned int len;
> > + struct sock *sk;
> > +
> > + vq = vsock->vqs[VSOCK_VQ_TX];
> > + mutex_lock(&vsock->tx_lock);
> > + do {
>
> You can move the declarations of pkt/len into the do block.
Okay.
>
> > + virtqueue_disable_cb(vq);
> > + while ((pkt = virtqueue_get_buf(vq, &len)) != NULL) {
>
> And the sk declaration here
Okay.
> > +static void virtio_transport_recv_pkt_work(struct work_struct *work)
> > +{
> > + struct virtio_vsock *vsock =
> > + container_of(work, struct virtio_vsock, rx_work);
> > + struct virtio_vsock_pkt *pkt;
> > + struct virtqueue *vq;
> > + unsigned int len;
>
> Same as above for pkt, len.
Okay.
> > + vsock = kzalloc(sizeof(*vsock), GFP_KERNEL);
> > + if (!vsock) {
> > + ret = -ENOMEM;
> > + goto out;
>
> Won't this attempt to kfree a NULL vsock?
kfree(NULL) is a nop so this is safe.
Download attachment "signature.asc" of type "application/pgp-signature" (474 bytes)
Powered by blists - more mailing lists