On Fri, Sep 18, 2020 at 06:37:21PM +0200, Christoph Hellwig wrote:
void shmem_unpin_map(struct file *file, void *ptr) {
- long i = shmem_npages(file);
- mapping_clear_unevictable(file->f_mapping);
- __shmem_unpin_map(file, ptr, shmem_npte(file));
- vunmap(ptr);
- for (i = 0; i < shmem_npages(file); i++) {
struct page *page;
page = shmem_read_mapping_page_gfp(file->f_mapping, i,
GFP_KERNEL);
if (!WARN_ON(IS_ERR(page))) {
put_page(page);
put_page(page);
}
- }
}
This is awkward. I'd like it if we had a vfree() variant which called put_page() instead of __free_pages(). I'd like it even more if we used release_pages() instead of our own loop that called put_page().
Perhaps something like this ...
+++ b/mm/vmalloc.c @@ -2262,7 +2262,7 @@ static void __vunmap(const void *addr, int deallocate_page s)
vm_remove_mappings(area, deallocate_pages);
- if (deallocate_pages) { + if (deallocate_pages == 1) { int i;
for (i = 0; i < area->nr_pages; i++) { @@ -2271,8 +2271,12 @@ static void __vunmap(const void *addr, int deallocate_pages) BUG_ON(!page); __free_pages(page, 0); } - atomic_long_sub(area->nr_pages, &nr_vmalloc_pages); + } else if (deallocate_pages == 2) { + release_pages(area->pages, area->nr_pages); + }
+ if (deallocate_pages) { + atomic_long_sub(area->nr_pages, &nr_vmalloc_pages); kvfree(area->pages); } @@ -2369,6 +2373,14 @@ void vunmap(const void *addr) } EXPORT_SYMBOL(vunmap);
+void vunmap_put_pages(const void *addr) +{ + BUG_ON(in_interrupt()); + might_sleep(); + if (addr) + __vunmap(addr, 2); +} + /** * vmap - map an array of pages into virtually contiguous space * @pages: array of page pointers
only with kernel-doc and so on. I bet somebody has a better idea for a name.