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:
parent
e76c8c8e73
commit
a5b88c7fda
1 changed files with 35 additions and 0 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue