23.01.2019 16:55, Kirill Tkhai пишет: > On 23.01.2019 14:49, Pavel Butsykin wrote: >> Fuse file with FUSE_S_FAIL_IMMEDIATELY state should not allow to execute new >> requests. But in case of kio requests it doesn't work because the status >> check >> is located behind kio.op->req_send(). To fix this let's move the status check >> before kio.op->req_send(). >> >> Note: We can drop hunk with req->end(fc, req) in __fuse_request_send() >> because >> it was only needed to clenup kio setattr request after >> pcs_kio_setattr_handle(). >> >> Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> > Why is this safe? > > After you move the check out of fc->lock, it becomes racy, and > fuse_invalidate_files() > may become work not as expected.
test_bit is atomic operation. Which type of race do you mean? >> --- >> fs/fuse/dev.c | 40 +++++++++++++++++++++++----------------- >> 1 file changed, 23 insertions(+), 17 deletions(-) >> >> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c >> index dc21886ee55d..dcbed5d4932c 100644 >> --- a/fs/fuse/dev.c >> +++ b/fs/fuse/dev.c >> @@ -538,6 +538,11 @@ static void __fuse_request_send(struct fuse_conn *fc, >> struct fuse_req *req, >> >> BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); >> >> + if (ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state)) { >> + req->out.h.error = -EIO; >> + return; >> + } >> + >> if (fc->kio.op && !fc->kio.op->req_send(fc, req, false, false)) >> return; >> >> @@ -547,11 +552,6 @@ static void __fuse_request_send(struct fuse_conn *fc, >> struct fuse_req *req, >> req->out.h.error = -ENOTCONN; >> if (req->end) >> req->end(fc, req); >> - } else if (ff && test_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state)) { >> - spin_unlock(&fiq->waitq.lock); >> - req->out.h.error = -EIO; >> - if (req->end) >> - req->end(fc, req); >> } else { >> req->in.h.unique = fuse_get_unique(fiq); >> queue_request(fiq, req); >> @@ -627,20 +627,26 @@ void fuse_request_send_background(struct fuse_conn >> *fc, struct fuse_req *req) >> { >> BUG_ON(!req->end); >> >> - if (fc->kio.op && !fc->kio.op->req_send(fc, req, true, false)) >> - return; >> - >> - spin_lock(&fc->lock); >> if (req->page_cache && req->ff && >> test_bit(FUSE_S_FAIL_IMMEDIATELY, &req->ff->ff_state)) { >> - BUG_ON(req->in.h.opcode != FUSE_READ); >> - req->out.h.error = -EIO; >> - __clear_bit(FR_BACKGROUND, &req->flags); >> - __clear_bit(FR_PENDING, &req->flags); >> - list_del_init(&req->list); >> - spin_unlock(&fc->lock); >> - request_end(fc, req); >> - } else if (fc->connected) { >> + BUG_ON(req->in.h.opcode != FUSE_READ); >> + req->out.h.error = -EIO; >> + __clear_bit(FR_BACKGROUND, &req->flags); >> + __clear_bit(FR_PENDING, &req->flags); >> + >> + spin_lock(&fc->lock); >> + list_del_init(&req->list); >> + spin_unlock(&fc->lock); >> + >> + request_end(fc, req); >> + return; >> + } >> + >> + if (fc->kio.op && !fc->kio.op->req_send(fc, req, true, false)) >> + return; >> + >> + spin_lock(&fc->lock); >> + if (fc->connected) { >> fuse_request_send_background_locked(fc, req); >> spin_unlock(&fc->lock); >> } else { >> _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel