|
@@ -2216,6 +2216,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
|
|
struct page *page;
|
|
|
pte_t _dst_pte, *dst_pte;
|
|
|
int ret;
|
|
|
+ pgoff_t offset, max_off;
|
|
|
|
|
|
ret = -ENOMEM;
|
|
|
if (!shmem_inode_acct_block(inode, 1))
|
|
@@ -2253,6 +2254,12 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
|
|
__SetPageSwapBacked(page);
|
|
|
__SetPageUptodate(page);
|
|
|
|
|
|
+ ret = -EFAULT;
|
|
|
+ offset = linear_page_index(dst_vma, dst_addr);
|
|
|
+ max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
|
|
|
+ if (unlikely(offset >= max_off))
|
|
|
+ goto out_release;
|
|
|
+
|
|
|
ret = mem_cgroup_try_charge_delay(page, dst_mm, gfp, &memcg, false);
|
|
|
if (ret)
|
|
|
goto out_release;
|
|
@@ -2268,8 +2275,14 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
|
|
if (dst_vma->vm_flags & VM_WRITE)
|
|
|
_dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte));
|
|
|
|
|
|
- ret = -EEXIST;
|
|
|
dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
|
|
|
+
|
|
|
+ ret = -EFAULT;
|
|
|
+ max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
|
|
|
+ if (unlikely(offset >= max_off))
|
|
|
+ goto out_release_uncharge_unlock;
|
|
|
+
|
|
|
+ ret = -EEXIST;
|
|
|
if (!pte_none(*dst_pte))
|
|
|
goto out_release_uncharge_unlock;
|
|
|
|
|
@@ -2287,13 +2300,14 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
|
|
|
|
|
/* No need to invalidate - it was non-present before */
|
|
|
update_mmu_cache(dst_vma, dst_addr, dst_pte);
|
|
|
- unlock_page(page);
|
|
|
pte_unmap_unlock(dst_pte, ptl);
|
|
|
+ unlock_page(page);
|
|
|
ret = 0;
|
|
|
out:
|
|
|
return ret;
|
|
|
out_release_uncharge_unlock:
|
|
|
pte_unmap_unlock(dst_pte, ptl);
|
|
|
+ delete_from_page_cache(page);
|
|
|
out_release_uncharge:
|
|
|
mem_cgroup_cancel_charge(page, memcg, false);
|
|
|
out_release:
|