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: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
00929447f5
commit
58ada94f95
@ -313,17 +313,71 @@ static void virtio_fs_request_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 scatterlist sg;
|
||||||
|
struct virtqueue *vq;
|
||||||
|
int ret = 0;
|
||||||
|
bool notify;
|
||||||
|
|
||||||
|
spin_lock(&fsvq->lock);
|
||||||
|
if (!fsvq->connected) {
|
||||||
|
if (in_flight)
|
||||||
|
dec_in_flight_req(fsvq);
|
||||||
|
kfree(forget);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_init_one(&sg, forget, sizeof(*forget));
|
||||||
|
vq = fsvq->vq;
|
||||||
|
dev_dbg(&vq->vdev->dev, "%s\n", __func__);
|
||||||
|
|
||||||
|
ret = virtqueue_add_outbuf(vq, &sg, 1, 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));
|
||||||
|
if (!in_flight)
|
||||||
|
inc_in_flight_req(fsvq);
|
||||||
|
/* Queue is full */
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
|
||||||
|
ret);
|
||||||
|
kfree(forget);
|
||||||
|
if (in_flight)
|
||||||
|
dec_in_flight_req(fsvq);
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_flight)
|
||||||
|
inc_in_flight_req(fsvq);
|
||||||
|
notify = virtqueue_kick_prepare(vq);
|
||||||
|
spin_unlock(&fsvq->lock);
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
virtqueue_notify(vq);
|
||||||
|
return ret;
|
||||||
|
out:
|
||||||
|
spin_unlock(&fsvq->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
|
static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct virtio_fs_forget *forget;
|
struct virtio_fs_forget *forget;
|
||||||
struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
|
struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
|
||||||
dispatch_work.work);
|
dispatch_work.work);
|
||||||
struct virtqueue *vq = fsvq->vq;
|
|
||||||
struct scatterlist sg;
|
|
||||||
struct scatterlist *sgs[] = {&sg};
|
|
||||||
bool notify;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
pr_debug("virtio-fs: worker %s called.\n", __func__);
|
pr_debug("virtio-fs: worker %s called.\n", __func__);
|
||||||
while (1) {
|
while (1) {
|
||||||
spin_lock(&fsvq->lock);
|
spin_lock(&fsvq->lock);
|
||||||
@ -335,44 +389,10 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_del(&forget->list);
|
list_del(&forget->list);
|
||||||
if (!fsvq->connected) {
|
|
||||||
dec_in_flight_req(fsvq);
|
|
||||||
spin_unlock(&fsvq->lock);
|
|
||||||
kfree(forget);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sg_init_one(&sg, forget, sizeof(*forget));
|
|
||||||
|
|
||||||
/* Enqueue the request */
|
|
||||||
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));
|
|
||||||
} else {
|
|
||||||
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
|
|
||||||
ret);
|
|
||||||
dec_in_flight_req(fsvq);
|
|
||||||
kfree(forget);
|
|
||||||
}
|
|
||||||
spin_unlock(&fsvq->lock);
|
spin_unlock(&fsvq->lock);
|
||||||
|
if (send_forget_request(fsvq, forget, true))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify = virtqueue_kick_prepare(vq);
|
|
||||||
spin_unlock(&fsvq->lock);
|
|
||||||
|
|
||||||
if (notify)
|
|
||||||
virtqueue_notify(vq);
|
|
||||||
pr_debug("virtio-fs: worker %s dispatched one forget request.\n",
|
|
||||||
__func__);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate and copy args into req->argbuf */
|
/* Allocate and copy args into req->argbuf */
|
||||||
@ -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)
|
|||||||
.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user