On Mon, Jan 07, 2019 at 03:09:04PM -0800, Andrew Morton wrote: > On Mon, 7 Jan 2019 14:39:35 -0800 Matthew Wilcox <willy@xxxxxxxxxxxxx> wrote: > > > On Mon, Jan 07, 2019 at 02:33:19PM -0800, Andrew Morton wrote: > > > On Mon, 7 Jan 2019 12:02:24 -0800 Matthew Wilcox <willy@xxxxxxxxxxxxx> wrote: > > > > > > > After we establish a reference on the page, we check the pointer continues > > > > to be in the correct position in i_pages. There's no need to check the > > > > page->mapping or page->index afterwards; if those can change after we've > > > > got the reference, they can change after we return the page to the caller. > > > > > > But that isn't what the comment says. > > > > Right. That patch from Nick moved the check from before taking the > > ref to after taking the ref. It was racy to have it before. But it's > > unnecessary to have it afterwards -- pages can't move once there's a > > ref on them. Or if they can move, they can move after the ref is taken. > > So Nick's patch was never necessary? I wonder what inspired it. It was necessary to not check before the pin; that was clearly correct. Checking after the pin, even with the code the way it was in 2006, was unnecessary. Look with a bit more context: - if (page->mapping == NULL || page->index != index) - break; - if (!page_cache_get_speculative(page)) goto repeat; /* Has the page moved? */ if (unlikely(page != *((void **)pages[i]))) { page_cache_release(page); goto repeat; } + /* + * must check mapping and index after taking the ref. + * otherwise we can get both false positives and false + * negatives, which is just confusing to the caller. + */ + if (page->mapping == NULL || page->index != index) { + page_cache_release(page); + break; + } + It's not immediately obvious that those added lines merely re-check the condition checked by the 'page != *((void **)pages[i])', but if you think about it, if page->index changes, then page must necessarily move within the radix tree / xarray. > Would it be excessively cautious to put a WARN_ON_ONCE() in there for a > while? I think it would ... it'd get in the way of a subsequent patch to store only head pages in the page cache.