The Linux block I/O layer is sophisticated with a lot of subtleties, it is not practical to go through the whole layer in a post.

So this is more like a note for me, with minimal explanation. You can check the references below to get started and go back here to see if it helps.

Flowchart

Flowchart

The states are marked with trace actions for blkparse.

References