zfsonlinux/zfs — pull request #552 by etienne-dechamps-o (2012-02-03 12:28:30+00:00)
Title: Fix synchronicity for ZVOLs

`zvol_write()` assumes that the write request must be written to stable storage if `rq_is_sync()` is true. Unfortunately, this assumption is incorrect. Indeed, "sync" does *not* mean what we think it means in the context of the Linux block layer. This is well explained in `linux/fs.h`:

- `WRITE`: A normal async write. Device will be plugged.
- `WRITE_SYNC`: Synchronous write. Identical to `WRITE`, but passes down the hint that someone will be waiting on this IO shortly.
- `WRITE_FLUSH`: Like `WRITE_SYNC` but with preceding cache flush.
- `WRITE_FUA`: Like `WRITE_SYNC` but data is guaranteed to be on non-volatile media on completion.

In other words, `SYNC` does not *mean* that the write must be on stable storage on completion. It just means that someone is waiting on us to complete the write request. Thus triggering a ZIL commit for each SYNC write request on a ZVOL is unnecessary and harmful for performance. To make matters worse, ZVOL users have no way to express that they actually want data to be written to stable storage, which means the ZIL is broken for ZVOLs.

The request for stable storage is expressed by the `FUA` flag, so we must commit the ZIL after the write if the `FUA` flag is set. In addition, we must commit the ZIL before the write if the `FLUSH` flag is set.

Also, we must inform the block layer that we actually support `FLUSH` and `FUA`.

Note: #388 was the original pull request for this, but I made a new one since I seriously messed up the branch by doing unwanted merges. I'll try to be more careful this time.