summaryrefslogtreecommitdiffstats
path: root/uClinux-2.4.31-uc0/mmnommu/mremap.c
blob: 783ba82d2a1f705a3d747ec2f24f3ca2dc16e28d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 *	linux/mm/remap.c
 *
 *  Copyright (c) 2001 Lineo, Inc. David McCullough <davidm@lineo.com>
 *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org> ref uClinux 2.0
 *	(C) Copyright 1996 Linus Torvalds
 */

#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/shm.h>
#include <linux/mman.h>
#include <linux/swap.h>

#include <asm/uaccess.h>
#include <asm/pgalloc.h>

extern unsigned long askedalloc, realalloc;

/*
 * Expand (or shrink) an existing mapping, potentially moving it at the
 * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
 *
 * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise
 * This option implies MREMAP_MAYMOVE.
 *
 * on uClinux, we only permit changing a mapping's size, and only as long as it stays within the
 * hole allocated by the kmalloc() call in do_mmap_pgoff() and the block is not shareable
 */
unsigned long do_mremap(unsigned long addr,
			unsigned long old_len, unsigned long new_len,
			unsigned long flags, unsigned long new_addr)
{
	struct vm_list_struct *vml = NULL;

	/* insanity checks first */
	if (new_len == 0)
		return (unsigned long) -EINVAL;

	if (flags & MREMAP_FIXED && new_addr != addr)
		return (unsigned long) -EINVAL;

	for (vml = current->mm->vmlist; vml; vml = vml->next)
		if (vml->vma->vm_start == addr)
			goto found;

	return (unsigned long) -EINVAL;

 found:
	if (vml->vma->vm_end != vml->vma->vm_start + old_len)
		return (unsigned long) -EFAULT;

	if (vml->vma->vm_flags & VM_MAYSHARE)
		return (unsigned long) -EPERM;

	if (new_len > ksize((void *) addr))
		return (unsigned long) -ENOMEM;

	/* all checks complete - do it */
	vml->vma->vm_end = vml->vma->vm_start + new_len;

	askedalloc -= old_len;
	askedalloc += new_len;

	return vml->vma->vm_start;
}

/*
 * FIXME: Could do a tradional realloc() in some cases.
 */
asmlinkage unsigned long sys_mremap(unsigned long addr,
				    unsigned long old_len, unsigned long new_len,
				    unsigned long flags, unsigned long new_addr)
{
	return -ENOSYS;
}