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

Reply via email to