patch-pre2.0.13 linux/mm/mmap.c
Next file: linux/mm/vmscan.c
Previous file: linux/kernel/sys.c
Back to the patch index
Back to the overall index
- Lines: 103
- Date:
Thu Jun 6 09:29:59 1996
- Orig file:
pre2.0.12/linux/mm/mmap.c
- Orig date:
Wed Jun 5 10:41:29 1996
diff -u --recursive --new-file pre2.0.12/linux/mm/mmap.c linux/mm/mmap.c
@@ -12,6 +12,8 @@
#include <linux/mman.h>
#include <linux/string.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -40,6 +42,78 @@
};
/*
+ * Check that a process has enough memory to allocate a
+ * new virtual mapping.
+ */
+static inline int vm_enough_memory(long pages)
+{
+ /*
+ * stupid algorithm to decide if we have enough memory: while
+ * simple, it hopefully works in most obvious cases.. Easy to
+ * fool it, but this should catch most mistakes.
+ */
+ long freepages;
+ freepages = buffermem >> PAGE_SHIFT;
+ freepages += page_cache_size;
+ freepages >>= 1;
+ freepages += nr_free_pages;
+ freepages += nr_swap_pages;
+ freepages -= MAP_NR(high_memory) >> 4;
+ return freepages > pages;
+}
+
+asmlinkage unsigned long sys_brk(unsigned long brk)
+{
+ unsigned long rlim;
+ unsigned long newbrk, oldbrk;
+
+ if (brk < current->mm->end_code)
+ return current->mm->brk;
+ newbrk = PAGE_ALIGN(brk);
+ oldbrk = PAGE_ALIGN(current->mm->brk);
+ if (oldbrk == newbrk)
+ return current->mm->brk = brk;
+
+ /*
+ * Always allow shrinking brk
+ */
+ if (brk <= current->mm->brk) {
+ current->mm->brk = brk;
+ do_munmap(newbrk, oldbrk-newbrk);
+ return brk;
+ }
+ /*
+ * Check against rlimit and stack..
+ */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (brk - current->mm->end_code > rlim)
+ return current->mm->brk;
+
+ /*
+ * Check against existing mmap mappings.
+ */
+ if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
+ return current->mm->brk;
+
+ /*
+ * Check if we have enough memory..
+ */
+ if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
+ return current->mm->brk;
+
+ /*
+ * Ok, looks good - let it rip.
+ */
+ current->mm->brk = brk;
+ do_mmap(NULL, oldbrk, newbrk-oldbrk,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, 0);
+ return brk;
+}
+
+/*
* Combine the mmap "prot" and "flags" argument into one "vm_flags" used
* internally. Essentially, translate the "PROT_xxx" and "MAP_xxx" bits
* into "VM_xxx".
@@ -178,6 +252,14 @@
vma->vm_pte = 0;
do_munmap(addr, len); /* Clear old maps */
+
+ /* Private writable mapping? Check memory availability.. */
+ if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) {
+ if (!vm_enough_memory(len >> PAGE_SHIFT)) {
+ kfree(vma);
+ return -ENOMEM;
+ }
+ }
if (file) {
int error = file->f_op->mmap(file->f_inode, file, vma);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this