diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2015-07-01 10:26:06 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2015-07-01 10:26:06 -0400 |
commit | 77cd9d488b32d19be852ad4d310ef13701557d61 (patch) | |
tree | 2bfe433ce2aaff445860eaf9bd009464ecafa2a3 /fs/fuse | |
parent | 45a91cb1a4fd9bb0e53c95e3dc9185dd5b5ba245 (diff) |
fuse: add req flag for private list
When an unlocked request is aborted, it is moved from fpq->io to a private
list. Then, after unlocking fpq->lock, the private list is processed and
the requests are finished off.
To protect the private list, we need to mark the request with a flag, so if
in the meantime the request is unlocked the list is not corrupted.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reviewed-by: Ashish Samant <ashish.samant@oracle.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dev.c | 10 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 2 |
2 files changed, 9 insertions, 3 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 32e0e74e8f4d..7f37e55edc0e 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -1328,7 +1328,8 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file, | |||
1328 | return reqsize; | 1328 | return reqsize; |
1329 | 1329 | ||
1330 | out_end: | 1330 | out_end: |
1331 | list_del_init(&req->list); | 1331 | if (!test_bit(FR_PRIVATE, &req->flags)) |
1332 | list_del_init(&req->list); | ||
1332 | spin_unlock(&fpq->lock); | 1333 | spin_unlock(&fpq->lock); |
1333 | request_end(fc, req); | 1334 | request_end(fc, req); |
1334 | return err; | 1335 | return err; |
@@ -1945,7 +1946,8 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc, | |||
1945 | err = -ENOENT; | 1946 | err = -ENOENT; |
1946 | else if (err) | 1947 | else if (err) |
1947 | req->out.h.error = -EIO; | 1948 | req->out.h.error = -EIO; |
1948 | list_del_init(&req->list); | 1949 | if (!test_bit(FR_PRIVATE, &req->flags)) |
1950 | list_del_init(&req->list); | ||
1949 | spin_unlock(&fpq->lock); | 1951 | spin_unlock(&fpq->lock); |
1950 | request_end(fc, req); | 1952 | request_end(fc, req); |
1951 | 1953 | ||
@@ -2149,8 +2151,10 @@ void fuse_abort_conn(struct fuse_conn *fc) | |||
2149 | req->out.h.error = -ECONNABORTED; | 2151 | req->out.h.error = -ECONNABORTED; |
2150 | spin_lock(&req->waitq.lock); | 2152 | spin_lock(&req->waitq.lock); |
2151 | set_bit(FR_ABORTED, &req->flags); | 2153 | set_bit(FR_ABORTED, &req->flags); |
2152 | if (!test_bit(FR_LOCKED, &req->flags)) | 2154 | if (!test_bit(FR_LOCKED, &req->flags)) { |
2155 | set_bit(FR_PRIVATE, &req->flags); | ||
2153 | list_move(&req->list, &to_end1); | 2156 | list_move(&req->list, &to_end1); |
2157 | } | ||
2154 | spin_unlock(&req->waitq.lock); | 2158 | spin_unlock(&req->waitq.lock); |
2155 | } | 2159 | } |
2156 | list_splice_init(&fpq->processing, &to_end2); | 2160 | list_splice_init(&fpq->processing, &to_end2); |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index ad3799e57efd..a9507fd97d5e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -269,6 +269,7 @@ struct fuse_io_priv { | |||
269 | * FR_PENDING: request is not yet in userspace | 269 | * FR_PENDING: request is not yet in userspace |
270 | * FR_SENT: request is in userspace, waiting for an answer | 270 | * FR_SENT: request is in userspace, waiting for an answer |
271 | * FR_FINISHED: request is finished | 271 | * FR_FINISHED: request is finished |
272 | * FR_PRIVATE: request is on private list | ||
272 | */ | 273 | */ |
273 | enum fuse_req_flag { | 274 | enum fuse_req_flag { |
274 | FR_ISREPLY, | 275 | FR_ISREPLY, |
@@ -281,6 +282,7 @@ enum fuse_req_flag { | |||
281 | FR_PENDING, | 282 | FR_PENDING, |
282 | FR_SENT, | 283 | FR_SENT, |
283 | FR_FINISHED, | 284 | FR_FINISHED, |
285 | FR_PRIVATE, | ||
284 | }; | 286 | }; |
285 | 287 | ||
286 | /** | 288 | /** |