summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-10-29 12:43:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-10-29 12:43:33 -0400
commit23fdb198ae81f47a574296dab5167c5e136a02ba (patch)
tree138440550fdf4d9ef42e52f321e8eee83dba5f5c
parent8005803a2ca0af49f36f6e9329b5ecda3df27347 (diff)
parent091d1a7267726ba162b12ce9332d76cdae602789 (diff)
Merge tag 'fuse-fixes-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse fixes from Miklos Szeredi: "Mostly virtiofs fixes, but also fixes a regression and couple of longstanding data/metadata writeback ordering issues" * tag 'fuse-fixes-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: redundant get_fuse_inode() calls in fuse_writepages_fill() fuse: Add changelog entries for protocols 7.1 - 7.8 fuse: truncate pending writes on O_TRUNC fuse: flush dirty data/metadata before non-truncate setattr virtiofs: Remove set but not used variable 'fc' virtiofs: Retry request submission from worker context virtiofs: Count pending forgets as in_flight forgets virtiofs: Set FR_SENT flag only after request has been sent virtiofs: No need to check fpq->connected state virtiofs: Do not end request in submission context fuse: don't advise readdirplus for negative lookup fuse: don't dereference req->args on finished request virtio-fs: don't show mount options virtio-fs: Change module name to virtiofs.ko
-rw-r--r--fs/fuse/Makefile3
-rw-r--r--fs/fuse/dev.c4
-rw-r--r--fs/fuse/dir.c16
-rw-r--r--fs/fuse/file.c14
-rw-r--r--fs/fuse/fuse_i.h4
-rw-r--r--fs/fuse/inode.c4
-rw-r--r--fs/fuse/virtio_fs.c169
-rw-r--r--include/uapi/linux/fuse.h37
8 files changed, 186 insertions, 65 deletions
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index 6419a2b3510d..3e8cebfb59b7 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -5,6 +5,7 @@
5 5
6obj-$(CONFIG_FUSE_FS) += fuse.o 6obj-$(CONFIG_FUSE_FS) += fuse.o
7obj-$(CONFIG_CUSE) += cuse.o 7obj-$(CONFIG_CUSE) += cuse.o
8obj-$(CONFIG_VIRTIO_FS) += virtio_fs.o 8obj-$(CONFIG_VIRTIO_FS) += virtiofs.o
9 9
10fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o 10fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o
11virtiofs-y += virtio_fs.o
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index dadd617d826c..ed1abc9e33cf 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -276,10 +276,12 @@ static void flush_bg_queue(struct fuse_conn *fc)
276void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) 276void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req)
277{ 277{
278 struct fuse_iqueue *fiq = &fc->iq; 278 struct fuse_iqueue *fiq = &fc->iq;
279 bool async = req->args->end; 279 bool async;
280 280
281 if (test_and_set_bit(FR_FINISHED, &req->flags)) 281 if (test_and_set_bit(FR_FINISHED, &req->flags))
282 goto put_request; 282 goto put_request;
283
284 async = req->args->end;
283 /* 285 /*
284 * test_and_set_bit() implies smp_mb() between bit 286 * test_and_set_bit() implies smp_mb() between bit
285 * changing and below intr_entry check. Pairs with 287 * changing and below intr_entry check. Pairs with
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index d572c900bb0f..54d638f9ba1c 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -405,7 +405,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
405 else 405 else
406 fuse_invalidate_entry_cache(entry); 406 fuse_invalidate_entry_cache(entry);
407 407
408 fuse_advise_use_readdirplus(dir); 408 if (inode)
409 fuse_advise_use_readdirplus(dir);
409 return newent; 410 return newent;
410 411
411 out_iput: 412 out_iput:
@@ -1521,6 +1522,19 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
1521 is_truncate = true; 1522 is_truncate = true;
1522 } 1523 }
1523 1524
1525 /* Flush dirty data/metadata before non-truncate SETATTR */
1526 if (is_wb && S_ISREG(inode->i_mode) &&
1527 attr->ia_valid &
1528 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1529 ATTR_TIMES_SET)) {
1530 err = write_inode_now(inode, true);
1531 if (err)
1532 return err;
1533
1534 fuse_set_nowrite(inode);
1535 fuse_release_nowrite(inode);
1536 }
1537
1524 if (is_truncate) { 1538 if (is_truncate) {
1525 fuse_set_nowrite(inode); 1539 fuse_set_nowrite(inode);
1526 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1540 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 0f0225686aee..db48a5cf8620 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -217,7 +217,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
217{ 217{
218 struct fuse_conn *fc = get_fuse_conn(inode); 218 struct fuse_conn *fc = get_fuse_conn(inode);
219 int err; 219 int err;
220 bool lock_inode = (file->f_flags & O_TRUNC) && 220 bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
221 fc->atomic_o_trunc && 221 fc->atomic_o_trunc &&
222 fc->writeback_cache; 222 fc->writeback_cache;
223 223
@@ -225,16 +225,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
225 if (err) 225 if (err)
226 return err; 226 return err;
227 227
228 if (lock_inode) 228 if (is_wb_truncate) {
229 inode_lock(inode); 229 inode_lock(inode);
230 fuse_set_nowrite(inode);
231 }
230 232
231 err = fuse_do_open(fc, get_node_id(inode), file, isdir); 233 err = fuse_do_open(fc, get_node_id(inode), file, isdir);
232 234
233 if (!err) 235 if (!err)
234 fuse_finish_open(inode, file); 236 fuse_finish_open(inode, file);
235 237
236 if (lock_inode) 238 if (is_wb_truncate) {
239 fuse_release_nowrite(inode);
237 inode_unlock(inode); 240 inode_unlock(inode);
241 }
238 242
239 return err; 243 return err;
240} 244}
@@ -1997,7 +2001,7 @@ static int fuse_writepages_fill(struct page *page,
1997 2001
1998 if (!data->ff) { 2002 if (!data->ff) {
1999 err = -EIO; 2003 err = -EIO;
2000 data->ff = fuse_write_file_get(fc, get_fuse_inode(inode)); 2004 data->ff = fuse_write_file_get(fc, fi);
2001 if (!data->ff) 2005 if (!data->ff)
2002 goto out_unlock; 2006 goto out_unlock;
2003 } 2007 }
@@ -2042,8 +2046,6 @@ static int fuse_writepages_fill(struct page *page,
2042 * under writeback, so we can release the page lock. 2046 * under writeback, so we can release the page lock.
2043 */ 2047 */
2044 if (data->wpa == NULL) { 2048 if (data->wpa == NULL) {
2045 struct fuse_inode *fi = get_fuse_inode(inode);
2046
2047 err = -ENOMEM; 2049 err = -ENOMEM;
2048 wpa = fuse_writepage_args_alloc(); 2050 wpa = fuse_writepage_args_alloc();
2049 if (!wpa) { 2051 if (!wpa) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 956aeaf961ae..d148188cfca4 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -479,6 +479,7 @@ struct fuse_fs_context {
479 bool destroy:1; 479 bool destroy:1;
480 bool no_control:1; 480 bool no_control:1;
481 bool no_force_umount:1; 481 bool no_force_umount:1;
482 bool no_mount_options:1;
482 unsigned int max_read; 483 unsigned int max_read;
483 unsigned int blksize; 484 unsigned int blksize;
484 const char *subtype; 485 const char *subtype;
@@ -713,6 +714,9 @@ struct fuse_conn {
713 /** Do not allow MNT_FORCE umount */ 714 /** Do not allow MNT_FORCE umount */
714 unsigned int no_force_umount:1; 715 unsigned int no_force_umount:1;
715 716
717 /* Do not show mount options */
718 unsigned int no_mount_options:1;
719
716 /** The number of requests waiting for completion */ 720 /** The number of requests waiting for completion */
717 atomic_t num_waiting; 721 atomic_t num_waiting;
718 722
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e040e2a2b621..16aec32f7f3d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -558,6 +558,9 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
558 struct super_block *sb = root->d_sb; 558 struct super_block *sb = root->d_sb;
559 struct fuse_conn *fc = get_fuse_conn_super(sb); 559 struct fuse_conn *fc = get_fuse_conn_super(sb);
560 560
561 if (fc->no_mount_options)
562 return 0;
563
561 seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id)); 564 seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id));
562 seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id)); 565 seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id));
563 if (fc->default_permissions) 566 if (fc->default_permissions)
@@ -1180,6 +1183,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
1180 fc->destroy = ctx->destroy; 1183 fc->destroy = ctx->destroy;
1181 fc->no_control = ctx->no_control; 1184 fc->no_control = ctx->no_control;
1182 fc->no_force_umount = ctx->no_force_umount; 1185 fc->no_force_umount = ctx->no_force_umount;
1186 fc->no_mount_options = ctx->no_mount_options;
1183 1187
1184 err = -ENOMEM; 1188 err = -ENOMEM;
1185 root = fuse_get_root_inode(sb, ctx->rootmode); 1189 root = fuse_get_root_inode(sb, ctx->rootmode);
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 6af3f131e468..a5c86048b96e 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -30,6 +30,7 @@ struct virtio_fs_vq {
30 struct virtqueue *vq; /* protected by ->lock */ 30 struct virtqueue *vq; /* protected by ->lock */
31 struct work_struct done_work; 31 struct work_struct done_work;
32 struct list_head queued_reqs; 32 struct list_head queued_reqs;
33 struct list_head end_reqs; /* End these requests */
33 struct delayed_work dispatch_work; 34 struct delayed_work dispatch_work;
34 struct fuse_dev *fud; 35 struct fuse_dev *fud;
35 bool connected; 36 bool connected;
@@ -54,6 +55,9 @@ struct virtio_fs_forget {
54 struct list_head list; 55 struct list_head list;
55}; 56};
56 57
58static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
59 struct fuse_req *req, bool in_flight);
60
57static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq) 61static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq)
58{ 62{
59 struct virtio_fs *fs = vq->vdev->priv; 63 struct virtio_fs *fs = vq->vdev->priv;
@@ -66,6 +70,19 @@ static inline struct fuse_pqueue *vq_to_fpq(struct virtqueue *vq)
66 return &vq_to_fsvq(vq)->fud->pq; 70 return &vq_to_fsvq(vq)->fud->pq;
67} 71}
68 72
73/* Should be called with fsvq->lock held. */
74static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq)
75{
76 fsvq->in_flight++;
77}
78
79/* Should be called with fsvq->lock held. */
80static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
81{
82 WARN_ON(fsvq->in_flight <= 0);
83 fsvq->in_flight--;
84}
85
69static void release_virtio_fs_obj(struct kref *ref) 86static void release_virtio_fs_obj(struct kref *ref)
70{ 87{
71 struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount); 88 struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
@@ -109,22 +126,6 @@ static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
109 flush_delayed_work(&fsvq->dispatch_work); 126 flush_delayed_work(&fsvq->dispatch_work);
110} 127}
111 128
112static inline void drain_hiprio_queued_reqs(struct virtio_fs_vq *fsvq)
113{
114 struct virtio_fs_forget *forget;
115
116 spin_lock(&fsvq->lock);
117 while (1) {
118 forget = list_first_entry_or_null(&fsvq->queued_reqs,
119 struct virtio_fs_forget, list);
120 if (!forget)
121 break;
122 list_del(&forget->list);
123 kfree(forget);
124 }
125 spin_unlock(&fsvq->lock);
126}
127
128static void virtio_fs_drain_all_queues(struct virtio_fs *fs) 129static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
129{ 130{
130 struct virtio_fs_vq *fsvq; 131 struct virtio_fs_vq *fsvq;
@@ -132,9 +133,6 @@ static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
132 133
133 for (i = 0; i < fs->nvqs; i++) { 134 for (i = 0; i < fs->nvqs; i++) {
134 fsvq = &fs->vqs[i]; 135 fsvq = &fs->vqs[i];
135 if (i == VQ_HIPRIO)
136 drain_hiprio_queued_reqs(fsvq);
137
138 virtio_fs_drain_queue(fsvq); 136 virtio_fs_drain_queue(fsvq);
139 } 137 }
140} 138}
@@ -253,14 +251,66 @@ static void virtio_fs_hiprio_done_work(struct work_struct *work)
253 251
254 while ((req = virtqueue_get_buf(vq, &len)) != NULL) { 252 while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
255 kfree(req); 253 kfree(req);
256 fsvq->in_flight--; 254 dec_in_flight_req(fsvq);
257 } 255 }
258 } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq))); 256 } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
259 spin_unlock(&fsvq->lock); 257 spin_unlock(&fsvq->lock);
260} 258}
261 259
262static void virtio_fs_dummy_dispatch_work(struct work_struct *work) 260static void virtio_fs_request_dispatch_work(struct work_struct *work)
263{ 261{
262 struct fuse_req *req;
263 struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
264 dispatch_work.work);
265 struct fuse_conn *fc = fsvq->fud->fc;
266 int ret;
267
268 pr_debug("virtio-fs: worker %s called.\n", __func__);
269 while (1) {
270 spin_lock(&fsvq->lock);
271 req = list_first_entry_or_null(&fsvq->end_reqs, struct fuse_req,
272 list);
273 if (!req) {
274 spin_unlock(&fsvq->lock);
275 break;
276 }
277
278 list_del_init(&req->list);
279 spin_unlock(&fsvq->lock);
280 fuse_request_end(fc, req);
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 }
264} 314}
265 315
266static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) 316static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
@@ -286,6 +336,7 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
286 336
287 list_del(&forget->list); 337 list_del(&forget->list);
288 if (!fsvq->connected) { 338 if (!fsvq->connected) {
339 dec_in_flight_req(fsvq);
289 spin_unlock(&fsvq->lock); 340 spin_unlock(&fsvq->lock);
290 kfree(forget); 341 kfree(forget);
291 continue; 342 continue;
@@ -307,13 +358,13 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
307 } else { 358 } else {
308 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", 359 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
309 ret); 360 ret);
361 dec_in_flight_req(fsvq);
310 kfree(forget); 362 kfree(forget);
311 } 363 }
312 spin_unlock(&fsvq->lock); 364 spin_unlock(&fsvq->lock);
313 return; 365 return;
314 } 366 }
315 367
316 fsvq->in_flight++;
317 notify = virtqueue_kick_prepare(vq); 368 notify = virtqueue_kick_prepare(vq);
318 spin_unlock(&fsvq->lock); 369 spin_unlock(&fsvq->lock);
319 370
@@ -452,7 +503,7 @@ static void virtio_fs_requests_done_work(struct work_struct *work)
452 503
453 fuse_request_end(fc, req); 504 fuse_request_end(fc, req);
454 spin_lock(&fsvq->lock); 505 spin_lock(&fsvq->lock);
455 fsvq->in_flight--; 506 dec_in_flight_req(fsvq);
456 spin_unlock(&fsvq->lock); 507 spin_unlock(&fsvq->lock);
457 } 508 }
458} 509}
@@ -502,6 +553,7 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev,
502 names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name; 553 names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name;
503 INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work); 554 INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work);
504 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs); 555 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs);
556 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs);
505 INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work, 557 INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work,
506 virtio_fs_hiprio_dispatch_work); 558 virtio_fs_hiprio_dispatch_work);
507 spin_lock_init(&fs->vqs[VQ_HIPRIO].lock); 559 spin_lock_init(&fs->vqs[VQ_HIPRIO].lock);
@@ -511,8 +563,9 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev,
511 spin_lock_init(&fs->vqs[i].lock); 563 spin_lock_init(&fs->vqs[i].lock);
512 INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work); 564 INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work);
513 INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work, 565 INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work,
514 virtio_fs_dummy_dispatch_work); 566 virtio_fs_request_dispatch_work);
515 INIT_LIST_HEAD(&fs->vqs[i].queued_reqs); 567 INIT_LIST_HEAD(&fs->vqs[i].queued_reqs);
568 INIT_LIST_HEAD(&fs->vqs[i].end_reqs);
516 snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name), 569 snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name),
517 "requests.%u", i - VQ_REQUEST); 570 "requests.%u", i - VQ_REQUEST);
518 callbacks[i] = virtio_fs_vq_done; 571 callbacks[i] = virtio_fs_vq_done;
@@ -708,6 +761,7 @@ __releases(fiq->lock)
708 list_add_tail(&forget->list, &fsvq->queued_reqs); 761 list_add_tail(&forget->list, &fsvq->queued_reqs);
709 schedule_delayed_work(&fsvq->dispatch_work, 762 schedule_delayed_work(&fsvq->dispatch_work,
710 msecs_to_jiffies(1)); 763 msecs_to_jiffies(1));
764 inc_in_flight_req(fsvq);
711 } else { 765 } else {
712 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", 766 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
713 ret); 767 ret);
@@ -717,7 +771,7 @@ __releases(fiq->lock)
717 goto out; 771 goto out;
718 } 772 }
719 773
720 fsvq->in_flight++; 774 inc_in_flight_req(fsvq);
721 notify = virtqueue_kick_prepare(vq); 775 notify = virtqueue_kick_prepare(vq);
722 776
723 spin_unlock(&fsvq->lock); 777 spin_unlock(&fsvq->lock);
@@ -819,7 +873,7 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,
819 873
820/* Add a request to a virtqueue and kick the device */ 874/* Add a request to a virtqueue and kick the device */
821static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, 875static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
822 struct fuse_req *req) 876 struct fuse_req *req, bool in_flight)
823{ 877{
824 /* requests need at least 4 elements */ 878 /* requests need at least 4 elements */
825 struct scatterlist *stack_sgs[6]; 879 struct scatterlist *stack_sgs[6];
@@ -835,6 +889,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
835 unsigned int i; 889 unsigned int i;
836 int ret; 890 int ret;
837 bool notify; 891 bool notify;
892 struct fuse_pqueue *fpq;
838 893
839 /* Does the sglist fit on the stack? */ 894 /* Does the sglist fit on the stack? */
840 total_sgs = sg_count_fuse_req(req); 895 total_sgs = sg_count_fuse_req(req);
@@ -889,7 +944,17 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
889 goto out; 944 goto out;
890 } 945 }
891 946
892 fsvq->in_flight++; 947 /* Request successfully sent. */
948 fpq = &fsvq->fud->pq;
949 spin_lock(&fpq->lock);
950 list_add_tail(&req->list, fpq->processing);
951 spin_unlock(&fpq->lock);
952 set_bit(FR_SENT, &req->flags);
953 /* matches barrier in request_wait_answer() */
954 smp_mb__after_atomic();
955
956 if (!in_flight)
957 inc_in_flight_req(fsvq);
893 notify = virtqueue_kick_prepare(vq); 958 notify = virtqueue_kick_prepare(vq);
894 959
895 spin_unlock(&fsvq->lock); 960 spin_unlock(&fsvq->lock);
@@ -915,9 +980,8 @@ __releases(fiq->lock)
915{ 980{
916 unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */ 981 unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */
917 struct virtio_fs *fs; 982 struct virtio_fs *fs;
918 struct fuse_conn *fc;
919 struct fuse_req *req; 983 struct fuse_req *req;
920 struct fuse_pqueue *fpq; 984 struct virtio_fs_vq *fsvq;
921 int ret; 985 int ret;
922 986
923 WARN_ON(list_empty(&fiq->pending)); 987 WARN_ON(list_empty(&fiq->pending));
@@ -928,44 +992,36 @@ __releases(fiq->lock)
928 spin_unlock(&fiq->lock); 992 spin_unlock(&fiq->lock);
929 993
930 fs = fiq->priv; 994 fs = fiq->priv;
931 fc = fs->vqs[queue_id].fud->fc;
932 995
933 pr_debug("%s: opcode %u unique %#llx nodeid %#llx in.len %u out.len %u\n", 996 pr_debug("%s: opcode %u unique %#llx nodeid %#llx in.len %u out.len %u\n",
934 __func__, req->in.h.opcode, req->in.h.unique, 997 __func__, req->in.h.opcode, req->in.h.unique,
935 req->in.h.nodeid, req->in.h.len, 998 req->in.h.nodeid, req->in.h.len,
936 fuse_len_args(req->args->out_numargs, req->args->out_args)); 999 fuse_len_args(req->args->out_numargs, req->args->out_args));
937 1000
938 fpq = &fs->vqs[queue_id].fud->pq; 1001 fsvq = &fs->vqs[queue_id];
939 spin_lock(&fpq->lock); 1002 ret = virtio_fs_enqueue_req(fsvq, req, false);
940 if (!fpq->connected) {
941 spin_unlock(&fpq->lock);
942 req->out.h.error = -ENODEV;
943 pr_err("virtio-fs: %s disconnected\n", __func__);
944 fuse_request_end(fc, req);
945 return;
946 }
947 list_add_tail(&req->list, fpq->processing);
948 spin_unlock(&fpq->lock);
949 set_bit(FR_SENT, &req->flags);
950 /* matches barrier in request_wait_answer() */
951 smp_mb__after_atomic();
952
953retry:
954 ret = virtio_fs_enqueue_req(&fs->vqs[queue_id], req);
955 if (ret < 0) { 1003 if (ret < 0) {
956 if (ret == -ENOMEM || ret == -ENOSPC) { 1004 if (ret == -ENOMEM || ret == -ENOSPC) {
957 /* Virtqueue full. Retry submission */ 1005 /*
958 /* TODO use completion instead of timeout */ 1006 * Virtqueue full. Retry submission from worker
959 usleep_range(20, 30); 1007 * context as we might be holding fc->bg_lock.
960 goto retry; 1008 */
1009 spin_lock(&fsvq->lock);
1010 list_add_tail(&req->list, &fsvq->queued_reqs);
1011 inc_in_flight_req(fsvq);
1012 schedule_delayed_work(&fsvq->dispatch_work,
1013 msecs_to_jiffies(1));
1014 spin_unlock(&fsvq->lock);
1015 return;
961 } 1016 }
962 req->out.h.error = ret; 1017 req->out.h.error = ret;
963 pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret); 1018 pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret);
964 spin_lock(&fpq->lock); 1019
965 clear_bit(FR_SENT, &req->flags); 1020 /* Can't end request in submission context. Use a worker */
966 list_del_init(&req->list); 1021 spin_lock(&fsvq->lock);
967 spin_unlock(&fpq->lock); 1022 list_add_tail(&req->list, &fsvq->end_reqs);
968 fuse_request_end(fc, req); 1023 schedule_delayed_work(&fsvq->dispatch_work, 0);
1024 spin_unlock(&fsvq->lock);
969 return; 1025 return;
970 } 1026 }
971} 1027}
@@ -992,6 +1048,7 @@ static int virtio_fs_fill_super(struct super_block *sb)
992 .destroy = true, 1048 .destroy = true,
993 .no_control = true, 1049 .no_control = true,
994 .no_force_umount = true, 1050 .no_force_umount = true,
1051 .no_mount_options = true,
995 }; 1052 };
996 1053
997 mutex_lock(&virtio_fs_mutex); 1054 mutex_lock(&virtio_fs_mutex);
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 802b0377a49e..373cada89815 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -38,6 +38,43 @@
38 * 38 *
39 * Protocol changelog: 39 * Protocol changelog:
40 * 40 *
41 * 7.1:
42 * - add the following messages:
43 * FUSE_SETATTR, FUSE_SYMLINK, FUSE_MKNOD, FUSE_MKDIR, FUSE_UNLINK,
44 * FUSE_RMDIR, FUSE_RENAME, FUSE_LINK, FUSE_OPEN, FUSE_READ, FUSE_WRITE,
45 * FUSE_RELEASE, FUSE_FSYNC, FUSE_FLUSH, FUSE_SETXATTR, FUSE_GETXATTR,
46 * FUSE_LISTXATTR, FUSE_REMOVEXATTR, FUSE_OPENDIR, FUSE_READDIR,
47 * FUSE_RELEASEDIR
48 * - add padding to messages to accommodate 32-bit servers on 64-bit kernels
49 *
50 * 7.2:
51 * - add FOPEN_DIRECT_IO and FOPEN_KEEP_CACHE flags
52 * - add FUSE_FSYNCDIR message
53 *
54 * 7.3:
55 * - add FUSE_ACCESS message
56 * - add FUSE_CREATE message
57 * - add filehandle to fuse_setattr_in
58 *
59 * 7.4:
60 * - add frsize to fuse_kstatfs
61 * - clean up request size limit checking
62 *
63 * 7.5:
64 * - add flags and max_write to fuse_init_out
65 *
66 * 7.6:
67 * - add max_readahead to fuse_init_in and fuse_init_out
68 *
69 * 7.7:
70 * - add FUSE_INTERRUPT message
71 * - add POSIX file lock support
72 *
73 * 7.8:
74 * - add lock_owner and flags fields to fuse_release_in
75 * - add FUSE_BMAP message
76 * - add FUSE_DESTROY message
77 *
41 * 7.9: 78 * 7.9:
42 * - new fuse_getattr_in input argument of GETATTR 79 * - new fuse_getattr_in input argument of GETATTR
43 * - add lk_flags in fuse_lk_in 80 * - add lk_flags in fuse_lk_in