fs: fuse: Workaround for CMA migration

The FUSE file system may hold references to pages for long
periods of time, preventing migration from occurring. If a CMA
page is used here, CMA allocations may fail. Work around this
by swapping out a CMA page for a non-CMA page when working with
the FUSE file system.

Change-Id: Id763ea833ee125c8732ae3759ec9e20d94aa8424
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
This commit is contained in:
Laura Abbott 2012-12-03 17:50:34 -08:00 committed by Liam Mark
parent e76c8c8e73
commit a5b88c7fda

View file

@ -900,6 +900,41 @@ static int fuse_readpages_fill(void *_data, struct page *page)
return -EIO;
}
#ifdef CONFIG_CMA
if (is_cma_pageblock(page)) {
struct page *oldpage = page, *newpage;
int err;
/* make sure that old page is not free in-between the calls */
page_cache_get(oldpage);
newpage = alloc_page(GFP_HIGHUSER);
if (!newpage) {
page_cache_release(oldpage);
return -ENOMEM;
}
err = replace_page_cache_page(oldpage, newpage, GFP_KERNEL);
if (err) {
__free_page(newpage);
page_cache_release(oldpage);
return err;
}
/*
* Decrement the count on new page to make page cache the only
* owner of it
*/
lock_page(newpage);
put_page(newpage);
/* finally release the old page and swap pointers */
unlock_page(oldpage);
page_cache_release(oldpage);
page = newpage;
}
#endif
page_cache_get(page);
req->pages[req->num_pages] = page;
req->page_descs[req->num_pages].length = PAGE_SIZE;