Skip to content

Commit

Permalink
fuse: req state use flags
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Miklos Szeredi committed Jul 1, 2015
1 parent 7a3b2c7 commit 33e14b4
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 21 deletions.
23 changes: 14 additions & 9 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand All @@ -438,15 +441,15 @@ 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)
return;

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);
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 6 additions & 11 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -283,6 +278,9 @@ enum fuse_req_flag {
FR_ABORTED,
FR_INTERRUPTED,
FR_LOCKED,
FR_PENDING,
FR_SENT,
FR_FINISHED,
};

/**
Expand All @@ -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;

Expand Down

0 comments on commit 33e14b4

Please sign in to comment.