virtiofs: Count pending forgets as in_flight forgets
If virtqueue is full, we put forget requests on a list and these forgets are dispatched later using a worker. As of now we don't count these forgets in fsvq->in_flight variable. This means when queue is being drained, we have to have special logic to first drain these pending requests and then wait for fsvq->in_flight to go to zero. By counting pending forgets in fsvq->in_flight, we can get rid of special logic and just wait for in_flight to go to zero. Worker thread will kick and drain all the forgets anyway, leading in_flight to zero. I also need similar logic for normal request queue in next patch where I am about to defer request submission in the worker context if queue is full. This simplifies the code a bit. Also add two helper functions to inc/dec in_flight. Decrement in_flight helper will later used to call completion when in_flight reaches zero. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
5dbe190f34
commit
c17ea00961
|
@ -67,6 +67,19 @@ static inline struct fuse_pqueue *vq_to_fpq(struct virtqueue *vq)
|
||||||
return &vq_to_fsvq(vq)->fud->pq;
|
return &vq_to_fsvq(vq)->fud->pq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Should be called with fsvq->lock held. */
|
||||||
|
static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq)
|
||||||
|
{
|
||||||
|
fsvq->in_flight++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should be called with fsvq->lock held. */
|
||||||
|
static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
|
||||||
|
{
|
||||||
|
WARN_ON(fsvq->in_flight <= 0);
|
||||||
|
fsvq->in_flight--;
|
||||||
|
}
|
||||||
|
|
||||||
static void release_virtio_fs_obj(struct kref *ref)
|
static void release_virtio_fs_obj(struct kref *ref)
|
||||||
{
|
{
|
||||||
struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
|
struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
|
||||||
|
@ -110,22 +123,6 @@ static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
|
||||||
flush_delayed_work(&fsvq->dispatch_work);
|
flush_delayed_work(&fsvq->dispatch_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void drain_hiprio_queued_reqs(struct virtio_fs_vq *fsvq)
|
|
||||||
{
|
|
||||||
struct virtio_fs_forget *forget;
|
|
||||||
|
|
||||||
spin_lock(&fsvq->lock);
|
|
||||||
while (1) {
|
|
||||||
forget = list_first_entry_or_null(&fsvq->queued_reqs,
|
|
||||||
struct virtio_fs_forget, list);
|
|
||||||
if (!forget)
|
|
||||||
break;
|
|
||||||
list_del(&forget->list);
|
|
||||||
kfree(forget);
|
|
||||||
}
|
|
||||||
spin_unlock(&fsvq->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
|
static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
|
||||||
{
|
{
|
||||||
struct virtio_fs_vq *fsvq;
|
struct virtio_fs_vq *fsvq;
|
||||||
|
@ -133,9 +130,6 @@ static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
|
||||||
|
|
||||||
for (i = 0; i < fs->nvqs; i++) {
|
for (i = 0; i < fs->nvqs; i++) {
|
||||||
fsvq = &fs->vqs[i];
|
fsvq = &fs->vqs[i];
|
||||||
if (i == VQ_HIPRIO)
|
|
||||||
drain_hiprio_queued_reqs(fsvq);
|
|
||||||
|
|
||||||
virtio_fs_drain_queue(fsvq);
|
virtio_fs_drain_queue(fsvq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +248,7 @@ static void virtio_fs_hiprio_done_work(struct work_struct *work)
|
||||||
|
|
||||||
while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
|
while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
|
||||||
kfree(req);
|
kfree(req);
|
||||||
fsvq->in_flight--;
|
dec_in_flight_req(fsvq);
|
||||||
}
|
}
|
||||||
} while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
|
} while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
|
||||||
spin_unlock(&fsvq->lock);
|
spin_unlock(&fsvq->lock);
|
||||||
|
@ -306,6 +300,7 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
|
||||||
|
|
||||||
list_del(&forget->list);
|
list_del(&forget->list);
|
||||||
if (!fsvq->connected) {
|
if (!fsvq->connected) {
|
||||||
|
dec_in_flight_req(fsvq);
|
||||||
spin_unlock(&fsvq->lock);
|
spin_unlock(&fsvq->lock);
|
||||||
kfree(forget);
|
kfree(forget);
|
||||||
continue;
|
continue;
|
||||||
|
@ -327,13 +322,13 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
spin_unlock(&fsvq->lock);
|
spin_unlock(&fsvq->lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsvq->in_flight++;
|
|
||||||
notify = virtqueue_kick_prepare(vq);
|
notify = virtqueue_kick_prepare(vq);
|
||||||
spin_unlock(&fsvq->lock);
|
spin_unlock(&fsvq->lock);
|
||||||
|
|
||||||
|
@ -472,7 +467,7 @@ static void virtio_fs_requests_done_work(struct work_struct *work)
|
||||||
|
|
||||||
fuse_request_end(fc, req);
|
fuse_request_end(fc, req);
|
||||||
spin_lock(&fsvq->lock);
|
spin_lock(&fsvq->lock);
|
||||||
fsvq->in_flight--;
|
dec_in_flight_req(fsvq);
|
||||||
spin_unlock(&fsvq->lock);
|
spin_unlock(&fsvq->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -730,6 +725,7 @@ __releases(fiq->lock)
|
||||||
list_add_tail(&forget->list, &fsvq->queued_reqs);
|
list_add_tail(&forget->list, &fsvq->queued_reqs);
|
||||||
schedule_delayed_work(&fsvq->dispatch_work,
|
schedule_delayed_work(&fsvq->dispatch_work,
|
||||||
msecs_to_jiffies(1));
|
msecs_to_jiffies(1));
|
||||||
|
inc_in_flight_req(fsvq);
|
||||||
} 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);
|
||||||
|
@ -739,7 +735,7 @@ __releases(fiq->lock)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsvq->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);
|
||||||
|
@ -921,7 +917,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
|
||||||
/* matches barrier in request_wait_answer() */
|
/* matches barrier in request_wait_answer() */
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
|
|
||||||
fsvq->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);
|
||||||
|
|
Loading…
Reference in New Issue