diff options
| author | Ingo Molnar <[email protected]> | 2009-03-23 16:53:20 +0100 | 
|---|---|---|
| committer | Ingo Molnar <[email protected]> | 2009-03-23 16:53:20 +0100 | 
| commit | efd247fa34084d9b162f485004ae6d8a04059f0c (patch) | |
| tree | 417dcbe06d5cce1353a4c19cbda480ae67652b5c /arch/s390/mm/mmap.c | |
| parent | af66df5ecf9c9e2d2ff86e8203510c1c4519d64c (diff) | |
| parent | 59fcbddaff6f862cc1584b488866d9c4a5579085 (diff) | |
Merge branches 'sched/debug' and 'linus' into sched/core
Diffstat (limited to 'arch/s390/mm/mmap.c')
| -rw-r--r-- | arch/s390/mm/mmap.c | 48 | 
1 files changed, 32 insertions, 16 deletions
| diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 5932a824547a..e008d236cc15 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -35,7 +35,7 @@   * Leave an at least ~128 MB hole.   */  #define MIN_GAP (128*1024*1024) -#define MAX_GAP (TASK_SIZE/6*5) +#define MAX_GAP (STACK_TOP/6*5)  static inline unsigned long mmap_base(void)  { @@ -46,7 +46,7 @@ static inline unsigned long mmap_base(void)  	else if (gap > MAX_GAP)  		gap = MAX_GAP; -	return TASK_SIZE - (gap & PAGE_MASK); +	return STACK_TOP - (gap & PAGE_MASK);  }  static inline int mmap_is_legacy(void) @@ -89,42 +89,58 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);  #else +int s390_mmap_check(unsigned long addr, unsigned long len) +{ +	if (!test_thread_flag(TIF_31BIT) && +	    len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) +		return crst_table_upgrade(current->mm, 1UL << 53); +	return 0; +} +  static unsigned long  s390_get_unmapped_area(struct file *filp, unsigned long addr,  		unsigned long len, unsigned long pgoff, unsigned long flags)  {  	struct mm_struct *mm = current->mm; +	unsigned long area;  	int rc; -	addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags); -	if (addr & ~PAGE_MASK) -		return addr; -	if (unlikely(mm->context.asce_limit < addr + len)) { -		rc = crst_table_upgrade(mm, addr + len); +	area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); +	if (!(area & ~PAGE_MASK)) +		return area; +	if (area == -ENOMEM && +	    !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) { +		/* Upgrade the page table to 4 levels and retry. */ +		rc = crst_table_upgrade(mm, 1UL << 53);  		if (rc)  			return (unsigned long) rc; +		area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);  	} -	return addr; +	return area;  }  static unsigned long -s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,  			  const unsigned long len, const unsigned long pgoff,  			  const unsigned long flags)  {  	struct mm_struct *mm = current->mm; -	unsigned long addr = addr0; +	unsigned long area;  	int rc; -	addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); -	if (addr & ~PAGE_MASK) -		return addr; -	if (unlikely(mm->context.asce_limit < addr + len)) { -		rc = crst_table_upgrade(mm, addr + len); +	area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); +	if (!(area & ~PAGE_MASK)) +		return area; +	if (area == -ENOMEM && +	    !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) { +		/* Upgrade the page table to 4 levels and retry. */ +		rc = crst_table_upgrade(mm, 1UL << 53);  		if (rc)  			return (unsigned long) rc; +		area = arch_get_unmapped_area_topdown(filp, addr, len, +						      pgoff, flags);  	} -	return addr; +	return area;  }  /*   * This function, called very early during the creation of a new |