I looked at your updated patch.
The issue with sound comes from setting mBytesRead = 0 too early (while the async read/write is still in flight).
So adding the "mBytesRead = mBytes; // Success" back, breaks sound again.
The problem/reason for this is in llaudio/llaudiodecodemgr.cpp around line 495:
As you can see, it uses the -1 as a marker for "not yet done" and 0 or more as marker for "done". So if the lllfsthread codes sets the mBytesRead to anything but -1 before the actual async read/write is completed (for a sound), this breaks down and the error handler for sounds kicks in and loading of sounds fails.
That should work for my patch and i see .dsf files created in the cache area properly. I wonder why it doesn't work for you.
Do the completions get collected ( does io_uring_peek_cqe return 0 and populate a cqe? Your patch does "have_work = io_uring_peek_cqe()" which has the logic reversed ).
I had some issues when the LFS thread was set as idle and slept and completions would not get collected in my first tries.
Edit: Missed the (non-cached) part. Will have to check it works properly with a cleaned cache.