Also, I think you misunderstood the blog as it's describing application read-ahead which is what you have to do when using O_DIRECT.
I implement read-ahead in the application by (optionally) preadv:ing a single read into multiple destination buffers in the pool, leaving them unpinned, since as long as you aren't up against the bandwidth limit of the drive, a larger read is generally as fast as multiple smaller one on modern hardware.
I've tried doing this with io_uring as well, but found just eating the preadv syscall cost was faster.
[1] Mandatory mmap=poop-emoji link: https://db.cs.cmu.edu/mmap-cidr2022/