]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blobdiff - mm/memory.c
mm: remove gup_flags FOLL_WRITE games from __get_user_pages()
[sojka/nv-tegra/linux-3.10.git] / mm / memory.c
index 60689778088fbc92b92d0d99e334becb2ca032b4..1b3e0937ae5ceb14f68495009500002c7982a940 100644 (file)
@@ -1477,6 +1477,16 @@ EXPORT_SYMBOL_GPL(zap_vma_ptes);
 
 #define FOLL_CMA 0x10000000
 
+/*
+ * FOLL_FORCE can write to even unwritable pte's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
+{
+       return pte_write(pte) ||
+               ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
+}
+
 /**
  * follow_page_mask - look up a page descriptor from a user-virtual address
  * @vma: vm_area_struct mapping @address
@@ -1585,7 +1595,7 @@ split_fallthrough:
        }
        if ((flags & FOLL_NUMA) && pte_numa(pte))
                goto no_page;
-       if ((flags & FOLL_WRITE) && !pte_write(pte))
+       if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags))
                goto unlock;
 
        page = vm_normal_page(vma, address, pte);
@@ -1948,7 +1958,7 @@ follow_page_again:
                                 */
                                if ((ret & VM_FAULT_WRITE) &&
                                    !(vma->vm_flags & VM_WRITE))
-                                       foll_flags &= ~FOLL_WRITE;
+                                       foll_flags |= FOLL_COW;
 
                                cond_resched();
                        }