fuse: req state use flags
authorMiklos Szeredi <mszeredi@suse.cz>
Wed, 1 Jul 2015 14:26:01 +0000 (16:26 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Wed, 1 Jul 2015 14:26:01 +0000 (16:26 +0200)
Use flags for representing the state in fuse_req.  This is needed since
req->list will be protected by different locks in different states, hence
we'll want the state itself to be split into distinct bits, each protected
with the relevant lock in that state.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h

index e5c541b7c7af268ad9ee4c2983e748c59d84d46b..f1e2efd6b1862c1449e4bc4c25fce2ebfc62d87d 100644 (file)
@@ -48,6 +48,7 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages,
        req->pages = pages;
        req->page_descs = page_descs;
        req->max_pages = npages;
+       __set_bit(FR_PENDING, &req->flags);
 }
 
 static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
@@ -380,8 +381,10 @@ __releases(fc->lock)
        req->end = NULL;
        list_del_init(&req->list);
        list_del_init(&req->intr_entry);
+       WARN_ON(test_bit(FR_PENDING, &req->flags));
+       WARN_ON(test_bit(FR_SENT, &req->flags));
        smp_wmb();
-       req->state = FUSE_REQ_FINISHED;
+       set_bit(FR_FINISHED, &req->flags);
        if (test_bit(FR_BACKGROUND, &req->flags)) {
                clear_bit(FR_BACKGROUND, &req->flags);
                if (fc->num_background == fc->max_background)
@@ -421,13 +424,13 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
        if (!fc->no_interrupt) {
                /* Any signal may interrupt this */
                err = wait_event_interruptible(req->waitq,
-                                       req->state == FUSE_REQ_FINISHED);
+                                       test_bit(FR_FINISHED, &req->flags));
                if (!err)
                        return;
 
                spin_lock(&fc->lock);
                set_bit(FR_INTERRUPTED, &req->flags);
-               if (req->state == FUSE_REQ_SENT)
+               if (test_bit(FR_SENT, &req->flags))
                        queue_interrupt(fc, req);
                spin_unlock(&fc->lock);
        }
@@ -438,7 +441,7 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
                /* Only fatal signals may interrupt this */
                block_sigs(&oldset);
                err = wait_event_interruptible(req->waitq,
-                                       req->state == FUSE_REQ_FINISHED);
+                                       test_bit(FR_FINISHED, &req->flags));
                restore_sigs(&oldset);
 
                if (!err)
@@ -446,7 +449,7 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
 
                spin_lock(&fc->lock);
                /* Request is not yet in userspace, bail out */
-               if (req->state == FUSE_REQ_PENDING) {
+               if (test_bit(FR_PENDING, &req->flags)) {
                        list_del(&req->list);
                        spin_unlock(&fc->lock);
                        __fuse_put_request(req);
@@ -460,7 +463,7 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
         * Either request is already in userspace, or it was forced.
         * Wait it out.
         */
-       wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
+       wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags));
 }
 
 static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
@@ -1273,7 +1276,7 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
        }
 
        req = list_entry(fc->pending.next, struct fuse_req, list);
-       req->state = FUSE_REQ_IO;
+       clear_bit(FR_PENDING, &req->flags);
        list_move(&req->list, &fc->io);
 
        in = &req->in;
@@ -1308,7 +1311,7 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
        if (!test_bit(FR_ISREPLY, &req->flags)) {
                request_end(fc, req);
        } else {
-               req->state = FUSE_REQ_SENT;
+               set_bit(FR_SENT, &req->flags);
                list_move_tail(&req->list, &fc->processing);
                if (test_bit(FR_INTERRUPTED, &req->flags))
                        queue_interrupt(fc, req);
@@ -1904,7 +1907,7 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc,
                return nbytes;
        }
 
-       req->state = FUSE_REQ_IO;
+       clear_bit(FR_SENT, &req->flags);
        list_move(&req->list, &fc->io);
        req->out.h = oh;
        set_bit(FR_LOCKED, &req->flags);
@@ -2059,6 +2062,8 @@ __acquires(fc->lock)
                struct fuse_req *req;
                req = list_entry(head->next, struct fuse_req, list);
                req->out.h.error = -ECONNABORTED;
+               clear_bit(FR_PENDING, &req->flags);
+               clear_bit(FR_SENT, &req->flags);
                request_end(fc, req);
                spin_lock(&fc->lock);
        }
index d0c23d075427f2eeaf00625778bd2310ea5a04af..64835cf589363efa283550ab465faec6bf98fd22 100644 (file)
@@ -1743,7 +1743,7 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
                }
        }
 
-       if (old_req->num_pages == 1 && old_req->state == FUSE_REQ_PENDING) {
+       if (old_req->num_pages == 1 && test_bit(FR_PENDING, &old_req->flags)) {
                struct backing_dev_info *bdi = inode_to_bdi(page->mapping->host);
 
                copy_highpage(old_req->pages[0], page);
index 3fd65f613515fa2927ab71e699e811fb2ca7c5e8..8eaf3b0de033792ef5db0d159ba5bff4251bd47a 100644 (file)
@@ -241,14 +241,6 @@ struct fuse_args {
 
 #define FUSE_ARGS(args) struct fuse_args args = {}
 
-/** The request state */
-enum fuse_req_state {
-       FUSE_REQ_PENDING = 0,
-       FUSE_REQ_IO,
-       FUSE_REQ_SENT,
-       FUSE_REQ_FINISHED
-};
-
 /** The request IO state (for asynchronous processing) */
 struct fuse_io_priv {
        int async;
@@ -274,6 +266,9 @@ struct fuse_io_priv {
  * FR_ABORTED:         the request was aborted
  * FR_INTERRUPTED:     the request has been interrupted
  * FR_LOCKED:          data is being copied to/from the request
+ * FR_PENDING:         request is not yet in userspace
+ * FR_SENT:            request is in userspace, waiting for an answer
+ * FR_FINISHED:                request is finished
  */
 enum fuse_req_flag {
        FR_ISREPLY,
@@ -283,6 +278,9 @@ enum fuse_req_flag {
        FR_ABORTED,
        FR_INTERRUPTED,
        FR_LOCKED,
+       FR_PENDING,
+       FR_SENT,
+       FR_FINISHED,
 };
 
 /**
@@ -309,9 +307,6 @@ struct fuse_req {
        /* Request flags, updated with test/set/clear_bit() */
        unsigned long flags;
 
-       /** State of the request */
-       enum fuse_req_state state;
-
        /** The request input */
        struct fuse_in in;