]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - mm/memory.c
dt-bindings: clock: milbeaut: add Milbeaut clock description
[linux.git] / mm / memory.c
index e11ca9dd823f20c60dd0c20ff7567e34a84a1dda..47fe250307c7aa0f553454af6f459343819f8770 100644 (file)
@@ -69,6 +69,7 @@
 #include <linux/userfaultfd_k.h>
 #include <linux/dax.h>
 #include <linux/oom.h>
+#include <linux/numa.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -1451,7 +1452,7 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
        spinlock_t *ptl;
 
        retval = -EINVAL;
-       if (PageAnon(page))
+       if (PageAnon(page) || PageSlab(page) || page_has_type(page))
                goto out;
        retval = -ENOMEM;
        flush_dcache_page(page);
@@ -1503,6 +1504,8 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
  * under mm->mmap_sem write-lock, so it can change vma->vm_flags.
  * Caller must set VM_MIXEDMAP on vma if it wants to call this
  * function from other places, for example from page-fault handler.
+ *
+ * Return: %0 on success, negative error code otherwise.
  */
 int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
                        struct page *page)
@@ -1830,7 +1833,9 @@ static inline int remap_p4d_range(struct mm_struct *mm, pgd_t *pgd,
  * @size: size of map area
  * @prot: page protection flags for this mapping
  *
- *  Note: this is only safe if the mm semaphore is held when called.
+ * Note: this is only safe if the mm semaphore is held when called.
+ *
+ * Return: %0 on success, negative error code otherwise.
  */
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
                    unsigned long pfn, unsigned long size, pgprot_t prot)
@@ -1903,6 +1908,8 @@ EXPORT_SYMBOL(remap_pfn_range);
  *
  * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get
  * whatever write-combining details or similar.
+ *
+ * Return: %0 on success, negative error code otherwise.
  */
 int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len)
 {
@@ -2381,12 +2388,13 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
  *
  * This function handles all that is needed to finish a write page fault in a
  * shared mapping due to PTE being read-only once the mapped page is prepared.
- * It handles locking of PTE and modifying it. The function returns
- * VM_FAULT_WRITE on success, 0 when PTE got changed before we acquired PTE
- * lock.
+ * It handles locking of PTE and modifying it.
  *
  * The function expects the page to be locked or other protection against
  * concurrent faults / writeback (such as DAX radix tree locks).
+ *
+ * Return: %VM_FAULT_WRITE on success, %0 when PTE got changed before
+ * we acquired PTE lock.
  */
 vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf)
 {
@@ -2504,8 +2512,11 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
         * Take out anonymous pages first, anonymous shared vmas are
         * not dirty accountable.
         */
-       if (PageAnon(vmf->page) && !PageKsm(vmf->page)) {
+       if (PageAnon(vmf->page)) {
                int total_map_swapcount;
+               if (PageKsm(vmf->page) && (PageSwapCache(vmf->page) ||
+                                          page_count(vmf->page) != 1))
+                       goto copy;
                if (!trylock_page(vmf->page)) {
                        get_page(vmf->page);
                        pte_unmap_unlock(vmf->pte, vmf->ptl);
@@ -2520,6 +2531,15 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
                        }
                        put_page(vmf->page);
                }
+               if (PageKsm(vmf->page)) {
+                       bool reused = reuse_ksm_page(vmf->page, vmf->vma,
+                                                    vmf->address);
+                       unlock_page(vmf->page);
+                       if (!reused)
+                               goto copy;
+                       wp_page_reuse(vmf);
+                       return VM_FAULT_WRITE;
+               }
                if (reuse_swap_page(vmf->page, &total_map_swapcount)) {
                        if (total_map_swapcount == 1) {
                                /*
@@ -2540,7 +2560,7 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
                                        (VM_WRITE|VM_SHARED))) {
                return wp_page_shared(vmf);
        }
-
+copy:
        /*
         * Ok, we need to copy. Oh, well..
         */
@@ -3201,6 +3221,8 @@ static vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page)
  *
  * Target users are page handler itself and implementations of
  * vm_ops->map_pages.
+ *
+ * Return: %0 on success, %VM_FAULT_ code in case of error.
  */
 vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
                struct page *page)
@@ -3261,11 +3283,12 @@ vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
  * This function handles all that is needed to finish a page fault once the
  * page to fault in is prepared. It handles locking of PTEs, inserts PTE for
  * given page, adds reverse page mapping, handles memcg charges and LRU
- * addition. The function returns 0 on success, VM_FAULT_ code in case of
- * error.
+ * addition.
  *
  * The function expects the page to be locked and on success it consumes a
  * reference of a page being mapped (for the PTE which maps it).
+ *
+ * Return: %0 on success, %VM_FAULT_ code in case of error.
  */
 vm_fault_t finish_fault(struct vm_fault *vmf)
 {
@@ -3321,12 +3344,8 @@ DEFINE_DEBUGFS_ATTRIBUTE(fault_around_bytes_fops,
 
 static int __init fault_around_debugfs(void)
 {
-       void *ret;
-
-       ret = debugfs_create_file_unsafe("fault_around_bytes", 0644, NULL, NULL,
-                       &fault_around_bytes_fops);
-       if (!ret)
-               pr_warn("Failed to create fault_around_bytes in debugfs");
+       debugfs_create_file_unsafe("fault_around_bytes", 0644, NULL, NULL,
+                                  &fault_around_bytes_fops);
        return 0;
 }
 late_initcall(fault_around_debugfs);
@@ -3517,10 +3536,13 @@ static vm_fault_t do_shared_fault(struct vm_fault *vmf)
  * but allow concurrent faults).
  * The mmap_sem may have been released depending on flags and our
  * return value.  See filemap_fault() and __lock_page_or_retry().
+ * If mmap_sem is released, vma may become invalid (for example
+ * by other thread calling munmap()).
  */
 static vm_fault_t do_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
+       struct mm_struct *vm_mm = vma->vm_mm;
        vm_fault_t ret;
 
        /*
@@ -3561,7 +3583,7 @@ static vm_fault_t do_fault(struct vm_fault *vmf)
 
        /* preallocated pagetable is unused: free it */
        if (vmf->prealloc_pte) {
-               pte_free(vma->vm_mm, vmf->prealloc_pte);
+               pte_free(vm_mm, vmf->prealloc_pte);
                vmf->prealloc_pte = NULL;
        }
        return ret;
@@ -3586,11 +3608,11 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct page *page = NULL;
-       int page_nid = -1;
+       int page_nid = NUMA_NO_NODE;
        int last_cpupid;
        int target_nid;
        bool migrated = false;
-       pte_t pte;
+       pte_t pte, old_pte;
        bool was_writable = pte_savedwrite(vmf->orig_pte);
        int flags = 0;
 
@@ -3610,12 +3632,12 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
         * Make it present again, Depending on how arch implementes non
         * accessible ptes, some can allow access by kernel mode.
         */
-       pte = ptep_modify_prot_start(vma->vm_mm, vmf->address, vmf->pte);
-       pte = pte_modify(pte, vma->vm_page_prot);
+       old_pte = ptep_modify_prot_start(vma, vmf->address, vmf->pte);
+       pte = pte_modify(old_pte, vma->vm_page_prot);
        pte = pte_mkyoung(pte);
        if (was_writable)
                pte = pte_mkwrite(pte);
-       ptep_modify_prot_commit(vma->vm_mm, vmf->address, vmf->pte, pte);
+       ptep_modify_prot_commit(vma, vmf->address, vmf->pte, old_pte, pte);
        update_mmu_cache(vma, vmf->address, vmf->pte);
 
        page = vm_normal_page(vma, vmf->address, pte);
@@ -3653,7 +3675,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
        target_nid = numa_migrate_prep(page, vma, vmf->address, page_nid,
                        &flags);
        pte_unmap_unlock(vmf->pte, vmf->ptl);
-       if (target_nid == -1) {
+       if (target_nid == NUMA_NO_NODE) {
                put_page(page);
                goto out;
        }
@@ -3667,7 +3689,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
                flags |= TNF_MIGRATE_FAIL;
 
 out:
-       if (page_nid != -1)
+       if (page_nid != NUMA_NO_NODE)
                task_numa_fault(last_cpupid, page_nid, 1, flags);
        return 0;
 }
@@ -4150,7 +4172,7 @@ EXPORT_SYMBOL(follow_pte_pmd);
  *
  * Only IO mappings and raw PFN mappings are allowed.
  *
- * Returns zero and the pfn at @pfn on success, -ve otherwise.
+ * Return: zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
        unsigned long *pfn)
@@ -4300,6 +4322,8 @@ int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
  * @gup_flags: flags modifying lookup behaviour
  *
  * The caller must hold a reference on @mm.
+ *
+ * Return: number of bytes copied from source to destination.
  */
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
                void *buf, int len, unsigned int gup_flags)