|
From: Miklos S. <mi...@sz...> - 2011-10-25 13:10:11
|
Michael Berlin <mic...@go...> writes:
> Hi Miklos,
>
> Thank you very much for your answer.
>
>>> Are you aware of any other projects which use the Fuse interruption
>>> support? So far I could not find a popular example where I could verify
>>> my findings. Therefore, I also included instructions how to reproduce
>>> the error for further debugging using our XtreemFS client at the end of
>>> this mail.
>>
>> I'm not aware of any project using interrupts.
>
> That's surprising. What did you use to test the interruption code? :)
A modified fusexmp_fh. That's usually my test platform.
>>> What about interruption of read ahead in Fuse in general? Are interrupt
>>> requests sent to the Fuse library for every pending read()? From the
>>> current experiences I guess that's not the case.
>>
>> You are correct, not all interrupt of read(2) will reach the library.
>> And the cause is indeed read-ahead or read by an unrelated process.
>
> What do you mean by an unrelated process?
Say
- process A is doing read of 64k bytes from offset 0
- process B is doing read of 64k bytes from offset 32k
The kernel for example will issue the following read request (the exact
sequence might not be this, but it doesn't matter):
a) READ 32k from 0
b) READ 32k from 32k
c) READ 32k from 64k
Lets assume that currently b) is being serviced and process A is
interrupted. What should now happen?
>> Have you tried the 'direct_io' option? That should help, but it has
>> side effects (no caching, no mmap, ...). It depends on your case
>> whether you prefer to do 'direct_io' or not.
>
> Yes, indeed. If direct_io is enabled, it does work. But that's not a
> satisfying solution.
>
> Are there any technical reasons why it should not be possible to
> interrupt read()s if read-ahead is enabled and direct_io disabled?
The technical reason is that there's no 1:1 mapping between read()
system calls and read requests. If a read() syscall is interrupted it
is not known which read request is it that is servicing that syscall.
Another hint: look at where read() syscalls are blocking in the kernel.
It will be on lock_page_killable(). In other words it is waiting for
the page to be in state PageUptodate. Other than the state, the page
doesn't contain any information about how or by whom it is being read.
If the process is killed, then the read will be interrupted (hence the
_killable on the lock_page), but the reader will still not be notified.
>
> I already wrote in my first mail: The Fuse library does receive the
> interrupt request, but the "unique" value of the pending read in
> question is wrong:
>
>>> find_interrupted() in fuse_lowlevel.c fails to find the active read()
>>> request: In particular, the check in line 1005 does not succeed:
>>> if (curr->unique == req->u.i.unique) {
>>> as the value for curr->unique is always off by one (compared to the
>>> value in req->u.i.unique), for instance 293 != 294.
>
> In general, the number seems to be off the by number of pending read
> requests. With two read()s pending, the unique value of the interrupt
> request received by the Fuse library was +2 compared to the unique
> value of the first pending read.
> Also, no multiple interrupt requests were received by the Fuse library
> for every pending read.
> (Sorry about being so unclear about this "unique" stuff - I'm just
> guessing it is a kind of request id?)
Yes, "unique" is the request ID.
> It would be great if this would work and it's possible to interrupt
> read()s, even in presence of read-ahead :-) Do you think it's feasible
> to fix this?
Not as far as I can see. It is not a fuse thing, it's a core kernel
thing. If the filesystem is using the generic cached read functions it
doesn't have a say in what happens on interruption.
Thanks,
Miklos
|