Yet another async I/O issue: block devices

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Mon Nov 12 04:02:01 CST 2001


Hi,

I just discovered yet another problem that arises for overlapped
I/O on normal disk files, more correctly, for any file on a block device.

Obviously IO requests on block devices on Linux are _always blocking_.
I wrote a very simple test program for reading from a floppy disk and
found exactly this behaviour, no matter if O_NONBLOCK was set or not.
"man 2 open" also says that O_NONBLOCK may or may not have any effect on
non-socket fd's and for block devices it clearly has none.

I don't know the reason for this, but it may have to do with Linux'
caching algorithms. This means that

- with ReadFile() etc.  on regular files, the asynch code will never be
  executed. Instead, the call will block when trying to read
  immediately, and then return success.

- I am not 100% sure in what context the asynchronous handlers are
  executed, but the read() write() calls there will be blocking as well.
  I assume this is not what we want.

- I guess that for programs that "know" some IO is going to take a
  lot of time (read()s on floppies, network file systems, ...) will
  potentially be broken if they try to do overlapped IO and "do something
  else" while the IO is executing. I do see the need, therefore, to
  have an approach that mimics Windows' behaviour here.

- The only simple approach that I can see for making this happen is
  creating a separate thread for reading/writing asynchronous IO.
  The simplest approach would actually be to do a clone() for each async
  request with CLONE_FILES | CLONE_VM | CLONE_PARENT.
  I don't know how this would fit into Wine's general synchronization
  approach - please give me hints.

- The separate thread itself would be very simple for files on block
  devices, because it can simply execute the blocking read and finish when
  the read finishes, leaving some status information somewhere.

- For other devices that _do_ support O_NONBLOCK, it may be cool to mimic
  this simple behaviour by clone()ing too, dup() ing the fd, resetting
  the O_NONBLOCK flag, and doing a blocking IO request just the same.
  That means to basically leave it up to the kernel to handle
  synchronization.

  This would also mean that we wouldn't have to worry about differences
  between files and sockets/pipes, because I'm 99% sure the kernel would
  do it right.

I don't understand the concept of the wine service thread well enough yet
to judge if that could be used for doing what I just suggested. Perhaps
someone can help me out with that, I'll be studying the sources in the
meantime.

Cheers,
Martin

PS. I guess another possible approach would be using raw I/O, but I am
    very certain this is not what we want.

-- 
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:Martin.Wilck at Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy









More information about the wine-devel mailing list