Messages in this thread | | | Date | Sun, 31 Jul 2022 23:14:20 +0100 | From | Matthew Wilcox <> | Subject | Re: [PATCH v3 2/2] make buffer_locked provide an acquire semantics |
| |
On Sun, Jul 31, 2022 at 04:43:08PM -0400, Mikulas Patocka wrote: > Let's have a look at this piece of code in __bread_slow: > get_bh(bh); > bh->b_end_io = end_buffer_read_sync; > submit_bh(REQ_OP_READ, 0, bh); > wait_on_buffer(bh); > if (buffer_uptodate(bh)) > return bh; > Neither wait_on_buffer nor buffer_uptodate contain a memory barrier. > Consequently, if someone calls sb_bread and then reads the buffer data, > the read of buffer data may be executed before wait_on_buffer(bh) on > architectures with weak memory ordering and it may return invalid data.
I think we should be consistent between PageUptodate() and buffer_uptodate(). Here's how it's done for pages currently:
static inline bool folio_test_uptodate(struct folio *folio) bool ret = test_bit(PG_uptodate, folio_flags(folio, 0)); /* * Must ensure that the data we read out of the folio is loaded * _after_ we've loaded folio->flags to check the uptodate bit. * We can skip the barrier if the folio is not uptodate, because * we wouldn't be reading anything from it. * * See folio_mark_uptodate() for the other side of the story. */ if (ret) smp_rmb();
return ret;
...
static __always_inline void folio_mark_uptodate(struct folio *folio) /* * Memory barrier must be issued before setting the PG_uptodate bit, * so that all previous stores issued in order to bring the folio * uptodate are actually visible before folio_test_uptodate becomes true. */ smp_wmb(); set_bit(PG_uptodate, folio_flags(folio, 0));
I'm happy for these to also be changed to use acquire/release; no attachment to the current code. But bufferheads & pages should have the same semantics, or we'll be awfully confused.
| |