On Tue, Jun 19, 2018 at 10:16:38AM -0700, Matthew Wilcox wrote: > I think I see a bug. No idea if it's the one you're hitting ;-) > > I had been intending to not use the 'entry' to decide whether we were > waiting on a 2MB or 4kB page, but rather the xas. I shelved that idea, > but not before dropping the DAX_PMD flag being passed from the PMD > pagefault caller. So if I put that back ... Did you get a chance to test this? > diff --git a/fs/dax.c b/fs/dax.c > index 9919b6b545fb..75cc160d2f0b 100644 > --- a/fs/dax.c > +++ b/fs/dax.c > @@ -367,13 +367,13 @@ static struct page *dax_busy_page(void *entry) > * a VM_FAULT code, encoded as an xarray internal entry. The ERR_PTR values > * overlap with xarray value entries. > */ > -static > -void *grab_mapping_entry(struct xa_state *xas, struct address_space *mapping) > +static void *grab_mapping_entry(struct xa_state *xas, > + struct address_space *mapping, unsigned long size) > { > bool pmd_downgrade = false; /* splitting 2MiB entry into 4k entries? */ > void *locked = dax_make_entry(pfn_to_pfn_t(0), > - DAX_EMPTY | DAX_LOCKED); > - void *unlocked = dax_make_entry(pfn_to_pfn_t(0), DAX_EMPTY); > + size | DAX_EMPTY | DAX_LOCKED); > + void *unlocked = dax_make_entry(pfn_to_pfn_t(0), size | DAX_EMPTY); > void *entry; > > retry: > @@ -1163,7 +1163,7 @@ static vm_fault_t dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, > if (write && !vmf->cow_page) > flags |= IOMAP_WRITE; > > - entry = grab_mapping_entry(&xas, mapping); > + entry = grab_mapping_entry(&xas, mapping, 0); > if (xa_is_internal(entry)) { > ret = xa_to_internal(entry); > goto out; > @@ -1396,7 +1396,7 @@ static vm_fault_t dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, > * page is already in the tree, for instance), it will return > * VM_FAULT_FALLBACK. > */ > - entry = grab_mapping_entry(&xas, mapping); > + entry = grab_mapping_entry(&xas, mapping, DAX_PMD); > if (xa_is_internal(entry)) { > result = xa_to_internal(entry); > goto fallback; >