On Sat, 19 Sep 2020, Matthew Wilcox wrote: > On Fri, Sep 18, 2020 at 09:20:09PM -0700, Andrew Morton wrote: > > LRU page reclaim always splits the shmem huge page first: I'd prefer not > > to demand that of i915, so check and split compound in shmem_writepage(). > > Sorry for not checking this earlier, but I don't think this is right. > > for (i = 0; i < obj->base.size >> PAGE_SHIFT; i++) { > ... > if (!page_mapped(page) && clear_page_dirty_for_io(page)) { > ... > ret = mapping->a_ops->writepage(page, &wbc); > > so we cleared the dirty bit on the entire hugepage, but then split > it after clearing the dirty bit, so the subpages are now not dirty. > I think we'll lose writes as a result? At least we won't swap pages > out that deserve to be paged out. Very good observation, thank you. It behaves a lot better with this patch in than without it; but you're right, only the head will get written to swap, and the tails left in memory; with dirty cleared, so they may be left indefinitely (I've not yet looked to see when if ever PageDirty might get set later). Hmm. It may just be a matter of restyling the i915 code with if (!page_mapped(page)) { clear_page_dirty_for_io(page); but I don't want to rush to that conclusion - there might turn out to be a good way of doing it at the shmem_writepage() end, but probably only hacks available. I'll mull it over: it deserves some thought about what would suit, if a THP arrived here some other way. We did have some i915 guys Cc'ed on the original posting, but no need to Cc them again until I'm closer to deciding what's right. Linus, Andrew, probably best to drop this patch for now, since no-one else has reported the problem here than me, testing with /sys/kernel/mm/transparent_hugepage/shmem_enabled set to "force"; and what it fixes is not a new regression in 5.9. Though no harm done if the patch goes in: it is an improvement, but seriously incomplete, as Matthew has observed. Hugh > > > > > - VM_BUG_ON_PAGE(PageCompound(page), page); > > + /* > > + * If /sys/kernel/mm/transparent_hugepage/shmem_enabled is "force", > > + * then drivers/gpu/drm/i915/gem/i915_gem_shmem.c gets huge pages, > > + * and its shmem_writeback() needs them to be split when swapping. > > + */ > > + if (PageTransCompound(page)) > > + if (split_huge_page(page) < 0) > > + goto redirty; > > + > > BUG_ON(!PageLocked(page)); > > mapping = page->mapping; > > index = page->index; > > _ > >