Commit 58ada94f authored by Vivek Goyal's avatar Vivek Goyal Committed by Miklos Szeredi

virtiofs: Use a common function to send forget

Currently we are duplicating logic to send forgets at two
places. Consolidate the code by calling one helper function.

This also uses virtqueue_add_outbuf() instead of
virtqueue_add_sgs(). Former is simpler to call.
Signed-off-by: default avatarVivek Goyal <vgoyal@redhat.com>
Reviewed-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 00929447
...@@ -313,65 +313,85 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work) ...@@ -313,65 +313,85 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work)
} }
} }
static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) /*
* Returns 1 if queue is full and sender should wait a bit before sending
* next request, 0 otherwise.
*/
static int send_forget_request(struct virtio_fs_vq *fsvq,
struct virtio_fs_forget *forget,
bool in_flight)
{ {
struct virtio_fs_forget *forget;
struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
dispatch_work.work);
struct virtqueue *vq = fsvq->vq;
struct scatterlist sg; struct scatterlist sg;
struct scatterlist *sgs[] = {&sg}; struct virtqueue *vq;
int ret = 0;
bool notify; bool notify;
int ret;
pr_debug("virtio-fs: worker %s called.\n", __func__);
while (1) {
spin_lock(&fsvq->lock); spin_lock(&fsvq->lock);
forget = list_first_entry_or_null(&fsvq->queued_reqs,
struct virtio_fs_forget, list);
if (!forget) {
spin_unlock(&fsvq->lock);
return;
}
list_del(&forget->list);
if (!fsvq->connected) { if (!fsvq->connected) {
if (in_flight)
dec_in_flight_req(fsvq); dec_in_flight_req(fsvq);
spin_unlock(&fsvq->lock);
kfree(forget); kfree(forget);
continue; goto out;
} }
sg_init_one(&sg, forget, sizeof(*forget)); sg_init_one(&sg, forget, sizeof(*forget));
vq = fsvq->vq;
/* Enqueue the request */
dev_dbg(&vq->vdev->dev, "%s\n", __func__); dev_dbg(&vq->vdev->dev, "%s\n", __func__);
ret = virtqueue_add_sgs(vq, sgs, 1, 0, forget, GFP_ATOMIC);
ret = virtqueue_add_outbuf(vq, &sg, 1, forget, GFP_ATOMIC);
if (ret < 0) { if (ret < 0) {
if (ret == -ENOMEM || ret == -ENOSPC) { if (ret == -ENOMEM || ret == -ENOSPC) {
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later\n", pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later\n",
ret); ret);
list_add_tail(&forget->list, list_add_tail(&forget->list, &fsvq->queued_reqs);
&fsvq->queued_reqs);
schedule_delayed_work(&fsvq->dispatch_work, schedule_delayed_work(&fsvq->dispatch_work,
msecs_to_jiffies(1)); msecs_to_jiffies(1));
if (!in_flight)
inc_in_flight_req(fsvq);
/* Queue is full */
ret = 1;
} else { } else {
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
ret); ret);
dec_in_flight_req(fsvq);
kfree(forget); kfree(forget);
if (in_flight)
dec_in_flight_req(fsvq);
} }
spin_unlock(&fsvq->lock); goto out;
return;
} }
if (!in_flight)
inc_in_flight_req(fsvq);
notify = virtqueue_kick_prepare(vq); notify = virtqueue_kick_prepare(vq);
spin_unlock(&fsvq->lock); spin_unlock(&fsvq->lock);
if (notify) if (notify)
virtqueue_notify(vq); virtqueue_notify(vq);
pr_debug("virtio-fs: worker %s dispatched one forget request.\n", return ret;
__func__); out:
spin_unlock(&fsvq->lock);
return ret;
}
static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
{
struct virtio_fs_forget *forget;
struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
dispatch_work.work);
pr_debug("virtio-fs: worker %s called.\n", __func__);
while (1) {
spin_lock(&fsvq->lock);
forget = list_first_entry_or_null(&fsvq->queued_reqs,
struct virtio_fs_forget, list);
if (!forget) {
spin_unlock(&fsvq->lock);
return;
}
list_del(&forget->list);
spin_unlock(&fsvq->lock);
if (send_forget_request(fsvq, forget, true))
return;
} }
} }
...@@ -710,14 +730,9 @@ __releases(fiq->lock) ...@@ -710,14 +730,9 @@ __releases(fiq->lock)
{ {
struct fuse_forget_link *link; struct fuse_forget_link *link;
struct virtio_fs_forget *forget; struct virtio_fs_forget *forget;
struct scatterlist sg;
struct scatterlist *sgs[] = {&sg};
struct virtio_fs *fs; struct virtio_fs *fs;
struct virtqueue *vq;
struct virtio_fs_vq *fsvq; struct virtio_fs_vq *fsvq;
bool notify;
u64 unique; u64 unique;
int ret;
link = fuse_dequeue_forget(fiq, 1, NULL); link = fuse_dequeue_forget(fiq, 1, NULL);
unique = fuse_get_unique(fiq); unique = fuse_get_unique(fiq);
...@@ -739,46 +754,7 @@ __releases(fiq->lock) ...@@ -739,46 +754,7 @@ __releases(fiq->lock)
.nlookup = link->forget_one.nlookup, .nlookup = link->forget_one.nlookup,
}; };
sg_init_one(&sg, forget, sizeof(*forget)); send_forget_request(fsvq, forget, false);
/* Enqueue the request */
spin_lock(&fsvq->lock);
if (!fsvq->connected) {
kfree(forget);
spin_unlock(&fsvq->lock);
goto out;
}
vq = fsvq->vq;
dev_dbg(&vq->vdev->dev, "%s\n", __func__);
ret = virtqueue_add_sgs(vq, sgs, 1, 0, forget, GFP_ATOMIC);
if (ret < 0) {
if (ret == -ENOMEM || ret == -ENOSPC) {
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later.\n",
ret);
list_add_tail(&forget->list, &fsvq->queued_reqs);
schedule_delayed_work(&fsvq->dispatch_work,
msecs_to_jiffies(1));
inc_in_flight_req(fsvq);
} else {
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
ret);
kfree(forget);
}
spin_unlock(&fsvq->lock);
goto out;
}
inc_in_flight_req(fsvq);
notify = virtqueue_kick_prepare(vq);
spin_unlock(&fsvq->lock);
if (notify)
virtqueue_notify(vq);
out:
kfree(link); kfree(link);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment