aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLaura Abbott <lauraa@codeaurora.org>2012-12-03 17:50:34 -0800
committerZiyan <jaraidaniel@gmail.com>2016-04-03 14:56:07 +0200
commitcc1c60470985a83aad1d1c2f8c2ecaf2f12cb173 (patch)
tree52e5f773cc763ad38cb2863492c0ac41e7e470fe /fs
parent20304de29f1f3704d7d1ebdbdabddfce4e08cad3 (diff)
downloadkernel_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.c35
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++;