diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/Kconfig | 9 | ||||
| -rw-r--r-- | mm/huge_memory.c | 7 | ||||
| -rw-r--r-- | mm/memcontrol.c | 36 | ||||
| -rw-r--r-- | mm/readahead.c | 9 | ||||
| -rw-r--r-- | mm/usercopy.c | 4 | 
5 files changed, 43 insertions, 22 deletions
| diff --git a/mm/Kconfig b/mm/Kconfig index 78a23c5c302d..be0ee11fa0d9 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -262,7 +262,14 @@ config COMPACTION  	select MIGRATION  	depends on MMU  	help -	  Allows the compaction of memory for the allocation of huge pages. +          Compaction is the only memory management component to form +          high order (larger physically contiguous) memory blocks +          reliably. The page allocator relies on compaction heavily and +          the lack of the feature can lead to unexpected OOM killer +          invocations for high order memory requests. You shouldn't +          disable this option unless there really is a strong reason for +          it and then we would be really interested to hear about that at  #  # support for page migration diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 2373f0a7d340..2db2112aa31e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1512,7 +1512,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  	struct page *page;  	pgtable_t pgtable;  	pmd_t _pmd; -	bool young, write, dirty; +	bool young, write, dirty, soft_dirty;  	unsigned long addr;  	int i; @@ -1546,6 +1546,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  	write = pmd_write(*pmd);  	young = pmd_young(*pmd);  	dirty = pmd_dirty(*pmd); +	soft_dirty = pmd_soft_dirty(*pmd);  	pmdp_huge_split_prepare(vma, haddr, pmd);  	pgtable = pgtable_trans_huge_withdraw(mm, pmd); @@ -1562,6 +1563,8 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  			swp_entry_t swp_entry;  			swp_entry = make_migration_entry(page + i, write);  			entry = swp_entry_to_pte(swp_entry); +			if (soft_dirty) +				entry = pte_swp_mksoft_dirty(entry);  		} else {  			entry = mk_pte(page + i, vma->vm_page_prot);  			entry = maybe_mkwrite(entry, vma); @@ -1569,6 +1572,8 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,  				entry = pte_wrprotect(entry);  			if (!young)  				entry = pte_mkold(entry); +			if (soft_dirty) +				entry = pte_mksoft_dirty(entry);  		}  		if (dirty)  			SetPageDirty(page + i); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 2ff0289ad061..9a6a51a7c416 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4082,24 +4082,6 @@ static void mem_cgroup_id_get_many(struct mem_cgroup *memcg, unsigned int n)  	atomic_add(n, &memcg->id.ref);  } -static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg) -{ -	while (!atomic_inc_not_zero(&memcg->id.ref)) { -		/* -		 * The root cgroup cannot be destroyed, so it's refcount must -		 * always be >= 1. -		 */ -		if (WARN_ON_ONCE(memcg == root_mem_cgroup)) { -			VM_BUG_ON(1); -			break; -		} -		memcg = parent_mem_cgroup(memcg); -		if (!memcg) -			memcg = root_mem_cgroup; -	} -	return memcg; -} -  static void mem_cgroup_id_put_many(struct mem_cgroup *memcg, unsigned int n)  {  	if (atomic_sub_and_test(n, &memcg->id.ref)) { @@ -5821,6 +5803,24 @@ static int __init mem_cgroup_init(void)  subsys_initcall(mem_cgroup_init);  #ifdef CONFIG_MEMCG_SWAP +static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg) +{ +	while (!atomic_inc_not_zero(&memcg->id.ref)) { +		/* +		 * The root cgroup cannot be destroyed, so it's refcount must +		 * always be >= 1. +		 */ +		if (WARN_ON_ONCE(memcg == root_mem_cgroup)) { +			VM_BUG_ON(1); +			break; +		} +		memcg = parent_mem_cgroup(memcg); +		if (!memcg) +			memcg = root_mem_cgroup; +	} +	return memcg; +} +  /**   * mem_cgroup_swapout - transfer a memsw charge to swap   * @page: page whose memsw charge to transfer diff --git a/mm/readahead.c b/mm/readahead.c index 65ec288dc057..c8a955b1297e 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -8,6 +8,7 @@   */  #include <linux/kernel.h> +#include <linux/dax.h>  #include <linux/gfp.h>  #include <linux/export.h>  #include <linux/blkdev.h> @@ -544,6 +545,14 @@ do_readahead(struct address_space *mapping, struct file *filp,  	if (!mapping || !mapping->a_ops)  		return -EINVAL; +	/* +	 * Readahead doesn't make sense for DAX inodes, but we don't want it +	 * to report a failure either.  Instead, we just return success and +	 * don't do any work. +	 */ +	if (dax_mapping(mapping)) +		return 0; +  	return force_page_cache_readahead(mapping, filp, index, nr);  } diff --git a/mm/usercopy.c b/mm/usercopy.c index 8ebae91a6b55..a3cc3052f830 100644 --- a/mm/usercopy.c +++ b/mm/usercopy.c @@ -83,7 +83,7 @@ static bool overlaps(const void *ptr, unsigned long n, unsigned long low,  	unsigned long check_high = check_low + n;  	/* Does not overlap if entirely above or entirely below. */ -	if (check_low >= high || check_high < low) +	if (check_low >= high || check_high <= low)  		return false;  	return true; @@ -124,7 +124,7 @@ static inline const char *check_kernel_text_object(const void *ptr,  static inline const char *check_bogus_address(const void *ptr, unsigned long n)  {  	/* Reject if object wraps past end of memory. */ -	if (ptr + n < ptr) +	if ((unsigned long)ptr + n < (unsigned long)ptr)  		return "<wrapped address>";  	/* Reject if NULL or ZERO-allocation. */ |