The following 3-patch series performs conversion of read and write methods of block drivers into bdrv_rw_vector with additional is_write argument.
Current I/O request path is twisted so much that it becomes very difficult to follow. A read or write request goes from common io routine to individual read or write, back to common on the next layer, again to individual read or write, and so on. The idea is to have common path as long as reads are not differ from writes much (or at all), and split them into individual routines when they actually become different. So one result of this change is that in some drivers, we now have tiny multiplexors which calls one or another routine based on is_write argument. These are mostly old drivers, and also drivers which have to deal with metadata. There's no multiplexors all over the path anymore. A side effect of this change is removal of quite some duplication, and combining several very similar code paths together. Probably the most interestig and questionable place is the 3rd patch, in block.c, where I combined 3 routines into one. I like the result better than 3 separate routines, especially because before this change, the fill_zeroes path was too twisted. While at it, the change fixes a bug - current block layer can derererence NULL pointers at will -- in case when only read bdrv function is provided but no write (or the reverse), block layer does not check if the pointer is NULL and calls it anyway. I moved the checks into individual block drivers. Please note that this is just an RFC. I run-tested (it compiles on each step) only few drivers and only ensured basic operation (it boots a windows guest and performs some i/o). My motivation initially was to verify my understanding of the block layer, but once I hit the twisted nature of it I thought I may fix this while at that, too. Thanks, /mjt