On Tue, Aug 25, 2026 at 09:37:34AM +1000, NeilBrown wrote:
quoted
For readahead, I think that queues / lru are not involved. We submit the I/O,
and once the I/O is done, we unlock the folio from interrupt context.
"submit the I/O" means "attach the page to a "struct bio" (or similar)
and attach the struct bio to a transmit queue for the device (or
similar). So there really is a queue.
quoted
end_buffer_async_read() / iomap_finish_folio_read() end up calling
folio_end_read(), where we do the magic
folio_wake_bit(folio, PG_locked);
Exactly where the lock ownership should be reclaimed is not immediately
clear to me. bio_endio() might be early enough but there are probably
better points.
A small difficulty here is that a bio has multiple folios and they are
all locked. I cannot see that lockdep has a concept of holding an
arbitrarily large set of related locks.
We could just tell lockdep
"I have some folios locked"
or maybe enhance lockdep to allow
"I have N folios locked"
or even
"I have N folios in address-space A with the highest offset being O".
This would allow lockdep to check the validity of locking another folio
- only allowed if the address space is the same and the offset is larger
than the previous largest.
It's more complex than that; see my other emails on the subject.
I think we need the ability for lockdep to call a function which says "I
hold this lock, is that lock OK to acquire". But the devil is in the
details.
quoted
It's interesting, that for writeback we never unlock the folio on the I/O path,
but instead have the dedicated page flag to tell us when writeback is complete.
PG_locked and PG_writeback are two different lock-bits with two
different meanings.
When a folio is PG_locked the content is invalid and shouldn't be accessed.
When a folio is in PG_writeback its data is not safe even though
PG_dirty has been cleared (if I remember correctly).
So these are two separate, though related, lock bits that would both
need to be tracked. lockdep would detect how they are related.
Some history ... before we had PG_writeback, we held PG_locked
throughout the writeback process. People argued convincingly that it
was fine to map a page into a process's address space (which requires
PG_locked) while it was being written back. And so PG_locked was
split. Now we take PG_locked at the beginning of the writeback process
and downgrade to PG_writeback at some point.