On Mon, Mar 17, 2025 at 05:00:03PM +0000, Matthew Wilcox wrote: > My proposal for movable non-folio pages is: > > * memdesc is used to point to struct movable_operations (these will > need to be aligned to 16 bytes, but I think that's fine) > * private is used to point to the next page in the list > * These pages are refcounted > * We retain a "lock" bit in page->flags > > The most disruptive part of this is that we can't use a list_head any > more. I don't think a singly-linked list is prohibitive, but either > we need to switch folios to also use a singly-linked list, or we need > to handle folios & movable pages separately. I think the former is > probably best. And of course, moments after sending this out I realise I didn't include how to handle zpdesc pages. zpdesc have their own memory descriptor (like folios do), so they can't use page->memdesc to point to their movable_ops. Either we can make zsmalloc_mops visible outside zsmalloc.c (which would prohibit zsmalloc being built as a module), or we can make struct zpdesc look like this: struct zpdesc { unsigned long flags; struct movable_operations *mops; struct zpdesc *next; atomic_t _refcount; ... }; so that the same code can handle both plain pages and zpdesc pages. It's a bit wasteful in that every zpdesc would contain exactly the same mops, but it saves playing games with symbol_get() or having zsmalloc fill in a zpdesc_mops pointer exported to modules by the migration code. Again, I'm not trying to define the "forever" code here, I'm looking for something quick and unlikely to introduce bugs so that we can move forward with splitting page & folio apart.