On Mon, Nov 23, 2020 at 8:07 PM Hugh Dickins <hughd@xxxxxxxxxx> wrote: > > Then on crashing a second time, realized there's a stronger reason against > that approach. If my testing just occasionally crashes on that check, > when the page is reused for part of a compound page, wouldn't it be much > more common for the page to get reused as an order-0 page before reaching > wake_up_page()? And on rare occasions, might that reused page already be > marked PageWriteback by its new user, and already be waited upon? What > would that look like? > > It would look like BUG_ON(PageWriteback) after wait_on_page_writeback() > in write_cache_pages() (though I have never seen that crash myself). So looking more at the patch, I started looking at this part: > + writeback = TestClearPageWriteback(page); > + /* No need for smp_mb__after_atomic() after TestClear */ > + waiters = PageWaiters(page); > + if (waiters) { > + /* > + * Writeback doesn't hold a page reference on its own, relying > + * on truncation to wait for the clearing of PG_writeback. > + * We could safely wake_up_page_bit(page, PG_writeback) here, > + * while holding i_pages lock: but that would be a poor choice > + * if the page is on a long hash chain; so instead choose to > + * get_page+put_page - though atomics will add some overhead. > + */ > + get_page(page); > + } and thinking more about this, my first reaction was "but that has the same race, just a smaller window". And then reading the comment more, I realize you relied on the i_pages lock, and that this odd ordering was to avoid the possible latency. But what about the non-mapping case? I'm not sure how that happens, but this does seem very fragile. I'm wondering why you didn't want to just do the get_page() unconditionally and early. Is avoiding the refcount really such a big optimization? Linus