Re: alpha 2.4.13: fix taso osf emulation

Ivan Kokshaysky
2001-10-26T10:45:49Z

On Fri, Oct 26, 2001 at 12:01:10PM +0200, Maciej W. Rozycki wrote:
> On Fri, 26 Oct 2001, Richard Henderson wrote:
> > Thoughts on changing all ports such that a mmap with a non-zero,
> > non-MAP_FIXED address starts the vma search at that address,
> > rather than looking for that exact address then checking the
> > regular unmapped base?
>
> It used to do so. It breaks things such as dynamic linking of shared
> objects linked at high load address. It breaks mmap() in principle, as it
> shouldn't fail when invoked with a non-zero, non-MAP_FIXED, invalid
> address if there is still address space available elsewhere.

Maciej and I discussed all this a while back, and I had a patch
which did exactly that that Richard suggested, plus:
as far as I can tell, it conforms to any existing mmap(2) documentation;
is more effective than current implementation, as I call the second
find_vma() only after VM wraparound, which is extremely rare;
keeps osf /sbin/loader happy, so no need for alpha-specific routine.
Patch appended, comments?

Ivan.

P.S. Just noticed missing closing brace in the patch from my previous post...
Sorry.

--- 2.4.13/mm/mmap.c Sun Sep 30 22:05:40 2001
+++ linux/mm/mmap.c Fri Oct 26 13:36:47 2001
@@ -590,27 +590,38 @@ free_vma:
static inline unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
{
struct vm_area_struct *vma;
+ unsigned long addr_limit = TASK_SIZE - len;
+ unsigned long addr1 = 0;

if (len > TASK_SIZE)
return -ENOMEM;

if (addr) {
addr = PAGE_ALIGN(addr);
- vma = find_vma(current->mm, addr);
- if (TASK_SIZE - len >= addr &&
- (!vma || addr + len <= vma->vm_start))
- return addr;
+ if (addr > TASK_UNMAPPED_BASE)
+ addr1 = addr;
+ goto find_free_area;
}
+
+default_area:
addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

+find_free_area:
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
- if (TASK_SIZE - len < addr)
- return -ENOMEM;
+ if (addr_limit < addr)
+ break;
if (!vma || addr + len <= vma->vm_start)
return addr;
addr = vma->vm_end;
}
+ if (addr1) {
+ /* No unmapped areas above addr; try below it */
+ addr_limit = addr1;
+ addr1 = 0;
+ goto default_area;
+ }
+ return -ENOMEM;
}
#else
extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);