|
@@ -2082,8 +2082,22 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
|
|
tree_rmap_item =
|
|
tree_rmap_item =
|
|
unstable_tree_search_insert(rmap_item, page, &tree_page);
|
|
unstable_tree_search_insert(rmap_item, page, &tree_page);
|
|
if (tree_rmap_item) {
|
|
if (tree_rmap_item) {
|
|
|
|
+ bool split;
|
|
|
|
+
|
|
kpage = try_to_merge_two_pages(rmap_item, page,
|
|
kpage = try_to_merge_two_pages(rmap_item, page,
|
|
tree_rmap_item, tree_page);
|
|
tree_rmap_item, tree_page);
|
|
|
|
+ /*
|
|
|
|
+ * If both pages we tried to merge belong to the same compound
|
|
|
|
+ * page, then we actually ended up increasing the reference
|
|
|
|
+ * count of the same compound page twice, and split_huge_page
|
|
|
|
+ * failed.
|
|
|
|
+ * Here we set a flag if that happened, and we use it later to
|
|
|
|
+ * try split_huge_page again. Since we call put_page right
|
|
|
|
+ * afterwards, the reference count will be correct and
|
|
|
|
+ * split_huge_page should succeed.
|
|
|
|
+ */
|
|
|
|
+ split = PageTransCompound(page)
|
|
|
|
+ && compound_head(page) == compound_head(tree_page);
|
|
put_page(tree_page);
|
|
put_page(tree_page);
|
|
if (kpage) {
|
|
if (kpage) {
|
|
/*
|
|
/*
|
|
@@ -2110,6 +2124,20 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
|
|
break_cow(tree_rmap_item);
|
|
break_cow(tree_rmap_item);
|
|
break_cow(rmap_item);
|
|
break_cow(rmap_item);
|
|
}
|
|
}
|
|
|
|
+ } else if (split) {
|
|
|
|
+ /*
|
|
|
|
+ * We are here if we tried to merge two pages and
|
|
|
|
+ * failed because they both belonged to the same
|
|
|
|
+ * compound page. We will split the page now, but no
|
|
|
|
+ * merging will take place.
|
|
|
|
+ * We do not want to add the cost of a full lock; if
|
|
|
|
+ * the page is locked, it is better to skip it and
|
|
|
|
+ * perhaps try again later.
|
|
|
|
+ */
|
|
|
|
+ if (!trylock_page(page))
|
|
|
|
+ return;
|
|
|
|
+ split_huge_page(page);
|
|
|
|
+ unlock_page(page);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|