All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fuse: return -ECONNABORTED on /dev/fuse read after abort
@ 2017-10-31 18:55 Szymon Lukasz
  2017-11-03 15:04 ` [PATCH v2] " Szymon Lukasz
  0 siblings, 1 reply; 10+ messages in thread
From: Szymon Lukasz @ 2017-10-31 18:55 UTC (permalink / raw)
  To: miklos; +Cc: linux-fsdevel, Szymon Lukasz

Currently the userspace has no way of knowing whether the fuse
connection ended because of umount or abort via sysfs. It makes it hard
for filesystems to free the mountpoint after abort without worrying
about removing some new mount.
The patch fixes it by returning different errors when userspace reads
from /dev/fuse (-ENODEV for umount and -ECONNABORTED for abort).

Signed-off-by: Szymon Lukasz <noh4hss@gmail.com>
---
 fs/fuse/control.c |  2 +-
 fs/fuse/dev.c     | 13 ++++++++-----
 fs/fuse/fuse_i.h  |  8 +++++++-
 fs/fuse/inode.c   |  4 ++--
 4 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index b9ea99c5b5b3..eeda05a7c882 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -35,7 +35,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
 {
 	struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
 	if (fc) {
-		fuse_abort_conn(fc);
+		fuse_abort_conn(fc, 1);
 		fuse_conn_put(fc);
 	}
 	return count;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 13c65dd2d37d..b51da52b92b9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1234,9 +1234,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
 	if (err)
 		goto err_unlock;
 
-	err = -ENODEV;
-	if (!fiq->connected)
+	if (!fiq->connected) {
+		err = fiq->aborted ? -ECONNABORTED : -ENODEV;
 		goto err_unlock;
+	}
 
 	if (!list_empty(&fiq->interrupts)) {
 		req = list_entry(fiq->interrupts.next, struct fuse_req,
@@ -1287,7 +1288,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
 	spin_lock(&fpq->lock);
 	clear_bit(FR_LOCKED, &req->flags);
 	if (!fpq->connected) {
-		err = -ENODEV;
+		err = fpq->aborted ? -ECONNABORTED : -ENODEV;
 		goto out_end;
 	}
 	if (err) {
@@ -2076,7 +2077,7 @@ static void end_polls(struct fuse_conn *fc)
  * is OK, the request will in that case be removed from the list before we touch
  * it.
  */
-void fuse_abort_conn(struct fuse_conn *fc)
+void fuse_abort_conn(struct fuse_conn *fc, int is_abort)
 {
 	struct fuse_iqueue *fiq = &fc->iq;
 
@@ -2095,6 +2096,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
 
 			spin_lock(&fpq->lock);
 			fpq->connected = 0;
+			fpq->aborted = is_abort;
 			list_for_each_entry_safe(req, next, &fpq->io, list) {
 				req->out.h.error = -ECONNABORTED;
 				spin_lock(&req->waitq.lock);
@@ -2113,6 +2115,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
 
 		spin_lock(&fiq->waitq.lock);
 		fiq->connected = 0;
+		fiq->aborted = is_abort;
 		list_splice_init(&fiq->pending, &to_end2);
 		list_for_each_entry(req, &to_end2, list)
 			clear_bit(FR_PENDING, &req->flags);
@@ -2151,7 +2154,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
 		/* Are we the last open device? */
 		if (atomic_dec_and_test(&fc->dev_count)) {
 			WARN_ON(fc->iq.fasync != NULL);
-			fuse_abort_conn(fc);
+			fuse_abort_conn(fc, 0);
 		}
 		fuse_dev_free(fud);
 	}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d5773ca67ad2..650e72be4174 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -387,6 +387,9 @@ struct fuse_iqueue {
 	/** Connection established */
 	unsigned connected;
 
+	/** Connection aborted via sysfs */
+	int aborted;
+
 	/** Readers of the connection are waiting on this */
 	wait_queue_head_t waitq;
 
@@ -414,6 +417,9 @@ struct fuse_pqueue {
 	/** Connection established */
 	unsigned connected;
 
+	/** Connection aborted via sysfs */
+	int aborted;
+
 	/** Lock protecting accessess to  members of this structure */
 	spinlock_t lock;
 
@@ -851,7 +857,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
 					 struct fuse_req *req);
 
 /* Abort all requests */
-void fuse_abort_conn(struct fuse_conn *fc);
+void fuse_abort_conn(struct fuse_conn *fc, int is_abort);
 
 /**
  * Invalidate inode attributes
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 94a745acaef8..8cc9de4ec16d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -371,7 +371,7 @@ void fuse_unlock_inode(struct inode *inode)
 
 static void fuse_umount_begin(struct super_block *sb)
 {
-	fuse_abort_conn(get_fuse_conn_super(sb));
+	fuse_abort_conn(get_fuse_conn_super(sb), 0);
 }
 
 static void fuse_send_destroy(struct fuse_conn *fc)
@@ -393,7 +393,7 @@ static void fuse_put_super(struct super_block *sb)
 
 	fuse_send_destroy(fc);
 
-	fuse_abort_conn(fc);
+	fuse_abort_conn(fc, 0);
 	mutex_lock(&fuse_mutex);
 	list_del(&fc->entry);
 	fuse_ctl_remove_conn(fc);
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-03-21 11:57 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-31 18:55 [PATCH] fuse: return -ECONNABORTED on /dev/fuse read after abort Szymon Lukasz
2017-11-03 15:04 ` [PATCH v2] " Szymon Lukasz
2017-11-06  9:51   ` Miklos Szeredi
2017-11-07  0:16     ` [PATCH v3] " Szymon Lukasz
2017-11-09 18:29       ` kbuild test robot
2017-11-09 19:44       ` kbuild test robot
2017-11-09 20:23       ` [PATCH v4] " Szymon Lukasz
     [not found]         ` <20171109202335.19797-1-noh4hss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-11-21 22:16           ` Szymon Łukasz
2017-11-21 22:43         ` Szymon Lukasz
2018-03-21 11:57         ` Miklos Szeredi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.