diff options
author | Laura Abbott <lauraa@codeaurora.org> | 2012-12-03 17:50:34 -0800 |
---|---|---|
committer | Ziyan <jaraidaniel@gmail.com> | 2016-04-03 14:56:07 +0200 |
commit | cc1c60470985a83aad1d1c2f8c2ecaf2f12cb173 (patch) | |
tree | 52e5f773cc763ad38cb2863492c0ac41e7e470fe /fs | |
parent | 20304de29f1f3704d7d1ebdbdabddfce4e08cad3 (diff) | |
download | kernel_samsung_tuna-cc1c60470985a83aad1d1c2f8c2ecaf2f12cb173.zip kernel_samsung_tuna-cc1c60470985a83aad1d1c2f8c2ecaf2f12cb173.tar.gz kernel_samsung_tuna-cc1c60470985a83aad1d1c2f8c2ecaf2f12cb173.tar.bz2 |
fs: fuse: Workaround for CMA migration
The FUSE file system may hold references to pages for long
periods of time, preventing migration from occuring. 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>
Diffstat (limited to 'fs')
-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 65eb03f..18c215c 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -660,6 +660,41 @@ static int fuse_readpages_fill(void *_data, struct page *page) return PTR_ERR(req); } } +#ifdef CONFIG_CMA + if (get_pageblock_migratetype(page) == MIGRATE_CMA) { + 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->num_pages++; |