free_stable_node(stable_node);
 }
 
+enum get_ksm_page_flags {
+       GET_KSM_PAGE_NOLOCK,
+       GET_KSM_PAGE_LOCK,
+       GET_KSM_PAGE_TRYLOCK
+};
+
 /*
  * get_ksm_page: checks if the page indicated by the stable node
  * is still its ksm page, despite having held no reference to it.
  * a page to put something that might look like our key in page->mapping.
  * is on its way to being freed; but it is an anomaly to bear in mind.
  */
-static struct page *get_ksm_page(struct stable_node *stable_node, bool lock_it)
+static struct page *get_ksm_page(struct stable_node *stable_node,
+                                enum get_ksm_page_flags flags)
 {
        struct page *page;
        void *expected_mapping;
                goto stale;
        }
 
-       if (lock_it) {
+       if (flags == GET_KSM_PAGE_TRYLOCK) {
+               if (!trylock_page(page)) {
+                       put_page(page);
+                       return ERR_PTR(-EBUSY);
+               }
+       } else if (flags == GET_KSM_PAGE_LOCK)
                lock_page(page);
+
+       if (flags != GET_KSM_PAGE_NOLOCK) {
                if (READ_ONCE(page->mapping) != expected_mapping) {
                        unlock_page(page);
                        put_page(page);
                struct page *page;
 
                stable_node = rmap_item->head;
-               page = get_ksm_page(stable_node, true);
+               page = get_ksm_page(stable_node, GET_KSM_PAGE_LOCK);
                if (!page)
                        goto out;
 
        struct page *page;
        int err;
 
-       page = get_ksm_page(stable_node, true);
+       page = get_ksm_page(stable_node, GET_KSM_PAGE_LOCK);
        if (!page) {
                /*
                 * get_ksm_page did remove_node_from_stable_tree itself.
                 * stable_node parameter itself will be freed from
                 * under us if it returns NULL.
                 */
-               _tree_page = get_ksm_page(dup, false);
+               _tree_page = get_ksm_page(dup, GET_KSM_PAGE_NOLOCK);
                if (!_tree_page)
                        continue;
                nr += 1;
        if (!is_stable_node_chain(stable_node)) {
                if (is_page_sharing_candidate(stable_node)) {
                        *_stable_node_dup = stable_node;
-                       return get_ksm_page(stable_node, false);
+                       return get_ksm_page(stable_node, GET_KSM_PAGE_NOLOCK);
                }
                /*
                 * _stable_node_dup set to NULL means the stable_node
                         * wrprotected at all times. Any will work
                         * fine to continue the walk.
                         */
-                       tree_page = get_ksm_page(stable_node_any, false);
+                       tree_page = get_ksm_page(stable_node_any,
+                                                GET_KSM_PAGE_NOLOCK);
                }
                VM_BUG_ON(!stable_node_dup ^ !!stable_node_any);
                if (!tree_page) {
                         * It would be more elegant to return stable_node
                         * than kpage, but that involves more changes.
                         */
-                       tree_page = get_ksm_page(stable_node_dup, true);
+                       tree_page = get_ksm_page(stable_node_dup,
+                                                GET_KSM_PAGE_TRYLOCK);
+
+                       if (PTR_ERR(tree_page) == -EBUSY)
+                               return ERR_PTR(-EBUSY);
+
                        if (unlikely(!tree_page))
                                /*
                                 * The tree may have been rebalanced,
                         * wrprotected at all times. Any will work
                         * fine to continue the walk.
                         */
-                       tree_page = get_ksm_page(stable_node_any, false);
+                       tree_page = get_ksm_page(stable_node_any,
+                                                GET_KSM_PAGE_NOLOCK);
                }
                VM_BUG_ON(!stable_node_dup ^ !!stable_node_any);
                if (!tree_page) {
        remove_rmap_item_from_tree(rmap_item);
 
        if (kpage) {
+               if (PTR_ERR(kpage) == -EBUSY)
+                       return;
+
                err = try_to_merge_with_ksm_page(rmap_item, page, kpage);
                if (!err) {
                        /*
 
                        list_for_each_entry_safe(stable_node, next,
                                                 &migrate_nodes, list) {
-                               page = get_ksm_page(stable_node, false);
+                               page = get_ksm_page(stable_node,
+                                                   GET_KSM_PAGE_NOLOCK);
                                if (page)
                                        put_page(page);
                                cond_resched();