[Devel,vz7,20/46] fuse: duplicate ->connected in iqueue

Submitted by Maxim Patlasov on March 25, 2017, 2:20 a.m.

Details

Message ID 149040840906.25341.6020287081007302313.stgit@maxim-thinkpad
State New
Series "fuse: add multi-threading support"
Headers show

Commit Message

Maxim Patlasov March 25, 2017, 2:20 a.m.
Backport from ml:

commit e16714d8756dc1237a66994e139b61feebcf707a
Author: Miklos Szeredi <mszeredi@suse.cz>
Date:   Wed Jul 1 16:26:01 2015 +0200

    fuse: duplicate ->connected in iqueue

    This will allow checking ->connected just with the input queue lock.

    Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
    Reviewed-by: Ashish Samant <ashish.samant@oracle.com>

Signed-off-by: Maxim Patlasov <mpatlasov@virtuozzo.com>
---
 fs/fuse/cuse.c   |    1 -
 fs/fuse/dev.c    |   19 ++++++++++---------
 fs/fuse/fuse_i.h |    3 +++
 fs/fuse/inode.c  |    3 ++-
 4 files changed, 15 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 6fc279a..474be9c 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -507,7 +507,6 @@  static int cuse_channel_open(struct inode *inode, struct file *file)
 	INIT_LIST_HEAD(&cc->list);
 	cc->fc.release = cuse_fc_release;
 
-	cc->fc.connected = 1;
 	cc->fc.initialized = 1;
 	rc = cuse_send_init(cc);
 	if (rc) {
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 8b18c19..816f9e4 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -324,7 +324,7 @@  void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
 	forget->forget_one.nlookup = nlookup;
 
 	spin_lock(&fc->lock);
-	if (fc->connected) {
+	if (fiq->connected) {
 		fiq->forget_list_tail->next = forget;
 		fiq->forget_list_tail = forget;
 		wake_up(&fiq->waitq);
@@ -451,17 +451,17 @@  static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
 static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req,
 				struct fuse_file *ff)
 {
+	struct fuse_iqueue *fiq = &fc->iq;
+
 	BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
 	spin_lock(&fc->lock);
-	if (!fc->connected) {
+	if (!fiq->connected) {
 		spin_unlock(&fc->lock);
 		req->out.h.error = -ENOTCONN;
 	} else if (ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state)) {
 		spin_unlock(&fc->lock);
 		req->out.h.error = -EIO;
 	} else {
-		struct fuse_iqueue *fiq = &fc->iq;
-
 		req->in.h.unique = fuse_get_unique(fiq);
 		queue_request(fiq, req);
 		/* acquire extra reference, since request is still needed
@@ -549,7 +549,7 @@  static int fuse_request_send_notify_reply(struct fuse_conn *fc,
 	__clear_bit(FR_ISREPLY, &req->flags);
 	req->in.h.unique = unique;
 	spin_lock(&fc->lock);
-	if (fc->connected) {
+	if (fiq->connected) {
 		queue_request(fiq, req);
 		err = 0;
 	}
@@ -1035,7 +1035,7 @@  __acquires(fc->lock)
 	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue_exclusive(&fiq->waitq, &wait);
-	while (fc->connected && !request_pending(fiq)) {
+	while (fiq->connected && !request_pending(fiq)) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (signal_pending(current))
 			break;
@@ -1225,13 +1225,13 @@  static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
  restart:
 	spin_lock(&fc->lock);
 	err = -EAGAIN;
-	if ((file->f_flags & O_NONBLOCK) && fc->connected &&
+	if ((file->f_flags & O_NONBLOCK) && fiq->connected &&
 	    !request_pending(fiq))
 		goto err_unlock;
 
 	request_wait(fc);
 	err = -ENODEV;
-	if (!fc->connected)
+	if (!fiq->connected)
 		goto err_unlock;
 	err = -ERESTARTSYS;
 	if (!request_pending(fiq))
@@ -2049,7 +2049,7 @@  static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
 	poll_wait(file, &fiq->waitq, wait);
 
 	spin_lock(&fc->lock);
-	if (!fc->connected)
+	if (!fiq->connected)
 		mask = POLLERR;
 	else if (request_pending(fiq))
 		mask |= POLLIN | POLLRDNORM;
@@ -2122,6 +2122,7 @@  void fuse_abort_conn(struct fuse_conn *fc)
 		LIST_HEAD(to_end2);
 
 		fc->connected = 0;
+		fiq->connected = 0;
 		fc->blocked = 0;
 		fuse_set_initialized(fc);
 		list_for_each_entry_safe(req, next, &fc->io, list) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 9325be6..0892108 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -408,6 +408,9 @@  struct fuse_req {
 };
 
 struct fuse_iqueue {
+	/** Connection established */
+	unsigned connected;
+
 	/** Readers of the connection are waiting on this */
 	wait_queue_head_t waitq;
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 9a57541..446d2e1 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -694,6 +694,7 @@  static void fuse_iqueue_init(struct fuse_iqueue *fiq)
 	INIT_LIST_HEAD(&fiq->pending);
 	INIT_LIST_HEAD(&fiq->interrupts);
 	fiq->forget_list_tail = &fiq->forget_list_head;
+	fiq->connected = 1;
 }
 
 void fuse_conn_init(struct fuse_conn *fc)
@@ -718,6 +719,7 @@  void fuse_conn_init(struct fuse_conn *fc)
 	fc->polled_files = RB_ROOT;
 	fc->blocked = 0;
 	fc->initialized = 0;
+	fc->connected = 1;
 	fc->attr_version = 1;
 	get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
 }
@@ -1208,7 +1210,6 @@  static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 
 	list_add_tail(&fc->entry, &fuse_conn_list);
 	sb->s_root = root_dentry;
-	fc->connected = 1;
 	file->private_data = fuse_conn_get(fc);
 	mutex_unlock(&fuse_mutex);
 	/*