fuse: req use bitops
authorMiklos Szeredi <mszeredi@suse.cz>
Wed, 1 Jul 2015 14:25:58 +0000 (16:25 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Wed, 1 Jul 2015 14:25:58 +0000 (16:25 +0200)
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@suse.cz>
Reviewed-by: Ashish Samant <ashish.samant@oracle.com>
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index 3b979abb7b54cd5de5907692409bb06968a8f2d2..dcfef5475ada73813abb21dfacc2d6fecea49862 100644 (file)
@@ -181,8 +181,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:
@@ -272,15 +274,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
@@ -291,9 +293,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)
@@ -385,9 +387,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;
 
@@ -442,12 +443,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)) {
                sigset_t oldset;
 
                /* Only fatal signals may interrupt this */
@@ -478,7 +479,7 @@ __acquires(fc->lock)
 
 static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
 {
-       BUG_ON(req->background);
+       BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
        spin_lock(&fc->lock);
        if (!fc->connected)
                req->out.h.error = -ENOTCONN;
@@ -496,9 +497,9 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
 
 void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
 {
-       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);
@@ -578,12 +579,12 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args)
 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;
@@ -617,7 +618,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) {
@@ -644,7 +645,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);
        /* ignore errors */
        fuse_put_request(fc, req);
@@ -660,10 +661,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;
@@ -678,10 +679,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;
@@ -902,7 +903,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;
@@ -1309,7 +1310,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;
@@ -1319,12 +1320,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);
        }
@@ -1921,7 +1922,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;
@@ -1931,7 +1932,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)
@@ -2097,8 +2098,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)) {
index 5ef05b5c4cff86e9353a0594f0faadc1ab8612f5..bf272263c1a27edd3feb3aeea86571f7aa726c04 100644 (file)
@@ -96,17 +96,17 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
                         * Drop the release request when client does not
                         * implement 'open'
                         */
-                       req->background = 0;
+                       __clear_bit(FR_BACKGROUND, &req->flags);
                        iput(req->misc.release.inode);
                        fuse_put_request(ff->fc, req);
                } else if (sync) {
-                       req->background = 0;
+                       __clear_bit(FR_BACKGROUND, &req->flags);
                        fuse_request_send(ff->fc, req);
                        iput(req->misc.release.inode);
                        fuse_put_request(ff->fc, req);
                } else {
                        req->end = fuse_release_end;
-                       req->background = 1;
+                       __set_bit(FR_BACKGROUND, &req->flags);
                        fuse_request_send_background(ff->fc, req);
                }
                kfree(ff);
@@ -299,8 +299,8 @@ void fuse_sync_release(struct fuse_file *ff, int flags)
 {
        WARN_ON(atomic_read(&ff->count) > 1);
        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);
@@ -426,7 +426,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);
@@ -1611,7 +1611,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;
@@ -1830,7 +1831,7 @@ static int fuse_writepages_fill(struct page *page,
                req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
                req->misc.write.next = NULL;
                req->in.argpages = 1;
-               req->background = 1;
+               __set_bit(FR_BACKGROUND, &req->flags);
                req->num_pages = 0;
                req->end = fuse_writepage_end;
                req->inode = inode;
index 7354dc142a50845a62e9a413d82d185afc1f5b0d..4503e995c7b2a59ef3a43a1d314fe5f841af2b38 100644 (file)
@@ -266,6 +266,27 @@ struct fuse_io_priv {
        struct completion *done;
 };
 
+/**
+ * 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
  */
@@ -283,32 +304,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;
 
        /** State of the request */
        enum fuse_req_state state;
index cec8abbe2c8c8a6de446e4abdf6c66815f6292d2..f7c9b7225ec51a232602e12a65107225f9c398b2 100644 (file)
@@ -362,8 +362,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);
        }
@@ -1060,7 +1060,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->destroy_req = fuse_request_alloc(0);