enum clear_refs_types type;
 };
 
+#ifdef CONFIG_MEM_SOFT_DIRTY
 static inline void clear_soft_dirty(struct vm_area_struct *vma,
                unsigned long addr, pte_t *pte)
 {
-#ifdef CONFIG_MEM_SOFT_DIRTY
        /*
         * The soft-dirty tracker uses #PF-s to catch writes
         * to pages, so write-protect the pte as well. See the
        }
 
        set_pte_at(vma->vm_mm, addr, pte, ptent);
-#endif
 }
 
+static inline void clear_soft_dirty_pmd(struct vm_area_struct *vma,
+               unsigned long addr, pmd_t *pmdp)
+{
+       pmd_t pmd = *pmdp;
+
+       pmd = pmd_wrprotect(pmd);
+       pmd = pmd_clear_flags(pmd, _PAGE_SOFT_DIRTY);
+
+       if (vma->vm_flags & VM_SOFTDIRTY)
+               vma->vm_flags &= ~VM_SOFTDIRTY;
+
+       set_pmd_at(vma->vm_mm, addr, pmdp, pmd);
+}
+
+#else
+
+static inline void clear_soft_dirty(struct vm_area_struct *vma,
+               unsigned long addr, pte_t *pte)
+{
+}
+
+static inline void clear_soft_dirty_pmd(struct vm_area_struct *vma,
+               unsigned long addr, pmd_t *pmdp)
+{
+}
+#endif
+
 static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
                                unsigned long end, struct mm_walk *walk)
 {
        spinlock_t *ptl;
        struct page *page;
 
-       split_huge_page_pmd(vma, addr, pmd);
+       if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
+               if (cp->type == CLEAR_REFS_SOFT_DIRTY) {
+                       clear_soft_dirty_pmd(vma, addr, pmd);
+                       goto out;
+               }
+
+               page = pmd_page(*pmd);
+
+               /* Clear accessed and referenced bits. */
+               pmdp_test_and_clear_young(vma, addr, pmd);
+               ClearPageReferenced(page);
+out:
+               spin_unlock(ptl);
+               return 0;
+       }
+
        if (pmd_trans_unstable(pmd))
                return 0;