diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/arch/m68k/atari/stram.c linux-2.4.22-ctx17a-ml0.02/arch/m68k/atari/stram.c
--- linux-2.4.22-ctx17a-ml0.01/arch/m68k/atari/stram.c	2003-06-13 16:51:31.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/arch/m68k/atari/stram.c	2003-09-11 00:09:41.000000000 +0200
@@ -643,6 +643,7 @@
 	swap_free(entry);
 	get_page(page);
 	++vma->vm_mm->rss;
+	ctx_rsspages_add(1);
 }
 
 static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/arch/x86_64/ia32/ia32_binfmt.c linux-2.4.22-ctx17a-ml0.02/arch/x86_64/ia32/ia32_binfmt.c
--- linux-2.4.22-ctx17a-ml0.01/arch/x86_64/ia32/ia32_binfmt.c	2003-09-05 09:28:23.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/arch/x86_64/ia32/ia32_binfmt.c	2003-09-11 00:10:32.000000000 +0200
@@ -261,6 +261,7 @@
 		if (page) {
 			bprm->page[i] = NULL;
 			current->mm->rss++;
+			ctx_rsspages_add(1);
 			put_dirty_page(current,page,stack_base);
 		}
 		stack_base += PAGE_SIZE;
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/fs/exec.c linux-2.4.22-ctx17a-ml0.02/fs/exec.c
--- linux-2.4.22-ctx17a-ml0.01/fs/exec.c	2003-09-05 09:28:23.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/fs/exec.c	2003-09-11 00:10:54.000000000 +0200
@@ -311,6 +311,7 @@
 		prot = vma->vm_page_prot;
 	set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, prot))));
 	tsk->mm->rss++;
+	ctx_rsspages_add(1);
 	spin_unlock(&tsk->mm->page_table_lock);
 
 	/* no need for flush_tlb */
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/fs/proc/array.c linux-2.4.22-ctx17a-ml0.02/fs/proc/array.c
--- linux-2.4.22-ctx17a-ml0.01/fs/proc/array.c	2003-09-05 09:28:23.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/fs/proc/array.c	2003-09-11 01:23:12.000000000 +0200
@@ -316,9 +316,12 @@
 			,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]));
+		buffer += sprintf (buffer,"total_vm: %d/%ld\n"
+			,atomic_read(&task->s_info->res[RLIMIT_AS])
+			,task->s_info->rlim[RLIMIT_AS]);
+		buffer += sprintf (buffer,"total_rss: %d/%ld\n"
+			,atomic_read(&task->s_info->res[RLIMIT_RSS])
+			,task->s_info->rlim[RLIMIT_RSS]);
 	}else{
 		buffer += sprintf (buffer,"s_context: %d\n",task->s_context);
 		buffer += sprintf (buffer,"ctxticks: none\n");
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/include/linux/sched.h linux-2.4.22-ctx17a-ml0.02/include/linux/sched.h
--- linux-2.4.22-ctx17a-ml0.01/include/linux/sched.h	2003-09-11 01:09:39.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/include/linux/sched.h	2003-09-11 01:04:19.000000000 +0200
@@ -1046,6 +1046,34 @@
 	atomic_sub(pages, &si->res[RLIMIT_AS]);
 }
 
+static inline int ctx_rsspages_avail(int pages)
+{
+	struct context_info *si = current->s_info;
+	if (!si)
+		return 1;
+	if (si->rlim[RLIMIT_RSS] == RLIM_INFINITY)
+		return 1;
+	if (si->rlim[RLIMIT_RSS] < atomic_read(&si->res[RLIMIT_RSS]) + pages)
+		return 0;
+	return 1;
+}
+
+static inline void ctx_rsspages_add(int pages)
+{
+	struct context_info *si = current->s_info;
+	if (!si)
+		return;
+	atomic_add(pages, &si->res[RLIMIT_RSS]);
+}
+
+static inline void ctx_rsspages_sub(int pages)
+{
+	struct context_info *si = current->s_info;
+	if (!si)
+		return;
+	atomic_sub(pages, &si->res[RLIMIT_RSS]);
+}
+
 static inline int need_resched(void)
 {
 	return (unlikely(current->need_resched));
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/kernel/fork.c linux-2.4.22-ctx17a-ml0.02/kernel/fork.c
--- linux-2.4.22-ctx17a-ml0.01/kernel/fork.c	2003-09-05 09:47:11.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/kernel/fork.c	2003-09-11 01:32:05.000000000 +0200
@@ -760,8 +760,10 @@
 		goto bad_fork_cleanup_namespace;
 	p->semundo = NULL;
 
-	if (p->mm)
+	if (p->mm) {
 		ctx_vmpages_add(p->mm->total_vm);
+		ctx_rsspages_add(p->mm->rss);
+	}
 	
 	/* Our parent execution domain becomes current domain
 	   These must match for thread signalling to apply */
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/kernel/sys.c linux-2.4.22-ctx17a-ml0.02/kernel/sys.c
--- linux-2.4.22-ctx17a-ml0.01/kernel/sys.c	2003-09-05 09:28:23.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/kernel/sys.c	2003-09-11 01:09:04.000000000 +0200
@@ -1127,6 +1127,8 @@
 		
 		s_info->rlim[RLIMIT_AS] = current->rlim[RLIMIT_AS].rlim_max >> PAGE_SHIFT;
 		atomic_set (&s_info->res[RLIMIT_AS], current->mm->total_vm);
+		s_info->rlim[RLIMIT_RSS] = current->rlim[RLIMIT_RSS].rlim_max >> PAGE_SHIFT;
+		atomic_set (&s_info->res[RLIMIT_RSS], current->mm->rss);
 	}
 }
 
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/mm/filemap.c linux-2.4.22-ctx17a-ml0.02/mm/filemap.c
--- linux-2.4.22-ctx17a-ml0.01/mm/filemap.c	2003-08-25 20:32:20.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/mm/filemap.c	2003-09-11 00:28:07.000000000 +0200
@@ -2543,6 +2543,8 @@
 				LONG_MAX; /* default: see resource.h */
 	if ((vma->vm_mm->rss + (end - start)) > rlim_rss)
 		return error;
+	if (!ctx_rsspages_avail(end - start))
+		return error;
 
 	/* round to cluster boundaries if this isn't a "random" area. */
 	if (!VM_RandomReadHint(vma)) {
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/mm/memory.c linux-2.4.22-ctx17a-ml0.02/mm/memory.c
--- linux-2.4.22-ctx17a-ml0.01/mm/memory.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.22-ctx17a-ml0.02/mm/memory.c	2003-09-11 00:32:03.000000000 +0200
@@ -392,10 +392,13 @@
 	 * Update rss for the mm_struct (not necessarily current->mm)
 	 * Notice that rss is an unsigned long.
 	 */
-	if (mm->rss > freed)
+	if (mm->rss > freed) {
+		ctx_rsspages_sub(freed);
 		mm->rss -= freed;
-	else
+	} else {
+		ctx_rsspages_sub(mm->rss);
 		mm->rss = 0;
+	}
 	spin_unlock(&mm->page_table_lock);
 }
 
@@ -981,8 +984,10 @@
 	 */
 	spin_lock(&mm->page_table_lock);
 	if (pte_same(*page_table, pte)) {
-		if (PageReserved(old_page))
+		if (PageReserved(old_page)) {
 			++mm->rss;
+			ctx_rsspages_add(1);
+		}
 		break_cow(vma, new_page, address, page_table);
 		lru_cache_add(new_page);
 
@@ -1167,6 +1172,7 @@
 		remove_exclusive_swap_page(page);
 
 	mm->rss++;
+	ctx_rsspages_add(1);
 	pte = mk_pte(page, vma->vm_page_prot);
 	if (write_access && can_share_swap_page(page))
 		pte = pte_mkdirty(pte_mkwrite(pte));
@@ -1213,6 +1219,7 @@
 			return 1;
 		}
 		mm->rss++;
+		ctx_rsspages_add(1);
 		flush_page_to_ram(page);
 		entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 		lru_cache_add(page);
@@ -1288,6 +1295,7 @@
 	/* Only go through if we didn't race with anybody else... */
 	if (pte_none(*page_table)) {
 		++mm->rss;
+		ctx_rsspages_add(1);
 		flush_page_to_ram(new_page);
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/mm/mmap.c linux-2.4.22-ctx17a-ml0.02/mm/mmap.c
--- linux-2.4.22-ctx17a-ml0.01/mm/mmap.c	2003-09-05 09:28:23.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/mm/mmap.c	2003-09-11 00:32:31.000000000 +0200
@@ -1144,6 +1144,7 @@
 	mpnt = mm->mmap;
 	mm->mmap = mm->mmap_cache = NULL;
 	mm->mm_rb = RB_ROOT;
+	ctx_rsspages_sub(mm->rss);
 	mm->rss = 0;
 	spin_unlock(&mm->page_table_lock);
 	ctx_vmpages_sub(mm->total_vm);
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/mm/swapfile.c linux-2.4.22-ctx17a-ml0.02/mm/swapfile.c
--- linux-2.4.22-ctx17a-ml0.01/mm/swapfile.c	2003-08-25 20:32:20.000000000 +0200
+++ linux-2.4.22-ctx17a-ml0.02/mm/swapfile.c	2003-09-11 00:32:50.000000000 +0200
@@ -375,6 +375,7 @@
 	set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
 	swap_free(entry);
 	++vma->vm_mm->rss;
+	ctx_rsspages_add(1);
 }
 
 /* mmlist_lock and vma->vm_mm->page_table_lock are held */
diff -NurP --minimal linux-2.4.22-ctx17a-ml0.01/mm/vmscan.c linux-2.4.22-ctx17a-ml0.02/mm/vmscan.c
--- linux-2.4.22-ctx17a-ml0.01/mm/vmscan.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.22-ctx17a-ml0.02/mm/vmscan.c	2003-09-11 00:33:04.000000000 +0200
@@ -90,6 +90,7 @@
 		set_pte(page_table, swp_entry_to_pte(entry));
 drop_pte:
 		mm->rss--;
+		ctx_rsspages_sub(1);
 		UnlockPage(page);
 		{
 			int freeable = page_count(page) - !!page->buffers <= 2;
