summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/virtio_fs.c61
1 files changed, 52 insertions, 9 deletions
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 3ea613d5e34f..2de8fc0d6a24 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -55,6 +55,9 @@ struct virtio_fs_forget {
55 struct list_head list; 55 struct list_head list;
56}; 56};
57 57
58static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
59 struct fuse_req *req, bool in_flight);
60
58static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq) 61static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq)
59{ 62{
60 struct virtio_fs *fs = vq->vdev->priv; 63 struct virtio_fs *fs = vq->vdev->priv;
@@ -260,6 +263,7 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work)
260 struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq, 263 struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
261 dispatch_work.work); 264 dispatch_work.work);
262 struct fuse_conn *fc = fsvq->fud->fc; 265 struct fuse_conn *fc = fsvq->fud->fc;
266 int ret;
263 267
264 pr_debug("virtio-fs: worker %s called.\n", __func__); 268 pr_debug("virtio-fs: worker %s called.\n", __func__);
265 while (1) { 269 while (1) {
@@ -268,13 +272,45 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work)
268 list); 272 list);
269 if (!req) { 273 if (!req) {
270 spin_unlock(&fsvq->lock); 274 spin_unlock(&fsvq->lock);
271 return; 275 break;
272 } 276 }
273 277
274 list_del_init(&req->list); 278 list_del_init(&req->list);
275 spin_unlock(&fsvq->lock); 279 spin_unlock(&fsvq->lock);
276 fuse_request_end(fc, req); 280 fuse_request_end(fc, req);
277 } 281 }
282
283 /* Dispatch pending requests */
284 while (1) {
285 spin_lock(&fsvq->lock);
286 req = list_first_entry_or_null(&fsvq->queued_reqs,
287 struct fuse_req, list);
288 if (!req) {
289 spin_unlock(&fsvq->lock);
290 return;
291 }
292 list_del_init(&req->list);
293 spin_unlock(&fsvq->lock);
294
295 ret = virtio_fs_enqueue_req(fsvq, req, true);
296 if (ret < 0) {
297 if (ret == -ENOMEM || ret == -ENOSPC) {
298 spin_lock(&fsvq->lock);
299 list_add_tail(&req->list, &fsvq->queued_reqs);
300 schedule_delayed_work(&fsvq->dispatch_work,
301 msecs_to_jiffies(1));
302 spin_unlock(&fsvq->lock);
303 return;
304 }
305 req->out.h.error = ret;
306 spin_lock(&fsvq->lock);
307 dec_in_flight_req(fsvq);
308 spin_unlock(&fsvq->lock);
309 pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n",
310 ret);
311 fuse_request_end(fc, req);
312 }
313 }
278} 314}
279 315
280static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) 316static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
@@ -837,7 +873,7 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,
837 873
838/* Add a request to a virtqueue and kick the device */ 874/* Add a request to a virtqueue and kick the device */
839static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, 875static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
840 struct fuse_req *req) 876 struct fuse_req *req, bool in_flight)
841{ 877{
842 /* requests need at least 4 elements */ 878 /* requests need at least 4 elements */
843 struct scatterlist *stack_sgs[6]; 879 struct scatterlist *stack_sgs[6];
@@ -917,7 +953,8 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
917 /* matches barrier in request_wait_answer() */ 953 /* matches barrier in request_wait_answer() */
918 smp_mb__after_atomic(); 954 smp_mb__after_atomic();
919 955
920 inc_in_flight_req(fsvq); 956 if (!in_flight)
957 inc_in_flight_req(fsvq);
921 notify = virtqueue_kick_prepare(vq); 958 notify = virtqueue_kick_prepare(vq);
922 959
923 spin_unlock(&fsvq->lock); 960 spin_unlock(&fsvq->lock);
@@ -963,15 +1000,21 @@ __releases(fiq->lock)
963 req->in.h.nodeid, req->in.h.len, 1000 req->in.h.nodeid, req->in.h.len,
964 fuse_len_args(req->args->out_numargs, req->args->out_args)); 1001 fuse_len_args(req->args->out_numargs, req->args->out_args));
965 1002
966retry:
967 fsvq = &fs->vqs[queue_id]; 1003 fsvq = &fs->vqs[queue_id];
968 ret = virtio_fs_enqueue_req(fsvq, req); 1004 ret = virtio_fs_enqueue_req(fsvq, req, false);
969 if (ret < 0) { 1005 if (ret < 0) {
970 if (ret == -ENOMEM || ret == -ENOSPC) { 1006 if (ret == -ENOMEM || ret == -ENOSPC) {
971 /* Virtqueue full. Retry submission */ 1007 /*
972 /* TODO use completion instead of timeout */ 1008 * Virtqueue full. Retry submission from worker
973 usleep_range(20, 30); 1009 * context as we might be holding fc->bg_lock.
974 goto retry; 1010 */
1011 spin_lock(&fsvq->lock);
1012 list_add_tail(&req->list, &fsvq->queued_reqs);
1013 inc_in_flight_req(fsvq);
1014 schedule_delayed_work(&fsvq->dispatch_work,
1015 msecs_to_jiffies(1));
1016 spin_unlock(&fsvq->lock);
1017 return;
975 } 1018 }
976 req->out.h.error = ret; 1019 req->out.h.error = ret;
977 pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret); 1020 pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret);