[Devel] [PATCH vz7 10/46] fuse: req use bitops

Maxim Patlasov mpatlasov at virtuozzo.com
Fri Mar 24 19:15:32 PDT 2017


Backport from ml:

commit 825d6d3395e88a616e4c953984d77eeacbad4310
Author: Miklos Szeredi <mszeredi at suse.cz>
Date:   Wed Jul 1 16:25:58 2015 +0200

    fuse: req use bitops

    Finer grained locking will mean there's no single lock to protect
    modification of bitfileds in fuse_req.

    So move to using bitops.  Can use the non-atomic variants for those which
    happen while the request definitely has only one reference.

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

Signed-off-by: Maxim Patlasov <mpatlasov at virtuozzo.com>
---
 fs/fuse/control.c |   14 +++++-----
 fs/fuse/dev.c     |   73 +++++++++++++++++++++++++++--------------------------
 fs/fuse/file.c    |   15 ++++++-----
 fs/fuse/fuse_i.h  |   49 +++++++++++++++++-------------------
 fs/fuse/inode.c   |    6 ++--
 5 files changed, 78 insertions(+), 79 deletions(-)

diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 8a686bd..6afa384 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -237,13 +237,13 @@ static int fuse_req_show(struct seq_file *f, void *v)
 			"in: op %-4d uniq 0x%016Lx node 0x%016Lx "
 			"out: err %-6d uniq 0x%016Lx\n",
 			req->state,
-			req->isreply ? 'r' : '-',
-			req->force ? 'f' : '-',
-			req->aborted ? 'a' : '-',
-			req->background ? 'b' : '-',
-			req->interrupted ? 'i' : '-',
-			req->locked ? 'l' : '-',
-			req->waiting ? 'w': '-',
+			test_bit(FR_ISREPLY, &req->flags) ? 'r' : '-',
+			test_bit(FR_FORCE, &req->flags) ? 'f' : '-',
+			test_bit(FR_ABORTED, &req->flags) ? 'a' : '-',
+			test_bit(FR_BACKGROUND, &req->flags) ? 'b' : '-',
+			test_bit(FR_INTERRUPTED, &req->flags) ? 'i' : '-',
+			test_bit(FR_LOCKED, &req->flags) ? 'l' : '-',
+			test_bit(FR_WAITING, &req->flags) ? 'w': '-',
 			req->in.h.opcode,
 			req->in.h.unique,
 			req->in.h.nodeid,
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 66ea344..29931bd 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -164,8 +164,10 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
 	}
 
 	fuse_req_init_context(req);
-	req->waiting = 1;
-	req->background = for_background;
+	__set_bit(FR_WAITING, &req->flags);
+	if (for_background)
+		__set_bit(FR_BACKGROUND, &req->flags);
+
 	return req;
 
  out:
@@ -255,15 +257,15 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
 		req = get_reserved_req(fc, file);
 
 	fuse_req_init_context(req);
-	req->waiting = 1;
-	req->background = 0;
+	__set_bit(FR_WAITING, &req->flags);
+	__clear_bit(FR_BACKGROUND, &req->flags);
 	return req;
 }
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
 	if (atomic_dec_and_test(&req->count)) {
-		if (unlikely(req->background)) {
+		if (test_bit(FR_BACKGROUND, &req->flags)) {
 			/*
 			 * We get here in the unlikely case that a background
 			 * request was allocated but not sent
@@ -274,9 +276,9 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 			spin_unlock(&fc->lock);
 		}
 
-		if (req->waiting) {
+		if (test_bit(FR_WAITING, &req->flags)) {
+			__clear_bit(FR_WAITING, &req->flags);
 			atomic_dec(&fc->num_waiting);
-			req->waiting = 0;
 		}
 
 		if (req->stolen_file)
@@ -368,9 +370,8 @@ __releases(fc->lock)
 	list_del_init(&req->list);
 	list_del_init(&req->intr_entry);
 	req->state = FUSE_REQ_FINISHED;
-	if (req->background) {
-		req->background = 0;
-
+	if (test_bit(FR_BACKGROUND, &req->flags)) {
+		clear_bit(FR_BACKGROUND, &req->flags);
 		if (fc->num_background == fc->max_background)
 			fc->blocked = 0;
 
@@ -438,12 +439,12 @@ __acquires(fc->lock)
 		if (req->state == FUSE_REQ_FINISHED)
 			return;
 
-		req->interrupted = 1;
+		set_bit(FR_INTERRUPTED, &req->flags);
 		if (req->state == FUSE_REQ_SENT)
 			queue_interrupt(fc, req);
 	}
 
-	if (!req->force) {
+	if (!test_bit(FR_FORCE, &req->flags)) {
 		/* Only fatal signals may interrupt this */
 		wait_answer_killable(fc, req);
 
@@ -471,7 +472,7 @@ __acquires(fc->lock)
 static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req,
 				struct fuse_file *ff)
 {
-	BUG_ON(req->background);
+	BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
 	spin_lock(&fc->lock);
 	if (!fc->connected)
 		req->out.h.error = -ENOTCONN;
@@ -492,9 +493,9 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req,
 void fuse_request_check_and_send(struct fuse_conn *fc, struct fuse_req *req,
 				 struct fuse_file *ff)
 {
-	req->isreply = 1;
-	if (!req->waiting) {
-		req->waiting = 1;
+	__set_bit(FR_ISREPLY, &req->flags);
+	if (!test_bit(FR_WAITING, &req->flags)) {
+		__set_bit(FR_WAITING, &req->flags);
 		atomic_inc(&fc->num_waiting);
 	}
 	__fuse_request_send(fc, req, ff);
@@ -514,12 +515,12 @@ EXPORT_SYMBOL_GPL(fuse_request_send);
 void fuse_request_send_background_locked(struct fuse_conn *fc,
 					 struct fuse_req *req)
 {
-	BUG_ON(!req->background);
-	if (!req->waiting) {
-		req->waiting = 1;
+	BUG_ON(!test_bit(FR_BACKGROUND, &req->flags));
+	if (!test_bit(FR_WAITING, &req->flags)) {
+		__set_bit(FR_WAITING, &req->flags);
 		atomic_inc(&fc->num_waiting);
 	}
-	req->isreply = 1;
+	__set_bit(FR_ISREPLY, &req->flags);
 	fc->num_background++;
 	if (fc->num_background == fc->max_background)
 		fc->blocked = 1;
@@ -540,7 +541,7 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
 	    test_bit(FUSE_S_FAIL_IMMEDIATELY, &req->ff->ff_state)) {
 		BUG_ON(req->in.h.opcode != FUSE_READ);
 		req->out.h.error = -EIO;
-		req->background = 0;
+		__clear_bit(FR_BACKGROUND, &req->flags);
 		request_end(fc, req);
 	} else if (fc->connected) {
 		fuse_request_send_background_locked(fc, req);
@@ -559,7 +560,7 @@ static int fuse_request_send_notify_reply(struct fuse_conn *fc,
 {
 	int err = -ENODEV;
 
-	req->isreply = 0;
+	__clear_bit(FR_ISREPLY, &req->flags);
 	req->in.h.unique = unique;
 	spin_lock(&fc->lock);
 	if (fc->connected) {
@@ -586,7 +587,7 @@ void fuse_force_forget(struct file *file, u64 nodeid)
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
-	req->isreply = 0;
+	__clear_bit(FR_ISREPLY, &req->flags);
 	__fuse_request_send(fc, req, NULL);
 	/* ignore errors */
 	fuse_put_request(fc, req);
@@ -602,10 +603,10 @@ static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
 	int err = 0;
 	if (req) {
 		spin_lock(&fc->lock);
-		if (req->aborted)
+		if (test_bit(FR_ABORTED, &req->flags))
 			err = -ENOENT;
 		else
-			req->locked = 1;
+			set_bit(FR_LOCKED, &req->flags);
 		spin_unlock(&fc->lock);
 	}
 	return err;
@@ -620,10 +621,10 @@ static int unlock_request(struct fuse_conn *fc, struct fuse_req *req)
 	int err = 0;
 	if (req) {
 		spin_lock(&fc->lock);
-		if (req->aborted)
+		if (test_bit(FR_ABORTED, &req->flags))
 			err = -ENOENT;
 		else
-			req->locked = 0;
+			clear_bit(FR_LOCKED, &req->flags);
 		spin_unlock(&fc->lock);
 	}
 	return err;
@@ -857,7 +858,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 
 	err = 0;
 	spin_lock(&cs->fc->lock);
-	if (cs->req->aborted)
+	if (test_bit(FR_ABORTED, &cs->req->flags))
 		err = -ENOENT;
 	else
 		*pagep = newpage;
@@ -1284,7 +1285,7 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
 				     (struct fuse_arg *) in->args, 0);
 	fuse_copy_finish(cs);
 	spin_lock(&fc->lock);
-	req->locked = 0;
+	clear_bit(FR_LOCKED, &req->flags);
 	if (!fc->connected) {
 		request_end(fc, req);
 		return -ENODEV;
@@ -1294,12 +1295,12 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
 		request_end(fc, req);
 		return err;
 	}
-	if (!req->isreply)
+	if (!test_bit(FR_ISREPLY, &req->flags)) {
 		request_end(fc, req);
-	else {
+	} else {
 		req->state = FUSE_REQ_SENT;
 		list_move_tail(&req->list, &fc->processing);
-		if (req->interrupted)
+		if (test_bit(FR_INTERRUPTED, &req->flags))
 			queue_interrupt(fc, req);
 		spin_unlock(&fc->lock);
 	}
@@ -1930,7 +1931,7 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc,
 	req->state = FUSE_REQ_WRITING;
 	list_move(&req->list, &fc->io);
 	req->out.h = oh;
-	req->locked = 1;
+	set_bit(FR_LOCKED, &req->flags);
 	cs->req = req;
 	if (!req->out.page_replace)
 		cs->move_pages = 0;
@@ -1940,7 +1941,7 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc,
 	fuse_copy_finish(cs);
 
 	spin_lock(&fc->lock);
-	req->locked = 0;
+	clear_bit(FR_LOCKED, &req->flags);
 	if (!fc->connected)
 		err = -ENOENT;
 	else if (err)
@@ -2103,8 +2104,8 @@ __acquires(fc->lock)
 
 	list_for_each_entry_safe(req, next, &fc->io, list) {
 		req->out.h.error = -ECONNABORTED;
-		req->aborted = 1;
-		if (!req->locked)
+		set_bit(FR_ABORTED, &req->flags);
+		if (!test_bit(FR_LOCKED, &req->flags))
 			list_move(&req->list, &to_end);
 	}
 	while (!list_empty(&to_end)) {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 41ed6f0..503e35c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -160,7 +160,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
 		struct fuse_req *req = ff->reserved_req;
 
 		if (sync) {
-			req->background = 0;
+			__clear_bit(FR_BACKGROUND, &req->flags);
 			fuse_request_send(ff->fc, req);
 			if (req->out.h.error == -EINTR) {
 				req->state = FUSE_REQ_INIT;
@@ -174,7 +174,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
 async_fallback:
 			fuse_file_list_del(ff);
 			req->end = fuse_release_end;
-			req->background = 1;
+			__set_bit(FR_BACKGROUND, &req->flags);
 			fuse_request_send_background(ff->fc, req);
 		}
 		kfree(ff);
@@ -466,8 +466,8 @@ void fuse_sync_release(struct fuse_file *ff, int flags)
 	WARN_ON(atomic_read(&ff->count) > 1);
 	fuse_file_list_del(ff);
 	fuse_prepare_release(ff, flags, FUSE_RELEASE);
-	ff->reserved_req->force = 1;
-	ff->reserved_req->background = 0;
+	__set_bit(FR_FORCE, &ff->reserved_req->flags);
+	__clear_bit(FR_BACKGROUND, &ff->reserved_req->flags);
 	fuse_request_send(ff->fc, ff->reserved_req);
 	fuse_put_request(ff->fc, ff->reserved_req);
 	kfree(ff);
@@ -637,7 +637,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
-	req->force = 1;
+	__set_bit(FR_FORCE, &req->flags);
 	fuse_request_send(fc, req);
 	err = req->out.h.error;
 	fuse_put_request(fc, req);
@@ -2007,7 +2007,8 @@ static int fuse_writepage_locked(struct page *page,
 	if (!req)
 		goto err;
 
-	req->background = 1; /* writeback always goes to bg_queue */
+	/* writeback always goes to bg_queue */
+	__set_bit(FR_BACKGROUND, &req->flags);
 	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
 	if (!tmp_page)
 		goto err_free;
@@ -2157,7 +2158,7 @@ static int fuse_send_writepages(struct fuse_fill_data *data)
 
 	req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
 	req->in.argpages = 1;
-	req->background = 1;
+	__set_bit(FR_BACKGROUND, &req->flags);
 	fuse_page_descs_length_init(req, 0, req->num_pages);
 	req->end = fuse_writepage_end;
 
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 09aab7e..31062a0 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -284,6 +284,27 @@ struct fuse_io_priv {
 };
 
 /**
+ * Request flags
+ *
+ * FR_ISREPLY:		set if the request has reply
+ * FR_FORCE:		force sending of the request even if interrupted
+ * FR_BACKGROUND:	request is sent in the background
+ * FR_WAITING:		request is counted as "waiting"
+ * FR_ABORTED:		the request was aborted
+ * FR_INTERRUPTED:	the request has been interrupted
+ * FR_LOCKED:		data is being copied to/from the request
+ */
+enum fuse_req_flag {
+	FR_ISREPLY,
+	FR_FORCE,
+	FR_BACKGROUND,
+	FR_WAITING,
+	FR_ABORTED,
+	FR_INTERRUPTED,
+	FR_LOCKED,
+};
+
+/**
  * A request to the client
  */
 struct fuse_req {
@@ -300,32 +321,8 @@ struct fuse_req {
 	/** Unique ID for the interrupt request */
 	u64 intr_unique;
 
-	/*
-	 * The following bitfields are either set once before the
-	 * request is queued or setting/clearing them is protected by
-	 * fuse_conn->lock
-	 */
-
-	/** True if the request has reply */
-	unsigned isreply:1;
-
-	/** Force sending of the request even if interrupted */
-	unsigned force:1;
-
-	/** The request was aborted */
-	unsigned aborted:1;
-
-	/** Request is sent in the background */
-	unsigned background:1;
-
-	/** The request has been interrupted */
-	unsigned interrupted:1;
-
-	/** Data is being copied to/from the request */
-	unsigned locked:1;
-
-	/** Request is counted as "waiting" */
-	unsigned waiting:1;
+	/* Request flags, updated with test/set/clear_bit() */
+	unsigned long flags;
 
 	/** Request contains pages from page-cache */
 	unsigned page_cache:1;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 9bd2490..fbd6d38 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -449,8 +449,8 @@ static void fuse_send_destroy(struct fuse_conn *fc)
 	if (req && fc->conn_init) {
 		fc->destroy_req = NULL;
 		req->in.h.opcode = FUSE_DESTROY;
-		req->force = 1;
-		req->background = 0;
+		__set_bit(FR_FORCE, &req->flags);
+		__clear_bit(FR_BACKGROUND, &req->flags);
 		fuse_request_send(fc, req);
 		fuse_put_request(fc, req);
 	}
@@ -1199,7 +1199,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 	init_req = fuse_request_alloc(0);
 	if (!init_req)
 		goto err_put_root;
-	init_req->background = 1;
+	__set_bit(FR_BACKGROUND, &init_req->flags);
 
 	if (is_bdev || (fc->flags & FUSE_UMOUNT_WAIT)) {
 		fc->destroy_req = fuse_request_alloc(0);



More information about the Devel mailing list