On Wed, Aug 30, 2023 at 10:50:10AM +0100, Ryan Roberts wrote: > In preparation for implementing folios_put_refs() in the next patch, > refactor release_pages() into a set of helper functions, which can be > reused. The primary difference between release_pages() and > folios_put_refs() is how they iterate over the set of folios. The > per-folio actions are identical. As you noted, we have colliding patchsets. I'm not hugely happy with how patch 4 turned out, so I thought I'd send some addendum patches to my RFC series that implement pfn_range_put() (maybe should have been pfn_ranges_put()?) on top of my patch series. I think it's a bit nicer, but not quite as nice as it could be. I'm thinking about doing ... void release_unref_folios(struct folio_batch *folios) { struct lruvec *lruvec = NULL; unsigned long flags = 0; int i; for (i = 0; i < folios->nr; i++) { struct folio *folio = folios->folios[i]; free_swap_cache(folio); __page_cache_release(folio, &lruvec, &flags); } mem_cgroup_uncharge_folios(folios); free_unref_folios(folios); } then this becomes: void folios_put(struct folio_batch *folios) { int i, j; for (i = 0, j = 0; i < folios->nr; i++) { struct folio *folio = folios->folios[i]; if (is_huge_zero_page(&folio->page)) continue; if (folio_is_zone_device(folio)) { if (put_devmap_managed_page(&folio->page)) continue; if (folio_put_testzero(folio)) free_zone_device_page(&folio->page); continue; } if (!folio_put_testzero(folio)) continue; if (folio_test_hugetlb(folio)) { free_huge_folio(folio); continue; } if (j != i) folios->folios[j] = folio; j++; } folios->nr = j; if (!j) return; release_unref_folios(folios); } and pfn_range_put() also becomes shorter and loses all the lruvec work. Thoughts?