Skip to content

Commit c17ea00

Browse files
rhvgoyalMiklos Szeredi
authored andcommitted
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 <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 5dbe190 commit c17ea00

File tree

1 file changed

+20
-24
lines changed

1 file changed

+20
-24
lines changed

fs/fuse/virtio_fs.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ static inline struct fuse_pqueue *vq_to_fpq(struct virtqueue *vq)
6767
return &vq_to_fsvq(vq)->fud->pq;
6868
}
6969

70+
/* Should be called with fsvq->lock held. */
71+
static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq)
72+
{
73+
fsvq->in_flight++;
74+
}
75+
76+
/* Should be called with fsvq->lock held. */
77+
static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
78+
{
79+
WARN_ON(fsvq->in_flight <= 0);
80+
fsvq->in_flight--;
81+
}
82+
7083
static void release_virtio_fs_obj(struct kref *ref)
7184
{
7285
struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
@@ -110,32 +123,13 @@ static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
110123
flush_delayed_work(&fsvq->dispatch_work);
111124
}
112125

113-
static inline void drain_hiprio_queued_reqs(struct virtio_fs_vq *fsvq)
114-
{
115-
struct virtio_fs_forget *forget;
116-
117-
spin_lock(&fsvq->lock);
118-
while (1) {
119-
forget = list_first_entry_or_null(&fsvq->queued_reqs,
120-
struct virtio_fs_forget, list);
121-
if (!forget)
122-
break;
123-
list_del(&forget->list);
124-
kfree(forget);
125-
}
126-
spin_unlock(&fsvq->lock);
127-
}
128-
129126
static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
130127
{
131128
struct virtio_fs_vq *fsvq;
132129
int i;
133130

134131
for (i = 0; i < fs->nvqs; i++) {
135132
fsvq = &fs->vqs[i];
136-
if (i == VQ_HIPRIO)
137-
drain_hiprio_queued_reqs(fsvq);
138-
139133
virtio_fs_drain_queue(fsvq);
140134
}
141135
}
@@ -254,7 +248,7 @@ static void virtio_fs_hiprio_done_work(struct work_struct *work)
254248

255249
while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
256250
kfree(req);
257-
fsvq->in_flight--;
251+
dec_in_flight_req(fsvq);
258252
}
259253
} while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
260254
spin_unlock(&fsvq->lock);
@@ -306,6 +300,7 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
306300

307301
list_del(&forget->list);
308302
if (!fsvq->connected) {
303+
dec_in_flight_req(fsvq);
309304
spin_unlock(&fsvq->lock);
310305
kfree(forget);
311306
continue;
@@ -327,13 +322,13 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
327322
} else {
328323
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
329324
ret);
325+
dec_in_flight_req(fsvq);
330326
kfree(forget);
331327
}
332328
spin_unlock(&fsvq->lock);
333329
return;
334330
}
335331

336-
fsvq->in_flight++;
337332
notify = virtqueue_kick_prepare(vq);
338333
spin_unlock(&fsvq->lock);
339334

@@ -472,7 +467,7 @@ static void virtio_fs_requests_done_work(struct work_struct *work)
472467

473468
fuse_request_end(fc, req);
474469
spin_lock(&fsvq->lock);
475-
fsvq->in_flight--;
470+
dec_in_flight_req(fsvq);
476471
spin_unlock(&fsvq->lock);
477472
}
478473
}
@@ -730,6 +725,7 @@ __releases(fiq->lock)
730725
list_add_tail(&forget->list, &fsvq->queued_reqs);
731726
schedule_delayed_work(&fsvq->dispatch_work,
732727
msecs_to_jiffies(1));
728+
inc_in_flight_req(fsvq);
733729
} else {
734730
pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
735731
ret);
@@ -739,7 +735,7 @@ __releases(fiq->lock)
739735
goto out;
740736
}
741737

742-
fsvq->in_flight++;
738+
inc_in_flight_req(fsvq);
743739
notify = virtqueue_kick_prepare(vq);
744740

745741
spin_unlock(&fsvq->lock);
@@ -921,7 +917,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
921917
/* matches barrier in request_wait_answer() */
922918
smp_mb__after_atomic();
923919

924-
fsvq->in_flight++;
920+
inc_in_flight_req(fsvq);
925921
notify = virtqueue_kick_prepare(vq);
926922

927923
spin_unlock(&fsvq->lock);

0 commit comments

Comments
 (0)