Hi Folks! Hi Rik! here is a preliminary patch to allow Per Context Virtual Memory Limits for ctx17a ...
to set the limit, no additional tool is required, just setting the virtual memory resource limit (ulimit -v <size>) is sufficient, the limit and the current value can be read via /proc/self/status | total_vm: 25600/876 I'm not sure if virtual memory limits really are a GoodThing(tm) but without trying it, nobody will know ... http://vserver.13thfloor.at/Experimental/patch-2.4.22-ctx17a-ml0.01.diff.bz2 enjoy, Herbert ; ; Virtual Server Project ; Per Context Virtual Memory Limit ; ; (C) 2003 Herbert P�tzl <[EMAIL PROTECTED]> ; ; Changelog: ; ; 0.01 - first public release ; - whitespace cleanups ; ; this patch is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License ; as published by the Free Software Foundation; either version 2 ; of the License, or (at your option) any later version. ; ; this patch is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; diff -NurP --minimal linux-2.4.22-ctx17a/arch/ia64/ia32/binfmt_elf32.c linux-2.4.22-ctx17a-ml0.01/arch/ia64/ia32/binfmt_elf32.c --- linux-2.4.22-ctx17a/arch/ia64/ia32/binfmt_elf32.c 2003-08-25 20:32:07.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/arch/ia64/ia32/binfmt_elf32.c 2003-09-05 09:28:23.000000000 +0200 @@ -188,6 +188,7 @@ mpnt->vm_private_data = 0; insert_vm_struct(current->mm, mpnt); current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + ctx_vmpages_add((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff -NurP --minimal linux-2.4.22-ctx17a/arch/ia64/kernel/perfmon.c linux-2.4.22-ctx17a-ml0.01/arch/ia64/kernel/perfmon.c --- linux-2.4.22-ctx17a/arch/ia64/kernel/perfmon.c 2003-08-25 20:32:07.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/arch/ia64/kernel/perfmon.c 2003-09-05 09:28:23.000000000 +0200 @@ -965,6 +965,7 @@ insert_vm_struct(mm, vma); mm->total_vm += size >> PAGE_SHIFT; + ctx_vmpages_add(size >> PAGE_SHIFT); up_write(¤t->mm->mmap_sem); diff -NurP --minimal linux-2.4.22-ctx17a/arch/ia64/mm/fault.c linux-2.4.22-ctx17a-ml0.01/arch/ia64/mm/fault.c --- linux-2.4.22-ctx17a/arch/ia64/mm/fault.c 2003-08-25 20:32:07.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/arch/ia64/mm/fault.c 2003-09-05 09:28:23.000000000 +0200 @@ -33,11 +33,14 @@ unsigned long grow; grow = PAGE_SIZE >> PAGE_SHIFT; + if (!ctx_vmpages_avail(grow)) + return -ENOMEM; if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)) return -ENOMEM; vma->vm_end += PAGE_SIZE; vma->vm_mm->total_vm += grow; + ctx_vmpages_add(grow); if (vma->vm_flags & VM_LOCKED) vma->vm_mm->locked_vm += grow; return 0; diff -NurP --minimal linux-2.4.22-ctx17a/arch/s390x/kernel/exec32.c linux-2.4.22-ctx17a-ml0.01/arch/s390x/kernel/exec32.c --- linux-2.4.22-ctx17a/arch/s390x/kernel/exec32.c 2001-04-12 04:02:29.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/arch/s390x/kernel/exec32.c 2003-09-05 09:28:23.000000000 +0200 @@ -67,6 +67,7 @@ mpnt->vm_private_data = (void *) 0; insert_vm_struct(current->mm, mpnt); current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + ctx_vmpages_add((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff -NurP --minimal linux-2.4.22-ctx17a/arch/x86_64/ia32/ia32_binfmt.c linux-2.4.22-ctx17a-ml0.01/arch/x86_64/ia32/ia32_binfmt.c --- linux-2.4.22-ctx17a/arch/x86_64/ia32/ia32_binfmt.c 2003-08-25 20:32:10.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/arch/x86_64/ia32/ia32_binfmt.c 2003-09-05 09:28:23.000000000 +0200 @@ -253,6 +253,7 @@ mpnt->vm_private_data = (void *) 0; insert_vm_struct(current->mm, mpnt); current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + ctx_vmpages_add((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff -NurP --minimal linux-2.4.22-ctx17a/fs/exec.c linux-2.4.22-ctx17a-ml0.01/fs/exec.c --- linux-2.4.22-ctx17a/fs/exec.c 2003-08-26 06:27:39.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/fs/exec.c 2003-09-05 09:28:23.000000000 +0200 @@ -352,6 +352,7 @@ mpnt->vm_private_data = (void *) 0; insert_vm_struct(current->mm, mpnt); current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + ctx_vmpages_add((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff -NurP --minimal linux-2.4.22-ctx17a/fs/proc/array.c linux-2.4.22-ctx17a-ml0.01/fs/proc/array.c --- linux-2.4.22-ctx17a/fs/proc/array.c 2003-08-26 06:27:39.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/fs/proc/array.c 2003-09-05 09:28:23.000000000 +0200 @@ -316,6 +316,9 @@ ,task->s_info->flags); buffer += sprintf (buffer,"initpid: %d\n" ,task->s_info->initpid); + buffer += sprintf (buffer,"total_vm: %ld/%d\n" + ,task->s_info->rlim[RLIMIT_AS] + ,atomic_read(&task->s_info->res[RLIMIT_AS])); }else{ buffer += sprintf (buffer,"s_context: %d\n",task->s_context); buffer += sprintf (buffer,"ctxticks: none\n"); @@ -334,7 +337,7 @@ buffer += sprintf (buffer,"ipv4root_bcast: %08x\n" ,task->ip_info->v4_bcast); buffer += sprintf (buffer,"ipv4root_refcnt: %d\n" - ,task->ip_info->refcount); + ,atomic_read(&task->ip_info->refcount)); }else{ buffer += sprintf (buffer,"ipv4root: 0\n"); buffer += sprintf (buffer,"ipv4root_bcast: 0\n"); diff -NurP --minimal linux-2.4.22-ctx17a/include/linux/mm.h linux-2.4.22-ctx17a-ml0.01/include/linux/mm.h --- linux-2.4.22-ctx17a/include/linux/mm.h 2003-09-03 19:23:51.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/include/linux/mm.h 2003-09-05 09:40:36.000000000 +0200 @@ -649,6 +649,8 @@ address &= PAGE_MASK; spin_lock(&vma->vm_mm->page_table_lock); grow = (vma->vm_start - address) >> PAGE_SHIFT; + if (!ctx_vmpages_avail(grow)) + return -ENOMEM; if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur) { spin_unlock(&vma->vm_mm->page_table_lock); @@ -657,6 +659,7 @@ vma->vm_start = address; vma->vm_pgoff -= grow; vma->vm_mm->total_vm += grow; + ctx_vmpages_add(grow); if (vma->vm_flags & VM_LOCKED) vma->vm_mm->locked_vm += grow; spin_unlock(&vma->vm_mm->page_table_lock); diff -NurP --minimal linux-2.4.22-ctx17a/include/linux/sched.h linux-2.4.22-ctx17a-ml0.01/include/linux/sched.h --- linux-2.4.22-ctx17a/include/linux/sched.h 2003-08-31 17:38:34.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/include/linux/sched.h 2003-09-05 09:40:36.000000000 +0200 @@ -1017,6 +1017,35 @@ void sys_assign_ip_info (struct iproot_info *); void sys_alloc_ip_info (void); + +static inline int ctx_vmpages_avail(int pages) +{ + struct context_info *si = current->s_info; + if (!si) + return 1; + if (si->rlim[RLIMIT_AS] == RLIM_INFINITY) + return 1; + if (si->rlim[RLIMIT_AS] < atomic_read(&si->res[RLIMIT_AS]) + pages) + return 0; + return 1; +} + +static inline void ctx_vmpages_add(int pages) +{ + struct context_info *si = current->s_info; + if (!si) + return; + atomic_add(pages, &si->res[RLIMIT_AS]); +} + +static inline void ctx_vmpages_sub(int pages) +{ + struct context_info *si = current->s_info; + if (!si) + return; + atomic_sub(pages, &si->res[RLIMIT_AS]); +} + static inline int need_resched(void) { return (unlikely(current->need_resched)); diff -NurP --minimal linux-2.4.22-ctx17a/kernel/fork.c linux-2.4.22-ctx17a-ml0.01/kernel/fork.c --- linux-2.4.22-ctx17a/kernel/fork.c 2003-08-26 06:27:40.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/kernel/fork.c 2003-09-05 09:47:11.000000000 +0200 @@ -759,6 +759,9 @@ if (retval) goto bad_fork_cleanup_namespace; p->semundo = NULL; + + if (p->mm) + ctx_vmpages_add(p->mm->total_vm); /* Our parent execution domain becomes current domain These must match for thread signalling to apply */ diff -NurP --minimal linux-2.4.22-ctx17a/kernel/signal.c linux-2.4.22-ctx17a-ml0.01/kernel/signal.c --- linux-2.4.22-ctx17a/kernel/signal.c 2003-08-26 06:27:40.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/kernel/signal.c 2003-09-05 09:28:23.000000000 +0200 @@ -1458,9 +1458,11 @@ found = 1; if (p->s_info == NULL || (p->s_info->flags & S_CTX_INFO_PRIVATE)==0){ + ctx_vmpages_sub(current->mm->total_vm); sys_release_s_info(current); sys_assign_s_info (p); current->s_info = p->s_info; + ctx_vmpages_add(current->mm->total_vm); }else{ ret = -EPERM; } diff -NurP --minimal linux-2.4.22-ctx17a/kernel/sys.c linux-2.4.22-ctx17a-ml0.01/kernel/sys.c --- linux-2.4.22-ctx17a/kernel/sys.c 2003-08-26 06:27:40.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/kernel/sys.c 2003-09-05 09:28:23.000000000 +0200 @@ -1075,7 +1075,8 @@ void sys_assign_s_info (struct task_struct *p) { down_write (&uts_sem); - if (p->s_info != NULL) p->s_info->refcount++; + if (p->s_info != NULL) + p->s_info->refcount++; up_write (&uts_sem); } @@ -1123,6 +1124,9 @@ ,atomic_read(¤t->files->count)); // printk ("new s_info ctx=%d file->count %d\n",current->s_context // ,atomic_read (&s_info->res[RLIMIT_NOFILE])); + + s_info->rlim[RLIMIT_AS] = current->rlim[RLIMIT_AS].rlim_max >> PAGE_SHIFT; + atomic_set (&s_info->res[RLIMIT_AS], current->mm->total_vm); } } diff -NurP --minimal linux-2.4.22-ctx17a/mm/mmap.c linux-2.4.22-ctx17a-ml0.01/mm/mmap.c --- linux-2.4.22-ctx17a/mm/mmap.c 2003-06-13 16:51:39.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/mm/mmap.c 2003-09-05 09:28:23.000000000 +0200 @@ -500,6 +500,10 @@ !vm_enough_memory(len >> PAGE_SHIFT)) return -ENOMEM; + /* check context space, maybe only Private writable mapping? */ + if (!ctx_vmpages_avail(len >> PAGE_SHIFT)) + return -ENOMEM; + /* Can we just expand an old anonymous mapping? */ if (!file && !(vm_flags & VM_SHARED) && rb_parent) if (vma_merge(mm, prev, rb_parent, addr, addr + len, vm_flags)) @@ -581,6 +585,7 @@ out: mm->total_vm += len >> PAGE_SHIFT; + ctx_vmpages_add(len >> PAGE_SHIFT); if (vm_flags & VM_LOCKED) { mm->locked_vm += len >> PAGE_SHIFT; make_pages_present(addr, addr + len); @@ -792,6 +797,7 @@ unsigned long end = addr + len; area->vm_mm->total_vm -= len >> PAGE_SHIFT; + ctx_vmpages_sub(len >> PAGE_SHIFT); if (area->vm_flags & VM_LOCKED) area->vm_mm->locked_vm -= len >> PAGE_SHIFT; @@ -1073,6 +1079,10 @@ if (!vm_enough_memory(len >> PAGE_SHIFT)) return -ENOMEM; + /* Check against context space limits */ + if (!ctx_vmpages_avail(len >> PAGE_SHIFT)) + return -ENOMEM; + flags = VM_DATA_DEFAULT_FLAGS | mm->def_flags; /* Can we just expand an old anonymous mapping? */ @@ -1100,6 +1110,7 @@ out: mm->total_vm += len >> PAGE_SHIFT; + ctx_vmpages_add(len >> PAGE_SHIFT); if (flags & VM_LOCKED) { mm->locked_vm += len >> PAGE_SHIFT; make_pages_present(addr, addr + len); @@ -1135,6 +1146,7 @@ mm->mm_rb = RB_ROOT; mm->rss = 0; spin_unlock(&mm->page_table_lock); + ctx_vmpages_sub(mm->total_vm); mm->total_vm = 0; mm->locked_vm = 0; diff -NurP --minimal linux-2.4.22-ctx17a/mm/mremap.c linux-2.4.22-ctx17a-ml0.01/mm/mremap.c --- linux-2.4.22-ctx17a/mm/mremap.c 2003-08-25 20:32:20.000000000 +0200 +++ linux-2.4.22-ctx17a-ml0.01/mm/mremap.c 2003-09-05 09:28:23.000000000 +0200 @@ -195,6 +195,7 @@ do_munmap(current->mm, addr, old_len); current->mm->total_vm += new_len >> PAGE_SHIFT; + ctx_vmpages_add(new_len >> PAGE_SHIFT); if (vm_locked) { current->mm->locked_vm += new_len >> PAGE_SHIFT; if (new_len > old_len) @@ -295,6 +296,9 @@ !(flags & MAP_NORESERVE) && !vm_enough_memory((new_len - old_len) >> PAGE_SHIFT)) goto out; + /* check context space, maybe only Private writable mapping? */ + if (!ctx_vmpages_avail((new_len - old_len) >> PAGE_SHIFT)) + goto out; /* old_len exactly to the end of the area.. * And we're not relocating the area. @@ -312,6 +316,7 @@ vma->vm_end = addr + new_len; spin_unlock(&vma->vm_mm->page_table_lock); current->mm->total_vm += pages; + ctx_vmpages_add(pages); if (vma->vm_flags & VM_LOCKED) { current->mm->locked_vm += pages; make_pages_present(addr + old_len,
