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 | 365ae710df91edc97d24817e3271e01bffaaee32 (patch) | |
tree | 3e535e7168b57fc310119e29947d2281ed60f484 | |
parent | 77cd9d488b32d19be852ad4d310ef13701557d61 (diff) |
fuse: request_end(): do once
When the connection is aborted it is possible that request_end() will be
called twice. Use atomic test and set to do the actual ending only once.
test_and_set_bit() also provides the necessary barrier semantics so no
explicit smp_wmb() is necessary.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reviewed-by: Ashish Samant <ashish.samant@oracle.com>
-rw-r--r-- | fs/fuse/dev.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7f37e55edc0e..cd242fc6a92b 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -384,14 +384,18 @@ __releases(fc->lock) | |||
384 | { | 384 | { |
385 | struct fuse_iqueue *fiq = &fc->iq; | 385 | struct fuse_iqueue *fiq = &fc->iq; |
386 | void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; | 386 | void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; |
387 | |||
388 | if (test_and_set_bit(FR_FINISHED, &req->flags)) { | ||
389 | spin_unlock(&fc->lock); | ||
390 | return; | ||
391 | } | ||
392 | |||
387 | req->end = NULL; | 393 | req->end = NULL; |
388 | spin_lock(&fiq->waitq.lock); | 394 | spin_lock(&fiq->waitq.lock); |
389 | list_del_init(&req->intr_entry); | 395 | list_del_init(&req->intr_entry); |
390 | spin_unlock(&fiq->waitq.lock); | 396 | spin_unlock(&fiq->waitq.lock); |
391 | WARN_ON(test_bit(FR_PENDING, &req->flags)); | 397 | WARN_ON(test_bit(FR_PENDING, &req->flags)); |
392 | WARN_ON(test_bit(FR_SENT, &req->flags)); | 398 | WARN_ON(test_bit(FR_SENT, &req->flags)); |
393 | smp_wmb(); | ||
394 | set_bit(FR_FINISHED, &req->flags); | ||
395 | if (test_bit(FR_BACKGROUND, &req->flags)) { | 399 | if (test_bit(FR_BACKGROUND, &req->flags)) { |
396 | clear_bit(FR_BACKGROUND, &req->flags); | 400 | clear_bit(FR_BACKGROUND, &req->flags); |
397 | if (fc->num_background == fc->max_background) | 401 | if (fc->num_background == fc->max_background) |