diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-01-19 09:52:15 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-01-19 09:52:15 -0800 |
| commit | de95841ab08083acae49190b82c658fbe4338aa7 (patch) | |
| tree | 03250e8fad0aa08ea52e5e9ae5446846189d234a | |
| parent | ca292680f390abe2b82e2ea67177dadac0399fd3 (diff) | |
| parent | a5b88c7fda4e34bae7e63aa5929ce9fd62204c51 (diff) | |
Merge "fs: fuse: Workaround for CMA migration"
| -rw-r--r-- | fs/fuse/file.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 338ae65a160f..5071d1039c26 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -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; |
