diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/config.in linux-openmosix/arch/i386/config.in
--- linux/arch/i386/config.in	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/i386/config.in	2004-04-06 21:16:50.000000000 +0200
@@ -10,6 +10,28 @@
 define_bool CONFIG_UID16 y
 
 mainmenu_option next_comment
+comment 'openMosix'
+bool 'openMosix process migration support' CONFIG_MOSIX
+if [ "$CONFIG_MOSIX" = "y" ]; then
+	bool 'Support clusters with a complex network topology' CONFIG_MOSIX_TOPOLOGY
+	if [ "$CONFIG_MOSIX_TOPOLOGY" = "y" ]; then
+	    int  'Maximum network-topology complexity to support (2-10)' CONFIG_MOSIX_MAXTOPOLOGY 4
+	fi
+
+	bool 'Stricter security on openMosix ports' CONFIG_MOSIX_SECUREPORTS
+	int  'Level of process-identity disclosure (0-3)' CONFIG_MOSIX_DISCLOSURE 1
+	#bool 'Create the kernel with a "-openmosix" extension' CONFIG_MOSIX_EXTMOSIX
+	bool 'openMosix File-System' CONFIG_MOSIX_FS
+	if [ "$CONFIG_MOSIX_FS" = "y" ]; then
+	   define_bool CONFIG_MOSIX_DFSA y
+	fi
+	bool 'Poll/Select exceptions on pipes' CONFIG_MOSIX_PIPE_EXCEPTIONS
+	bool 'Disable OOM Killer' CONFIG_MOSIX_NO_OOM
+	bool 'Load Limit' CONFIG_MOSIX_LOADLIMIT
+fi
+endmenu
+
+mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
 endmenu
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/defconfig linux-openmosix/arch/i386/defconfig
--- linux/arch/i386/defconfig	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/i386/defconfig	2004-02-05 10:50:54.000000000 +0100
@@ -1,6 +1,25 @@
 #
 # Automatically generated make config: don't edit
 #
+
+#
+# MOSIX options
+#
+
+CONFIG_MOSIX=y
+# CONFIG_MOSIX_TOPOLOGY is not set
+CONFIG_MOSIX_MAXTOPOLOGY=4
+# CONFIG_MOSIX_CHEAT_MIGSELF is not set
+# CONFIG_MOSIX_DEBUG is not set
+# CONFIG_MOSIX_WEEEEEEEEE is not set
+CONFIG_MOSIX_DISCLOSURE=1
+# CONFIG_MOSIX_EXTMOSIX is not set
+CONFIG_MOSIX_DIAG=y
+CONFIG_MOSIX_SECUREPORTS=y
+# CONFIG_MOSIX_DFSA is not set
+# CONFIG_MOSIX_FS is not set
+# CONFIG_MOSIX_PIPE_EXCEPTIONS is not set
+
 CONFIG_X86=y
 CONFIG_ISA=y
 # CONFIG_SBUS is not set
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/entry.S linux-openmosix/arch/i386/kernel/entry.S
--- linux/arch/i386/kernel/entry.S	2003-06-13 16:51:29.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/entry.S	2004-02-05 10:50:55.000000000 +0100
@@ -46,6 +46,10 @@
 #include <asm/segment.h>
 #include <asm/smp.h>
 
+#ifdef CONFIG_MOSIX
+#include "mosasm.H"
+#endif /* CONFIG_MOSIX */
+
 EBX		= 0x00
 ECX		= 0x04
 EDX		= 0x08
@@ -187,10 +191,16 @@
 	pushl %ebx
 	call SYMBOL_NAME(schedule_tail)
 	addl $4, %esp
+#ifdef CONFIG_MOSIX
+ENTRY(ret_from_kickstart)
+	GET_CURRENT(%ebx)
+	jmp	ret_from_sys_call
+#else
 	GET_CURRENT(%ebx)
 	testb $0x02,tsk_ptrace(%ebx)	# PT_TRACESYS
 	jne tracesys_exit
 	jmp	ret_from_sys_call
+#endif /* CONFIG_MOSIX */
 
 /*
  * Return to user mode is not as complex as all this looks,
@@ -207,14 +217,42 @@
 	jne tracesys
 	cmpl $(NR_syscalls),%eax
 	jae badsys
+#ifdef CONFIG_MOSIX
+	testl $(DTRACESYS1|DTRACESYS2),DFLAGS(%ebx)
+	jne adjust_trace_before_syscall
+adjusted_trace:
+	testb $DREMOTE,DFLAGS(%ebx)
+	je local_syscall
+on_remote:
+	pushl %eax
+	call *SYMBOL_NAME(remote_sys_call_table)(,%eax,4)
+	addl $4,%esp
+	movl %eax,EAX(%esp)
+	jmp ret_from_sys_call
+local_syscall:
+#endif /* CONFIG_MOSIX */
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# save the return value
+#ifdef CONFIG_MOSIX
+	call SYMBOL_NAME(mosix_local_syscall)
+#endif /* CONFIG_MOSIX */
 ENTRY(ret_from_sys_call)
+#ifdef CONFIG_MOSIX
+	testl $(DTRACESYS1|DTRACESYS2),DFLAGS(%ebx)
+	jne adjust_trace_before_syscall
+ret_check_reschedule:
+#endif /* CONFIG_MOSIX */
 	cli				# need_resched and signals atomic test
 	cmpl $0,need_resched(%ebx)
 	jne reschedule
 	cmpl $0,sigpending(%ebx)
 	jne signal_return
+#ifdef CONFIG_MOSIX
+straight_to_mosix:
+	call SYMBOL_NAME(mosix_pre_usermode_actions)
+	testl %eax,%eax
+	jne ret_from_sys_call
+#endif /* CONFIG_MOSIX */
 restore_all:
 	RESTORE_ALL
 
@@ -226,7 +264,11 @@
 	jne v86_signal_return
 	xorl %edx,%edx
 	call SYMBOL_NAME(do_signal)
+#ifdef CONFIG_MOSIX
+	jmp straight_to_mosix
+#else
 	jmp restore_all
+#endif /* CONFIG_MOSIX */
 
 	ALIGN
 v86_signal_return:
@@ -234,18 +276,41 @@
 	movl %eax,%esp
 	xorl %edx,%edx
 	call SYMBOL_NAME(do_signal)
+#ifdef CONFIG_MOSIX
+	jmp straight_to_mosix
+#else
 	jmp restore_all
+#endif /* CONFIG_MOSIX */
 
 	ALIGN
 tracesys:
 	movl $-ENOSYS,EAX(%esp)
 	call SYMBOL_NAME(syscall_trace)
+#ifdef CONFIG_MOSIX
+adjust_trace_before_syscall:		# only arrive here with DTRACESYS(1|2)
+	testl $DDEPUTY,DFLAGS(%ebx)
+	jne straight_to_mosix		# no mess with signals/syscalls/tracesys
+	testl $DREMOTE,DFLAGS(%ebx)
+	je no_need_to_unsync
+	call wait_for_permission_to_continue
+no_need_to_unsync:
+	testl $DTRACESYS2,DFLAGS(%ebx)
+	jne second_tracesys		# skipping system-call
+	orl $DTRACESYS2,DFLAGS(%ebx)	# next time we skip the system-call
+	movl $-ENOSYS,EAX(%esp)
+	movl ORIG_EAX(%esp),%eax
+	cmpl $(NR_syscalls),%eax
+	jae second_tracesys		# prevent system-call out of range trick
+	jmp adjusted_trace		# now do the system-call
+second_tracesys:			# note: "syscall_trace" clears the flags
+#else
 	movl ORIG_EAX(%esp),%eax
 	cmpl $(NR_syscalls),%eax
 	jae tracesys_exit
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# save the return value
 tracesys_exit:
+#endif /* CONFIG_MOSIX */
 	call SYMBOL_NAME(syscall_trace)
 	jmp ret_from_sys_call
 badsys:
@@ -259,7 +324,11 @@
 	movl EFLAGS(%esp),%eax		# mix EFLAGS and CS
 	movb CS(%esp),%al
 	testl $(VM_MASK | 3),%eax	# return to VM86 mode or non-supervisor?
+#ifdef CONFIG_MOSIX
+	jne ret_check_reschedule
+#else
 	jne ret_from_sys_call
+#endif /* CONFIG_MOSIX */
 	jmp restore_all
 
 	ALIGN
@@ -267,6 +336,73 @@
 	call SYMBOL_NAME(schedule)    # test
 	jmp ret_from_sys_call
 
+#ifdef CONFIG_MOSIX
+/*
+ * call_with_regs(caddr_t routine, pt_regs *before, pt_regs *after)
+ * pushes the "before" regs on the stack and calls routine,
+ * then places the possibly-modified registers in "after"
+ * (which may possibly equal "before").
+ * Also, set "current->altregs" to the pushed registers, then restores it.
+ */
+ENTRY(call_with_regs)
+	pushl	%ebx
+	GET_CURRENT(%ebx)
+	pushl	ALTREGS(%ebx)
+	movl	16(%esp),%eax
+	pushl	56(%eax)
+	pushl	52(%eax)
+	pushl	48(%eax)
+	pushl	44(%eax)
+	pushl	40(%eax)
+	pushl	36(%eax)
+	pushl	32(%eax)
+	pushl	28(%eax)
+	pushl	24(%eax)
+	pushl	20(%eax)
+	pushl	16(%eax)
+	pushl	12(%eax)
+	pushl	8(%eax)
+	pushl	4(%eax)
+	pushl	0(%eax)
+	movl	%esp,ALTREGS(%ebx)
+	movl	72(%esp),%eax
+	call	*%eax
+	movl	80(%esp),%edx
+	popl	%ecx
+	movl	%ecx,0(%edx)
+	popl	%ecx
+	movl	%ecx,4(%edx)
+	popl	%ecx
+	movl	%ecx,8(%edx)
+	popl	%ecx
+	movl	%ecx,12(%edx)
+	popl	%ecx
+	movl	%ecx,16(%edx)
+	popl	%ecx
+	movl	%ecx,20(%edx)
+	popl	%ecx
+	movl	%ecx,24(%edx)
+	popl	%ecx
+	movl	%ecx,28(%edx)
+	popl	%ecx
+	movl	%ecx,32(%edx)
+	popl	%ecx
+	movl	%ecx,36(%edx)
+	popl	%ecx
+	movl	%ecx,40(%edx)
+	popl	%ecx
+	movl	%ecx,44(%edx)
+	popl	%ecx
+	movl	%ecx,48(%edx)
+	popl	%ecx
+	movl	%ecx,52(%edx)
+	popl	%ecx
+	movl	%ecx,56(%edx)
+	popl	ALTREGS(%ebx)
+	popl	%ebx
+	ret
+#endif /* CONFIG_MOSIX */
+
 ENTRY(divide_error)
 	pushl $0		# no error code
 	pushl $ SYMBOL_NAME(do_divide_error)
@@ -410,7 +546,11 @@
 	.long SYMBOL_NAME(sys_read)
 	.long SYMBOL_NAME(sys_write)
 	.long SYMBOL_NAME(sys_open)		/* 5 */
+#ifdef CONFIG_MOSIX_DFSA
+	.long SYMBOL_NAME(sys_close_syscall)
+#else
 	.long SYMBOL_NAME(sys_close)
+#endif /* CONFIG_MOSIX_DFSA */
 	.long SYMBOL_NAME(sys_waitpid)
 	.long SYMBOL_NAME(sys_creat)
 	.long SYMBOL_NAME(sys_link)
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/i387.c linux-openmosix/arch/i386/kernel/i387.c
--- linux/arch/i386/kernel/i387.c	2003-08-25 13:44:39.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/i387.c	2004-02-05 10:50:55.000000000 +0100
@@ -544,3 +544,66 @@
 
 	return fpvalid;
 }
+
+#ifdef CONFIG_MOSIX
+
+int
+has_fxsr(void)
+{
+	return(cpu_has_fxsr);
+}
+
+void
+fsave_to_fxsave(union i387_union *from, union i387_union *to)
+{
+	int i;
+	long *fcp, *tcp;
+
+	to->fxsave.cwd = from->fsave.cwd;
+	to->fxsave.swd = from->fsave.swd;
+	to->fxsave.twd = twd_i387_to_fxsr(from->fsave.twd);
+	to->fxsave.fop = from->fxsave.padding[0];
+	to->fxsave.fip = from->fsave.fip;
+	to->fxsave.fcs = from->fsave.fcs;
+	to->fxsave.foo = from->fsave.foo;
+	to->fxsave.mxcsr = from->fxsave.padding[1];
+	to->fxsave.fos = from->fsave.fos;
+	for(fcp = from->fsave.st_space , tcp = to->fxsave.st_space ,
+		i = 0 ; i < 8 ; i++)
+	{
+		*tcp++ = *fcp++;
+		*tcp++ = *fcp++;
+		*tcp = *((unsigned short *)fcp)++;
+		tcp += 2;
+	}
+	memcpy(to->fxsave.xmm_space, from->fxsave.xmm_space,
+						sizeof(from->fxsave.xmm_space));
+}
+
+void
+fxsave_to_fsave(union i387_union *from, union i387_union *to)
+{
+	int i;
+	long *fcp, *tcp;
+
+	to->fsave.cwd = from->fxsave.cwd;
+	to->fsave.swd = from->fxsave.swd;
+	to->fsave.twd = twd_fxsr_to_i387(&from->fxsave);
+	to->fsave.fip = from->fxsave.fip;
+	to->fsave.fcs = from->fxsave.fcs;
+	to->fsave.foo = from->fxsave.foo;
+	to->fsave.fos = from->fxsave.fos;
+	to->fxsave.padding[0] = from->fxsave.fop;
+	to->fxsave.padding[1] = from->fxsave.mxcsr;
+	for(fcp = from->fxsave.st_space , tcp = to->fsave.st_space ,
+		i = 0 ; i < 8 ; i++)
+	{
+		*tcp++ = *fcp++;
+		*tcp++ = *fcp++;
+		*((unsigned short *)tcp)++ = *fcp;
+		fcp += 2;
+	}
+	memcpy(to->fxsave.xmm_space, from->fxsave.xmm_space,
+						sizeof(to->fxsave.xmm_space));
+}
+#endif /* CONFIG_MOSIX */
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/ioport.c linux-openmosix/arch/i386/kernel/ioport.c
--- linux/arch/i386/kernel/ioport.c	2003-06-13 16:51:29.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/ioport.c	2004-02-05 10:50:55.000000000 +0100
@@ -15,6 +15,10 @@
 #include <linux/smp_lock.h>
 #include <linux/stddef.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
 static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
 {
@@ -61,6 +65,10 @@
 		return -EINVAL;
 	if (turn_on && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
+#ifdef CONFIG_MOSIX
+	if(turn_on && !mosix_go_home_for_reason(1, DSTAY_FOR_IOPL))
+		return(-ENOMEM);
+#endif /* CONFIG_MOSIX */
 	/*
 	 * If it's the first ioperm() call in this thread's lifetime, set the
 	 * IO bitmap up. ioperm() is much less timing critical than clone(),
@@ -112,6 +120,11 @@
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
+#ifdef CONFIG_MOSIX
+	if(!mosix_go_home_for_reason(1, DSTAY_FOR_IOPL))
+		return(-ENOMEM);
+	regs = mos_to_regs(&current->mosix);
+#endif /* CONFIG_MOSIX */
 	regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
 	return 0;
 }
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/Makefile linux-openmosix/arch/i386/kernel/Makefile
--- linux/arch/i386/kernel/Makefile	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/i386/kernel/Makefile	2004-02-05 10:50:55.000000000 +0100
@@ -45,3 +45,14 @@
 obj-$(CONFIG_EDD)             	+= edd.o
 
 include $(TOPDIR)/Rules.make
+
+ifdef CONFIG_MOSIX
+entry.o: ./mosasm.H
+
+offset: offset.c $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/types.h $(TOPDIR)/include/linux/sched.h $(TOPDIR)/include/linux/signal.h $(TOPDIR)/include/linux/sys.h $(TOPDIR)/include/linux/kernel.h
+	$(HOSTCC) $(HOSTCFLAGS) -D__KERNEL__ -I$(TOPDIR)/include -o offset offset.c
+
+./mosasm.H: offset entry.S
+	./offset < entry.S > mosasm.H
+
+endif
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/offset.c linux-openmosix/arch/i386/kernel/offset.c
--- linux/arch/i386/kernel/offset.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/arch/i386/kernel/offset.c	2003-09-10 20:48:31.000000000 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, Amnon Barak (amnon@MOSIX.org)
+ * Some sections copyright 2002 by Moshe Bar
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+/*
+ * Produce an include-file for "entry.S", with:
+ * 1. constant-offsets of some required MOSIX-members of "task_struct"
+ * 2. some bits to test "current->dflags"
+ * 3. a duplicate system-call table (remote_sys_call_table), with all
+ *    system-calls names preceded by a "remote_".
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/sys.h>
+
+struct file;
+#define FILE	struct file
+
+extern int printf(char *, ...);
+extern int fgets(char *, int, FILE *);
+extern int perror(char *);
+extern FILE *stdin;
+
+char line[2048];
+
+int
+main(void)
+{
+	register char *c;
+	long t, time(long *);
+	char *ctime(long *);
+
+	time(&t);
+	printf("/* Please do not edit -- this file is created automatically */\n");
+	printf("/* %.24s */\n\n", ctime(&t));
+	printf("ALTREGS\t\t= 0x%X\n",
+		(int)&(((struct task_struct *)0)->mosix.altregs));
+	printf("DFLAGS\t\t= 0x%X\n",
+		(int)&(((struct task_struct *)0)->mosix.dflags));
+	printf("DDEPUTY\t\t= 0x%X\n", DDEPUTY);
+	printf("DREMOTE\t\t= 0x%X\n", DREMOTE);
+	printf("DTRACESYS1\t\t= 0x%X\n", DTRACESYS1);
+	printf("DTRACESYS2\t\t= 0x%X\n", DTRACESYS2);
+	printf(".data\n");
+	printf("\nENTRY(remote_sys_call_table)\n");
+	while(fgets(line, 2048, stdin) &&
+		strcmp(line, "ENTRY(sys_call_table)\n"))
+			;
+	while(fgets(line, 2048, stdin))
+	if(!strncmp(line, "\t.long SYMBOL_NAME(", 19))
+	{
+		for(c = &line[19] ; *c && *c != ')' ; c++);
+		*c = '\0';
+		if(!strcmp(&line[19], "sys_ni_syscall"))
+		{
+			printf("\t.long SYMBOL_NAME(sys_ni_syscall)\n");
+			continue;
+		}
+		printf("\t.long SYMBOL_NAME(remote_%s)\n", &line[19]);
+	}
+	else if(!strcmp(line, "\t.rept NR_syscalls-(.-sys_call_table)/4\n"))
+		printf("\t.rept NR_syscalls-(.-remote_sys_call_table)/4\n");
+	else
+	{
+		printf("%s", line);
+		if(!strncmp(line, "\t.endr", 5))
+			break;
+	}
+	printf(".text\n");
+	return(0);
+}
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/process.c linux-openmosix/arch/i386/kernel/process.c
--- linux/arch/i386/kernel/process.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/i386/kernel/process.c	2004-02-05 10:50:55.000000000 +0100
@@ -52,6 +52,10 @@
 
 #include <linux/irq.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int hlt_counter;
@@ -163,6 +167,8 @@
 /* shamelessly grabbed from lib/vsprintf.c for readability */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
 #endif
+
+
 static int __init reboot_setup(char *str)
 {
 	while(1) {
@@ -522,6 +528,43 @@
 	return retval;
 }
 
+#ifdef CONFIG_MOSIX
+/*
+ * Create a thread that starts as kernel, but will eventually run in user-mode:
+ * The slight differences from "kernel_thread" are:
+ * 1) not using CLONE_VM.
+ * 2) adding SIGCHLD to the flags.
+ * 3) leaving space on the stack for the user-registers.
+ */
+int arch_user_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	long retval, d0;
+
+	__asm__ __volatile__(
+		"movl %%esp,%%esi\n\t"
+		"int $0x80\n\t"		/* Linux/i386 system call */
+		"cmpl %%esp,%%esi\n\t"	/* child or parent? */
+		"je 1f\n\t"		/* parent - jump */
+		"subl %7,%%esp\n\t"	/* space for user-registers */
+		/* Load the argument into eax, and push it.  That way, it does
+		 * not matter whether the called function is compiled with
+		 * -mregparm or not.  */
+		"movl %4,%%eax\n\t"
+		"pushl %%eax\n\t"		
+		"call *%5\n\t"		/* call fn */
+		"movl %3,%0\n\t"	/* exit */
+		"int $0x80\n"
+		"1:\t"
+		:"=&a" (retval), "=&S" (d0)
+		:"0" (__NR_clone), "i" (__NR_exit),
+		 "r" (arg), "r" (fn),
+		 "b" (flags | SIGCHLD),
+		 "i" (sizeof(struct pt_regs))
+		: "memory");
+	return retval;
+}
+#endif /* CONFIG_MOSIX */
+
 /*
  * Free current thread data structures etc..
  */
@@ -597,6 +640,10 @@
 
 	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
 	struct_cpy(childregs, regs);
+#ifdef CONFIG_MOSIX
+	p->mosix.altregs = (uint32_t *)childregs;
+	p->mosix.deputy_regs = current->mosix.deputy_regs;
+#endif /* CONFIG_MOSIX */
 	childregs->eax = 0;
 	childregs->esp = esp;
 
@@ -748,10 +795,32 @@
 			 */
 			tss->bitmap = INVALID_IO_BITMAP_OFFSET;
 	}
+#ifdef CONFIG_MOSIX
+	if(test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
+	{
+		/* REMOTE emulates the RDTSC instruction */
+		if(next_p->mosix.dflags & DREMOTE)
+		{
+			if(!(prev_p->mosix.dflags & DREMOTE))
+				__asm__ __volatile__("movl %%cr4,%%eax\n\t" \
+					"orl $4,%%eax\n\t" \
+					"movl %%eax,%%cr4\n" \
+					: : :"ax");
+		}
+		else if(prev_p->mosix.dflags & DREMOTE)
+			__asm__ __volatile__("movl %%cr4,%%eax\n\t" \
+				"andl $0xfffffffb,%%eax\n\t" \
+				"movl %%eax,%%cr4\n" \
+				: : :"ax");
+	}
+#endif /* CONFIG_MOSIX */
 }
 
 asmlinkage int sys_fork(struct pt_regs regs)
 {
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(BIT_OF_REGISTER(esp));
+#endif /* CONFIG_MOSIX */
 	return do_fork(SIGCHLD, regs.esp, &regs, 0);
 }
 
@@ -759,12 +828,27 @@
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
+#ifdef CONFIG_MOSIX
+	int retval;
+#endif /* CONFIG_MOSIX */
 
 	clone_flags = regs.ebx;
 	newsp = regs.ecx;
 	if (!newsp)
+#ifdef CONFIG_MOSIX
+		mosix_obtain_registers(BIT_OF_REGISTER(esp)) ,
+#endif /* CONFIG_MOSIX */
 		newsp = regs.esp;
+#ifdef CONFIG_MOSIX
+	if((clone_flags & CLONE_VM) && (retval = mosix_pre_clone()))
+		return(retval);
+	retval = do_fork(clone_flags, newsp, &regs, 0);
+	if(clone_flags & CLONE_VM)
+		mosix_post_clone();
+	return(retval);
+#else
 	return do_fork(clone_flags, newsp, &regs, 0);
+#endif /* CONFIG_MOSIX */
 }
 
 /*
@@ -779,7 +863,18 @@
  */
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
+#ifdef CONFIG_MOSIX
+	int retval;
+
+	mosix_obtain_registers(BIT_OF_REGISTER(esp));
+	if((retval = mosix_pre_clone()))
+		return(retval);
+	retval = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
+	mosix_post_clone();
+	return(retval);
+#else
 	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
+#endif /* CONFIG_MOSIX */
 }
 
 /*
@@ -815,23 +910,50 @@
 	unsigned long ebp, esp, eip;
 	unsigned long stack_page;
 	int count = 0;
+#ifdef CONFIG_MOSIX
+	unsigned long result = 0;
+	if (!p || p == current || LOGICAL_STATE(p) == TASK_RUNNING)
+#else
 	if (!p || p == current || p->state == TASK_RUNNING)
+#endif /* CONFIG_MOSIX */
 		return 0;
 	stack_page = (unsigned long)p;
 	esp = p->thread.esp;
 	if (!stack_page || esp < stack_page || esp > 8188+stack_page)
+#ifdef CONFIG_MOSIX
+		return(result);
+#else
 		return 0;
+#endif /* CONFIG_MOSIX */
 	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
 	ebp = *(unsigned long *) esp;
 	do {
 		if (ebp < stack_page || ebp > 8184+stack_page)
+#ifdef CONFIG_MOSIX
+			return(result);
+#else
 			return 0;
+#endif /* CONFIG_MOSIX */
 		eip = *(unsigned long *) (ebp+4);
 		if (eip < first_sched || eip >= last_sched)
+#ifdef CONFIG_MOSIX
+		{
+			if(!result)
+				return eip;
+		}
+		else
+			result = 0;
+#else
 			return eip;
+#endif /* CONFIG_MOSIX */
 		ebp = *(unsigned long *) ebp;
+#ifdef CONFIG_MOSIX
+	} while (count++ < 64);
+	return(result);
+#else
 	} while (count++ < 16);
 	return 0;
+#endif /* CONFIG_MOSIX */
 }
 #undef last_sched
 #undef first_sched
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/ptrace.c linux-openmosix/arch/i386/kernel/ptrace.c
--- linux/arch/i386/kernel/ptrace.c	2002-08-03 02:39:42.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/ptrace.c	2004-02-05 10:50:55.000000000 +0100
@@ -21,6 +21,10 @@
 #include <asm/i387.h>
 #include <asm/debugreg.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -44,13 +48,47 @@
  * this routine assumes that all the privileged stacks are in our
  * data space.
  */   
+#ifdef CONFIG_MOSIX
+inline int get_stack_long(struct task_struct *task, int offset)
+#else
 static inline int get_stack_long(struct task_struct *task, int offset)
+#endif /* CONFIG_MOSIX */
 {
 	unsigned char *stack;
 
+#ifdef CONFIG_MOSIX
+	if(task != current)
+		lock_mosix();
+	if(task->mosix.dflags & DDEPUTY)
+	{
+		if(task != current)
+			unlock_mosix();
+		return(request_process(task, NULL, PR_PTRACE_GET_STACK_LONG,
+			offset));
+	}
+	if(task == current)
+		mosix_obtain_registers(ALL_REGISTERS);
+	else
+		task_lock(task);
+	if(!task->thread.saved_esp0)	/* unless in VM86 mode */
+		stack = (char *)(mos_to_regs(&task->mosix) + 1);
+	else
+#endif /* CONFIG_MOSIX */
 	stack = (unsigned char *)task->thread.esp0;
 	stack += offset;
+#ifdef CONFIG_MOSIX
+	{
+		int res = *((int *)stack);
+		if(task != current)
+		{
+			task_unlock(task);
+			unlock_mosix();
+		}
+		return(res);
+	}
+#else
 	return (*((int *)stack));
+#endif /* CONFIG_MOSIX */
 }
 
 /*
@@ -59,14 +97,43 @@
  * this routine assumes that all the privileged stacks are in our
  * data space.
  */
+#ifdef CONFIG_MOSIX
+inline int put_stack_long(struct task_struct *task, int offset,
+#else
 static inline int put_stack_long(struct task_struct *task, int offset,
+#endif /* CONFIG_MOSIX */
 	unsigned long data)
 {
 	unsigned char * stack;
 
+#ifdef CONFIG_MOSIX
+	if(task != current)
+		lock_mosix();
+	if(task->mosix.dflags & DDEPUTY)
+	{
+		if(task != current)
+			unlock_mosix();
+		return(request_process_arg2(task, NULL,
+			PR_PTRACE_PUT_STACK_LONG, offset, data));
+	}
+	if(task == current)
+		mosix_obtain_registers(ALL_REGISTERS);
+	else
+		task_lock(task);
+	if(!task->thread.saved_esp0)	/* unless in VM86 mode */
+		stack = (char *)(mos_to_regs(&task->mosix) + 1);
+	else
+#endif /* CONFIG_MOSIX */
 	stack = (unsigned char *) task->thread.esp0;
 	stack += offset;
 	*(unsigned long *) stack = data;
+#ifdef CONFIG_MOSIX
+	if(task != current)
+	{
+		task_unlock(task);
+		unlock_mosix();
+	}
+#endif /* CONFIG_MOSIX */
 	return 0;
 }
 
@@ -107,6 +174,17 @@
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+void
+ptrace_putregs(unsigned long *data)
+{
+	register int i;
+
+	for (i = 0; i < FRAME_SIZE ; i++)
+		putreg(current, i << 2, data[i]);
+}
+#endif /* CONFIG_MOSIX */
+
 static unsigned long getreg(struct task_struct *child,
 	unsigned long regno)
 {
@@ -147,6 +225,17 @@
 	put_stack_long(child, EFL_OFFSET, tmp);
 }
 
+#ifdef CONFIG_MOSIX
+void
+ptrace_getregs(unsigned long *data)
+{
+	register int i;
+
+	for (i = 0; i < FRAME_SIZE ; i++)
+		data[i] = getreg(current, i << 2);
+}
+#endif /* CONFIG_MOSIX */
+
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -161,6 +250,9 @@
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
+#ifdef CONFIG_MOSIX_DFSA
+		tell_process(current, DREQ_NOTUPTODATE);
+#endif /* CONFIG_MOSIX_DFSA */
 		ret = 0;
 		goto out;
 	}
@@ -210,6 +302,17 @@
 		    addr > sizeof(struct user) - 3)
 			break;
 
+#ifdef CONFIG_MOSIX
+		lock_mosix();
+		if(child->mosix.dflags & DDEPUTY)
+		{
+			unlock_mosix();
+			if(request_process(child, &tmp, PR_PTRACE_PEEKUSER, addr))
+				goto out;
+		}
+		else
+		{
+#endif /* CONFIG_MOSIX */
 		tmp = 0;  /* Default return condition */
 		if(addr < FRAME_SIZE*sizeof(long))
 			tmp = getreg(child, addr);
@@ -219,6 +322,10 @@
 			addr = addr >> 2;
 			tmp = child->thread.debugreg[addr];
 		}
+#ifdef CONFIG_MOSIX
+		unlock_mosix();
+		}
+#endif /* CONFIG_MOSIX */
 		ret = put_user(tmp,(unsigned long *) data);
 		break;
 	}
@@ -265,7 +372,23 @@
 
 			  addr -= (long) &dummy->u_debugreg;
 			  addr = addr >> 2;
+#ifdef CONFIG_MOSIX
+			  lock_mosix();
+			  if(child->mosix.dflags & DDEPUTY)
+			  {
+				unlock_mosix();
+				if(request_process_arg2(child, NULL,
+					PR_PTRACE_POKEUSER, addr, data))
+					goto out;
+			  }
+			  else
+			  {
+#endif /* CONFIG_MOSIX */
 			  child->thread.debugreg[addr] = data;
+#ifdef CONFIG_MOSIX
+			  unlock_mosix();
+			  }
+#endif /* CONFIG_MOSIX */
 			  ret = 0;
 		  }
 		  break;
@@ -282,9 +405,22 @@
 		else
 			child->ptrace &= ~PT_TRACESYS;
 		child->exit_code = data;
+#ifdef CONFIG_MOSIX
+		if(child->mosix.dflags & DDEPUTY)
+		{
+			if(request_process(child, NULL, PR_PTRACE_CONT,
+								request))
+				goto out;
+		}
+		else
+		{
+#endif /* CONFIG_MOSIX */
 	/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET,tmp);
+#ifdef CONFIG_MOSIX
+		}
+#endif /* CONFIG_MOSIX */
 		wake_up_process(child);
 		ret = 0;
 		break;
@@ -299,7 +435,11 @@
 		long tmp;
 
 		ret = 0;
+#ifdef CONFIG_MOSIX
+		if (LOGICAL_STATE(child) == TASK_ZOMBIE) /* already dead */
+#else
 		if (child->state == TASK_ZOMBIE)	/* already dead */
+#endif /* CONFIG_MOSIX */
 			break;
 		child->exit_code = SIGKILL;
 		/* make sure the single step bit is not set. */
@@ -320,8 +460,21 @@
 			/* Spurious delayed TF traps may occur */
 			child->ptrace |= PT_DTRACE;
 		}
+#ifdef CONFIG_MOSIX
+		if(child->mosix.dflags & DDEPUTY)
+		{
+			if(request_process(child, NULL, PR_PTRACE_SINGLE_STEP,
+									0))
+				goto out;
+		}
+		else
+		{
+#endif /* CONFIG_MOSIX */
 		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
+#ifdef CONFIG_MOSIX
+		}
+#endif /* CONFIG_MOSIX */
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -339,26 +492,57 @@
 			ret = -EIO;
 			break;
 		}
+#ifdef CONFIG_MOSIX
+		/* NOTE: even when child does not look like a DEPUTY,
+		 * it could easily become one while we wait for a page
+		 * on __put_user ... therefore, we do this ALWAYS:
+		 */
+		{
+			unsigned long t[FRAME_SIZE];
+
+			if(request_process(child, &t, PR_PTRACE_GETREGS, 0))
+				ret = -EIO;
+			else
+				copy_to_user((void *)data, t, sizeof(t));
+		}
+#else
 		for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
 			__put_user(getreg(child, i),(unsigned long *) data);
 			data += sizeof(long);
 		}
+#endif /* CONFIG_MOSIX */
 		ret = 0;
 		break;
 	}
 
 	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+#ifndef CONFIG_MOSIX
 		unsigned long tmp;
+#endif /* CONFIG_MOSIX */
 	  	if (!access_ok(VERIFY_READ, (unsigned *)data, FRAME_SIZE*sizeof(long))) {
 			ret = -EIO;
 			break;
 		}
+#ifdef CONFIG_MOSIX
+		/* NOTE: even when child does not look like a DEPUTY,
+		 * it could easily become one while we wait for a page
+		 * on __get_user ... therefore, we do this ALWAYS:
+		 */
+		{
+			unsigned long t[FRAME_SIZE];
+
+			copy_from_user(t, (void *)data, sizeof(t));
+			ret = request_process(child, &t, PR_PTRACE_SETREGS, 0)
+								? -EIO : 0;
+		}
+#else
 		for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
 			__get_user(tmp, (unsigned long *) data);
 			putreg(child, i, tmp);
 			data += sizeof(long);
 		}
 		ret = 0;
+#endif /* CONFIG_MOSIX */
 		break;
 	}
 
@@ -369,9 +553,27 @@
 			break;
 		}
 		ret = 0;
+#ifdef CONFIG_MOSIX
+		/* DEPUTY or NOT - the child-process may become DEPUTY
+		 * while we page-fault on "__copy_to_user",
+		 * so we always do it the long way:
+		 */
+		{
+			struct user_i387_struct f;
+
+			if(request_process(child, &f, PR_PTRACE_GETFPREGS, 0))
+			{
+				ret = -EIO;
+				goto out;
+			}
+			__copy_to_user((void *)data, &f,
+				sizeof(struct user_i387_struct));
+		}
+#else
 		if ( !child->used_math )
 			load_empty_fpu(child);
 		get_fpregs((struct user_i387_struct *)data, child);
+#endif /* CONFIG_MOSIX */
 		break;
 	}
 
@@ -381,9 +583,23 @@
 			ret = -EIO;
 			break;
 		}
+#ifdef CONFIG_MOSIX
+		/* DEPUTY or NOT - the child-process may become DEPUTY
+		 * while we page-fault on "__copy_from_user",
+		 * so we always do it the long way:
+		 */
+		{
+			struct user_i387_struct f;
+
+			__copy_from_user(&f, (void *)data, sizeof(f));
+			ret = request_process(child, &f, PR_PTRACE_SETFPREGS, 0)
+								? -EIO : 0;
+		}
+#else
 		child->used_math = 1;
 		set_fpregs(child, (struct user_i387_struct *)data);
 		ret = 0;
+#endif /* CONFIG_MOSIX */
 		break;
 	}
 
@@ -393,9 +609,28 @@
 			ret = -EIO;
 			break;
 		}
+#ifdef CONFIG_MOSIX
+		ret = 0;
+		/* DEPUTY or NOT - the child-process may become DEPUTY
+		 * while we page-fault on "__copy_to_user",
+		 * so we always do it the long way:
+		 */
+		{
+			struct user_fxsr_struct f;
+
+			if(request_process(child, &f, PR_PTRACE_GETFPXREGS, 0))
+			{
+				ret = -EIO;
+				goto out;
+			}
+			__copy_to_user((void *)data, &f,
+				sizeof(struct user_fxsr_struct));
+		}
+#else
 		if ( !child->used_math )
 			load_empty_fpu(child);
 		ret = get_fpxregs((struct user_fxsr_struct *)data, child);
+#endif /* CONFIG_MOSIX */
 		break;
 	}
 
@@ -405,8 +640,22 @@
 			ret = -EIO;
 			break;
 		}
+#ifdef CONFIG_MOSIX
+		/* DEPUTY or NOT - the child-process may become DEPUTY
+		 * while we page-fault on "__copy_from_user",
+		 * so we always do it the long way:
+		 */
+		{
+			struct user_fxsr_struct f;
+
+			__copy_from_user(&f, (void *)data, sizeof(f));
+			ret = request_process(child, &f, PR_PTRACE_SETFPXREGS,
+								0) ? -EIO : 0;
+		}
+#else
 		child->used_math = 1;
 		ret = set_fpxregs(child, (struct user_fxsr_struct *)data);
+#endif /* CONFIG_MOSIX */
 		break;
 	}
 
@@ -430,7 +679,163 @@
 	return ret;
 }
 
+#ifdef CONFIG_MOSIX
+/*
+ * The following routines are parts of sys_ptrace performed by the
+ * child process on itself.
+ * Should the relevant code in "sys_ptrace" change, the following routines
+ * must also be modified accordingly.
+ */
+unsigned long
+ptrace_peekuser(long addr)
+{
+	struct user * dummy = NULL;
+	unsigned long tmp;
+
+	tmp = 0;  /* Default return condition */
+	if(addr < FRAME_SIZE*sizeof(long))
+		tmp = getreg(current, addr);
+	if(addr >= (long) &dummy->u_debugreg[0] &&
+	   addr <= (long) &dummy->u_debugreg[7]){
+		addr -= (long) &dummy->u_debugreg[0];
+		addr = addr >> 2;
+		tmp = current->thread.debugreg[addr];
+	};
+	return(tmp);
+}
+
+void
+ptrace_pokeuser(long addr, long data)
+{
+	current->thread.debugreg[addr] = data;
+#define loaddebug(tsk,register) \
+		__asm__("movl %0,%%db" #register  \
+			: /* no output */ \
+			:"r" (tsk->thread.debugreg[register]))
+	/* unlike the original ptrace code, we are doing this for ourselves,
+	 * and there may be no "switch_to" before we go to user-mode again,
+	 * so here we go:
+	 */
+	if(current->thread.debugreg[7])
+	{
+		loaddebug(current, 0);
+		loaddebug(current, 1);
+		loaddebug(current, 2);
+		loaddebug(current, 3);
+		loaddebug(current, 6);
+		loaddebug(current, 7);
+	}
+}
+
+void
+ptrace_cont(int request)
+{
+	unsigned long tmp;
+	struct task_struct *tsk = current;
+
+	tmp = get_stack_long(tsk, EFL_OFFSET) & ~TRAP_FLAG;
+	put_stack_long(tsk, EFL_OFFSET, tmp);
+	if (request == PTRACE_SYSCALL)
+		tsk->ptrace |= PT_TRACESYS;
+	else
+		tsk->ptrace &= ~PT_TRACESYS;
+	if (request == PTRACE_DETACH)
+		tsk->ptrace &= ~PT_PTRACED;
+}
+
+void
+ptrace_single_step(void)
+{
+	unsigned long tmp;
+
+	tmp = get_stack_long(current, EFL_OFFSET) | TRAP_FLAG;
+	put_stack_long(current, EFL_OFFSET, tmp);
+	current->ptrace |= PT_PTRACED | PT_DTRACE;
+#ifdef CONFIG_MOSIX_DFSA
+	tell_process(current, DREQ_NOTUPTODATE);
+#endif /* CONFIG_MOSIX_DFSA */
+}
+
+void
+ptrace_getfpregs(struct user_i387_struct *to)
+{
+	struct task_struct *p = current;
+
+	unlazy_fpu(p);
+	if (!p->used_math)
+		load_empty_fpu(p);
+	get_fpregs(to, p);
+}
+
+void
+ptrace_getfpxregs(struct user_fxsr_struct *to)
+{
+	struct task_struct *p = current;
+
+	unlazy_fpu(p);
+	if (!p->used_math)
+		load_empty_fpu(p);
+	get_fpxregs(to, p);
+}
+
+void
+ptrace_setfpregs(struct user_i387_struct *from)
+{
+	struct task_struct *p = current;
+
+	clear_fpu(p);
+	p->used_math = 1;
+	set_fpregs(p, from);
+}
+
+void
+ptrace_setfpxregs(struct user_fxsr_struct *from)
+{
+	struct task_struct *p = current;
+
+	clear_fpu(p);
+	p->used_math = 1;
+	set_fpxregs(p, from);
+}
+#endif /* CONFIG_MOSIX */
+
+#ifdef CONFIG_MOSIX
+/*
+ * When a process starts a system call in PT_TRACESYS mode, it must run
+ * the full sequence: A=syscall_trace, B=the_system_call, C=syscall_trace.
+ * Since our process can migrate at any of those stages, we maintain 2 flags
+ * that tell us where to resume in the sequence.
+ * In the particular case of DTRACESYS1, the trace was already complete
+ * before the migration.  In the case of DTRACESYS2, the system-call was already
+ * complete before the migration and the code in "entry.S" prevents it from
+ * re-running.
+ */
+asmlinkage void
+syscall_trace(void)
+{
+	extern asmlinkage void do_syscall_trace(void);
+
+	switch(current->mosix.dflags & (DTRACESYS1|DTRACESYS2))
+	{
+		case 0:
+			current->mosix.dflags |= DTRACESYS1;
+			break;
+		case DTRACESYS1:
+			return;
+		case DTRACESYS2:
+		case DTRACESYS1|DTRACESYS2:
+			current->mosix.dflags &= ~(DTRACESYS1|DTRACESYS2);
+	}
+	if(current->mosix.dflags & DREMOTE)
+		mosix_remote_syscall_trace();
+	else
+		do_syscall_trace();
+}
+
+asmlinkage void do_syscall_trace(void)
+#else
 asmlinkage void syscall_trace(void)
+#endif /* CONFIG_MOSIX */
 {
 	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
 			(PT_PTRACED|PT_TRACESYS))
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/signal.c linux-openmosix/arch/i386/kernel/signal.c
--- linux/arch/i386/kernel/signal.c	2002-08-03 02:39:42.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/signal.c	2004-02-05 10:50:55.000000000 +0100
@@ -24,6 +24,10 @@
 #include <asm/uaccess.h>
 #include <asm/i387.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 #define DEBUG_SIG 0
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -37,6 +41,29 @@
 	if (from->si_code < 0)
 		return __copy_to_user(to, from, sizeof(siginfo_t));
 	else {
+#ifdef CONFIG_MOSIX
+		/* it is unreasonable to send a separate request per word,
+		 * so find the limit and send them all together.
+		 */
+		int sz = offsetof(struct siginfo, _sifields);
+
+		switch(from->si_code >> 16)
+		{
+			case __SI_FAULT >> 16:
+				sz += sizeof(to->_sifields._sigfault);
+				break;
+			case __SI_CHLD >> 16:
+				sz += sizeof(to->_sifields._sigchld);
+				break;
+			case __SI_MIGRATION >> 16:
+				sz += sizeof(to->_sifields._sigmig);
+				break;
+			default:
+				sz += sizeof(to->_sifields._kill);
+				break;
+		}
+		return(__copy_to_user(to, from, sz));
+#else
 		int err;
 
 		/* If you change siginfo_t structure, please be sure
@@ -62,6 +89,7 @@
 		/* case __SI_RT: This is not generated by the kernel as of now.  */
 		}
 		return err;
+#endif /* CONFIG_MOSIX */
 	}
 }
 
@@ -81,6 +109,10 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(
+	   BIT_OF_REGISTER(orig_eax)|BIT_OF_REGISTER(eax)|BIT_OF_REGISTER(eip));
+#endif /* CONFIG_MOSIX */
 	regs->eax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
@@ -110,6 +142,10 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(
+	   BIT_OF_REGISTER(orig_eax)|BIT_OF_REGISTER(eax)|BIT_OF_REGISTER(eip));
+#endif /* CONFIG_MOSIX */
 	regs->eax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
@@ -155,6 +191,10 @@
 sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 {
 	struct pt_regs *regs = (struct pt_regs *) &uss;
+
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(BIT_OF_REGISTER(esp));
+#endif /* CONFIG_MOSIX */
 	return do_sigaltstack(uss, uoss, regs->esp);
 }
 
@@ -185,11 +225,19 @@
 	char retcode[8];
 };
 
+#ifdef CONFIG_MOSIX
+int
+#else
 static int
+#endif /* CONFIG_MOSIX */
 restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax)
 {
 	unsigned int err = 0;
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(ALL_REGISTERS);
+#endif /* CONFIG_MOSIX */
+
 #define COPY(x)		err |= __get_user(regs->x, &sc->x)
 
 #define COPY_SEG(seg)							\
@@ -249,10 +297,18 @@
 asmlinkage int sys_sigreturn(unsigned long __unused)
 {
 	struct pt_regs *regs = (struct pt_regs *) &__unused;
+#ifdef CONFIG_MOSIX
+	struct sigframe *frame;
+#else
 	struct sigframe *frame = (struct sigframe *)(regs->esp - 8);
+#endif /* CONFIG_MOSIX */
 	sigset_t set;
 	int eax;
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(BIT_OF_REGISTER(esp));
+	frame = (struct sigframe *)(regs->esp - 8);
+#endif /* CONFIG_MOSIX */
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -267,6 +323,14 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		if (mosix_deputy_restore_sigcontext(&frame->sc, &eax))
+			goto badframe;
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	if (restore_sigcontext(regs, &frame->sc, &eax))
 		goto badframe;
 	return eax;
@@ -279,11 +343,19 @@
 asmlinkage int sys_rt_sigreturn(unsigned long __unused)
 {
 	struct pt_regs *regs = (struct pt_regs *) &__unused;
+#ifdef CONFIG_MOSIX
+	struct rt_sigframe *frame;
+#else
 	struct rt_sigframe *frame = (struct rt_sigframe *)(regs->esp - 4);
+#endif /* CONFIG_MOSIX */
 	sigset_t set;
 	stack_t st;
 	int eax;
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(BIT_OF_REGISTER(esp));
+	frame = (struct rt_sigframe *)(regs->esp - 4);
+#endif /* CONFIG_MOSIX */
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -295,6 +367,14 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		if(mosix_deputy_restore_sigcontext(&frame->uc.uc_mcontext,&eax))
+			goto badframe;
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
 		goto badframe;
 
@@ -302,6 +382,9 @@
 		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(BIT_OF_REGISTER(esp));
+#endif /* CONFIG_MOSIX */
 	do_sigaltstack(&st, NULL, regs->esp);
 
 	return eax;
@@ -321,6 +404,9 @@
 {
 	int tmp, err = 0;
 
+#ifdef CONFIG_MOSIX_NO_NEED__ALL_CALLERS_ALREADY_DID
+	mosix_obtain_registers(ALL_REGISTERS);
+#endif /* CONFIG_MOSIX_NO_NEED__ALL_CALLERS_ALREADY_DID */
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
 	err |= __put_user(tmp, (unsigned int *)&sc->gs);
@@ -385,12 +471,19 @@
 	return (void *)((esp - frame_size) & -8ul);
 }
 
+#ifdef CONFIG_MOSIX
+void setup_frame(int sig, struct k_sigaction *ka,
+#else
 static void setup_frame(int sig, struct k_sigaction *ka,
+#endif /* CONFIG_MOSIX */
 			sigset_t *set, struct pt_regs * regs)
 {
 	struct sigframe *frame;
 	int err = 0;
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(ALL_REGISTERS);
+#endif /* CONFIG_MOSIX */
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -455,12 +548,19 @@
 	force_sig(SIGSEGV, current);
 }
 
+#ifdef CONFIG_MOSIX
+void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+#else
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+#endif /* CONFIG_MOSIX */
 			   sigset_t *set, struct pt_regs * regs)
 {
 	struct rt_sigframe *frame;
 	int err = 0;
 
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(ALL_REGISTERS);
+#endif /* CONFIG_MOSIX */
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -538,6 +638,10 @@
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(
+	   BIT_OF_REGISTER(orig_eax)|BIT_OF_REGISTER(eax)|BIT_OF_REGISTER(eip));
+#endif /* CONFIG_MOSIX */
 	/* Are we from a system call? */
 	if (regs->orig_eax >= 0) {
 		/* If so, check system call restarting.. */
@@ -559,6 +663,11 @@
 	}
 
 	/* Set up the stack frame */
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		mosix_deputy_setup_frame(sig, ka, *info, oldset);
+	else
+#endif /* CONFIG_MOSIX */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame(sig, ka, info, oldset, regs);
 	else
@@ -586,6 +695,11 @@
 	siginfo_t info;
 	struct k_sigaction *ka;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DREMOTE)
+		return(0);
+#endif /* CONFIG_MOSIX */
+
 	/*
 	 * We want the common case to go fast, which
 	 * is why we may in certain cases get here from
@@ -610,6 +724,10 @@
 
 		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			/* Let the debugger run.  */
+#ifdef CONFIG_MOSIX
+			if(current->mosix.dflags & DDEPUTY)
+				mosix_deputy_rusage(0);
+#endif /* CONFIG_MOSIX */
 			current->exit_code = signr;
 			current->state = TASK_STOPPED;
 			notify_parent(current, SIGCHLD);
@@ -668,6 +786,10 @@
 
 			case SIGSTOP: {
 				struct signal_struct *sig;
+#ifdef CONFIG_MOSIX
+				if(current->mosix.dflags & DDEPUTY)
+					mosix_deputy_rusage(0);
+#endif /* CONFIG_MOSIX */
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
 				sig = current->p_pptr->sig;
@@ -703,6 +825,10 @@
 	}
 
 	/* Did we come from a system call? */
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(
+	   BIT_OF_REGISTER(orig_eax)|BIT_OF_REGISTER(eax)|BIT_OF_REGISTER(eip));
+#endif /* CONFIG_MOSIX */
 	if (regs->orig_eax >= 0) {
 		/* Restart the system call - no handlers present */
 		if (regs->eax == -ERESTARTNOHAND ||
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/sys_i386.c linux-openmosix/arch/i386/kernel/sys_i386.c
--- linux/arch/i386/kernel/sys_i386.c	2003-08-25 13:44:39.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/sys_i386.c	2004-02-05 10:50:55.000000000 +0100
@@ -22,6 +22,10 @@
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way Unix traditionally does this, though.
@@ -55,12 +59,20 @@
 			goto out;
 	}
 
+#ifdef CONFIG_MOSIX
+	error = do_mmap_pgoff_down(file, addr, len, prot, flags, pgoff);
+#else
 	down_write(&current->mm->mmap_sem);
 	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 
 	if (file)
 		fput(file);
+#ifdef CONFIG_MOSIX_DFSA
+	if(file && file_count(file) > 1)
+		dfsa_touch_file(fd);
+#endif /* CONFIG_MOSIX_DFSA */
 out:
 	return error;
 }
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/traps.c linux-openmosix/arch/i386/kernel/traps.c
--- linux/arch/i386/kernel/traps.c	2002-11-29 00:53:09.000000000 +0100
+++ linux-openmosix/arch/i386/kernel/traps.c	2004-02-05 10:50:55.000000000 +0100
@@ -50,6 +50,11 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#include <asm/processor.h>
+#endif /* CONFIG_MOSIX */
+
 asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
 asmlinkage void lcall27(void);
@@ -388,7 +393,11 @@
 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
 DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+#ifdef CONFIG_MOSIX
+DO_ERROR_INFO( 6, SIGILL,  "invalid operand", real_invalid_op, ILL_ILLOPN, regs->eip)
+#else
 DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
+#endif /* CONFIG_MOSIX */
 DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available)
 DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
 DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
@@ -405,6 +414,24 @@
 	if (!(regs->xcs & 3))
 		goto gp_in_kernel;
 
+#ifdef CONFIG_MOSIX
+	if(error_code == 0 && (current->mosix.dflags & DREMOTE))
+	{
+		short code;
+		u64 clk;
+
+		if(!get_user(code, (short *)regs->eip) &&
+			code == 0x310F) /* RDTSC */
+		{
+			clk = mosix_remote_tsc();
+			regs->eax = clk & 0xffffffff;
+			regs->edx = clk >> 32;
+			regs->eip += 2;
+			return;
+		}
+		mosix_go_home(0);
+	}
+#endif /* CONFIG_MOSIX */
 	current->thread.error_code = error_code;
 	current->thread.trap_no = 13;
 	force_sig(SIGSEGV, current);
@@ -501,6 +528,30 @@
 	inb(0x71);		/* dummy */
 }
 
+
+#ifdef CONFIG_MOSIX
+static __u32 user_features[NCAPINTS] = USER_MODE_FEATURES;
+
+asmlinkage void
+do_invalid_op(struct pt_regs * regs, long error_code)
+{
+	if((current->mosix.dflags & DREMOTE) && !(regs->eflags & VM_MASK) &&
+							(regs->xcs & 3) == 3)
+	{
+		int i;
+
+		for(i = 0 ; i < NCAPINTS ; i++)
+		if(current->mosix.features[i] & user_features[i] &
+					~boot_cpu_data.x86_capability[i])
+		{
+			mosix_go_home(0);	/* no return if successful */
+			break;
+		}
+	}
+	do_real_invalid_op(regs, error_code);
+}
+#endif /* CONFIG_MOSIX */
+
 /*
  * Our handling of the processor debug registers is non-trivial.
  * We do not clear them on entry and exit from the kernel. Therefore
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/kernel/vm86.c linux-openmosix/arch/i386/kernel/vm86.c
--- linux/arch/i386/kernel/vm86.c	2003-08-25 13:44:39.000000000 +0200
+++ linux-openmosix/arch/i386/kernel/vm86.c	2004-02-05 10:50:55.000000000 +0100
@@ -27,7 +27,9 @@
  *                instead of returning to userspace. This simplifies
  *                do_int, and is needed by handle_vm6_fault. Kasper
  *                Dupont <kasperd@daimi.au.dk>
- *   
+ *  
+ *   Oct 7 2003 - Unfixed ptrace bug fix for 2.4.19
+		  Moshe Bar <moshe@moshebar.com> 
  */
 
 #include <linux/errno.h>
@@ -45,6 +47,10 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /*
  * Known problems:
  *
@@ -97,6 +103,10 @@
 	struct pt_regs *ret;
 	unsigned long tmp;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DREMOTE)
+		panic("remote save_v86");
+#endif /* CONFIG_MOSIX */
 	if (!current->thread.vm86_info) {
 		printk("no vm86_info: BAD\n");
 		do_exit(SIGSEGV);
@@ -111,9 +121,18 @@
 		do_exit(SIGSEGV);
 	}
 	tss = init_tss + smp_processor_id();
+#ifdef CONFIG_MOSIX
+	lock_mosix();	/* ptrace checks saved_esp0 under the mosix-lock */
+#endif /* CONFIG_MOSIX */
 	tss->esp0 = current->thread.esp0 = current->thread.saved_esp0;
 	current->thread.saved_esp0 = 0;
 	ret = KVM86->regs32;
+#ifdef CONFIG_MOSIX
+	unlock_mosix();
+	task_lock(current);
+	current->mosix.stay &= ~DSTAY_FOR_86;
+	task_unlock(current);
+#endif /* CONFIG_MOSIX */
 	return ret;
 }
 
@@ -167,6 +186,13 @@
 	struct task_struct *tsk;
 	int tmp, ret = -EPERM;
 
+#ifdef CONFIG_MOSIX
+	if(!mosix_go_home_for_reason(1, DSTAY_FOR_86))
+	{
+		ret = -ENOMEM;
+		goto out;
+	}
+#endif /* CONFIG_MOSIX */
 	tsk = current;
 	if (tsk->thread.saved_esp0)
 		goto out;
@@ -224,6 +250,13 @@
 	ret = -EFAULT;
 	if (tmp)
 		goto out;
+#ifdef CONFIG_MOSIX
+	if(!mosix_go_home_for_reason(1, DSTAY_FOR_86))
+	{
+		ret = -ENOMEM;
+		goto out;
+	}
+#endif /* CONFIG_MOSIX */
 	info.regs32 = (struct pt_regs *) &subfunction;
 	info.vm86plus.is_vm86pus = 1;
 	tsk->thread.vm86_info = (struct vm86_struct *)v86;
@@ -276,9 +309,15 @@
  * Save old state, set default return value (%eax) to 0
  */
 	info->regs32->eax = 0;
+#ifdef CONFIG_MOSIX
+	lock_mosix();
+#endif /* CONFIG_MOSIX */
 	tsk->thread.saved_esp0 = tsk->thread.esp0;
 	tss = init_tss + smp_processor_id();
 	tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
+#ifdef CONFIG_MOSIX
+	unlock_mosix();
+#endif /* CONFIG_MOSIX */
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
 	if (info->flags & VM86_SCREEN_BITMAP)
@@ -298,6 +337,11 @@
 
 	regs32 = save_v86_state(regs16);
 	regs32->eax = retval;
+#ifdef CONFIG_MOSIX
+	task_lock(current);
+	current->mosix.stay &= ~DSTAY_FOR_86;
+	task_unlock(current);
+#endif /* CONFIG_MOSIX */
 	__asm__ __volatile__("movl %0,%%esp\n\t"
 		"jmp ret_from_sys_call"
 		: : "r" (regs32), "b" (current));
@@ -706,7 +750,11 @@
 	int ret = 0;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if ((p == tsk) && (p->sig)) {
 			ret = 1;
 			break;
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/lib/usercopy.c linux-openmosix/arch/i386/lib/usercopy.c
--- linux/arch/i386/lib/usercopy.c	2003-06-13 16:51:29.000000000 +0200
+++ linux-openmosix/arch/i386/lib/usercopy.c	2004-02-05 10:50:55.000000000 +0100
@@ -119,6 +119,11 @@
 __strncpy_from_user(char *dst, const char *src, long count)
 {
 	long res;
+
+#ifdef CONFIG_MOSIX
+	if(USER_IS_REMOTE)
+		return(deputy_strncpy_from_user(dst, (char *)src, count, 0));
+#endif /* CONFIG_MOSIX */
 	__do_strncpy_from_user(dst, src, count, res);
 	return res;
 }
@@ -145,6 +150,11 @@
 strncpy_from_user(char *dst, const char *src, long count)
 {
 	long res = -EFAULT;
+
+#ifdef CONFIG_MOSIX
+	if(USER_IS_REMOTE)
+		return(deputy_strncpy_from_user(dst, (char *)src, count, 1));
+#endif /* CONFIG_MOSIX */
 	if (access_ok(VERIFY_READ, src, 1))
 		__do_strncpy_from_user(dst, src, count, res);
 	return res;
@@ -189,6 +199,10 @@
 unsigned long
 clear_user(void *to, unsigned long n)
 {
+#ifdef CONFIG_MOSIX
+	if (USER_IS_REMOTE)
+		return(deputy_clear_user(to, n, 1));
+#endif /* CONFIG_MOSIX */
 	if (access_ok(VERIFY_WRITE, to, n))
 		__do_clear_user(to, n);
 	return n;
@@ -208,6 +222,10 @@
 unsigned long
 __clear_user(void *to, unsigned long n)
 {
+#ifdef CONFIG_MOSIX
+	if (USER_IS_REMOTE)
+		return(deputy_clear_user(to, n, 0));
+#endif /* CONFIG_MOSIX */
 	__do_clear_user(to, n);
 	return n;
 }
@@ -228,6 +246,10 @@
 	unsigned long mask = -__addr_ok(s);
 	unsigned long res, tmp;
 
+#ifdef CONFIG_MOSIX
+	if(USER_IS_REMOTE)
+		return(deputy_strnlen_user((char *)s, n));
+#endif /* CONFIG_MOSIX */
 	__asm__ __volatile__(
 		"	testl %0, %0\n"
 		"	jz 3f\n"
diff -Naur --exclude=CVS --exclude=configs linux/arch/i386/mm/fault.c linux-openmosix/arch/i386/mm/fault.c
--- linux/arch/i386/mm/fault.c	2002-11-29 00:53:09.000000000 +0100
+++ linux-openmosix/arch/i386/mm/fault.c	2004-02-05 10:50:56.000000000 +0100
@@ -25,6 +25,10 @@
 #include <asm/pgalloc.h>
 #include <asm/hardirq.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 extern void die(const char *,struct pt_regs *,long);
 
 /*
@@ -38,6 +42,10 @@
 	if (!size)
 		return 1;
 
+#ifdef CONFIG_MOSIX
+	if(USER_IS_REMOTE)
+		return(deputy_verify_write((void *)addr, size));
+#endif /* CONFIG_MOSIX */
 	vma = find_vma(current->mm, start);
 	if (!vma)
 		goto bad_area;
@@ -127,6 +135,7 @@
 asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
 extern unsigned long idt;
 
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/kernel/entry.S linux-openmosix/arch/ia64/kernel/entry.S
--- linux/arch/ia64/kernel/entry.S	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/kernel/entry.S	2004-02-05 10:50:56.000000000 +0100
@@ -41,6 +41,10 @@
 #include <asm/unistd.h>
 #include <asm/asmmacro.h>
 #include <asm/pgtable.h>
+#ifdef CONFIG_OMIA64
+#include "mosia64asm.H"
+#endif /* CONFIGR_OMIA64 */
+
 
 #include "minstate.h"
 
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/geo_op.c linux-openmosix/arch/ia64/sn/io/sn2/geo_op.c
--- linux/arch/ia64/sn/io/sn2/geo_op.c	2003-08-25 13:44:39.000000000 +0200
+++ linux-openmosix/arch/ia64/sn/io/sn2/geo_op.c	2004-02-05 10:50:57.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/klconflib.c linux-openmosix/arch/ia64/sn/io/sn2/klconflib.c
--- linux/arch/ia64/sn/io/sn2/klconflib.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/klconflib.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/klgraph.c linux-openmosix/arch/ia64/sn/io/sn2/klgraph.c
--- linux/arch/ia64/sn/io/sn2/klgraph.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/klgraph.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/l1_command.c linux-openmosix/arch/ia64/sn/io/sn2/l1_command.c
--- linux/arch/ia64/sn/io/sn2/l1_command.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/l1_command.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/ml_iograph.c linux-openmosix/arch/ia64/sn/io/sn2/ml_iograph.c
--- linux/arch/ia64/sn/io/sn2/ml_iograph.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/ml_iograph.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/ml_SN_init.c linux-openmosix/arch/ia64/sn/io/sn2/ml_SN_init.c
--- linux/arch/ia64/sn/io/sn2/ml_SN_init.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/ml_SN_init.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/module.c linux-openmosix/arch/ia64/sn/io/sn2/module.c
--- linux/arch/ia64/sn/io/sn2/module.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/module.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/pciio.c linux-openmosix/arch/ia64/sn/io/sn2/pciio.c
--- linux/arch/ia64/sn/io/sn2/pciio.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/pciio.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/shub.c linux-openmosix/arch/ia64/sn/io/sn2/shub.c
--- linux/arch/ia64/sn/io/sn2/shub.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/shub.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -7,7 +7,7 @@
  * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
-#ident  "$Revision: 1.1 $"
+#ident  "$Revision: 1.1 $"
 
 #include <linux/types.h>
 #include <linux/slab.h>
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/shubio.c linux-openmosix/arch/ia64/sn/io/sn2/shubio.c
--- linux/arch/ia64/sn/io/sn2/shubio.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/shubio.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/xbow.c linux-openmosix/arch/ia64/sn/io/sn2/xbow.c
--- linux/arch/ia64/sn/io/sn2/xbow.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/xbow.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/sn2/xtalk.c linux-openmosix/arch/ia64/sn/io/sn2/xtalk.c
--- linux/arch/ia64/sn/io/sn2/xtalk.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/sn2/xtalk.c	2004-02-05 10:51:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/arch/ia64/sn/io/snia_if.c linux-openmosix/arch/ia64/sn/io/snia_if.c
--- linux/arch/ia64/sn/io/snia_if.c	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/arch/ia64/sn/io/snia_if.c	2004-02-05 10:50:57.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/Documentation/Configure.help linux-openmosix/Documentation/Configure.help
--- linux/Documentation/Configure.help	2003-11-28 19:26:19.000000000 +0100
+++ linux-openmosix/Documentation/Configure.help	2004-02-05 10:50:52.000000000 +0100
@@ -100,6 +100,181 @@
   like MGA monitors that you are very unlikely to see on today's
   systems.
 
+openMosix extensions
+CONFIG_MOSIX
+  Say Y to support process migration and automatic load-balancing
+  within a cluster.
+
+Support clusters with a complex network topology
+CONFIG_MOSIX_TOPOLOGY
+  This option is intended for configurations where the network
+  "distance" between the nodes is not uniform, so you require
+  node-dependent fine-tuning (see "man tune").
+
+  If all the nodes in your openMosix cluster are connected via a simple
+  network and use the same networking hardware (which is the more
+  common case), Say N here (and save kernel-time!).
+
+  Say Y here if not all your openMosix cluster is connected via a simple
+  network or if some nodes use significantly different networking
+  hardware (if you are not sure whether the difference is significant,
+  compile some openMosix kernel anyway and compare the results of "tune").
+
+Maximum network-topology complexity to support
+CONFIG_MOSIX_MAXTOPOLOGY
+  In a complex network-toplogy, each node can identify a number of
+  subsets of the other nodes, each set having the same networking
+  hardware, the same processor type (perhaps slower or faster, but
+  of the same type) and the same routing path.
+  The maximum network-complexity is defined as the maximum number of
+  those sets over all the nodes in your cluster.  minimizing this
+  number helps saving kernel time and inter-node communication, so
+  please use only the level of complexity that you actually need.
+
+  IMPORTANT NOTE: even if you prepare different kernels for different
+  nodes, all the nodes in your cluster must have the same value
+  configured here.
+
+  openMosix allows this value to be in the range of 2-10 (higher values
+  will be truncated and lower values imply no complex topology).
+
+
+openMosix diagnostics
+CONFIG_MOSIX_DIAG
+  Say Y to include openMosix consistency checks.
+  While this adds code to the kernel, it may prevent unexpected
+  occurences when running new versions of openMosix.
+
+
+Process arrival messages
+CONFIG_MOSIX_WEEEEEEEEE
+  If you say Y to this option, the console will display messages whenever
+  a process arrives: Weeeeeeeee..... for remote (guest) processes and
+  Wooooooooo..... for local processes returning home.
+
+Loopback process-migration testing
+CONFIG_MOSIX_CHEAT_MIGSELF
+  Say Y to allow loopback process "migration" from a node into itself
+  (useful only for kernel-debugging).
+
+Level of process-identity disclosure
+CONFIG_MOSIX_DISCLOSURE
+  Determine how much information about processes is disclosed by default
+  when they run as guests on remote nodes:
+  0 = no information
+  1 = only PID (and TGID if different)
+  2 = PID(/TGID), UID, GID
+  3 = PID(/TGID), UID, GID, PGRP, SESSION, COMMAND
+  Processes may modify this default by writing to /proc/self/disclosure.
+
+Prevent the "-openmosix" extension on kernel name
+CONFIG_MOSIX_EXTMOSIX
+  Say Y if you want the kernel and module directory to have the "-openMosix"
+  extension (to distinguish it from coexistant non-MOSIX kernels of the
+  same kernel version number).
+
+Stricter security on openMosix ports
+CONFIG_MOSIX_SECUREPORTS
+  The internal kernel TCP/UDP ports used by openMosix may not be accessed
+  by normal users (and even the Super-User has no real reason to access
+  them).  The question arises whether to allow user-connections to those
+  ports on other (internet) nodes, outside the cluster.
+  If routing schemes allow a openMosix node to also be accessed from within
+  the cluster using an IP address that is not listed in the openMosix
+  configuration, you must say Y (or risk that a hacking user will mess
+  with the openMosix internals by connecting to that IP address and one of
+  the openMosix port numbers).  However, these port numbers, though not
+  listed in "/etc/services", may be in use for other purposes somewhere
+  else on the internet - and this option would prevent accessing them,
+  so if your users require such access, say N and make sure that all the
+  IP addresses by which your nodes can be reached are listed as aliases
+  in the openMosix configuration.
+
+Direct File-System Access for openMosix
+CONFIG_MOSIX_DFSA
+  Direct File System Access:
+  DFSA is now ready for Beta-testing.  It can currently only be used
+  by oMFS (openMosix File-System).  You may be interested in this option
+  if you either like experimenting and experiencing the power of DFSA
+  with MFS, or if you are interested in either developing a new
+  file-system, or adapting an existing one to DFSA.
+
+  For the lay user, all you need is to also configure MFS, then run
+  the following commands on each node:
+      mkdir /mfs
+      mount -t mfs cluster /mfs -odfsa=1
+
+  If you are more serious about it, please read "Documentation/DFSA"
+  or run "man dfsa".
+
+openMosix File-System
+CONFIG_MOSIX_FS
+  The openMosix File-System (oMFS) is now ready for Beta-testing.
+  Along with DFSA, it forms the basis for the next generation
+  of openMosix, expanding the power of openMosix beyond CPU-bound tasks
+  into I/O tasks as well.
+
+  On its own, oMFS allows processes to access most files (more accurately,
+  all regular files, directories and symbolic-links, but excluding the
+  "/proc" file-system and oMFS itself) on all the nodes in the cluster.
+
+  oMFS assumes that all users/group-ID's throughout the cluster are
+  equivalent: if this is not the case, you cannot use oMFS, so you must
+  say 'N' here, unless you have a sub-cluster where the user/group-ID's
+  are equivalent, in which case you may still choose to configure MFS
+  only in that sub-cluster.
+
+  To use oMFS, all you need is to type:
+        mount -t mfs cluster /mfs
+  (the word "cluster" can be changed to suit your taste and the "/mfs"
+  mount-point is only a suggestion, to be used in this discussion).
+  For a permanent solution, enter the following line in "/etc/fstab":
+        cluster    /mfs    mfs    defaults    0 0
+
+  You can now access each node via "/mfs/{node_number}", you may also
+  access the following useful directories:
+
+  /mfs/here     - The current node where your process runs
+  /mfs/home     - Your home node
+  /mfs/magic    - The current node when used by the "creat" system call
+                  (or an "open" with the "O_CREAT" option) - otherwise,
+                  the last node on which an MFS magical file was
+                  successfully created (this is very useful for creating
+                  temporary-files, then immediately unlinking them)
+  /mfs/lastexec - The node on which the process last issued a successful
+                  "execve" system-call.
+  /mfs/selected - The node you selected by either your process itself or
+                  one of its ancesstors (before forking this process),
+                  writing a number into "/proc/self/selected".
+
+  MFS is currently the only file-system that can be used with DFSA.
+  Detailed technical information is available in
+  "Documentation/filesystems/mfs.txt".
+
+Poll/Select exceptions on pipes
+CONFIG_MOSIX_PIPE_EXCEPTIONS
+  This feature is not required for MOSIX-proper, but some user-mode
+  programs like it.  It allows a program to be notified when someone
+  is wishing to read from a pipe.  If you say Y, you may then use:
+  ioctl(pipefd, TCSBRK, arg) to set or clear exception conditions.
+  If (arg & 1), an exception is generated when someone is trying to
+  read the pipe.  If (arg & 2), an exception is generated when the
+  pipe has no more readers.  The default is that pipes never generate
+  any exceptions.  An exception can be returned by the "select" system
+  call and will also cause POLLPRI to be included in the return-value
+  of the "poll" system-call.  You can also get an under-estimate of the
+  number of bytes that processes curretly try to read from the pipe using
+  ioctl(pipefd, TIOCGWINSZ, 0).
+
+Disable OOM (out of memory killer)
+CONFIG_MOSIX_NO_OOM
+   This feature allows you to turn off the abominevolous out of memory killer
+   recently re-introduced into ther Linux kernel. Because the kernel does
+   over-commit memory (which could be avoided altogether) when all processes
+   belonging to a process are required to return to that node, there might be
+   a shortage of RAM + Swapspace to accomdate them all and then the OOM killer
+   kicks in. Turn this feature on to avoid using the OOM killer.
+
 Prompt for advanced kernel configuration options
 CONFIG_ADVANCED_OPTIONS
   This option will enable prompting for a variety of advanced kernel
diff -Naur --exclude=CVS --exclude=configs linux/Documentation/DFSA linux-openmosix/Documentation/DFSA
--- linux/Documentation/DFSA	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/Documentation/DFSA	2002-05-19 16:39:21.000000000 +0200
@@ -0,0 +1,215 @@
+DFSA - Direct File-System Access:
+
+The first generation of openMosix has brought about great performance
+improvements in CPU jobs - "number crunchers", but cannot help in the
+case of I/O tasks, which need to communicate with their home-node as
+often as every system-call, and are therefore better off remaining there.
+
+The second generation of openMosix, includes DFSA, whereby the more common
+system-calls can be (under certain conditions) performed directly on the
+caller's current node, thus increasing the benefit and probability that
+I/O-oriented (or mixed I/O and CPU) tasks will also migrate.
+
+DFSA operates over suitable, cluster-wide shared file-systems that fulfill
+certain requirements.  The only file-system to currently fulfill those
+requirements is the openMosix File-System (MFS).
+
+To use DFSA without violating access permissions, the permission-scheme
+(user and group ID's) must be identical, or at least compatible throughout
+the openMosix cluster.
+
+Each partition that is to operate in DFSA mode must be assigned a unique
+DFSA index, currently in the range of 1-8, that must be identical on all
+the nodes in the openMosix cluster.
+
+To request a particular partition to operate in DFSA mode, mount (or remount)
+it with the "-odfsa={n}" argument  (1 <= n <= 8).
+
+You should do the same on all the nodes in the cluster either at about the
+same time or before openMosix is configured: failure to assign all DFSA
+mount-points on some of the nodes is not fatal, but may result in serious
+performance degradation, while simultaneous use of the same index for
+different partitions, is likely to cause various faults.
+
+To disassociate a partition from DFSA, run:
+
+mount -o remount {mount-point} -odfsa=0.
+
+You may also designate symbolic-links to operate in DFSA mode: this is
+equivalent to a declaration that the given links are identical on all
+nodes and point to the same partition.  It saves remote processes who use
+those link(s) the need to contact their home node every use in order to
+read those links.  To declare a symbolic-link as identical, type:
+
+echo {symbolic-link} > /proc/hpc/admin/dfsalinks,
+
+where the symbolic-link must be an absolute-pathname, pointing at an existing
+file (or directory or another symbolic-link) on an already-mounted partition
+that is capable of DFSA (but it is not required to be already associated with
+a DFSA index).
+
+To remove a symbolic-link declaration, type:
+
+echo -{symbolic-link} > /proc/hpc/admin/dfsalinks:
+
+If you intend to re-define a declared symbolic link, you must first re-
+move its declaration, then re-declare after the change is made.
+
+To see a list of all currently-declared symbolic links, type:
+
+cat /proc/hpc/admin/dfsalinks.
+
+To cancel all symbolic-link declarations, type:
+
+echo - > /proc/hpc/admin/dfsalinks.
+
+The number of declared symbolic-links is currently limited to 8 and their
+path-name length is limited to 128 characters.
+
+requirements from a complying file-system:
+------------------------------------------
+1) all operations on the file system must be synchronous, in the sense that
+   there is [at most] only one buffer/inode cache throughout the cluster.
+   (on client-server file-systems, this usually means that the whole cache
+   is maintained on the server - however, a sophisticated server may "lend"
+   the cache of particular inodes to particular clients at any given time.
+   on shared-hardware file-systems, this probably requires either a hardware
+   invalidation signal or a new version to be marked on each inode after each
+   modification).
+
+2) The time-stamps on files and between files of the same file-system must be
+   consistent and advancing (unless the clock is deliberately set backwards),
+   regardless from which node modifications are made.
+
+3) The file-system must populate the following two new super-block methods:
+   a) "identify":
+       Given a "dentry", encapsulate identifying information about it into
+       a finite, rather-small structure, in a way that is sufficient to be
+       able to re-establish that open file/directory on another node.
+   b) "reconstruct":
+       Given only a mount-structure ("vfsmnt") and information that was
+       provided by "identify", produce a live new "dentry".
+
+       Also, while not enforced by DFSA itself, in order for the getcwd
+       system-call to work correctly on a shared file-system, regardless
+       of where the call is made from, it is also highly recommended to
+       populate the following new inode-method:
+   c) "checkpath":
+       Given a "dentry", ensure that following its path via the "dcache"
+       will truly reflect its current position on the shared file-system -
+       and if not, make the necessary fixes by adjusting the "dentry" around
+       the directory cache: The "dcache" of shared file-systems cannot be
+       trusted, since processes running on other nodes can move (or remove)
+       a directory at any time.
+
+4) The file-system must ensure that files/directories are not cleared when
+   unlinked, for as long as any process in the cluster still holds them open.
+   There are several possible techniques to achieve this, but given the
+   distributed nature of the file-system, some form of garbage-collection
+   is probably also called upon.
+
+Which system-calls are supported:
+---------------------------------
+The following system-calls are normally supported and usually run directly
+by the process, while any other calls, or hard cases still need to go via
+the home-node:
+
+	read, readv, write, writev, readahead
+	lseek, llseek
+	open, creat, close
+	dup, dup2, fcntl/fcntl64 (F_DUPFD,F_GETFL,F_SETFL)
+	getdents, getdents64, old_readdir
+	fsync, fdatasync
+	chdir, fchdir, getcwd
+	stat, stat64, newstat, lstat, lstat64, newlstat,
+	fstat, fstat64, newfstat
+	access
+	truncate, truncate64, ftruncate, ftruncate64
+	chmod, chown, chown16, lchown, lchown16, fchmod, fchown, fchown16
+	utime, utimes
+	symlink, readlink
+	mkdir, rmdir
+	link, unlink, rename
+
+Examples of hard cases:
+* if not all nodes have the same mounted DFSA partitions, or they do -
+  but with different mount-flags.
+* if the calling process is being traced.
+* if the process has a non-standard root-directory.
+* If the calling process has an emulating personality that causes it
+  to use an alternate root (but this is currently not relevant for the
+  i386 architecture).
+* if the calling process shares either its files or current directory
+  as a result of the "clone" system-call.
+* operations occuring during re-configuration of DFSA on either the
+  home-node or the node where the process runs.
+* operations involving special files (eg. other than regular, directories
+  or symbolic-links)
+* operations on files that were commonly opened and still shared with other
+  related processes.
+* dup2, where the second file-descriptor is an already open non-DFSA file
+  (that requires closing).
+* chdir/fchdir when the previous directory is non-DFSA.
+* link/rename that fail due to an attempt to cross-device link.
+* open/dup/dup2/fcntl(F_DUPFD) that requires an allowable-increase in
+  the maximal file-descriptor index (initially 1023!).
+* When the home-node has pending requests for the process (such as
+  signals, requests for "ps" information, request to migrate or consider
+  migration, etc.)
+* Use of path-names that leave the DFSA partition, as demonstrated by
+  the following example:
+	"/mfs" is a DFSA file-system
+	/mfstmp is a symbolic link to /mfs/2/tmp, and is declared in
+		/proc/hpc/admin/dfsalinks.
+	/mtmp is a symbolic link to /mfstmp, and is declared in
+		/proc/hpc/admin/dfsalinks.
+	/mfs2 is a symbolic link to /mfs/2, but is not declared.
+	on node #2, /fie is a symbolic link to "/tmp/foo".
+  then the following are accepted as simple cases (and identical):
+	/mfs/2/tmp/foo
+	//mfs//2/tmp/foo
+	/./mfs/2/tmp/foo
+	/mfstmp/foo
+	/mtmp/foo
+	/mfs/2/fie
+	mfs/2/tmp/foo  (when in the root directory)
+	
+  but not the following:
+	/tmp/../mfs/tmp/foo
+		(the kernel is not allowed to assume that each node has an
+		 accessible "/tmp" directory!)
+	/mfs/2/../../mfs/2/tmp/foo
+		(the secon ".." steps out of the "/mfs" DFSA partition)
+        /mfs2/tmp/foo
+		(/mfs2 is not declared, hence no assurance was provided
+		that it is identical on all nodes)
+	mfstmp/foo (or mfstmp/foo) when in the root directory
+		(just a difficult case to recognize)
+
+* when the home-node DEPUTY has pending requests for the process (such as
+  signals, requests for "ps" information, request to migrate or consider
+  migration, etc.)
+
+Deviations from normal Linux/Unix/Posix behavior:
+--------------------------------------------------
+It was impossible to maintain 100% compatibility on DFSA file-systems,
+but the deviations are kept to the very minimum:
+
+* A process that received a signal may continue running a few DFSA system-calls
+  before it actually receives and handles the signal.
+  (in contrast, any POSIX process that receives a signal may possibly
+   complete the next system-call, but cannot issue any new ones beyond that).
+
+* Simultaneous mapping and I/O on the same DFSA file creates unpredictable
+  results as follows:
+  1) execution (and library and all other file-mappings) is not always
+     protected against other process(es) modifying the file: either the
+     writing-process or the executing/mapping process may fail to receive the
+     "ETXTBSY" error.
+  2) The "MS_INVALIDATE" flag of "msync" may fail to ensure that previous
+     "write"(s) to a mapped DFSA file are discarded.
+  3) when a process modifies memory that is mapped as "MAP_SHARED" to a DFSA
+     file, but has not yet written it back (using "msync", "munmap", "exec"
+     or "exit"), it is possible that another process that reads that file as
+     it migrates will first see some of the changes but later (as opposed to
+     normal behavior), see the old values (or some of them) again.
diff -Naur --exclude=CVS --exclude=configs linux/Documentation/filesystems/00-INDEX linux-openmosix/Documentation/filesystems/00-INDEX
--- linux/Documentation/filesystems/00-INDEX	2002-11-29 00:53:08.000000000 +0100
+++ linux-openmosix/Documentation/filesystems/00-INDEX	2004-02-05 10:50:53.000000000 +0100
@@ -24,6 +24,8 @@
 	- info and mount options for the OS/2 HPFS.
 isofs.txt
 	- info and mount options for the ISO 9660 (CDROM) filesystem.
+mfs.txt
+        - info on the openMosix filesystem.
 jfs.txt
 	- info and mount options for the JFS filesystem.
 ncpfs.txt
diff -Naur --exclude=CVS --exclude=configs linux/Documentation/filesystems/mfs.txt linux-openmosix/Documentation/filesystems/mfs.txt
--- linux/Documentation/filesystems/mfs.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/Documentation/filesystems/mfs.txt	2002-05-19 16:39:22.000000000 +0200
@@ -0,0 +1,197 @@
+MFS interface, capabilities and limitations:
+============================================
+To use MFS, configure the "CONFIG_MOSIX_FS" option into the kernel
+then mount it, using:
+	mount -t mfs {any_name} {mount_point} [-o dfsa={n}]
+This gives access to nearly all files throughout the openMosix cluster,
+with the root of each node available via {mount_point}/{node_number}/.
+Also available as sub-directories are:
+
+/{mount_point}/here/
+	The current node where your process runs
+/{mount_point}/home/
+	Your home node
+/{mount_point}/magic/
+	The current node when used by the "creat" system call (or an "open"
+	with the "O_CREAT" option) - otherwise, the last node on which an MFS
+	magical file was successfully created (this is very useful for creating
+	temporary-files, then immediately unlinking them)
+/{mount_point}/lastexec/
+	The node on which the process last issued a successful "execve"
+	system-call.
+/{mount_point}/selected/
+	The node you selected by either your process itself or as inherited
+	by one of its ancesstors (before forking this process), writing a
+	number into "/proc/self/selected".
+
+You may also wish to have MFS be automatically by entering the following
+line into "/etc/fstab":
+        cluster    /{mount_point}    mfs    defaults    0 0
+or for DFSA use:
+        cluster    /{mount_point}    mfs    dfsa=1      0 0
+
+Once CONFIG_MOSIX_FS is configured in the kernel and openMosix has been configured
+(See "man setpe"), other nodes can access the node's file-system even without
+the above mount.  To disallow MFS access to this node, write a "1" to
+"/proc/hpc/admin/nomfs" (to re-allow, write a "0").
+
+MFS was designed to also run under DFSA, allowing direct access by processes,
+from wherever they run at each moment, to the node holding the files/directories
+that they require, bypassing their "DEPUTY" in most cases.  This makes it even
+more efficient if the required files are on the same node as the process, in
+which case the process can serve itself without resorting to the network.
+To use MFS with DFSA, make sure that the mount-point is the same on all nodes,
+then mount (or remount) MFS with the "-odfsa={n} flag, where {n} is in the
+range of 1-8 and identical on all nodes in the cluster:
+
+Users and Groups:
+-----------------
+MFS assumes that all user and group ID's throughout the cluster have
+equivalent access rights.  You should not use MFS on clusters with
+heterogenous user/group scheme.  While allowing the Super-User to access
+all files throughout the cluster, this is implied anyway by the security
+requirements of openMosix (See "man mosix").  If most of your cluster uses the
+same scheme, but some nodes do not, you may either configure MFS only in the
+kernel of those nodes that use the same scheme, or write a "1" to
+"/proc/hpc/admin/nomfs" during node-startup and before openMosix is configured
+on the other nodes, as well as not mounting MFS there.
+
+Temporary files:
+----------------
+the "here", "magic", "lastexec" and "selected" directories are designed
+to provide easier access to temporary files, so that programs are helped
+to create their temporary files where they run.  With many programs, you
+can make use these directories without recompiling, by using the "TMPDIR"
+environment variable.
+
+The most conservative, but safest thing to do, which can be applied to all
+programs, is to:
+	setenv TMPDIR "/{mount-point}/selected/tmp
+In this case, your shell (or the calling script) should run
+	echo `cat /proc/self/where` > /proc/self/selected
+before calling the program.
+(note that "cp" cannot be used here, since only the shell may modify its
+own "selected", but "echo" works because it is built into most shells)
+
+The next, little less conservative approach, but still safe for programs
+that do not rely on passing file-names to their children as arguments of
+"exec", is to:
+	setenv TMPDIR "/{mount-point}/lastexec/tmp
+       (or "env TMPDIR=/{mount-point}/lastexec/tmp program [args]")
+
+The next, still less conservative, but more powerful approach, can be used
+for programs that create temporary-files, which either create only one MFS file,
+or unlink temporary-files as soon as they are created.  For such programs:
+	setenv TMPDIR "/{mount-point}/magic/tmp
+       (or "env TMPDIR=/{mount-point}/magic/tmp program [args]")
+
+Finally, programs that are locked on any particular node, may use:
+	setenv TMPDIR "/{mount-point}/here/tmp
+       (or "env TMPDIR=/{mount-point}/here/tmp program [args]")
+Please note that this approach is not 100% safe, because even while locked,
+migration back to the home-node may still occur if/when the node where the
+program runs is being shut-down for reboot.
+
+Of course, when designing a new program to run with MFS,
+all the above methods can be freely mixed.
+
+Interpretation of symbolic-links:
+---------------------------------
+The following non-trivial interpretation of symbolic links found within MFS,
+was designed to provide uniformity of access between links created locally
+and via MFS, especially by scripts and "makefile"s that use `pwd` as part
+of symbolic links:
+
+The rule is that when a symbolic link begins with a '/', it refers to the
+root of the file-system's node - not the home-node!
+Similarly, a "/.." (or any combination with ".." that calls for the parent of
+the file-system's root) refers to the file-system's root again, rather than to
+the MFS mount-point.
+
+One of the implications is that a symbolic link is never allowed to cross nodes.
+
+Excluded files:
+---------------
+The following may not be accessed via the MFS file-system:
+* nodes that excluded themselves.
+* special files - other than regular-files, directories or symbolic-links.
+* the "proc" file-system.
+* any subdirectories of the recursive MFS mount-point with the exception
+  of symblic links starting in '/', pointing to the same node, and doing
+  so only once.
+
+Examples:
+assuming that there are 3 nodes in the cluster and on node #2:
+1) MFS is mounted on "/mfs"
+2) "/usr/src/linux_here" is a symbolic link to "/mfs/2/usr/src/linux"
+3) "/usr/src/local_linux" is a symbolic link to "../../mfs/2/usr/src/linux"
+4) "/usr/src/other_linux" is a symbolic link to "/mfs/3/usr/src/linux"
+5) "/usr/src/mfs_linux" is a symbolic link to "/mfs/2/mfs/2/usr/src/linux"
+
+then the following are accessible:
+
+/mfs/2/usr/src/linux
+/mfs/2/etc/hosts
+/mfs/2/mfs
+/mfs/2/usr/src/linux_here
+/usr/src/local_linux
+/usr/src/other_linux
+
+but the following are not (and will result in "Permission denied" error):
+
+/mfs/2/dev/tty6			(special character device)
+/mfs/2/proc/hpc		("proc" file system)
+/mfs/2/mfs/2/tmp	(to prevent infinite recursion and confusing the shell)
+/mfs/2/usr/src/local_linux	(symbolic-link does not start with '/')
+/mfs/2/usr/src/other_linux	(symbolic-link pointing to another node)
+/usr/src/mfs_linux		(symbolic-link pointing to local node twice)
+
+(please note, however, that symbolic-links are still readable
+with "lstat" and "readlink" regardless of their contents)
+
+Garbage Collection:
+-------------------
+When either a client node or part of the network crashes, a garbage-collection
+mechanism will eventually clean up the references to the held-files or
+directories on the serving node(s).  It may take, however, up to an hour
+until the server(s) finally give up the connection, during which the serving
+node(s) will not be able to un-mount the particular file-system(s) involved.
+
+The Super-User may still force an un-mount in 3 ways:
+1) disable MFS by writing a "1" to "/proc/hpc/admin/nomfs".
+2) un-configure openMosix by running "setpe -off".
+3) write the name of a file or directory to be released to
+   "/proc/hpc/admin/mfskill".  If the given name is of a directory, all
+   files and sub-directories under it will be released as well (with the
+   possible exception of files being actively accessed at that very moment),
+   thus writing '/' releases everything, but is very distruptive to users,
+   so it is better to write the name of the mount-point of the file-system
+   that you wish to un-mount.
+
+Functionality limitations:
+--------------------------
+* Mandatory file-locking is not supported.
+* the F_NOTIFY fcntl option is not supported.
+* Voluntary file-locking only operates among processes of the same home-node
+  (and since it will not be supported by DFSA, it always requires DEPUTY-
+  assitance on the home-node).
+* file-ioctl is currently only supported for the EXT2 file-system.
+* mmap of MFS files only supports private mappings (MAP_PRIVATE).
+  Open files must have read-permission.
+  The actual implementation of "mmap" and "execve" does not use demand-paging,
+  but rather reads in the relevant text/data from the file before proceeding.
+* Every effort was attempted to prevent giving the same inode-number to
+  different files, and in most cases this is the case, but it is not totally
+  possible with only 32 bits inode-numbers and the large potential number of
+  files on numerous nodes and devices within each node.  Priority is given so
+  that files on any particular node do not get the same inode-numbers, but even
+  this cannot be absolutely guaranteed when some of the files are NFS (or other
+  file-systems that use the full 32-bit space for inode numbers).  To identify
+  an inode most accurately, one should use the raw "stat" ("fstat"/"lstat")
+  system-call as provided by the kernel before being filtered by the
+  compatibility library, providing the node-number in the "__unused1" field,
+  the device-number in the "__unused2" field and the local inode-numer in the
+  "__unused3" field (these fields are currently always 0 for non-MFS).
+  In the "stat64"/"lstat64"/"fstat64" system-calls, the node number can be
+  found in "__pad0[2-3]", the device-number in "__pad0[4-5]" and the local
+  inode number in "__pad0[6-9]".
diff -Naur --exclude=CVS --exclude=configs linux/Documentation/sysctl/vm.txt linux-openmosix/Documentation/sysctl/vm.txt
--- linux/Documentation/sysctl/vm.txt	2002-11-29 00:53:08.000000000 +0100
+++ linux-openmosix/Documentation/sysctl/vm.txt	2004-02-05 10:50:54.000000000 +0100
@@ -179,7 +179,11 @@
 programs that malloc() huge amounts of memory "just-in-case"
 and don't use much of it.
 
-Look at: mm/mmap.c::vm_enough_memory() for more information.
+Flag values of 2 - 4 introduce a new "strict overcommit"
+policy that attempt to prevent any overcommit of memory.
+
+See Documentation/vm/overcommit-accounting and
+mm/mmap.c::vm_enough_memory() for more information.
 
 ==============================================================
 
diff -Naur --exclude=CVS --exclude=configs linux/drivers/bluetooth/hci_bcsp.c linux-openmosix/drivers/bluetooth/hci_bcsp.c
--- linux/drivers/bluetooth/hci_bcsp.c	2003-06-13 16:51:32.000000000 +0200
+++ linux-openmosix/drivers/bluetooth/hci_bcsp.c	2004-02-05 10:51:13.000000000 +0100
@@ -25,7 +25,7 @@
 */
 
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #define VERSION "0.1"
diff -Naur --exclude=CVS --exclude=configs linux/drivers/bluetooth/hci_bcsp.h linux-openmosix/drivers/bluetooth/hci_bcsp.h
--- linux/drivers/bluetooth/hci_bcsp.h	2003-06-13 16:51:32.000000000 +0200
+++ linux-openmosix/drivers/bluetooth/hci_bcsp.h	2004-02-05 10:51:13.000000000 +0100
@@ -25,7 +25,7 @@
 */
 
 /* 
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #ifndef __HCI_BCSP_H__
diff -Naur --exclude=CVS --exclude=configs linux/drivers/char/defkeymap.c linux-openmosix/drivers/char/defkeymap.c
--- linux/drivers/char/defkeymap.c	1999-10-07 19:17:09.000000000 +0200
+++ linux-openmosix/drivers/char/defkeymap.c	2004-02-05 10:51:13.000000000 +0100
@@ -1,3 +1,4 @@
+
 /* Do not edit this file! It was automatically generated by   */
 /*    loadkeys --mktable defkeymap.map > defkeymap.c          */
 
@@ -37,7 +38,7 @@
 	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
 	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf03e,	0xf10a,
 	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
-	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
 	0xf20b,	0xf601,	0xf602,	0xf117,	0xf600,	0xf20a,	0xf115,	0xf116,
 	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
@@ -56,7 +57,7 @@
 	0xf912,	0xf913,	0xf30b,	0xf90e,	0xf90f,	0xf910,	0xf30a,	0xf90b,
 	0xf90c,	0xf90d,	0xf90a,	0xf310,	0xf206,	0xf200,	0xf07c,	0xf516,
 	0xf517,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
-	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
 	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
 	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
@@ -94,7 +95,7 @@
 	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
 	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf200,	0xf200,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
-	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
 	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
 	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
@@ -132,7 +133,7 @@
 	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
 	0xf302,	0xf303,	0xf300,	0xf20c,	0xf206,	0xf200,	0xf200,	0xf50a,
 	0xf50b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
-	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
 	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf20c,
 	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
@@ -147,6 +148,7 @@
 
 unsigned int keymap_count = 7;
 
+
 /*
  * Philosophy: most people do not define more strings, but they who do
  * often want quite a lot of string space. So, we statically allocate
@@ -184,6 +186,7 @@
 	'\033', '[', 'P', 0, 
 };
 
+
 char *funcbufptr = func_buf;
 int funcbufsize = sizeof(func_buf);
 int funcbufleft = 0;          /* space left */
@@ -223,40 +226,40 @@
 };
 
 struct kbdiacr accent_table[MAX_DIACR] = {
-	{'`', 'A', '\300'},	{'`', 'a', '\340'},
-	{'\'', 'A', '\301'},	{'\'', 'a', '\341'},
-	{'^', 'A', '\302'},	{'^', 'a', '\342'},
-	{'~', 'A', '\303'},	{'~', 'a', '\343'},
-	{'"', 'A', '\304'},	{'"', 'a', '\344'},
-	{'O', 'A', '\305'},	{'o', 'a', '\345'},
-	{'0', 'A', '\305'},	{'0', 'a', '\345'},
-	{'A', 'A', '\305'},	{'a', 'a', '\345'},
-	{'A', 'E', '\306'},	{'a', 'e', '\346'},
-	{',', 'C', '\307'},	{',', 'c', '\347'},
-	{'`', 'E', '\310'},	{'`', 'e', '\350'},
-	{'\'', 'E', '\311'},	{'\'', 'e', '\351'},
-	{'^', 'E', '\312'},	{'^', 'e', '\352'},
-	{'"', 'E', '\313'},	{'"', 'e', '\353'},
-	{'`', 'I', '\314'},	{'`', 'i', '\354'},
-	{'\'', 'I', '\315'},	{'\'', 'i', '\355'},
-	{'^', 'I', '\316'},	{'^', 'i', '\356'},
-	{'"', 'I', '\317'},	{'"', 'i', '\357'},
-	{'-', 'D', '\320'},	{'-', 'd', '\360'},
-	{'~', 'N', '\321'},	{'~', 'n', '\361'},
-	{'`', 'O', '\322'},	{'`', 'o', '\362'},
-	{'\'', 'O', '\323'},	{'\'', 'o', '\363'},
-	{'^', 'O', '\324'},	{'^', 'o', '\364'},
-	{'~', 'O', '\325'},	{'~', 'o', '\365'},
-	{'"', 'O', '\326'},	{'"', 'o', '\366'},
-	{'/', 'O', '\330'},	{'/', 'o', '\370'},
-	{'`', 'U', '\331'},	{'`', 'u', '\371'},
-	{'\'', 'U', '\332'},	{'\'', 'u', '\372'},
-	{'^', 'U', '\333'},	{'^', 'u', '\373'},
-	{'"', 'U', '\334'},	{'"', 'u', '\374'},
-	{'\'', 'Y', '\335'},	{'\'', 'y', '\375'},
-	{'T', 'H', '\336'},	{'t', 'h', '\376'},
-	{'s', 's', '\337'},	{'"', 'y', '\377'},
-	{'s', 'z', '\337'},	{'i', 'j', '\377'},
+	{'`', 'A', 'À'},	{'`', 'a', 'à'},
+	{'\'', 'A', 'Á'},	{'\'', 'a', 'á'},
+	{'^', 'A', 'Â'},	{'^', 'a', 'â'},
+	{'~', 'A', 'Ã'},	{'~', 'a', 'ã'},
+	{'"', 'A', 'Ä'},	{'"', 'a', 'ä'},
+	{'O', 'A', 'Å'},	{'o', 'a', 'å'},
+	{'0', 'A', 'Å'},	{'0', 'a', 'å'},
+	{'A', 'A', 'Å'},	{'a', 'a', 'å'},
+	{'A', 'E', 'Æ'},	{'a', 'e', 'æ'},
+	{',', 'C', 'Ç'},	{',', 'c', 'ç'},
+	{'`', 'E', 'È'},	{'`', 'e', 'è'},
+	{'\'', 'E', 'É'},	{'\'', 'e', 'é'},
+	{'^', 'E', 'Ê'},	{'^', 'e', 'ê'},
+	{'"', 'E', 'Ë'},	{'"', 'e', 'ë'},
+	{'`', 'I', 'Ì'},	{'`', 'i', 'ì'},
+	{'\'', 'I', 'Í'},	{'\'', 'i', 'í'},
+	{'^', 'I', 'Î'},	{'^', 'i', 'î'},
+	{'"', 'I', 'Ï'},	{'"', 'i', 'ï'},
+	{'-', 'D', 'Ð'},	{'-', 'd', 'ð'},
+	{'~', 'N', 'Ñ'},	{'~', 'n', 'ñ'},
+	{'`', 'O', 'Ò'},	{'`', 'o', 'ò'},
+	{'\'', 'O', 'Ó'},	{'\'', 'o', 'ó'},
+	{'^', 'O', 'Ô'},	{'^', 'o', 'ô'},
+	{'~', 'O', 'Õ'},	{'~', 'o', 'õ'},
+	{'"', 'O', 'Ö'},	{'"', 'o', 'ö'},
+	{'/', 'O', 'Ø'},	{'/', 'o', 'ø'},
+	{'`', 'U', 'Ù'},	{'`', 'u', 'ù'},
+	{'\'', 'U', 'Ú'},	{'\'', 'u', 'ú'},
+	{'^', 'U', 'Û'},	{'^', 'u', 'û'},
+	{'"', 'U', 'Ü'},	{'"', 'u', 'ü'},
+	{'\'', 'Y', 'Ý'},	{'\'', 'y', 'ý'},
+	{'T', 'H', 'Þ'},	{'t', 'h', 'þ'},
+	{'s', 's', 'ß'},	{'"', 'y', 'ÿ'},
+	{'s', 'z', 'ß'},	{'i', 'j', 'ÿ'},
 };
 
 unsigned int accent_table_size = 68;
diff -Naur --exclude=CVS --exclude=configs linux/drivers/char/mem.c linux-openmosix/drivers/char/mem.c
--- linux/drivers/char/mem.c	2003-11-28 19:26:20.000000000 +0100
+++ linux-openmosix/drivers/char/mem.c	2004-02-05 10:51:14.000000000 +0100
@@ -444,6 +444,9 @@
 	left = count;
 
 	/* do we want to be clever? Arbitrary cut-off */
+#ifdef CONFIG_MOSIX
+	if(!(current->mosix.dflags & DDEPUTY))
+#endif /* CONFIG_MOSIX */
 	if (count >= PAGE_SIZE*4) {
 		unsigned long partial;
 
@@ -528,6 +531,62 @@
 	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
 }
 
+#ifdef CONFIG_MOSIX
+static ssize_t read_fun(struct file * file, char * buf, 
+			 size_t count, loff_t *ppos)
+{
+	unsigned long i, n = 0;
+
+	if (!count)
+		return 0;
+
+	if (!access_ok(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	while(count)
+	{
+		i = (count > 2*PAGE_SIZE ? 2*PAGE_SIZE : count);
+		if(copy_to_user(buf, current, i) < 0)
+			return(EFAULT);
+		buf += i;
+		count -= i;
+		n += i;
+	}
+	return(n);
+}
+
+static ssize_t write_fun(struct file * file, const char * buf, 
+			 size_t count, loff_t *ppos)
+{
+	unsigned long i, n = 0;
+	char *page;
+
+	if (!count)
+		return 0;
+
+	if (!access_ok(VERIFY_READ, buf, count))
+		return -EFAULT;
+
+	if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+		return(-ENOMEM);
+
+	while(count)
+	{
+		i = (count > PAGE_SIZE ? PAGE_SIZE : count);
+		if(copy_from_user(page, (char *)buf, i) < 0)
+		{
+			free_page((long)page);
+			return(EFAULT);
+		}
+		buf += i;
+		count -= i;
+		n += i;
+	}
+	free_page((long)page);
+	return(n);
+}
+#endif /* CONFIG_MOSIX */
+
 struct page *kmem_vm_nopage(struct vm_area_struct *vma, unsigned long address, int write)
 {
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
@@ -664,6 +723,13 @@
 	write:		write_full,
 };
 
+#ifdef CONFIG_MOSIX
+static struct file_operations fun_fops = {
+	read: read_fun,
+	write: write_fun,
+};
+#endif /* CONFIG_MOSIX */
+
 static int memory_open(struct inode * inode, struct file * filp)
 {
 	switch (MINOR(inode->i_rdev)) {
@@ -693,6 +759,11 @@
 		case 9:
 			filp->f_op = &urandom_fops;
 			break;
+#ifdef CONFIG_MOSIX
+		case 10:
+			filp->f_op = &fun_fops;
+			break;
+#endif /* CONFIG_MOSIX */
 		default:
 			return -ENXIO;
 	}
diff -Naur --exclude=CVS --exclude=configs linux/drivers/char/pc_keyb.c linux-openmosix/drivers/char/pc_keyb.c
--- linux/drivers/char/pc_keyb.c	2002-11-29 00:53:12.000000000 +0100
+++ linux-openmosix/drivers/char/pc_keyb.c	2004-02-05 10:51:14.000000000 +0100
@@ -528,6 +528,7 @@
 	spin_unlock_irq(&kbd_controller_lock);
 }
 
+
 /*
  * send_data sends a character to the keyboard and waits
  * for an acknowledge, possibly retrying if asked to. Returns
diff -Naur --exclude=CVS --exclude=configs linux/drivers/char/sysrq.c linux-openmosix/drivers/char/sysrq.c
--- linux/drivers/char/sysrq.c	2003-08-25 13:44:41.000000000 +0200
+++ linux-openmosix/drivers/char/sysrq.c	2004-02-05 10:51:14.000000000 +0100
@@ -288,7 +288,11 @@
 {
 	struct task_struct *p;
 
-	for_each_task(p) {
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
+  	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if (p->mm && p->pid != 1)
 			/* Not swapper, init nor kernel thread */
 			force_sig(sig, p);
diff -Naur --exclude=CVS --exclude=configs linux/drivers/char/tty_io.c linux-openmosix/drivers/char/tty_io.c
--- linux/drivers/char/tty_io.c	2003-11-28 19:26:20.000000000 +0100
+++ linux-openmosix/drivers/char/tty_io.c	2004-02-05 10:51:14.000000000 +0100
@@ -511,7 +511,11 @@
 	}
 	
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+ 	for_each_local_task(p) {
+#else
  	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if ((tty->session > 0) && (p->session == tty->session) &&
 		    p->leader) {
 			send_sig(SIGHUP,p,1);
@@ -611,7 +615,11 @@
 	tty->pgrp = -1;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p)
+#else
 	for_each_task(p)
+#endif /* CONFIG_MOSIX */
 	  	if (p->session == current->session)
 			p->tty = NULL;
 	read_unlock(&tasklist_lock);
@@ -1255,7 +1263,11 @@
 		struct task_struct *p;
 
 		read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+		for_each_local_task(p) {
+#else
 		for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 			if (p->tty == tty || (o_tty && p->tty == o_tty))
 				p->tty = NULL;
 		}
@@ -1602,7 +1614,11 @@
 			struct task_struct *p;
 
 			read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+			for_each_local_task(p)
+#else
 			for_each_task(p)
+#endif /* CONFIG_MOSIX */
 				if (p->tty == tty)
 					p->tty = NULL;
 			read_unlock(&tasklist_lock);
@@ -1891,7 +1907,11 @@
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if ((p->tty == tty) ||
 		    ((session > 0) && (p->session == session))) {
 			send_sig(SIGKILL, p, 1);
diff -Naur --exclude=CVS --exclude=configs linux/drivers/message/fusion/mptctl.h linux-openmosix/drivers/message/fusion/mptctl.h
--- linux/drivers/message/fusion/mptctl.h	2003-08-25 13:44:42.000000000 +0200
+++ linux-openmosix/drivers/message/fusion/mptctl.h	2004-02-05 10:51:14.000000000 +0100
@@ -298,6 +298,12 @@
  * a bidirectional set up. Normal messages will have one or
  * both of these buffers NULL.
  */
+
+/* A hack due to the name clash with MF */
+#ifdef CONFIG_MOSIX
+#undef MF
+#endif
+
 struct mpt_ioctl_command {
 	mpt_ioctl_header hdr;
 	int		timeout;	/* optional (seconds) */
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/cmdlinepart.c linux-openmosix/drivers/mtd/cmdlinepart.c
--- linux/drivers/mtd/cmdlinepart.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/cmdlinepart.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Read flash partition table from command line
  *
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/amd76xrom.c linux-openmosix/drivers/mtd/maps/amd76xrom.c
--- linux/drivers/mtd/maps/amd76xrom.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/amd76xrom.c	2004-02-05 10:51:15.000000000 +0100
@@ -2,7 +2,7 @@
  * amd76xrom.c
  *
  * Normal mappings of chips in physical memory
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #include <linux/module.h>
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/ceiva.c linux-openmosix/drivers/mtd/maps/ceiva.c
--- linux/drivers/mtd/maps/ceiva.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/ceiva.c	2004-02-05 10:51:15.000000000 +0100
@@ -11,7 +11,7 @@
  *
  * (C) 2000 Nicolas Pitre <nico@cam.org>
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #include <linux/config.h>
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/edb7312.c linux-openmosix/drivers/mtd/maps/edb7312.c
--- linux/drivers/mtd/maps/edb7312.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/edb7312.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Handle mapping of the NOR flash on Cogent EDB7312 boards
  *
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/fortunet.c linux-openmosix/drivers/mtd/maps/fortunet.c
--- linux/drivers/mtd/maps/fortunet.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/fortunet.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,6 +1,6 @@
 /* fortunet.c memory map
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #include <linux/module.h>
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/impa7.c linux-openmosix/drivers/mtd/maps/impa7.c
--- linux/drivers/mtd/maps/impa7.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/impa7.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Handle mapping of the NOR flash on implementa A7 boards
  *
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/lasat.c linux-openmosix/drivers/mtd/maps/lasat.c
--- linux/drivers/mtd/maps/lasat.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/lasat.c	2004-02-05 10:51:15.000000000 +0100
@@ -8,7 +8,7 @@
  * modify it under the terms of the GNU General Public License version
  * 2 as published by the Free Software Foundation.
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  */
 
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/nettel.c linux-openmosix/drivers/mtd/maps/nettel.c
--- linux/drivers/mtd/maps/nettel.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/nettel.c	2004-02-05 10:51:15.000000000 +0100
@@ -6,7 +6,7 @@
  *      (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
  *      (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
  *
- *	$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ *	$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 /****************************************************************************/
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/pcmciamtd.c linux-openmosix/drivers/mtd/maps/pcmciamtd.c
--- linux/drivers/mtd/maps/pcmciamtd.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/pcmciamtd.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
  *
@@ -47,7 +47,7 @@
 
 
 #define DRIVER_DESC	"PCMCIA Flash memory card driver"
-#define DRIVER_VERSION	"$Revision: 1.1 $"
+#define DRIVER_VERSION	"$Revision: 1.1 $"
 
 /* Size of the PCMCIA address space: 26 bits = 64 MB */
 #define MAX_PCMCIA_ADDR	0x4000000
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/physmap64.c linux-openmosix/drivers/mtd/maps/physmap64.c
--- linux/drivers/mtd/maps/physmap64.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/physmap64.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Normal mappings of chips in physical memory
  */
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/scb2_flash.c linux-openmosix/drivers/mtd/maps/scb2_flash.c
--- linux/drivers/mtd/maps/scb2_flash.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/scb2_flash.c	2004-02-05 10:51:15.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  * MTD map driver for BIOS Flash on Intel SCB2 boards
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  * Copyright (C) 2002 Sun Microsystems, Inc.
  * Tim Hockin <thockin@sun.com>
  *
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/scx200_docflash.c linux-openmosix/drivers/mtd/maps/scx200_docflash.c
--- linux/drivers/mtd/maps/scx200_docflash.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/scx200_docflash.c	2004-02-05 10:51:15.000000000 +0100
@@ -2,7 +2,7 @@
 
    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
 
-   $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $ 
+   $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $ 
 
    National Semiconductor SCx200 flash mapped with DOCCS
 */
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/maps/uclinux.c linux-openmosix/drivers/mtd/maps/uclinux.c
--- linux/drivers/mtd/maps/uclinux.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/maps/uclinux.c	2004-02-05 10:51:15.000000000 +0100
@@ -5,7 +5,7 @@
  *
  *	(C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
  *
- * 	$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * 	$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 /****************************************************************************/
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/nand/autcpu12.c linux-openmosix/drivers/mtd/nand/autcpu12.c
--- linux/drivers/mtd/nand/autcpu12.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/nand/autcpu12.c	2004-02-05 10:51:16.000000000 +0100
@@ -6,7 +6,7 @@
  *  Derived from drivers/mtd/spia.c
  * 	 Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
  * 
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/nand/edb7312.c linux-openmosix/drivers/mtd/nand/edb7312.c
--- linux/drivers/mtd/nand/edb7312.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/nand/edb7312.c	2004-02-05 10:51:16.000000000 +0100
@@ -6,7 +6,7 @@
  *  Derived from drivers/mtd/nand/autcpu12.c
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff -Naur --exclude=CVS --exclude=configs linux/drivers/mtd/nand/nand_ids.c linux-openmosix/drivers/mtd/nand/nand_ids.c
--- linux/drivers/mtd/nand/nand_ids.c	2003-06-13 16:51:34.000000000 +0200
+++ linux-openmosix/drivers/mtd/nand/nand_ids.c	2004-02-05 10:51:16.000000000 +0100
@@ -4,7 +4,7 @@
  *  Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
  *
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff -Naur --exclude=CVS --exclude=configs linux/drivers/net/irda/donauboe.c linux-openmosix/drivers/net/irda/donauboe.c
--- linux/drivers/net/irda/donauboe.c	2003-06-13 16:51:35.000000000 +0200
+++ linux-openmosix/drivers/net/irda/donauboe.c	2004-02-05 10:51:16.000000000 +0100
@@ -48,7 +48,7 @@
 
 
 static char *rcsid =
-  "$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $";
+  "$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $";
 
 /* See below for a description of the logic in this driver */
 
diff -Naur --exclude=CVS --exclude=configs linux/drivers/net/sk98lin/skdim.c linux-openmosix/drivers/net/sk98lin/skdim.c
--- linux/drivers/net/sk98lin/skdim.c	2003-11-28 19:26:20.000000000 +0100
+++ linux-openmosix/drivers/net/sk98lin/skdim.c	2004-02-05 10:51:17.000000000 +0100
@@ -2,8 +2,8 @@
  *
  * Name:	skdim.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.1 $
- * Date:	$Date: 2004/07/02 08:38:16 $
+ * Version:	$Revision: 1.1 $
+ * Date:	$Date: 2004/07/02 08:38:16 $
  * Purpose:	All functions to maintain interrupt moderation
  *
  ******************************************************************************/
@@ -26,6 +26,9 @@
  * History:
  *	
  *	$Log: openMosix-2.4.24-om1,v $
  *	Revision 1.1  2004/07/02 08:38:16  sithender
  *	Remove old kernel patch, and add current.
  *	
+ *	Revision 1.4  2004/02/05 09:51:17  sithender
+ *	adding openmosix patch for 2.4.24
+ *	
  *	Revision 1.2  2003/08/21 12:35:05  mlindner
  *	Fix: Corrected CPU detection and compile errors on single CPU machines
  *	
@@ -62,7 +65,7 @@
 
 #ifndef	lint
 static const char SysKonnectFileId[] =
-	"@(#) $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $ (C) SysKonnect.";
+	"@(#) $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $ (C) SysKonnect.";
 #endif
 
 #define __SKADDR_C
diff -Naur --exclude=CVS --exclude=configs linux/drivers/net/sk98lin/skgemib.c linux-openmosix/drivers/net/sk98lin/skgemib.c
--- linux/drivers/net/sk98lin/skgemib.c	2003-11-28 19:26:20.000000000 +0100
+++ linux-openmosix/drivers/net/sk98lin/skgemib.c	2004-02-05 10:51:17.000000000 +0100
@@ -2,8 +2,8 @@
  *
  * Name:	skgemib.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.1 $
- * Date:	$Date: 2004/07/02 08:38:16 $
+ * Version:	$Revision: 1.1 $
+ * Date:	$Date: 2004/07/02 08:38:16 $
  * Purpose:	Private Network Management Interface Management Database
  *
  ****************************************************************************/
@@ -27,6 +27,9 @@
  * History:
  *
  *	$Log: openMosix-2.4.24-om1,v $
  *	Revision 1.1  2004/07/02 08:38:16  sithender
  *	Remove old kernel patch, and add current.
  *	
+ *	Revision 1.6  2004/02/05 09:51:17  sithender
+ *	adding openmosix patch for 2.4.24
+ *	
  *	Revision 1.9  2003/05/23 12:55:20  tschilli
  *	OID_SKGE_BOARDLEVEL added.
  *	
diff -Naur --exclude=CVS --exclude=configs linux/drivers/scsi/cpqfcTSworker.c linux-openmosix/drivers/scsi/cpqfcTSworker.c
--- linux/drivers/scsi/cpqfcTSworker.c	2003-06-13 16:51:36.000000000 +0200
+++ linux-openmosix/drivers/scsi/cpqfcTSworker.c	2004-02-05 10:51:17.000000000 +0100
@@ -174,6 +174,10 @@
 	fs = init_task.fs;
 	current->fs = fs;
 	atomic_inc(&fs->count);
+#ifdef CONFIG_MOSIX
+	atomic_inc(&fs->users);
+#endif /* CONFIG_MOSIX */
+
 
 	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
 
diff -Naur --exclude=CVS --exclude=configs linux/drivers/scsi/nsp32.c linux-openmosix/drivers/scsi/nsp32.c
--- linux/drivers/scsi/nsp32.c	2003-11-28 19:26:20.000000000 +0100
+++ linux-openmosix/drivers/scsi/nsp32.c	2004-02-05 10:51:18.000000000 +0100
@@ -1558,7 +1558,7 @@
 	base = host->io_port;
 
 	SPRINTF("NinjaSCSI-32 status\n\n");
-	SPRINTF("Driver version:        %s, $Revision: 1.1 $\n", nsp32_release_version);
+	SPRINTF("Driver version:        %s, $Revision: 1.1 $\n", nsp32_release_version);
 	SPRINTF("SCSI host No.:         %d\n",		hostno);
 	SPRINTF("IRQ:                   %d\n",		host->irq);
 	SPRINTF("IO:                    0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1);
diff -Naur --exclude=CVS --exclude=configs linux/drivers/sound/ad1889.c linux-openmosix/drivers/sound/ad1889.c
--- linux/drivers/sound/ad1889.c	2003-11-28 19:26:20.000000000 +0100
+++ linux-openmosix/drivers/sound/ad1889.c	2004-02-05 10:51:18.000000000 +0100
@@ -24,7 +24,7 @@
 <jsm> tausq: Anyway, to set up sample rates for D to A, you just use the sample rate on the codec. For A to D, you need to set the codec always to 48K (using the split sample rate feature on the codec) and then set the resampler on the AD1889 to the sample rate you want.
 <jsm> Also, when changing the sample rate on the codec you need to power it down and re power it up for the change to take effect!
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 #include <linux/config.h>
 #include <linux/module.h>
diff -Naur --exclude=CVS --exclude=configs linux/drivers/usb/host/usb-uhci.c linux-openmosix/drivers/usb/host/usb-uhci.c
--- linux/drivers/usb/host/usb-uhci.c	2003-08-25 13:44:42.000000000 +0200
+++ linux-openmosix/drivers/usb/host/usb-uhci.c	2004-02-05 10:51:19.000000000 +0100
@@ -16,7 +16,7 @@
  * (C) Copyright 1999 Randy Dunlap
  * (C) Copyright 1999 Gregory P. Smith
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #include <linux/config.h>
@@ -53,7 +53,7 @@
 /* This enables an extra UHCI slab for memory debugging */
 #define DEBUG_SLAB
 
-#define VERSTR "$Revision: 1.1 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.1 $ time " __TIME__ " " __DATE__
 
 #include <linux/usb.h>
 #include "usb-uhci.h"
diff -Naur --exclude=CVS --exclude=configs linux/drivers/usb/host/usb-uhci.h linux-openmosix/drivers/usb/host/usb-uhci.h
--- linux/drivers/usb/host/usb-uhci.h	2003-06-13 16:51:36.000000000 +0200
+++ linux-openmosix/drivers/usb/host/usb-uhci.h	2004-02-05 10:51:19.000000000 +0100
@@ -2,7 +2,7 @@
 #define __LINUX_UHCI_H
 
 /*
-   $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+   $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 #define MODNAME "usb-uhci"
 #define UHCI_LATENCY_TIMER 0
diff -Naur --exclude=CVS --exclude=configs linux/drivers/usb/storage/usb.c linux-openmosix/drivers/usb/storage/usb.c
--- linux/drivers/usb/storage/usb.c	2003-08-25 13:44:42.000000000 +0200
+++ linux-openmosix/drivers/usb/storage/usb.c	2004-02-05 10:51:19.000000000 +0100
@@ -320,6 +320,9 @@
 	exit_files(current);
 	current->files = init_task.files;
 	atomic_inc(&current->files->count);
+#ifdef CONFIG_MOSIX_DFSA
+	atomic_inc(&current->files->users);
+#endif /* CONFIG_MOSIX_DFSA */
 	daemonize();
 	reparent_to_init();
 
diff -Naur --exclude=CVS --exclude=configs linux/fs/binfmt_aout.c linux-openmosix/fs/binfmt_aout.c
--- linux/fs/binfmt_aout.c	2001-11-03 02:39:20.000000000 +0100
+++ linux-openmosix/fs/binfmt_aout.c	2004-02-05 10:51:20.000000000 +0100
@@ -29,6 +29,10 @@
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
 static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
@@ -108,6 +112,14 @@
 	dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
 #endif
 	dump.signal = signr;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		if(mosix_deputy_dump_thread(&dump))
+			goto end_coredump;
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	dump_thread(regs, &dump);
 
 /* If the size of the dump file exceeds the rlimit, then see what would happen
@@ -189,7 +201,11 @@
  * memory and creates the pointer tables from them, and puts their
  * addresses on the "stack", returning the new stack pointer value.
  */
+#ifdef CONFIG_MOSIX
+unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
+#else
 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
+#endif /* CONFIG_MOSIX */
 {
 	char **argv, **envp;
 	unsigned long * sp;
@@ -258,6 +274,9 @@
 	unsigned long fd_offset;
 	unsigned long rlim;
 	int retval;
+#ifdef CONFIG_MOSIX
+	unsigned long start_stack;
+#endif /* CONFIG_MOSIX */
 
 	ex = *((struct exec *) bprm->buf);		/* exec-header */
 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
@@ -296,6 +315,12 @@
 	set_personality(PER_LINUX);
 #endif
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		mosix_deputy_init_aout_mm(&ex);
+	else
+	{
+#endif /* CONFIG_MOSIX */
 	current->mm->end_code = ex.a_text +
 		(current->mm->start_code = N_TXTADDR(ex));
 	current->mm->end_data = ex.a_data +
@@ -305,6 +330,9 @@
 
 	current->mm->rss = 0;
 	current->mm->mmap = NULL;
+#ifdef CONFIG_MOSIX
+	}
+#endif /* CONFIG_MOSIX */
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
 #ifdef __sparc__
@@ -349,6 +377,9 @@
 			return error;
 		}
 			 
+#if defined(CONFIG_MOSIX) && !defined(__i386__)
+#error On platforms where "flush_icache_range" is non-empty, code must be adjusted
+#endif /* CONFIG_MOSIX */
 		flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
 	} else {
 		static unsigned long error_time, error_time2;
@@ -379,24 +410,38 @@
 			goto beyond_if;
 		}
 
+#ifdef CONFIG_MOSIX
+		error = do_mmap_down(bprm->file, N_TXTADDR(ex), ex.a_text,
+			PROT_READ | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+			fd_offset);
+#else
 		down_write(&current->mm->mmap_sem);
 		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
 			PROT_READ | PROT_EXEC,
 			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 			fd_offset);
 		up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 
 		if (error != N_TXTADDR(ex)) {
 			send_sig(SIGKILL, current, 0);
 			return error;
 		}
 
+#ifdef CONFIG_MOSIX
+ 		error = do_mmap_down(bprm->file, N_DATADDR(ex), ex.a_data,
+				PROT_READ | PROT_WRITE | PROT_EXEC,
+				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+				fd_offset + ex.a_text);
+#else
 		down_write(&current->mm->mmap_sem);
  		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
 				PROT_READ | PROT_WRITE | PROT_EXEC,
 				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 				fd_offset + ex.a_text);
 		up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 		if (error != N_DATADDR(ex)) {
 			send_sig(SIGKILL, current, 0);
 			return error;
@@ -405,8 +450,27 @@
 beyond_if:
 	set_binfmt(&aout_format);
 
+#ifdef CONFIG_MOSIX
+	/* if DEPUTY, the REMOTE already did "set_brk" in aout_remote_init_mm */
+	if(!(current->mosix.dflags & DDEPUTY))
+#endif /* CONFIG_MOSIX */
 	set_brk(current->mm->start_brk, current->mm->brk);
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		retval = mosix_deputy_setup_args(SETUP_ARGS_AS_AOUT,
+								&start_stack);
+		if(retval < 0)
+		{
+			send_sig(SIGKILL, current, 0);
+			return(retval);
+		}
+		mosix_obtain_registers(START_THREAD_REGS);
+	}
+	else
+	{
+#endif /* CONFIG_MOSIX */
 	retval = setup_arg_pages(bprm); 
 	if (retval < 0) { 
 		/* Someone check-me: is this error path enough? */ 
@@ -414,17 +478,46 @@
 		return retval;
 	}
 
+#ifdef CONFIG_MOSIX
+	start_stack =
+#endif /* CONFIG_MOSIX */
 	current->mm->start_stack =
 		(unsigned long) create_aout_tables((char *) bprm->p, bprm);
+#ifdef CONFIG_MOSIX
+	}
+#endif /* CONFIG_MOSIX */
 #ifdef __alpha__
 	regs->gp = ex.a_gpvalue;
 #endif
+#ifdef CONFIG_MOSIX
+	start_thread(regs, ex.a_entry, start_stack);
+#else
 	start_thread(regs, ex.a_entry, current->mm->start_stack);
+#endif /* CONFIG_MOSIX */
 	if (current->ptrace & PT_PTRACED)
 		send_sig(SIGTRAP, current, 0);
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+void
+aout_remote_init_mm(struct exec *ex)
+{
+	register struct task_struct *p = current;
+
+	/* in principle we should first check for the "PER_LINUX" personality */
+	/* but then which LINUX does not have it??? */
+
+	p->mm->end_code = ex->a_text + (p->mm->start_code = N_TXTADDR(*ex));
+	p->mm->end_data = ex->a_data + (p->mm->start_data = N_DATADDR(*ex));
+	p->mm->brk = ex->a_bss + (p->mm->start_brk = N_BSSADDR(*ex));
+
+	p->mm->rss = 0;
+	p->mm->mmap = NULL;
+	set_brk(p->mm->start_brk, current->mm->brk);
+}
+#endif /* CONFIG_MOSIX */
+
 static int load_aout_library(struct file *file)
 {
 	struct inode * inode;
@@ -478,12 +571,19 @@
 		goto out;
 	}
 	/* Now use mmap to map the library into memory. */
+#ifdef CONFIG_MOSIX
+	error = do_mmap_down(file, start_addr, ex.a_text + ex.a_data,
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+			N_TXTOFF(ex));
+#else
 	down_write(&current->mm->mmap_sem);
 	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
 			PROT_READ | PROT_WRITE | PROT_EXEC,
 			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 			N_TXTOFF(ex));
 	up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 	retval = error;
 	if (error != start_addr)
 		goto out;
diff -Naur --exclude=CVS --exclude=configs linux/fs/binfmt_elf.c linux-openmosix/fs/binfmt_elf.c
--- linux/fs/binfmt_elf.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/binfmt_elf.c	2004-02-05 10:51:20.000000000 +0100
@@ -42,6 +42,10 @@
 
 #include <linux/elf.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_elf_library(struct file*);
 static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
@@ -106,12 +110,17 @@
 	}
 }
 
-static elf_addr_t * 
+static elf_addr_t *
 create_elf_tables(char *p, int argc, int envc,
 		  struct elfhdr * exec,
 		  unsigned long load_addr,
 		  unsigned long load_bias,
+#ifdef CONFIG_MOSIX
+		  unsigned long interp_load_addr, int ibcs,
+		  struct elf_tables_extras *extras)
+#else
 		  unsigned long interp_load_addr, int ibcs)
+#endif /* CONFIG_MOSIX */
 {
 	elf_caddr_t *argv;
 	elf_caddr_t *envp;
@@ -123,13 +132,18 @@
 
 	/*
 	 * Get hold of platform and hardware capabilities masks for
-	 * the machine we are running on.  In some cases (Sparc), 
+	 * the machine we are running on.  In some cases (Sparc),
 	 * this info is impossible to get, in others (i386) it is
 	 * merely difficult.
 	 */
 
+#ifdef CONFIG_MOSIX
+	hwcap = extras->hwcap;
+	k_platform = extras->platform;
+#else
 	hwcap = ELF_HWCAP;
 	k_platform = ELF_PLATFORM;
+#endif /* CONFIG_MOSIX */
 
 	if (k_platform) {
 		platform_len = strlen(k_platform) + 1;
@@ -192,12 +206,19 @@
 	NEW_AUX_ENT( 6, AT_BASE, interp_load_addr);
 	NEW_AUX_ENT( 7, AT_FLAGS, 0);
 	NEW_AUX_ENT( 8, AT_ENTRY, load_bias + exec->e_entry);
+#ifdef CONFIG_MOSIX
+	NEW_AUX_ENT(9, AT_UID, (elf_addr_t) extras->uid);
+	NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) extras->euid);
+	NEW_AUX_ENT(11, AT_GID, (elf_addr_t) extras->gid);
+	NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) extras->egid);
+#else
 	NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid);
 	NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
 	NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
 	NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
+#endif /* CONFIG_MOSIX */
 #ifdef ARCH_DLINFO
-	/* 
+	/*
 	 * ARCH_DLINFO must come last so platform specific code can enforce
 	 * special alignment requirements on the AUXV if necessary (eg. PPC).
 	 */
@@ -244,11 +265,17 @@
 {
 	unsigned long map_addr;
 
+#ifdef CONFIG_MOSIX
+	map_addr = do_mmap_down(filep, ELF_PAGESTART(addr),
+			eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot,
+			type, eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
+#else
 	down_write(&current->mm->mmap_sem);
 	map_addr = do_mmap(filep, ELF_PAGESTART(addr),
 			   eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,
 			   eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
 	up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 	return(map_addr);
 }
 
@@ -350,7 +377,7 @@
 	/*
 	 * Now fill out the bss section.  First pad the last page up
 	 * to the page boundary, and then perform a mmap to make sure
-	 * that there are zero-mapped pages up to and including the 
+	 * that there are zero-mapped pages up to and including the
 	 * last bss page.
 	 */
 	padzero(elf_bss);
@@ -377,10 +404,23 @@
 	loff_t offset;
 	int retval;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		mosix_deputy_fix_elf_aout_interp(interp_ex->a_bss,
+					interp_ex->a_data, interp_ex->a_text);
+	else
+#endif /* CONFIG_MOSIX */
 	current->mm->end_code = interp_ex->a_text;
 	text_data = interp_ex->a_text + interp_ex->a_data;
+#ifdef CONFIG_MOSIX
+	if(!current->mosix.dflags & DDEPUTY)
+	{
+#endif /* CONFIG_MOSIX */
 	current->mm->end_data = text_data;
 	current->mm->brk = interp_ex->a_bss + text_data;
+#ifdef CONFIG_MOSIX
+	}
+#endif /* CONFIG_MOSIX */
 
 	switch (N_MAGIC(*interp_ex)) {
 	case OMAGIC:
@@ -403,6 +443,12 @@
 	retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
 	if (retval < 0)
 		goto out;
+#ifdef CONFIG_MOSIX
+#ifndef __i386__
+On platforms where "flush_icache_range" is non-empty,
+it has to distributed and run REMOTELY.
+#endif /* __i386__ */
+#endif /* CONFIG_MOSIX */
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
 
@@ -446,7 +492,10 @@
   	struct exec interp_ex;
 	char passed_fileno[6];
 	struct files_struct *files;
-	
+#ifdef CONFIG_MOSIX
+	struct elf_tables_extras extras;
+#endif /* CONFIG_MOSIX */
+
 	/* Get the exec-header */
 	elf_ex = *((struct elfhdr *) bprm->buf);
 
@@ -595,7 +644,7 @@
 		  if (elf_interpreter) {
 		    retval = copy_strings_kernel(1,&passed_p,bprm);
 			if (retval)
-				goto out_free_dentry; 
+				goto out_free_dentry;
 		    bprm->argc++;
 		  }
 		}
@@ -614,6 +663,22 @@
 	}
 
 	/* OK, This is the point of no return */
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		current->flags &= ~PF_FORKNOEXEC;
+		elf_entry = (unsigned long) elf_ex.e_entry;
+		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+		mosix_deputy_setup_args(SETUP_ARGS_AS_ELF, NULL);
+		if(IS_ERR((const unsigned *)bprm->p))
+		{
+			send_sig(SIGKILL, current, 0);
+			return(0);	/* too late for error */
+		}
+	}
+	else
+	{
+#endif /* CONFIG_MOSIX */
 	current->mm->start_data = 0;
 	current->mm->end_data = 0;
 	current->mm->end_code = 0;
@@ -631,6 +696,9 @@
 	}
 	
 	current->mm->start_stack = bprm->p;
+#ifdef CONFIG_MOSIX
+	}
+#endif /* CONFIG_MOSIX */
 
 	/* Now we do a little grungy work by mmaping the ELF image into
 	   the correct location in memory.  At this point, we assume that
@@ -646,7 +714,7 @@
 
 		if (unlikely (elf_brk > elf_bss)) {
 			unsigned long nbyte;
-	            
+
 			/* There was a PT_LOAD segment with p_memsz > p_filesz
 			   before this one. Map anonymous pages, if needed,
 			   and clear the area.  */
@@ -745,6 +813,26 @@
 
 	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
+#ifdef CONFIG_MOSIX
+	extras.uid = current->uid;
+	extras.euid = current->euid;
+	extras.gid = current->gid;
+	extras.egid = current->egid;
+	extras.hwcap = ELF_HWCAP;
+	memcpy(extras.platform, ELF_PLATFORM, sizeof(extras.platform));
+	extras.platform[sizeof(extras.platform)-1] = '\0';
+	if(current->mosix.dflags & DDEPUTY)
+	    bprm->p = mosix_deputy_elf_setup((char *)bprm->p,
+		bprm->argc, bprm->envc, &elf_ex,
+		load_addr, load_bias, interp_load_addr,
+		(interpreter_type == INTERPRETER_AOUT ? 0 : 1),
+		interpreter_type == INTERPRETER_AOUT ?
+			strlen(passed_fileno) + 1 : 0,
+		elf_brk, end_code, start_code, start_data, end_data, elf_bss,
+		current->personality, &extras);
+	if(!(current->mosix.dflags & DDEPUTY))	/* must check again! */
+	{
+#endif /* CONFIG_MOSIX */
 	bprm->p = (unsigned long)
 	  create_elf_tables((char *)bprm->p,
 			bprm->argc,
@@ -752,7 +840,12 @@
 			&elf_ex,
 			load_addr, load_bias,
 			interp_load_addr,
+#ifdef CONFIG_MOSIX
+			(interpreter_type == INTERPRETER_AOUT ? 0 : 1),
+								&extras);
+#else
 			(interpreter_type == INTERPRETER_AOUT ? 0 : 1));
+#endif /* CONFIG_MOSIX */
 	/* N.B. passed_fileno might not be initialized? */
 	if (interpreter_type == INTERPRETER_AOUT)
 		current->mm->arg_start += strlen(passed_fileno) + 1;
@@ -786,11 +879,21 @@
 		   Since we do not have the power to recompile these, we
 		   emulate the SVr4 behavior.  Sigh.  */
 		/* N.B. Shouldn't the size here be PAGE_SIZE?? */
+#ifdef CONFIG_MOSIX
+		error = do_mmap_down(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+				MAP_FIXED | MAP_PRIVATE, 0);
+#else
 		down_write(&current->mm->mmap_sem);
 		error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
 				MAP_FIXED | MAP_PRIVATE, 0);
 		up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
+	}
+
+#ifdef CONFIG_MOSIX
 	}
+	mosix_obtain_registers(START_THREAD_REGS|ELF_PLAT_INIT_REGS);
+#endif /* CONFIG_MOSIX */
 
 #ifdef ELF_PLAT_INIT
 	/*
@@ -832,6 +935,69 @@
 	goto out;
 }
 
+#ifdef CONFIG_MOSIX
+/*
+ * the following routine is the remote portion of part of "do_load_elf_binary"
+ * and must be updated with changes to the former.
+ */
+unsigned long
+elf_remote_setup(char *p, int argc, int envc, struct elfhdr *exec,
+	unsigned long load_addr, unsigned long load_bias,
+	unsigned long interp_load_addr, int ibcs, int add_arg_start,
+	unsigned long elf_brk, unsigned long end_code, unsigned long start_code,
+	unsigned long start_data, unsigned long end_data, unsigned long elf_bss,
+	unsigned long personality, struct elf_tables_extras *extras)
+{
+	unsigned long ret;
+	struct exec_domain *new_domain = lookup_exec_domain(personality);
+
+	if(!new_domain)
+		mosix_go_home(2);	/* never returns */
+
+	if (current->exec_domain && current->exec_domain->module)
+		__MOD_DEC_USE_COUNT(current->exec_domain->module);
+	current->exec_domain = new_domain;
+	if (new_domain->module)
+		__MOD_INC_USE_COUNT(new_domain->module);
+	ret = (unsigned long)create_elf_tables(p, argc, envc, exec, load_addr,
+		load_bias, interp_load_addr, ibcs, extras);
+	current->mm->arg_start += add_arg_start;
+	current->mm->start_brk = current->mm->brk = elf_brk;
+	current->mm->end_code = end_code;
+	current->mm->start_code = start_code;
+	current->mm->start_data = start_data;
+	current->mm->end_data = end_data;
+	current->mm->start_stack = (unsigned long)p;
+
+	/* Calling set_brk effectively mmaps the pages that we need for the bss and break
+	   sections */
+	set_brk(elf_bss, elf_brk);
+
+	padzero(elf_bss);
+
+#if 0
+	printk("(start_brk) %x\n" , current->mm->start_brk);
+	printk("(end_code) %x\n" , current->mm->end_code);
+	printk("(start_code) %x\n" , current->mm->start_code);
+	printk("(end_data) %x\n" , current->mm->end_data);
+	printk("(start_stack) %x\n" , current->mm->start_stack);
+	printk("(brk) %x\n" , current->mm->brk);
+#endif
+
+	if ( personality == PER_SVR4 )
+	{
+		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+		   and some applications "depend" upon this behavior.
+		   Since we do not have the power to recompile these, we
+		   emulate the SVr4 behavior.  Sigh.  */
+		/* N.B. Shouldn't the size here be PAGE_SIZE?? */
+		do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+				MAP_FIXED | MAP_PRIVATE, 0);
+	}
+	return(ret);
+}
+#endif /* CONFIG_MOSIX */
+
 /* This is really simpleminded and specialized - we are loading an
    a.out library that is given an ELF header. */
 
@@ -878,6 +1044,16 @@
 	while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
 
 	/* Now use mmap to map the library into memory. */
+#ifdef CONFIG_MOSIX
+	error = do_mmap_down(file,
+			ELF_PAGESTART(elf_phdata->p_vaddr),
+			(elf_phdata->p_filesz +
+			 ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+			(elf_phdata->p_offset -
+			 ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
+#else
 	down_write(&current->mm->mmap_sem);
 	error = do_mmap(file,
 			ELF_PAGESTART(elf_phdata->p_vaddr),
@@ -888,6 +1064,7 @@
 			(elf_phdata->p_offset -
 			 ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
 	up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 	if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
 		goto out_free_ph;
 
@@ -967,6 +1144,14 @@
 
 #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
 
+#ifdef CONFIG_MOSIX
+int
+elf_maydump(struct vm_area_struct *vma)
+{
+	return(maydump(vma));
+}
+#endif /* CONFIG_MOSIX */
+
 /* An ELF note in memory */
 struct memelfnote
 {
@@ -1061,17 +1246,60 @@
 	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
 	elf_fpregset_t fpu;		/* NT_PRFPREG */
 	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
+#ifdef CONFIG_MOSIX
+	struct vmalist *vmas = NULL, *rvma;
+	unsigned long arg_start, arg_end;
+#endif /* CONFIG_MOSIX */
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		segs = 0;
+		mosix_deputy_rusage(0);
+		if((i=mosix_deputy_list_vmas(&vmas, &arg_start, &arg_end)) < 0)
+		{
+			MOD_DEC_USE_COUNT;
+			return(0);
+		}
+		for(rvma = vmas ; i-- > 0 ; rvma++)
+		{
+			if(rvma->maydump)
+			{
+				int sz = rvma->vmend - rvma->vmstart;
+
+				if (size+sz >= limit)
+					break;
+				else
+					size += sz;
+			}
+			segs++;
+		}
+		vma = NULL;	/* to satisfy the silly compiler */
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	/* first copy the parameters from user space */
 	memset(&psinfo, 0, sizeof(psinfo));
 	{
 		int i, len;
 
+#ifdef CONFIG_MOSIX
+		if(current->mosix.dflags & DDEPUTY)
+			len = arg_end - arg_start;
+		else
+#endif /* CONFIG_MOSIX */
 		len = current->mm->arg_end - current->mm->arg_start;
 		if (len >= ELF_PRARGSZ)
 			len = ELF_PRARGSZ-1;
+#ifdef CONFIG_MOSIX
+		copy_from_user(&psinfo.pr_psargs,
+			(current->mosix.dflags & DDEPUTY) ?
+			   (const char *)arg_start :
+  			      (const char *)current->mm->arg_start, len);
+#else
 		copy_from_user(&psinfo.pr_psargs,
 			      (const char *)current->mm->arg_start, len);
+#endif /* CONFIG_MOSIX */
 		for(i = 0; i < len; i++)
 			if (psinfo.pr_psargs[i] == 0)
 				psinfo.pr_psargs[i] = ' ';
@@ -1084,6 +1312,9 @@
 	 * This transfers the registers from regs into the standard
 	 * coredump arrangement, whatever that is.
 	 */
+#ifdef CONFIG_MOSIX
+	mosix_obtain_registers(ALL_REGISTERS);
+#endif /* CONFIG_MOSIX */
 #ifdef ELF_CORE_COPY_REGS
 	ELF_CORE_COPY_REGS(prstatus.pr_reg, regs)
 #else
@@ -1097,11 +1328,15 @@
 #endif
 
 	/* now stop all vm operations */
+#ifdef CONFIG_MOSIX
+	if(!(current->mosix.dflags & DDEPUTY))
+	{
+		down_write(&current->mm->mmap_sem);
+		segs = current->mm->map_count;
+	}
+#else	
 	down_write(&current->mm->mmap_sem);
 	segs = current->mm->map_count;
-
-#ifdef DEBUG
-	printk("elf_core_dump: %d segs %lu limit\n", segs, limit);
 #endif
 
 	/* Set up header */
@@ -1169,7 +1404,12 @@
 	notes[1].type = NT_PRPSINFO;
 	notes[1].datasz = sizeof(psinfo);
 	notes[1].data = &psinfo;
+#ifdef CONFIG_MOSIX
+	i = LOGICAL_STATE(current);
+	i = i ? ffz(~i) + 1 : 0;
+#else
 	i = current->state ? ffz(~current->state) + 1 : 0;
+#endif /* CONFIG_MOSIX */
 	psinfo.pr_state = i;
 	psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];
 	psinfo.pr_zomb = psinfo.pr_sname == 'Z';
@@ -1185,6 +1425,11 @@
 	notes[2].data = current;
 
 	/* Try to dump the FPU. */
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		prstatus.pr_fpvalid = mosix_deputy_dump_fpu(&fpu);
+	else
+#endif /* CONFIG_MOSIX */
 	prstatus.pr_fpvalid = dump_fpu (regs, &fpu);
 	if (!prstatus.pr_fpvalid)
 	{
@@ -1197,7 +1442,7 @@
 		notes[3].datasz = sizeof(fpu);
 		notes[3].data = &fpu;
 	}
-	
+
 	/* Write notes phdr entry */
 	{
 		struct elf_phdr phdr;
@@ -1223,6 +1468,30 @@
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
 	/* Write program headers for segments dump */
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	for(rvma = vmas , i = 0 ; i < segs ; rvma++ , i++) {
+		struct elf_phdr phdr;
+		size_t sz;
+
+		sz = rvma->vmend - rvma->vmstart;
+
+		phdr.p_type = PT_LOAD;
+		phdr.p_offset = offset;
+		phdr.p_vaddr = rvma->vmstart;
+		phdr.p_paddr = 0;
+		phdr.p_filesz = rvma->maydump ? sz : 0;
+		phdr.p_memsz = sz;
+		offset += phdr.p_filesz;
+		phdr.p_flags = (rvma->vmflags & VM_READ) ? PF_R : 0;
+		if (rvma->vmflags & VM_WRITE) phdr.p_flags |= PF_W;
+		if (rvma->vmflags & VM_EXEC) phdr.p_flags |= PF_X;
+		phdr.p_align = ELF_EXEC_PAGESIZE;
+
+		DUMP_WRITE(&phdr, sizeof(phdr));
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		struct elf_phdr phdr;
 		size_t sz;
@@ -1250,6 +1519,23 @@
 
 	DUMP_SEEK(dataoff);
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		for(i = 0 , rvma = vmas ; i < segs ; rvma++ , i++)
+		if(rvma->maydump)
+		{
+			unsigned long addr = rvma->vmstart;
+			unsigned long len = rvma->vmend - rvma->vmstart;
+
+#ifdef DEBUG
+			printk("elf_core_dump: writing %08lx %lx\n", addr, len);
+#endif
+			DUMP_WRITE((void *)addr, len);
+		}
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		unsigned long addr;
 
@@ -1292,7 +1578,14 @@
 	}
 
  end_coredump:
+#ifdef CONFIG_MOSIX
+	if(vmas)
+		kfree(vmas);
+#endif /* CONFIG_MOSIX */
 	set_fs(fs);
+#ifdef CONFIG_MOSIX
+	if (!(current->mosix.dflags & DDEPUTY))
+#endif		
 	up_write(&current->mm->mmap_sem);
 	return has_dumped;
 }
diff -Naur --exclude=CVS --exclude=configs linux/fs/buffer.c linux-openmosix/fs/buffer.c
--- linux/fs/buffer.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/buffer.c	2004-02-05 10:51:20.000000000 +0100
@@ -53,6 +53,10 @@
 #include <asm/bitops.h>
 #include <asm/mmu_context.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 #define NR_RESERVED (10*MAX_BUF_PER_PAGE)
 #define MAX_UNUSED_BUFFERS NR_RESERVED+20 /* don't ever have more than this 
 					     number of unused buffer heads */
@@ -425,6 +429,10 @@
 	struct inode * inode;
 	int ret, err;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
+
 	ret = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -464,7 +472,7 @@
 
 	if (unlikely(!file->f_op || !file->f_op->fsync))
 		return -EINVAL;
-	
+
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
@@ -484,6 +492,10 @@
 	struct inode *inode;
 	int ret;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
+
 	ret = -EBADF;
 	file = fget(fd);
 	if (!file)
diff -Naur --exclude=CVS --exclude=configs linux/fs/dcache.c linux-openmosix/fs/dcache.c
--- linux/fs/dcache.c	2003-06-13 16:51:37.000000000 +0200
+++ linux-openmosix/fs/dcache.c	2004-02-05 10:51:20.000000000 +0100
@@ -26,6 +26,10 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/smp_lock.h>
+#endif /* CONFIG_MOSIX */
+
 #define DCACHE_PARANOIA 1
 /* #define DCACHE_DEBUG 1 */
 
@@ -833,6 +837,11 @@
 void d_rehash(struct dentry * entry)
 {
 	struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
+
+#ifdef CONFIG_MOSIX_FS
+	if(entry->d_flags & DCACHE_NO_CACHE)
+		return;
+#endif /* CONFIG_MOSIX_FS */
 	if (!list_empty(&entry->d_hash)) BUG();
 	spin_lock(&dcache_lock);
 	list_add(&entry->d_hash, list);
@@ -905,6 +914,9 @@
 	spin_lock(&dcache_lock);
 	/* Move the dentry to the target hash queue */
 	list_del(&dentry->d_hash);
+#ifdef CONFIG_MOSIX_FS
+	if(!(dentry->d_flags & DCACHE_NO_CACHE))
+#endif /* CONFIG_MOSIX_FS */
 	list_add(&dentry->d_hash, &target->d_hash);
 
 	/* Unhash the target: dput() will then get rid of it */
@@ -950,6 +962,9 @@
 
 	*--end = '\0';
 	buflen--;
+#ifdef CONFIG_MOSIX_FS
+	if (!(dentry->d_flags & DCACHE_NO_CACHE))
+#endif /* CONFIG_MOSIX_FS */
 	if (!IS_ROOT(dentry) && list_empty(&dentry->d_hash)) {
 		buflen -= 10;
 		end -= 10;
@@ -1024,19 +1039,40 @@
 	char *page = (char *) __get_free_page(GFP_USER);
 
 	if (!page)
+#ifdef CONFIG_MOSIX_DFSA
+		return ((current->mosix.dflags & DREMOTE) ?
+							-EDOITATHOME : -ENOMEM);
+#else
 		return -ENOMEM;
+#endif /* CONFIG_MOSIX_DFSA */
 
 	read_lock(&current->fs->lock);
+#ifdef CONFIG_MOSIX_DFSA
+	if(!current->fs->pwd)	/* we are REMOTE and not on a DFSA FS! */
+	{
+		read_unlock(&current->fs->lock);
+		return(-EDOITATHOME);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	pwdmnt = mntget(current->fs->pwdmnt);
 	pwd = dget(current->fs->pwd);
 	rootmnt = mntget(current->fs->rootmnt);
 	root = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+	if(pwd->d_inode->i_op && pwd->d_inode->i_op->check_path)
+		pwd->d_inode->i_op->check_path(pwd);
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
 
 	error = -ENOENT;
 	/* Has the current directory has been unlinked? */
 	spin_lock(&dcache_lock);
+#ifdef CONFIG_MOSIX_FS
+	if (pwd->d_parent == pwd || !list_empty(&pwd->d_hash) ||
+					(pwd->d_flags & DCACHE_NO_CACHE)) {
+#else
 	if (pwd->d_parent == pwd || !list_empty(&pwd->d_hash)) {
+#endif /* CONFIG_MOSIX_FS */
 		unsigned long len;
 		char * cwd;
 
diff -Naur --exclude=CVS --exclude=configs linux/fs/dnotify.c linux-openmosix/fs/dnotify.c
--- linux/fs/dnotify.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/fs/dnotify.c	2004-02-05 10:51:20.000000000 +0100
@@ -20,6 +20,10 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
 int dir_notify_enable = 1;
@@ -78,6 +82,10 @@
 	inode = filp->f_dentry->d_inode;
 	if (!S_ISDIR(inode->i_mode))
 		return -ENOTDIR;
+#ifdef CONFIG_MOSIX_FS
+	if(inode->i_sb->s_magic == MFS_SUPER_MAGIC)
+		return(-EPERM);
+#endif /* CONFIG_MOSIX_FS */
 	dn = kmem_cache_alloc(dn_cache, SLAB_KERNEL);
 	if (dn == NULL)
 		return -ENOMEM;
diff -Naur --exclude=CVS --exclude=configs linux/fs/exec.c linux-openmosix/fs/exec.c
--- linux/fs/exec.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/exec.c	2004-02-05 10:51:20.000000000 +0100
@@ -19,7 +19,7 @@
  * current->executable is only used by the procfs.  This allows a dispatch
  * table to check for several different types  of binary formats.  We keep
  * trying until we recognize the file or we run out of supported binary
- * formats. 
+ * formats.
  */
 
 #include <linux/config.h>
@@ -49,6 +49,13 @@
 #endif
 
 int core_uses_pid;
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 char core_pattern[65] = "core";
 int core_setuid_ok = 0;
 /* The maximal length of core_pattern is also specified in sysctl.c */ 
@@ -75,7 +82,7 @@
 	fmt->next = formats;
 	formats = fmt;
 	write_unlock(&binfmt_lock);
-	return 0;	
+	return 0;
 }
 
 int unregister_binfmt(struct linux_binfmt * fmt)
@@ -130,6 +137,9 @@
 	if (IS_ERR(file))
 		goto out;
 
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dflags &= ~DSTATSDOWN;	/* NOT a DFSA system-call */
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -ENOEXEC;
 	if(file->f_op && file->f_op->read) {
 		struct linux_binfmt * fmt;
@@ -185,7 +195,7 @@
  * memory to free pages in kernel mem. These are in a format ready
  * to be put directly into the top of new user memory.
  */
-int copy_strings(int argc,char ** argv, struct linux_binprm *bprm) 
+int copy_strings(int argc,char ** argv, struct linux_binprm *bprm)
 {
 	struct page *kmapped_page = NULL;
 	char *kaddr = NULL;
@@ -270,10 +280,10 @@
 {
 	int r;
 	mm_segment_t oldfs = get_fs();
-	set_fs(KERNEL_DS); 
+	set_fs(KERNEL_DS);
 	r = copy_strings(argc, argv, bprm);
 	set_fs(oldfs);
-	return r; 
+	return r;
 }
 
 /*
@@ -337,9 +347,14 @@
 	bprm->exec += stack_base;
 
 	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
-	if (!mpnt) 
-		return -ENOMEM; 
-	
+	if (!mpnt)
+		return -ENOMEM;
+ 
+	if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p)) >> PAGE_SHIFT)) {
+ 		kmem_cache_free(vm_area_cachep, mpnt);
+ 		return -ENOMEM;
+ 	}
+
 	down_write(&current->mm->mmap_sem);
 	{
 		mpnt->vm_mm = current->mm;
@@ -353,7 +368,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;
-	} 
+	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
 		struct page *page = bprm->page[i];
@@ -364,7 +379,7 @@
 		stack_base += PAGE_SIZE;
 	}
 	up_write(&current->mm->mmap_sem);
-	
+
 	return 0;
 }
 
@@ -375,7 +390,16 @@
 	struct file *file;
 	int err = 0;
 
+#ifdef CONFIG_MOSIX_FS
+        /* if file is MFS, we need to complete in order to perform the "open"
+         * method of dentry_open (which is NULL on MFS itself) */
+        nd.express_function = EF_OPEN;
+        nd.complete_args.ints.i1 = O_RDONLY+1;
+        nd.complete_args.ints.i2 = 0;
+        err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_COMPLETE, &nd);
+#else
 	err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
+#endif /* CONFIG_MOSIX_FS */
 	file = ERR_PTR(err);
 	if (!err) {
 		inode = nd.dentry->d_inode;
@@ -421,7 +445,11 @@
 	return result;
 }
 
+#ifdef CONFIG_MOSIX
+int exec_mmap(void)
+#else
 static int exec_mmap(void)
+#endif /* CONFIG_MOSIX */
 {
 	struct mm_struct * mm, * old_mm;
 
@@ -449,6 +477,9 @@
 		task_unlock(current);
 		activate_mm(active_mm, mm);
 		mm_release();
+#ifdef CONFIG_MOSIX
+		mosix_exec_mmap(old_mm);
+#endif /* CONFIG_MOSIX */
 		if (old_mm) {
 			if (active_mm != old_mm) BUG();
 			mmput(old_mm);
@@ -466,7 +497,7 @@
  * disturbing other processes.  (Other processes might share the signal
  * table via the CLONE_SIGNAL option to clone().)
  */
- 
+
 static inline int make_private_signals(void)
 {
 	struct signal_struct * newsig;
@@ -484,7 +515,7 @@
 	spin_unlock_irq(&current->sigmask_lock);
 	return 0;
 }
-	
+
 /*
  * If make_private_signals() made a copy of the signal table, decrement the
  * refcount of the original table, and free it if necessary.
@@ -567,21 +598,28 @@
 	oldsig = current->sig;
 	retval = make_private_signals();
 	if (retval) goto flush_failed;
-
+	
 	/*
 	 * Make sure we have private file handles. Ask the
 	 * fork helper to do the work for us and the exit
 	 * helper to do the cleanup of the old one.
 	 */
-	 
-	files = current->files;		/* refcounted so safe to hold */
+
+	files = current->files;         /* refcounted so safe to hold */
 	retval = unshare_files();
 	if(retval)
 		goto flush_failed;
 	
-	/* 
+	/*
 	 * Release all of the old mmap stuff
 	 */
+#ifdef CONFIG_MOSIX
+	if(!(current->mosix.dflags & DDEPUTY))
+		mosix_clear_statistics();
+	if(current->mosix.dflags & DDEPUTY)
+		retval = mosix_deputy_exec_mmap(bprm->filename);
+	else
+#endif /* CONFIG_MOSIX */
 	retval = exec_mmap();
 	if (retval) goto mmap_failed;
 
@@ -593,8 +631,12 @@
 	current->sas_ss_sp = current->sas_ss_size = 0;
 
 	if (current->euid == current->uid && current->egid == current->gid) {
+#ifdef CONFIG_MOSIX
+	  	set_me_dumpable(1);
+#else
 		current->mm->dumpable = 1;
 		current->task_dumpable = 1;
+#endif /* CONFIG_MOSIX */
 	}
 	name = bprm->filename;
 	for (i=0; (ch = *(name++)) != '\0';) {
@@ -605,20 +647,27 @@
 				current->comm[i++] = ch;
 	}
 	current->comm[i] = '\0';
+#ifdef CONFIG_MOSIX
+	tell_process(current, DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
 
 	flush_thread();
 
 	de_thread(current);
 
-	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
+	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
 	    permission(bprm->file->f_dentry->d_inode,MAY_READ))
+#ifdef CONFIG_MOSIX
+		set_me_dumpable(0);
+#else
 		current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 
 	/* An exec changes our domain. We are no longer part of the thread
 	   group */
-	   
+
 	current->self_exec_id++;
-			
+
 	flush_signal_handlers(current);
 	flush_old_files(current->files);
 
@@ -646,8 +695,8 @@
 	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
 }
 
-/* 
- * Fill the binprm structure from the inode. 
+/*
+ * Fill the binprm structure from the inode.
  * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
  */
 int prepare_binprm(struct linux_binprm *bprm)
@@ -701,7 +750,7 @@
 			cap_set_full(bprm->cap_inheritable);
 			cap_set_full(bprm->cap_permitted);
 		}
-		if (bprm->e_uid == 0) 
+		if (bprm->e_uid == 0)
 			cap_set_full(bprm->cap_effective);
 	}
 
@@ -724,7 +773,7 @@
  *
  */
 
-void compute_creds(struct linux_binprm *bprm) 
+void compute_creds(struct linux_binprm *bprm)
 {
 	kernel_cap_t new_permitted, working;
 	int do_unlock = 0;
@@ -736,12 +785,21 @@
 
 	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
 	    !cap_issubset(new_permitted, current->cap_permitted)) {
+#ifdef CONFIG_MOSIX
+                set_me_dumpable(0);
+#else
                 current->mm->dumpable = 0;
-		
+#endif /* CONFIG_MOSIX */
+
 		lock_kernel();
 		if (must_not_trace_exec(current)
+#ifdef CONFIG_MOSIX_DFSA
+		    || atomic_read(&current->fs->users) > 1
+		    || atomic_read(&current->files->users) > 1
+#else
 		    || atomic_read(&current->fs->count) > 1
 		    || atomic_read(&current->files->count) > 1
+#endif /* CONFIG_MOSIX_DFSA */
 		    || atomic_read(&current->sig->count) > 1) {
 			if(!capable(CAP_SETUID)) {
 				bprm->e_uid = current->uid;
@@ -764,9 +822,15 @@
 		current->cap_effective =
 			cap_intersect(new_permitted, bprm->cap_effective);
 	}
-	
+
         /* AUD: Audit candidate if current->cap_effective is set */
 
+#ifdef CONFIG_MOSIX
+	tell_process(current, DREQ_CAPCNG|DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
         current->suid = current->euid = current->fsuid = bprm->e_uid;
         current->sgid = current->egid = current->fsgid = bprm->e_gid;
 
@@ -911,13 +975,26 @@
 		return retval;
 
 	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
-	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); 
+	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
 
 	bprm.file = file;
 	bprm.filename = filename;
 	bprm.sh_bang = 0;
 	bprm.loader = 0;
 	bprm.exec = 0;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		mosix_deputy_count_args(argv, envp, &bprm.argc, &bprm.envc);
+		if(bprm.argc < 0 || bprm.envc < 0)
+		{
+			allow_write_access(file);
+			fput(file);
+			return(bprm.argc < 0 ? bprm.argc : bprm.envc);
+		}
+		goto counted;
+	}
+#endif /* CONFIG_MOSIX */
 	if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {
 		allow_write_access(file);
 		fput(file);
@@ -929,30 +1006,61 @@
 		fput(file);
 		return bprm.envc;
 	}
+#ifdef CONFIG_MOSIX
+	counted:
+#endif /* CONFIG_MOSIX */
 
 	retval = prepare_binprm(&bprm);
-	if (retval < 0) 
-		goto out; 
+#ifdef CONFIG_MOSIX
+	current->mosix.inexec = &bprm;
+	if((current->mosix.dflags & DDEPUTY) && retval >= 0)
+		retval = mosix_deputy_bring_strings(&bprm, (char *)regs->ebx,
+								envp, argv);
+	else
+	{
+#endif /* CONFIG_MOSIX */
+	if (retval < 0)
+		goto out;
 
 	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
-	if (retval < 0) 
-		goto out; 
+	if (retval < 0)
+		goto out;
 
 	bprm.exec = bprm.p;
 	retval = copy_strings(bprm.envc, envp, &bprm);
-	if (retval < 0) 
-		goto out; 
+	if (retval < 0)
+		goto out;
 
 	retval = copy_strings(bprm.argc, argv, &bprm);
-	if (retval < 0) 
-		goto out; 
+#ifdef CONFIG_MOSIX
+	}
+#endif /* CONFIG_MOSIX */
+	if (retval < 0)
+		goto out;
 
 	retval = search_binary_handler(&bprm,regs);
+#ifdef CONFIG_MOSIX
+	current->mosix.inexec = NULL;
+	if(retval >= 0)
+	{
+		mosix_decay_exec();
+		current->mosix.sigmig = 0;
+#ifdef CONFIG_MOSIX_FS
+		current->mosix.lastexec = current->mosix.whereami ? : PE;
+#ifdef CONFIG_MOSIX_DFSA
+		current->mosix.dupdates |= DFSA_UPDSEL;
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
+	}
+#endif /* CONFIG_MOSIX */
 	if (retval >= 0)
 		/* execve success */
 		return retval;
 
 out:
+#ifdef CONFIG_MOSIX
+	current->mosix.inexec = NULL;
+#endif /* CONFIG_MOSIX */
 	/* Something went wrong, return the inode and free the argument pages*/
 	allow_write_access(bprm.file);
 	if (bprm.file)
@@ -1081,8 +1189,14 @@
 	 * If core_pattern does not include a %p (as is the default)
 	 * and core_uses_pid is set, then .%pid will be appended to
 	 * the filename */
+#ifdef CONFIG_MOSIX
+	if (!pid_in_pattern || (core_uses_pid ||
+	    (current->mm && atomic_read(&current->mm->mm_realusers) != 1)))
+#else
 	if (!pid_in_pattern
-            && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
+            && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1))
+#endif /* CONFIG_MOSIX */
+	{
 		rc = snprintf(out_ptr, out_end - out_ptr,
 			      ".%d", current->pid);
 		if (rc > out_end - out_ptr)
@@ -1106,13 +1220,21 @@
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
+#ifdef CONFIG_MOSIX
+	if(!i_am_dumpable())
+#else
 	if (!is_dumpable(current))
+#endif /* CONFIG_MOSIX */
 	{
 		if(!core_setuid_ok || !current->task_dumpable)
 			goto fail;
 		current->fsuid = 0;
 	}
+#ifdef CONFIG_MOSIX
+	set_me_dumpable(0);
+#else  
 	current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 	if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
 		goto fail;
 
@@ -1134,6 +1256,10 @@
 		goto close_fail;
 	if (do_truncate(file->f_dentry, 0) != 0)
 		goto close_fail;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		mosix_deputy_rusage(0);
+#endif /* CONFIG_MOSIX */
 
 	retval = binfmt->core_dump(signr, regs, file);
 
@@ -1145,3 +1271,43 @@
 	unlock_kernel();
 	return retval;
 }
+
+#ifdef CONFIG_MOSIX
+/*
+ * The following routines are performed on the REMOTE side
+ * and must be updated whenever the corresponding original-code
+ * is modified:
+ */
+
+void
+execve_remote_counts(char **argv, char **envp, int *argc, int *envc)
+{
+/* the following definition must match the value
+ * of bprm.p at the beginning of do_execve():
+ * (otherwise, this constant needs to be passed as argument)
+ */
+#define BPRM_P_AS_SIZE (PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *))
+	if ((*argc = count(argv, BPRM_P_AS_SIZE / sizeof(void *))) < 0)
+		return;
+	if ((*envc = count(envp, BPRM_P_AS_SIZE / sizeof(void *))) < 0)
+		return;
+}
+
+int
+execve_remote_bring_strings(struct linux_binprm *bprm, char **envp, char **argv)
+{
+	int retval;
+	char *filename = getname(bprm->filename);
+
+	if(IS_ERR(filename))
+		return((int)filename);
+	retval = copy_strings_kernel(1, &filename, bprm);
+	putname(filename);
+	if(retval < 0)
+		return(retval);
+	bprm->exec = bprm->p;
+	if((retval = copy_strings(bprm->envc, envp, bprm)) < 0)
+		return(retval);
+	return(copy_strings(bprm->argc, argv, bprm));
+}
+#endif /* CONFIG_MOSIX */
diff -Naur --exclude=CVS --exclude=configs linux/fs/fcntl.c linux-openmosix/fs/fcntl.c
--- linux/fs/fcntl.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/fcntl.c	2004-02-05 10:51:20.000000000 +0100
@@ -17,6 +17,10 @@
 #include <asm/siginfo.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
 extern int fcntl_getlease(struct file *filp);
@@ -86,6 +90,13 @@
 			files->max_fdset, start);
 	}
 	
+#ifdef CONFIG_MOSIX_DFSA
+	if((current->mosix.dflags & DREMOTE) && newfd >= files->max_fds)
+	{
+		error = -EDOITATHOME;
+		goto out;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -EMFILE;
 	if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
 		goto out;
@@ -142,12 +153,24 @@
 	struct file * file, *tofree;
 	struct files_struct * files = current->files;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(oldfd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	write_lock(&files->file_lock);
 	if (!(file = fcheck(oldfd)))
 		goto out_unlock;
 	err = newfd;
 	if (newfd == oldfd)
 		goto out_unlock;
+#ifdef CONFIG_MOSIX_DFSA
+	if((current->mosix.dflags & DREMOTE) &&
+		(newfd >= files->max_fdset || newfd >= files->max_fds ||
+		(!files->fd[newfd] && FD_ISSET(newfd, files->open_fds))))
+	{
+		err = -EDOITATHOME;
+		goto out_unlock;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	err = -EBADF;
 	if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
 		goto out_unlock;
@@ -174,6 +197,11 @@
 	FD_SET(newfd, files->open_fds);
 	FD_CLR(newfd, files->close_on_exec);
 	write_unlock(&files->file_lock);
+#ifdef CONFIG_MOSIX_DFSA
+	if(tofree)
+		dfsa_close_file(newfd);
+	dfsa_open_file(newfd);
+#endif /* CONFIG_MOSIX_DFSA */
 
 	if (tofree)
 		filp_close(tofree, files);
@@ -195,6 +223,9 @@
 	int ret = -EBADF;
 	struct file * file = fget(fildes);
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fildes, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	if (file)
 		ret = dupfd(file, 0);
 	return ret;
@@ -211,6 +242,16 @@
 	 * In the case of an append-only file, O_APPEND
 	 * cannot be cleared
 	 */
+#ifdef CONFIG_MOSIX_FS
+	if(!(arg & O_APPEND))
+	/* no way to guess the IS_APPEND status on MFS - need to look */
+	{
+		struct inode_operations *iops = filp->f_dentry->d_inode->i_op;
+
+		if (iops && iops->revalidate)
+			iops->revalidate(filp->f_dentry);
+	}
+#endif /* CONFIG_MOSIX_FS */
 	if (!(arg & O_APPEND) && IS_APPEND(inode))
 		return -EPERM;
 
@@ -256,6 +297,18 @@
 {
 	long err = -EINVAL;
 
+#ifdef CONFIG_MOSIX_DFSA
+	switch(cmd)
+	{
+		case F_GETFL:
+			dfsa_syscall_on_file(fd, 0);
+			break;
+		case F_DUPFD:
+		case F_SETFL:
+			dfsa_syscall_on_file(fd, 1);
+			break;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	switch (cmd) {
 		case F_DUPFD:
 			if (arg < NR_OPEN) {
@@ -444,7 +497,11 @@
 		send_sigio_to_task(p, fown, fd, band);
 		goto out;
 	}
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		int match = p->pid;
 		if (pid < 0)
 			match = -p->pgrp;
diff -Naur --exclude=CVS --exclude=configs linux/fs/file.c linux-openmosix/fs/file.c
--- linux/fs/file.c	2002-08-03 02:39:45.000000000 +0200
+++ linux-openmosix/fs/file.c	2004-02-05 10:51:20.000000000 +0100
@@ -14,6 +14,9 @@
 
 #include <asm/bitops.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
 
 /*
  * Allocate an fd array, using kmalloc or vmalloc.
@@ -99,6 +102,10 @@
 		struct file **old_fds;
 		int i;
 		
+#ifdef CONFIG_MOSIX_DFSA
+		if(files == current->files)
+			current->mosix.dupdates |= DFSA_UPDMAX;
+#endif /* CONFIG_MOSIX_DFSA */
 		old_fds = xchg(&files->fd, new_fds);
 		i = xchg(&files->max_fds, nfds);
 
@@ -166,6 +173,9 @@
 int expand_fdset(struct files_struct *files, int nr)
 {
 	fd_set *new_openset = 0, *new_execset = 0;
+#ifdef CONFIG_MOSIX_DFSA
+	fd_set *new_closed = 0, *new_opened = 0, *new_modified = 0;
+#endif /* CONFIG_MOSIX_DFSA */
 	int error, nfds = 0;
 
 	error = -EMFILE;
@@ -189,8 +199,18 @@
 	error = -ENOMEM;
 	new_openset = alloc_fdset(nfds);
 	new_execset = alloc_fdset(nfds);
+#ifdef CONFIG_MOSIX_DFSA
+	new_closed = alloc_fdset(nfds);
+	new_opened = alloc_fdset(nfds);
+	new_modified = alloc_fdset(nfds);
+#endif /* CONFIG_MOSIX_DFSA */
 	write_lock(&files->file_lock);
+#ifdef CONFIG_MOSIX_DFSA
+	if (!new_openset || !new_execset ||
+				!new_closed || !new_opened || !new_modified)
+#else
 	if (!new_openset || !new_execset)
+#endif /* CONFIG_MOSIX_DFSA */
 		goto out;
 
 	error = 0;
@@ -200,6 +220,10 @@
 		int i = files->max_fdset / (sizeof(unsigned long) * 8);
 		int count = (nfds - files->max_fdset) / 8;
 		
+#ifdef CONFIG_MOSIX_DFSA
+		if(files == current->files)
+			current->mosix.dupdates |= DFSA_UPDMAX;
+#endif /* CONFIG_MOSIX_DFSA */
 		/* 
 		 * Don't copy the entire array if the current fdset is
 		 * not yet initialised.  
@@ -209,14 +233,32 @@
 			memcpy (new_execset, files->close_on_exec, files->max_fdset/8);
 			memset (&new_openset->fds_bits[i], 0, count);
 			memset (&new_execset->fds_bits[i], 0, count);
+#ifdef CONFIG_MOSIX_DFSA
+			memcpy (new_closed, files->closed, files->max_fdset/8);
+			memcpy (new_opened, files->opened, files->max_fdset/8);
+			memcpy (new_modified, files->modified, files->max_fdset/8);
+			memset (&new_closed->fds_bits[i], 0, count);
+			memset (&new_opened->fds_bits[i], 0, count);
+			memset (&new_modified->fds_bits[i], 0, count);
+#endif /* CONFIG_MOSIX_DFSA */
 		}
 		
 		nfds = xchg(&files->max_fdset, nfds);
 		new_openset = xchg(&files->open_fds, new_openset);
 		new_execset = xchg(&files->close_on_exec, new_execset);
+#ifdef CONFIG_MOSIX_DFSA
+		new_closed = xchg(&files->closed, new_closed);
+		new_opened = xchg(&files->opened, new_opened);
+		new_modified = xchg(&files->modified, new_modified);
+#endif /* CONFIG_MOSIX_DFSA */
 		write_unlock(&files->file_lock);
 		free_fdset (new_openset, nfds);
 		free_fdset (new_execset, nfds);
+#ifdef CONFIG_MOSIX_DFSA
+		free_fdset (files->closed, nfds);
+		free_fdset (files->opened, nfds);
+		free_fdset (files->modified, nfds);
+#endif /* CONFIG_MOSIX_DFSA */
 		write_lock(&files->file_lock);
 		return 0;
 	} 
@@ -228,6 +270,14 @@
 		free_fdset(new_openset, nfds);
 	if (new_execset)
 		free_fdset(new_execset, nfds);
+#ifdef CONFIG_MOSIX_DFSA
+	if (new_closed)
+		free_fdset(new_closed, nfds);
+	if (new_opened)
+		free_fdset(new_opened, nfds);
+	if (new_modified)
+		free_fdset(new_modified, nfds);
+#endif /* CONFIG_MOSIX_DFSA */
 	write_lock(&files->file_lock);
 	return error;
 }
diff -Naur --exclude=CVS --exclude=configs linux/fs/file_table.c linux-openmosix/fs/file_table.c
--- linux/fs/file_table.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/fs/file_table.c	2004-02-05 10:51:20.000000000 +0100
@@ -58,7 +58,12 @@
 	/*
 	 * Allocate a new one if we're below the limit.
 	 */
+#ifdef CONFIG_MOSIX_FS
+	if (files_stat.nr_files < files_stat.max_files ||
+		(current->mosix.dirty_bits & MFSARG_EMPTYF_PRI)) {
+#else
 	if (files_stat.nr_files < files_stat.max_files) {
+#endif /* CONFIG_MOSIX_FS */
 		file_list_unlock();
 		f = kmem_cache_alloc(filp_cachep, SLAB_KERNEL);
 		file_list_lock();
@@ -113,6 +118,9 @@
 			file->f_op->release(inode, file);
 		fops_put(file->f_op);
 		if (file->f_mode & FMODE_WRITE)
+#ifdef CONFIG_MOSIX
+		if (!(file->f_flags & O_NOWRITEACCESS))
+#endif /* CONFIG_MOSIX */
 			put_write_access(inode);
 		file_list_lock();
 		file->f_dentry = NULL;
diff -Naur --exclude=CVS --exclude=configs linux/fs/inode.c linux-openmosix/fs/inode.c
--- linux/fs/inode.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/inode.c	2004-02-05 10:51:20.000000000 +0100
@@ -18,6 +18,11 @@
 #include <linux/prefetch.h>
 #include <linux/locks.h>
 
+#ifdef CONFIG_MOSIX
+spinlock_t unique_gen_lock = SPIN_LOCK_UNLOCKED;
+unsigned long long unique_generator;
+#endif /* CONFIG_MOSIX */
+
 /*
  * New inode.c implementation.
  *
@@ -873,6 +878,9 @@
 		list_add(&inode->i_list, &inode_in_use);
 		inode->i_ino = ++last_ino;
 		inode->i_state = 0;
+#ifdef CONFIG_MOSIX
+		OPENMOSIX_VMODIFIED(inode);
+#endif /* CONFIG_MOSIX */
 		spin_unlock(&inode_lock);
 	}
 	return inode;
@@ -901,6 +909,9 @@
 			list_add(&inode->i_hash, head);
 			inode->i_ino = ino;
 			inode->i_state = I_LOCK;
+#ifdef CONFIG_MOSIX
+			OPENMOSIX_VMODIFIED(inode);
+#endif /* CONFIG_MOSIX */
 			spin_unlock(&inode_lock);
 
 			/* reiserfs specific hack right here.  We don't
@@ -924,7 +935,6 @@
 			 */
 			inode->i_state &= ~I_LOCK;
 			wake_up(&inode->i_wait);
-
 			return inode;
 		}
 
diff -Naur --exclude=CVS --exclude=configs linux/fs/ioctl.c linux-openmosix/fs/ioctl.c
--- linux/fs/ioctl.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/ioctl.c	2004-02-05 10:51:20.000000000 +0100
@@ -11,6 +11,10 @@
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 {
 	int error;
@@ -51,6 +55,9 @@
 	struct file * filp;
 	unsigned int flag;
 	int on, error = -EBADF;
+#ifdef CONFIG_MOSIX_DFSA
+	int flags_changed = 0;
+#endif /* CONFIG_MOSIX_DFSA */
 
 	filp = fget(fd);
 	if (!filp)
@@ -79,6 +86,9 @@
 				filp->f_flags |= flag;
 			else
 				filp->f_flags &= ~flag;
+#ifdef CONFIG_MOSIX_DFSA
+			flags_changed = 1;
+#endif /* CONFIG_MOSIX_DFSA */
 			break;
 
 		case FIOASYNC:
@@ -99,6 +109,9 @@
 				filp->f_flags |= FASYNC;
 			else
 				filp->f_flags &= ~FASYNC;
+#ifdef CONFIG_MOSIX_DFSA
+			flags_changed = 1;
+#endif /* CONFIG_MOSIX_DFSA */
 			break;
 
 		case FIOQSIZE:
@@ -120,6 +133,10 @@
 	}
 	unlock_kernel();
 	fput(filp);
+#ifdef CONFIG_MOSIX_DFSA
+	if(flags_changed)
+		dfsa_touch_file(fd);
+#endif /* CONFIG_MOSIX_DFSA */
 
 out:
 	return error;
diff -Naur --exclude=CVS --exclude=configs linux/fs/lockd/svc.c linux-openmosix/fs/lockd/svc.c
--- linux/fs/lockd/svc.c	2003-06-13 16:51:37.000000000 +0200
+++ linux-openmosix/fs/lockd/svc.c	2004-02-05 10:51:22.000000000 +0100
@@ -300,6 +300,9 @@
 	 * Wait for the lockd process to exit, but since we're holding
 	 * the lockd semaphore, we can't wait around forever ...
 	 */
+#ifdef CONFIG_MOSIX
+	current->mosix.ignoreoldsigs = 1;
+#endif /* CONFIG_MOSIX */
 	current->sigpending = 0;
 	interruptible_sleep_on_timeout(&lockd_exit, HZ);
 	if (nlmsvc_pid) {
diff -Naur --exclude=CVS --exclude=configs linux/fs/Makefile linux-openmosix/fs/Makefile
--- linux/fs/Makefile	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/Makefile	2004-02-05 10:51:20.000000000 +0100
@@ -64,6 +64,9 @@
 subdir-$(CONFIG_REISERFS_FS)	+= reiserfs
 subdir-$(CONFIG_DEVPTS_FS)	+= devpts
 subdir-$(CONFIG_SUN_OPENPROMFS)	+= openpromfs
+ifdef CONFIG_MOSIX
+subdir-$(CONFIG_MOSIX_FS)       += mfs
+endif
 subdir-$(CONFIG_BEFS_FS)	+= befs
 subdir-$(CONFIG_JFS_FS)		+= jfs
 
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/ccontact.c linux-openmosix/fs/mfs/ccontact.c
--- linux/fs/mfs/ccontact.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/ccontact.c	2002-05-31 04:12:18.000000000 +0200
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ * Some sections copyright 2002 by Moshe Bar
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/slab.h>
+#include <linux/mfs.h>
+#include <linux/mfs_socket.h>
+
+spinlock_t mfs_client_lock = SPIN_LOCK_UNLOCKED;
+
+#define MFS_CLIENT_OPTCONS	50
+#define	MFS_MAX_HOGGING_A_NODE	8
+
+struct mfs_client_contact
+{
+	struct mfs_client_contact *next;
+	int to;
+	struct socket *sock;
+	int serial;
+	int has_mh;
+	struct mfs_message_header mh;
+} *mfs_busy_clients, *mfs_connected_clients, *mfs_closing_clients;
+
+int mfs_client_serial;
+
+DECLARE_WAIT_QUEUE_HEAD(wait_for_busy_contact);
+int waiting_for_busy_contact;
+
+int
+mfs_client_send(struct mfs_client_contact *s, int type, void *header, int hdln,
+			void *dat1, int len1, void *dat2, int len2)
+{
+	return(mfs_send(s->sock, 0, s->serial,
+				type, header, hdln, dat1, len1, dat2, len2));
+}
+
+int
+mfs_client_receive(struct mfs_client_contact *s,
+					void **header, void **dat1, void **dat2)
+{
+	if(s->has_mh)
+	{
+		s->has_mh = 0;
+if(mfs_debug > 1)
+printk("mfs_client_receive: continuing with serial %d, type %d (%d/%d/%d)\n",
+s->mh.serial, s->mh.type, s->mh.hdsz, s->mh.dat1sz, s->mh.dat2sz);
+		return(mfs_receive(s->sock, MFS_MUST_MATCH, &s->serial, &s->mh,
+							header, dat1, dat2));
+	}
+	else
+		return(mfs_receive(s->sock, MFS_SKIP_OTHERS, &s->serial, NULL,
+							header, dat1, dat2));
+}
+
+int
+mfs_client_contact_has_data(struct mfs_client_contact *con)
+{
+	return(mfs_socket_has_data(con->sock));
+}
+
+void
+delayed_close_client(struct mfs_client_contact *con)
+{
+	mfs_send(con->sock, 1, 0, MFS_CLOSE, NULL, 0, NULL, 0, NULL,0);
+	spin_lock(&mfs_client_lock);
+	con->next = mfs_closing_clients;
+	mfs_closing_clients = con;
+	spin_unlock(&mfs_client_lock);
+}
+
+void
+mfs_client_check_closed(struct mfs_client_contact **head)
+{
+	struct mfs_client_contact *c, *prev, *next;
+	struct mfs_client_contact *dispose = NULL;
+
+	spin_lock(&mfs_client_lock);
+	for(prev = NULL, c = *head ; c ; c = next)
+	{
+		next = c->next;
+		if(mfs_socket_is_closed(c->sock))
+		{
+			if(prev)
+				prev->next = next;
+			else
+				*head = next;
+			c->next = dispose;
+			dispose = c;
+		}
+		else
+			prev = c;
+	}
+	spin_unlock(&mfs_client_lock);
+	for(; dispose ; dispose = next)
+	{
+		next = dispose->next;
+		mfs_close_socket(dispose->sock);
+		kfree(dispose);
+	}
+}
+
+void
+mfs_release_contact(struct mfs_client_contact *con)
+{
+	struct mfs_client_contact *s, *prev;
+	unsigned int bcnt = 0, pcnt = 0, tcnt = 0;
+	int pe = con->to;
+	unsigned int found = 0;
+
+	spin_lock(&mfs_client_lock);
+	for(prev = NULL , s = mfs_busy_clients ; s ; )
+	{
+		tcnt++;
+		if(s == con)
+		{
+			s = s->next;
+			if(prev)
+				prev->next = s;
+			else
+				mfs_busy_clients = s;
+			found = 1;
+		}
+		else
+		{
+			if(s->to == pe && ++bcnt >= MFS_MAX_HOGGING_A_NODE &&
+									found)
+				break;
+			prev = s;
+			s = s->next;
+		}
+	}
+	if(!found)
+		printk("mfs_release_contact: not listed!\n");
+	if((pcnt = bcnt) < MFS_MAX_HOGGING_A_NODE)
+	for(s = mfs_connected_clients ; s ; s = s->next)
+	{
+		tcnt++;
+		if(s->to == pe && ++pcnt == MFS_MAX_HOGGING_A_NODE)
+			break;
+	}
+	if((tcnt >= MFS_CLIENT_OPTCONS && pcnt) ||
+						pcnt >= MFS_MAX_HOGGING_A_NODE)
+	{
+		spin_unlock(&mfs_client_lock);
+		delayed_close_client(con);
+		if(bcnt >= MFS_MAX_HOGGING_A_NODE)
+			return;
+		spin_lock(&mfs_client_lock);
+	}
+	else
+	{
+		con->next = mfs_connected_clients;
+		mfs_connected_clients = con;
+	}
+	if(waiting_for_busy_contact == pe ||
+		waiting_for_busy_contact == MFS_UNKNOWN_PE)
+	{
+		waiting_for_busy_contact = 0;
+		wake_up(&wait_for_busy_contact);
+	}
+	spin_unlock(&mfs_client_lock);
+}
+
+static inline int
+node_is_hogged(int pe)
+{
+	unsigned int n = 0;
+	struct mfs_client_contact *s;
+
+	for(s = mfs_busy_clients ; s ; s = s->next)
+	if(s->to == pe && ++n == MFS_MAX_HOGGING_A_NODE)
+		return(1);
+	return(0);
+}
+
+struct mfs_client_contact *
+mfs_new_request(int pe, int type, void *header, int hdln, void *dat1, int len1,
+							void *dat2, int len2)
+{
+	struct mfs_client_contact *s, *prev, *prevprev, *con;
+	unsigned int tried_a_new = 0;
+	unsigned int cnt;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if(pe == MFS_BAD_PE)
+		return(ERR_PTR(-ESTALE));
+	spin_lock(&mfs_client_lock);
+	for(prev = prevprev = NULL , cnt = 0 , s = mfs_connected_clients ; s ;
+					prevprev = prev, prev = s , s = s->next)
+	if(s->to == pe)
+		break;
+	else
+		cnt++;
+	if(s)
+	{
+		found_a_connected:
+		if(prev)
+			prev->next = s->next;
+		else
+			mfs_connected_clients = s->next;
+		try_it:
+		con = s;
+		con->to = pe;
+		con->next = mfs_busy_clients;
+		mfs_busy_clients = con;
+		con->serial = ++mfs_client_serial;
+		spin_unlock(&mfs_client_lock);
+		if(!mfs_send(con->sock, 1, con->serial, type, header, hdln,
+						dat1, len1, dat2, len2) &&
+			mfs_receive(con->sock, MFS_JUST_HEADER, &con->serial,
+					&con->mh, NULL, NULL, NULL) >= 0)
+		{
+			con->has_mh = 1;
+if(mfs_debug > 1)
+printk("mfs_new_request: first reply will be serial %d, type %d (%d/%d/%d)\n",
+con->mh.serial, con->mh.type, con->mh.hdsz, con->mh.dat1sz, con->mh.dat2sz);
+			return(con);
+		}
+		spin_lock(&mfs_client_lock);
+		for(prev = NULL , s = mfs_busy_clients ; s && s != con ;
+							prev = s , s = s->next)
+			;
+		if(s)
+		{
+			if(prev)
+				prev->next = s->next;
+			else
+				mfs_busy_clients = s->next;
+			if(waiting_for_busy_contact == pe ||
+				waiting_for_busy_contact == MFS_UNKNOWN_PE)
+			{
+				waiting_for_busy_contact = 0;
+				wake_up(&wait_for_busy_contact);
+			}
+			spin_unlock(&mfs_client_lock);
+			mfs_close_socket(s->sock);
+			kfree(s);
+			spin_lock(&mfs_client_lock);
+		}
+		else
+			printk("mfs_new_request: contact disappeared!\n");
+	}
+	else if(cnt >= MFS_CLIENT_OPTCONS)
+	{
+		/* trim out the last one (also last used) */
+		prevprev->next = NULL;
+		spin_unlock(&mfs_client_lock);
+		delayed_close_client(prev);
+		mfs_client_check_closed(&mfs_closing_clients);
+		spin_lock(&mfs_client_lock);
+	}
+	if(tried_a_new || !PE)
+	{
+		spin_unlock(&mfs_client_lock);
+		return(ERR_PTR(-EREMOTE));
+	}
+	if(node_is_hogged(pe))
+	{
+		add_wait_queue(&wait_for_busy_contact, &wait);
+		while(1)
+		{
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			if(waiting_for_busy_contact &&
+				waiting_for_busy_contact != pe)
+				waiting_for_busy_contact = MFS_UNKNOWN_PE;
+			else
+				waiting_for_busy_contact = pe;
+			if(!node_is_hogged(pe))
+				break;
+			spin_unlock(&mfs_client_lock);
+			if(!PE)
+			{
+				remove_wait_queue(&wait_for_busy_contact, &wait);
+				set_current_state(TASK_RUNNING);
+				return(NULL);
+			}
+			schedule_timeout(HZ);
+			spin_lock(&mfs_client_lock);
+			for(prev = NULL , s = mfs_connected_clients ; s ;
+							prev = s , s = s->next)
+			if(s->to == pe)
+			{
+				remove_wait_queue(&wait_for_busy_contact,&wait);
+				set_current_state(TASK_RUNNING);
+				goto found_a_connected;
+			}
+		}
+		remove_wait_queue(&wait_for_busy_contact, &wait);
+		set_current_state(TASK_RUNNING);
+	}
+	spin_unlock(&mfs_client_lock);
+	tried_a_new++;
+	if(!(s = (struct mfs_client_contact *)kmalloc(sizeof(*s), GFP_KERNEL)))
+		return(ERR_PTR(-ENOMEM));
+	s->sock = mfs_connect_to(pe);
+	s->has_mh = 0;
+	if(!IS_ERR(s->sock))
+	{
+		spin_lock(&mfs_client_lock);
+		goto try_it;
+	}
+	con = (struct mfs_client_contact *)s->sock;
+	kfree(s);
+	return(con);
+}
+
+void
+mfs_monitor_client_contacts(void)
+{
+	mfs_client_check_closed(&mfs_connected_clients);
+	mfs_client_check_closed(&mfs_closing_clients);
+}
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/client.c linux-openmosix/fs/mfs/client.c
--- linux/fs/mfs/client.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/client.c	2003-12-02 10:59:37.000000000 +0100
@@ -0,0 +1,761 @@
+/* All changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ * Some sections copyright 2002 by Moshe Bar
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/mfs.h>
+
+void
+pack_credits(struct mfs_cred *cred)
+{
+	register struct task_struct *p = current;
+	register int i;
+
+	cred->uid = p->uid;
+	cred->euid = p->euid;
+	cred->sgid = p->sgid;
+	cred->fsuid = p->fsuid;
+	cred->gid = p->gid;
+	cred->egid = p->egid;
+	cred->sgid = p->sgid;
+	cred->fsgid = p->fsgid;
+	cred->ngroups = p->ngroups;
+	for(i = cred->ngroups-1 ; i >= 0 ; i--)
+		cred->groups[i] = p->groups[i];
+	cred->caps = p->cap_effective;
+	cred->whereami = current->mosix.whereami ? : PE;
+	cred->deppe = current->mosix.deppe ? : PE;
+}
+
+/* originally by Amnon Shiloh with changes by Moshe Bar*/
+int
+mfs_client_statfs(int pe, mfs_handle_t handle, struct statfs *statbuf)
+{
+        struct mfs_request_statfs s;
+        struct mfs_reply_statfs *r;
+        struct mfs_client_contact *con;
+	int err;
+	pack_credits(&s.cred);
+	s.handle = handle;
+	con = mfs_new_request(pe, MFS_REQUEST_STATFS, &s, sizeof(s), NULL, 0,NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_STATFS)
+	{
+		err = r->result;
+		if(err >= 0)
+		*statbuf = r->stat;
+	}
+	else if(err >= 0)
+	{
+	printk("openMosix: mfs_client_statfs: ambiguous reply %d\n", err);
+	err = -EINVAL;
+	}
+	if(r)
+	 kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+inline void
+mfs_file_up_to_date(struct file *filp)
+{
+	struct dentry *dp;
+	struct mfs_dinfo *i;
+
+	if((dp = filp->f_dentry) && (i = (struct mfs_dinfo *)dp->d_fsdata))
+		i->latest = jiffies;
+}
+
+int
+mfs_client_attach_handle(int pe, mfs_handle_t handle)
+{
+	struct mfs_request_attach_handle s;
+	struct mfs_reply_attach_handle *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	s.handle = handle;
+	con = mfs_new_request(pe, MFS_REQUEST_ATTACH_HANDLE, &s, sizeof(s),
+							NULL, 0, NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_ATTACH_HANDLE)
+		err = r->result;
+	else if(err >= 0)
+	{
+		printk("mfs_client_attach_handle: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+int
+mfs_client_touch_handle(int pe, mfs_handle_t handle)
+{
+	struct mfs_request_touch_handle s;
+	struct mfs_reply_touch_handle *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	s.handle = handle;
+	con = mfs_new_request(pe, MFS_REQUEST_TOUCH_HANDLE, &s, sizeof(s),
+							NULL, 0, NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_TOUCH_HANDLE)
+		err = r->result;
+	else if(err >= 0)
+	{
+		printk("mfs_client_touch_handle: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+void
+mfs_client_dispose_handle(int pe, mfs_handle_t handle)
+{
+	struct mfs_request_dispose_handle s;
+	struct mfs_client_contact *con;
+	void *r;
+
+	s.handle = handle;
+	con = mfs_new_request(pe, MFS_REQUEST_DISPOSE_HANDLE, &s, sizeof(s),
+							NULL, 0, NULL, 0);
+	if(IS_ERR(con))
+		return;
+	mfs_client_receive(con, &r, NULL, NULL);
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+}
+
+int
+mfs_client_llseek(int pe, mfs_handle_t handle, struct file *filp, loff_t offset,
+								int origin)
+{
+	struct mfs_request_llseek s;
+	struct mfs_reply_llseek *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.offset = offset;
+	s.origin = origin;
+	con = mfs_new_request(pe, MFS_REQUEST_LLSEEK, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_LLSEEK)
+	{
+		cp_file_fields(filp, &r->file);
+		err = r->result;
+		if(err >= 0)
+			mfs_file_up_to_date(filp);
+	}
+	else if(err >= 0)
+	{
+		printk("mfs_client_llseek: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+ssize_t
+mfs_client_read(int pe, mfs_handle_t handle, struct file *filp, char *buf,
+						size_t count, loff_t *ppos)
+{
+	struct mfs_request_read s;
+	struct mfs_reply_read *r;
+	struct mfs_client_contact *con;
+	void *data;
+	int err;
+	ssize_t i, result = 0;
+	int user_err = 0;
+	unsigned int done = 0;
+
+	if((int)count < 0)
+		return(-EINVAL);
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.count = count;
+	s.pos = *ppos;
+	con = mfs_new_request(pe, MFS_REQUEST_READ, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	while(!done)
+	{
+		err = mfs_client_receive(con, (void **)&r, &data, NULL);
+		if(err < 0)
+		{
+			result = err;
+			break;
+		}
+		switch(err)
+		{
+			case MFS_INTERIM_DATA:
+				i = ((struct mfs_interim_data *)r)->count;
+				if(!user_err && copy_to_user(buf, data, i))
+					user_err = -EFAULT;
+				else
+					buf += i;
+				/* do not exit: it is always the server
+				 * that should close the connection
+				 */
+				break;
+			case MFS_REPLY_READ:
+				done = 1;
+				if(!user_err && r->datalen &&
+					copy_to_user(buf, data, r->datalen))
+					user_err = -EFAULT;
+				cp_file_fields(filp, &r->file);
+				*ppos = r->ppos;
+				result = r->result;
+				if(result >= 0)
+					mfs_file_up_to_date(filp);
+				break;
+			default:
+				printk("mfs_client_read: unexpected reply %d\n",
+									err);
+				result = -EINVAL;
+				done = 1;
+				break;
+				
+		}
+		if(r)
+			kfree(r);
+	}
+	mfs_release_contact(con);
+	return(user_err ? : result);
+}
+
+ssize_t
+mfs_client_write(int pe, mfs_handle_t handle, struct file *filp, char *buf,
+					size_t count, loff_t *ppos, long flim)
+{
+	struct mfs_request_write s;
+	struct mfs_interim_data i;
+	struct mfs_reply_write *r;
+	struct mfs_client_contact *con;
+	void *data;
+	int err;
+	ssize_t result = 0;
+	int user_err = 0;
+	size_t max, sent, cnt;
+	char smallbuf[4];
+	char *tbuf = NULL;	/* NULL just because bad compiler complains */
+
+	if(count == 0)
+		return(0);
+	if((int)count < 0)
+		return(-EINVAL);
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.count = count;
+	s.pos = *ppos;
+	s.flim = flim;
+	for(max = count > 16384 ? 16384 : count ; max > sizeof(smallbuf) ;
+								max >>= 1)
+	if((tbuf = (char *)kmalloc(max, GFP_KERNEL)))
+		break;
+	if(max <= sizeof(smallbuf))
+	{
+		tbuf = smallbuf;
+		max = sizeof(smallbuf);
+	}
+	s.datalen = sent = count < max ? count : max;
+	if(copy_from_user(tbuf, buf, sent))
+	{
+		user_err = -EFAULT;
+		goto free_buf;
+	}
+	buf += sent;
+	con = mfs_new_request(pe, MFS_REQUEST_WRITE, &s, sizeof(s), tbuf, sent,
+								NULL, 0);
+	if(IS_ERR(con))
+	{
+		result = (int)con;
+		goto free_buf;
+	}
+	while(sent < count)
+	{
+		if(mfs_client_contact_has_data(con))
+			break;
+		cnt = count - sent;
+		if(cnt > max)
+			cnt = max;
+		if(user_err || copy_from_user(tbuf, buf, cnt))
+		{
+			user_err = -EFAULT;
+			mfs_client_send(con, MFS_STOP, NULL, 0,
+					NULL, 0, NULL, 0);
+			break;	/* let the server quit first */
+		}
+		i.count = cnt;
+		if((err = mfs_client_send(con, MFS_INTERIM_DATA,
+			&i, sizeof(i), (void *)tbuf, cnt,
+			NULL, 0)))
+		{
+			result = err;
+			break;
+		}
+		buf += cnt;
+		sent += cnt;
+	}
+	err = mfs_client_receive(con, (void **)&r, &data, NULL);
+	if(err == MFS_CONTINUE)
+		err = mfs_client_receive(con, (void **)&r, &data, NULL);
+	if(err == MFS_REPLY_WRITE)
+	{
+		cp_file_fields(filp, &r->file);
+		*ppos = r->ppos;
+		result = r->result;
+		if(result >= 0)
+			mfs_file_up_to_date(filp);
+		if(r->hadsigxfsz)
+			send_sig(SIGXFSZ, current, 0);
+	}
+	else if(err < 0)
+		result = err;
+	else
+	{
+		printk("mfs_client_write: unexpected reply %d\n", err);
+		result = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	free_buf:
+	if(max != sizeof(smallbuf))
+		kfree(tbuf);
+	return(user_err ? : result);
+}
+
+int
+mfs_client_readdir_transfer(void *d, int len, void *dirent, filldir_t filldir)
+{
+	ino_t ino;
+	loff_t off;
+	unsigned int type;
+	short namelen;
+	int err;
+
+	while(len)
+	{
+		len -= sizeof(ino)+sizeof(off)+sizeof(type)+sizeof(namelen);
+		if(len < 0)
+			return(-EINVAL);
+		ino = *((ino_t *)d)++;
+		off = *((loff_t *)d)++;
+		type = *((unsigned int *)d)++;
+		namelen = *((short *)d)++;
+		if(len < namelen)
+			return(-EINVAL);
+		len -= namelen;
+		if((err = filldir(dirent, (const char *)d, namelen, off, ino,
+									type)))
+			return(err);
+		d += namelen;
+	}
+	return(0);
+}
+
+int
+mfs_client_readdir(int pe, mfs_handle_t handle, struct file *filp, void *dirent,
+	filldir_t filldir, int policy, int maxbytes, int *packets, int *bytes)
+{
+	struct mfs_request_readdir s;
+	struct mfs_reply_readdir *r;
+	struct mfs_interim_readdir ri;
+	struct mfs_client_contact *con;
+	void *data;
+	ssize_t i;
+	int result = 0;
+	unsigned int done = 0;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.policy = policy;
+	s.maxbytes = maxbytes;
+	*packets = *bytes = 0;
+	con = mfs_new_request(pe, MFS_REQUEST_READDIR, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	while(!done && (result =
+		mfs_client_receive(con, (void **)&r, &data, NULL)) >= 0)
+	{
+		switch(result)
+		{
+			case MFS_INTERIM_DATA:
+				i = ((struct mfs_interim_data *)r)->count;
+				(*packets)++;
+				(*bytes) += i;
+				ri.error = mfs_client_readdir_transfer(data, i,
+							dirent, filldir);
+				if((result = mfs_client_send(con,
+					MFS_INTERIM_READDIR, &ri, sizeof(ri),
+					NULL, 0, NULL, 0)))
+					done = 1;
+				break;
+			case MFS_REPLY_READDIR:
+				done = 1;
+				(*bytes) += r->datalen;
+				if(!r->datalen ||
+					!(result = mfs_client_readdir_transfer(
+					data, r->datalen, dirent, filldir)))
+					result = r->result;
+				cp_file_fields(filp, &r->file);
+				if(result >= 0)
+					mfs_file_up_to_date(filp);
+				break;
+			default:
+				printk("mfs_client_readdir: unexpected reply %d\n", result);
+				result = -EINVAL;
+				done = 1;
+				break;
+		}
+		if(r)
+			kfree(r);
+	}
+	mfs_release_contact(con);
+	return(result);
+}
+
+int
+mfs_client_ioctl(int pe, mfs_handle_t handle, struct file *filp,
+		unsigned int cmd, unsigned long arg, int size, int *data)
+{
+	struct mfs_request_ioctl s;
+	struct mfs_reply_ioctl *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.cmd = cmd;
+	s.arg = arg;
+	s.data = *data;
+	s.size = size;
+	con = mfs_new_request(pe, MFS_REQUEST_IOCTL, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_IOCTL)
+	{
+		cp_file_fields(filp, &r->file);
+		if(size < 0)
+			*data = r->data;
+		err = r->result;
+		if(err >= 0)
+			mfs_file_up_to_date(filp);
+	}
+	else if(err >= 0)
+	{
+		printk("mfs_client_ioctl: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+int
+mfs_client_fsync(int pe, mfs_handle_t handle, struct file *filp, int datasync)
+{
+	struct mfs_request_fsync s;
+	struct mfs_reply_fsync *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.datasync = datasync;
+	con = mfs_new_request(pe, MFS_REQUEST_FSYNC, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_FSYNC)
+	{
+		cp_file_fields(filp, &r->file);
+		err = r->result;
+		if(err >= 0)
+			mfs_file_up_to_date(filp);
+	}
+	else if(err >= 0)
+	{
+		printk("mfs_client_fsync: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+int
+mfs_client_open(int pe, mfs_handle_t handle, struct inode *inode, struct file *filp)
+{
+	struct mfs_client_contact *con;
+	struct mfs_request_open s;
+	struct mfs_reply_open *r;
+	int ret;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.inode = *inode;
+	con = mfs_new_request(pe, MFS_REQUEST_OPEN, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if (IS_ERR(con))
+		return ((int) con);
+
+	ret = mfs_client_receive(con, (void **) &r, 0, 0);
+	switch (ret)
+	{
+		case MFS_REPLY_OPEN:
+			cp_file_fields(filp, &r->file);
+			ret = r->result;
+			if (ret >= 0)
+				mfs_file_up_to_date(filp);
+			break;
+		default:
+			printk("mfs_client_open: unexpected reply %d\n", ret);
+			ret = -EINVAL;
+			break;
+	}
+	mfs_release_contact(con);
+	return ret;
+}
+
+int
+mfs_client_close(int pe, mfs_handle_t handle, struct inode *inode, struct file *filp)
+{
+	struct mfs_client_contact *con;
+	struct mfs_request_open s;
+	struct mfs_reply_open *r;
+	int ret;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.file = *filp;
+	s.inode = *inode;
+	con = mfs_new_request(pe, MFS_REQUEST_CLOSE, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if (IS_ERR(con))
+		return ((int) con);
+
+	ret = mfs_client_receive(con, (void **) &r, 0, 0);
+	switch (ret)
+	{
+		case MFS_REPLY_CLOSE:
+			cp_file_fields(filp, &r->file);
+			ret = r->result;
+			if (ret >= 0)
+				mfs_file_up_to_date(filp);
+			break;
+		default:
+			printk("mfs_client_closedir: unexpected reply %d\n", ret);
+			ret = -EINVAL;
+			break;
+	}
+	mfs_release_contact(con);
+	return ret;
+}
+
+int
+mfs_client_revalidate(int pe, mfs_handle_t handle, struct subinode *iinfo)
+{
+	struct mfs_request_revalidate s;
+	struct mfs_reply_revalidate *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	con = mfs_new_request(pe, MFS_REQUEST_REVALIDATE, &s, sizeof(s),
+							NULL, 0, NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_REVALIDATE)
+	{
+		*iinfo = r->iinfo;
+		err = r->result;
+	}
+	else if(err >= 0)
+	{
+		printk("mfs_client_revalidate: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+int
+mfs_client_express_lookup(int pe, mfs_handle_t *handle, char *name,
+	unsigned int follow, struct subinode *iinfo, char **newname,
+	struct mfs_completion *complete)
+{
+	struct mfs_request_express s;
+	struct mfs_reply_express *r;
+	struct mfs_client_contact *con;
+	int err;
+	void *name_back, *more_data;
+
+	*newname = NULL;
+	pack_credits(&s.cred);
+	s.handle = *handle;
+	s.namelen = strlen(name) + 1;
+	s.follow = follow;
+	s.link_count = current->link_count;
+	s.total_link_count = current->total_link_count;
+	s.complete = *complete;
+	con = mfs_new_request(pe, MFS_REQUEST_EXPRESS, &s, sizeof(s),
+				(void *)name, s.namelen,
+				s.complete.more_data, s.complete.more_data_len);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, &name_back, &more_data);
+	if(err == MFS_REPLY_EXPRESS)
+	{
+		*handle = r->handle;
+		*iinfo = r->iinfo;
+		*complete = r->complete;
+		err = r->result;
+		if(!err)
+		{
+			if(!r->namelen)
+				*newname = NULL;
+			else if((*newname = kmalloc(r->namelen, GFP_KERNEL)))
+				memcpy(*newname, name_back, r->namelen);
+			else
+				err = -ENOMEM;
+		}
+		if(complete->more_data)
+		{
+			if((complete->more_data =
+				kmalloc(complete->more_data_len, GFP_KERNEL)))
+				memcpy(complete->more_data, more_data,
+						complete->more_data_len);
+			else
+			{
+				if(!err)
+					err = -ENOMEM;
+				if(*newname)
+				{
+					kfree(*newname);
+					*newname = NULL;
+				}
+			}
+		}
+	}
+	else if(err >= 0)
+	{
+		printk("mfs_client_express_lookup: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+char *
+mfs_client_check_path(int pe, mfs_handle_t handle)
+{
+	struct mfs_request_checkpath s;
+	struct mfs_reply_checkpath *r;
+	char *path;
+	char *copy = NULL;
+	struct mfs_client_contact *con;
+	int err;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	con = mfs_new_request(pe, MFS_REQUEST_CHECKPATH, &s, sizeof(s), NULL, 0,
+								NULL, 0);
+	if(IS_ERR(con))
+		return(NULL);
+	err = mfs_client_receive(con, (void **)&r, (void *)&path, NULL);
+	if(err == MFS_REPLY_CHECKPATH)
+	{
+		if(r->namelen && (copy = kmalloc(r->namelen, GFP_KERNEL)))
+			memcpy(copy, path, r->namelen);
+	}
+	else if(err >= 0)
+	{
+		printk("mfs_client_check_path: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(copy);
+}
+
+int
+mfs_client_setattr(int pe, mfs_handle_t handle, struct iattr *iattr)
+{
+	struct mfs_request_setattr s;
+	struct mfs_reply_setattr *r;
+	struct mfs_client_contact *con;
+	int err;
+
+	pack_credits(&s.cred);
+	s.handle = handle;
+	s.attr = *iattr;
+	con = mfs_new_request(pe, MFS_REQUEST_SETATTR, &s, sizeof(s),
+							NULL, 0, NULL, 0);
+	if(IS_ERR(con))
+		return((int)con);
+	err = mfs_client_receive(con, (void **)&r, NULL, NULL);
+	if(err == MFS_REPLY_SETATTR)
+		err = r->result;
+	else if(err >= 0)
+	{
+		printk("mfs_client_setattr: unexpected reply %d\n", err);
+		err = -EINVAL;
+	}
+	if(r)
+		kfree(r);
+	mfs_release_contact(con);
+	return(err);
+}
+
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/complete.c linux-openmosix/fs/mfs/complete.c
--- linux/fs/mfs/complete.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/complete.c	2002-11-16 07:22:58.000000000 +0100
@@ -0,0 +1,759 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ * Some sections copyright 2002 by Moshe Bar
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/mfs.h>
+#include <linux/utime.h>
+#include <linux/smp_lock.h>
+#include <linux/quotaops.h>
+
+extern struct dentry *lookup_create(struct nameidata *, int);
+extern int chown_common(struct dentry *, uid_t, gid_t);
+
+#define	MAX_READLINK	10240
+
+void
+mfs_prepare_other(struct mfs_completion *c, struct nameidata *ond)
+{
+	struct dentry *other = ond->dentry;
+	struct mfs_dinfo *info;
+
+	if(other->d_sb != mfs_super ||
+		!(info = (struct mfs_dinfo *)other->d_fsdata))
+		c->other_pe = 0;
+	else
+	{
+		c->other_pe = info->pe;
+		c->other = info->handle;
+		if(atomic_read(&other->d_count) > 1)
+			c->dispose_other = 0;
+		else
+		{
+			kfree(info);
+			other->d_fsdata = NULL;
+			c->dispose_other = 1;
+		}
+	}
+}
+
+void
+mfs_prepare_utime(struct mfs_completion *c, time_t *pa, time_t *pm)
+{
+	if(get_user(c->args.times.a, pa) || get_user(c->args.times.m, pm))
+	{
+		c->needed = 0;
+		c->error = -EFAULT;
+	}
+}
+
+void
+mfs_prepare_completion(struct mfs_completion *c, struct nameidata *nd)
+{
+	struct dentry *base = nd->dentry;
+	struct utimbuf *ut;
+	struct timeval *uts;
+	struct mfs_dinfo *info;
+
+	c->done = 0;
+	c->other_pe = 0;
+	c->dispose_other = 0;
+	c->more_data = NULL;
+	c->more_data_len = 0;
+	c->error = 0;
+	c->ro = mfs_is_ro;
+	c->dispose_base = 0;
+	if((info = (struct mfs_dinfo *)base->d_fsdata))
+	{
+		c->base_pe = info->pe;
+		c->base = info->handle;
+		if(atomic_read(&base->d_count) == 1)
+		{
+			kfree(info);
+			base->d_fsdata = NULL;
+			c->dispose_base = 1;
+		}
+	}
+	else
+	{
+		c->base_pe = 0;
+		c->base = MFS_ROOT_INO;
+	}
+	if(!(c->needed = ((nd->flags & LOOKUP_COMPLETE) != 0)))
+		return;
+	c->args = nd->complete_args;
+	switch(c->func = nd->express_function)
+	{
+		case EF_OPEN:
+		case EF_ACCESS:
+		case EF_UNLINK:
+		case EF_MKDIR:
+		case EF_RMDIR:
+		case EF_TRUNCATE:
+		case EF_CHOWN:
+		case EF_CHMOD:
+		case EF_MKNOD:
+		case EF_STATFS:
+			return;
+		case EF_RENAME:
+			if(nd->complete_args.oldnd->last_type == LAST_NORM)
+			{
+				c->more_data = (char *)
+					nd->complete_args.oldnd->last.name;
+				c->more_data_len = strlen(c->more_data)+1;
+			}
+			/* fall through */
+		case EF_LINK:
+			mfs_prepare_other(c, nd->complete_args.oldnd);
+			return;
+		case EF_SYMLINK:
+			c->more_data = nd->complete_parg;
+			c->more_data_len = strlen(c->more_data)+1;
+			return;
+		case EF_READLINK:
+			if(c->args.buffer.bufsiz > MAX_READLINK)
+				c->args.buffer.bufsiz = MAX_READLINK;
+			return;
+		case EF_UTIME:
+			ut = (struct utimbuf *)nd->complete_parg;
+			if(ut)
+				mfs_prepare_utime(c, &ut->actime, &ut->modtime);
+			else
+				c->other_pe = 1;
+			return;
+		case EF_UTIMES:
+			uts = (struct timeval *)nd->complete_parg;
+			if(uts)
+				mfs_prepare_utime(c, &uts[0].tv_sec,
+								&uts[1].tv_sec);
+			else
+				c->other_pe = 1;
+			return;
+		case EF_STAT:
+			nd->complete_parg = NULL;
+			return;
+		default:
+			c->needed = 0;
+			return;
+	}
+}
+
+int
+mfs_low_complete_link(struct mfs_completion *c, struct nameidata *nd)
+{
+	struct nameidata ond;
+	int err;
+	struct dentry *new_dentry;
+
+	if(c->other_pe != MFS_PE)
+		return(-EXDEV);
+	if((err = mfs_to_local(c->other, &ond)))
+		return(err);
+	err = -EXDEV;
+	if(ond.mnt != nd->mnt)
+		goto out;
+	new_dentry = lookup_create(nd, 0);
+	if(IS_ERR(new_dentry))
+		err = PTR_ERR(new_dentry);
+	else
+	{
+		err = vfs_link(ond.dentry, nd->dentry->d_inode, new_dentry);
+		dput(new_dentry);
+	}
+	up(&nd->dentry->d_inode->i_sem);
+	out:
+	mfs_lput(ond.dentry, ond.mnt);
+	return(err);
+}
+
+int
+mfs_low_complete_unlink(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct dentry *dentry;
+
+	if(nd->last_type != LAST_NORM)
+		return(-EISDIR);
+	down(&nd->dentry->d_inode->i_sem);
+	dentry = lookup_hash(&nd->last, nd->dentry);
+	if(IS_ERR(dentry))
+		err = PTR_ERR(dentry);
+	else
+	{
+		if(!dentry->d_inode)
+			err = -ENOENT;
+		else if(nd->last.name[nd->last.len])
+			err = S_ISDIR(dentry->d_inode->i_mode) ?
+							-EISDIR : -ENOTDIR;
+		else
+			err = vfs_unlink(nd->dentry->d_inode, dentry);
+		dput(dentry);
+	}
+	up(&nd->dentry->d_inode->i_sem);
+	return(err);
+}
+
+int
+mfs_low_complete_symlink(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct dentry *dentry;
+
+	dentry = lookup_create(nd, 0);
+	if(IS_ERR(dentry))
+		err = PTR_ERR(dentry);
+	else
+	{
+		err = vfs_symlink(nd->dentry->d_inode, dentry, c->more_data);
+		dput(dentry);
+	}
+	up(&nd->dentry->d_inode->i_sem);
+	return(err);
+}
+
+int
+mfs_low_complete_mkdir(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct dentry *dentry;
+
+	dentry = lookup_create(nd, 1);
+	if(IS_ERR(dentry))
+		err = PTR_ERR(dentry);
+	else
+	{
+		err = vfs_mkdir(nd->dentry->d_inode, dentry, c->args.ints.i1);
+		dput(dentry);
+	}
+	up(&nd->dentry->d_inode->i_sem);
+	return(err);
+}
+
+int
+mfs_low_complete_mknod(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct dentry *dentry;
+	int mode = c->args.ints.i1;
+
+	dentry = lookup_create(nd, 1);
+	if(IS_ERR(dentry))
+		err = PTR_ERR(dentry);
+	else
+	{
+		switch(mode & S_IFMT)
+		{
+			case 0:
+			case S_IFREG:
+				err = vfs_create(nd->dentry->d_inode, dentry,
+									mode);
+				break;
+			case S_IFCHR:
+			case S_IFBLK:
+			case S_IFIFO:
+			case S_IFSOCK:
+			case S_IFDIR:
+				err = -EPERM;
+				break;
+			default:
+				err = -EINVAL;
+				break;
+		}
+		dput(dentry);
+	}
+	up(&nd->dentry->d_inode->i_sem);
+	return(err);
+}
+
+int
+mfs_low_complete_rmdir(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct dentry *dentry;
+
+	switch(nd->last_type)
+	{
+		case LAST_NORM:
+			break;
+		case LAST_DOTDOT:
+			return(-ENOTEMPTY);
+		default:
+			return(-EBUSY);
+	}
+	down(&nd->dentry->d_inode->i_sem);
+	dentry = lookup_hash(&nd->last, nd->dentry);
+	if(IS_ERR(dentry))
+		err = PTR_ERR(dentry);
+	else
+	{
+		err = vfs_rmdir(nd->dentry->d_inode, dentry);
+		dput(dentry);
+	}
+	up(&nd->dentry->d_inode->i_sem);
+	return(err);
+}
+
+int
+mfs_low_complete_rename(struct mfs_completion *c, struct nameidata *newnd)
+{
+	struct nameidata ond;
+	int err;
+	struct dentry *old_dir, *new_dir;
+	struct dentry *old_dentry, *new_dentry;
+
+	if(c->other_pe != MFS_PE)
+		return(-EXDEV);
+	if((err = mfs_to_local(c->other, &ond)))
+		return(err);
+	if(c->more_data_len)
+	{
+		unsigned int hash = init_name_hash();
+		const unsigned char *n;
+
+		ond.last_type = LAST_NORM;
+		ond.last.name = c->more_data;
+		ond.last.len = strlen(c->more_data);
+		for(n = ond.last.name ; *n && *n != '/' ; n++)
+			hash = partial_name_hash(*n, hash);
+		ond.last.hash = end_name_hash(hash);
+	}
+	err = -EXDEV;
+	if(ond.mnt != newnd->mnt)
+		goto out;
+	err = -EBUSY;
+	if (ond.last_type != LAST_NORM || newnd->last_type != LAST_NORM)
+		goto out;
+	old_dir = ond.dentry;
+	new_dir = newnd->dentry;
+	double_lock(new_dir, old_dir);
+
+	old_dentry = lookup_hash(&ond.last, old_dir);
+	err = PTR_ERR(old_dentry);
+	if (IS_ERR(old_dentry))
+		goto out1;
+	/* source must exist */
+	err = -ENOENT;
+	if (!old_dentry->d_inode)
+		goto out2;
+	/* unless the source is a directory trailing slashes give -ENOTDIR */
+	if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
+		err = -ENOTDIR;
+		if (ond.last.name[ond.last.len])
+			goto out2;
+		if (newnd->last.name[newnd->last.len])
+			goto out2;
+	}
+	new_dentry = lookup_hash(&newnd->last, new_dir);
+	err = PTR_ERR(new_dentry);
+	if (IS_ERR(new_dentry))
+		goto out2;
+
+	lock_kernel();
+	err = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
+								new_dentry);
+	unlock_kernel();
+
+	dput(new_dentry);
+	out2:
+	dput(old_dentry);
+	out1:
+	double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
+	out:
+	mfs_lput(ond.dentry, ond.mnt);
+	return(err);
+}
+
+int
+mfs_low_complete_readlink(struct mfs_completion *c, struct nameidata *nd)
+{
+	char *buf;
+	mm_segment_t old_fs = get_fs();
+	int err;
+	struct inode *ip = nd->dentry->d_inode;
+	int sz = c->args.buffer.bufsiz;
+
+	if(!ip)
+		return(-ENOENT);
+	if(!ip->i_op || !ip->i_op->readlink)
+		return(-EINVAL);
+	if(ip->i_op && ip->i_op->revalidate &&
+		(err = ip->i_op->revalidate(nd->dentry)))
+		return(err);
+	if(!(buf = kmalloc(sz, GFP_KERNEL)))
+		return(-ENOMEM);
+	UPDATE_ATIME(ip);
+	set_fs(KERNEL_DS);
+	if(!ip->i_op || !ip->i_op->readlink)
+		err = -EINVAL;
+	else
+		err = ip->i_op->readlink(nd->dentry, buf, sz);
+	set_fs(old_fs);
+	if(err > 0)
+	{
+		c->more_data = buf;
+		c->more_data_len = err;
+	}
+	else
+		kfree(buf);
+	return(err);
+}
+
+int
+mfs_low_complete_truncate(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct inode *ip = nd->dentry->d_inode;
+
+	if(!S_ISREG(ip->i_mode))
+		return(-EACCES);
+	if((err = permission(ip, MAY_WRITE)))
+		return(err);
+	if(IS_RDONLY(ip))
+		return(-EROFS);
+	if(IS_IMMUTABLE(ip) || IS_APPEND(ip))
+		return(-EPERM);
+	if((err = get_write_access(ip)))
+		return(err);
+	if(!(err = locks_verify_truncate(ip, NULL, c->args.len)))
+	{
+		DQUOT_INIT(ip);
+		err = do_truncate(nd->dentry, c->args.len);
+	}
+	put_write_access(ip);
+	return(err);
+}
+
+int
+mfs_low_complete_utime(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct iattr newattrs;
+	struct inode *ip = nd->dentry->d_inode;
+
+	if(IS_RDONLY(ip))
+		return(-EROFS);
+	newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
+	if(c->other_pe)
+	{
+		if((err = permission(ip, MAY_WRITE)))
+			if(current->fsuid != ip->i_uid && (err = permission(ip, MAY_WRITE)))
+			return(err);
+	}
+	else
+	{
+		newattrs.ia_atime = c->args.times.a;
+		newattrs.ia_mtime = c->args.times.m;
+		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
+	}
+	return(notify_change(nd->dentry, &newattrs));
+}
+
+int
+mfs_low_complete_chmod(struct mfs_completion *c, struct nameidata *nd)
+{
+	struct iattr newattrs;
+	mode_t mode = c->args.mode;
+	struct inode *ip = nd->dentry->d_inode;
+
+	if(IS_RDONLY(ip))
+		return(-EROFS);
+	if(IS_IMMUTABLE(ip) || IS_APPEND(ip))
+		return(-EPERM);
+	if (mode == (mode_t) -1)
+		mode = ip->i_mode;
+	newattrs.ia_mode = (mode & S_IALLUGO) | (ip->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	return(notify_change(nd->dentry, &newattrs));
+}
+
+int
+mfs_low_complete_stat(struct mfs_completion *c, struct nameidata *nd)
+{
+	int err;
+	struct inode *ip = nd->dentry->d_inode;
+
+	if (ip->i_op && ip->i_op->revalidate &&
+		(err = ip->i_op->revalidate(nd->dentry)))
+		return(err);
+	if(!(c->more_data = kmalloc(sizeof(struct subinode), GFP_KERNEL)))
+		return(-ENOMEM);
+	c->more_data_len = sizeof(struct subinode);
+	ip = nd->dentry->d_inode;
+	mfs_ip_to_subip((struct subinode *)c->more_data, ip);
+	((struct subinode *)c->more_data)->si_ino = global_inum(ip);
+	return(0);
+}
+
+mfs_handle_t
+mfs_low_complete(struct mfs_completion *c, struct nameidata *nd)
+{
+	mfs_handle_t result;
+
+	if(!c->needed)
+		goto export;
+	c->error = 0;
+	c->done = 1;
+	if(c->ro)
+		current->mosix.dirty_bits |= MFSARG_RONLY;
+	switch(c->func)
+	{
+		case EF_OPEN:
+			c->error = open_namei(NULL, c->args.ints.i1,
+							c->args.ints.i2, nd);
+			break;
+		case EF_ACCESS:
+			c->error = permission(nd->dentry->d_inode,
+							c->args.ints.i1);
+			break;
+		case EF_LINK:
+			c->error = mfs_low_complete_link(c, nd);
+			break;
+		case EF_UNLINK:
+			c->error = mfs_low_complete_unlink(c, nd);
+			break;
+		case EF_SYMLINK:
+			c->error = mfs_low_complete_symlink(c, nd);
+			c->more_data = NULL;
+			c->more_data_len = 0;
+			break;
+		case EF_MKDIR:
+			c->error = mfs_low_complete_mkdir(c, nd);
+			break;
+		case EF_MKNOD:
+			c->error = mfs_low_complete_mknod(c, nd);
+			break;
+		case EF_RMDIR:
+			c->error = mfs_low_complete_rmdir(c, nd);
+			break;
+		case EF_RENAME:
+			c->error = mfs_low_complete_rename(c, nd);
+			c->more_data = NULL;
+			c->more_data_len = 0;
+			break;
+		case EF_READLINK:
+			c->error = mfs_low_complete_readlink(c, nd);
+			break;
+		case EF_TRUNCATE:
+			c->error = mfs_low_complete_truncate(c, nd);
+			break;
+		case EF_UTIME:
+		case EF_UTIMES:
+			c->error = mfs_low_complete_utime(c, nd);
+			break;
+		case EF_CHMOD:
+			c->error = mfs_low_complete_chmod(c, nd);
+			break;
+		case EF_CHOWN:
+			c->error = chown_common(nd->dentry, c->args.ids.uid,
+							c->args.ids.gid);
+			break;
+		case EF_STAT:
+			c->error = mfs_low_complete_stat(c, nd);
+			break;
+		case EF_STATFS:
+			c->error = mfs_low_complete_statfs(c, nd);
+			break;
+		default:
+			c->done = 0;
+			break;
+	}
+	current->mosix.dirty_bits &= ~MFSARG_RONLY;
+	if(c->dispose_other && c->other_pe == MFS_PE)
+	{
+		c->dispose_other = 0;
+		mfs_low_dispose_handle(c->other);
+	}
+	if(c->dispose_base && c->base_pe == MFS_PE)
+	{
+		c->dispose_base = 0;
+		mfs_low_dispose_handle(c->base);
+	}	
+	if(c->done && (c->func != EF_OPEN || c->error))
+		return(0);
+	export:
+	if(!(result = local_to_mfs(nd)))
+	{
+		if(c->more_data)
+		{
+			kfree(c->more_data);
+			c->more_data = NULL;
+			c->more_data_len = 0;
+		}
+		c->error = -ENOMEM;
+		path_release(nd);
+		if(c->needed)
+			c->done = 1;
+	}
+	return(result);
+}
+
+int mfs_low_complete_statfs(struct mfs_completion *c, struct nameidata *nd)
+{
+
+	int err;
+	struct inode *ip = nd->dentry->d_inode;
+
+	if(!ip)
+		return (-ENOENT);
+	if(!(c->more_data = kmalloc(sizeof(struct statfs), GFP_KERNEL)))
+		 return(-ENOMEM);
+	err = vfs_statfs(ip->i_sb, (struct statfs *)c->more_data);
+	if (err)
+	{
+		kfree(c->more_data);
+		c->more_data = NULL;
+	}
+	else
+		c->more_data_len = sizeof(struct statfs);
+	return(err);
+}
+
+
+void
+mfs_low_complete_error(struct mfs_completion *c, int err)
+{
+	if(c->dispose_base && c->base_pe == MFS_PE)
+	{
+		c->dispose_base = 0;
+		mfs_low_dispose_handle(c->base);
+	}
+	if(c->dispose_other && c->other_pe == MFS_PE)
+	{
+		c->dispose_other = 0;
+		mfs_low_dispose_handle(c->other);
+	}
+	c->error = err;
+	c->more_data = NULL;	/* in case of EF_SYMLINK */
+	c->more_data_len = 0;
+	if(c->needed)
+		c->done = 1;
+}
+
+int
+mfs_check_completion(struct mfs_completion *c, struct nameidata *nd)
+{
+	struct inode *inode;
+	struct subinode *subip;
+
+	if(c->dispose_other)
+		mfs_dispose_handle(c->other_pe, c->other);
+	if(c->dispose_base)
+		mfs_dispose_handle(c->base_pe, c->base);
+	if(!c->done)
+		return(0);
+	nd->complete_flags |= COMPLETE_DONE;
+	if(c->error && (c->func != EF_READLINK || c->error < 0))
+		return(1);
+	switch(c->func)
+	{
+		case EF_OPEN:
+			return(0);
+		case EF_STAT:
+			nd->complete_parg = NULL;
+			if(!(subip = (struct subinode *)c->more_data))
+			{
+				if(!c->error)
+					c->error = -ENOMEM;
+				return(1);
+			}
+			if((inode = (struct inode *)
+				    kmalloc(sizeof(struct inode), GFP_KERNEL)))
+			{
+				path_release(nd);
+				mfs_subip_to_ip(inode, subip);
+				inode->i_ino =
+				    ((struct subinode *)c->more_data)->si_ino;
+				inode->i_dev = mfs_super->s_dev;
+				inode->u.mfs_i.pe = c->other_pe;
+				nd->complete_parg = inode;
+				/* the caller must later kfree this! */
+			}
+			else if(!c->error)
+				c->error = -ENOMEM;
+			kfree(subip);
+			return(1);
+		case EF_READLINK:
+			if(c->more_data)
+			{
+				if(c->error >= 0 &&
+					copy_to_user((void *)c->args.buffer.buf,
+					c->more_data, c->more_data_len))
+					c->error = -EFAULT;
+				kfree(c->more_data);
+				path_release(nd);
+			}
+			else if(c->error >= 0)
+				c->error = -ENOMEM;
+			return(1);
+		case EF_STATFS:
+			if(c->more_data) {
+				if(copy_to_user((void *)c->args.statfs,
+						c->more_data, sizeof(struct statfs)))
+					c->error = -EFAULT;
+				kfree(c->more_data);
+				path_release(nd);
+				
+			}
+			
+		default:
+			path_release(nd);
+		case 0:
+			return(1);
+	}
+}
+
+int
+mfs_link_complete(struct mfs_completion *c, int pe, struct nameidata *nd)
+{
+	int result;
+	char node[6];
+	int len, copy;
+	struct inode *ip;
+
+	if(c->dispose_other)
+		mfs_dispose_handle(c->other_pe, c->other);
+	if(c->dispose_base)
+		mfs_dispose_handle(c->base_pe, c->base);
+	if(!c->needed)
+		return(-EPERM);
+	nd->complete_flags |= COMPLETE_DONE;
+	switch(c->func)
+	{
+		case EF_READLINK:
+			sprintf(node, "%d", pe);
+			len = strlen(node);
+			result = copy = min(len, c->args.buffer.bufsiz);
+			if(copy_to_user((void *)c->args.buffer.buf, node, copy))
+				return(-EFAULT);
+			break;
+		case EF_STAT:
+			if(!(ip = (struct inode *)
+				    kmalloc(sizeof(*ip), GFP_KERNEL)))
+				return(-ENOMEM);
+			nd->complete_parg = ip;
+			memset(ip, 0, sizeof(*ip));
+			ip->i_dev = mfs_super->s_dev;
+			ip->i_ino = pe;
+			ip->u.mfs_i.pe = pe;
+			ip->i_mode = S_IFLNK | 0555;
+			ip->i_nlink = 1;
+			for(len = pe ; len ; len /= 10)
+				ip->i_size++;
+			ip->i_version = pe;
+			result = 0;
+			break;
+		default:
+			return(-EPERM);
+	}
+	path_release(nd);
+	return(result);
+}
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/convert.c linux-openmosix/fs/mfs/convert.c
--- linux/fs/mfs/convert.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/convert.c	2002-10-15 08:07:29.000000000 +0200
@@ -0,0 +1,629 @@
+/* all changes since Feb 12, 2002 copyright by Moshe Bar (moshe@moshebar.com)
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ * Some sections copyright 2002 by Moshe Bar
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/hpc.h>
+#include <linux/slab.h>
+#include <linux/mfs.h>
+#include <asm/uaccess.h>
+
+static struct semaphore mfsc_sem = __MUTEX_INITIALIZER(mfsc_sem);
+
+mfs_handle_t mfs_unique;
+struct dentry *mfs_root;
+struct vfsmount *mfs_mnt;
+ino_t mfs_root_ino;
+dev_t mfs_root_dev;
+int mfs_root_usage;
+
+#define	MFS_HASHES	64
+struct mfs_map
+{
+	struct list_head llist;
+	struct list_head glist;
+	mfs_handle_t handle;
+	struct dentry *l;
+	struct vfsmount *mnt;
+	int dcount;	/* inc: local_to_mfs ; dec: mfs_put_handle */
+	int usecount;	/* inc: mfs_to_local ; dec: mfs_lput */
+	unsigned long latest;
+};
+
+static struct list_head lhash[MFS_HASHES], ghash[MFS_HASHES];
+
+static inline int
+hash_dentry(struct dentry *d)
+{
+	return(((((unsigned int)d) >> 8) + (((unsigned int)d) >> 14) +
+		(((unsigned int)d) >> 20)) % MFS_HASHES);
+}
+
+static inline int
+hash_handle(mfs_handle_t l)
+{
+	unsigned int h = l;
+
+	return((h+(h>>6)+(h>>12)+(h>>18)+(h>>24)) % MFS_HASHES);
+}
+
+int
+mfs_conversion_init(void)
+{
+	unsigned int i;
+
+	if(!mfs_unique)
+	{
+		mfs_root = dget(current->fs->root);
+		mfs_mnt = mntget(current->fs->rootmnt);
+		mfs_root_ino = mfs_root->d_inode->i_ino;
+		mfs_root_dev = mfs_root->d_inode->i_dev;
+		mfs_unique = ((mfs_handle_t) CURRENT_TIME) << 31;
+		if(mfs_unique <= MFS_ROOT_INO)	/* 0 time? */
+			mfs_unique = MFS_ROOT_INO + 1;
+		for(i = 0 ; i < MFS_HASHES ; i++)
+		{
+			INIT_LIST_HEAD(&lhash[i]);
+			INIT_LIST_HEAD(&ghash[i]);
+		}
+	}
+	return(0);
+}
+
+void
+mfs_put(struct mfs_map *m, int putuse)
+{
+	struct list_head *x, *nex, *prv;
+
+	if(putuse)
+		m->usecount--;
+	else
+		m->dcount--;
+	if(m->usecount > 0 || m->dcount > 0)
+		return;
+	x = &m->llist;
+	nex = x->next;
+	prv = x->prev;
+	nex->prev = prv;
+	prv->next = nex;
+	x = &m->glist;
+	nex = x->next;
+	prv = x->prev;
+	nex->prev = prv;
+	prv->next = nex;
+	dput(m->l);
+	mntput(m->mnt);
+	kfree(m);
+}
+
+void
+mfs_change_root(struct dentry *from, struct vfsmount *frommnt,
+				struct dentry *to, struct vfsmount *tomnt)
+{
+	int h;
+	struct list_head *head, *x;
+	struct mfs_map *m, *new = NULL;
+	int new_root_usage = 0;
+
+	down(&mfsc_sem);
+	if(from != mfs_root || frommnt != mfs_mnt ||
+					(to == from && tomnt == frommnt))
+		goto out;
+	if(mfs_root_usage && !(new = (struct mfs_map *)
+			kmalloc(sizeof (struct mfs_map), GFP_KERNEL)))
+	{
+		printk("oMFS root failed to change (ENOMEM)!\n");
+		goto out;
+	}
+
+	/* is the new root listed? (if so, and no external refs, remove it) */
+	head = &lhash[hash_dentry(to)];
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, llist));
+		if(m->l == to && m->mnt == tomnt)
+		{
+			new_root_usage = m->dcount;
+			m->dcount = 1;
+			mfs_put(m, 0);
+			break;
+		}
+	}
+
+	if(mfs_root_usage)
+	{
+		/* someone is actively using the old root,
+		 * so we must set it up as a normal hashed entry */
+		new->l = dget(from);
+		new->mnt = mntget(frommnt);
+		new->dcount = 0;
+		new->usecount = mfs_root_usage;
+		new->handle = mfs_unique++;
+		new->latest = jiffies;
+		h = hash_dentry(from);
+		new->llist.next = lhash[h].next;
+		lhash[h].next->prev = &new->llist;
+		new->llist.prev = &lhash[h];
+		lhash[h].next = &new->llist;
+		h = hash_handle(new->handle);
+		new->glist.next = ghash[h].next;
+		ghash[h].next->prev = &new->glist;
+		new->glist.prev = &ghash[h];
+		ghash[h].next = &new->glist;
+		new = NULL;
+	}
+	dget(to);
+	mntget(tomnt);
+	mfs_root = to;
+	mfs_mnt = tomnt;
+	mfs_root_ino = to->d_inode->i_ino;
+	mfs_root_dev = to->d_inode->i_dev;
+	mfs_root_usage = new_root_usage;
+	dput(from);
+	mntput(frommnt);
+	if(new)
+		kfree(new);
+	out:
+	up(&mfsc_sem);
+}
+
+mfs_handle_t
+local_to_mfs(struct nameidata *local)
+{
+	struct dentry *dp = local->dentry;
+	struct vfsmount *mnt = local->mnt;
+	int h = hash_dentry(dp);
+	struct list_head *head = &lhash[h], *x;
+	struct mfs_map *m;
+
+	down(&mfsc_sem);
+	if(dp == mfs_root && mnt == mfs_mnt)
+	{
+		up(&mfsc_sem);
+		return(MFS_PE);
+	}
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, llist));
+		if(m->l == dp && mnt == mnt)
+		{
+			m->dcount++;
+			up(&mfsc_sem);
+			return(m->handle);
+		}
+	}
+	if(!(m = (struct mfs_map *)kmalloc(sizeof (struct mfs_map),GFP_KERNEL)))
+	{
+		up(&mfsc_sem);
+		return(0);
+	}
+	m->l = dget(dp);
+	m->mnt = mntget(mnt);
+	m->dcount = 1;
+	m->usecount = 0;
+	m->handle = mfs_unique++;
+	m->llist.next = lhash[h].next;
+	lhash[h].next->prev = &m->llist;
+	m->llist.prev = &lhash[h];
+	lhash[h].next = &m->llist;
+	h = hash_handle(m->handle);
+	m->glist.next = ghash[h].next;
+	ghash[h].next->prev = &m->glist;
+	m->glist.prev = &ghash[h];
+	ghash[h].next = &m->glist;
+	m->latest = jiffies;
+	up(&mfsc_sem);
+	return(m->handle);
+}
+
+int
+mfs_to_local(mfs_handle_t handle, struct nameidata *local)
+{
+	struct list_head *head, *x, *nex, *prv;
+	struct mfs_map *m;
+
+	down(&mfsc_sem);
+	if(handle == MFS_PE)
+	{
+		its_the_root:
+		mfs_root_usage++;
+		local->dentry = mfs_root;
+		local->mnt = mfs_mnt;
+		up(&mfsc_sem);
+		return(0);
+	}
+	if(handle < MFS_ROOT_INO)
+	{
+		up(&mfsc_sem);
+		return(-EINVAL);
+	}
+	head = &ghash[hash_handle(handle)];
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, glist));
+		if(m->handle == handle)
+		{
+			local->dentry = m->l;
+			local->mnt = m->mnt;
+			if(m->l == mfs_root && m->mnt == mfs_mnt)
+				/* very rare, but possible after root change */
+				goto its_the_root;
+			m->usecount++;
+			/* move to head of queues: */
+			if(x != head->next)
+			{
+				nex = x->next;
+				prv = x->prev;
+				nex->prev = prv;
+				prv->next = nex;
+				x->next = head->next;
+				x->prev = head;
+				x->next->prev = x;
+				head->next = x;
+			}
+			head = &lhash[hash_dentry(local->dentry)];
+			x = &m->llist;
+			if(x != head->next)
+			{
+				nex = x->next;
+				prv = x->prev;
+				nex->prev = prv;
+				prv->next = nex;
+				x->next = head->next;
+				x->prev = head;
+				x->next->prev = x;
+				head->next = x;
+			}
+			m->latest = jiffies;
+			up(&mfsc_sem);
+			return(0);
+		}
+	}
+	up(&mfsc_sem);
+	printk("MFS: Handle %016LX not found (obsolete)\n", handle);
+	return(-ESTALE);
+}
+
+void
+mfs_lput(struct dentry *dp, struct vfsmount *mnt)
+{
+	struct list_head *head, *x;
+	struct mfs_map *m;
+
+	down(&mfsc_sem);
+	if(dp == mfs_root && mnt == mfs_mnt)
+	{
+		mfs_root_usage--;
+		up(&mfsc_sem);
+		return;
+	}
+	head = &lhash[hash_dentry(dp)];
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, llist));
+		if(m->l == dp && m->mnt == mnt)
+		{
+			mfs_put(m, 1);
+			up(&mfsc_sem);
+			return;
+		}
+	}
+	up(&mfsc_sem);
+	printk("mfs_lput: no handle!\n");
+}
+
+int
+mfs_get_handle(mfs_handle_t handle)
+{
+	int h = hash_handle(handle);
+	struct list_head *head = &ghash[h], *x;
+	struct mfs_map *m;
+
+	if(handle < MFS_ROOT_INO)
+		return(0);
+	down(&mfsc_sem);
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, glist));
+		if(m->handle == handle)
+		{
+			m->dcount++;
+			m->latest = jiffies;
+			up(&mfsc_sem);
+			return(0);
+		}
+	}
+	up(&mfsc_sem);
+	printk("MFS: Handle %016LX not found (obsolete) when duplicated\n",
+									handle);
+	return(-ESTALE);
+}
+
+int
+mfs_access_handle(mfs_handle_t handle)
+{
+	int h = hash_handle(handle);
+	struct list_head *head = &ghash[h], *x;
+	struct mfs_map *m;
+
+	if(handle < MFS_ROOT_INO)
+		return(0);
+	down(&mfsc_sem);
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, glist));
+		if(m->handle == handle)
+		{
+			m->latest = jiffies;
+			up(&mfsc_sem);
+			return(0);
+		}
+	}
+	up(&mfsc_sem);
+	printk("MFS: Handle %016LX not found (obsolete) when claimed\n",
+									handle);
+	return(-ESTALE);
+}
+
+void
+mfs_put_handle(mfs_handle_t handle)
+{
+	int h = hash_handle(handle);
+	struct list_head *head = &ghash[h], *x;
+	struct mfs_map *m;
+
+	if(handle < MFS_ROOT_INO)
+		return;
+	down(&mfsc_sem);
+	for(x = head->next ; x != head ; x = x->next)
+	{
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, glist));
+		if(m->handle == handle)
+		{
+			mfs_put(m, 0);
+			up(&mfsc_sem);
+			return;
+		}
+	}
+	up(&mfsc_sem);
+	printk("MFS: Handle %016LX not found (obsolete) when released\n",
+									handle);
+}
+
+int
+mfs_try_to_cleanup(int force)
+{
+	unsigned int h;
+	struct mfs_map *m;
+	struct list_head *next;
+
+	if(!mfs_unique)
+		return(0);
+	down(&mfsc_sem);
+	if(force != 2)
+	for(h = 0 ; h < MFS_HASHES ; h++)
+	while(lhash[h].next != &lhash[h])
+	{
+		m = (struct mfs_map *)((char *)lhash[h].next -
+					offsetof(struct mfs_map, llist));
+		if(!force || m->usecount)
+		{
+			busy:
+			up(&mfsc_sem);
+			return(-EBUSY);
+		}
+	}
+	for(h = 0 ; h < MFS_HASHES ; h++)
+	for(next = lhash[h].next ; next != &lhash[h] ; )
+	{
+		m = (struct mfs_map *)((char *)next -
+					offsetof(struct mfs_map, llist));
+		next = next->next;
+		if(m->usecount)
+		{
+			if(force == 2)
+				m->dcount = 0;
+			else
+				goto busy;
+		}
+		else
+		{
+			m->dcount = 1;
+			mfs_put(m, 0);
+		}
+	}
+	up(&mfsc_sem);
+	return(0);
+}
+
+void
+mfs_throw_garbage(void)
+{
+	unsigned int h;
+	struct mfs_map *m;
+	struct list_head *next;
+	unsigned int n = 0;
+
+	down(&mfsc_sem);
+	for(h = 0 ; h < MFS_HASHES ; h++)
+	for(next = lhash[h].next ; next != &lhash[h] ; )
+	{
+		m = (struct mfs_map *)((char *)lhash[h].next -
+					offsetof(struct mfs_map, llist));
+		next = next->next;
+		if(!m->usecount &&
+			time_after(jiffies, m->latest + MFS_GARBAGE_TIME))
+		{
+			m->dcount = 1;
+			mfs_put(m, 0);
+			n++;
+		}
+	}
+	up(&mfsc_sem);
+	if(n)
+		printk("MFS: Disposed of %d unclaimed entr%s\n", n,
+							n > 1 ? "ies" : "y");
+}
+
+/* why is this not in dcache.c? */
+int
+is_descendant(struct dentry *dp, struct vfsmount *mnt, struct dentry *pdp,
+							struct vfsmount *pmnt)
+{
+	spin_lock(&dcache_lock);
+	while(1)
+	{
+		if(dp == pdp && mnt == pmnt)
+		{
+			spin_unlock(&dcache_lock);
+			return(1);
+		}
+		if(dp == mnt->mnt_root)
+		{
+			struct vfsmount *xmnt = mnt->mnt_parent;
+
+			if(xmnt == mnt)
+				break;
+			dp = mnt->mnt_mountpoint;
+			mnt = xmnt;
+		}
+		else
+			dp = dp->d_parent;
+	}
+	spin_unlock(&dcache_lock);
+	return(0);
+}
+
+int
+mfs_kill(char *filename)
+{
+	unsigned int h;
+	struct mfs_map *m;
+	struct list_head *next;
+	unsigned int n = 0;
+	int error;
+	mm_segment_t old_fs;
+	struct nameidata nd;
+
+	old_fs = set_fs(KERNEL_DS);
+	error = 0;
+	if(path_init(filename, LOOKUP_POSITIVE, &nd))
+		error = path_walk(filename, &nd);
+	set_fs(old_fs);
+	if(error)
+		return(error);
+	down(&mfsc_sem);
+	for(h = 0 ; h < MFS_HASHES ; h++)
+	for(next = lhash[h].next ; next != &lhash[h] ; )
+	{
+		m = (struct mfs_map *)((char *)lhash[h].next -
+					offsetof(struct mfs_map, llist));
+		next = next->next;
+		if(is_descendant(m->l, m->mnt, nd.dentry, nd.mnt))
+		{
+			m->dcount = 1;
+			mfs_put(m, 0);
+			n++;
+		}
+	}
+	up(&mfsc_sem);
+	if(n)
+		printk("MFS_KILL: Killed %d entr%s\n", n, n > 1 ? "ies" : "y");
+	path_release(&nd);
+	return(0);
+}
+
+/* JUST FOR DEBUGGING: */
+void
+mfs_print_latest(unsigned long when)
+{
+	int diff = (when - jiffies) / HZ;
+
+	printk(", age=");
+	if(diff < 0 || diff > 24*3600)
+		printk("%ld", when);
+	else if(diff == 0)
+		printk("in %ld ticks", when - jiffies);
+	else if(diff < 6000)
+		printk("%d seconds", diff);
+	else if(diff < 3600)
+		printk("%d:%02d minutes", diff/60, diff % 60);
+	else
+		printk("%d:%02d:%02d hours", diff/3600, (diff % 3600) / 60,
+								diff % 60);
+}
+
+int
+dump_mfsc(void)
+{
+	register unsigned int h;
+	struct list_head *head, *x;
+	struct mfs_map *m;
+	int cnt = 0;
+
+	for(h = 0 ; h < MFS_HASHES ; h++)
+	for(head = &lhash[h] , x = head->next ; x != head ; x = x->next)
+	{
+		cnt++;
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, llist));
+		printk("%d: handle=%016LX, l=%x, ip=%x, count=%d, use=%d",
+			h, m->handle,
+			(int)m->l, (int)m->l->d_inode, m->dcount, m->usecount);
+		if(m->l->d_inode)
+			printk("\n        dev=%d/%d, ino=%ld, mode=0%o",
+				MAJOR(m->l->d_inode->i_dev),
+				MINOR(m->l->d_inode->i_dev),
+				m->l->d_inode->i_ino, m->l->d_inode->i_mode);
+		mfs_print_latest(m->latest);
+		printk("\n");
+	}
+	return(cnt);
+}
+
+int
+dump_mfsc2(void)
+{
+	register unsigned int h;
+	struct list_head *head, *x;
+	struct mfs_map *m;
+	int cnt = 0;
+
+	for(h = 0 ; h < MFS_HASHES ; h++)
+	for(head = &ghash[h] , x = head->next ; x != head ; x = x->next)
+	{
+		cnt++;
+		m = (struct mfs_map *)((char *)x -
+					offsetof(struct mfs_map, glist));
+		printk("%d: handle=%016LX, l=%x, ip=%x, count=%d, use=%d",
+			h, m->handle,
+			(int)m->l, (int)m->l->d_inode, m->dcount, m->usecount);
+		if(m->l->d_inode)
+			printk("\n        dev=%d/%d, ino=%ld, mode=0%o",
+				MAJOR(m->l->d_inode->i_dev),
+				MINOR(m->l->d_inode->i_dev),
+				m->l->d_inode->i_ino, m->l->d_inode->i_mode);
+		mfs_print_latest(m->latest);
+		printk("\n");
+	}
+	return(cnt);
+}
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/count.c linux-openmosix/fs/mfs/count.c
--- linux/fs/mfs/count.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/count.c	2002-10-15 08:07:29.000000000 +0200
@@ -0,0 +1,284 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar (moshe@moshebar.com)
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+
+#include <linux/sched.h>
+#if defined(CONFIG_MOSIX_FS) && defined(CONFIG_MOSIX_DFSA)
+#include <linux/hpcctl.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/mfs.h>
+#include <linux/mfs_socket.h>
+#include <hpc/defs.h>
+#include <linux/hpc.h>
+
+#define	weight(_c,_i,_o)	((_c)*2048+(_i)+(_o))
+#define	threshold		0xffe00000
+/* in openMosix we never enable DEBUG_MFSCOUNT but we leave it here for documentation purposes */
+
+#define DEBUG_MFSCOUNT
+#ifdef DEBUG_MFSCOUNT
+int debug_mfscount;
+
+void do_dump_mfscount(struct task_struct *p)
+{
+	unsigned int i;
+	struct mfs_stats *s = p->mosix.mfs_stats;
+
+	if(!s || !s->nnodes)
+	{
+		printk("%s MFS Statistics for %d(%s)\n", s ? "Empty" : "No",
+							p->pid, p->comm);
+		return;
+	}
+	for(i = 0 ; i < s->nnodes ; i++)
+	printk("%d: node #%d, conns=%d, inbytes=%d, outbytes=%d\n", i,
+		s->nodes[i], (int)s->conns[i], (int)s->inbytes[i],
+		(int)s->outbytes[i]);
+}
+#endif /* DEBUG_MFSCOUNT */
+
+void
+mfs_count(int w, int inbytes, int outbytes)
+{
+	struct task_struct *p = current;
+	struct mfs_stats *s = p->mosix.mfs_stats;
+	register int i;
+	int64_t prev, worst = 0, best = 0;
+	int victim = -1;
+	long new_weight;
+
+	if(!mfs_is_dfsa || !(p->mosix.dflags & (DREMOTE|DSTATSDOWN)))
+		return;
+#ifdef DEBUG_MFSCOUNT
+	if(debug_mfscount > 1)
+		printk("mfs_count(%d,%d,%d): ", w, inbytes, outbytes);
+#endif /* DEBUG_MFSCOUNT */
+	if(w == 0 || w > MOSIX_MAX)
+		return;
+	if(!s)
+	{
+		if(!(s = kmalloc(sizeof(struct mfs_stats), GFP_KERNEL)))
+			return;
+		p->mosix.mfs_stats = s;
+		s->nnodes = 0;
+	}
+	new_weight = weight(1, inbytes, outbytes);
+	for(i = (s->hint < s->nnodes && s->nodes[s->hint] == w) ? s->hint :
+						s->nnodes - 1 ; i >= 0 ; i--)
+	{
+		prev = weight(s->conns[i], s->inbytes[i], s->outbytes[i]);
+		if(s->nodes[i] == w)
+		{
+			s->conns[i]++;
+			s->inbytes[i] += inbytes;
+			s->outbytes[i] += outbytes;
+			s->hint = i;
+			if(w != PE &&
+				(((((long)prev)+new_weight)^prev) & threshold))
+				mosix_add_to_whereto(p, MFSBALANCE);
+#ifdef DEBUG_MFSCOUNT
+			if(debug_mfscount)
+			{
+				printk("Successfully added <%d,%d> to %d\n",
+					inbytes, outbytes, w);
+				if(debug_mfscount > 2)
+					do_dump_mfscount(p);
+			}
+#endif /* DEBUG_MFSCOUNT */
+			return;
+		}
+		if(victim == -1)
+		{
+			best = worst = prev;
+			victim = i;
+		}
+		else
+		{
+			if(prev > best)
+				best = prev;
+			if(prev < worst)
+			{
+				worst = prev;
+				victim = i;
+			}
+		}
+	}
+	if((i = s->nnodes) < MAX_MFS_STATNODES)
+	{
+		s->nnodes++;
+		s->nodes[i] = w;
+		s->conns[i] = 1;
+		s->inbytes[i] = inbytes;
+		s->outbytes[i] = outbytes;
+		s->hint = i;
+#ifdef DEBUG_MFSCOUNT
+		if(debug_mfscount)
+		{
+			printk("New MFS stats (%d,%d) for %d\n",
+				inbytes, outbytes, w);
+			if(debug_mfscount > 2)
+				do_dump_mfscount(p);
+		}
+#endif /* DEBUG_MFSCOUNT */
+		return;
+	}
+	i = victim;
+	if(--s->conns[i] <= 0 || (s->inbytes[i] -= inbytes) <= 0 ||
+		(s->outbytes[i] -= outbytes) <= 0)
+	{
+		if(victim == --s->nnodes)
+		{
+#ifdef DEBUG_MFSCOUNT
+			if(debug_mfscount)
+			{
+				printk("Anulled victim=%d\n", s->nodes[i]);
+				if(debug_mfscount > 2)
+					do_dump_mfscount(p);
+			}
+#endif /* DEBUG_MFSCOUNT */
+			return;
+		}
+		victim = s->nnodes;
+		s->nodes[i] = s->nodes[victim];
+		s->conns[i] = s->conns[victim];
+		s->inbytes[i] = s->inbytes[victim];
+		s->outbytes[i] = s->outbytes[victim];
+		if(s->hint == victim)
+			s->hint = i;
+#ifdef DEBUG_MFSCOUNT
+		if(debug_mfscount)
+		{
+			printk("Anulled/replaced a victim\n");
+			if(debug_mfscount > 2)
+				do_dump_mfscount(p);
+		}
+#endif /* DEBUG_MFSCOUNT */
+	}
+#ifdef DEBUG_MFSCOUNT
+	else if(debug_mfscount)
+	{
+		printk("Reduced victim=%d by <%d,%d>\n", s->nodes[i],
+							inbytes, outbytes);
+		if(debug_mfscount > 2)
+			do_dump_mfscount(p);
+	}
+#endif /* DEBUG_MFSCOUNT */
+	return;
+}
+
+int
+mfs_add_stats(struct mfs_stats *add, struct mfs_stats *to, struct mosix_task *m)
+{
+	register int i;
+	register unsigned int j;
+	int64_t prev, worst = 0;
+	int victim = -1;
+#if MAX_MFS_STATNODES > BITS_PER_LONG
+#error unsigned long is not enough
+#else
+	unsigned long bit, done = 0;
+#endif /* MAX_MFS_STATNODES > BITS_PER_LONG */
+	int node;
+	int ret = 0;
+
+	if(!add || !add->nnodes)
+		return(0);
+	if(!to)
+	{
+		if(!to && (!m || !(to = m->mfs_stats =
+				kmalloc(sizeof(struct mfs_stats), GFP_KERNEL))))
+			return(0);
+		*to = *add;
+		for(i = to->nnodes-1 ; i >= 0 ; i--)
+		if(weight(to->conns[i], to->inbytes[i], to->outbytes[i]) &
+								threshold)
+			return(1);
+		return(0);
+	}
+	for(i = 0 ; i < to->nnodes ; i++)
+	{
+		node = to->nodes[i];
+		for(j = 0 ; j < add->nnodes ; j++)
+		if(add->nodes[j] == node)
+		{
+			prev = weight(to->conns[i], to->inbytes[i],
+							to->outbytes[i]);
+			to->conns[i] += add->conns[i];
+			to->inbytes[i] += add->inbytes[i];
+			to->outbytes[i] += add->outbytes[i];
+			if(!ret && node != PE &&
+				(weight(to->conns[i], to->inbytes[i],
+					to->outbytes[i]) ^ prev) & threshold)
+				ret = 1;
+			done |= (1 << (j-1));
+			break;
+		}
+	}
+	for(bit = 1 , j = 0 ; j < add->nnodes ; j++ , bit <<= 1)
+	if(!(done & bit))
+	{
+		if(to->nnodes < MAX_MFS_STATNODES)
+		{
+			i = to->nnodes++;
+			to->nodes[i] = add->nodes[j];
+			to->conns[i] = add->conns[j];
+			to->inbytes[i] = add->inbytes[j];
+			to->outbytes[i] = add->outbytes[j];
+			if(!ret && (weight(to->conns[i], to->inbytes[i],
+				to->outbytes[i]) & threshold))
+				ret = 1;
+			continue;
+		}
+		for(i = 0 ; i < MAX_MFS_STATNODES ; i++)
+		{
+			prev = weight(add->conns[i], add->inbytes[i],
+							add->outbytes[i]);
+			if(i == 0 || prev < worst)
+			{
+				victim = i;
+				worst = prev;
+			}
+		}
+		if(!ret && (weight(add->conns[i], add->inbytes[i],
+						add->outbytes[i]) & threshold))
+			ret = 1;
+		to->nodes[victim] = add->nodes[i];
+		to->conns[victim] = add->conns[i];
+		to->inbytes[victim] = add->inbytes[i];
+		to->outbytes[victim] = add->outbytes[i];
+	}
+	return(ret);
+}
+
+#ifdef DEBUG_MFSCOUNT
+void
+dump_mfscount(int pid)
+{
+	struct task_struct *p;
+
+	if(!pid)
+		p = current;
+	else
+		p = find_any_task_by_pid(pid);
+	if(p)
+		do_dump_mfscount(p);
+	else
+		printk("No Such Task (%d)\n", pid);
+}
+#endif /* DEBUG_MFSCOUNT */
+
+#endif /* CONFIG_MOSIX_FS && CONFIG_MOSIX_DFSA */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/file.c linux-openmosix/fs/mfs/file.c
--- linux/fs/mfs/file.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/file.c	2003-11-14 10:01:25.000000000 +0100
@@ -0,0 +1,1941 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar (moshe@moshebar.com)
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/hpc.h>
+#include <linux/hpcctl.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/mfs.h>
+#include <linux/mfs_socket.h>
+#include <linux/locks.h>
+#include <linux/module.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <linux/dcache.h>
+#include <linux/quotaops.h>
+#include <linux/ext2_fs.h>
+#include <linux/file.h>
+
+int MFS_PE;
+int mfs_is_mounted;
+char mfs_is_ro;
+#ifdef CONFIG_MOSIX_DFSA
+char mfs_is_dfsa;
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+#define	mfs_loopback_test	0
+int mfs_debug;
+struct super_block *mfs_super;
+extern int may_create(struct inode *, struct dentry *);
+
+#define	AN_IMPOSSIBLE_ERROR	(-ECHILD)	/* cannot occur in FS context */
+
+ino_t
+global_inum(struct inode *ip)
+{
+	dev_t dev = ip->i_dev;
+	ino_t mask = (MFS_PE << 16) ^ (MAJOR(dev) << 16) ^ (MINOR(dev) << 24);
+	ino_t result = ip->i_ino ^ mask;
+
+	if(ip->i_ino == mfs_root_ino && dev == mfs_root_dev)
+		return(MFS_PE);
+	if(((unsigned long)result) <= MFS_ROOT_INO)
+		result ^= 0x80800000;
+	return(result);
+}
+
+inline void
+mfs_get_handling(struct dentry *dp, int *where, mfs_handle_t *handle)
+{
+	struct mfs_dinfo *p = (struct mfs_dinfo *)dp->d_fsdata;
+
+	*where = p->pe;
+	*handle = p->handle;
+}
+
+inline int
+mfs_is_last_use(struct dentry *dp, int *where, mfs_handle_t *handle)
+{
+	if(dp->d_fsdata)
+	{
+		*where = ((struct mfs_dinfo *)dp->d_fsdata)->pe;
+		*handle = ((struct mfs_dinfo *)dp->d_fsdata)->handle;
+		if(atomic_read(&dp->d_count) > 1)
+			return(0);
+		kfree(dp->d_fsdata);
+		dp->d_fsdata = NULL;
+		return(1);
+	}
+	else
+	{
+		*where = 0;
+		*handle = MFS_ROOT_INO;
+		return(0);
+	}
+}
+
+inline int
+mfs_low_attach_handle(mfs_handle_t handle)
+{
+	if(handle > MFS_ROOT_INO)	/* do not waste time on root */
+		return(mfs_get_handle(handle));
+	return(0);
+}
+
+inline int
+mfs_attach_handle(int pe, mfs_handle_t handle)
+{
+	if(handle <= MFS_ROOT_INO)
+		return(0);
+	mfs_count_attach_handle(pe);
+	if(pe == MFS_PE && !mfs_loopback_test)
+		return(mfs_low_attach_handle(handle));
+	else if(pe)
+		return(mfs_client_attach_handle(pe, handle));
+	return(0);
+}
+
+inline int
+mfs_low_touch_handle(mfs_handle_t handle)
+{
+	if(handle > MFS_ROOT_INO)	/* do not waste time on root */
+		return(mfs_access_handle(handle));
+	return(0);
+}
+
+inline int
+mfs_touch_handle(int pe, mfs_handle_t handle)
+{
+	if(handle <= MFS_ROOT_INO)
+		return(0);
+	mfs_count_touch_handle(pe);
+	if(pe == MFS_PE && !mfs_loopback_test)
+		return(mfs_low_touch_handle(handle));
+	else if(pe)
+		return(mfs_client_touch_handle(pe, handle));
+	return(0);
+}
+
+inline void
+mfs_low_dispose_handle(mfs_handle_t handle)
+{
+	if(handle > MFS_ROOT_INO)	/* do not waste time on root */
+		mfs_put_handle(handle);
+}
+
+inline void
+mfs_dispose_handle(int pe, mfs_handle_t handle)
+{
+	if(handle <= MFS_ROOT_INO)
+		return;
+	mfs_count_dispose_handle(pe);
+	if(pe == MFS_PE && !mfs_loopback_test)
+		mfs_low_dispose_handle(handle);
+	else if(pe)
+		mfs_client_dispose_handle(pe, handle);
+}
+
+extern struct file_operations mfs_file_file_operations;
+extern struct file_operations mfs_symlink_file_operations;
+extern struct file_operations mfs_dir_file_operations;
+extern struct inode_operations mfs_file_inode_operations;
+extern struct inode_operations mfs_symlink_inode_operations;
+extern struct inode_operations mfs_dir_inode_operations;
+extern struct dentry_operations mfs_dentry_operations;
+
+void
+mfs_ip_to_subip(struct subinode *subip, struct inode *ip)
+{
+	subip->si_mode = ip->i_mode;
+	subip->si_nlink = ip->i_nlink;
+	subip->si_iuid = ip->i_uid;
+	subip->si_gid = ip->i_gid;
+	subip->si_rdev = ip->i_rdev;
+	subip->si_size = ip->i_size;
+	subip->si_atime = ip->i_atime;
+	subip->si_ctime = ip->i_ctime;
+	subip->si_mtime = ip->i_mtime;
+	subip->si_blksize = ip->i_blksize;
+	subip->si_blocks = ip->i_blocks;
+	subip->si_origino = ip->i_ino;
+	subip->si_origdev = ip->i_dev;
+}
+
+void
+mfs_subip_to_ip(struct inode *ip, struct subinode *subip)
+{
+	ip->i_mode = subip->si_mode;
+	ip->i_nlink = subip->si_nlink;
+	ip->i_uid = subip->si_iuid;
+	ip->i_gid = subip->si_gid;
+	ip->i_rdev = subip->si_rdev;
+	ip->i_size = subip->si_size;
+	ip->i_atime = subip->si_atime;
+	ip->i_ctime = subip->si_ctime;
+	ip->i_mtime = subip->si_mtime;
+	ip->i_blksize = subip->si_blksize;
+	ip->i_blocks = subip->si_blocks;
+	ip->i_version = subip->si_origino;
+	ip->i_generation = subip->si_origdev;
+	ip->i_sb = mfs_super;
+	switch(ip->i_mode & S_IFMT)
+	{
+		case S_IFREG:
+			ip->i_op = &mfs_file_inode_operations;
+			ip->i_fop = &mfs_file_file_operations;
+			break;
+		case S_IFLNK:
+			ip->i_op = &mfs_symlink_inode_operations;
+			ip->i_fop = &mfs_symlink_file_operations;
+			break;
+		case S_IFDIR:
+			ip->i_op = &mfs_dir_inode_operations;
+			ip->i_fop = &mfs_dir_file_operations;
+			break;
+		default:
+			printk("MFS: inum %d of bad mode (0%o)\n",
+						(int)ip->i_ino, ip->i_mode);
+			make_bad_inode(ip);
+			break;
+	}
+}
+
+void
+cp_file_fields(struct file *filto, struct file *filfrom)
+{
+	filto->f_mode = filfrom->f_mode;
+	filto->f_pos = filfrom->f_pos;
+	filto->f_owner = filfrom->f_owner;
+	filto->f_reada = filfrom->f_reada;
+	filto->f_ramax = filfrom->f_ramax;
+	filto->f_raend = filfrom->f_raend;
+	filto->f_ralen = filfrom->f_ralen;
+	filto->f_rawin = filfrom->f_rawin;
+/* the following two fields are not actually currently in use!
+	filto->f_uid = filfrom->f_uid;
+	filto->f_gid = filfrom->f_gid;
+*/
+	filto->f_error = filfrom->f_error;
+	filto->f_version = filfrom->f_version;
+	filto->private_data = filfrom->private_data;
+}
+
+int
+prepare_dummy_file(mfs_handle_t handle, struct file *dummy, struct file *filp)
+{
+	struct nameidata nd;
+	int err;
+
+	if((err = mfs_to_local(handle, &nd)))
+		return(err);
+	if(nd.dentry->d_inode && nd.dentry->d_inode->i_op)
+		dummy->f_op = nd.dentry->d_inode->i_fop;
+	else
+		dummy->f_op = NULL;
+	dummy->f_dentry = nd.dentry;
+	dummy->f_vfsmnt = nd.mnt;
+	dummy->f_flags = filp->f_flags & (O_LARGEFILE|O_SYNC);
+	dummy->f_iobuf = NULL;
+	dummy->f_iobuf_lock = 0;
+	atomic_set(&dummy->f_count, 1);
+	cp_file_fields(dummy, filp);
+	return(0);
+}
+
+void
+collect_dummy_file(struct file *dummy, struct file *filp)
+{
+	mfs_lput(dummy->f_dentry, dummy->f_vfsmnt);
+	cp_file_fields(filp, dummy);
+}
+
+loff_t
+mfs_dir_llseek(struct file *filp, loff_t offset, int origin)
+{
+	int where;
+	mfs_handle_t handle;
+
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	mfs_count_llseek(where);
+	if(where != MFS_PE || mfs_loopback_test)
+		return(mfs_client_llseek(where, handle, filp, offset, origin));
+	return(mfs_low_llseek(handle, filp, offset, origin));
+}
+
+loff_t
+mfs_file_llseek(struct file *filp, loff_t offset, int origin)
+{
+	uint64_t newoff;
+
+	switch(origin)
+	{
+		case 0:
+			newoff = offset;
+			break;
+		case 1:
+			newoff = offset + filp->f_pos;
+			break;
+		default:
+			goto must_call;
+	}
+	if(!(newoff >> 32))
+	{
+		if(newoff != filp->f_pos)
+		{
+			lock_kernel();
+			filp->f_pos = newoff;
+			filp->f_reada = 0;
+			filp->f_version = ++event;
+			unlock_kernel();
+		}
+		return(newoff);
+	}
+
+	must_call:
+	return(mfs_dir_llseek(filp, offset, origin));
+}
+
+loff_t
+mfs_low_llseek(mfs_handle_t handle, struct file *filp, loff_t offset,
+								int origin)
+{
+	loff_t ret;
+	struct file dummy;
+	extern loff_t llseek(struct file *, loff_t, int);
+
+	if((ret = prepare_dummy_file(handle, &dummy, filp)))
+		return(ret);
+	lock_kernel();
+	ret = llseek(&dummy, offset, origin);
+	unlock_kernel();
+	collect_dummy_file(&dummy, filp);
+	return(ret);
+}
+
+ssize_t
+mfs_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+	int where;
+	mfs_handle_t handle;
+
+	if(!(filp->f_mode & FMODE_READ))
+		return(-EBADF);
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	mfs_count_read(where, count);
+	if(where != MFS_PE || mfs_loopback_test)
+		return(mfs_client_read(where, handle, filp, buf, count, ppos));
+	return(mfs_low_read(handle, filp, buf, count, ppos));
+}
+
+ssize_t
+mfs_low_read(mfs_handle_t handle, struct file *filp, char *buf, size_t count,
+								loff_t *ppos)
+{
+	loff_t ret;
+	struct file *dummy;
+	struct file_operations *fops;
+	loff_t mppos;
+
+	current->mosix.dirty_bits |= MFSARG_EMPTYF_PRI;
+	dummy = get_empty_filp();
+	current->mosix.dirty_bits &= ~MFSARG_EMPTYF_PRI;
+	if(!dummy)
+		return(-ENFILE);
+
+	if((ret = prepare_dummy_file(handle, dummy, filp)))
+	{
+		put_filp(dummy);
+		return(ret);
+	}
+	dget(dummy->f_dentry);
+	mntget(dummy->f_vfsmnt);
+	fops = dummy->f_dentry->d_inode->i_fop;
+	mppos = *ppos;
+#ifdef ONE_DAY_S_FILES_WILL_BE_USED_FOR_RDONLY_FILES
+	if(ip->i_sb)
+		file_move(dummy, &ip->i_sb->s_files);
+#endif /* ONE_DAY_S_FILES_WILL_BE_USED_FOR_RDONLY_FILES */
+	if(!fops || !fops->read)
+		ret = -EINVAL;
+	else
+		ret = fops->read(dummy, buf, count, &mppos);
+	collect_dummy_file(dummy, filp);
+	*ppos = mppos;
+	dummy->f_mode &= ~FMODE_WRITE;
+	fput(dummy);
+	return(ret);
+}
+
+ssize_t
+mfs_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+	int where;
+	mfs_handle_t handle;
+	int flim = current->rlim[RLIMIT_FSIZE].rlim_cur;
+
+	if(!(filp->f_mode & FMODE_WRITE))
+		return(-EBADF);
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	mfs_count_write(where, count);
+	if(where != MFS_PE || mfs_loopback_test)
+		return(mfs_client_write(where, handle, filp, (char *)buf, count,
+								ppos, flim));
+	return(mfs_low_write(handle, filp, (char *)buf, count, ppos, flim));
+}
+
+ssize_t
+mfs_low_write(mfs_handle_t handle, struct file *filp, char *buf, size_t count,
+							loff_t *ppos, long flim)
+{
+	loff_t ret;
+	struct file *dummy;
+	struct file_operations *fops;
+	struct super_block *sb;
+	struct inode *ip;
+	loff_t mppos;
+
+	/* unlike other functions, we need to allocate a dummy "file"
+	 * in the proper way, because NFS files could live even after
+	 * we exit */
+	current->mosix.dirty_bits |= MFSARG_EMPTYF_PRI;
+	dummy = get_empty_filp();
+	current->mosix.dirty_bits &= ~MFSARG_EMPTYF_PRI;
+	if(!dummy)
+		return(-ENFILE);
+	
+	if((ret = prepare_dummy_file(handle, dummy, filp)))
+	{
+		put_filp(dummy);
+		return(ret);
+	}
+	dget(dummy->f_dentry);
+	mntget(dummy->f_vfsmnt);
+	current->rlim[RLIMIT_FSIZE].rlim_cur = flim;
+	ip = dummy->f_dentry->d_inode;
+	sb = ip->i_sb;
+	fops = ip->i_fop;
+	mppos = *ppos;
+	if(filp->f_flags & O_APPEND)
+		mppos = ip->i_size;
+	if(sb)
+		file_move(dummy, &sb->s_files);
+	if(get_write_access(ip))
+		dummy->f_flags |= O_NOWRITEACCESS;
+	if((ret = locks_verify_area(FLOCK_VERIFY_WRITE, ip, NULL, mppos,count)))
+		;
+	else if(sb && (sb->s_flags & MS_RDONLY))
+		ret = -EROFS;
+	else if(!fops || !fops->write)
+		ret = -EINVAL;
+	else
+		ret = fops->write(dummy, buf, count, &mppos);
+	collect_dummy_file(dummy, filp);
+	*ppos = mppos;
+	fput(dummy);
+	return(ret);
+}
+
+int
+mfs_open(struct inode *inode, struct file *filp)
+{
+	int where;
+	mfs_handle_t handle;
+
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	if (where != MFS_PE)
+		return mfs_client_open(where, handle, inode, filp);
+	return mfs_low_open(handle, inode, filp);
+}
+
+int
+mfs_close(struct inode *inode, struct file *filp)
+{
+	int where;
+	mfs_handle_t handle;
+
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	if (where != MFS_PE)
+		return mfs_client_close(where, handle, inode, filp);
+	return mfs_low_close(handle, inode, filp);
+}
+
+int
+mfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	int where;
+	mfs_handle_t handle;
+	struct task_struct *p = current;
+	int policy;
+	int packets, bytes;
+	int result;
+
+	switch(p->mosix.dirty_bits &
+		(MFSARG_GETDENTS|MFSARG_GETDENTS64|MFSARG_OLDREADDIR))
+	{
+		case MFSARG_GETDENTS:
+			policy = MFS_READDIR_GETDENTS;
+			break;
+		case MFSARG_GETDENTS64:
+			policy = MFS_READDIR_GETDENTS64;
+			break;
+		case MFSARG_OLDREADDIR:
+			policy = MFS_READDIR_JUSTONE;
+			break;
+		default:
+			policy = MFS_READDIR_UNKNOWN;
+			break;
+	}
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	if(where != MFS_PE || mfs_loopback_test)
+		result = mfs_client_readdir(where, handle, filp, dirent,
+			filldir, policy, p->mosix.dirty_arg, &packets, &bytes);
+	else
+		result = mfs_low_readdir(handle, filp, dirent, filldir,
+							&packets, &bytes);
+	mfs_count_readdir(where, packets, bytes);
+	return(result);
+}
+
+struct mfs_local_readdir_callback
+{
+	filldir_t realfilldir;
+	void *realdirent;
+	struct dentry *parent;
+	struct vfsmount *pmnt;
+	int packets, bytes, inbytes;
+};
+
+int
+mfs_local_filldir(void *__cb, const char *name, int namelen, loff_t offset,
+						ino_t ino, unsigned int type)
+{
+	struct mfs_local_readdir_callback *cb = __cb;
+	struct inode ji;
+	struct inode *ri;
+	unsigned int b = sizeof(ino_t) + sizeof(loff_t) + sizeof(namelen) +
+						strnlen(name, namelen) + 1;
+
+	cb->bytes += b;
+	if((cb->inbytes += b) > MFS_MAXBLOCK)
+	{
+		cb->packets++;
+		cb->inbytes = b;
+	}
+	ji.i_ino = ino;
+	ji.i_dev = cb->parent->d_inode->i_dev;
+	/* to present a single, flat filesystem, we must adjust in case the
+	 * son falls outside the parent's file-system. */
+	if(namelen == 1 && name[0] == '.')
+		;	/* nothing */
+	else if(namelen == 2 && name[0] == '.' && name[1] == '.')
+	{
+		if(cb->parent == cb->pmnt->mnt_root)
+		{
+			ri = cb->pmnt->mnt_mountpoint->d_inode;
+			ji.i_ino = ri->i_ino;
+			ji.i_dev = ri->i_dev;
+		}
+	}
+	else
+	{
+		struct list_head *p;
+		struct vfsmount *m;
+
+		spin_lock(&dcache_lock);
+		for(p = cb->pmnt->mnt_mounts.next ; p != &cb->pmnt->mnt_mounts ;
+			p = p->next)
+		{
+			m = list_entry(p, struct vfsmount, mnt_child);
+			if(m->mnt_mountpoint->d_inode->i_ino == ji.i_ino)
+			{
+				struct inode *mroot = m->mnt_root->d_inode;
+
+				ji.i_dev = mroot->i_dev;
+				ji.i_ino = mroot->i_ino;
+				break;
+			}
+		}
+		spin_unlock(&dcache_lock);
+	}
+	return(cb->realfilldir(cb->realdirent, name, namelen, offset,
+						global_inum(&ji), type));
+}
+
+int
+mfs_low_open(mfs_handle_t handle, struct inode *inode, struct file *filp)
+{
+	struct file dummy;
+	struct file_operations *fops;
+	int ret;
+
+	ret = prepare_dummy_file(handle, &dummy, filp);
+	if (ret)
+		return ret;
+	fops = dummy.f_dentry->d_inode->i_fop;
+	if (fops && fops->open)
+		ret = fops->open(inode, &dummy);
+	collect_dummy_file(&dummy, filp);
+	return ret;
+}
+
+int
+mfs_low_close(mfs_handle_t handle, struct inode *inode, struct file *filp)
+{
+	struct file dummy;
+	struct file_operations *fops;
+	int ret;
+
+	ret = prepare_dummy_file(handle, &dummy, filp);
+	if (ret)
+		return ret;
+	fops = dummy.f_dentry->d_inode->i_fop;
+	if (fops && fops->release)
+		ret = fops->release(inode, &dummy);
+	collect_dummy_file(&dummy, filp);
+	return ret;
+}
+
+int
+mfs_low_readdir(mfs_handle_t handle, struct file *filp, void *dirent,
+				filldir_t filldir, int *packets, int *bytes)
+{
+	int ret;
+	struct file_operations *fops;
+	struct file dummy;
+	struct mfs_local_readdir_callback lrb;
+
+	if((ret = prepare_dummy_file(handle, &dummy, filp)))
+		return(ret);
+	fops = dummy.f_dentry->d_inode->i_fop;
+	lrb.realfilldir = filldir;
+	lrb.realdirent = dirent;
+	lrb.parent = dummy.f_dentry;
+	lrb.pmnt = dummy.f_vfsmnt;
+	lrb.packets = lrb.bytes = lrb.inbytes = 0;
+	ret = vfs_readdir(&dummy, mfs_local_filldir, (void *)&lrb);
+	collect_dummy_file(&dummy, filp);
+	*packets = lrb.packets;
+	*bytes = lrb.bytes;
+	return(ret);
+}
+
+int
+mfs_ioctl(struct inode *ip, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	int where;
+	mfs_handle_t handle;
+	int size;
+	int data;
+	int ret;
+
+	/* currently supporting only EXT2 ioctls: the following others
+	 * are possible candidates (later): ncpfs, smbfs, umsdos */
+	switch(cmd)
+	{
+		case EXT2_IOC_GETFLAGS:
+		case EXT2_IOC_GETVERSION:
+			size = -(int)sizeof(int);
+			break;
+		case EXT2_IOC_SETFLAGS:
+		case EXT2_IOC_SETVERSION:
+			size = sizeof(int);
+			break;
+		default:
+			return(-EPERM);
+	}
+	if(size > 0 && copy_from_user((void *)&data, (void *)arg, size))
+		return(-EFAULT);
+	mfs_get_handling(filp->f_dentry, &where, &handle);
+	mfs_count_ioctl(where);
+	if(where != MFS_PE || mfs_loopback_test)
+		ret = mfs_client_ioctl(where, handle, filp, cmd, arg, size,
+									&data);
+	else
+		ret = mfs_low_ioctl(handle, filp, cmd, arg, size, &data);
+	if(!ret && size < 0 && copy_to_user((void *)arg, (void *)&data, -size))
+		ret = -EFAULT;
+	return(ret);
+}
+
+int
+mfs_low_ioctl(mfs_handle_t handle, struct file *filp, unsigned int cmd,
+					unsigned long arg, int size, int *data)
+{
+	int ret;
+	struct file_operations *fops;
+	struct file dummy;
+	mm_segment_t old_fs;
+
+	if((ret = prepare_dummy_file(handle, &dummy, filp)))
+		return(ret);
+	fops = dummy.f_dentry->d_inode->i_fop;
+	if(!fops || !fops->ioctl)
+		ret = -ENOTTY;
+	else
+	{
+		if(size)
+			old_fs = set_fs(KERNEL_DS);
+		lock_kernel();
+		ret = fops->ioctl(dummy.f_dentry->d_inode, &dummy, cmd,
+			size ? (unsigned long)data : arg);
+		unlock_kernel();
+		if(size)
+			set_fs(old_fs);
+	}
+	collect_dummy_file(&dummy, filp);
+	return(ret);
+}
+
+int
+mfs_mmap(struct file *f, struct vm_area_struct *x)
+{
+	/* cannot be reached: just a place-holder */
+	/* some code (including "binfmt_elf.c") check for the existance of this
+	 * routine, but "do_mmap" will detect that there are no a_ops
+	 * and convert it to a file-read
+	 */
+	panic("mfs_mmap");
+	return(-ENOSYS);
+}
+
+int
+mfs_fsync(struct file *filp, struct dentry *dp, int datasync)
+{
+	int where;
+	mfs_handle_t handle;
+
+	mfs_get_handling(dp, &where, &handle);
+	mfs_count_fsync(where);
+	if(where != MFS_PE || mfs_loopback_test)
+		return(mfs_client_fsync(where, handle, filp, datasync));
+	return(mfs_low_fsync(handle, filp, datasync));
+}
+
+int
+mfs_low_fsync(mfs_handle_t handle, struct file *filp, int datasync)
+{
+	int ret;
+	struct file_operations *fops;
+	struct file dummy;
+
+	if((ret = prepare_dummy_file(handle, &dummy, filp)))
+		return(ret);
+	fops = dummy.f_dentry->d_inode->i_fop;
+	down(&dummy.f_dentry->d_inode->i_sem);
+	if(!fops || !fops->fsync)
+		ret = -EINVAL;
+	else
+		ret = fops->fsync(&dummy, dummy.f_dentry, datasync);
+	up(&dummy.f_dentry->d_inode->i_sem);
+	collect_dummy_file(&dummy, filp);
+	return(ret);
+}
+
+static struct file_operations mfs_file_file_operations =
+{
+	llseek:		mfs_file_llseek,
+	open:		mfs_open,
+	release:	mfs_close,
+	read:		mfs_read,
+	write:		mfs_write,
+	ioctl:		mfs_ioctl,
+	mmap:		mfs_mmap,
+	fsync:		mfs_fsync,
+};
+
+static struct file_operations mfs_symlink_file_operations =
+{
+	ioctl:		mfs_ioctl,
+};
+
+static struct file_operations mfs_dir_file_operations =
+{
+	llseek:		mfs_dir_llseek,
+	open:		mfs_open,
+	release:	mfs_close,
+	read:		mfs_read,
+	readdir:	mfs_readdir,
+	ioctl:		mfs_ioctl,
+	fsync:		mfs_fsync,
+};
+
+struct mfs_iphand
+{
+	int pe;
+	mfs_handle_t handle;
+};
+
+int
+compare_mfs_ip(struct inode *ip, unsigned long ig1, void *arg)
+{
+	int pe = ((struct mfs_iphand *)arg)->pe;
+
+	return(!pe || (ip->u.mfs_i.pe == pe &&
+		ip->u.mfs_i.handle == ((struct mfs_iphand *)arg)->handle));
+}
+
+struct inode *mfs_iget(unsigned long ino, int pe, mfs_handle_t handle)
+{
+	struct mfs_iphand h;
+
+	h.pe = pe;
+	h.handle = handle;
+	current->mosix.iget_mfs_pe = pe;
+	current->mosix.iget_mfs_handle = handle;
+	return(iget4(mfs_super, ino, compare_mfs_ip, &h));
+}
+
+int
+mfs_revalidate(struct dentry *dentry)
+{
+	int where;
+	mfs_handle_t handle;
+	int ret;
+	struct subinode iinfo;
+	struct inode *ip = dentry->d_inode;
+
+	mfs_get_handling(dentry, &where, &handle);
+	mfs_ip_to_subip(&iinfo, ip);
+	mfs_count_revalidate(where);
+	if(where != MFS_PE || mfs_loopback_test)
+		ret = mfs_client_revalidate(where, handle, &iinfo);
+	else
+		ret = mfs_low_revalidate(handle, &iinfo);
+	if(!ret)
+		mfs_subip_to_ip(ip, &iinfo);
+	return(ret);
+}
+
+int
+mfs_low_revalidate(mfs_handle_t handle, struct subinode *iinfo)
+{
+	struct inode *lip;
+	int ret;
+	struct nameidata nd;
+
+	if((ret = mfs_to_local(handle, &nd)))
+		return(ret);
+	lip = nd.dentry->d_inode;
+	if(!lip || !lip->i_op || !lip->i_op->revalidate)
+		ret = 0;
+	else
+		ret = lip->i_op->revalidate(nd.dentry);
+	if(!ret)
+		mfs_ip_to_subip(iinfo, lip);
+	mfs_lput(nd.dentry, nd.mnt);
+	return(ret);
+}
+
+int
+mfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	int where;
+	mfs_handle_t handle;
+
+	if(mfs_is_ro)
+		return(-EROFS);
+	if(!dentry->d_fsdata) /* someone trying to fiddle with the MFS root */
+		return(-EPERM);
+	mfs_get_handling(dentry, &where, &handle);
+	mfs_count_setattr(where);
+	if(where != MFS_PE || mfs_loopback_test)
+		return(mfs_client_setattr(where, handle, attr));
+	return(mfs_low_setattr(handle, attr));
+}
+
+int
+mfs_low_setattr(mfs_handle_t handle, struct iattr *attr)
+{
+	struct nameidata nd;
+	struct inode *ip;
+	int ret;
+	unsigned int wa = 0;
+
+	if((ret = mfs_to_local(handle, &nd)))
+		return(ret);
+	ret = -EINVAL;
+	if(!(ip = nd.dentry->d_inode))
+		goto out;
+	if(attr->ia_valid & ATTR_SIZE)
+	{
+		/* this must be ftruncate: */
+
+		if((ret = get_write_access(ip)))
+			goto out;
+		wa = 1;
+		ret = -EISDIR;
+		if(S_ISDIR(ip->i_mode))
+			goto out;
+		ret = -EINVAL;
+		if(!S_ISREG(ip->i_mode))
+			goto out;
+		ret = -EPERM;
+		if(IS_APPEND(ip))
+			goto out;
+		if((ret = locks_verify_truncate(ip, NULL, attr->ia_size)))
+			goto out;
+		down(&ip->i_sem);
+	}
+	ret = notify_change(nd.dentry, attr);
+	if(attr->ia_valid & ATTR_SIZE)
+		up(&ip->i_sem);
+	out:
+	if(wa)
+		put_write_access(ip);
+	mfs_lput(nd.dentry, nd.mnt);
+	return(ret);
+}
+
+int
+mfs_root_name_to_ino(char *name, int len)
+{
+	int node = 0;
+
+	if(*name >= '0' && *name <= '9')
+	while(len && node <= MOSIX_MAX && *name >= '0' && *name <= '9')
+	{
+		node = node * 10 + (*name - '0');
+		name++;
+		len--;
+	}
+	else if(len)
+	switch(*name)
+	{
+		case 'h':
+			if(len != 4 || name[3] != 'e')
+				return(0);
+			if(name[1] == 'e' && name[2] == 'r')
+				return(current->mosix.whereami ? : PE);
+			if(name[1] == 'o' && name[2] == 'm')
+				return(current->mosix.deppe ? : PE);
+			break;
+		case 'l':
+			if(len == 8 && !memcmp(&name[1], "astexec", 7))
+				return(current->mosix.lastexec ? :
+					(current->mosix.deppe ? : PE));
+			break;
+		case 'm':
+			if(len == 5 && !memcmp(&name[1], "agic", 4))
+				return(current->mosix.lastmagic ? :
+					(current->mosix.deppe ? : PE));
+		case 's':
+			if(len == 8 && !memcmp(&name[1], "elected", 7))
+				return(current->mosix.selected ? :
+					(current->mosix.deppe ? : PE));
+	}
+	if(len || !mos_to_net(node, NULL))
+		node = 0;
+	return(node);
+}
+
+static void
+fill_last_component(char *nam, struct nameidata *nd)
+{
+	char *start = nam, *end;
+
+	while(*nam)
+		nam++;
+	end = nam;
+	for(nam-- ; *nam == '/' && nam > start ; nam--)
+		;
+	while(nam > start && *(nam-1) != '/')
+		nam--;
+	nd->last.name = nam;
+	nd->last.len = end - nam + 1;
+	nd->last_type = LAST_NORM;
+	switch(*nam)
+	{
+		case '/':
+		case '\0':
+			nd->last_type = LAST_ROOT;
+			break;
+		case '.':
+			switch(*(nam+1))
+			{
+				case '.':
+					if(*(nam+2) == '/' || *(nam+2) == '\0')
+						nd->last_type = LAST_DOTDOT;
+					break;
+				case '/':
+				case '\0':
+					nd->last_type = LAST_DOT;
+					return;
+			}
+			break;
+	}
+}
+
+int
+mfs_express_lookup(struct nameidata *nd, char **name)
+{
+	char *nam = *name;
+	struct vfsmount *mnt;
+	int pe;
+	mfs_handle_t handle;
+	struct subinode iinfo;
+	struct inode *ip;
+	struct qstr qnam;
+	char *newname = NULL;
+	struct mfs_completion complete;
+	struct dentry *result;
+	int err;
+	unsigned int magic = 0;
+	int link = 0;
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int flags = nd->flags & ~(LOOKUP_COMPLETE|LOOKUP_STAYFS);
+#else
+	unsigned int flags = nd->flags & ~LOOKUP_COMPLETE;
+#endif /* CONFIG_MOSIX_DFSA */
+
+	mfs_prepare_completion(&complete, nd);
+	if(complete.error < 0)
+	{
+		mfs_check_completion(&complete, nd);
+		return(complete.error);
+	}
+	pe = complete.base_pe;
+	handle = complete.base;
+	*name = NULL;
+	while(*nam)
+	{
+		if(pe == 0)
+		{
+			char *c;
+
+			if(*nam == '.')
+			switch(*(nam+1))
+			{
+				case '\0':
+					nam++;
+					continue;
+				case '/':
+					nam += 2;
+					while(*nam == '/')
+						nam++;
+					continue;
+				case '.':
+					if(*(nam+2) == '\0' || *(nam+2) == '/')
+						goto name_leads_back;
+					break;
+			}
+			for(c = nam ; *c && *c != '/' ; c++)
+				;
+			pe = mfs_root_name_to_ino(nam, c - nam);
+			handle = pe;
+			if(!pe)
+			{
+				mfs_check_completion(&complete, nd);
+#ifdef CONFIG_MOSIX_DFSA
+				if(current->mosix.dflags & DREMOTE)
+					return(-EDOITATHOME);
+#endif /* CONFIG_MOSIX_DFSA */
+				return(-ENOENT);
+			}
+			if(nam[0] == 'm')
+				magic = 1;
+			link = (nam[0] >= 'a');
+			while(*c == '/')
+				c++;
+			nam = c;
+		}
+		if(flags & LOOKUP_MFS)
+		{
+			/* server may only access the MFS root itself or reach
+			 * back to the node's root via the correct link */
+			mfs_check_completion(&complete, nd);
+			if(pe != MFS_PE || !(flags & LOOKUP_MFS_MFS))
+				return(-EACCES);
+			nd->flags &= ~LOOKUP_MFS_MFS;
+			dput(nd->dentry);
+			mntput(nd->mnt);
+			nd->dentry = dget(mfs_root);
+			nd->mnt = mntget(mfs_mnt);
+			if(*nam)
+				*name = nam;
+			return(0);
+		}
+		if(!*nam && (nd->flags & LOOKUP_PARENT))
+		{
+			mfs_check_completion(&complete, nd);
+			return(-EPERM);
+		}
+		if(pe && !*nam && link && !(nd->flags & LOOKUP_FOLLOW))
+			return(mfs_link_complete(&complete, pe, nd));
+		mfs_count_express(pe, complete.more_data_len);
+		if(pe != MFS_PE || mfs_loopback_test)
+			err = mfs_client_express_lookup(pe, &handle, nam,
+					flags, &iinfo, &newname, &complete);
+		else
+			err = mfs_low_express_lookup(&handle, nam, flags,
+					current->link_count,
+					current->total_link_count, &iinfo,
+					&newname, &complete);
+#if 0
+printk("mfs_express_lookup: nam=<%s>, newname=%x", nam, newname);
+if(newname)printk("<%s>\n", newname);else printk("\n");
+#endif
+
+		if(err == AN_IMPOSSIBLE_ERROR && iinfo.si_count)
+		{
+			pe = magic = 0;
+#if 0
+printk("mfs_express_lookup: skipping from <%s> to ", nam);
+#endif
+			nam += iinfo.si_count - 1;
+#if 0
+printk("<%s>\n", nam);
+#endif
+			if(!*nam && (nd->flags & LOOKUP_PARENT))
+			{
+				mfs_check_completion(&complete, nd);
+				return(-EPERM);
+			}
+			dput(nd->dentry);
+			nd->dentry = dget(mfs_super->s_root);
+		}
+		else if(IS_ERR((const void *)err))
+		{
+			mfs_check_completion(&complete, nd);
+			return(err);
+		}
+		else
+		{
+			if(nd->flags & LOOKUP_PARENT)
+				fill_last_component(nam, nd);
+			break;
+		}
+	}
+	if(pe == 0)
+	{
+		mfs_check_completion(&complete, nd);
+		return(0);
+	}
+	if(mfs_check_completion(&complete, nd))
+	{
+		if(newname)
+			kfree(newname);
+		return(complete.error);
+	}
+	if(newname)
+	{
+		qnam.name = newname;
+		qnam.len = strlen(newname);
+	}
+	else	/* can still function - except 'getcwd' */
+	{
+		qnam.name = "__removed__";
+		qnam.len = 11;
+	}
+	result = d_alloc(mfs_super->s_root, &qnam);
+	if(newname)
+		kfree(newname);
+	if(!result)
+	{
+		mfs_dispose_handle(pe, handle);
+		return(-ENOMEM);
+	}
+	if(!(result->d_fsdata = kmalloc(sizeof(struct mfs_dinfo), GFP_KERNEL)))
+	{
+		dput(result);
+		mfs_dispose_handle(pe, handle);
+		return(-ENOMEM);
+	}
+	result->d_flags |= DCACHE_NO_CACHE;
+	result->d_op = &mfs_dentry_operations;
+	((struct mfs_dinfo *)result->d_fsdata)->pe = pe;
+	((struct mfs_dinfo *)result->d_fsdata)->handle = handle;
+	((struct mfs_dinfo *)result->d_fsdata)->latest = jiffies;
+	if(iinfo.si_ino)
+	{
+		ip = mfs_iget(iinfo.si_ino, pe, handle);
+		if(!ip)
+		{
+			dput(result);
+			return(-EACCES);
+		}
+		mfs_subip_to_ip(ip, &iinfo);
+		d_add(result, ip);
+	}
+	else
+		d_add(result, NULL);
+	if(magic && (nd->complete_flags & COMPLETE_DONE))
+		nd->complete_flags |= COMPLETE_MAGICAL;
+	dput(nd->dentry);
+	nd->dentry = result;
+	return(0);
+
+	name_leads_back:
+	mfs_check_completion(&complete, nd);
+#ifdef CONFIG_MOSIX_DFSA
+	if(nd->flags & LOOKUP_STAYFS)
+	{
+		if(current->mosix.dflags & DREMOTE)
+			return(-EDOITATHOME);
+		nd->flags &= ~LOOKUP_STAYFS;
+		current->mosix.dflags &= ~DSTATSDOWN;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	for(nam += 2 ; *nam == '/' ; nam++)
+		;
+#if 0
+printk("name leads back, left=../<%s>\n", nam);
+#endif
+	if(*nam)
+		*name = nam;
+	else if(nd->flags & LOOKUP_PARENT)
+		return(-EPERM);
+	dput(nd->dentry);
+	mnt = nd->mnt;
+	nd->mnt = mntget(mnt->mnt_parent);
+	nd->dentry = dget(mnt->mnt_mountpoint->d_parent);
+	mntput(mnt);
+	return(0);
+}
+
+char *
+mfs_full_name(struct dentry *of, struct vfsmount *on)
+{
+	char *a, *b;
+	char *page = (char *)kmalloc(PAGE_SIZE, GFP_KERNEL);
+	int x;
+
+	if(!page)
+		return(NULL);
+	if(of == mfs_root && on == mfs_mnt)
+	{
+		a = &page[PAGE_SIZE-1];
+		*a = '\0';
+	}
+	else
+	{
+		spin_lock(&dcache_lock);
+		a = __d_path(of, on, mfs_root, mfs_mnt, page, PAGE_SIZE);
+		spin_unlock(&dcache_lock);
+	}
+	for(x = MFS_PE ; x ; x /= 10)
+	{
+		if(a == page)
+		{
+			kfree(page);
+			return(NULL);
+		}
+		*(--a) = x % 10 + '0';
+	}
+	if(a != page)
+	{
+		for(b = page ; *a ; )
+			*b++ = *a++;
+		*b = '\0';
+		a = page;
+	}
+	return(a);
+}
+
+int
+mfs_low_express_lookup(mfs_handle_t *handlep, char *name, unsigned int flags,
+	int link_count, int total_link_count, struct subinode *iinfo,
+	char **newname, struct mfs_completion *complete)
+{
+	struct inode *ip;
+	struct nameidata nd;
+	int error;
+
+	iinfo->si_count = 0;
+	*newname = NULL;
+	if((error = mfs_to_local(*handlep, &nd)))
+	{
+		mfs_low_complete_error(complete, error);
+		return(error);
+	}
+#if 0
+ip = nd.dentry->d_inode;
+printk("mfs_low_express_lookup, original ino=%x/%d, d_count=%d\n", ip->i_dev, ip->i_ino, atomic_read(&nd.dentry->d_count));
+#endif
+	nd.flags = (flags | LOOKUP_MFS) & ~LOOKUP_MFS_MFS;
+	nd.last_type = LAST_ROOT;
+	nd.name_left = NULL;
+	nd.complete_flags = 0;
+	dget(nd.dentry);
+	mntget(nd.mnt);
+	mfs_lput(nd.dentry, nd.mnt);
+	current->link_count = link_count;
+	current->total_link_count = total_link_count;
+	error = path_walk(name, &nd);
+	if(nd.name_left)	/* "/.." */
+	{
+		iinfo->si_count = (nd.name_left - name) + 1;
+#if 0
+printk("mfs_low_express_lookup: name_left %x<%s>, orig_name=%x<%s>, skip_factor=%d\n", nd.name_left, nd.name_left, name, name, iinfo->si_count);
+#endif
+		return(AN_IMPOSSIBLE_ERROR);
+	}
+	if(error)
+	{
+		mfs_low_complete_error(complete, error);
+		return(error);
+	}
+	if((*handlep = mfs_low_complete(complete, &nd)))
+	{
+		/* need information back */
+		if((ip = nd.dentry->d_inode))
+		{
+			iinfo->si_ino = global_inum(ip);
+			mfs_ip_to_subip(iinfo, ip);
+		}
+		else
+			iinfo->si_ino = 0;
+		*newname = mfs_full_name(nd.dentry, nd.mnt);
+#if 0
+printk("mfs_low_express_lookup: dev=%x, ip=%d, name=<%s>, newname=%x", ip ? ip->i_dev : 0, ip ? ip->i_ino : 0, name, *newname);
+if(*newname)printk("<%s>", *newname);printk("\n");
+#endif
+	}
+	else
+	{
+#if 0
+printk("mfs_low_express_lookup(%s): all resolved, err=%d", name, complete->error);
+if(nd.dentry->d_inode)printk(", dev=%x, ino=%d\n", nd.dentry->d_inode->i_dev, nd.dentry->d_inode->i_ino);
+printk("\n");
+#endif
+		*handlep = 0;
+	}
+#if 0
+ip = nd.dentry->d_inode; printk("before path release, ");
+if(ip)printk("ino=%x/%d, ", ip->i_dev, ip->i_ino);
+printk("d_count=%d\n", atomic_read(&nd.dentry->d_count));
+#endif 
+	if(!IS_ERR((const void *)complete->error))
+		path_release(&nd);
+	return(complete->error);
+}
+
+void
+mfs_check_path(struct dentry *dp)
+{
+	int where;
+	mfs_handle_t handle;
+	char *name;
+	unsigned int len;
+
+	if(dp == mfs_super->s_root)
+		return;
+	if(dp->d_parent != mfs_super->s_root)
+	{
+		return;
+	}
+	mfs_get_handling(dp, &where, &handle);
+	if(where != MFS_PE || mfs_loopback_test)
+		name = mfs_client_check_path(where, handle);
+	else
+		name = mfs_low_check_path(handle);
+	mfs_count_check_path(where, name ? strlen(name)+1 : 0);
+	if(!name || !strcmp(name, dp->d_name.name))
+		return;
+
+	len = strlen(name);
+	if(len <= dp->d_name.len)
+	{
+		dp->d_name.len = len;
+		strcpy((char *)dp->d_name.name, name);
+		kfree(name);
+	}
+	else
+	{
+		if(dname_external(dp))
+			kfree(dp->d_name.name);
+		dp->d_name.name = name;
+		dp->d_name.len = len;
+	}
+}
+
+char *
+mfs_low_check_path(mfs_handle_t handle)
+{
+	struct nameidata nd;
+	char *ret;
+
+	if(mfs_to_local(handle, &nd))
+		return(NULL);
+	ret = mfs_full_name(nd.dentry, nd.mnt);
+	mfs_lput(nd.dentry, nd.mnt);
+	return(ret);
+}
+
+struct inode_operations mfs_file_inode_operations = {
+        revalidate:	mfs_revalidate,
+	setattr:	mfs_setattr,
+	check_path:	mfs_check_path,
+};
+
+struct inode_operations mfs_symlink_inode_operations = {
+        revalidate:	mfs_revalidate,
+	setattr:	mfs_setattr,
+	check_path:	mfs_check_path,
+};
+
+struct inode_operations mfs_dir_inode_operations = {
+        revalidate:	mfs_revalidate,
+	setattr:	mfs_setattr,
+	express_lookup:	mfs_express_lookup,
+	check_path:	mfs_check_path,
+};
+
+int
+mfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	int first, last;
+
+	if(filp->f_pos == 0)
+	{
+		if(filldir(dirent, ".", 1, 0,
+				filp->f_dentry->d_inode->i_ino, DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 1;
+	}
+	if(filp->f_pos == 1)
+	{
+		if(filldir(dirent, "..", 2, 1,
+				filp->f_dentry->d_inode->i_ino, DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 2;
+	}
+	if(filp->f_pos == 2)
+	{
+		if(filldir(dirent, "here", 4, 2,
+				mfs_root_name_to_ino("here", 4), DT_DIR))
+			return(0);
+		filp->f_pos = 3;
+	}
+	if(filp->f_pos == 3)
+	{
+		if(filldir(dirent, "home", 4, 3,
+				mfs_root_name_to_ino("home", 4), DT_DIR))
+			return(0);
+		filp->f_pos = 4;
+	}
+	if(filp->f_pos == 4)
+	{
+		if(filldir(dirent, "lastexec", 8, 4,
+				mfs_root_name_to_ino("lastexec", 8), DT_DIR))
+			return(0);
+		filp->f_pos = 5;
+	}
+	if(filp->f_pos == 5)
+	{
+		if(filldir(dirent, "magic", 5, 5,
+				mfs_root_name_to_ino("magic", 5), DT_DIR))
+			return(0);
+		filp->f_pos = 6;
+	}
+	if(filp->f_pos == 6)
+	{
+		if(filldir(dirent, "selected", 8, 6,
+				mfs_root_name_to_ino("selected", 8), DT_DIR))
+			return(0);
+		filp->f_pos = 7;
+	}
+	if(filp->f_pos < 7 || filp->f_pos >= 7 + MOSIX_MAX)
+		return(0);
+	while(scan_mosix_nodes(filp->f_pos - 6, &first, &last))
+	while(first <= last)
+	{
+		char node[6];
+		int n = first;
+		char *c;
+
+		c = &node[5];
+		*c = '\0';
+		while(n)
+		{
+			c--;
+			*c = n % 10 + '0';
+			n /= 10;
+		}
+		if(filldir(dirent, c, sizeof(node) - 1 - (c - node),
+			first + 6, first, DT_DIR))
+				return(0);
+		filp->f_pos = ++first + 6;
+	}
+	return(0);
+}
+
+static struct file_operations mfs_root_file_operations =
+{
+	readdir:	mfs_root_readdir,
+};
+
+int
+mfs_root_revalidate(struct dentry *dp)
+{
+	struct inode *ip = dp->d_inode;
+
+	ip->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
+	ip->i_nlink = 1;
+	ip->i_uid = 0;
+	ip->i_gid = 0;
+	ip->i_rdev = 0;
+	ip->i_size = 0;
+	ip->i_atime = 0;
+	ip->i_ctime = 0;
+	ip->i_mtime = 0;
+	ip->i_blksize = 1024;
+	ip->i_blocks = 0;
+	return(0);
+}
+
+struct dentry *
+mfs_root_lookup(struct inode *dir, struct dentry *dentry)
+{
+	struct mfs_dinfo *info;
+	struct inode *inode = NULL;
+	int node;
+
+	if(!(node = mfs_root_name_to_ino((char *)dentry->d_name.name,
+							dentry->d_name.len)))
+	{
+#ifdef CONFIG_MOSIX_DFSA
+		if(current->mosix.dflags & DREMOTE)
+			return(ERR_PTR(-EDOITATHOME));
+#endif /* CONFIG_MOSIX_DFSA */
+		return(ERR_PTR(-EACCES));
+	}
+	if(!(info = (struct mfs_dinfo *)kmalloc(sizeof(struct mfs_dinfo),
+								GFP_KERNEL)))
+		return(ERR_PTR(-ENOMEM));
+	info->pe = node;
+	info->handle = node;
+	info->latest = jiffies;
+	dentry->d_flags |= DCACHE_NO_CACHE;
+	dentry->d_op = &mfs_dentry_operations;
+	dentry->d_fsdata = info;
+	inode = mfs_iget(node, node, node);
+	if(!inode)
+		return(ERR_PTR(-ENOMEM));
+	d_add(dentry, inode);
+	return(NULL);
+}
+
+/* note: most of the following functions are actually required, even though
+ * not really permitted on the MFS root itself, because the MFS root is
+ * technically the parent of all MFS nodes.
+ */
+struct inode_operations mfs_root_inode_operations = {
+	revalidate:	mfs_root_revalidate,
+	setattr:	mfs_setattr,
+	express_lookup:	mfs_express_lookup,
+};
+
+void
+mfs_read_inode(struct inode * inode)
+{
+	unsigned long ino = inode->i_ino;
+	struct subinode iinfo;
+	int err;
+
+	if(ino == MFS_ROOT_INO)
+	{
+		inode->i_mode = S_IFDIR | S_IXUGO | S_IRUGO | S_IWUGO;
+		inode->i_op = &mfs_root_inode_operations;
+		inode->i_fop = &mfs_root_file_operations;
+		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		inode->i_blocks = 0;
+		inode->i_blksize = 1024;
+		inode->i_uid = 0;
+		inode->i_gid = 0;
+		inode->i_nlink = 1;
+		inode->i_size = 0;
+		inode->i_generation = 0;
+		inode->i_version = 0;
+		return;
+	}
+	inode->u.mfs_i.pe = current->mosix.iget_mfs_pe;
+	inode->u.mfs_i.handle = current->mosix.iget_mfs_handle;
+	if(ino < MFS_ROOT_INO)
+	{
+		mfs_count_revalidate(ino);
+		if(ino != MFS_PE || mfs_loopback_test)
+			err = mfs_client_revalidate(ino, ino, &iinfo);
+		else
+			err = mfs_low_revalidate(MFS_PE, &iinfo);
+		if(err)		/* just guess */
+		{
+			inode->i_mode = S_IFDIR | S_IXUGO | S_IRUGO;
+			inode->i_op = &mfs_dir_inode_operations;
+			inode->i_mtime = inode->i_atime = inode->i_ctime =
+								CURRENT_TIME;
+			inode->i_blocks = 0;
+			inode->i_blksize = 1024;
+			inode->i_uid = 0;
+			inode->i_gid = 0;
+			inode->i_nlink = 1;
+			inode->i_size = 0;
+		}
+		else
+			mfs_subip_to_ip(inode, &iinfo);
+	}
+}
+int mfs_bh_statfs(mfs_handle_t handle, struct statfs *buf)
+{
+
+	struct nameidata nd;
+	int rc;
+	if ((rc = mfs_to_local(handle, &nd))) return (rc);
+	rc = vfs_statfs(nd.dentry->d_inode->i_sb, buf);
+	mfs_lput(nd.dentry, nd.mnt); /* mfs long put */ 
+	return rc;
+}	
+
+
+
+int
+mfs_statfs(struct super_block *sb, struct statfs *buf)
+{
+	struct dentry *dp; /* use the dentry */
+	mfs_handle_t handle; /* get a handle to the mfs fs*/
+	unsigned int dest;
+
+	if (current->mosix.dirty_bits & MFSARG_STATFS_FP)
+	{
+		current->mosix.dirty_bits &= ~MFSARG_STATFS_FP; /* get the file handle */
+		dp = current->mosix.dirty_file->f_dentry; /* get the right dentry pointer */
+		if (!dp->d_fsdata) goto ESC;
+		mfs_get_handling(dp, &dest, &handle); /* get handling and put in dest */
+		mfs_count_statfs(dest); /* now actually do it */
+		if (dest != MFS_PE)
+			return(mfs_client_statfs(dest, handle, buf));
+		return (mfs_bh_statfs(handle, buf));
+	}
+
+ESC:	
+	buf->f_type = MFS_SUPER_MAGIC; /* here we say it's MFS */
+	buf->f_bsize = PAGE_SIZE/sizeof(long);
+	buf->f_namelen = NAME_MAX;
+	buf->f_blocks = 9999999;/* here we should call the concerned PE and get the real values*/
+	buf->f_bfree = 99999999;
+        buf->f_bavail = 9999999;
+        buf->f_files = 9999999;
+        buf->f_ffree = 99999;
+	return(0);
+}
+
+void
+mfs_put_super(struct super_block *sb)
+{
+	mfs_is_mounted = 0;
+	mfs_super = NULL;
+}
+
+#ifdef CONFIG_MOSIX_DFSA
+struct mfs_ident	/* used in mfs_identify/mfs_reconstruct */
+{
+	int pe;
+	mfs_handle_t handle;
+	ino_t ino;
+	mode_t mode;
+};
+
+int
+mfs_identify(struct dentry *dentry, void *into)
+{
+	struct mfs_ident *i = into;
+	struct mfs_dinfo *p = (struct mfs_dinfo *)dentry->d_fsdata;
+
+	if(sizeof(struct mfs_ident) > MAX_IDENT_RECORD_LEN)
+		panic("mfs_identify: insufficient\n");
+	if(p)
+	{
+		i->pe = p->pe;
+		i->handle = p->handle;
+	}
+	else
+	{
+		i->pe = 0;
+		i->handle = 0;
+	}
+	i->ino = dentry->d_inode->i_ino;
+	i->mode = dentry->d_inode->i_mode;
+	return(sizeof(struct mfs_ident));
+}
+
+struct dentry *
+mfs_reconstruct(struct vfsmount *mnt, void *info, int infolen)
+{
+	struct mfs_ident *i = (struct mfs_ident *)info;
+	struct dentry *dp;
+	struct inode *ip;
+	struct qstr qname;
+
+	if(mnt->mnt_sb != mfs_super || infolen != sizeof(struct mfs_ident))
+	{
+		printk("mfs_reconstruct: improper data\n");
+		return(NULL);
+	}
+	if(!i->pe)
+		return(i->handle ? NULL : dget(mfs_super->s_root));
+	qname.name = "yet_unknown";
+	qname.len = 11;
+	if(!(dp = d_alloc(mfs_super->s_root, &qname)))
+		return(NULL);
+	if(!(dp->d_fsdata = kmalloc(sizeof(struct mfs_dinfo), GFP_KERNEL)))
+	{
+		dput(dp);
+		return(NULL);
+	}
+	dp->d_flags |= DCACHE_NO_CACHE;
+	dp->d_op = &mfs_dentry_operations;
+	((struct mfs_dinfo *)dp->d_fsdata)->pe = i->pe;
+	((struct mfs_dinfo *)dp->d_fsdata)->handle = i->handle;
+	((struct mfs_dinfo *)dp->d_fsdata)->latest = jiffies;
+	ip = mfs_iget(i->ino, i->pe, i->handle);
+	if(!ip)
+	{
+		kfree(dp->d_fsdata);
+		dp->d_fsdata = NULL;
+		dput(dp);
+		return(NULL);
+	}
+	ip->i_mode = i->mode;
+	switch(i->mode & S_IFMT)
+	{
+		case S_IFREG:
+			ip->i_op = &mfs_file_inode_operations;
+			ip->i_fop = &mfs_file_file_operations;
+			break;
+		case S_IFLNK:
+			ip->i_op = &mfs_symlink_inode_operations;
+			ip->i_fop = &mfs_symlink_file_operations;
+			break;
+		case S_IFDIR:
+			ip->i_op = &mfs_dir_inode_operations;
+			ip->i_fop = &mfs_dir_file_operations;
+			break;
+		default:
+			printk("mfs_reconstruct: inum %d of bad mode (0%o)\n",
+						(int)ip->i_ino, ip->i_mode);
+			make_bad_inode(ip);
+			break;
+	}
+	d_add(dp, ip);
+	if(mfs_attach_handle(i->pe, i->handle))
+	{
+		kfree(dp->d_fsdata);
+		dp->d_fsdata = NULL;
+		dput(dp);
+		return(NULL);
+	}
+	return(dp);
+}
+
+void
+mfs_dfsa_changed(struct vfsmount *mnt, int new)
+{
+	mfs_is_dfsa = (new != 0);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
+struct super_operations mfs_sops =
+{
+	read_inode:		mfs_read_inode,
+	put_inode:		force_delete,
+	put_super:		mfs_put_super,
+	statfs:			mfs_statfs,
+#ifdef CONFIG_MOSIX_DFSA
+	identify:		mfs_identify,
+	reconstruct:		mfs_reconstruct,
+	dfsa_changed:		mfs_dfsa_changed,
+#endif /* CONFIG_MOSIX_DFSA */
+};
+
+int
+mfs_dentry_compare(struct dentry *d, struct qstr *a, struct qstr *b)
+{
+	/* since MFS uses no hashing/caching, we should never reach here! */
+	printk("mfs_dentry_compare! (<%s>, <%s>)\n", a->name, b->name);
+	return(1);
+}
+
+void
+mfs_dentry_release(struct dentry *dp)
+{
+	int where;
+	mfs_handle_t handle;
+
+	if(dp->d_fsdata)
+	{
+		where = ((struct mfs_dinfo *)dp->d_fsdata)->pe;
+		handle = ((struct mfs_dinfo *)dp->d_fsdata)->handle;
+		kfree(dp->d_fsdata);
+		dp->d_fsdata = NULL;
+		mfs_dispose_handle(where, handle);
+	}
+}
+
+struct dentry_operations mfs_dentry_operations =
+{
+	d_compare:		mfs_dentry_compare,
+	d_release:		mfs_dentry_release,
+};
+
+struct super_block *
+mfs_read_super(struct super_block *s, void *data, int silent)
+{
+	struct inode * root_inode;
+	struct super_block *ret = s;
+
+	if(mfs_is_mounted)
+	{
+		printk("MFS already mounted!\n");
+		return(NULL);
+	}
+	if(!PE)
+		printk("WARNING: MFS mounting is ineffective until openMosix is configured.\n");
+	mfs_is_mounted = 1;
+	mfs_is_ro = (s->s_flags & MS_RDONLY);
+	mfs_super = s;
+	s->s_blocksize = 1024;
+	s->s_blocksize_bits = 10;
+	s->s_magic = MFS_SUPER_MAGIC;
+	s->s_op = &mfs_sops;
+	root_inode = iget(s, MFS_ROOT_INO);
+	if (!root_inode || !(s->s_root = d_alloc_root(root_inode)))
+	{
+		printk("Failed initializing openMosix file-system.\n");
+		iput(root_inode);
+		mfs_is_mounted = 0;
+		ret = NULL;
+	}
+	else
+		s->s_root->d_op = &mfs_dentry_operations;
+	s->s_maxbytes = ~0LL;
+	return(ret);
+}
+
+void
+mfs_change_pe(void)
+{
+	lock_mosix();
+	if(MFS_PE == ((PE && !mosadmin_mode_nomfs) ? PE : MFS_UNKNOWN_PE))
+	{
+		unlock_mosix();
+		return;
+	}
+	unlock_mosix();
+	if(mfs_try_to_cleanup(0))
+	{
+		printk("WARNING: Due to the openMosix configuration-change, all MFS files and\n");
+		printk("directories previously opened on this node will become inaccessible!\n");
+		mfs_try_to_cleanup(2);
+	}
+	lock_mosix();
+	MFS_PE = (PE && !mosadmin_mode_nomfs) ? PE : MFS_UNKNOWN_PE;
+	unlock_mosix();
+}
+
+DECLARE_FSTYPE(mfs_fs_type, "mfs", mfs_read_super, 0);
+
+int init_mfs(void)
+{
+	int err;
+
+	MFS_PE = (PE && !mosadmin_mode_nomfs) ? PE : MFS_UNKNOWN_PE;
+	if((err = register_filesystem(&mfs_fs_type)))
+		return err;
+	mfs_conversion_init();
+	mfs_make_servers();
+	return 0;
+}
+
+void exit_mfs(void)
+{
+	unregister_filesystem(&mfs_fs_type);
+}
+
+int
+mfs_walk_init_root(struct nameidata *nd)
+{
+	int ret;
+
+	lock_kernel();
+	if(mfs_root)
+	{
+		nd->dentry = dget(mfs_root);
+		nd->mnt = mntget(mfs_mnt);
+		ret = 1;
+	}
+	else
+		ret = 0;
+	unlock_kernel();
+	return(ret);
+}
+
+int
+is_mfs_root(struct nameidata *nd)
+{
+	return(nd->dentry == mfs_root && nd->mnt == mfs_mnt);
+}
+
+void
+mfs_report_used(void)
+{
+	struct dentry *root;
+	struct dentry *dp;
+	struct list_head *next;
+	unsigned long timo = jiffies + 10 * HZ;
+	struct mfs_dinfo *i;
+	
+	loop:
+	if(!mfs_super)
+		return;
+	root = mfs_super->s_root;
+	dget(root);
+	for(next = root->d_subdirs.next ; next != &root->d_subdirs &&
+				time_before(jiffies, timo) ; next = next->next)
+	{
+		dp = list_entry(next, struct dentry, d_child);
+		if((i = dp->d_fsdata) &&
+			time_before(i->latest + MFS_REPORT_TIME, jiffies))
+		{
+			dget(dp);
+			i->latest = jiffies;
+			if(mfs_touch_handle(i->pe, i->handle))
+				i->pe = MFS_BAD_PE;
+			dput(dp);
+			goto loop;
+		}
+	}
+	dput(root);
+}
+
+int
+mfs_client_daemon(void *nothing)
+{
+	struct task_struct *p = current;
+
+	lock_kernel();
+	common_daemon_setup("oMFS_gc", 0);
+	while(1)
+	{
+		mfs_report_used();
+		mfs_monitor_client_contacts();
+		p->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(20 * HZ);
+		flush_signals(p);
+	}
+}
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/Makefile linux-openmosix/fs/mfs/Makefile
--- linux/fs/mfs/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/Makefile	2002-02-14 11:35:25.000000000 +0100
@@ -0,0 +1,8 @@
+#
+# Makefile for the Linux MOSIX mfs filesystem routines.
+#
+
+O_TARGET := mfs.o
+obj-y    := file.o convert.o complete.o server.o client.o scontact.o ccontact.o socket.o count.o
+
+include $(TOPDIR)/Rules.make
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/scontact.c linux-openmosix/fs/mfs/scontact.c
--- linux/fs/mfs/scontact.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/scontact.c	2002-09-18 09:20:02.000000000 +0200
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh.
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/mfs.h>
+#include <linux/mfs_socket.h>
+#include <hpc/routines.h>
+
+#define	MFS_MINSERVERS	2
+#define	MFS_MAXDEDICATED 6
+#define	MFS_MAXSERVERS	14
+#define	MFS_CONTACT_KEEPALIVE (60*HZ)
+#define	MFS_MAXQ	100	/* do not increase - leave space under 128 */
+
+spinlock_t mfs_servq_lock = SPIN_LOCK_UNLOCKED;
+
+struct task_struct *mfs_main_server_task;
+int n_mfs_servers;
+int mfs_total_services;
+
+struct mfs_server_contact
+{
+	struct mfs_server_contact *next;
+	struct socket *sock;
+	int caller;
+	int serial;
+	unsigned long last_use;
+};
+
+/* service queue: */
+struct mfs_server_contact *queued_services;
+struct mfs_server_contact *last_queued_service;
+int mfs_qlen;
+
+/* past connections that are still kept open: */
+struct mfs_server_contact *mfs_idle_connections;
+
+/* servers waiting: */
+DECLARE_WAIT_QUEUE_HEAD(wait_to_serve_mfs);
+atomic_t waiting_to_serve_mfs = ATOMIC_INIT(0);
+int mfs_idle_servers;
+
+/* main server waiting: */
+DECLARE_WAIT_QUEUE_HEAD(wait_for_mfs_calls);
+volatile int waiting_for_mfs_calls;
+volatile int mfs_has_new_calls;
+
+int
+mfs_server_send(struct mfs_server_contact *s, int type, void *header, int hdln,
+			void *dat1, int len1, void *dat2, int len2)
+{
+	return(mfs_send(s->sock, 0, s->serial, type,
+					header, hdln, dat1, len1, dat2, len2));
+}
+
+int
+mfs_server_receive(struct mfs_server_contact *s,
+					void **header, void **dat1, void **dat2)
+{
+	return(mfs_receive(s->sock, MFS_MUST_MATCH, &s->serial, NULL,
+							header, dat1, dat2));
+}
+
+void
+mfs_serve1(struct mfs_server_contact *s)
+{
+	int type, more, changed;
+	void *header;
+	void *dat1;
+	void *dat2;
+	static int n_dedicated;
+
+	mfs_set_main_ownership(s->sock, 0);
+	again:
+	type = mfs_receive(s->sock, MFS_FIRST_RECEIVE, &s->serial, NULL,
+							&header, &dat1, &dat2);
+	if(type == MFS_CLOSE || type < MFS_NONE)
+	{
+		mfs_close_socket(s->sock);
+if(mfs_debug > 1)
+printk("mfs_serve1: closing socket %x by client request!\n", (int)s->sock);
+		s->sock = NULL;
+	}
+	else
+		mfs_serve(s, type, header, dat1, dat2);
+	if(header)
+		kfree(header);
+	if(!s->sock)
+		return;
+	spin_lock(&mfs_servq_lock);
+	more = 1 + (n_dedicated < MFS_MAXDEDICATED);
+	if(more == 2)
+		n_dedicated++;
+	spin_unlock(&mfs_servq_lock);
+	changed = mfs_set_main_ownership(s->sock, more);
+	if(more == 2)
+	{
+		spin_lock(&mfs_servq_lock);
+		n_dedicated--;
+		spin_unlock(&mfs_servq_lock);
+	}
+	if(!changed)
+	{
+		if(mfs_debug)
+			printk("mfs_serv1: serving in chain!\n");
+		goto again;
+	}
+}
+
+/* trim_idle_connections must be called with mfs_servq_lock! */
+void
+trim_idle_connections(void)
+{
+#define	HOGS_CONSIDERED	10
+	struct mfs_server_contact *s, *prev, *next, *dispose = NULL;
+	unsigned int nhogs = 0;
+	int hogpe[HOGS_CONSIDERED];
+	int hogs[HOGS_CONSIDERED];
+	unsigned int i, least;
+	int caller, leastval, penalty, bar;
+	unsigned int disposed = 0;
+
+	/* compile the hog-table */
+	for(prev = NULL, s = mfs_idle_connections ; s ; prev = s , s = s->next)
+	{
+		caller = s->caller;
+		for(i = 0 ; i < nhogs ; i++)
+		if(hogpe[i] == caller)
+		{
+			hogs[i]++;
+			goto next_connection;
+		}
+		if(i < HOGS_CONSIDERED)
+		{
+			hogpe[i] = caller;
+			hogs[i] = 1;
+			nhogs++;
+			goto next_connection;
+		}
+		leastval = 10000000;
+		least = 0;
+		for(i = 0 ; i < HOGS_CONSIDERED ; i++)
+		if(hogs[i] < leastval)
+		{
+			least = i;
+			leastval = hogs[i];
+		}
+		hogpe[least] = caller;
+		hogs[least] = 1;
+		next_connection:;
+	}
+	/* calculate penalties, store in the "serial" field (unused for idle) */
+	/* penalty increases for old sockets and for hogs */
+	for(s = mfs_idle_connections ; s ; s = s->next)
+	{
+		penalty = abs((long)jiffies - (long)(s->last_use));
+		if(penalty > 2*MFS_CONTACT_KEEPALIVE)	/* avoid overflow */
+			penalty = 2*MFS_CONTACT_KEEPALIVE;
+		penalty = mfs_total_services * penalty / MFS_CONTACT_KEEPALIVE; 
+		caller = s->caller;
+		for(i = 0 ; i < nhogs ; i++)
+		if(hogpe[i] == caller)
+		{
+			penalty *= hogs[i];
+			break;
+		}
+		s->serial = penalty;
+	}
+	/* collect old sockets, more aggressively as services are exhausted */
+	for(bar = MFS_MAXQ/2 ;
+		mfs_idle_connections && mfs_total_services - disposed > MFS_MAXQ
+							; bar = bar * 2 / 3)
+	for(prev = NULL, s = mfs_idle_connections ; s ; )
+	if(s->serial >= bar)
+	{
+		next = s->next;
+		if(prev)
+			prev->next = next;
+		else
+			mfs_idle_connections = next;
+if(mfs_debug)
+printk("trim_idle_connections: penalty=%d, closing socket %x\n", s->serial,
+(int)s->sock);
+		s->next = dispose;
+		dispose = s;
+		disposed++;
+		s = next;
+	}
+	else
+	{
+		prev = s;
+		s = s->next;
+	}
+	/* dispose of those sockets */
+	mfs_total_services -= disposed;
+	spin_unlock(&mfs_servq_lock);
+	for(; dispose ; dispose = next)
+	{
+		next = dispose->next;
+		mfs_close_socket(dispose->sock);
+		kfree(dispose);
+	}
+	spin_lock(&mfs_servq_lock);
+}
+
+void
+mfs_recycle_service(struct mfs_server_contact *s)
+{
+	spin_lock(&mfs_servq_lock);
+	if(!s->sock)
+	{
+		mfs_total_services--;
+		spin_unlock(&mfs_servq_lock);
+		kfree(s);
+		return;
+	}
+	if(mfs_total_services >= MFS_MAXQ)
+		trim_idle_connections();
+	if(mfs_total_services < MFS_MAXQ)
+	{
+		s->last_use = jiffies;
+		s->next = mfs_idle_connections;
+		mfs_idle_connections = s;
+		spin_unlock(&mfs_servq_lock);
+		return;
+	}
+if(mfs_debug)
+printk("mfs_recycle_service: closing socket %x (too many connections already)\n", (int)s->sock);
+	mfs_total_services--;
+	spin_unlock(&mfs_servq_lock);
+	mfs_close_socket(s->sock);
+	kfree(s);
+}
+
+int
+mfs_server(void *nothing)
+{
+	struct mfs_server_contact *s;
+	struct task_struct *p = current;
+	extern struct task_struct *child_reaper;
+
+	strcpy(p->comm, "mfs_server");
+	p->exit_signal = SIGCHLD;
+	p->p_opptr = child_reaper;
+	write_lock_irq(&tasklist_lock);
+	REMOVE_LINKS(p);
+	p->p_pptr = p->p_opptr;
+	SET_LINKS(p);
+	p->fs->umask = 0;
+	write_unlock_irq(&tasklist_lock);
+	set_fs(KERNEL_DS);	/* all server I/O always to kernel */
+	spin_lock(&mfs_servq_lock);
+	mfs_idle_servers--;
+	while(1)
+	{
+		while((s = queued_services))
+		{
+			mfs_qlen--;
+			if(!(queued_services = s->next))
+				last_queued_service = NULL;
+			spin_unlock(&mfs_servq_lock);
+			mfs_serve1(s);
+			mfs_recycle_service(s);
+			spin_lock(&mfs_servq_lock);
+		}
+		if(n_mfs_servers > MFS_MINSERVERS || MFS_PE == MFS_UNKNOWN_PE)
+		{
+			n_mfs_servers--;
+			spin_unlock(&mfs_servq_lock);
+			return(0);		/* and exit */
+		}
+		mfs_idle_servers++;
+		atomic_inc(&waiting_to_serve_mfs);
+		spin_unlock(&mfs_servq_lock);
+		interruptible_sleep_on(&wait_to_serve_mfs);
+		if(p->sigpending)
+		{
+			spin_lock_irq(&p->sigmask_lock);
+			flush_signals(p);
+			spin_unlock_irq(&p->sigmask_lock);
+		}
+		spin_lock(&mfs_servq_lock);
+		atomic_dec(&waiting_to_serve_mfs);
+		mfs_idle_servers--;
+	}
+}
+
+void
+mfs_new_request_arrived(void)
+{
+if(mfs_debug > 1)
+printk("mfs_new_request_arrived!\n");
+	mfs_has_new_calls = 1;
+	if(waiting_for_mfs_calls)
+		wake_up_interruptible(&wait_for_mfs_calls);
+}
+
+/* mfs_add_to_queue must be called with mfs_servq_lock! */
+static inline void
+mfs_add_to_queue(struct mfs_server_contact *s)
+{
+	s->next = NULL;
+	mfs_qlen++;
+	if(last_queued_service)
+		last_queued_service->next = s;
+	else
+		queued_services = s;
+	last_queued_service = s;
+	if(atomic_read(&waiting_to_serve_mfs))
+		wake_up_interruptible(&wait_to_serve_mfs);
+}
+
+int
+mfs_main_server(void *nothing)
+{
+	register struct task_struct *p = current;
+	struct socket *mainsock = NULL, *sock;
+	struct mfs_server_contact *s, *prev, *next, *dispose = NULL;
+	int caller;
+	unsigned long last_trim = 0;
+	int client_pid = 0;
+	int success;
+	DECLARE_WAITQUEUE(wait, p);
+
+	mfs_main_server_task = p;
+	common_daemon_setup("oMfs_main_server", 1);
+	while(client_pid <= 0 || !mainsock)
+	{
+		if(client_pid <= 0)
+			client_pid = kernel_thread(mfs_client_daemon, NULL, 0);
+		if(!mainsock)
+			mainsock = mfs_open_main_socket();
+		if(client_pid > 0 && mainsock)
+			break;
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(MFS_CONTACT_KEEPALIVE / 3);
+		spin_lock_irq(&p->sigmask_lock);
+		flush_signals(p);
+		spin_unlock_irq(&p->sigmask_lock);
+	}
+	mainloop:
+	spin_lock(&mfs_servq_lock);
+	if(MFS_PE != MFS_UNKNOWN_PE)
+	while(n_mfs_servers < MFS_MINSERVERS)
+	{
+		n_mfs_servers++;
+		mfs_idle_servers++;
+		spin_unlock(&mfs_servq_lock);
+		success = (kernel_thread(mfs_server, NULL, 0) >= 0);
+		spin_lock(&mfs_servq_lock);
+		if(!success)
+		{
+			n_mfs_servers--;
+			mfs_idle_servers--;
+			break;
+		}
+	}
+	if(mfs_has_new_calls)
+	{
+		spin_unlock(&mfs_servq_lock);
+		mfs_has_new_calls = 0;
+		while((sock = mfs_new_connection(mainsock, &caller)))
+		if(MFS_PE == MFS_UNKNOWN_PE)
+			mfs_close_socket(sock);
+		else
+		{
+if(mfs_debug)
+printk("mfs_main_server: new connection=%x (mainsock=%x)\n", (int)sock, (int)mainsock);
+			if((s = (struct mfs_server_contact *)kmalloc(
+				sizeof(struct mfs_server_contact), GFP_KERNEL)))
+			{
+				spin_lock(&mfs_servq_lock);
+				mfs_total_services++;
+				s->sock = sock;
+				s->caller = caller;
+				mfs_add_to_queue(s);
+				spin_unlock(&mfs_servq_lock);
+			}
+			else
+				mfs_close_socket(sock);
+		}
+		spin_lock(&mfs_servq_lock);
+		for(prev = NULL, s = mfs_idle_connections ; s ; )
+		if(MFS_PE == MFS_UNKNOWN_PE || mfs_socket_has_data(s->sock))
+		{
+			next = s->next;
+			if(prev)
+				prev->next = next;
+			else
+				mfs_idle_connections = next;
+			if(MFS_PE == MFS_UNKNOWN_PE)
+			{
+				s->next = dispose;
+				dispose = s;
+				mfs_total_services--;
+			}
+			else
+			{
+if(mfs_debug)
+printk("mfs_main_server: new request on old sock (%x)\n", (int)s->sock);
+				mfs_add_to_queue(s);
+			}
+			s = next;
+		}
+		else
+		{
+			prev = s;
+			s = s->next;
+		}
+		while(mfs_qlen > mfs_idle_servers &&
+			n_mfs_servers < MFS_MAXSERVERS &&
+			MFS_PE != MFS_UNKNOWN_PE)
+		{
+if(mfs_debug > 1)printk("mfs_main_server adding a server\n");
+			n_mfs_servers++;
+			mfs_idle_servers++;
+			spin_unlock(&mfs_servq_lock);
+			success = (kernel_thread(mfs_server, NULL, 0) >= 0);
+			spin_lock(&mfs_servq_lock);
+			if(!success)
+			{
+				n_mfs_servers--;
+				mfs_idle_servers--;
+				if(!n_mfs_servers)
+				{
+					/* too bad - just shut all down */
+					while((s = queued_services))
+					{
+						queued_services = s->next;
+						mfs_qlen--;
+						mfs_total_services--;
+						spin_unlock(&mfs_servq_lock);
+						mfs_close_socket(s->sock);
+						kfree(s);
+						spin_lock(&mfs_servq_lock);
+					}
+				}
+				break;
+			}
+		}
+	}
+	if(abs((long)jiffies - (long)last_trim) > HZ)
+	{
+		for(prev = NULL, s = mfs_idle_connections ; s ; )
+		if(abs((long)jiffies - (long)(s->last_use)) >=
+							MFS_CONTACT_KEEPALIVE)
+		{
+			next = s->next;
+			if(prev)
+				prev->next = next;
+			else
+				mfs_idle_connections = next;
+			if(mfs_socket_has_data(s->sock))
+				mfs_add_to_queue(s);
+			else
+			{
+if(mfs_debug > 1)
+printk("mfs_main_server: closing old socket %x\n", (int)s->sock);
+				s->next = dispose;
+				dispose = s;
+				mfs_total_services--;
+			}
+			s = next;
+		}
+		else
+		{
+			prev = s;
+			s = s->next;
+		}
+	}
+	spin_unlock(&mfs_servq_lock);
+	last_trim = jiffies;
+	for(; dispose ; dispose = next)
+	{
+		next = dispose->next;
+		mfs_close_socket(dispose->sock);
+		kfree(dispose);
+	}
+	if(!mfs_has_new_calls)
+	{
+		add_wait_queue(&wait_for_mfs_calls, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+		waiting_for_mfs_calls = 1;
+		if(!mfs_has_new_calls)
+			schedule_timeout(MFS_CONTACT_KEEPALIVE / 3);
+		waiting_for_mfs_calls = 0;
+		remove_wait_queue(&wait_for_mfs_calls, &wait);
+		set_current_state(TASK_RUNNING);
+	}
+	spin_lock_irq(&p->sigmask_lock);
+	flush_signals(p);
+	spin_unlock_irq(&p->sigmask_lock);
+	mfs_throw_garbage();
+	goto mainloop;
+}
+
+void
+mfs_make_servers(void)
+{
+	kernel_thread(mfs_main_server, NULL, 0);
+}
+
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/server.c linux-openmosix/fs/mfs/server.c
--- linux/fs/mfs/server.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/server.c	2003-12-02 10:59:37.000000000 +0100
@@ -0,0 +1,516 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar (moshe@moshebar.com)
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s):Moshe Bar,  Amnon Shiloh.
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/slab.h>
+#include <linux/mfs.h>
+#include <linux/dirent.h>
+
+void
+unpack_credits(struct mfs_cred *cred)
+{
+	register struct task_struct *p = current;
+	register int i;
+
+	p->uid = cred->uid;
+	p->euid = cred->euid;
+	p->sgid = cred->sgid;
+	p->fsuid = cred->fsuid;
+	p->gid = cred->gid;
+	p->egid = cred->egid;
+	p->sgid = cred->sgid;
+	p->fsgid = cred->fsgid;
+	p->ngroups = cred->ngroups;
+	for(i = cred->ngroups-1 ; i >= 0 ; i--)
+		p->groups[i] = cred->groups[i];
+	p->cap_effective = (p->cap_effective & ~REMOTE_CAPS) |
+						(cred->caps & REMOTE_CAPS);
+	p->mosix.whereami = cred->whereami;
+	p->mosix.deppe = cred->deppe;
+}
+/* Ported to oM by Moshe Bar */ 
+void
+mfs_serve_statfs(struct mfs_server_contact *con, struct mfs_request_statfs *s)
+
+{
+	struct mfs_reply_statfs r; /* by Shiloh and Moshe Bar*/
+	unpack_credits(&s->cred);
+	r.result = mfs_bh_statfs(s->handle, &r.stat); /*run bottom half part of syscall */
+	 mfs_server_send(con, MFS_REPLY_STATFS, &r, sizeof(r), NULL, 0,NULL, 0);
+}
+
+
+void
+mfs_serve_attach(struct mfs_server_contact *con,
+					struct mfs_request_attach_handle *s)
+{
+	struct mfs_reply_attach_handle r;
+
+	r.result = mfs_low_attach_handle(s->handle);
+	mfs_server_send(con, MFS_REPLY_ATTACH_HANDLE, &r, sizeof(r), NULL, 0,
+								NULL, 0);
+}
+
+void
+mfs_serve_touch(struct mfs_server_contact *con,
+					struct mfs_request_touch_handle *s)
+{
+	struct mfs_reply_touch_handle r;
+
+	r.result = mfs_low_touch_handle(s->handle);
+	mfs_server_send(con, MFS_REPLY_TOUCH_HANDLE, &r, sizeof(r), NULL, 0,
+								NULL, 0);
+}
+
+void
+mfs_serve_open(struct mfs_server_contact *con, struct mfs_request_open *s)
+{
+	struct mfs_reply_open r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_open(s->handle, &s->inode, &s->file);
+	r.inode = s->inode;
+	r.file = s->file;
+	mfs_server_send(con, MFS_REPLY_OPEN, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+void
+mfs_serve_close(struct mfs_server_contact *con, struct mfs_request_open *s)
+{
+	struct mfs_reply_open r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_close(s->handle, &s->inode, &s->file);
+	r.inode = s->inode;
+	r.file = s->file;
+	mfs_server_send(con, MFS_REPLY_CLOSE, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+void
+mfs_serve_llseek(struct mfs_server_contact *con, struct mfs_request_llseek *s)
+{
+	struct mfs_reply_llseek r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_llseek(s->handle, &s->file, s->offset, s->origin);
+	r.file = s->file;
+	mfs_server_send(con, MFS_REPLY_LLSEEK, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+/* we also need to do read-ahead soon Moshe Bar*/
+void
+mfs_serve_read(struct mfs_server_contact *con, struct mfs_request_read *s)
+{
+	struct mfs_reply_read r;
+	int n;
+	size_t count = s->count;
+	size_t cnt, sent = 0;
+	char *buf = NULL;
+	int ret = 0;
+	size_t max;
+	char smallbuf[4];
+	struct mfs_interim_data d;
+
+	for(max = s->count > 16384 ? 16384 : s->count ; max > sizeof(smallbuf) ;
+								max >>= 1)
+	if((buf = (char *)kmalloc(max, GFP_KERNEL)))
+		break;
+	if(max <= sizeof(smallbuf))
+	{
+		buf = smallbuf;
+		max = sizeof(smallbuf);
+	}
+	unpack_credits(&s->cred);
+	while(count > 0)
+	{
+		cnt = count;
+		if(cnt > max)
+			cnt = max;
+		n = mfs_low_read(s->handle, &s->file, buf, cnt, &s->pos);
+		if(n < cnt || cnt == count)
+		{
+			if(n < 0)
+				ret = n;
+			else
+				ret += n;
+			break;
+		}
+		ret += cnt;
+		d.count = cnt;
+		if(mfs_server_send(con, MFS_INTERIM_DATA, (void *)&d, sizeof(d),
+			(void *)buf, cnt, NULL, 0))
+			goto free_buf;
+		sent += cnt;
+		count -= cnt;
+	}
+	r.file = s->file;
+	r.ppos = s->pos;
+	r.result = ret;
+	r.datalen = (ret > 0 && ret > sent) ? ret - sent : 0;
+	mfs_server_send(con, MFS_REPLY_READ, &r, sizeof(r),
+				r.datalen ? buf : NULL, r.datalen, NULL, 0);
+	free_buf:
+	if(max != sizeof(smallbuf))
+		kfree(buf);
+}
+
+void
+mfs_serve_write(struct mfs_server_contact *con, struct mfs_request_write *s,
+								void *buf)
+{
+	struct mfs_reply_write r;
+	struct mfs_interim_data *i = NULL;
+	ssize_t n;
+	size_t count = s->count;
+	size_t cnt;
+	struct task_struct *p = current;
+
+	unpack_credits(&s->cred);
+	if(signal_pending(p))
+	{
+		spin_lock_irq(&p->sigmask_lock);
+		flush_signals(p);
+		spin_unlock_irq(&p->sigmask_lock);
+	}
+	cnt = s->datalen;
+	if(cnt < count)
+		mfs_server_send(con, MFS_CONTINUE, NULL, 0, NULL, 0, NULL, 0);
+	r.result = mfs_low_write(s->handle, &s->file, buf, cnt,&s->pos,s->flim);
+	/* in Linux, an append-"write", once started is not broken even if
+	 * another process interfered */
+	s->file.f_flags &= ~O_APPEND;
+	if(r.result == cnt)
+	while(r.result < count)
+	{
+		if(i)
+			kfree(i);
+		if((n = mfs_server_receive(con, (void **)&i, &buf, NULL)) < 0)
+			return;
+		if(n == MFS_STOP)
+		{
+			r.result = -EFAULT;
+			break;
+		}
+		if(n != MFS_INTERIM_DATA)
+		{
+			printk("mfs_serve_write: unexpected type: %d\n", n);
+			if(i)
+				kfree(i);
+			return;
+		}
+		n = mfs_low_write(s->handle, &s->file, buf, i->count, &s->pos,
+								s->flim);
+		r.result += n;
+		if(n < i->count)
+		{
+			if(n < 0)
+				r.result = n;
+			break;
+		}
+	}
+	if(i)
+		kfree(i);
+	r.file = s->file;
+	r.ppos = s->pos;
+	if(sigismember(&p->pending.signal, SIGXFSZ))
+	{
+		spin_lock_irq(&p->sigmask_lock);
+		flush_signals(p);
+		spin_unlock_irq(&p->sigmask_lock);
+		r.hadsigxfsz = 1;
+	}
+	else
+		r.hadsigxfsz = 0;
+	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
+	mfs_server_send(con, MFS_REPLY_WRITE, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+struct mfs_serve_readdir_callback
+{
+	struct mfs_server_contact *con;
+	void *buf, *bufp;
+	int buflen;
+	int policy;
+	int maxbytes;
+};
+
+int
+mfs_serve_flush_dirs(struct mfs_serve_readdir_callback *cb)
+{
+	struct mfs_interim_data i;
+	struct mfs_interim_readdir *ri;
+	int t, err;
+
+	i.count = cb->bufp - cb->buf;
+	if(i.count == 0)
+		return(0);
+	if(mfs_server_send(cb->con, MFS_INTERIM_DATA, (void *)&i, sizeof(i),
+						cb->buf, i.count, NULL, 0))
+		return(-EINVAL);
+	t = mfs_server_receive(cb->con, (void **)&ri, NULL, NULL);
+	if(t == MFS_INTERIM_READDIR)
+		err = ri->error;
+	else
+		err = -EINVAL;
+	if(ri)
+		kfree(ri);
+	if(err)
+		return(err);
+	cb->bufp = cb->buf;
+	return(0);
+}
+
+int
+mfs_serve_filldir(void *__cb, const char *name, int namelen, loff_t offset,
+						ino_t ino, unsigned int type)
+{
+	struct mfs_serve_readdir_callback *cb = __cb;
+	int reclen;
+	int err;
+
+	switch(cb->policy)
+	{
+		case MFS_READDIR_JUSTONE:
+			if(!cb->maxbytes)
+				return(-EINVAL);
+			cb->maxbytes = 0;
+			break;
+		case MFS_READDIR_GETDENTS:
+			reclen = (offsetof(struct dirent, d_name[0]) + namelen +
+				1 + sizeof(long)-1) & ~(sizeof(long)-1);
+			if(reclen > cb->maxbytes)
+				return(-EINVAL);
+			cb->maxbytes -= reclen;
+			break;
+		case MFS_READDIR_GETDENTS64:
+			reclen = (offsetof(struct dirent64, d_name[0]) +
+				namelen + 1 + sizeof(u64)-1) & ~(sizeof(u64)-1);
+			if(reclen > cb->maxbytes)
+				return(-EINVAL);
+			cb->maxbytes -= reclen;
+			break;
+	}
+	reclen = sizeof(ino_t) + sizeof(loff_t) + sizeof(unsigned int) +
+						sizeof(short) + namelen;
+	if(reclen > cb->buflen - (cb->bufp - cb->buf))
+	{
+		if(cb->bufp == cb->buf || (cb->policy != MFS_READDIR_GETDENTS
+				&& cb->policy != MFS_READDIR_GETDENTS64))
+		{
+			/* should not happen - we allocated at least dirent64 */
+			printk("mfs_serve_filldir: buffer not sufficient\n");
+			return(-EINVAL);
+		}
+		if((err = mfs_serve_flush_dirs(cb)))
+			return(err);
+	}
+	*((ino_t *)cb->bufp)++ = ino;
+	*((loff_t *)cb->bufp)++ = offset;
+	*((unsigned int *)cb->bufp)++ = type;
+	*((short *)cb->bufp)++ = namelen;
+	memcpy(cb->bufp, (void *)name, namelen);
+	cb->bufp += namelen;
+	if(cb->policy == MFS_READDIR_UNKNOWN)
+		return(mfs_serve_flush_dirs(cb));
+	else
+		return(0);
+}
+
+void
+mfs_serve_readdir(struct mfs_server_contact *con, struct mfs_request_readdir *s)
+{
+	struct mfs_reply_readdir r;
+	int ret = 0;
+	struct mfs_serve_readdir_callback cb;
+	int multi = (s->policy == MFS_READDIR_GETDENTS ||
+					s->policy == MFS_READDIR_GETDENTS64);
+	int duma, dumb;
+
+	for(cb.buflen = multi ? 16384 : sizeof(struct dirent64) ;
+		cb.buflen >= sizeof(struct dirent64) ; cb.buflen >>= 1)
+	if((cb.buf = (char *)kmalloc(cb.buflen, GFP_KERNEL)))
+		break;
+	cb.bufp = cb.buf;
+	cb.policy = s->policy;
+	cb.maxbytes = multi ? s->maxbytes : 1;
+	cb.con = con;
+	unpack_credits(&s->cred);
+	if(cb.buflen < sizeof(struct dirent64))
+		ret = -ENOMEM;
+	else
+		ret = mfs_low_readdir(s->handle, &s->file, (void *)&cb, 
+					mfs_serve_filldir, &duma, &dumb);
+	r.file = s->file;
+	r.result = ret;
+	r.datalen = cb.bufp - cb.buf;
+	mfs_server_send(con, MFS_REPLY_READDIR, &r, sizeof(r),
+				r.datalen ? cb.buf : NULL, r.datalen, NULL, 0);
+	if(cb.buflen >= sizeof(struct dirent64))
+		kfree(cb.buf);
+}
+
+void
+mfs_serve_ioctl(struct mfs_server_contact *con, struct mfs_request_ioctl *s)
+{
+	struct mfs_reply_ioctl r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_ioctl(s->handle, &s->file, s->cmd, s->arg, s->size,
+								&s->data);
+	r.file = s->file;
+	r.data = s->data;
+	mfs_server_send(con, MFS_REPLY_IOCTL, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+void
+mfs_serve_fsync(struct mfs_server_contact *con, struct mfs_request_fsync *s)
+{
+	struct mfs_reply_fsync r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_fsync(s->handle, &s->file, s->datasync);
+	r.file = s->file;
+	mfs_server_send(con, MFS_REPLY_FSYNC, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+void
+mfs_serve_revalidate(struct mfs_server_contact *con,
+					struct mfs_request_revalidate *s)
+{
+	struct mfs_reply_revalidate r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_revalidate(s->handle, &r.iinfo);
+	mfs_server_send(con, MFS_REPLY_REVALIDATE, &r, sizeof(r), NULL, 0, NULL, 0);
+}
+
+void
+mfs_serve_express(struct mfs_server_contact *con, struct mfs_request_express *s,
+						char *name, void *more_data)
+{
+	struct mfs_reply_express r;
+	char *newname;
+
+	unpack_credits(&s->cred);
+	r.handle = s->handle;
+	r.complete = s->complete;
+	if(r.complete.more_data)
+		r.complete.more_data = more_data;
+	r.result = mfs_low_express_lookup(&r.handle, name, s->follow,
+			s->link_count, s->total_link_count, &r.iinfo,
+			&newname, &r.complete);
+	r.namelen = (r.result || !newname) ? 0 : strlen(newname) + 1;
+	mfs_server_send(con, MFS_REPLY_EXPRESS, &r, sizeof(r),
+				r.namelen ? (void *)newname : NULL, r.namelen,
+				r.complete.more_data, r.complete.more_data_len);
+	if(r.namelen)
+		kfree(newname);
+	if(r.complete.more_data)
+		kfree(r.complete.more_data);
+}
+
+void
+mfs_serve_checkpath(struct mfs_server_contact *con,
+						struct mfs_request_checkpath *s)
+{
+	struct mfs_reply_checkpath r;
+	char *path;
+
+	unpack_credits(&s->cred);
+	path = mfs_low_check_path(s->handle);
+	r.namelen = path ? strlen(path)+1 : 0;
+	mfs_server_send(con, MFS_REPLY_CHECKPATH, &r, sizeof(r),
+		r.namelen ? (void *)path : NULL, r.namelen, NULL, 0);
+	if(path)
+		kfree(path);
+}
+
+void
+mfs_serve_setattr(struct mfs_server_contact *con, struct mfs_request_setattr *s)
+{
+	struct mfs_reply_setattr r;
+
+	unpack_credits(&s->cred);
+	r.result = mfs_low_setattr(s->handle, &s->attr);
+	mfs_server_send(con, MFS_REPLY_SETATTR, &r, sizeof(r), NULL, 0,
+								NULL, 0);
+}
+
+void
+mfs_serve(struct mfs_server_contact *con, int type, void *header, void *dat1,
+								void *dat2)
+{
+	switch(type)
+	{
+	case MFS_REQUEST_ATTACH_HANDLE:
+		mfs_serve_attach(con,
+				(struct mfs_request_attach_handle *)header);
+		break;
+	case MFS_REQUEST_TOUCH_HANDLE:
+		mfs_serve_touch(con,(struct mfs_request_touch_handle *)header);
+		break;
+	case MFS_REQUEST_DISPOSE_HANDLE:
+		mfs_low_dispose_handle(
+			((struct mfs_request_dispose_handle *)header)->handle);
+		mfs_server_send(con, MFS_CONTINUE, NULL, 0, NULL, 0, NULL,0);
+		break;
+	case MFS_REQUEST_LLSEEK:
+		mfs_serve_llseek(con, (struct mfs_request_llseek *)header);
+		break;
+	case MFS_REQUEST_READ:
+		mfs_serve_read(con, (struct mfs_request_read *)header);
+		break;
+	case MFS_REQUEST_WRITE:
+		mfs_serve_write(con, (struct mfs_request_write *)header, dat1);
+		break;
+	case MFS_REQUEST_OPEN:
+		mfs_serve_open(con, (struct mfs_request_open *)header);
+		break;
+	case MFS_REQUEST_CLOSE:
+		mfs_serve_close(con, (struct mfs_request_open *)header);
+		break;
+	case MFS_REQUEST_READDIR:
+		mfs_serve_readdir(con, (struct mfs_request_readdir *)header);
+		break;
+	case MFS_REQUEST_IOCTL:
+		mfs_serve_ioctl(con, (struct mfs_request_ioctl *)header);
+		break;
+	case MFS_REQUEST_FSYNC:
+		mfs_serve_fsync(con, (struct mfs_request_fsync *)header);
+		break;
+	case MFS_REQUEST_REVALIDATE:
+		mfs_serve_revalidate(con,
+				(struct mfs_request_revalidate *)header);
+		break;
+	case MFS_REQUEST_EXPRESS:
+		mfs_serve_express(con, (struct mfs_request_express *)header,
+							(char *)dat1, dat2);
+		break;
+	case MFS_REQUEST_CHECKPATH:
+		mfs_serve_checkpath(con,
+					(struct mfs_request_checkpath *)header);
+		break;
+	case MFS_REQUEST_SETATTR:
+		mfs_serve_setattr(con, (struct mfs_request_setattr *)header);
+		break;
+	case MFS_REQUEST_STATFS:
+		mfs_serve_statfs(con, (struct mfs_request_statfs *)header);
+		break;
+	default:
+		printk("mfs_serve: type %d unimplemented\n", type);
+	}
+}
+
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/mfs/socket.c linux-openmosix/fs/mfs/socket.c
--- linux/fs/mfs/socket.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/fs/mfs/socket.c	2004-02-05 02:48:26.000000000 +0100
@@ -0,0 +1,505 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ * used code by Oren Laadan.
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_MOSIX_FS
+#include <net/tcp.h>
+#include <linux/hpc.h>
+#include <linux/slab.h>
+#include <linux/mfs.h>
+#include <linux/mfs_socket.h>
+#include <linux/poll.h>
+#include <hpc/routines.h>
+#include <hpc/protocol.h>
+
+/* meanwhile, we assume openMosix uses only IPv4 addresses */
+/* when openMosix can use IPv6, this file must also be upgraded */
+
+#define	MFS_CONNECT_TIMO	(10*HZ)
+#define	MFS_RECEIVE_TIMO	(10*HZ)
+
+int
+mfs_common_socket_setup(struct socket *sock)
+{
+	mm_segment_t oldfs = get_fs();
+	int error = 0;
+	int val;
+
+	set_fs(KERNEL_DS);
+	val = 32768+1024;
+	sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, sizeof(val));
+	sock_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, sizeof(val));
+	val = MOSIX_CONNECTION_KEEPALIVE_INTERVAL;
+	sock->ops->setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL,
+						(char *) &val, sizeof(val));
+	val = MOSIX_CONNECTION_KEEPALIVE_MAXTRIES;
+	sock->ops->setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT,
+						(char *) &val, sizeof(val));
+	val = MOSIX_CONNECTION_KEEPALIVE_TOTAL;
+	sock->ops->setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE,
+						(char *) &val, sizeof(val));
+	val = 1;
+	sock->ops->setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+						(char *)&val, sizeof(val));
+	error = sock_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+						(char *)&val, sizeof(val));
+	set_fs(oldfs);
+	set_bit(SOCK_INTER_MOSIX, &sock->flags);
+	return(error);
+}
+
+struct socket *
+mfs_open_main_socket(void)
+{
+	struct socket *sock;
+	struct sockaddr_in addr;
+
+	deeper_sleep();
+
+	memset(&addr, 0, sizeof(struct sockaddr_in));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = INADDR_ANY;
+	addr.sin_port = MFS_MAIN_PORT;
+	if(sock_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock))
+		goto failed;
+
+	if(mfs_common_socket_setup(sock))
+	{
+		goto failed;
+	}
+
+	if(sock->ops->bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
+	{
+		goto failed;
+	}
+	if(sock->ops->listen(sock, SOMAXCONN))
+	{
+		goto failed;
+	}
+
+	lighter_sleep();
+	spin_lock_irq(&skown_lock);
+	sock->sk->owner = mfs_main_server_task;
+	spin_unlock_irq(&skown_lock);
+	return(sock);
+
+failed:
+	lighter_sleep();
+	if (sock)
+		sock_release(sock);
+	return(NULL);
+}
+
+struct socket *
+mfs_new_connection(struct socket *parent, int *caller)
+{
+	struct socket *sock;
+	struct mosix_addr mosaddr;
+	int val = sizeof(mosaddr.saddr);
+
+	if(!(parent->ops->poll(NULL, parent, NULL) & POLLIN))
+		return(NULL);
+	if (!(sock = sock_alloc()))
+		return(NULL);
+	sock->type = parent->type;
+	sock->ops = parent->ops;
+	if(sock->ops->accept(parent, sock, O_NONBLOCK))
+		goto failed;
+	if (sock->ops->getname(sock, &mosaddr.saddr, &val, 1))
+		goto failed;
+	if(!(*caller = net_to_mos(&mosaddr)))
+	{
+		comm_report_violation("MFS", &mosaddr.saddr);
+		goto failed;
+	}
+	if(mfs_common_socket_setup(sock))
+		goto failed;
+	spin_lock_irq(&skown_lock);
+	sock->sk->owner = mfs_main_server_task;
+	spin_unlock_irq(&skown_lock);
+	return(sock);
+	failed:
+	sock_release(sock);
+	return(NULL);
+}
+
+struct socket *
+mfs_connect_to(int to)
+{
+	struct task_struct *p = current;
+	int error;
+	struct socket *sock = NULL;
+	struct sockaddr addr;
+	unsigned long timo = MFS_CONNECT_TIMO;
+	DECLARE_WAITQUEUE(wait, p);
+
+	deeper_sleep();
+	if(!mos_to_net(to, &addr))
+	{
+		error = -EREMOTE;
+		goto failed;
+	}
+	((struct sockaddr_in *)&addr)->sin_port = MFS_MAIN_PORT;
+	if((error = sock_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)))
+		goto failed;
+	if((error = mfs_common_socket_setup(sock)))
+		goto failed;
+	sock->ops->connect(sock, &addr, sizeof(addr), O_NONBLOCK);
+	add_wait_queue(sock->sk->sleep, &wait);
+	while (sock->state != SS_CONNECTED)
+	{
+		set_current_state(TASK_INTERRUPTIBLE);
+		error = sock->ops->connect(sock, &addr, sizeof(addr),
+								O_NONBLOCK);
+		if (error != -EALREADY || (error = sock_error(sock->sk)))
+			break;
+		timo = schedule_timeout(timo);
+		if (timo <= 0)
+		{
+			error = -EAGAIN;
+			break;
+		}
+	}
+	remove_wait_queue(sock->sk->sleep, &wait);
+	set_current_state(TASK_RUNNING);
+
+	if (error)
+		goto failed;
+	if (sock->sk->err)
+	{
+		error = sock_error(sock->sk);	/* cleans error.. */
+		goto failed;
+	}
+	lighter_sleep();
+	return (sock);
+
+failed:
+	lighter_sleep();
+	if (sock)
+		sock_release(sock);
+	return (ERR_PTR(error));
+}
+
+inline int
+mfs_socket_has_data(struct socket *sock)
+{
+	return((sock->ops->poll(NULL, sock, 0) &
+				(POLLRDNORM|POLLIN|POLLHUP|POLLERR)) != 0);
+}
+
+/*
+ * "mfs_socket_is_closed" is only called by the client on inactive sockets:
+ * we never expect server-initiated data, so POLLIN implies a closed socket.
+ */
+int
+mfs_socket_is_closed(struct socket *sock)
+{
+if(mfs_debug > 1)printk("socket_is_closed(%x): poll=0x%x\n", (int)sock, sock->ops->poll(NULL, sock, NULL));
+	return((sock->ops->poll(NULL, sock, NULL) &
+						(POLLHUP|POLLERR|POLLIN)) != 0);
+}
+
+int
+mfs_send(struct socket *sock, int first, int serial, int type,
+	void *header, int hdsz, void *dat1, int dat1sz, void *dat2, int dat2sz)
+{
+	struct mfs_message_header hd;
+	struct iovec iov[5];
+	struct msghdr msg = { NULL, 0, iov, 0, NULL, 0, MSG_NOSIGNAL };
+	mm_segment_t oldfs;
+	unsigned int niov = 1;
+	int size = 0;
+	int error = -ENOMEM;
+
+	hd.serial = serial;
+	hd.first = first;
+	hd.version = MFS_VERSION;
+	hd.caller = PE;
+	hd.type = type;
+	hd.hdsz = hdsz;
+	hd.dat1sz = dat1sz;
+	hd.dat2sz = dat2sz;
+	iov[0].iov_base = &hd;
+	iov[0].iov_len = sizeof(hd);
+	if(hdsz)
+	{
+		iov[1].iov_base = header;
+		iov[1].iov_len = hdsz;
+		niov++;
+	}
+	if(dat1sz)
+	{
+		iov[niov].iov_base = dat1;
+		iov[niov++].iov_len = dat1sz;
+	}
+	if(dat2sz)
+	{
+		iov[niov].iov_base = dat2;
+		iov[niov++].iov_len = dat2sz;
+	}
+	size = sizeof(hd) + hdsz + dat1sz + dat2sz;
+	msg.msg_iovlen = niov;
+
+	deeper_sleep();
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	error = sock->ops->sendmsg(sock, &msg, size, 0);
+	set_fs(oldfs);
+	lighter_sleep();
+
+	return (error < 0 ? error : 0);
+}
+
+int
+mfs_do_receive(struct socket *sock, void *base, int len)
+{
+	struct task_struct *p = current;
+	int n = 0;
+	struct iovec iov;
+	struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0,
+				MSG_NOSIGNAL | MSG_DONTWAIT};
+	int done = 0;
+	unsigned long timo = MFS_RECEIVE_TIMO;
+	DECLARE_WAITQUEUE(wait, p);
+
+	add_wait_queue(sock->sk->sleep, &wait);
+	while(done < len)
+	{
+		set_current_state(TASK_INTERRUPTIBLE);
+		p->mosix.ignoreoldsigs = 1;
+		p->sigpending = 0;
+		if(!mfs_socket_has_data(sock))
+		{
+			if(timo <= 0)
+			{
+				len = -EPIPE;
+				break;
+			}
+			timo = schedule_timeout(timo);
+			continue;
+		}
+		iov.iov_base = (void *)((char *)base + done);
+		iov.iov_len = len - done;
+		msg.msg_iov = &iov;
+		msg.msg_iovlen = 1;
+		n = sock->ops->recvmsg(sock, &msg, len-done, msg.msg_flags, 0);
+		if (n == -EAGAIN || n == -ERESTARTSYS || n == -EINTR)
+			continue;
+		if(n <= 0)
+		{
+			len = n < 0 ? n : ECONNRESET;
+			break;
+		}
+		done += n;
+	}
+	remove_wait_queue(sock->sk->sleep, &wait);
+	set_current_state(TASK_RUNNING);
+	recalc_sigpending(p);
+	return (len);
+}
+
+int
+mfs_receive(struct socket *sock, int policy, int *serial,
+		struct mfs_message_header *preread_header,
+					void **header, void **dat1, void **dat2)
+{
+	struct mfs_message_header hd;
+	void *contents = NULL;
+	int tlen;
+	mm_segment_t oldfs;
+	int error;
+	unsigned int need_another;
+
+	deeper_sleep();
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	next_message:
+	need_another = 0;
+
+	if(preread_header && policy != MFS_JUST_HEADER)
+	{
+		hd = *preread_header;
+		preread_header = NULL;
+		error = 0;
+	}
+	else if ((error = mfs_do_receive(sock, &hd, sizeof(hd))) != sizeof(hd))
+	{
+if(mfs_debug)
+printk("%s-mfs_receive: asked for header(%d), got %d\n", desc_mostask(NULL), sizeof(hd), error);
+		if (error >= 0)
+			error = -EPIPE;
+		goto failed;
+	}
+if(mfs_debug)
+printk("%s-mfs_do_receive: asked and got header: ", desc_mostask(NULL));
+if(mfs_debug)
+printk("version=%d, first=%d, caller=%d, serial=%d, type=%d, size=%d/%d/%d\n", hd.version,hd.first, hd.caller, hd.serial, hd.type, hd.hdsz, hd.dat1sz, hd.dat2sz);
+	if(hd.version != MFS_VERSION)
+	{
+		static int limit;
+
+		if(limit++ < 5)
+		{
+			printk("MFS received request from wrong version:\n");
+			printk("Mine is %d, theirs (%d) is %d\n", MFS_VERSION,
+							hd.caller, hd.version);
+			error = -EINVAL;
+			goto failed;
+		}
+	}
+	error = 0;
+	switch(policy)
+	{
+		case MFS_JUST_HEADER:
+			if(hd.serial != *serial)
+			{
+				need_another = 1;
+				break;
+			}
+			*preread_header = hd;
+			goto done;
+		case MFS_SKIP_OTHERS:
+			if(hd.serial != *serial)
+				need_another = 1;
+			break;
+		case MFS_MUST_MATCH:
+			if(hd.first || hd.serial != *serial)
+			{
+				error = -EPIPE;
+				goto failed;
+			}
+			break;
+		case MFS_FIRST_RECEIVE:
+			if(hd.first)
+				*serial = hd.serial;
+			else
+			{
+				error = -EPIPE;
+				goto failed;
+			}
+			break;
+	}
+	tlen = hd.hdsz + hd.dat1sz + hd.dat2sz;
+
+	if (tlen)
+	{
+		if(!(contents = kmalloc(tlen, GFP_KERNEL)))
+		{
+			error = -ENOMEM;
+			goto failed;
+		}
+		if ((error = mfs_do_receive(sock, contents, tlen)) != tlen) {
+if(mfs_debug)
+printk("%s-mfs_receive: asked for body(%d), got %d\n", desc_mostask(NULL), tlen, error);
+			if (error >= 0)
+				error = -EFAULT;
+			goto failed;
+		}
+if(mfs_debug>1)
+printk("%s-mfs_receive: asked and got body(%d)\n", desc_mostask(NULL), tlen);
+	}
+	error = 0;
+
+done:
+failed:
+	lighter_sleep();
+	set_fs(oldfs);
+	if(error)
+	{
+		if(contents)
+			kfree(contents);
+		if(header)
+			*header = NULL;
+		if(dat1)
+			*dat1 = NULL;
+		if(dat2)
+			*dat2 = NULL;
+if(mfs_debug)
+printk("%s-mfs_receive: error=%d\n", desc_mostask(NULL), error);
+		return(error);
+	}
+	else if(need_another)
+	{
+		need_another = 0;
+if(mfs_debug)
+printk("%s-mfs_receive: need another!\n", desc_mostask(NULL));
+		if(contents)
+		{
+			kfree(contents);
+			contents = NULL;
+		}
+		goto next_message;
+	}
+	if(header)
+		*header = contents;
+	if(dat1)
+		*dat1 = (void *)(((char *)contents) + hd.hdsz);
+	if(dat2)
+		*dat2 = (void *)(((char *)contents) + hd.hdsz + hd.dat1sz);
+	return(hd.type);
+}
+
+int
+mfs_set_main_ownership(struct socket *sock, int main)
+{
+	int timo = HZ;
+
+	spin_lock_irq(&skown_lock);
+	if(!main)
+	{
+		sock->sk->owner = NULL;
+		spin_unlock_irq(&skown_lock);
+		return(1);
+	}
+	sock->sk->owner = current;
+	set_bit(SOCK_WAIT_MFSDATA, &sock->flags);
+	spin_unlock_irq(&skown_lock);
+	while(1)
+	{
+		current->state = TASK_INTERRUPTIBLE;
+		if(sock->ops->poll(NULL, sock, 0) & POLLIN)
+		{
+			spin_lock_irq(&skown_lock);
+			clear_bit(SOCK_WAIT_MFSDATA, &sock->flags);
+			sock->sk->owner = NULL;
+			spin_unlock_irq(&skown_lock);
+			current->state = TASK_RUNNING;
+			return(0);
+		}
+		if(main == 1 || timo <= 0)
+		{
+			spin_lock_irq(&skown_lock);
+			clear_bit(SOCK_WAIT_MFSDATA, &sock->flags);
+			sock->sk->owner = NULL;
+			current->state = TASK_RUNNING;
+			spin_unlock_irq(&skown_lock);
+			sock->sk->owner = mfs_main_server_task;
+			mfs_new_request_arrived();
+			return(1);
+		}
+		timo = schedule_timeout(timo);
+	}
+}
+
+void
+mfs_close_socket(struct socket *sock)
+{
+	spin_lock_irq(&skown_lock);
+	if(sock->sk)
+		sock->sk->owner = NULL;
+	clear_bit(SOCK_INTER_MOSIX, &sock->flags);
+	spin_unlock_irq(&skown_lock);
+	if(sock->ops)
+		sock->ops->shutdown(sock, 2);
+	sock_release(sock);
+}
+
+#endif /* CONFIG_MOSIX_FS */
diff -Naur --exclude=CVS --exclude=configs linux/fs/namei.c linux-openmosix/fs/namei.c
--- linux/fs/namei.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/namei.c	2004-02-05 10:51:20.000000000 +0100
@@ -13,6 +13,15 @@
  */
 /* [Feb-Apr 2000, AV] Rewrite to the new namespace architecture.
  */
+/* heavy changes by openMosix
+   we basically don't use the Linux name lookup services, but do it on our own since we cannot 
+   rely on dcache. 
+
+   This part is old and needs to be rewritten
+
+   Moshe Bar
+
+*/
 
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -26,6 +35,15 @@
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#include <linux/proc_fs.h>
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#define	replaced_name	name_left
+#endif /* CONFIG_MOSIX_DFSA */
+
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /* [Feb-1997 T. Schoebel-Theuer]
@@ -238,6 +256,7 @@
 	spin_unlock(&arbitration_lock);
 	return 0;
 }
+
 int deny_write_access(struct file * file)
 {
 	spin_lock(&arbitration_lock);
@@ -325,6 +344,25 @@
 	return result;
 }
 
+#ifdef CONFIG_MOSIX_DFSA
+static inline int
+dfsa_crossed(struct nameidata *nd, struct vfsmount *prevmnt)
+{
+	if(nd->flags & LOOKUP_STAYFS)
+	{
+		mntput(prevmnt);
+		if(nd->mnt != prevmnt)
+		{
+			if(current->mosix.dflags & DREMOTE)
+				return(-EDOITATHOME);
+			nd->flags &= ~LOOKUP_STAYFS;
+			current->mosix.dflags &= ~DSTATSDOWN;
+		}
+	}
+	return(0);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * This limits recursive symlink follows to 8, while
  * limiting consecutive symlinks to 40.
@@ -439,6 +477,15 @@
 		;
 }
 
+#ifdef CONFIG_MOSIX_FS
+static inline int
+unacceptable_mfs_fs(unsigned long magic)
+{
+	return(magic == PROC_SUPER_MAGIC || magic == 0x42494e4d);
+						  /* (BINMisc) */
+}
+#endif /* CONFIG_MOSIX_FS */
+
 /*
  * Name resolution.
  *
@@ -453,7 +500,29 @@
 	struct inode *inode;
 	int err;
 	unsigned int lookup_flags = nd->flags;
-
+#ifdef CONFIG_MOSIX_DFSA
+	struct vfsmount *prevmnt = NULL;
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+	char *orig_part = NULL, *orig_ref = NULL, *tmpname;
+	unsigned int flattings = 0;
+	char *free_me = NULL;
+#endif /* CONFIG_MOSIX_FS */
+
+#ifdef CONFIG_MOSIX_DFSA
+	/* an early error in path_init? (callers did not error-check there!) */
+	if(nd->flags & LOOKUP_DOITATHOME)
+	{
+		path_release(nd);
+		return(-EDOITATHOME);
+	}
+	if(nd->flags & LOOKUP_REPLACENAME)
+	{
+		nd->flags &= ~LOOKUP_REPLACENAME;
+		name = nd->replaced_name;
+		nd->replaced_name = NULL;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	while (*name=='/')
 		name++;
 	if (!*name)
@@ -461,7 +530,12 @@
 
 	inode = nd->dentry->d_inode;
 	if (current->link_count)
+#ifdef CONFIG_MOSIX_FS
+		lookup_flags = LOOKUP_FOLLOW |
+			(nd->flags & (LOOKUP_MFS|LOOKUP_MFS_MFS));
+#else
 		lookup_flags = LOOKUP_FOLLOW;
+#endif /* CONFIG_MOSIX_FS */
 
 	/* At this point we know we have a real path component. */
 	for(;;) {
@@ -469,6 +543,47 @@
 		struct qstr this;
 		unsigned int c;
 
+#ifdef CONFIG_MOSIX_FS
+		/* have we consumed the whole link and can continue
+		 * with the original name?
+		 */
+		if(orig_part && name >= orig_part)
+		{
+			name = orig_ref + (name - orig_part);
+			orig_part = orig_ref = NULL;
+			if(free_me)
+			{
+				kfree(free_me);
+				free_me = NULL;
+			}
+			flattings = 0;	/* real progress made */
+			nd->flags &= ~LOOKUP_MFS_MFS;
+		}
+		if(inode->i_op->express_lookup)
+		{
+			if(current->link_count)
+			/* flatten the path by passing it back to top-level,
+			 * so all is included in the same express_lookup */
+			{
+				if(!(nd->name_left =
+					kmalloc(strlen(name)+1, GFP_KERNEL)))
+				{
+					err = -ENOMEM;
+					break;
+				}
+				strcpy(nd->name_left, name);
+				return(0);
+			}
+			err = inode->i_op->express_lookup(nd, (char **)&name);
+			if(IS_ERR((const void *)err))
+				break;
+			if(!name)
+				goto return_err; /*trick: err can be positive*/
+			inode = nd->dentry->d_inode;
+			continue;
+		}
+#endif /* CONFIG_MOSIX_FS */
+
 		err = permission(inode, MAY_EXEC);
 		dentry = ERR_PTR(err);
  		if (err)
@@ -504,7 +619,25 @@
 			case 2:	
 				if (this.name[1] != '.')
 					break;
+#ifdef CONFIG_MOSIX_FS
+				if((nd->flags & LOOKUP_MFS) &&
+					!current->link_count && !orig_ref &&
+					is_mfs_root(nd))
+				{
+					nd->name_left = (char *)name;
+					path_release(nd);
+					goto return_base;
+				}
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+				if(nd->flags & LOOKUP_STAYFS)
+					prevmnt = mntget(nd->mnt);
+#endif /* CONFIG_MOSIX_DFSA */
 				follow_dotdot(nd);
+#ifdef CONFIG_MOSIX_DFSA
+				if((err = dfsa_crossed(nd, prevmnt)))
+					break;
+#endif /* CONFIG_MOSIX_DFSA */
 				inode = nd->dentry->d_inode;
 				/* fallthrough */
 			case 1:
@@ -528,8 +661,16 @@
 				break;
 		}
 		/* Check mountpoints.. */
+#ifdef CONFIG_MOSIX_DFSA
+		if(nd->flags & LOOKUP_STAYFS)
+			prevmnt = mntget(nd->mnt);
+#endif /* CONFIG_MOSIX_DFSA */
 		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
 			;
+#ifdef CONFIG_MOSIX_DFSA
+		if((err = dfsa_crossed(nd, prevmnt)))
+			break;
+#endif /* CONFIG_MOSIX_DFSA */
 
 		err = -ENOENT;
 		inode = dentry->d_inode;
@@ -546,6 +687,43 @@
 				goto return_err;
 			err = -ENOENT;
 			inode = nd->dentry->d_inode;
+#ifdef CONFIG_MOSIX_FS
+			if(nd->name_left)
+			{
+				unsigned int l = strlen(nd->name_left);
+
+				err = -ELOOP;
+				if(flattings++ > 8)
+				{
+					kfree(nd->name_left);
+					nd->name_left = NULL;
+					break;
+				}
+				err = -ENOMEM;
+				if(!(tmpname = kmalloc(l + strlen(name) + 2,
+								GFP_KERNEL)))
+				{
+					kfree(nd->name_left);
+					nd->name_left = NULL;
+					break;
+				}
+				sprintf(tmpname, "%s/%s", nd->name_left, name);
+				kfree(nd->name_left);
+				if(current->link_count)
+				{
+					nd->name_left = tmpname;
+					return(0);
+				}
+				if(free_me)
+					kfree(free_me);
+				free_me = tmpname;
+				nd->name_left = NULL;
+				orig_part = tmpname + l + 1;
+				orig_ref = (char *)name;
+				name = tmpname;
+				continue;
+			}
+#endif /* CONFIG_MOSIX_FS */
 			if (!inode)
 				break;
 			err = -ENOTDIR; 
@@ -556,8 +734,19 @@
 			nd->dentry = dentry;
 		}
 		err = -ENOTDIR; 
+#ifdef CONFIG_MOSIX_FS
+		if (!inode->i_op->express_lookup)
+#endif /* CONFIG_MOSIX_FS */
 		if (!inode->i_op->lookup)
 			break;
+#ifdef CONFIG_MOSIX_FS
+		if(lookup_flags & LOOKUP_MFS)
+		{
+			err = -EACCES;
+			if(unacceptable_mfs_fs(nd->mnt->mnt_sb->s_magic))
+				break;
+		}
+#endif /* CONFIG_MOSIX_FS */
 		continue;
 		/* here ends the main loop */
 
@@ -572,7 +761,25 @@
 			case 2:	
 				if (this.name[1] != '.')
 					break;
+#ifdef CONFIG_MOSIX_FS
+				if((nd->flags & LOOKUP_MFS) &&
+					!current->link_count && !orig_ref &&
+					is_mfs_root(nd))
+				{
+					nd->name_left = (char *)name;
+					path_release(nd);
+					goto return_base;
+				}
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+				if(nd->flags & LOOKUP_STAYFS)
+					prevmnt = mntget(nd->mnt);
+#endif /* CONFIG_MOSIX_DFSA */
 				follow_dotdot(nd);
+#ifdef CONFIG_MOSIX_DFSA
+				if((err = dfsa_crossed(nd, prevmnt)))
+					break;
+#endif /* CONFIG_MOSIX_DFSA */
 				inode = nd->dentry->d_inode;
 				/* fallthrough */
 			case 1:
@@ -590,8 +797,16 @@
 			if (IS_ERR(dentry))
 				break;
 		}
+#ifdef CONFIG_MOSIX_DFSA
+		if(nd->flags & LOOKUP_STAYFS)
+			prevmnt = mntget(nd->mnt);
+#endif /* CONFIG_MOSIX_DFSA */
 		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
 			;
+#ifdef CONFIG_MOSIX_DFSA
+		if((err = dfsa_crossed(nd, prevmnt)))
+			break;
+#endif /* CONFIG_MOSIX_DFSA */
 		inode = dentry->d_inode;
 		if ((lookup_flags & LOOKUP_FOLLOW)
 		    && inode && inode->i_op && inode->i_op->follow_link) {
@@ -600,6 +815,29 @@
 			if (err)
 				goto return_err;
 			inode = nd->dentry->d_inode;
+#ifdef CONFIG_MOSIX_FS
+			if(nd->name_left)
+			{
+				err = -ELOOP;
+				if(flattings++ > 8)
+				{
+					kfree(nd->name_left);
+					nd->name_left = NULL;
+					break;
+				}
+				err = -ENOMEM;
+				if(free_me)
+					kfree(free_me);
+				if(current->link_count)
+					return(0);
+				orig_ref = (char *)name;
+				name = free_me = nd->name_left;
+				nd->name_left = NULL;
+				lookup_flags = nd->flags;
+				orig_part = NULL;
+				continue;
+			}
+#endif /* CONFIG_MOSIX_FS */
 		} else {
 			dput(nd->dentry);
 			nd->dentry = dentry;
@@ -609,9 +847,26 @@
 			goto no_inode;
 		if (lookup_flags & LOOKUP_DIRECTORY) {
 			err = -ENOTDIR; 
+#ifdef CONFIG_MOSIX_FS
+			if (!inode->i_op || (!inode->i_op->lookup &&
+						!inode->i_op->express_lookup))
+#else
 			if (!inode->i_op || !inode->i_op->lookup)
+#endif /* CONFIG_MOSIX_FS */
+				break;
+		}
+#ifdef CONFIG_MOSIX_FS
+		if(lookup_flags & LOOKUP_MFS)
+		{
+			umode_t mod = inode->i_mode & S_IFMT;
+
+			err = -EACCES;
+			if(mod != S_IFREG && mod != S_IFDIR && mod != S_IFLNK)
+				break;
+			if(unacceptable_mfs_fs(nd->mnt->mnt_sb->s_magic))
 				break;
 		}
+#endif /* CONFIG_MOSIX_FS */
 		goto return_base;
 no_inode:
 		err = -ENOENT;
@@ -643,6 +898,10 @@
 			}
 		}
 return_base:
+#ifdef CONFIG_MOSIX_FS
+		if(free_me)
+			kfree(free_me);
+#endif /* CONFIG_MOSIX_FS */
 		return 0;
 out_dput:
 		dput(dentry);
@@ -650,6 +909,10 @@
 	}
 	path_release(nd);
 return_err:
+#ifdef CONFIG_MOSIX_FS
+	if(free_me)
+		kfree(free_me);
+#endif /* CONFIG_MOSIX_FS */
 	return err;
 }
 
@@ -719,12 +982,53 @@
 		dput(olddentry);
 		mntput(oldmnt);
 	}
+#ifdef CONFIG_MOSIX_DFSA
+	tell_process(current, DREQ_NOTUPTODATE);
+#endif /* CONFIG_MOSIX_DFSA */
 }
 
 /* SMP-safe */
 static inline int
 walk_init_root(const char *name, struct nameidata *nd)
 {
+#ifdef CONFIG_MOSIX_DFSA
+	if(nd->flags & LOOKUP_STAYFS)
+	{
+		struct task_struct *p = current;
+
+		if(current->fs->altroot)
+		{
+			p->mosix.dflags &= ~DSTATSDOWN;
+			nd->flags &= ~LOOKUP_STAYFS;
+		}
+		else if(p->mosix.dflags & DDEPUTY)
+			nd->flags &= ~LOOKUP_STAYFS;
+		else if(((p->mosix.dflags & DREMOTE) || CAN_DFSA(p)) &&
+			name_starts_in_dfsa((char **)&name, nd))
+		{
+			if(!(p->mosix.dflags & DREMOTE) && !p->link_count)
+				p->mosix.dflags |= DSTATSDOWN;
+			if(!*name)
+				return(0);
+			nd->flags |= LOOKUP_REPLACENAME;
+			nd->replaced_name = (char *)name;
+			return(1);
+		}
+		else if(p->mosix.dflags & DREMOTE)
+		{
+			nd->flags |= LOOKUP_DOITATHOME;
+			nd->mnt = NULL;
+			nd->dentry = NULL;
+			return(1);
+		}
+		else
+			p->mosix.dflags &= ~DSTATSDOWN;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+	if(nd->flags & LOOKUP_MFS)
+		return(mfs_walk_init_root(nd));
+#endif /* CONFIG_MOSIX_FS */
 	read_lock(&current->fs->lock);
 	if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
 		nd->mnt = mntget(current->fs->altrootmnt);
@@ -755,12 +1059,48 @@
 {
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
+#ifdef CONFIG_MOSIX_FS
+	nd->name_left = NULL;
+	nd->complete_flags = 0;
+#ifdef CONFIG_MOSIX_DIAG
+	if(flags & LOOKUP_MFS)
+		panic("MFS should have own path_init!");
+#endif /* CONFIG_MOSIX_DIAG */
+#endif /* CONFIG_MOSIX_FS */
 	if (*name=='/')
 		return walk_init_root(name,nd);
 	read_lock(&current->fs->lock);
 	nd->mnt = mntget(current->fs->pwdmnt);
 	nd->dentry = dget(current->fs->pwd);
 	read_unlock(&current->fs->lock);
+#ifdef CONFIG_MOSIX_DFSA
+	if(!nd->dentry)	/* possible on REMOTE! */
+	{
+		nd->flags |= LOOKUP_DOITATHOME;
+		return(1);
+	}
+
+	if(nd->flags & LOOKUP_STAYFS)
+	{
+		struct task_struct *p = current;
+
+		if(p->mosix.dflags & DDEPUTY)
+			nd->flags &= ~LOOKUP_STAYFS;
+		else if(((p->mosix.dflags & DREMOTE) || CAN_DFSA(p)) &&
+								within_dfsa(nd))
+		{
+			if(!(p->mosix.dflags & DREMOTE))
+				p->mosix.dflags |= DSTATSDOWN;
+		}
+		else
+		{
+			if(p->mosix.dflags & DREMOTE)
+				nd->flags |= LOOKUP_DOITATHOME;
+			else
+				p->mosix.dflags &= ~DSTATSDOWN;
+		}
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	return 1;
 }
 
@@ -859,6 +1199,10 @@
 		err = path_lookup(tmp, flags, nd);
 		putname(tmp);
 	}
+#ifdef CONFIG_MOSIX_FS
+	else
+		nd->complete_flags = 0;
+#endif /* CONFIG_MOSIX_FS */
 	return err;
 }
 
@@ -927,7 +1271,11 @@
  *  3. We should have write and exec permissions on dir
  *  4. We can't do it if dir is immutable (done in permission())
  */
+#ifdef CONFIG_MOSIX_FS
+inline int may_create(struct inode *dir, struct dentry *child) {
+#else
 static inline int may_create(struct inode *dir, struct dentry *child) {
+#endif /* CONFIG_MOSIX_FS */
 	if (child->d_inode)
 		return -EEXIST;
 	if (IS_DEADDIR(dir))
@@ -1005,16 +1353,45 @@
 	struct dentry *dentry;
 	struct dentry *dir;
 	int count = 0;
-
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+        unsigned int more_flags = 0;
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
+	
 	acc_mode = ACC_MODE(flag);
-
+#ifdef CONFIG_MOSIX_FS
+        if(!pathname)   /* special argument to skip path-search */
+        {
+                if(flag & O_CREAT)
+                        goto low_create;
+                else
+                        goto low_nocreate;
+        }
+        nd->express_function = EF_OPEN;
+        nd->complete_args.ints.i1 = flag;
+        nd->complete_args.ints.i2 = mode & ~current->fs->umask;
+        more_flags |= LOOKUP_COMPLETE;
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+        if(current->mosix.dirty_bits & FILP_OPEN_SYSCALL)
+                more_flags |= LOOKUP_STAYFS;
+#endif /* CONFIG_MOSIX_DFSA */
+	
 	/*
 	 * The simplest case - just a plain lookup.
 	 */
 	if (!(flag & O_CREAT)) {
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+                error = path_lookup(pathname, lookup_flags(flag)|more_flags, nd);
+#else
 		error = path_lookup(pathname, lookup_flags(flag), nd);
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
 		if (error)
 			return error;
+#ifdef CONFIG_MOSIX_FS
+                if(nd->complete_flags & COMPLETE_DONE)
+                        return(0);
+               low_nocreate:
+#endif /* CONFIG_MOSIX_FS */
 		dentry = nd->dentry;
 		goto ok;
 	}
@@ -1022,9 +1399,18 @@
 	/*
 	 * Create - we need to know the parent.
 	 */
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+        error = path_lookup(pathname, LOOKUP_PARENT|more_flags, nd);
+#else
 	error = path_lookup(pathname, LOOKUP_PARENT, nd);
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		return error;
+#ifdef CONFIG_MOSIX_FS
+        if(nd->complete_flags & COMPLETE_DONE)
+                return(0);
+        low_create:
+#endif /* CONFIG_MOSIX_FS */
 
 	/*
 	 * We have the parent and last component. First of all, check
@@ -1213,7 +1599,11 @@
 }
 
 /* SMP-safe */
+#ifdef CONFIG_MOSIX_FS
+struct dentry *lookup_create(struct nameidata *nd, int is_dir)
+#else
 static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
+#endif /* CONFIG_MOSIX_FS */
 {
 	struct dentry *dentry;
 
@@ -1274,7 +1664,17 @@
 	if (IS_ERR(tmp))
 		return PTR_ERR(tmp);
 
+#ifdef CONFIG_MOSIX_FS
+        nd.express_function = EF_MKNOD;
+        nd.complete_args.ints.i1 = mode & ~current->fs->umask;
+        error = path_lookup(tmp, LOOKUP_COMPLETE|LOOKUP_PARENT, &nd);
+#else
 	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_FS
+        if(nd.complete_flags & COMPLETE_DONE)
+                goto out;
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto out;
 	dentry = lookup_create(&nd, 0);
@@ -1342,9 +1742,24 @@
 		struct dentry *dentry;
 		struct nameidata nd;
 
+#ifdef CONFIG_MOSIX_FS
+                nd.express_function = EF_MKDIR;
+                nd.complete_args.ints.i1 = mode & ~current->fs->umask;
+                error = path_lookup(tmp, LOOKUP_COMPLETE|LOOKUP_PARENT|LOOKUP_STAYFS,
+                                                                       &nd);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+                error = path_lookup(tmp, LOOKUP_PARENT|LOOKUP_STAYFS, &nd);
+#else
 		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 		if (error)
 			goto out;
+#ifdef CONFIG_MOSIX_FS
+                if(nd.complete_flags & COMPLETE_DONE)
+                        goto out;
+#endif /* CONFIG_MOSIX_FS */
 		dentry = lookup_create(&nd, 1);
 		error = PTR_ERR(dentry);
 		if (!IS_ERR(dentry)) {
@@ -1438,10 +1853,23 @@
 	if(IS_ERR(name))
 		return PTR_ERR(name);
 
+#ifdef CONFIG_MOSIX_FS
+        nd.express_function = EF_RMDIR;
+        error = path_lookup(name, LOOKUP_COMPLETE|LOOKUP_PARENT|LOOKUP_STAYFS, &nd);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+        error = path_lookup(name, LOOKUP_PARENT|LOOKUP_STAYFS, &nd);
+#else
 	error = path_lookup(name, LOOKUP_PARENT, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto exit;
-
+#ifdef CONFIG_MOSIX_FS
+        if(nd.complete_flags & COMPLETE_DONE)
+                goto exit;
+#endif /* CONFIG_MOSIX_FS */
+	
 	switch(nd.last_type) {
 		case LAST_DOTDOT:
 			error = -ENOTEMPTY;
@@ -1506,9 +1934,22 @@
 	if(IS_ERR(name))
 		return PTR_ERR(name);
 
+#ifdef CONFIG_MOSIX_FS
+        nd.express_function = EF_UNLINK;
+        error = path_lookup(name, LOOKUP_COMPLETE|LOOKUP_PARENT|LOOKUP_STAYFS, &nd);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+        error = path_lookup(name, LOOKUP_PARENT|LOOKUP_STAYFS, &nd);
+#else
 	error = path_lookup(name, LOOKUP_PARENT, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto exit;
+#ifdef CONFIG_MOSIX_FS
+        if(nd.complete_flags & COMPLETE_DONE)
+                goto exit;
+#endif /* CONFIG_MOSIX_FS */
 	error = -EISDIR;
 	if (nd.last_type != LAST_NORM)
 		goto exit1;
@@ -1577,9 +2018,24 @@
 		struct dentry *dentry;
 		struct nameidata nd;
 
+#ifdef CONFIG_MOSIX_FS
+                nd.express_function = EF_SYMLINK;
+                nd.complete_parg = from;
+                error = path_lookup(to, LOOKUP_COMPLETE|LOOKUP_PARENT|LOOKUP_STAYFS,
+                                                                        &nd);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+                error = path_lookup(to, LOOKUP_PARENT|LOOKUP_STAYFS, &nd);
+#else
 		error = path_lookup(to, LOOKUP_PARENT, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 		if (error)
 			goto out;
+#ifdef CONFIG_MOSIX_FS
+                if(nd.complete_flags & COMPLETE_DONE)
+                        goto out;
+#endif /* CONFIG_MOSIX_FS */
 		dentry = lookup_create(&nd, 0);
 		error = PTR_ERR(dentry);
 		if (!IS_ERR(dentry)) {
@@ -1654,13 +2110,38 @@
 	if (!IS_ERR(to)) {
 		struct dentry *new_dentry;
 		struct nameidata nd, old_nd;
-
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+                unsigned int more_flags = 0;
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
+		
+#ifdef CONFIG_MOSIX_DFSA
+                error = __user_walk(oldname, LOOKUP_POSITIVE|LOOKUP_STAYFS, &old_nd);
+#else
 		error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
+#endif /* CONFIG_MOSIX_DFSA */	
 		if (error)
 			goto exit;
+
+#ifdef CONFIG_MOSIX_DFSA
+                if(current->mosix.dflags & (DREMOTE|DSTATSDOWN))
+                        more_flags |= LOOKUP_STAYFS;
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+                nd.express_function = EF_LINK;
+                nd.complete_args.oldnd = &old_nd;
+                more_flags |= LOOKUP_COMPLETE;
+#endif /* CONFIG_MOSIX_FS */
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+                error = path_lookup(to, LOOKUP_PARENT|more_flags, &nd);
+#else
 		error = path_lookup(to, LOOKUP_PARENT, &nd);
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
 		if (error)
 			goto out;
+#ifdef CONFIG_MOSIX_FS
+                if(nd.complete_flags & COMPLETE_DONE)
+                        goto out;
+#endif /* CONFIG_MOSIX_FS */
 		error = -EXDEV;
 		if (old_nd.mnt != nd.mnt)
 			goto out_release;
@@ -1853,12 +2334,36 @@
 	struct dentry * old_dir, * new_dir;
 	struct dentry * old_dentry, *new_dentry;
 	struct nameidata oldnd, newnd;
-
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+        unsigned int more_flags = 0;
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
+
+#ifdef CONFIG_MOSIX_DFSA
+        error = path_lookup(oldname, LOOKUP_PARENT|LOOKUP_STAYFS, &oldnd);
+#else
 	error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
+#endif /* CONFIG_MOSIX_DFSA */
 	if (error)
 		goto exit;
 
+#ifdef CONFIG_MOSIX_DFSA
+        if(current->mosix.dflags & (DREMOTE|DSTATSDOWN))
+                more_flags |= LOOKUP_STAYFS;
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+        newnd.express_function = EF_RENAME;
+        newnd.complete_args.oldnd = &oldnd;
+        more_flags |= LOOKUP_COMPLETE;
+#endif /* CONFIG_MOSIX_FS */
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+        error = path_lookup(newname, LOOKUP_PARENT|more_flags, &newnd);
+#else
 	error = path_lookup(newname, LOOKUP_PARENT, &newnd);
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_FS
+        if(newnd.complete_flags & COMPLETE_DONE)
+                goto exit1;
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto exit1;
 
@@ -1965,8 +2470,16 @@
 		if (!walk_init_root(link, nd))
 			/* weird __emul_prefix() stuff did it */
 			goto out;
+#ifdef CONFIG_MOSIX_FS
+		if(nd->flags & LOOKUP_MFS)
+			nd->flags |= LOOKUP_MFS_MFS;
+#endif /* CONFIG_MOSIX_FS */
 	}
 	res = link_path_walk(link, nd);
+#ifdef CONFIG_MOSIX_FS
+	if(!nd->name_left)
+		nd->flags &= ~LOOKUP_MFS_MFS;
+#endif /* CONFIG_MOSIX_FS */
 out:
 	if (current->link_count || res || nd->last_type!=LAST_NORM)
 		return res;
diff -Naur --exclude=CVS --exclude=configs linux/fs/namespace.c linux-openmosix/fs/namespace.c
--- linux/fs/namespace.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/namespace.c	2004-02-05 10:51:21.000000000 +0100
@@ -21,6 +21,17 @@
 #include <linux/seq_file.h>
 #include <linux/namespace.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/file.h>
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
 struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
 int do_remount_sb(struct super_block *sb, int flags, void * data);
 void kill_super(struct super_block *sb);
@@ -40,7 +51,7 @@
 
 struct vfsmount *alloc_vfsmnt(char *name)
 {
-	struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); 
+	struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
 	if (mnt) {
 		memset(mnt, 0, sizeof(struct vfsmount));
 		atomic_set(&mnt->mnt_count,1);
@@ -237,6 +248,11 @@
 	}
 	if (mnt->mnt_sb->s_op->show_options)
 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+	/* seq_puts(m, " 0 0"); */
+#ifdef CONFIG_MOSIX_DFSA
+	if (mnt->mnt_dfsa)
+		seq_printf(m, ",dfsa=%d", mnt->mnt_dfsa);
+#endif /* CONFIG_MOSIX_DFSA */
 	seq_puts(m, " 0 0\n");
 	return err;
 }
@@ -331,6 +347,15 @@
 	}
 
 	down_write(&current->namespace->sem);
+#ifdef CONFIG_MOSIX_DFSA
+	/*	down_half_interruptible(&current->namespace->sem);*/
+	/* while (!down_write_trylock(&current->namespace->sem)) */
+	if(current->namespace == init_task.namespace &&  (retval = dfsa_setmnt(mnt, 0, 0)))
+	{
+		up_write(&current->namespace->sem);
+		return(retval);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	spin_lock(&dcache_lock);
 
 	if (atomic_read(&sb->s_active) == 1) {
@@ -387,9 +412,9 @@
 }
 
 /*
- *	The 2.0 compatible umount. No flags. 
+ *	The 2.0 compatible umount. No flags.
  */
- 
+
 asmlinkage long sys_oldumount(char * name)
 {
 	return sys_umount(name,0);
@@ -496,7 +521,6 @@
 	err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
 	if (err)
 		return err;
-
 	down_write(&current->namespace->sem);
 	err = -EINVAL;
 	if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) {
@@ -532,6 +556,9 @@
 {
 	int err;
 	struct super_block * sb = nd->mnt->mnt_sb;
+#ifdef CONFIG_MOSIX_DFSA
+	int odfsa = 0, new_dfsa, cng_dfsa = 0;
+#endif /* CONFIG_MOSIX_DFSA */
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -542,11 +569,36 @@
 	if (nd->dentry != nd->mnt->mnt_root)
 		return -EINVAL;
 
+#ifdef CONFIG_MOSIX_DFSA
+	if(current->namespace == init_task.namespace &&
+	   (cng_dfsa = dfsa_option(data, &new_dfsa)))
+	{
+		down_write(&current->namespace->sem);
+		/* down_half_interruptible(&current->namespace->sem); */
+		odfsa = nd->mnt->mnt_dfsa;
+		nd->mnt->mnt_dfsa = new_dfsa;
+		err = dfsa_setmnt(nd->mnt, new_dfsa, flags);
+		up_write(&current->namespace->sem);
+		if(err)
+			return(err);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	down_write(&sb->s_umount);
 	err = do_remount_sb(sb, flags, data);
 	if (!err)
 		nd->mnt->mnt_flags=mnt_flags;
 	up_write(&sb->s_umount);
+#ifdef CONFIG_MOSIX_DFSA
+	if(err && cng_dfsa) {
+		/* undo - unless someone else played with mount meanwhile */
+		down_write(&current->namespace->sem);
+		/* down_half_interruptible(&current->namespace->sem); */
+		if(nd->mnt->mnt_dfsa == new_dfsa)
+			dfsa_setmnt(nd->mnt, odfsa, nd->mnt->mnt_sb->s_flags);
+		/* up(&current->namespace->sem);*/
+		up_write(&current->namespace->sem);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
 	return err;
 }
 
@@ -555,6 +607,9 @@
 	struct nameidata old_nd, parent_nd;
 	struct vfsmount *p;
 	int err = 0;
+#ifdef CONFIG_MOSIX_DFSA
+	int odfsa = 0;
+#endif
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (!old_name || !*old_name)
@@ -569,7 +624,14 @@
 	err = -EINVAL;
 	if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt))
 		goto out;
-
+#ifdef CONFIG_MOSIX_DFSA
+	odfsa = old_nd.mnt->mnt_dfsa;
+	if(odfsa) {
+		if((err = dfsa_setmnt(old_nd.mnt, 0, 0)))
+			goto out;
+		old_nd.mnt->mnt_dfsa = 0;
+	}
+#endif
 	err = -ENOENT;
 	down(&nd->dentry->d_inode->i_zombie);
 	if (IS_DEADDIR(nd->dentry->d_inode))
@@ -602,7 +664,20 @@
 	spin_unlock(&dcache_lock);
 out1:
 	up(&nd->dentry->d_inode->i_zombie);
+
 out:
+#ifdef CONFIG_MOSIX_DFSA
+       if(err && odfsa) {
+               int e = dfsa_setmnt(old_nd.mnt, odfsa, 0);
+
+               if(e) {
+                       printk("Moving a mount-point: failed restoring DFSA "
+                              "option (errno=%d)\n", e);
+                       printk("following a failed attempt to move '%s'\n", old_name);
+	       } else
+                      old_nd.mnt->mnt_dfsa = odfsa;
+      }
+#endif /* CONFIG_MOSIX_DFSA */
 	up_write(&current->namespace->sem);
 	if (!err)
 		path_release(&parent_nd);
@@ -655,7 +730,7 @@
 	int i;
 	unsigned long page;
 	unsigned long size;
-	
+
 	*where = 0;
 	if (!data)
 		return 0;
@@ -674,7 +749,7 @@
 
 	i = size - copy_from_user((void *)page, data, size);
 	if (!i) {
-		free_page(page); 
+		free_page(page);
 		return -EFAULT;
 	}
 	if (i != PAGE_SIZE)
@@ -703,6 +778,9 @@
 	struct nameidata nd;
 	int retval = 0;
 	int mnt_flags = 0;
+#ifdef CONFIG_MOSIX_DFSA
+	int dfsa_opt;
+#endif /* CONFIG_MOSIX_DFSA */
 
 	/* Discard magic */
 	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
@@ -739,6 +817,25 @@
 	else
 		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
 				      dev_name, data_page);
+#ifdef CONFIG_MOSIX_DFSA
+	down_write(&current->namespace->sem); /* possible location of dead_lock for tmpfs under oMFS? Moshe */
+	/* down_half_interruptible(&current->namespace->sem); what is this?? Moshe */
+	if(!retval && current->namespace == init_task.namespace && 
+	   dfsa_option((char *)data_page, &dfsa_opt) &&
+	   d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry)
+	   && (nd.mnt->mnt_dfsa = dfsa_opt) &&
+	   dfsa_setmnt(nd.mnt, dfsa_opt, flags))
+	{
+		/* too late to undo the mount - all we can do is complain: */
+		nd.mnt->mnt_dfsa = 0;
+		printk("openMosix: mount succeeded, but DFSA option failed: "
+			"if you can fix the problem, run:\n");
+		printk("'mount -o remount,dfsa=%d %s %s'\n", dfsa_opt,
+			dev_name, dir_name);
+	}
+	up_write(&current->namespace->sem);
+	/* up(&current->namespace->sem); */
+#endif /* CONFIG_MOSIX_DFSA */
 	path_release(&nd);
 	return retval;
 }
@@ -861,6 +958,11 @@
 	putname(dir_page);
 out1:
 	free_page(type_page);
+/* #ifdef CONFIG_MOSIX_FS maybe this should be turned on again?? Moshe */
+/*         /\* for consistency *\/ */
+/* 	if(retval > 0 && !strcmp(type, "mfs")) */
+/* 		mosix_rebuild_file_list(); */
+/* #endif */
 	return retval;
 }
 
@@ -870,7 +972,12 @@
 	struct fs_struct *fs;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	/* DFSA is disabled, so no REMOTE roots (and no cwd's away) */
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		task_lock(p);
 		fs = p->fs;
 		if (fs) {
@@ -887,6 +994,33 @@
 	read_unlock(&tasklist_lock);
 }
 
+#ifdef CONFIG_MOSIX_DFSA
+void restore_dfsa_mounts(void)
+{
+	struct list_head *p;
+	struct namespace *n = current->namespace;
+	int told = 0;
+
+	down_write(&n->sem);
+	list_for_each(p, &n->list) {
+		struct vfsmount *tmp = list_entry(p, struct vfsmount, mnt_list);
+
+		if(tmp->mnt_dfsa &&
+		   dfsa_setmnt(tmp, tmp->mnt_dfsa, tmp->mnt_sb->s_flags))
+		{
+			if(!told++)
+				printk("One or more partitions failed to restore DFSA"
+				       " status after pivot_root.\n"
+				       "If you can fix the problem, please remount "
+				       "the affected partition(s) with the appropriate"
+				       " dfsa= option\n");
+			tmp->mnt_dfsa = 0;
+		}
+	}
+	up_write(&n->sem);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * Moves the current root to put_root, and sets root/cwd of all processes
  * which had them on the old root to new_root.
@@ -909,6 +1043,10 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+#ifdef CONFIG_MOSIX_DFSA
+	if(current->namespace == init_task.namespace && (error = disable_dfsa()))
+		return(error);
+#endif /* CONFIG_MOSIX_DFSA */
 	lock_kernel();
 
 	error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
@@ -938,6 +1076,15 @@
 		goto out2;
 	if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
 		goto out2;
+#ifdef CONFIG_MOSIX_FS
+	if(new_nd.dentry->d_inode->i_sb->s_magic == MFS_SUPER_MAGIC ||
+		old_nd.dentry->d_inode->i_sb->s_magic == MFS_SUPER_MAGIC)
+	{
+		/* MFS does not support mounts (which are otherwise ignored) */
+		error = -EINVAL;
+		goto out2;
+	}
+#endif /* CONFIG_MOSIX_FS */
 	error = -EBUSY;
 	if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt)
 		goto out2; /* loop */
@@ -965,6 +1112,9 @@
 	attach_mnt(user_nd.mnt, &old_nd);
 	attach_mnt(new_nd.mnt, &root_parent);
 	spin_unlock(&dcache_lock);
+#ifdef CONFIG_MOSIX_FS
+	mfs_change_root(user_nd.dentry, user_nd.mnt, new_nd.dentry, new_nd.mnt);
+#endif /* CONFIG_MOSIX_FS */
 	chroot_fs_refs(&user_nd, &new_nd);
 	error = 0;
 	path_release(&root_parent);
@@ -978,6 +1128,12 @@
 	path_release(&new_nd);
 out0:
 	unlock_kernel();
+#ifdef CONFIG_MOSIX_DFSA
+       if(current->namespace == init_task.namespace) {
+               enable_dfsa();
+               restore_dfsa_mounts();
+       }
+#endif /* CONFIG_MOSIX_DFSA */
 	return error;
 out3:
 	spin_unlock(&dcache_lock);
diff -Naur --exclude=CVS --exclude=configs linux/fs/nfsd/auth.c linux-openmosix/fs/nfsd/auth.c
--- linux/fs/nfsd/auth.c	2000-07-24 08:04:10.000000000 +0200
+++ linux-openmosix/fs/nfsd/auth.c	2004-02-05 10:51:22.000000000 +0100
@@ -9,6 +9,9 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svcauth.h>
 #include <linux/nfsd/nfsd.h>
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
 
 #define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
 void
@@ -20,6 +23,9 @@
 	if (rqstp->rq_userset)
 		return;
 
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	if (exp->ex_flags & NFSEXP_ALLSQUASH) {
 		cred->cr_uid = exp->ex_anon_uid;
 		cred->cr_gid = exp->ex_anon_gid;
diff -Naur --exclude=CVS --exclude=configs linux/fs/nfsd/export.c linux-openmosix/fs/nfsd/export.c
--- linux/fs/nfsd/export.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/nfsd/export.c	2004-02-05 10:51:22.000000000 +0100
@@ -487,6 +487,9 @@
 		return 0;
 	}
 
+#ifdef CONFIG_MOSIX
+	current->mosix.ignoreoldsigs = 1;
+#endif /* CONFIG_MOSIX */
 	current->sigpending = 0;
 	want_lock++;
 	while (hash_count || hash_lock) {
diff -Naur --exclude=CVS --exclude=configs linux/fs/nfsd/vfs.c linux-openmosix/fs/nfsd/vfs.c
--- linux/fs/nfsd/vfs.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/nfsd/vfs.c	2004-02-05 10:51:22.000000000 +0100
@@ -45,6 +45,10 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
 #define NFSDDBG_FACILITY		NFSDDBG_FILEOP
 #define NFSD_PARANOIA
 
@@ -108,6 +112,13 @@
 	dparent = fhp->fh_dentry;
 	exp  = fhp->fh_export;
 
+#ifdef CONFIG_MOSIX_FS
+	if(dparent->d_sb->s_magic == MFS_SUPER_MAGIC)
+	{
+		err = -EPERM;
+		goto out;
+	}
+#endif /* CONFIG_MOSIX_FS */
 	err = nfserr_acces;
 
 	/* Lookup the name, but don't follow links */
@@ -509,6 +520,9 @@
 		filp->f_op->release(inode, filp);
 	fops_put(filp->f_op);
 	if (filp->f_mode & FMODE_WRITE)
+#ifdef CONFIG_MOSIX
+	if (!(filp->f_flags & O_NOWRITEACCESS))
+#endif /* CONFIG_MOSIX */
 		put_write_access(inode);
 }
 
diff -Naur --exclude=CVS --exclude=configs linux/fs/open.c linux-openmosix/fs/open.c
--- linux/fs/open.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/open.c	2004-02-05 10:51:21.000000000 +0100
@@ -20,6 +20,12 @@
 
 #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#include <linux/hpc.h>
+#include <hpc/debug.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 int vfs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	int retval = -ENODEV;
@@ -41,8 +47,15 @@
 {
 	struct nameidata nd;
 	int error;
-
+#ifdef CONFIG_MOSIX_FS
+	        nd.express_function = EF_STATFS;
+		nd.complete_args.statfs = buf;
+		error = __user_walk(path, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_COMPLETE, &nd);
+		if(nd.complete_flags & COMPLETE_DONE)
+                return(error);
+#else
 	error = user_path_walk(path, &nd);
+#endif 	
 	if (!error) {
 		struct statfs tmp;
 		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
@@ -63,7 +76,14 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
+#ifdef CONFIG_MOSIX_FS
+        current->mosix.dirty_bits |= MFSARG_STATFS_FP; /* ?? */
+        current->mosix.dirty_file = file;	
+#endif	
 	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits &= ~MFSARG_STATFS_FP; /* ?? */
+#endif
 	if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
 		error = -EFAULT;
 	fput(file);
@@ -93,6 +113,10 @@
 		BUG();
 	files->fd[fd] = file;
 	write_unlock(&files->file_lock);
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_open_file(fd); /* by Amit Shah */
+	/* leave out for now, but needs to be fixed mosix_rebuild_file_list(); */
+#endif
 }
 
 int do_truncate(struct dentry *dentry, loff_t length)
@@ -125,7 +149,21 @@
 	if (length < 0)	/* sorry, but loff_t says... */
 		goto out;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_TRUNCATE;
+	nd.complete_args.len = length;
+	error = __user_walk(path, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS|
+							LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(path,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(path, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto out;
 	inode = nd.dentry->d_inode;
@@ -191,6 +229,9 @@
 	error = -EINVAL;
 	if (length < 0)
 		goto out;
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -262,7 +303,21 @@
 	struct inode * inode;
 	struct iattr newattrs;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_UTIME;
+	nd.complete_parg = times;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto out;
 	inode = nd.dentry->d_inode;
@@ -306,7 +361,21 @@
 	struct inode * inode;
 	struct iattr newattrs;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_UTIMES;
+	nd.complete_parg = utimes;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS| LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS , &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 
 	if (error)
 		goto out;
@@ -366,7 +435,22 @@
 	else
 		current->cap_effective = current->cap_permitted;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_ACCESS;
+	nd.complete_args.ints.i1 = mode;
+	res = __user_walk(filename,
+		LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_COMPLETE|LOOKUP_STAYFS,
+									&nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(res);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	res = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	res = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!res) {
 		res = permission(nd.dentry->d_inode, mode);
 		/* SuS v2 requires we report a read only fs too */
@@ -379,6 +463,11 @@
 	current->fsuid = old_fsuid;
 	current->fsgid = old_fsgid;
 	current->cap_effective = old_cap;
+#ifdef CONFIG_MOSIX_DFSA
+	/* a bit paranoid, for the rare case when we slept interruptibly
+	 * during "permission" and the temporary fs[ug]id passed across: */
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 
 	return res;
 }
@@ -388,7 +477,12 @@
 	int error;
 	struct nameidata nd;
 
+#ifdef CONFIG_MOSIX_DFSA
+        error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY|
+                                                        LOOKUP_STAYFS, &nd);
+#else
 	error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
+#endif /* CONFIG_MOSIX_DFSA */
 	if (error)
 		goto out;
 
@@ -412,6 +506,9 @@
 	struct vfsmount *mnt;
 	int error;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -469,6 +566,9 @@
 	int err = -EBADF;
 	struct iattr newattrs;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	file = fget(fd);
 	if (!file)
 		goto out;
@@ -501,7 +601,21 @@
 	int error;
 	struct iattr newattrs;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_CHMOD;
+	nd.complete_args.mode = mode;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (error)
 		goto out;
 	inode = nd.dentry->d_inode;
@@ -526,7 +640,11 @@
 	return error;
 }
 
+#ifdef CONFIG_MOSIX_FS
+int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+#else
 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+#endif /* CONFIG_MOSIX_FS */
 {
 	struct inode * inode;
 	int error;
@@ -591,7 +709,22 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_CHOWN;
+	nd.complete_args.ids.uid = user;
+	nd.complete_args.ids.gid = group;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = chown_common(nd.dentry, user, group);
 		path_release(&nd);
@@ -604,7 +737,21 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_CHOWN;
+	nd.complete_args.ids.uid = user;
+	nd.complete_args.ids.gid = group;
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk_link(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = chown_common(nd.dentry, user, group);
 		path_release(&nd);
@@ -618,6 +765,9 @@
 	struct file * file;
 	int error = -EBADF;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	file = fget(fd);
 	if (file) {
 		error = chown_common(file->f_dentry, user, group);
@@ -644,6 +794,9 @@
 {
 	int namei_flags, error;
 	struct nameidata nd;
+#ifdef CONFIG_MOSIX_FS
+	int old_magic = current->mosix.lastmagic;
+#endif /* CONFIG_MOSIX_FS */
 
 	namei_flags = flags;
 	if ((namei_flags+1) & O_ACCMODE)
@@ -651,9 +804,31 @@
 	if (namei_flags & O_TRUNC)
 		namei_flags |= 2;
 
+#ifdef CONFIG_MOSIX_FS
+	if(flags & O_CREAT)
+		current->mosix.lastmagic = current->mosix.whereami ? : PE;
+#endif /* CONFIG_MOSIX_FS */
 	error = open_namei(filename, namei_flags, mode, &nd);
+#ifdef CONFIG_MOSIX_FS
+	if(!(nd.complete_flags & COMPLETE_MAGICAL))
+		current->mosix.lastmagic = old_magic;
+#endif /* CONFIG_MOSIX_FS */
 	if (!error)
+#ifdef CONFIG_MOSIX_FS
+	{
+		struct file *newf = dentry_open(nd.dentry, nd.mnt, flags);
+
+		if(IS_ERR(newf))
+			current->mosix.lastmagic = old_magic;
+#ifdef CONFIG_MOSIX_DFSA
+		else if(current->mosix.lastmagic != old_magic)
+			current->mosix.dupdates |= DFSA_UPDSEL;
+#endif /* CONFIG_MOSIX_DFSA */
+		return newf;
+	}
+#else
 		return dentry_open(nd.dentry, nd.mnt, flags);
+#endif /* CONFIG_MOSIX_FS */
 
 	return ERR_PTR(error);
 }
@@ -745,6 +920,11 @@
 
 	/* Do we need to expand the fdset array? */
 	if (fd >= files->max_fdset) {
+#ifdef CONFIG_MOSIX_DFSA
+		if(current->mosix.dflags & DREMOTE)
+			error = -EDOITATHOME;
+		else
+#endif /* CONFIG_MOSIX_DFSA */
 		error = expand_fdset(files, fd);
 		if (!error) {
 			error = -EMFILE;
@@ -757,6 +937,11 @@
 	 * Check whether we need to expand the fd array.
 	 */
 	if (fd >= files->max_fds) {
+#ifdef CONFIG_MOSIX_DFSA
+		if(current->mosix.dflags & DREMOTE)
+			error = -EDOITATHOME;
+		else
+#endif /* CONFIG_MOSIX_DFSA */
 		error = expand_fd_array(files, fd);
 		if (!error) {
 			error = -EMFILE;
@@ -795,10 +980,46 @@
 	if (!IS_ERR(tmp)) {
 		fd = get_unused_fd();
 		if (fd >= 0) {
+#ifdef CONFIG_MOSIX_DFSA
+			struct file * f;
+			mode_t imode;
+
+			current->mosix.dirty_bits |= FILP_OPEN_SYSCALL;
+			f = filp_open(tmp, flags, mode);
+			current->mosix.dirty_bits &= ~FILP_OPEN_SYSCALL;
+#else
 			struct file *f = filp_open(tmp, flags, mode);
+#endif /* CONFIG_MOSIX_DFSA */
 			error = PTR_ERR(f);
 			if (IS_ERR(f))
 				goto out_error;
+#ifdef CONFIG_MOSIX_DFSA
+			imode = f->f_dentry->d_inode->i_mode;
+			if(!S_ISREG(imode) && !S_ISDIR(imode))
+			{
+				if(current->mosix.dflags & DREMOTE)
+				{
+#ifdef CONFIG_MOSIX_DEBUG
+					if(ds_debug & DSDEB_DFSA)
+					printk("%d(%s)-File <%s> Did not open, "
+						"mode=%d\n", current->pid,
+						current->comm, tmp, imode);
+#endif /* CONFIG_MOSIX_DEBUG */
+					filp_close(f, NULL);
+					error = -EDOITATHOME;
+					goto out_error;
+				}
+				current->mosix.dflags &= ~DSTATSDOWN;
+			}
+#ifdef CONFIG_MOSIX_DEBUG
+			if((current->mosix.dflags & DREMOTE) &&
+							(ds_debug & DSDEB_DFSA))
+				printk("%d(%s)-Opened <%s> Remotely, fd=%d, "
+					"ino=%ld\n", current->pid,
+					current->comm, tmp, (int)fd,
+					f->f_dentry->d_inode->i_ino);
+#endif /* CONFIG_MOSIX_DEBUG */
+#endif /* CONFIG_MOSIX_DFSA */
 			fd_install(fd, f);
 		}
 out:
@@ -809,6 +1030,10 @@
 out_error:
 	put_unused_fd(fd);
 	fd = error;
+#ifdef CONFIG_MOSIX_DFSA
+	if(error == -ETXTBSY && (current->mosix.dflags & DREMOTE))
+		error = -EDOITATHOME;
+#endif /* CONFIG_MOSIX_DFSA */
 	goto out;
 }
 
@@ -869,6 +1094,9 @@
 	FD_CLR(fd, files->close_on_exec);
 	__put_unused_fd(files, fd);
 	write_unlock(&files->file_lock);
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_close_file(fd);
+#endif /* CONFIG_MOSIX_DFSA */
 	return filp_close(filp, files);
 
 out_unlock:
@@ -876,6 +1104,35 @@
 	return -EBADF;
 }
 
+#ifdef CONFIG_MOSIX_DFSA
+/*
+ * almost like "sys_close", except for raising DSTATSDOWN in the right
+ * circumstances, which we cannot do this in "sys_close" itself only
+ * because it can be called from other system-calls.
+ * [wish they all called "do_close" instead!]
+ */
+asmlinkage long sys_close_syscall(unsigned int fd)
+{
+	register struct task_struct *p = current;
+
+	if((p->mosix.dflags & (DDEPUTY|DREMOTE)) || !CAN_DFSA(p))
+		goto call_sys;
+
+	/* no locking of "&p->files->file_lock" is needed because CAN_DFSA
+	 * included checking that no clones are sharing our files! */
+	if (fd >= p->files->max_fds)
+	/* if we were to run remotely, we could also "close" a bad file there!*/
+	{
+		p->mosix.dflags |= DSTATSDOWN;
+		return -EBADF;
+	}
+	if(can_dfsa_file(fd))	/* and we already know CAN_DFSA(p) is true */
+		p->mosix.dflags |= DSTATSDOWN;
+	call_sys:
+	return(sys_close(fd));
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * This routine simulates a hangup on the tty, to arrange that users
  * are given clean terminals at login time.
diff -Naur --exclude=CVS --exclude=configs linux/fs/pipe.c linux-openmosix/fs/pipe.c
--- linux/fs/pipe.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/pipe.c	2004-02-05 10:51:21.000000000 +0100
@@ -69,8 +69,24 @@
 			goto out;
 
 		for (;;) {
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+			unsigned long bytes, prev;
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 			PIPE_WAITING_READERS(*inode)++;
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+			bytes = count;
+			if (bytes > PIPE_BUF)
+				bytes = PIPE_BUF;
+			prev = PIPE_READING_BYTES(*inode);
+			PIPE_READING_BYTES(*inode) += bytes;
+			if (!prev && (PIPE_EXCEPTIONS(*inode) &
+							PIPE_EXCEPTION_INPUT))
+				wake_up_interruptible(PIPE_WAIT(*inode));
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 			pipe_wait(inode);
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+			PIPE_READING_BYTES(*inode) -= bytes;
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 			PIPE_WAITING_READERS(*inode)--;
 			ret = -ERESTARTSYS;
 			if (signal_pending(current))
@@ -259,6 +275,22 @@
 	return -EBADF;
 }
 
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+static inline int
+set_pipe_exceptions(struct inode *ip, unsigned long val)
+{
+	int oval = PIPE_EXCEPTIONS(*ip);
+
+	PIPE_EXCEPTIONS(*ip) = val;
+	if (val & ~(PIPE_EXCEPTION_INPUT|PIPE_EXCEPTION_NOINPUT))
+		return -EINVAL;
+	if (((val & PIPE_EXCEPTION_INPUT & ~oval) && PIPE_READING_BYTES(*ip))
+	    || ((val & PIPE_EXCEPTION_NOINPUT & ~oval) && !PIPE_READERS(*ip)))
+		wake_up_interruptible(PIPE_WAIT(*ip));
+	return 0;
+}
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
+
 static int
 pipe_ioctl(struct inode *pino, struct file *filp,
 	   unsigned int cmd, unsigned long arg)
@@ -266,6 +298,12 @@
 	switch (cmd) {
 		case FIONREAD:
 			return put_user(PIPE_LEN(*pino), (int *)arg);
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+		case TCSBRK:
+			return set_pipe_exceptions(pino, arg);
+		case TIOCGWINSZ:
+			return PIPE_READING_BYTES(*pino);
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 		default:
 			return -EINVAL;
 	}
@@ -288,6 +326,13 @@
 		mask |= POLLHUP;
 	if (!PIPE_READERS(*inode))
 		mask |= POLLERR;
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+	if (((PIPE_EXCEPTIONS(*inode) & PIPE_EXCEPTION_INPUT) &&
+		PIPE_READING_BYTES(*inode)) ||
+	    ((PIPE_EXCEPTIONS(*inode) & PIPE_EXCEPTION_NOINPUT) &&
+		!PIPE_READERS(*inode)))
+		mask |= POLLPRI;
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 
 	return mask;
 }
@@ -453,6 +498,9 @@
 	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
 	PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0;
 	PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+	PIPE_READING_BYTES(*inode) = PIPE_EXCEPTIONS(*inode) = 0;
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 
 	return inode;
 fail_page:
diff -Naur --exclude=CVS --exclude=configs linux/fs/proc/array.c linux-openmosix/fs/proc/array.c
--- linux/fs/proc/array.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/proc/array.c	2004-02-05 10:51:22.000000000 +0100
@@ -77,6 +77,13 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#include <linux/ptrace.h>
+#include <linux/smp_lock.h>
+#include <linux/file.h>
+#endif /* CONFIG_MOSIX */
+
 /* Gcc optimizes away "strlen(x)" for constant x */
 #define ADDBUF(buffer, string) \
 do { memcpy(buffer, string, strlen(string)); \
@@ -131,7 +138,12 @@
 
 static inline const char * get_task_state(struct task_struct *tsk)
 {
-	unsigned int state = tsk->state & (TASK_RUNNING |
+#ifdef CONFIG_MOSIX
+	unsigned int state = LOGICAL_STATE(tsk)
+#else
+	unsigned int state = tsk->state
+#endif /* CONFIG_MOSIX */ 
+					& (TASK_RUNNING |
 					   TASK_INTERRUPTIBLE |
 					   TASK_UNINTERRUPTIBLE |
 					   TASK_ZOMBIE |
@@ -177,7 +189,11 @@
 	return buffer;
 }
 
+#ifdef CONFIG_MOSIX
+inline char * task_mem(struct mm_struct *mm, char *buffer)
+#else
 static inline char * task_mem(struct mm_struct *mm, char *buffer)
+#endif /* CONFIG_MOSIX */
 {
 	struct vm_area_struct * vma;
 	unsigned long data = 0, stack = 0;
@@ -278,10 +294,18 @@
 {
 	char * orig = buffer;
 	struct mm_struct *mm;
+#ifdef CONFIG_MOSIX
+	int should_ask = 0;
+#endif /* CONFIG_MOSIX */
 
 	buffer = task_name(task, buffer);
 	buffer = task_state(task, buffer);
 	task_lock(task);
+#ifdef CONFIG_MOSIX
+	if((should_ask = SHOULD_ASK_PROCESS(task)))
+		mm = NULL;
+	else
+#endif /* CONFIG_MOSIX */
 	mm = task->mm;
 	if(mm)
 		atomic_inc(&mm->mm_users);
@@ -290,6 +314,10 @@
 		buffer = task_mem(mm, buffer);
 		mmput(mm);
 	}
+#ifdef CONFIG_MOSIX
+	else if(should_ask)
+		buffer = request_process_to_buf(task,buffer,PR_PROCFS_TASK_MEM);
+#endif /* CONFIG_MOSIX */
 	buffer = task_sig(task, buffer);
 	buffer = task_cap(task, buffer);
 #if defined(CONFIG_ARCH_S390)
@@ -298,10 +326,153 @@
 	return buffer - orig;
 }
 
+#ifdef CONFIG_MOSIX
+
+int proc_pid_where(struct task_struct *task, char *buffer)
+{
+	task_lock(task);
+	sprintf(buffer, "%d\n", (task->mosix.stay & DSTAY_SYSTEM) ? 0 :
+							task->mosix.whereami);
+	task_unlock(task);
+	return (strlen(buffer));
+}
+
+int proc_pid_lock(struct task_struct *task, char *buffer)
+{
+	sprintf(buffer, "%d\n", (task->mosix.stay & DNOMIGRATE) ? 1 : 0);
+	buffer[2] = '\0';
+	return(2);	/* == strlen(buffer) */
+}
+
+int proc_pid_disclosure(struct task_struct *task, char *buffer)
+{
+	sprintf(buffer, "%d\n", task->mosix.disclosure);
+	return(strlen(buffer));
+}
+
+int proc_pid_migfilter(struct task_struct *task, char *buffer)
+{
+	sprintf(buffer, "%d\n", (task->mosix.dflags & DMIGFILTER) ? 1 : 0);
+	buffer[2] = '\0';
+	return(2);	/* == strlen(buffer) */
+}
+
+int proc_pid_migpolicy(struct task_struct *task, char *buffer)
+{
+	sprintf(buffer, "%d\n", task->mosix.mask.migpolicy);
+	return(strlen(buffer));
+}
+
+int proc_pid_mignodes(struct task_struct *task, char *buffer)
+{
+	sprintf(buffer, "%08x\n", task->mosix.mask.mignodes);
+	return(strlen(buffer));
+}
+
+int proc_pid_miggroup(struct task_struct *task, char *buffer)
+{
+        sprintf(buffer, "%d\n", task->mosix.mask.miggroup);
+        return(strlen(buffer));
+}
+
+
+char *mosix_stay_string[] = {
+	"monkey",	"mmap_dev",	"VM86_mode",	"system",
+	"priv_inst",	"mem_lock",	"clone_vm",	"rt_sched",
+	"direct_io",	NULL,	"kiobuf",	NULL,
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	"extern_1",	"extern_2",	"extern_3",	"extern_4",
+	NULL,		NULL,		NULL,		"user_lock"
+};
+
+int proc_pid_cantmove(struct task_struct *task, char *buffer)
+{
+	typeof (task->mosix.stay) i;
+	unsigned int j;
+
+	for (buffer[0] = '\0' , j = 0 , i = 1 ; i ; i <<= 1 , j++)
+	if (task->mosix.stay & DSTAY & i)
+	{
+		if(buffer[0])
+			strcat(buffer, ", ");
+		strcat(buffer, mosix_stay_string[j] ? : "unrecognized");
+	}
+	if(buffer[0])
+		strcat(buffer, "\n");
+	return(strlen(buffer));
+}
+
+int proc_pid_nmigs(struct task_struct *task, char *buffer)
+{
+	task_lock(task);
+	sprintf(buffer, "%d\n", task->mosix.nmigs);
+	task_unlock(task);
+	return(strlen(buffer));
+}
+
+int proc_pid_sigmig(struct task_struct *task, char * buffer)
+{
+	sprintf(buffer, "%d\n", task->mosix.sigmig);
+	return(strlen(buffer));
+}
+
+#ifdef CONFIG_MOSIX_FS
+int proc_pid_selected(struct task_struct *task, char *buffer)
+{
+	sprintf(buffer, "%d\n", task->mosix.selected);
+	return(strlen(buffer));
+}
+#endif /* CONFIG_MOSIX_FS */
+
+void
+proc_get_stat_parts(struct task_struct *task, struct mm_struct *mm,
+					struct proc_remote_stat_parts *t)
+{
+	if (mm)
+	{
+		struct vm_area_struct *vma;
+
+		t->vsize = 0;
+		down_read(&mm->mmap_sem);
+		vma = mm->mmap;
+		while (vma) {
+			t->vsize += vma->vm_end - vma->vm_start;
+			vma = vma->vm_next;
+		}
+		t->rss = mm->rss;
+		t->start_code = mm->start_code;
+		t->end_code = mm->end_code;
+		t->start_stack = mm->start_stack;
+		up_read(&mm->mmap_sem);
+		if(task == current && (task->mosix.dflags & DREMOTE))
+		/* just in case EIP and/or ESP are held by DEPUTY: */
+			mosix_obtain_registers(
+				BIT_OF_REGISTER(eip)|BIT_OF_REGISTER(esp));
+		t->eip = KSTK_EIP(task);
+		t->esp = KSTK_ESP(task);
+	}
+	else
+		memset(t, 0, sizeof(*t));
+	t->priority = task->counter;
+	t->priority = 20 - (t->priority * 10 + DEF_COUNTER / 2) / DEF_COUNTER;
+	t->processor = task->processor;
+	if(task->mosix.dflags & DREMOTE)
+		t->processor += 32*PE;
+}
+#endif /* CONFIG_MOSIX */
+
 int proc_pid_stat(struct task_struct *task, char * buffer)
 {
+#ifdef CONFIG_MOSIX
+	unsigned long wchan;
+	long nice;
+	struct proc_remote_stat_parts rinfo;
+#else
 	unsigned long vsize, eip, esp, wchan;
 	long priority, nice;
+#endif /* CONFIG_MOSIX */
 	int tty_pgrp = -1, tty_nr = 0;
 	sigset_t sigign, sigcatch;
 	char state;
@@ -310,8 +481,36 @@
 	struct mm_struct *mm;
 
 	state = *get_task_state(task);
+#ifndef CONFIG_MOSIX
 	vsize = eip = esp = 0;
+#endif /* !CONFIG_MOSIX */
 	task_lock(task);
+#ifdef CONFIG_MOSIX
+	if (task->tty) {
+		tty_pgrp = task->tty->pgrp;
+		tty_nr = kdev_t_to_nr(task->tty->device);
+	}
+	if(SHOULD_ASK_PROCESS(task))
+	{
+		task_unlock(task);
+		if(request_process(task, &rinfo, PR_PROCFS_GET_STAT_PARTS, 0)<0)
+			memset((caddr_t)&rinfo, 0, sizeof(rinfo));
+		mm = NULL;
+	}
+	else
+	{
+		mm = task->mm;
+		if(mm)
+			atomic_inc(&mm->mm_users);
+		task_unlock(task);
+		proc_get_stat_parts(task, mm, &rinfo);
+	}
+	/* the following test has nothing to do with MOSIX - just security! */
+	if ((current->fsuid != task->euid ||
+	    !cap_issubset(task->cap_permitted, current->cap_permitted)) &&
+	    !capable(CAP_DAC_OVERRIDE))
+		rinfo.eip = rinfo.esp = 0;
+#else
 	mm = task->mm;
 	if(mm)
 		atomic_inc(&mm->mm_users);
@@ -332,6 +531,7 @@
 		esp = KSTK_ESP(task);
 		up_read(&mm->mmap_sem);
 	}
+#endif /* CONFIG_MOSIX */
 
 	wchan = get_wchan(task);
 
@@ -339,8 +539,10 @@
 
 	/* scale priority and nice values from timeslices to -20..20 */
 	/* to make it look like a "normal" Unix priority/nice value  */
+#ifndef CONFIG_MOSIX
 	priority = task->counter;
 	priority = 20 - (priority * 10 + DEF_COUNTER / 2) / DEF_COUNTER;
+#endif /* !CONFIG_MOSIX */
 	nice = task->nice;
 
 	read_lock(&tasklist_lock);
@@ -366,19 +568,36 @@
 		task->times.tms_stime,
 		task->times.tms_cutime,
 		task->times.tms_cstime,
+#ifdef CONFIG_MOSIX
+		rinfo.priority,
+#else
 		priority,
+#endif /* CONFIG_MOSIX */
 		nice,
 		0UL /* removed */,
 		task->it_real_value,
 		task->start_time,
+#ifdef CONFIG_MOSIX
+		rinfo.vsize,
+		rinfo.rss,
+#else
 		vsize,
 		mm ? mm->rss : 0, /* you might want to shift this left 3 */
+#endif /* CONFIG_MOSIX */
 		task->rlim[RLIMIT_RSS].rlim_cur,
+#ifdef CONFIG_MOSIX
+		rinfo.start_code,
+		rinfo.end_code,
+		rinfo.start_stack,
+		rinfo.esp,
+		rinfo.eip,
+#else
 		mm ? mm->start_code : 0,
 		mm ? mm->end_code : 0,
 		mm ? mm->start_stack : 0,
 		esp,
 		eip,
+#endif /* CONFIG_MOSIX */
 		/* The signal information here is obsolete.
 		 * It must be decimal for Linux 2.0 compatibility.
 		 * Use /proc/#/status for real-time signals.
@@ -391,7 +610,12 @@
 		task->nswap,
 		task->cnswap,
 		task->exit_signal,
-		task->processor);
+#ifdef CONFIG_MOSIX
+		(int)rinfo.processor
+#else
+		task->processor
+#endif /* CONFIG_MOSIX */
+		);
 	if(mm)
 		mmput(mm);
 	return res;
@@ -476,12 +700,24 @@
 {
 	struct mm_struct *mm;
 	int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
+#ifdef CONFIG_MOSIX
+	int should_ask = 0;
+#endif /* CONFIG_MOSIX */
 
 	task_lock(task);
+#ifdef CONFIG_MOSIX
+	if((should_ask = SHOULD_ASK_PROCESS(task)))
+		mm = NULL;
+	else
+#endif /* CONFIG_MOSIX */
 	mm = task->mm;
 	if(mm)
 		atomic_inc(&mm->mm_users);
 	task_unlock(task);
+#ifdef CONFIG_MOSIX
+	if(should_ask)
+		return(request_process(task, buffer, PR_PROCFS_GET_STATM, 0));
+#endif /* CONFIG_MOSIX */
 	if (mm) {
 		struct vm_area_struct * vma;
 		down_read(&mm->mmap_sem);
@@ -512,6 +748,44 @@
 		       size, resident, share, trs, lrs, drs, dt);
 }
 
+#ifdef CONFIG_MOSIX
+int proc_list_maps(struct vmamaps *maps, int start)
+{
+	struct mm_struct *mm;
+	struct vm_area_struct *map;
+	int i;
+
+	if (!(mm = current->mm))
+		return 0;
+	down_read(&mm->mmap_sem);
+	map = mm->mmap;
+	while (map && start-- > 0)
+		map = map->vm_next;
+	for (i = 0; map && i < PAGE_SIZE / sizeof(struct vmamaps); i++)
+	{
+		maps->vmstart = map->vm_start;
+		maps->vmend = map->vm_end;
+		maps->vmflags = map->vm_flags;
+		maps->vmpgoff = map->vm_pgoff;
+		maps->fp = map->vm_file ? home_file(map->vm_file) : 0;
+		maps++;
+		map = map->vm_next;
+	}
+	up_read(&mm->mmap_sem);
+	return i * sizeof(struct vmamaps);
+}
+
+void ref_mapped_files(struct vmamaps *maps, int len)
+{
+	unsigned int i;
+	struct file *fp;
+
+	for (i = 0; i < len / sizeof(struct vmamaps); i++)
+		if ((fp = maps[i].fp))
+			get_file(fp);
+}
+#endif /* CONFIG_MOSIX */
+
 static int show_map(struct seq_file *m, void *v)
 {
 	struct vm_area_struct *map = v;
@@ -607,6 +881,15 @@
 {
 	int i, len;
 
+#ifdef CONFIG_MOSIX
+	if(SHOULD_ASK_PROCESS(task))
+		request_process(task, buffer, PR_PROCFS_UPDATE_TIMES, 0);
+
+	if(task->mosix.nmigs) {
+                len += sprintf(buffer + len, "TIMES ON REMOTE CLUSTER NODES NOT LISTED\n");
+                return len;
+        }
+#endif /* CONFIG_MOSIX */
 	len = sprintf(buffer,
 		"cpu  %lu %lu\n",
 		task->times.tms_utime,
diff -Naur --exclude=CVS --exclude=configs linux/fs/proc/base.c linux-openmosix/fs/proc/base.c
--- linux/fs/proc/base.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/proc/base.c	2004-02-05 10:51:23.000000000 +0100
@@ -26,6 +26,11 @@
 #include <linux/seq_file.h>
 #include <linux/namespace.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#include <linux/smp_lock.h>
+#endif /* CONFIG_MOSIX */
+
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
  * Feel free to change the macro below - just keep the range distinct from
@@ -40,6 +45,21 @@
 int proc_pid_status(struct task_struct*,char*);
 int proc_pid_statm(struct task_struct*,char*);
 int proc_pid_cpu(struct task_struct*,char*);
+#ifdef CONFIG_MOSIX
+int proc_pid_where(struct task_struct*,char*);
+int proc_pid_nmigs(struct task_struct*,char*);
+int proc_pid_cantmove(struct task_struct*,char*);
+int proc_pid_lock(struct task_struct*,char*);
+int proc_pid_sigmig(struct task_struct*,char*);
+int proc_pid_disclosure(struct task_struct*,char*);
+int proc_pid_migfilter(struct task_struct*,char*);
+int proc_pid_migpolicy(struct task_struct*,char*);
+int proc_pid_mignodes(struct task_struct*,char*);
+int proc_pid_miggroup(struct task_struct*,char*);
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_FS
+int proc_pid_selected(struct task_struct*,char*);
+#endif /* CONFIG_MOSIX_FS */
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
@@ -51,6 +71,32 @@
 	return -ENOENT;
 }
 
+#ifdef CONFIG_MOSIX
+struct file *
+first_executable(void)
+{
+	struct mm_struct *mm = current->mm;
+	register struct vm_area_struct *vma;
+	struct file *f = NULL;
+
+	if(!mm)
+		return(NULL);
+	down_read(&mm->mmap_sem);
+	for(vma = current->mm->mmap ; vma ; vma = vma->vm_next)
+	if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
+	{
+		f = vma->vm_file;
+		if(current->mosix.dflags & DREMOTE)
+			f = home_file(f);
+		else
+			get_file(f);
+		break;
+	}
+	up_read(&mm->mmap_sem);
+	return(f);
+}
+#endif /* CONFIG_MOSIX */
+
 static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
 	struct mm_struct * mm;
@@ -59,6 +105,24 @@
 	struct task_struct *task = inode->u.proc_i.task;
 
 	task_lock(task);
+#ifdef CONFIG_MOSIX
+	if(SHOULD_ASK_PROCESS(task))
+	{
+		struct file *f;
+
+		task_unlock(task);
+		f = (struct file *)request_process(task, &f,
+							PR_PROCFS_GET_EXE, 0);
+		if(f && !IS_ERR(f))
+		{
+			*mnt = mntget(f->f_vfsmnt);
+			*dentry = dget(f->f_dentry);
+			result = 0;
+			fput(f);
+		}
+		goto out;
+	}
+#endif /* CONFIG_MOSIX */
 	mm = task->mm;
 	if (mm)
 		atomic_inc(&mm->mm_users);
@@ -87,6 +151,12 @@
 {
 	struct fs_struct *fs;
 	int result = -ENOENT;
+#ifdef CONFIG_MOSIX_DFSA
+	struct task_struct *p = inode->u.proc_i.task;
+
+	if(SHOULD_ASK_PROCESS(p))
+		request_process(p, NULL, PR_DFSA_SYNCHRONIZE, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	task_lock(inode->u.proc_i.task);
 	fs = inode->u.proc_i.task->fs;
 	if(fs)
@@ -153,36 +223,56 @@
 	return retval;
 }
 
+#ifdef CONFIG_MOSIX
+int proc_pid_environ(struct task_struct *task, char * buffer)
+#else
 static int proc_pid_environ(struct task_struct *task, char * buffer)
+#endif /* CONFIG_MOSIX */
 {
 	struct mm_struct *mm;
 	int res = 0;
-
-	if (!may_ptrace_attach(task))
-		return -ESRCH;
-
+ 	if (!may_ptrace_attach(task))
+ 		return -ESRCH;
 	task_lock(task);
+#ifdef CONFIG_MOSIX
+	if(SHOULD_ASK_PROCESS(task))
+	{
+		task_unlock(task);
+		return(request_process(task, buffer, PR_PROCFS_GET_ENV, 0));
+	}
+#endif /* CONFIG_MOSIX */
 	mm = task->mm;
 	if (mm)
 		atomic_inc(&mm->mm_users);
 	task_unlock(task);
 	if (mm) {
-		unsigned int len = mm->env_end - mm->env_start;
+ 		unsigned int len = mm->env_end - mm->env_start;
 		if (len > PAGE_SIZE)
 			len = PAGE_SIZE;
 		res = access_process_vm(task, mm->env_start, buffer, len, 0);
-		if (!may_ptrace_attach(task))
-			res = -ESRCH;
+ 		if (!may_ptrace_attach(task))
+ 			res = -ESRCH;
 		mmput(mm);
 	}
 	return res;
 }
 
+#ifdef CONFIG_MOSIX
+int proc_pid_cmdline(struct task_struct *task, char * buffer)
+#else
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
+#endif /* CONFIG_MOSIX */
 {
 	struct mm_struct *mm;
 	int res = 0;
 	task_lock(task);
+#ifdef CONFIG_MOSIX
+	if(SHOULD_ASK_PROCESS(task))
+	{
+		task_unlock(task);
+		return(request_process(task, buffer, PR_PROCFS_GET_ARG, 0));
+	}
+#endif /* CONFIG_MOSIX */
 	mm = task->mm;
 	if (mm)
 		atomic_inc(&mm->mm_users);
@@ -233,6 +323,10 @@
 	our_vfsmnt = mntget(current->fs->rootmnt);
 	base = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
+#ifdef CONFIG_MOSIX
+	if(!root)	/* hope it will be fixed by 2.4.0 */
+		return(-ENOENT);
+#endif /* CONFIG_MOSIX */
 
 	spin_lock(&dcache_lock);
 	de = root;
@@ -367,6 +461,7 @@
 	read:		proc_info_read,
 };
 
+
 static int mem_open(struct inode* inode, struct file* file)
 {
 	file->private_data = (void*)((long)current->self_exec_id);
@@ -394,12 +489,18 @@
 	if (mm)
 		atomic_inc(&mm->mm_users);
 	task_unlock(task);
+#ifndef CONFIG_MOSIX
 	if (!mm){
 		copied = 0;
 		goto out_free;
 	}
+#endif /* CONFIG_MOSIX */
+
 
 	if (file->private_data != (void*)((long)current->self_exec_id) ) {
+#ifdef CONFIG_MOSIX
+	  	if (mm)
+#endif /* CONFIG_MOSIX */
 		mmput(mm);
 		copied = -EIO;
 		goto out_free;
@@ -425,6 +526,9 @@
 		count -= retval;
 	}
 	*ppos = src;
+#ifdef CONFIG_MOSIX
+	if(mm)
+#endif /* CONFIG_MOSIX */
 	mmput(mm);
 
 out_free:
@@ -598,6 +702,24 @@
 	PROC_PID_STATM,
 	PROC_PID_MAPS,
 	PROC_PID_CPU,
+#ifdef CONFIG_MOSIX
+	PROC_PID_WHERE,
+	PROC_PID_MIGRATE,
+	PROC_PID_GOTO,
+	PROC_PID_LOCK,
+	PROC_PID_NMIGS,
+	PROC_PID_CANTMOVE,
+	PROC_PID_SIGMIG,
+	PROC_PID_DISCLOSURE,
+	PROC_PID_MIGFILTER,
+	PROC_PID_MIGPOLICY,
+	PROC_PID_MIGNODES,
+	PROC_PID_MIGGROUP,
+#ifdef CONFIG_MOSIX_FS
+	PROC_PID_SELECTED,
+#endif /* CONFIG_MOSIX_FS */
+	PROC_PID_MOSIX_START = PROC_MOSIX_USE_START,
+#endif /* CONFIG_MOSIX */
 	PROC_PID_MOUNTS,
 	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
@@ -619,6 +741,23 @@
   E(PROC_PID_ROOT,	"root",		S_IFLNK|S_IRWXUGO),
   E(PROC_PID_EXE,	"exe",		S_IFLNK|S_IRWXUGO),
   E(PROC_PID_MOUNTS,	"mounts",	S_IFREG|S_IRUGO),
+#ifdef CONFIG_MOSIX
+  E(PROC_PID_WHERE,	"where",	S_IFREG|S_IRUGO),
+  E(PROC_PID_MIGRATE,	"migrate",	S_IFREG|S_IWUSR),
+  E(PROC_PID_GOTO,	"goto",		S_IFREG|S_IWUGO),
+  E(PROC_PID_LOCK,	"lock",		S_IFREG|S_IRUGO|S_IWUSR),
+  E(PROC_PID_NMIGS,	"nmigs",	S_IFREG|S_IRUGO),
+  E(PROC_PID_CANTMOVE,	"cantmove",	S_IFREG|S_IRUGO),
+  E(PROC_PID_SIGMIG,	"sigmig",	S_IFREG|S_IRUGO|S_IWUSR),
+  E(PROC_PID_DISCLOSURE,"disclosure",	S_IFREG|S_IRUGO|S_IWUSR),
+  E(PROC_PID_MIGFILTER,	"migfilter",	S_IFREG|S_IRUGO|S_IWUSR),
+  E(PROC_PID_MIGPOLICY,	"migpolicy",	S_IFREG|S_IRUGO|S_IWUSR),
+  E(PROC_PID_MIGNODES,	"mignodes",	S_IFREG|S_IRUGO|S_IWUSR),
+  E(PROC_PID_MIGGROUP,  "miggroup",	S_IFREG|S_IRUGO|S_IWUSR),
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_FS
+  E(PROC_PID_SELECTED,	"selected",	S_IFREG|S_IRUGO|S_IWUSR),
+#endif /* CONFIG_MOSIX_FS */
   {0,0,NULL,0}
 };
 #undef E
@@ -649,6 +788,10 @@
 				goto out;
 			filp->f_pos++;
 		default:
+#ifdef CONFIG_MOSIX_DFSA
+			if(SHOULD_ASK_PROCESS(p))
+				request_process(p, NULL, PR_DFSA_SYNCHRONIZE,0);
+#endif /* CONFIG_MOSIX_DFSA */
 			task_lock(p);
 			files = p->files;
 			if (files)
@@ -731,7 +874,11 @@
 
 /* building an inode */
 
+#ifdef CONFIG_MOSIX
+int task_dumpable(struct task_struct *task)
+#else
 static int task_dumpable(struct task_struct *task)
+#endif /* CONFIG_MOSIX */
 {
 	int dumpable = 0;
 	struct mm_struct *mm;
@@ -740,6 +887,11 @@
 	mm = task->mm;
 	if (mm)
 		dumpable = mm->dumpable;
+#ifdef CONFIG_MOSIX
+	else if((current->mosix.dflags & (DDEPUTY|DDUMPABLE)) ==
+							(DDEPUTY|DDUMPABLE))
+		dumpable = 1;
+#endif /* CONFIG_MOSIX */
 	task_unlock(task);
 	return dumpable;
 }
@@ -856,6 +1008,10 @@
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd);
 	if (!inode)
 		goto out;
+#ifdef CONFIG_MOSIX_DFSA
+	if(SHOULD_ASK_PROCESS(task))
+		request_process(task, NULL, PR_DFSA_SYNCHRONIZE,0);
+#endif /* CONFIG_MOSIX_DFSA */
 	task_lock(task);
 	files = task->files;
 	if (files)
@@ -904,6 +1060,64 @@
 	permission:	proc_permission,
 };
 
+#ifdef CONFIG_MOSIX
+static int
+proc_pid_writeonly(struct task_struct *doesnt_matter, char *buf)
+{
+	return(-EPERM);
+}
+
+static ssize_t
+proc_mosix_write(struct file *file, const char *buf, size_t cnt, loff_t *ppos)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	ssize_t result = -EPERM;
+	struct task_struct *task = inode->u.proc_i.task;
+
+	switch(inode->i_ino & 0xffff)
+	{
+	    case PROC_PID_MIGRATE:
+		result = proc_mosix_pid_set_migrate(file, task, buf, cnt);
+		break;
+	    case PROC_PID_GOTO:
+		result = proc_mosix_pid_set_goto(file, task, buf, cnt);
+		break;
+	    case PROC_PID_LOCK:
+		result = proc_mosix_pid_set_lock(file, task, buf, cnt);
+		break;
+	    case PROC_PID_SIGMIG:
+		result = proc_mosix_pid_set_sigmig(file, task, buf, cnt);
+		break;
+	    case PROC_PID_DISCLOSURE:
+		result = proc_mosix_pid_set_disclosure(file, task, buf, cnt);
+		break;
+	    case PROC_PID_MIGFILTER:
+		result = proc_mosix_pid_set_migfilter(file, task, buf, cnt);
+		break;
+	    case PROC_PID_MIGPOLICY:
+		result = proc_mosix_pid_set_migpolicy(file, task, buf, cnt);
+		break;
+	    case PROC_PID_MIGNODES:
+		result = proc_mosix_pid_set_mignodes(file, task, buf, cnt);
+		break;
+            case PROC_PID_MIGGROUP:
+                result = proc_mosix_pid_set_miggroup(file, task, buf, cnt);
+                break;
+#ifdef CONFIG_MOSIX_FS
+	    case PROC_PID_SELECTED:
+		result = proc_mosix_pid_set_selected(file, task, buf, cnt);
+		break;
+#endif /* CONFIG_MOSIX_FS */
+	}
+	return(result);
+}
+
+static struct file_operations proc_mosix_file_operations = {
+	read: proc_info_read,
+	write: proc_mosix_write,
+};
+#endif /* CONFIG_MOSIX */
+
 static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode;
@@ -987,6 +1201,62 @@
 		case PROC_PID_MOUNTS:
 			inode->i_fop = &proc_mounts_operations;
 			break;
+#ifdef CONFIG_MOSIX
+		case PROC_PID_WHERE:
+			inode->i_fop = &proc_info_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_where;
+			break;
+		case PROC_PID_NMIGS:
+			inode->i_fop = &proc_info_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_nmigs;
+			break;
+		case PROC_PID_CANTMOVE:
+			inode->i_fop = &proc_info_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_cantmove;
+			break;
+		case PROC_PID_MIGRATE:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_writeonly;
+			break;
+		case PROC_PID_GOTO:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_writeonly;
+			break;
+		case PROC_PID_LOCK:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_lock;
+			break;
+		case PROC_PID_SIGMIG:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_sigmig;
+			break;
+		case PROC_PID_DISCLOSURE:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_disclosure;
+			break;
+		case PROC_PID_MIGFILTER:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_migfilter;
+			break;
+		case PROC_PID_MIGPOLICY:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_migpolicy;
+			break;
+		case PROC_PID_MIGNODES:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_mignodes;
+			break;
+                case PROC_PID_MIGGROUP:
+                        inode->i_fop = &proc_mosix_file_operations;
+                        inode->u.proc_i.op.proc_read = proc_pid_miggroup;
+                        break;
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_FS
+		case PROC_PID_SELECTED:
+			inode->i_fop = &proc_mosix_file_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_selected;
+			break;
+#endif /* CONFIG_MOSIX_FS */
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
@@ -1101,6 +1371,14 @@
 {
 	if (inode->u.proc_i.file)
 		fput(inode->u.proc_i.file);
+#ifdef CONFIG_MOSIX
+	{
+		int ino = inode->i_ino & 0xffff;
+
+		if(ino >= PROC_PID_MOSIX_START && ino < PROC_PID_FD_DIR)
+			return;
+	}
+#endif /* CONFIG_MOSIX */
 	if (inode->u.proc_i.task)
 		free_task_struct(inode->u.proc_i.task);
 }
@@ -1120,7 +1398,11 @@
 
 	index--;
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		int pid = p->pid;
 		if (!pid)
 			continue;
diff -Naur --exclude=CVS --exclude=configs linux/fs/proc/generic.c linux-openmosix/fs/proc/generic.c
--- linux/fs/proc/generic.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/proc/generic.c	2004-02-05 10:51:23.000000000 +0100
@@ -359,7 +359,11 @@
 	lookup:		proc_lookup,
 };
 
+#ifdef CONFIG_MOSIX
+int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
+#else
 static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
+#endif /* CONFIG_MOSIX */
 {
 	int	i;
 	
diff -Naur --exclude=CVS --exclude=configs linux/fs/proc/inode.c linux-openmosix/fs/proc/inode.c
--- linux/fs/proc/inode.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/proc/inode.c	2004-02-05 10:51:23.000000000 +0100
@@ -195,7 +195,11 @@
 	 * Fixup the root inode's nlink value
 	 */
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) if (p->pid) root_inode->i_nlink++;
+#else
 	for_each_task(p) if (p->pid) root_inode->i_nlink++;
+#endif /* CONFIG_MOSIX */
 	read_unlock(&tasklist_lock);
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
diff -Naur --exclude=CVS --exclude=configs linux/fs/proc/proc_misc.c linux-openmosix/fs/proc/proc_misc.c
--- linux/fs/proc/proc_misc.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/fs/proc/proc_misc.c	2004-02-05 10:51:23.000000000 +0100
@@ -157,7 +157,7 @@
 {
 	struct sysinfo i;
 	int len;
-	int pg_size ;
+	int pg_size, committed;
 
 /*
  * display in kilobytes.
@@ -194,7 +194,8 @@
 		"LowTotal:     %8lu kB\n"
 		"LowFree:      %8lu kB\n"
 		"SwapTotal:    %8lu kB\n"
-		"SwapFree:     %8lu kB\n",
+		"SwapFree:     %8lu kB\n"
+		"Committed_AS: %8u kB\n",
 		K(i.totalram),
 		K(i.freeram),
 		K(i.sharedram),
@@ -208,7 +209,8 @@
 		K(i.totalram-i.totalhigh),
 		K(i.freeram-i.freehigh),
 		K(i.totalswap),
-		K(i.freeswap));
+		K(i.freeswap),
+		K(committed));
 
 	return proc_calc_metrics(page, start, off, count, eof, len);
 #undef B
diff -Naur --exclude=CVS --exclude=configs linux/fs/proc/root.c linux-openmosix/fs/proc/root.c
--- linux/fs/proc/root.c	2002-08-03 02:39:45.000000000 +0200
+++ linux-openmosix/fs/proc/root.c	2004-02-05 10:51:23.000000000 +0100
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  proc root directory handling functions
+ *  addes some stuff for openMosix (/proc/hpc)
  */
 
 #include <asm/uaccess.h>
@@ -17,7 +18,14 @@
 #include <linux/module.h>
 #include <asm/bitops.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
+#ifdef CONFIG_MOSIX
+struct proc_dir_entry *proc_mosix;
+#endif /* CONFIG_MOSIX */
 
 #ifdef CONFIG_SYSCTL
 struct proc_dir_entry *proc_sys_root;
@@ -48,6 +56,10 @@
 	proc_mkdir("sys/fs", 0);
 	proc_mkdir("sys/fs/binfmt_misc", 0);
 #endif
+#ifdef CONFIG_MOSIX
+	proc_mosix = proc_mkdir("hpc", 0);
+	mosix_proc_init();
+#endif /* CONFIG_MOSIX */
 	proc_root_fs = proc_mkdir("fs", 0);
 	proc_root_driver = proc_mkdir("driver", 0);
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
@@ -76,6 +88,9 @@
 		int nlink = proc_root.nlink;
 
 		nlink += nr_threads;
+#ifdef CONFIG_MOSIX
+		nlink -= count_guests();
+#endif /* CONFIG_MOSIX */
 
 		dir->i_nlink = nlink;
 	}
diff -Naur --exclude=CVS --exclude=configs linux/fs/readdir.c linux-openmosix/fs/readdir.c
--- linux/fs/readdir.c	2002-08-03 02:39:45.000000000 +0200
+++ linux-openmosix/fs/readdir.c	2004-02-05 10:51:21.000000000 +0100
@@ -5,6 +5,10 @@
  */
 
 #include <linux/sched.h>
+#ifdef CONFIG_MOSIX
+#include <linux/stddef.h>
+#include <linux/dirent.h>
+#endif /* CONFIG_MOSIX */
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
@@ -13,6 +17,10 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 int vfs_readdir(struct file *file, filldir_t filler, void *buf)
 {
 	struct inode *inode = file->f_dentry->d_inode;
@@ -193,11 +201,30 @@
 		return -EINVAL;
 	buf->count++;
 	dirent = buf->dirent;
+#ifdef CONFIG_MOSIX
+	{
+		union
+		{
+			struct old_linux_dirent o;
+			struct dirent d;
+		} u;
+
+		u.o.d_ino = ino;
+		u.o.d_offset = offset;
+		u.o.d_namlen = namlen;
+		memcpy(u.d.d_name, name, namlen);
+		u.d.d_name[namlen] = '\0';
+		copy_to_user(dirent, &u,
+			offsetof(struct old_linux_dirent, d_name[0]) +
+				namlen + 1);
+	}
+#else
 	put_user(ino, &dirent->d_ino);
 	put_user(offset, &dirent->d_offset);
 	put_user(namlen, &dirent->d_namlen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
+#endif /* CONFIG_MOSIX */
 	return 0;
 }
 
@@ -207,6 +234,9 @@
 	struct file * file;
 	struct readdir_callback buf;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -215,7 +245,13 @@
 	buf.count = 0;
 	buf.dirent = dirent;
 
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits |= MFSARG_OLDREADDIR;
+#endif /* CONFIG_MOSIX_FS */
 	error = vfs_readdir(file, fillonedir, &buf);
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits &= ~MFSARG_OLDREADDIR;
+#endif /* CONFIG_MOSIX_FS */
 	if (error >= 0)
 		error = buf.count;
 
@@ -250,6 +286,9 @@
 	struct linux_dirent * dirent;
 	struct getdents_callback * buf = (struct getdents_callback *) __buf;
 	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+#ifdef CONFIG_MOSIX
+	struct dirent d;
+#endif /* CONFIG_MOSIX */
 
 	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
@@ -260,9 +299,24 @@
 	dirent = buf->current_dir;
 	buf->previous = dirent;
 	put_user(ino, &dirent->d_ino);
+#ifdef CONFIG_MOSIX
+/* access to remote-data is much faster in one block */
+	d.d_reclen = reclen;
+	memcpy(d.d_name, name, namlen);
+	d.d_name[namlen] = '\0';
+/* NOTICE:
+We take great liberty to fill the potential round-up byte(s)
+that are not filled by standard Linux.
+SORRY - performance would be horrible otherwise with all the fragmentation.
+*/
+
+	copy_to_user(&dirent->d_reclen, &d.d_reclen,
+				reclen - offsetof(struct dirent, d_reclen));
+#else
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
+#endif /* CONFIG_MOSIX */
 	((char *) dirent) += reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
@@ -276,6 +330,9 @@
 	struct getdents_callback buf;
 	int error;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -286,7 +343,14 @@
 	buf.count = count;
 	buf.error = 0;
 
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits |= MFSARG_GETDENTS;
+	current->mosix.dirty_arg = count;
+#endif /* CONFIG_MOSIX_FS */
 	error = vfs_readdir(file, filldir, &buf);
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits &= ~MFSARG_GETDENTS;
+#endif /* CONFIG_MOSIX_FS */
 	if (error < 0)
 		goto out_putf;
 	error = buf.error;
@@ -359,6 +423,9 @@
 	struct getdents_callback64 buf;
 	int error;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -369,7 +436,14 @@
 	buf.count = count;
 	buf.error = 0;
 
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits |= MFSARG_GETDENTS64;
+	current->mosix.dirty_arg = count;
+#endif /* CONFIG_MOSIX_FS */
 	error = vfs_readdir(file, filldir64, &buf);
+#ifdef CONFIG_MOSIX_FS
+	current->mosix.dirty_bits &= ~MFSARG_GETDENTS64;
+#endif /* CONFIG_MOSIX_FS */
 	if (error < 0)
 		goto out_putf;
 	error = buf.error;
diff -Naur --exclude=CVS --exclude=configs linux/fs/read_write.c linux-openmosix/fs/read_write.c
--- linux/fs/read_write.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/read_write.c	2004-02-05 10:51:21.000000000 +0100
@@ -29,6 +29,10 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 struct file_operations generic_ro_fops = {
 	llseek:		generic_file_llseek,
 	read:		generic_file_read,
@@ -91,7 +95,11 @@
 	return retval;
 }
 
+#ifdef CONFIG_MOSIX_FS
+inline loff_t llseek(struct file *file, loff_t offset, int origin)
+#else
 static inline loff_t llseek(struct file *file, loff_t offset, int origin)
+#endif /* CONFIG_MOSIX_FS */
 {
 	loff_t (*fn)(struct file *, loff_t, int);
 	loff_t retval;
@@ -110,6 +118,9 @@
 	off_t retval;
 	struct file * file;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	retval = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -135,6 +146,9 @@
 	struct file * file;
 	loff_t offset;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	retval = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -164,6 +178,9 @@
 	ssize_t ret;
 	struct file * file;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	ret = -EBADF;
 	file = fget(fd);
 	if (file) {
@@ -189,6 +206,9 @@
 	ssize_t ret;
 	struct file * file;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	ret = -EBADF;
 	file = fget(fd);
 	if (file) {
@@ -333,6 +353,9 @@
 	ssize_t ret;
 
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	ret = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -353,6 +376,9 @@
 	ssize_t ret;
 
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 	ret = -EBADF;
 	file = fget(fd);
 	if (!file)
diff -Naur --exclude=CVS --exclude=configs linux/fs/stat.c linux-openmosix/fs/stat.c
--- linux/fs/stat.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/stat.c	2004-02-05 10:51:21.000000000 +0100
@@ -13,6 +13,14 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#include <linux/slab.h>
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * Revalidate the inode. This is required for proper NFS attribute caching.
  */
@@ -125,6 +133,14 @@
 		tmp.st_blocks = inode->i_blocks;
 		tmp.st_blksize = inode->i_blksize;
 	}
+#ifdef CONFIG_MOSIX_FS
+	if(inode->i_sb && inode->i_sb->s_magic == MFS_SUPER_MAGIC)
+	{
+		tmp.__unused1 = inode->u.mfs_i.pe;
+		tmp.__unused2 = inode->i_generation;
+		tmp.__unused3 = inode->i_version;
+	}
+#endif /* CONFIG_MOSIX_FS */
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -139,7 +155,28 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_STAT;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+	{
+		if(nd.complete_parg)
+		{
+			error = cp_old_stat((struct inode *)nd.complete_parg,
+								statbuf);
+			kfree(nd.complete_parg);
+		}
+		return(error);
+	}
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW| LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = do_revalidate(nd.dentry);
 		if (!error)
@@ -155,7 +192,28 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_STAT;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+	{
+		if(nd.complete_parg)
+		{
+			error = cp_new_stat((struct inode *)nd.complete_parg,
+								statbuf);
+			kfree(nd.complete_parg);
+		}
+		return(error);
+	}
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = do_revalidate(nd.dentry);
 		if (!error)
@@ -176,7 +234,27 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_STAT;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS|
+							LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+	{
+		if(nd.complete_parg)
+		{
+			error = cp_old_stat((struct inode *)nd.complete_parg,
+								statbuf);
+			kfree(nd.complete_parg);
+		}
+		return(error);
+	}
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk_link(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = do_revalidate(nd.dentry);
 		if (!error)
@@ -193,7 +271,27 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_STAT;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS|
+							LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+	{
+		if(nd.complete_parg)
+		{
+			error = cp_new_stat((struct inode *)nd.complete_parg,
+								statbuf);
+			kfree(nd.complete_parg);
+		}
+		return(error);
+	}
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk_link(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = do_revalidate(nd.dentry);
 		if (!error)
@@ -214,6 +312,9 @@
 	struct file * f;
 	int err = -EBADF;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	f = fget(fd);
 	if (f) {
 		struct dentry * dentry = f->f_dentry;
@@ -233,6 +334,9 @@
 	struct file * f;
 	int err = -EBADF;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	f = fget(fd);
 	if (f) {
 		struct dentry * dentry = f->f_dentry;
@@ -253,7 +357,21 @@
 	if (bufsiz <= 0)
 		return -EINVAL;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_READLINK;
+	nd.complete_args.buffer.buf = buf;
+	nd.complete_args.buffer.bufsiz = bufsiz;
+	error = __user_walk(path, LOOKUP_POSITIVE|LOOKUP_STAYFS|LOOKUP_COMPLETE,
+									&nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+		return(error);
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(path, LOOKUP_POSITIVE|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk_link(path, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		struct inode * inode = nd.dentry->d_inode;
 
@@ -328,6 +446,14 @@
 		tmp.st_blocks = inode->i_blocks;
 		tmp.st_blksize = inode->i_blksize;
 	}
+#ifdef CONFIG_MOSIX_FS
+	if(inode->i_sb && inode->i_sb->s_magic == MFS_SUPER_MAGIC)
+	{
+		STAT64_NODE(tmp) = inode->u.mfs_i.pe;
+		STAT64_ORIGDEV(tmp) = inode->i_generation;
+		STAT64_ORIGINO(tmp) = inode->i_version;
+	}
+#endif /* CONFIG_MOSIX_FS */
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -336,7 +462,28 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_STAT;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_FOLLOW|
+					LOOKUP_STAYFS|LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+	{
+		if(nd.complete_parg)
+		{
+			error = cp_new_stat64((struct inode *)nd.complete_parg,
+								statbuf);
+			kfree(nd.complete_parg);
+		}
+		return(error);
+	}
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename,
+			LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = do_revalidate(nd.dentry);
 		if (!error)
@@ -351,7 +498,27 @@
 	struct nameidata nd;
 	int error;
 
+#ifdef CONFIG_MOSIX_FS
+	nd.express_function = EF_STAT;
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS|
+							LOOKUP_COMPLETE, &nd);
+	if(nd.complete_flags & COMPLETE_DONE)
+	{
+		if(nd.complete_parg)
+		{
+			error = cp_new_stat64((struct inode *)nd.complete_parg,
+								statbuf);
+			kfree(nd.complete_parg);
+		}
+		return(error);
+	}
+#else
+#ifdef CONFIG_MOSIX_DFSA
+	error = __user_walk(filename, LOOKUP_POSITIVE|LOOKUP_STAYFS, &nd);
+#else
 	error = user_path_walk_link(filename, &nd);
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX_FS */
 	if (!error) {
 		error = do_revalidate(nd.dentry);
 		if (!error)
@@ -366,6 +533,9 @@
 	struct file * f;
 	int err = -EBADF;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_syscall_on_file(fd, 0);
+#endif /* CONFIG_MOSIX_DFSA */
 	f = fget(fd);
 	if (f) {
 		struct dentry * dentry = f->f_dentry;
diff -Naur --exclude=CVS --exclude=configs linux/fs/super.c linux-openmosix/fs/super.c
--- linux/fs/super.c	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/fs/super.c	2004-02-05 10:51:21.000000000 +0100
@@ -18,6 +18,7 @@
  *    Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
  *  Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
  *  Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
+ *  Changed to include trylock routing       openMosix Aug 23, 2002
  */
 
 #include <linux/config.h>
@@ -575,8 +576,13 @@
  * filesystems which don't use real block-devices.  -- jrs
  */
 
+#ifdef CONFIG_MOSIX_FS
+enum {Max_anon = 255};
+static unsigned long unnamed_dev_in_use[(Max_anon+1)/(8*sizeof(unsigned long))];
+#else
 enum {Max_anon = 256};
 static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
+#endif /* CONFIG_MOSIX_FS */
 static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
 
 /**
@@ -585,6 +591,10 @@
  */
 static void put_anon_dev(kdev_t dev)
 {
+#ifdef CONFIG_MOSIX_FS
+	if(MINOR(dev) == Max_anon)
+		return;
+#endif /*CONFIG_MOSIX_FS */
 	spin_lock(&unnamed_dev_lock);
 	clear_bit(MINOR(dev), unnamed_dev_in_use);
 	spin_unlock(&unnamed_dev_lock);
@@ -635,16 +645,25 @@
 		return old;
 	}
 
-	spin_lock(&unnamed_dev_lock);
-	dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
-	if (dev == Max_anon) {
+#ifdef CONFIG_MOSIX_FS
+	if(!strcmp(type->name, "mfs"))
+		dev = mk_kdev(UNNAMED_MAJOR, Max_anon); /* changed from MKDEV to mk_kdev for 2.5 compat - Amit */
+	else
+	  {
+#endif /* CONFIG_MOSIX_FS */
+		spin_lock(&unnamed_dev_lock);
+		dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
+		if (dev == Max_anon) {
+			spin_unlock(&unnamed_dev_lock);
+			spin_unlock(&sb_lock);
+			destroy_super(s);
+			return ERR_PTR(-EMFILE);
+		}
+		set_bit(dev, unnamed_dev_in_use);
 		spin_unlock(&unnamed_dev_lock);
-		spin_unlock(&sb_lock);
-		destroy_super(s);
-		return ERR_PTR(-EMFILE);
+#ifdef CONFIG_MOSIX_FS
 	}
-	set_bit(dev, unnamed_dev_in_use);
-	spin_unlock(&unnamed_dev_lock);
+#endif /* CONFIG_MOSIX_FS */
 
 	s->s_dev = dev;
 	insert_super(s, type);
diff -Naur --exclude=CVS --exclude=configs linux/fs/umsdos/ioctl.c linux-openmosix/fs/umsdos/ioctl.c
--- linux/fs/umsdos/ioctl.c	2001-08-28 17:16:07.000000000 +0200
+++ linux-openmosix/fs/umsdos/ioctl.c	2004-02-05 10:51:23.000000000 +0100
@@ -15,6 +15,10 @@
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 struct UMSDOS_DIR_ONCE {
 	struct dirent *ent;
 	int count;
@@ -209,6 +213,20 @@
 		}
 		/* update the original f_pos */
 		filp->f_pos = pos;
+#ifdef CONFIG_MOSIX_DFSA
+		{
+			struct files_struct *files = current->files;
+			register unsigned int i;
+
+			if(atomic_read(&files->count) == 1)
+			for(i = 0 ; i < files->max_fds ; i++)
+			if(files->fd[i] == filp)
+			{
+				dfsa_touch_file(i);
+				break;
+			}
+		}
+#endif /* CONFIG_MOSIX_DFSA */
 	read_dput:
 		d_drop(demd);
 		dput(demd);
diff -Naur --exclude=CVS --exclude=configs linux/hpc/badops.c linux-openmosix/hpc/badops.c
--- linux/hpc/badops.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/badops.c	2004-02-05 02:48:27.000000000 +0100
@@ -0,0 +1,228 @@
+/* Changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+
+#include <linux/sched.h>
+#include <linux/hpcctl.h>
+#include <linux/hpc.h>
+#include <net/tcp.h>
+#include <hpc/protocol.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/hpcversion.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <linux/fs.h>
+
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+
+static int
+bad_result(void)
+{
+	printk("%s: Tried using a DFSA 'failed_to_reopen' file -- killed!\n",
+		desc_mostask(NULL));
+	force_sig(SIGKILL, current);
+	return(-EBADF);
+}
+
+loff_t
+all_bad_llseek(struct file *f, loff_t x, int y)
+{
+	return(bad_result());
+}
+
+ssize_t
+all_bad_read(struct file *f, char *x, size_t y, loff_t *z)
+{
+	return(bad_result());
+}
+
+ssize_t
+all_bad_write(struct file *f, const char *x, size_t y, loff_t *z)
+{
+	return(bad_result());
+}
+
+unsigned int
+all_bad_poll(struct file *f, struct poll_table_struct *x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_ioctl(struct inode *i, struct file *x, unsigned int y, unsigned long z)
+{
+	return(bad_result());
+}
+
+int
+all_bad_mmap(struct file *f, struct vm_area_struct *x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_open(struct inode *i, struct file *x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_fsync(struct file *f, struct dentry *d, int datasync)
+{
+	return(bad_result());
+}
+
+int
+all_bad_fasync(int x, struct file *f, int y)
+{
+	return(bad_result());
+}
+
+int
+all_bad_lock(struct file *f, int x, struct file_lock *y)
+{
+	return(bad_result());
+}
+
+struct file_operations all_bad_file_operations =
+{
+	.llseek = all_bad_llseek,
+	.read = all_bad_read,
+	.write = all_bad_write,
+	.poll = all_bad_poll,
+	.ioctl = all_bad_ioctl,
+	.mmap = all_bad_mmap,
+	.open = all_bad_open,
+	.fsync = all_bad_fsync,
+	.fasync = all_bad_fasync,
+	.lock = all_bad_lock
+};
+
+int
+all_bad_create(struct inode *i, struct dentry *x, int y)
+{
+	return(bad_result());
+}
+
+struct dentry *
+all_bad_lookup(struct inode *i, struct dentry *x)
+{
+	bad_result();
+	return 0;
+}
+
+int
+all_bad_link(struct dentry *d, struct inode *i, struct dentry *e)
+{
+	return(bad_result());
+}
+
+int
+all_bad_unlink(struct inode *i, struct dentry *d)
+{
+	return(bad_result());
+}
+
+int
+all_bad_symlink(struct inode *i, struct dentry *d, const char *a)
+{
+	return(bad_result());
+}
+
+int
+all_bad_follow_link(struct dentry *dp, struct nameidata *nd)
+{
+	return(bad_result());
+}
+
+int
+all_bad_get_block(struct inode *f, struct buffer_head *x, int y)
+{
+	return(bad_result());
+}
+
+int
+all_bad_readpage(struct file *f, struct page *x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_writepage(struct file *f, struct page *x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_bmap(struct inode *i, int x)
+{
+	return(bad_result());
+}
+
+void
+all_bad_truncate(struct inode *i)
+{
+	bad_result();
+}
+
+int
+all_bad_permission(struct inode *i, int x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_smap(struct inode *i, int x)
+{
+	return(bad_result());
+}
+
+int
+all_bad_revalidate(struct dentry *d)
+{
+	return(bad_result());
+}
+
+int
+all_bad_setattr(struct dentry *d, struct iattr *attr)
+{
+	return(bad_result());
+}
+
+struct inode_operations all_bad_inode_operations = {
+        .create = all_bad_create,
+        .lookup = all_bad_lookup,
+        .link = all_bad_link,
+        .unlink = all_bad_unlink,
+        .symlink = all_bad_symlink,
+        .follow_link = all_bad_follow_link,
+        .truncate = all_bad_truncate,
+        .permission = all_bad_permission,
+        .revalidate = all_bad_revalidate,
+	.setattr = all_bad_setattr,
+};
+
+#endif /* CONFIG_MOSIX_DFSA */
+
+struct super_operations all_bad_super_operations = {
+	.alloc_inode = 0,
+	.destroy_inode = 0,
+	.read_inode = 0,
+	.write_inode = 0,
+};
+
+struct super_block bad_super_block = {
+	.s_dev = 0,
+	.s_op = &all_bad_super_operations,
+	.s_blocksize_bits = 0,
+};
diff -Naur --exclude=CVS --exclude=configs linux/hpc/balance.c linux-openmosix/hpc/balance.c
--- linux/hpc/balance.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/balance.c	2004-04-06 21:19:37.000000000 +0200
@@ -0,0 +1,1222 @@
+/* All changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Amnon Barak, Moshe Bar
+ */
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/hpcctl.h>
+#include <net/sock.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <hpc/protocol.h>
+#include <linux/hpc.h>
+#include <asm/uaccess.h>
+#include <asm/i387.h>
+#include <linux/smp_lock.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <hpc/hpcversion.h>
+#include <hpc/balance.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
+struct opcost remote_here_adjusted[MAX_MOSIX_TOPOLOGY];
+#ifndef CONFIG_MOSIX_TOPOLOGY
+struct opcost remote_here;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+
+static int load_balancing_counter;
+static int memory_balancing_counter;
+
+
+void
+age_balancing(void)
+{
+	spin_lock_irq(&whereto_lock);
+	if(load_balancing_counter-- == 0 && chosen_for_balance)
+	{
+		free_task_struct(chosen_for_balance);
+		chosen_for_balance = NULL;
+	}
+	if(memory_balancing_counter-- == 0 && chosen_for_mdp)
+	{
+		free_task_struct(chosen_for_mdp);
+		chosen_for_mdp = NULL;
+	}
+	spin_unlock_irq(&whereto_lock);
+}
+
+void
+mosix_clear_statistics(void)
+{
+	register struct mosix_task *m = &current->mosix;
+
+	m->ndemandpages = 0;
+	m->nsyscalls = 0;
+	m->ncopyouts = 0;
+	m->copyoutbytes = 0;
+	m->ncopyins = 0;
+	m->copyinbytes = 0;
+	m->iocounter = 0;
+	m->cutime = 0;
+	m->dctime = 0;
+	m->pagetime = 0;
+	read_lock(&tasklist_lock);
+	m->decsecs = 0;
+	read_unlock(&tasklist_lock);
+	spin_lock_irq(&whereto_lock);
+	m->last_consider = 0;
+	m->last_mconsider = time_now();
+	spin_unlock_irq(&whereto_lock);
+	if(m->dflags & (DREMOTE|DDEPUTY))
+		m->uttime = 0;
+	else
+		m->uttime = -current->times.tms_utime;
+#ifdef CONFIG_MOSIX_DFSA
+	m->copy_ins = 0;
+	m->bytes_in = 0;
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+	if(m->mfs_stats)
+		m->mfs_stats->nnodes = 0;
+#endif /* CONFIG_MOSIX_FS */
+}
+
+#ifdef CONFIG_MOSIX_TOPOLOGY
+#define sel_routine(routine, struct_name)				\
+static int								\
+routine(struct struct_name *costs, int with)				\
+{									\
+	register int i;							\
+									\
+	for(i = 0 ; i < MAX_MOSIX_TOPOLOGY ; i++ , costs++)		\
+	{								\
+		if(!costs->first)					\
+			return(i);					\
+		if(!costs->last)					\
+		{							\
+			if(with != costs->first)			\
+				return(i);				\
+		}							\
+		else if((costs->last >= costs->first) ?			\
+			(with >= costs->first && with <= costs->last) :	\
+			(with > costs->first || with < costs->last))	\
+				return(i);				\
+	}								\
+	return(0);							\
+}
+
+sel_routine(select_cost, opcost)
+#ifdef CONFIG_MOSIX_FS
+sel_routine(select_mfscost, mfs_cost)
+#endif /* CONFIG_MOSIX_FS */
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+
+int64_t
+#ifdef CONFIG_MOSIX_TOPOLOGY
+io_cost(struct mosix_task *m, struct opcost *costs, int with)
+#else
+io_cost(struct mosix_task *m, struct opcost *costs)
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+{
+	int64_t b, e;
+
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	costs += select_cost(costs, with);
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	b = m->copyoutbytes * costs->outkb + m->copyinbytes * costs->inkb;
+	e = m->ndemandpages * costs->page + m->nsyscalls * costs->syscall;
+	if(costs->out || costs->in)	/* they are usually 0, so save time */
+#if COPY_COUNTER_MULTIPLIER != EVENT_COUNTER_VALUE
+#warning no reason they should not be the same, but inefficient code provided:
+		return((b >> 10) + (e >> EVENT_COUNTER_SHIFT) +
+			(m->ncopyouts * costs->out + m->ncopyins * costs->in) /
+						COPY_COUNTER_MULTIPLIER);
+#else
+		e += m->ncopyouts * costs->out + m->ncopyins * costs->in;
+#endif
+#if EVENT_COUNTER_SHIFT == 10
+	/* we are lucky that the cost of a system call is the same
+	 * order of magnitude as copying 1KB to/from user-space
+	 */
+	return((b + e) >> 10);
+#else
+	return((b >> 10) + (e >> EVENT_COUNTER_SHIFT));
+#endif
+}
+
+int64_t
+remote_costs_in_ms(struct mosix_task *m)
+{
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	return(io_cost(m, m->depcost, PE) * STD_SPD / m->depspeed +
+				io_cost(m, remote_here_adjusted, m->deppe));
+#else
+	return(io_cost(m, m->depcost) * STD_SPD / m->depspeed +
+				io_cost(m, remote_here_adjusted));
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+}
+
+#ifdef CONFIG_MOSIX_FS
+
+enum mfs_where {MFS_CLIENT, MFS_SERVER};
+
+int64_t
+#ifdef CONFIG_MOSIX_TOPOLOGY
+mfs_cos(int64_t conns, int64_t inbytes, int64_t outbytes,
+			struct mfs_cost *costs, enum mfs_where type, int with)
+#else
+mfs_cos(int64_t conns, int64_t inbytes, int64_t outbytes, enum mfs_where type)
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+{
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	if(with == 0)
+		with = PE;
+	costs += select_mfscost(costs, with);
+#else
+	struct mfs_cost *costs = mfs_cost;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	if(type == MFS_CLIENT)
+		return(conns * costs->MFS_CONN_C + ((inbytes*costs->MFS_INKB_C +
+					outbytes * costs->MFS_OUTKB_C) >> 10));
+	else
+		return(conns * costs->MFS_CONN_S + ((inbytes*costs->MFS_INKB_S +
+					outbytes * costs->MFS_OUTKB_S) >> 10));
+}
+#endif /* CONFIG_MOSIX_FS */
+
+void
+add_statistics_to_ancesstor(struct task_struct *p, struct task_struct *pp)
+{
+	struct mosix_task *m = &p->mosix;
+	struct mosix_task *mm = &pp->mosix;
+	int remote = (m->dflags & DREMOTE);
+	int64_t ut, age;
+	unsigned long newcounter;
+
+	lock_mosix();
+	age = ticks_to_ms(p->times.tms_utime + m->uttime) + m->cutime;
+	ut = age - m->dctime;
+	if(remote)
+		age += remote_costs_in_ms(m);
+	if(age > 4 * MILLION) 
+	/* over 2.4 seconds, son is too old and not dependent any more */
+	{
+		unlock_mosix();
+		return;
+	}
+	mm->cutime += ut;
+	mm->nsyscalls += m->nsyscalls;
+	mm->ncopyouts += m->ncopyouts;
+	mm->copyoutbytes += m->copyoutbytes;
+	mm->ncopyins += m->ncopyins;
+	mm->copyinbytes += m->copyinbytes;
+	mm->ndemandpages += m->ndemandpages;
+	if(remote)
+	{
+		newcounter = mm->iocounter + m->ndemandpages + m->nsyscalls +
+				m->ncopyouts + m->copyoutbytes +
+				m->ncopyins + m->copyinbytes;
+		if((newcounter ^ mm->iocounter) & 0xfff00000)
+		{
+			mosix_add_to_whereto(pp, IOBALANCE);
+			mm->iocounter = 0;
+		}
+		else
+			mm->iocounter = newcounter;
+	}
+	mm->pagetime += m->pagetime;
+#ifdef CONFIG_MOSIX_FS
+	if(mfs_add_stats(m->mfs_stats, mm->mfs_stats, mm))
+		mosix_add_to_whereto(pp, MFSBALANCE);
+#endif /* CONFIG_MOSIX_FS */
+	unlock_mosix();
+}
+
+/*
+ * produce statistics at the end of local system-calls:
+ */
+void
+mosix_local_syscall(void)
+{
+	register struct mosix_task *m = &current->mosix;
+
+#ifdef CONFIG_MOSIX_DFSA
+	if(m->dflags & (DDEPUTY|DREMOTE|DSTATSDOWN))
+	{
+		m->copy_ins = m->bytes_in = 0;
+		m->dflags &= ~DSTATSDOWN;
+		return;
+	}
+	if(m->copy_ins)
+	{
+		m->ncopyins += m->copy_ins * COPY_COUNTER_MULTIPLIER;
+		m->copyinbytes += m->bytes_in;
+		m->copy_ins = m->bytes_in = 0;
+	}
+#else
+	if(!(m->dflags & (DDEPUTY|DREMOTE)))
+#endif /* CONFIG_MOSIX_DFSA */
+		m->nsyscalls += EVENT_COUNTER_VALUE;
+}
+
+/*
+ * altruistic load:
+ * this function takes into account the cost of a load not only on a given
+ * process, but also on the other processes in its environment.
+ * When there are enough processors to take the load, a process gets served as
+ * soon as practicable, as fast as the processor can run, eg. by the threshold.
+ * Otherwise, there is a cost which is:
+ * given L=load, N=ncpus:
+ * For the process itself: the cost is L.
+ * For the other (N*L-1) processes:
+ *	Without the extra process, they would each need (N*L-1)/N units of time
+ *		to complete.
+ *	With the extra process, they will need L units of time to complete.
+ * the loss is therefore (N*L-1)*(L-(N*L-1)/N) = (N*L-1)*(L-L+1/N) = L - 1/N.
+ */
+
+#define	INFLOAD 0x8000000
+#ifdef CONFIG_MOSIX_LOADLIMIT
+unsigned long load_limit = 0;
+unsigned long cpu_limit = 0;
+inline int
+altload(int load, unsigned long load_remote, unsigned long load_local, 
+	unsigned long cpu_remote, unsigned long cpu_local, 
+	unsigned long speed, int ncpus, 
+	unsigned long load_limit, 
+	unsigned long llimitmode,
+	unsigned long cpu_limit,
+	unsigned long cpulimit_mode
+	)
+{
+	int threshold = MF * STD_SPD / speed;
+	switch(llimitmode) 
+	{
+	case 0:
+		if (load_limit && load > load_limit)
+			return INFLOAD;
+	break;
+	case 1:
+		if (load_limit && load_remote  > load_limit)
+			return INFLOAD;
+	case 2:
+		if (load_limit && load_local  > load_limit)
+			return INFLOAD;
+	break;
+	}
+	switch(cpulimit_mode) 
+	{
+	case 0:
+		if (cpu_limit && ((cpu_remote+cpu_local) > cpu_limit))
+			return INFLOAD;
+	break;
+	case 1:
+		if (cpu_limit && cpu_remote  > cpu_limit)
+			return INFLOAD;
+	case 2:
+		if (cpu_limit && cpu_local  > cpu_limit)
+			return INFLOAD;
+	break;
+    }
+  if(load <= threshold)
+    return(threshold);
+  if(load <= threshold + threshold/ncpus)
+    return(threshold + ncpus * load * (load-threshold) / threshold);
+  return(2 * load - threshold / ncpus);
+}
+#else
+inline int
+altload(int load, unsigned long speed, int ncpus)
+{
+	int threshold = MF * STD_SPD / speed;
+	if(load <= threshold)
+		return(threshold);
+	if(load <= threshold + threshold/ncpus)
+		return(threshold + ncpus * load * (load-threshold) / threshold);
+	return(2 * load - threshold / ncpus);
+}
+#endif
+
+int
+send_local_aload(int type)
+{
+	struct aload_h a;
+
+	read_lock_bh(&loadinfo_lock);
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	a.aload = altload(export_load, 
+			  loadinfo[0].loadremote, loadinfo[0].loadlocal,
+			  loadinfo[0].cpuremote,  loadinfo[0].cpulocal,
+			  loadinfo[0].speed, loadinfo[0].ncpus,
+			  0, 0, 0, 0);
+#else
+	a.aload = altload(export_load, loadinfo[0].speed, loadinfo[0].ncpus);
+#endif
+	read_unlock_bh(&loadinfo_lock);
+	a.freepages = export_mem();
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	memcpy(a.mfscosts, mfs_cost, sizeof(mfs_cost));
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	return(comm_send(type, &a, sizeof(a), NULL, 0, 0));
+}
+void
+choose(void)
+{
+        int64_t priority, lastpri = 0;
+	int pri, bestpri;
+        register int load, bestload;
+	struct task_struct *p, *sel = NULL;
+	register struct mosix_task *m;
+        int mintime, very_mintime;
+	int minload;
+
+	mintime = MILLION * acpuse / (smp_num_cpus * MF);
+	very_mintime = mintime / 3;
+	minload = 4 * acpuse / smp_num_cpus;	/* normally 4*MF */
+        bestpri = mintime;
+        bestload = -1;
+	read_lock(&tasklist_lock);
+	if(!chosen_for_balance)
+	for_each_task(p)
+        if(!((m = &p->mosix)->dflags & (DDEPUTY|DFINISHED|DPASSING)) &&
+		!m->stay && !m->whereto && p != chosen_for_mdp &&
+		(!mosadmin_mode_lstay || (m->dflags & DREMOTE)))
+        {
+		priority = ticks_to_ms(p->times.tms_utime + m->uttime) +
+								m->cutime;
+		/* (note: m->dctime deliberately not taken into account:
+		 * otherwise if statistics decay too quickly, there may never
+		 * be a process chosen for migration) */
+		if(m->dflags & DREMOTE)
+#ifdef CONFIG_MOSIX_TOPOLOGY
+			priority += io_cost(m, remote_here_adjusted, m->deppe);
+#else
+			priority += io_cost(m, remote_here_adjusted);
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		priority -= m->last_consider;
+		if(priority < 0)
+		/* it "should not" happen, but some operating systems (BSDI)
+		   can have user-time go back due to rounding... */
+			continue;
+		pri = (priority > 4*MILLION) ? 4*MILLION : priority; /*4 secs.  */
+                if(pri < bestpri)
+                {
+                        if(bestpri == mintime &&
+				/* (thrashing, or (m->load <= minload)) */
+				m->load > minload && pri >= very_mintime)
+                                pri = mintime;
+                        else
+                                continue;
+                }
+                load = m->load;
+                if(pri > bestpri || load > bestload)
+                {
+                        bestload = load;
+			if(sel)
+				free_task_struct(sel);
+			get_task_struct(p);
+                        sel = p;
+                        bestpri = pri;
+			lastpri = priority;
+                }
+        }
+	read_unlock(&tasklist_lock);
+        if(!sel)
+		return;
+	spin_lock_irq(&whereto_lock);
+	if(chosen_for_balance)
+	{
+		free_task_struct(sel);
+		spin_unlock_irq(&whereto_lock);
+		return;
+	}
+        sel->mosix.last_consider += lastpri;
+	chosen_for_balance = sel;
+	mosix_do_add_to_whereto(sel, BALANCE);
+	load_balancing_counter = BALANCING_TIMEOUT;
+	if(sel->mosix.whereto != BALANCE)
+	{
+		free_task_struct(chosen_for_balance);
+		chosen_for_balance = NULL;
+	}
+	spin_unlock_irq(&whereto_lock);
+}
+
+void
+load_balance(void)
+{
+	register int load;
+	register struct loadinfo *l;
+	unsigned int doit = 0;
+
+	if(mosadmin_mode_stay)
+		return;
+
+	read_lock_bh(&loadinfo_lock);
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	load = altload(loadinfo[0].load, 
+		       loadinfo[0].loadremote, loadinfo[0].loadlocal,
+		       loadinfo[0].cpuremote,  loadinfo[0].cpulocal,
+		       loadinfo[0].speed, loadinfo[0].ncpus,
+		       loadinfo[0].load_limit, loadinfo[0].llimitmode,
+		       loadinfo[0].cpu_limit,  loadinfo[0].cpulimitmode);
+#else
+	load = altload(loadinfo[0].load, loadinfo[0].speed, loadinfo[0].ncpus);
+#endif
+	for(l = &loadinfo[1]; l < &loadinfo[INFO_WIN] ; l++)
+	if(l->pe && l->mem > 0 && 
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	   altload(l->load, l->loadremote, l->loadlocal,
+		   l->cpuremote, l->cpulocal,
+		   l->speed, l->ncpus, 0, 0, 0, 0) <= load
+#else
+	   altload(l->load, l->speed, l->ncpus) <= load
+#endif
+	     )
+{
+		doit = 1;
+		break;
+	}
+	read_unlock_bh(&loadinfo_lock);
+        if(doit)
+                choose();
+}
+
+void
+mchoose(int need)
+{
+	int quality, bestquality = 0;
+	int df, diff = MIN_MCHOOSE_AGAIN;
+	now_t dff;
+	struct task_struct *p, *sel = NULL;
+	register struct mosix_task *m;
+
+	read_lock(&tasklist_lock);
+	if(!chosen_for_mdp)
+	for_each_task(p)
+        if(!((m = &p->mosix)->dflags & (DDEPUTY|DFINISHED|DPASSING)) &&
+		!m->stay && !m->whereto && p != chosen_for_balance &&
+		(!mosadmin_mode_lstay || (m->dflags & DREMOTE)))
+	{
+		dff = time_since(m->last_mconsider);
+		if(dff > MAX_MCHOOSE_AGAIN)
+			df = MAX_MCHOOSE_AGAIN;
+		else
+			df = dff;
+		if(df < diff)
+			continue;
+		quality = memory_relief_quality(p, need);
+		if(quality > bestquality || (quality > 0 && df > diff))
+                {
+			if(sel)
+				free_task_struct(sel);
+			get_task_struct(p);
+                        sel = p;
+                        bestquality = quality;
+			diff = df;
+                }
+        }
+	read_unlock(&tasklist_lock);
+        if(!sel)
+		return;
+	spin_lock_irq(&whereto_lock);
+	if(chosen_for_mdp)
+	{
+		free_task_struct(sel);
+		spin_unlock_irq(&whereto_lock);
+		return;
+	}
+	sel->mosix.page_allocs = 0;
+	sel->mosix.last_mconsider = time_now();
+	chosen_for_mdp = sel;
+	mosix_do_add_to_whereto(sel, MEMBALANCE);
+	memory_balancing_counter = BALANCING_TIMEOUT;
+	if(sel->mosix.whereto != MEMBALANCE)
+	{
+		free_task_struct(chosen_for_mdp);
+		chosen_for_mdp = NULL;
+	}
+	spin_unlock_irq(&whereto_lock);
+}
+
+void
+memory_balance(void)
+{
+	register struct loadinfo *l;
+	int need;
+	unsigned int doit = 0;
+
+	if(mosadmin_mode_stay || mosadmin_mode_quiet ||
+		(need = memory_badly_required()) <= 0)
+		return;
+	read_lock_bh(&loadinfo_lock);
+	for(l = &loadinfo[1]; l < &loadinfo[INFO_WIN] ; l++)
+	if(l->pe && l->mem > MIN_EXPECTED_PROC_SIZE)
+	{
+		doit = 1;
+		break;
+	}
+	read_unlock_bh(&loadinfo_lock);
+	if(doit)
+		mchoose(need);
+}
+
+void
+changed_my_mind_and_staying(void)
+{
+	current->mosix.pages_i_bring = 0;
+}
+
+void
+ask_deputy_to_goto(int where)
+{
+	void *head;
+	int hlen;
+
+	if(comm_send(DEP_CONSIDER|REPLY, &where, sizeof(int), NULL, 0, 0) ||
+		(where && remote_wait(DEP_CONSIDER, &head, &hlen)))
+		remote_disappear();
+	if(where)
+		comm_free(head);
+}
+
+struct sonstats
+{
+	int64_t utime;		/* ms */
+	int64_t ndemandpages;
+	int64_t nsyscalls;
+	int64_t ncopyouts;
+	int64_t copyoutbytes;
+	int64_t ncopyins;
+	int64_t copyinbytes;
+	int64_t pagetime;	/* ms */
+#ifdef CONFIG_MOSIX_FS
+	struct mfs_stats mfs;
+#endif /* CONFIG_MOSIX_FS */
+};
+
+void
+consider(int reason, struct sonstats *sons)
+{
+#define	MAX_CONSIDERED	(INFO_WIN+1+MAX_MFS_STATNODES)
+#if MAX_CONSIDERED > 127
+#error char is not enough for map
+#endif /*MAX_CONSIDERED*/
+	struct task_struct *p = current;
+	register struct mosix_task *m = &p->mosix;
+	int mach[MAX_CONSIDERED], aload[MAX_CONSIDERED];
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	unsigned long load_limit_[MAX_CONSIDERED];
+	unsigned long load_[MAX_CONSIDERED];
+	unsigned long load_remote_[MAX_CONSIDERED];
+	unsigned long llimit_mode_[MAX_CONSIDERED];
+	unsigned long load_local_[MAX_CONSIDERED];
+	unsigned long cpu_limit_[MAX_CONSIDERED];
+	unsigned long cpu_remote_[MAX_CONSIDERED];
+	unsigned long cpulimit_mode_[MAX_CONSIDERED];
+	unsigned long cpu_local_[MAX_CONSIDERED];
+#endif
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	struct costinfo
+	{
+		struct opcost opcost[MAX_MOSIX_TOPOLOGY];
+#ifdef CONFIG_MOSIX_FS
+		struct mfs_cost mfscost[MAX_MOSIX_TOPOLOGY];
+#endif /* CONFIG_MOSIX_FS */
+	} *costinfo = NULL;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+#ifdef CONFIG_MOSIX_FS
+	struct mfs_stats *mfs_tot;
+	char map[MAX_MFS_STATNODES];
+	int orig_n;
+#endif /* CONFIG_MOSIX_FS */
+	double costs[MAX_CONSIDERED];
+	register int i, n = 0, j, k;
+	int depmach = -1;
+	double tim, dtim, rtim;
+	int remote = (m->dflags & DREMOTE) ? 1 : 0;
+	int64_t ms;
+	struct aload_h a;
+
+	if((m->stay & DSTAY) || !PE || mosadmin_mode_quiet)
+		goto out;
+	if(reason && (m->stay || mosadmin_mode_stay ||
+		(mosadmin_mode_lstay && !(m->dflags & DREMOTE))))
+	{
+		goto out;
+	}
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	if(!(costinfo = (struct costinfo *)
+		kmalloc(sizeof(struct costinfo) * MAX_CONSIDERED, GFP_KERNEL)))
+	{
+		goto out;
+	}
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	m->migpages = count_migrating_pages();
+#ifdef CONFIG_MOSIX_FS
+	if(sons && sons->mfs.nnodes)
+	{
+		mfs_tot = &sons->mfs;
+		mfs_add_stats(m->mfs_stats, mfs_tot, NULL);
+	}
+	else
+		mfs_tot = m->mfs_stats;
+#endif /* CONFIG_MOSIX_FS */
+	if(remote)
+	{
+	      if(remote_request(REM_GETALOAD, NULL, 0, NULL, 0, 0,
+			(void **)&a, -sizeof(a)))
+		{
+			printk("%s: failed to send getaload - exiting\n",
+				desc_mostask(m));
+			remote_disappear();
+		}
+		depmach = m->deppe;
+		aload[0] = a.aload;
+		if(reason != IOBALANCE && a.freepages < m->migpages)
+			aload[0] += INFLOAD;
+		/* deliberately leave costinfo[0].opcost undefined! */
+#if defined(CONFIG_MOSIX_FS) && defined(CONFIG_MOSIX_TOPOLOGY)
+		memcpy(costinfo[0].mfscost, a.mfscosts, sizeof(a.mfscosts));
+#endif /* CONFIG_MOSIX_FS && CONFIG_MOSIX_TOPOLOGY */
+		mach[n++] = GOBACKHOME;
+	}
+	read_lock_bh(&loadinfo_lock);
+	for(i = 0 ; i < INFO_WIN ; i++)
+#ifdef CONFIG_MOSIX_CHEAT_MIGSELF
+	if(loadinfo[i].pe && (!i || loadinfo[i].pe != depmach)
+#else
+	if(loadinfo[i].pe && loadinfo[i].pe != depmach
+#endif /* CONFIG_MOSIX_CHEAT_MIGSELF */
+		&& (i == 0 || (loadinfo[i].mem >= m->migpages &&
+						loadinfo[i].free_slots)))
+	{
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		memcpy(costinfo[n].opcost, loadinfo[i].costs,
+						sizeof(loadinfo[i].costs));
+#ifdef CONFIG_MOSIX_FS
+		memcpy(costinfo[n].mfscost, loadinfo[i].mfscosts,
+						sizeof(loadinfo[i].mfscosts));
+#endif /* CONFIG_MOSIX_FS */
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		/* CONFIG_MOSIX_LOADLIMIT*/
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		/* If process is remote and node is overloaded then it has to migrate
+		 * out of curren node */
+		if (i || (remote && !i))
+		  aload[n] = altload(loadinfo[i].load, loadinfo[i].loadremote, 
+				     loadinfo[i].loadlocal,
+				     loadinfo[i].cpuremote,
+				     loadinfo[i].cpulocal,
+				     loadinfo[i].speed,
+				     loadinfo[i].ncpus, loadinfo[i].load_limit,
+				     loadinfo[i].llimitmode,
+				     loadinfo[i].cpu_limit,
+				     loadinfo[i].cpulimitmode);
+		else
+		  aload[n] = altload(loadinfo[i].load, loadinfo[i].loadremote,
+				     loadinfo[i].loadlocal,
+				     loadinfo[i].cpuremote,
+				     loadinfo[i].cpulocal,
+				     loadinfo[i].speed,
+				     loadinfo[i].ncpus, 0, 0, 0, 0);
+#else
+		aload[n] = altload(loadinfo[i].load, loadinfo[i].speed,
+				loadinfo[i].ncpus);
+
+#endif
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		load_limit_[n] = loadinfo[i].load_limit;
+		load_[n] = loadinfo[i].load;
+		load_remote_[n] = loadinfo[i].loadremote;
+		llimit_mode_[n] = loadinfo[i].llimitmode;
+		load_local_[n] = loadinfo[i].loadlocal;
+		cpu_limit_[n] = loadinfo[i].cpu_limit;
+		cpu_remote_[n] = loadinfo[i].cpuremote;
+		cpu_local_[n] = loadinfo[i].cpulocal;
+		cpulimit_mode_[n] = loadinfo[i].cpulimitmode;
+#endif
+		/* CONFIG_MOSIX_LOADLIMIT:
+		 * aload has to be set inifinity if loadinfo[i].load is greater
+		 * then loadinfo[i].load_limit */
+		
+		if(i)
+		{
+			k = loadinfo[i].pe;
+			if(m->dflags & DMIGFILTER)
+			switch(m->mask.migpolicy)
+			{
+			case 0:	/* MIG_POLICY_DENY */
+				if((m->mask.mignodes >> (k - 1)) & 1)
+					continue;
+				break;
+			case 1:	/* MIG_POLICY_ALLOW */
+				if(!((m->mask.mignodes >> (k - 1)) & 1))
+					continue;
+				break;
+			}
+			mach[n] = k;
+		}
+		else
+		{
+			mach[n] = 0;
+			if(reason == MEMBALANCE)
+			{
+				if(remote)
+					continue;
+				aload[n] += INFLOAD;
+			}
+		}
+		n++;
+	}
+	read_unlock_bh(&loadinfo_lock);
+#ifdef CONFIG_MOSIX_FS
+	/* collect info on MFS nodes */
+	orig_n = n;
+	if(mfs_tot)
+	for(i = 0 ; i < mfs_tot->nnodes ; i++)
+	{
+		struct loadinfo info;
+
+		if(mfs_tot->conns[i] < 10 &&
+			(mfs_tot->inbytes[i] + mfs_tot->outbytes[i]) < 1000000)
+			continue;
+		k = mfs_tot->nodes[i];
+		if(k == PE || k == depmach)
+			continue;
+		for(j = 1 ; j < orig_n ; j++)
+		if(mach[j] == k)
+			goto not_this_one;
+		if(balance_get_load(k, &info))
+			continue;
+		if (info.mem < m->migpages || !info.free_slots)
+			continue;
+		mach[n] = k;
+		/* CONFIG_MOSIX_LOADLIMIT */
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		/* If process is remote and node is overloaded then it has to migrate
+		 * out of current node */
+		if (k != PE || (k==PE && remote))
+		  aload[n] = altload(info.load, info.loadremote, info.loadlocal,
+				     info.cpuremote, info.cpulocal,
+				     info.speed,
+		     		     info.ncpus, info.load_limit, info.llimitmode,
+				     info.cpu_limit, info.cpulimitmode);
+		else
+	           aload[n] = altload(info.load, info.loadremote, info.loadlocal,
+				      info.cpuremote, info.cpulocal,
+				      info.speed, info.ncpus, 0, 0, 0, 0);
+#else
+		aload[n] = altload(info.load, info.speed, info.ncpus);
+#endif
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		load_limit_[n] = info.load_limit;
+		load_[n] = info.load;
+		load_remote_[n] = info.loadremote;
+		load_local_[n] = info.loadlocal;
+		llimit_mode_[n] = info.llimitmode;
+		cpu_limit_[n] = info.cpu_limit;
+		cpu_remote_[n] = info.cpuremote;
+		cpu_local_[n] = info.cpulocal;
+		cpulimit_mode_[n] = info.cpulimitmode;
+#endif
+		/* CONFIG_MOSIX_LOADLIMIT:
+		 * aload has to be set inifinity if loadinfo[i].load is greater
+		 * then loadinfo[i].load_limit */
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		memcpy(costinfo[n].opcost, info.costs, sizeof(info.costs));
+		memcpy(costinfo[n].mfscost, info.mfscosts,
+							sizeof(info.mfscosts));
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		n++;
+		not_this_one:;
+	}
+#endif /* CONFIG_MOSIX_FS */
+	if(n == 0 || (n == 1 && mach[0] == 0))
+		goto out;	/* save time */
+#ifdef CONFIG_MOSIX_FS
+	/* prepare the MFS mapping */
+	if(mfs_tot)
+	for(i = mfs_tot->nnodes - 1 ; i >= 0 ; i--)
+	{
+		k = mfs_tot->nodes[i];
+		if(k == PE)
+			map[i] = remote;
+		else if(remote && k == m->deppe)
+			map[i] = 0;
+		else
+		{
+			map[i] = -1;
+			for(j = n - 1 ; j > 0 ; j--)
+			if(mach[j] == k)
+			{
+				map[i] = j;
+				break;
+			}
+		}
+	}
+#endif /* CONFIG_MOSIX_FS */
+	/* we must NOT sleep throughout the following FP calculations:*/
+	kernel_fpu_begin();
+	init_fpu();
+	ms = ticks_to_ms(p->times.tms_utime+m->uttime) + m->cutime - m->dctime;
+	if(sons)
+		ms += sons->utime;
+	if((m->dpolicy & DADV_POLICY) == DADV_NOCPU)
+		tim = 0.0;
+	else
+		/* secs on a std. machine */
+		tim = ms / DMILLION * cpuspeed / STD_SPD;
+	if(reason == MEMBALANCE)
+		tim += (m->pagetime + (sons ? sons->pagetime : 0)) / DMILLION;
+	for(i = 0 ; i < n ; i++)
+		costs[i] = tim * aload[i] / MF;
+	if((m->dpolicy & DADV_POLICY) == DADV_CPU)
+		goto skip_comm;
+	if(sons)	/* temporarily add */
+	{
+		lock_mosix();
+		m->ndemandpages += sons->ndemandpages;
+		m->nsyscalls += sons->nsyscalls;
+		m->ncopyouts += sons->ncopyouts;
+		m->copyoutbytes += sons->copyoutbytes;
+		m->ncopyins += sons->ncopyins;
+		m->copyinbytes += sons->copyinbytes;
+		unlock_mosix();
+	}
+	for(i = 1 ; i < n ; i++)
+	{
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		dtim = io_cost(m, remote ? m->depcost : deputy_here, mach[i]);
+		rtim = io_cost(m, costinfo[i].opcost, m->deppe);
+#else
+		dtim = io_cost(m, remote ? m->depcost : deputy_here);
+		rtim = io_cost(m, &remote_here);
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		costs[i] += (dtim * aload[0] + rtim * aload[i]) / (DMILLION*MF);
+	}
+	if(sons)	/* restore */
+	{
+		lock_mosix();
+		m->ndemandpages -= sons->ndemandpages;
+		m->nsyscalls -= sons->nsyscalls;
+		m->ncopyouts -= sons->ncopyouts;
+		m->copyoutbytes -= sons->copyoutbytes;
+		m->ncopyins -= sons->ncopyins;
+		m->copyinbytes -= sons->copyinbytes;
+		unlock_mosix();
+	}
+#ifdef CONFIG_MOSIX_FS
+	if(!mfs_tot)
+		goto skip_comm;
+	for(i = 0 ; i < n ; i++)
+	for(j = 0 ; j < mfs_tot->nnodes ; j++)
+	if((k = map[j]) != -1 && k != i)
+	{
+		int c = mfs_tot->conns[j];
+		int in = mfs_tot->inbytes[j];
+		int out = mfs_tot->outbytes[j];
+
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		dtim = mfs_cos(c, in, out, costinfo[k].mfscost, MFS_SERVER,
+								mach[i]);
+		rtim = mfs_cos(c, in, out, costinfo[i].mfscost, MFS_CLIENT,
+								mach[k]);
+#else
+		dtim = mfs_cos(c, in, out, MFS_SERVER);
+		rtim = mfs_cos(c, in, out, MFS_CLIENT);
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		costs[i] += (dtim * aload[k] + rtim * aload[i]) / (DMILLION*MF);
+	}
+#endif /* CONFIG_MOSIX_FS */
+	skip_comm:
+	if (reason != MEMBALANCE)
+	{
+		/* migration cost: */
+		double decay_factor;
+
+		if(m->dctime > 0)	/* decay occured */
+		{
+			ms = ticks_to_ms(p->times.tms_utime + m->uttime);
+			if(ms)
+				decay_factor = ((double)(ms - m->dctime)) / ms;
+			else
+			{
+				decay_factor = 1.0;
+			}
+		}
+		else
+			decay_factor = 1.0;
+		decay_factor /= DMILLION; /* to save multiple divisions later */
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		for(i = 0 ; i < n ; i++)
+		if(i != remote)
+		{
+			j = select_cost(deputy_here, i ? mach[i] : m->deppe);
+			costs[i] += decay_factor *
+				(mosix_cost[j].MIGRATION_BASIC +
+				m->migpages * mosix_cost[j].MIGRATION_PER_PAGE);
+		}
+#else
+		tim = decay_factor * (mosix_cost[0].MIGRATION_BASIC +
+			m->migpages * mosix_cost[0].MIGRATION_PER_PAGE);
+		for(i = 0 ; i < n ; i++)
+		if(i != remote)
+			costs[i] += tim;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	}
+	/* sort by least cost */
+	for(i = 0 ; i < n-1 ; i++)
+	for(j = i+1 ; j < n ; j++)
+	if(costs[i] > costs[j])
+	{
+		tim = costs[i];
+		costs[i] = costs[j];
+		costs[j] = tim;
+		k = mach[i];
+		mach[i] = mach[j];
+		mach[j] = k;
+	}
+	kernel_fpu_end();
+	m->loadhere = aload[remote];
+	for(i = 0 ; i < n ; i++)
+	{
+		if((k = mach[i]) == 0)
+			goto out;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		/* if destination node k is overloaded then skip it */
+		switch (llimit_mode_[k])
+	    	  {
+    		  case 0:
+		    if (load_limit_[k] && (load_[k] > load_limit_[k]) && 
+			!(remote && k == depmach))
+		      continue;
+		    break;
+		  case 1:
+		    if (load_limit_[k] && (load_remote_[k] > load_limit_[k]) && 
+			!(remote && k == depmach) )
+		      continue;
+		    break;
+		  case 2:
+		    if (load_limit_[k] && (load_local_[k] > load_limit_[k]) && 
+			!(remote && k == depmach) )
+		      continue;
+		    break;
+		  }
+		switch (cpulimit_mode_[k])
+		  {
+		  case 0:
+		    if (cpu_limit_[k] && 
+			(cpu_remote_[k]+cpu_local_[k] > cpu_limit_[k]) && 
+			!(remote && k == depmach))
+		      continue;
+		    break;
+		  case 1:
+		    if (cpu_limit_[k] && (cpu_remote_[k] > cpu_limit_[k]) && 
+			!(remote && k == depmach) )
+		      continue;
+		    break;
+		  case 2:
+		    if (cpu_limit_[k] && (cpu_local_[k] > cpu_limit_[k]) && 
+			!(remote && k == depmach) )
+		      continue;
+		    break;
+		  }
+#endif
+		if(remote)
+		{
+			ask_deputy_to_goto(k);
+		}
+		else if(passto(k, reason) == 0)
+			goto out;
+		/* conditions changed meanwhile? */
+		if(mosadmin_mode_quiet || (reason && (mosadmin_mode_stay ||
+			(mosadmin_mode_lstay && !(m->dflags & DREMOTE)))))
+			goto out;
+	}
+	out:
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	if(costinfo)
+		kfree(costinfo);
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	m->migpages = 0;
+	unchoose_me();
+	if(m->dflags & DREMOTE)
+		ask_deputy_to_goto(0);
+}
+
+void
+unchoose_me(void)
+{
+	struct task_struct *p = current;
+	unsigned int l = 0, m = 0;
+
+	spin_lock_irq(&whereto_lock);
+	if(p == chosen_for_balance)
+	{
+		free_task_struct(p);
+		chosen_for_balance = NULL;
+		l = 1;
+	}
+	else if(p == chosen_for_mdp)
+	{
+		free_task_struct(p);
+		chosen_for_mdp = NULL;
+		m = 1;
+	}
+	spin_unlock_irq(&whereto_lock);
+	if(l)
+		load_balance();
+	else if(m)
+		memory_balance();
+}
+
+int
+mosix_forkmigrate(void)
+{
+	struct task_struct *me = current;
+	struct task_struct *p, *a;
+        register struct mosix_task *q;
+	struct sonstats s;
+	register int remote;
+	int64_t age;
+	unsigned int any = 0;
+
+	if(me->mosix.dflags & DDEPUTY)
+		panic("forkmigrate: DEPUTY");
+	if(me->mosix.stay || !PE)
+		return(0);
+	remote = (me->mosix.dflags & DREMOTE) != 0;
+	lock_mosix();
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	for(a = p->mosix.ancesstor ; a ; a = a->mosix.ancesstor)
+        if(a == me)
+	{
+		q = &p->mosix;
+		age = ticks_to_ms(p->times.tms_utime + q->uttime) + q->cutime;
+		if(remote)
+			age += remote_costs_in_ms(q);
+		else
+			age += ticks_to_ms(p->times.tms_stime);
+		if(age > 4 * MILLION) 
+		/* over 4 seconds, descendant is no longer dependent */
+		{
+			q->ancesstor = NULL;
+			break;
+		}
+		if(!any)
+		{
+			any = 1;
+			memset(&s, 0, sizeof s);
+		}
+		s.utime += ticks_to_ms(p->times.tms_utime + q->uttime) +
+							q->cutime - q->dctime;
+		/* we need not worry about the "q->uttime" part of q->dctime
+		   on a local process: if the process ever migrated, it would
+		   not be dependent and we would never reach here!
+		*/
+		s.nsyscalls += q->nsyscalls;
+		s.ncopyouts += q->ncopyouts;
+		s.copyoutbytes += q->copyoutbytes;
+		s.ncopyins += q->ncopyins;
+		s.copyinbytes += q->copyinbytes;
+		s.pagetime += q->pagetime;
+#ifdef CONFIG_MOSIX_FS
+		mfs_add_stats(q->mfs_stats, &s.mfs, NULL);
+#endif /* CONFIG_MOSIX_FS */
+		break;
+	}
+	read_unlock(&tasklist_lock);
+	unlock_mosix();
+	if(!any)
+		return(0);
+	if(remote && comm_send(REM_CONSIDERING, NULL, 0, NULL, 0, 0))
+		remote_disappear();
+        consider(BALANCE, &s);
+	return(me->mosix.dflags & DDEPUTY);
+	/* for local processes, DDEPUTY means we moved,
+	 * and REMOTE processes do not care for result -
+	 * for they would never reach here if migrated.
+	 */
+}
+
+int
+send_with_miginfo(int type, void *header, int hdsz)
+{
+	struct miginfo mi;
+	register struct mosix_task *m = &current->mosix;
+
+	mi.aload = m->loadhere;
+	mi.pages = m->migpages ? : count_migrating_pages();
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	mi.remote = (current->mosix.dflags & DREMOTE) ? 1 : 0;
+	mi.deppe = current->mosix.deppe;
+#endif
+	return(comm_send(type, header, hdsz, (char *)&mi, sizeof(mi), 0));
+}
+
+int
+balance_commit_mig(int reason, int pages_i_bring)
+{
+	int me, him;
+	struct miginfo mi;
+
+	if(comm_copydata(&mi, sizeof(mi) | COMM_ZEROCOPYOK, 0))
+		goto commit;	/* no MOSIX on other side! */
+	switch(reason) {
+	case 0:
+	case IOBALANCE:
+	case MFSBALANCE:
+		goto commit;
+	default:
+		read_lock_bh(&loadinfo_lock);
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		if (mi.remote && mi.deppe == PE)
+		  me = altload(export_load, loadinfo[0].loadremote,
+			       loadinfo[0].loadlocal,
+			       loadinfo[0].loadremote,
+			       loadinfo[0].loadlocal,
+			       loadinfo[0].speed,
+			       loadinfo[0].ncpus, 0, 0, 0, 0);
+		else
+		  me = altload(export_load, loadinfo[0].loadremote,
+			       loadinfo[0].loadlocal,
+			       loadinfo[0].cpuremote,
+			       loadinfo[0].cpulocal,
+			       loadinfo[0].speed,
+			       loadinfo[0].ncpus, loadinfo[0].load_limit,
+			       loadinfo[0].llimitmode,
+			       loadinfo[0].cpu_limit,
+			       loadinfo[0].cpulimitmode);
+
+#else
+		me = altload(export_load, loadinfo[0].speed,
+			     loadinfo[0].ncpus);
+#endif
+		read_unlock_bh(&loadinfo_lock);
+		him = mi.aload;
+		if(me > him)
+			break;
+		/* fall through - check memory as well */
+	case MEMBALANCE:
+		me = export_mem();
+		if(me >= mi.pages)
+			goto commit;
+		break;
+	}
+	return(0);	/* NO! */
+ commit:
+	info_someone_came_in();
+	return(1);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/comm.c linux-openmosix/hpc/comm.c
--- linux/hpc/comm.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/comm.c	2002-12-29 16:29:28.000000000 +0100
@@ -0,0 +1,2108 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Oren Laadan, Moshe Bar
+ */
+
+
+#include <linux/sched.h>
+#include <linux/socket.h>
+#include <linux/poll.h>
+#include <net/sock.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <linux/hpc.h>
+#include <linux/hpcctl.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/smp_lock.h>
+#include <asm/pgtable.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#include <linux/mfs_socket.h>
+#endif /* CONFIG_MOSIX_FS */
+
+#define MIG_DAEMON_PORT		0x3412
+#define INFO_DAEMON_PORT	0x3415
+
+/*
+ * mosix specific data per contact
+ */
+#define COMM_DEF_HEADSIZE	256
+
+struct mosix_link {
+	/* the first 2 elements are common to both types and must stay there */
+	struct socket *sock;	/* socket for communications */
+	int flags;		/* status flags */
+	int dlen;		/* length of pending data */
+	int peer;		/* mosix # of peer */
+	char *hideptr;		/* pointer to hidden data (current) */
+	char *hidebuf;		/* pointer to start of hidden data buffer */
+	int hidelen;		/* dlen of hidden data */
+	char head[COMM_DEF_HEADSIZE];
+};
+
+spinlock_t skown_lock = SPIN_LOCK_UNLOCKED;
+
+#define COMM_HEADINUSE		0x01
+#define COMM_WAITACCEPT		0x02
+#define COMM_HIDEDATA		0x04
+#define COMM_FULLLINK		0x08
+#define COMM_INFOLINK		0x10
+
+#define	COMM_MAX_MULTIWAIT	10
+
+#define COMM_SOCKET_SPARE	2048
+#define COMM_SOCKET_DATA	16384
+/*#define COMM_SOCKET_BUFFER	(COMM_SOCKET_SPARE + COMM_SOCKET_DATA)*/
+#define	COMM_SOCKET_BUFFER	131072
+
+
+
+
+
+#define COMM_REMOTE_TIMO	((unsigned long) 200*HZ) /* changed form 300 */
+#define COMM_CONNECT_TIMO	((unsigned long) 4*HZ)   /* changed from 5 */
+#define COMM_RECONN_TIMO	((unsigned long) 10*HZ)
+
+
+#ifdef CONFIG_MOSIX_DFSA
+#define	DISABLE_FLAGS	(DDEPUTY|DREMOTEDFSA)
+#else
+#define	DISABLE_FLAGS	DDEPUTY
+#endif /* CONFIG_MOSIX_DFSA */
+
+#define	DISABLE_EVENTS()	do {if(current->mosix.dflags & DISABLE_FLAGS) deeper_sleep();} while(0)
+#define	ENABLE_EVENTS()		do {if(current->mosix.dflags & DISABLE_FLAGS) lighter_sleep();} while(0)
+
+int comm_type;
+unsigned long comm_remote_timo = COMM_REMOTE_TIMO;	/* for remote accept */
+unsigned long comm_connect_timo = COMM_CONNECT_TIMO;	/* for connection */
+unsigned long comm_reconn_timo = COMM_RECONN_TIMO;	/* for reconnection */
+
+/*
+ * make sure that all pages in range cause no remote page-fault requests later.
+ * Once we find a page that would cause a page-fault, we may either report it
+ * by returning 0 (normal return is 1) or fix it and make it dirty.
+ */
+int
+dirty_all_remote_pages(unsigned long start, unsigned long size, int doit)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct * vma;
+	unsigned long addr, lastaddr;
+	unsigned long limit = (start + size + PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned int hidedata = 0;
+	int ret = 1;
+
+	if(size == 0)
+		return(1);
+	down_read(&mm->mmap_sem);
+	if(!(vma = find_vma(mm, start)))
+		goto unlock;
+	for(addr = start & ~(PAGE_SIZE-1) ; addr < limit ; addr += PAGE_SIZE)
+	{
+		while(!vma->vm_file || addr >= vma->vm_end ||
+			(doit && !(vma->vm_flags & VM_WRITE)))
+			/* (the last condition will cause a SIGSEGV,
+					   which we don't want here) */
+		{
+			lastaddr = vma->vm_end;
+			if(!(vma = vma->vm_next))
+				goto unlock;
+			if(vma->vm_file && (vma->vm_flags & VM_GROWSDOWN))
+			/* (a mad-hatter is permitted use sys_mmap this way) */
+			{
+				if((addr = lastaddr) >= limit)
+					goto unlock;
+			}
+			else if((addr = vma->vm_start) >= limit)
+				goto unlock;
+			addr = vma->vm_start;
+		}
+		if(vma->vm_flags & VM_GROWSDOWN)
+		  /* Hmmm... will any executable file-format ever allow this? */
+			panic("dirty_all_remote_pages: stack mapped to file");
+
+		/* Dirty pages (including swap) are OK - all others are not */
+		pgd = pgd_offset(current->mm, addr);
+		if(pgd_none(*pgd) || pgd_bad(*pgd) ||
+			pmd_none(*(pmd = pmd_offset(pgd, addr))) ||
+			pmd_none(*pmd) || pmd_bad(*pmd) ||
+			(pte_present(*(pte = pte_offset(pmd, addr))) ?
+				!pte_dirty(*pte) : pte_none(*pte)))
+		{
+			if(!doit)
+			{
+				ret = 0;
+				goto unlock;
+			}
+			if (!hidedata) {
+				hidedata = 1;
+				if(comm_hidedata())
+				{
+					ret = 0;
+					goto unlock;
+				}
+			}
+			handle_mm_fault(mm, vma, addr, 1);
+		}
+	}
+	unlock:
+	up_write(&mm->mmap_sem);
+	return(ret);
+}
+
+/*
+ * internal communication routines
+ */
+
+static void *comm_mkhead(int);
+static inline void comm_setup_link(mosix_link *, int);
+static inline void comm_unset_link(mosix_link *);
+static inline int comm_setup_socket(struct socket *, int);
+static inline void comm_unset_socket(struct socket *);
+static void *comm_malloc(int);
+static int comm_dorecv(struct socket *, struct msghdr *, int);
+static int comm_packregs(struct comm_header *, char *);
+static int comm_unpackregs(struct comm_header *, char *);
+static int comm_packident(char *);
+static int comm_unpackident(char *);
+static int comm_waitaccept(void);
+static int comm_poll(int, int, unsigned long);
+static void comm_data_ready(struct sock *, int);
+static int comm_getname(struct socket *, struct sockaddr *);
+static void comm_shutdown(mosix_link *);
+
+static inline struct socket *comm_set_address(int, struct sockaddr *, int);
+static inline struct socket *comm_ip_set_addr(int, struct sockaddr *, int);
+static inline int comm_ip_getname(struct socket *, struct sockaddr *);
+static inline int comm_ip_setup_socket(struct socket *, int);
+static void comm_ip_migration_mode(int);
+
+void
+comm_report_violation(char *desire, struct sockaddr *addr)
+{
+	unsigned int a = htonl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
+
+	printk("Received an unauthorized %s request from %d.%d.%d.%d\n", desire,
+		(a & 0xff000000) >> 24, (a & 0xff0000) >> 16,
+		(a & 0xff00) >> 8, a & 0xff);
+}
+
+static inline struct task_struct *
+find_task_by_sock(struct socket *sock)
+{
+	struct task_struct *p = NULL;
+	struct sock *sk;
+
+	spin_lock(&skown_lock);
+	if((sk = sock->sk) && (p = sk->owner))
+		get_task_struct(p);
+	else
+		spin_unlock(&skown_lock);
+	return(p);
+}
+
+static inline void
+comm_setup_link(mosix_link *mlink, int peer)
+{
+	mlink->dlen = 0;
+	mlink->peer = peer;
+	mlink->hideptr = NULL;
+	mlink->hidebuf = NULL;
+	mlink->hidelen = 0;
+}	
+
+static inline void
+comm_unset_link(mosix_link *mlink)
+{
+	if (mlink->flags & COMM_FULLLINK) {
+		if (mlink->hidebuf) {
+			kfree(mlink->hidebuf);
+			mlink->hidebuf = NULL;
+			mlink->hideptr = NULL;
+			mlink->hidelen = 0;
+		}
+		mlink->dlen = 0;
+	}
+	mlink->flags &= ~(COMM_WAITACCEPT | COMM_HIDEDATA);
+}
+
+static void *
+comm_malloc(int size)
+{
+	void *mem;
+
+	while(1)
+	{
+		if((mem = kmalloc(size, GFP_KERNEL)))
+			return(mem);
+	}
+}
+
+static int
+comm_packregs(struct comm_header *header, char *ptr)
+{
+	int regs;
+	int bit;
+	int size = 0;
+	int *regptr = (int *)ptr;
+	struct task_struct *p = current;
+	regs = which_regs_to_send();
+	if (header)
+		header->regs = regs;
+	if (!regs)
+		return (0);
+
+	regs = ~regs;
+
+	while (regs != 0xffffffff) {
+		bit = ffz(regs);
+		if (ptr)
+			*(regptr++) = ((int *)p->mosix.altregs)[bit];
+		regs |= (1 << bit);
+		size++;
+	}
+	return (size << 2);	/* size * sizeof(int) */
+}
+
+
+static int
+comm_unpackregs(struct comm_header *header, char *ptr)
+{
+	int regs;
+	int bit;
+	int size = 0;
+	int *regptr = (int *)ptr;
+	struct task_struct *p = current;
+
+	regs = header->regs;
+	p->mosix.deputy_regs ^= regs;
+
+	regs = ~regs;
+	while (regs != 0xffffffff) {
+		bit = ffz(regs);
+		((int *)p->mosix.altregs)[bit] = *(regptr++);
+		regs |= (1 << bit);
+		size++;
+	}
+
+
+	return (size << 2);	/* size * sizeof(int) */
+}
+
+
+static int
+comm_packident(char *ptr)
+{
+	if (ptr) {
+		((int *)ptr)[0] = PE;
+		((int *)ptr)[1] = comm_getpeer(current->mosix.contact);
+
+		/*
+		 * if this is the first migration to a node,
+		 * tell them, so they flush any of our old cached files,
+		 */
+		if (!config_get_status(((int *)ptr)[1]))
+			((int *)ptr)[0] |= 0x80000000;
+
+	}
+	return (2 * sizeof(int));
+}
+
+
+static int
+comm_unpackident(char *ptr)
+{
+	int ret = -1;
+	int him, me;
+	him = ((int *)ptr)[0];
+	me = ((int *)ptr)[1];
+	
+	if (him & 0x80000000)
+		rinode_flush_files(him & ~0x80000000);
+	if (comm_getpeer(current->mosix.contact) == (him & 0x7fffffff)
+								 && PE == me)
+		ret = 2 * sizeof(int);
+
+	return (ret);
+}
+
+
+/*
+ * comm_startup() - initialize communication layer
+ */
+void
+comm_startup(void)
+{
+	/* nothing to do */
+}
+
+/*
+ * comm_setup_socket() - setup socket parameters (specific to its type)
+ */
+static inline int
+comm_setup_socket(struct socket *sock, int mos)
+{
+	int val;
+	int error;
+	int connect = 0;
+	mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	/*
+	 * socket parameters:
+	 * - SO_SNDBUF, SO_RCVBUF 
+	 * - SO_KEEPALIVE (for connection-oriented sockets)
+	 */
+
+	val = COMM_SOCKET_BUFFER;
+	if ((error = sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
+						(char *) &val, sizeof(val))) ||
+	    (error = sock_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+	    					(char *) &val, sizeof(val))))
+		goto failed;
+/*
+	val = IPTOS_LOWDELAY;
+	if ((error = sock_setsockopt(sock, SOL_IP, IP_TOS, (char *)&val,
+								sizeof(val))))
+		goto failed;
+*/
+
+	switch (mos) {
+	case COMM_INFO:
+		sock->sk->data_ready = comm_data_ready;
+		break;
+	case COMM_LOOSE:
+		/* 
+		 * set "sk->bsdism" (SO_BSDCOMPAT) to prevent ICMP
+		 * errors from being reflected in the UDP socket,
+		 * thus receiving old errors on new calls.
+		 */
+		val = 1;
+		if ((error = sock_setsockopt(sock, SOL_SOCKET,
+					     SO_BSDCOMPAT, (char*)&val,sizeof(val))))
+			goto failed;
+	case COMM_ACCEPT:
+	case COMM_TOADDR:
+	default:
+		set_bit(SOCK_INTER_MOSIX, &sock->flags);
+		if (mos == COMM_LOOSE) /* UDP - we're done */
+			break;
+		val = 1;
+		if ((error = sock_setsockopt(sock, SOL_SOCKET,
+					     SO_KEEPALIVE, (char *) &val, sizeof(val))))
+			goto failed;
+		/* fall through */
+	case COMM_MIGD:
+		connect = 1;
+		val = 1;
+		break;
+	}
+
+	switch (comm_type) {
+	case AF_INET:
+		error = comm_ip_setup_socket(sock, connect);
+		break;
+	default:
+		panic("comm_setup_socket: unknown comm_type");
+	}
+
+ failed:
+	set_fs(oldfs);
+	return (error);
+}
+
+static inline void
+comm_unset_socket(struct socket *sock)
+{
+	spin_lock_irq(&skown_lock);
+	sock->sk->owner = NULL;
+	clear_bit(SOCK_INTER_MOSIX, &sock->flags);
+	spin_unlock_irq(&skown_lock);
+}
+
+
+static inline int
+comm_ip_setup_socket(struct socket *sock, int connect)
+{
+	int val;
+	int error;
+
+	/* NOTE: at this point set_fs(KERNEL_DS) is on */
+
+	if (connect) {
+		mm_segment_t oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		val = MOSIX_CONNECTION_KEEPALIVE_INTERVAL;
+		if ((error = sock->ops->setsockopt(sock, IPPROTO_TCP,
+			TCP_KEEPINTVL, (char *) &val, sizeof(val))))
+		{
+			resume:
+			set_fs(oldfs);
+			return(error);
+		}
+		val = MOSIX_CONNECTION_KEEPALIVE_MAXTRIES;
+		if ((error = sock->ops->setsockopt(sock, IPPROTO_TCP,
+			TCP_KEEPCNT, (char *) &val, sizeof(val))))
+			goto resume;
+		val = MOSIX_CONNECTION_KEEPALIVE_TOTAL;
+		if ((error = sock->ops->setsockopt(sock, IPPROTO_TCP,
+			TCP_KEEPIDLE, (char *) &val, sizeof(val))))
+			goto resume;
+		val = 1;
+		if ((error = sock->ops->setsockopt(sock, IPPROTO_TCP,
+			TCP_NODELAY, (char *) &val, sizeof(val))))
+			goto resume;
+		set_fs(oldfs);
+	}
+	return (0);
+}
+
+/*
+ * comm_open() - open a socket for openMosix communications
+ * 
+ * mos > 0: 		connect to migdaemon on node #mos
+ * mos = COMM_TOADDR:	connect to address given in maddr->saddr
+ * mos = COMM_ACCEPT:	set up a socket and prepare to accept
+ * mos = COMM_MIGD:	set up a socket for mig-daemon
+ * mos = COMM_INFOD:	set up a socket for info-daemon
+ * mos = COMM_LOOSE	connect to multiple daemons
+ */
+mosix_link *
+comm_open(int mos, mosix_addr *maddr, unsigned long timo)
+{
+	int error = -EDIST;
+	struct socket *sock = NULL;
+	mosix_link *mlink = NULL;
+	struct sockaddr sa;
+	int connect = 1, bind = 1, need_comm = 1, listen = 1, peer = 0;
+	struct sockaddr *saddr = &(maddr->saddr);
+	DECLARE_WAITQUEUE(wait, current);
+
+	/*
+	 * COMM_INFO:	connect = 0, need_comm = 0, listen = 0, bind = 1
+	 * COMM_MIGD:	connect = 0, need_comm = 1, listen = 1, bind = 1
+	 * COMM_ACCEPT:	connect = 0, need_comm = 1, listen = 1, bind = 1
+	 * COMM_TOADDR: connect = 1, need_comm = 1, listen = 0, bind = 1
+	 * COMM_LOOSE:  connect = 0, need_comm = 0, listen = 0, bind = 0
+	 * deafult:     connect = 1, need_comm = 1, listen = 1, bind = 1
+	 */
+	switch (mos) {
+	case COMM_LOOSE:
+		bind = 0;
+		/* fall through */
+	case COMM_INFO:
+		listen = 0;
+		/* fall through */
+	case COMM_MIGD:
+		need_comm = 0;
+		/* fall through */
+	case COMM_ACCEPT:
+		connect = 0;
+		if(!saddr)
+			saddr = &sa;
+		break;
+	case COMM_TOADDR:
+		if(saddr->sa_family != AF_INET)
+			return(NULL);
+		break;
+	default:
+		peer = mos;
+		saddr = &sa;
+		break;
+	}
+	DISABLE_EVENTS();
+	/* fill in socket address and allocate a socket */
+	if (!(sock = comm_set_address(mos, saddr, 1)))
+		goto failed;
+
+	if (need_comm) {	 	/* mosix_link required ? */
+		mlink = kmalloc(sizeof(mosix_link), GFP_KERNEL);
+		if (!mlink) {
+		no_memory:
+			goto failed;
+		}
+		mlink->flags = COMM_FULLLINK;
+		comm_setup_link(mlink, peer);
+	} else {
+		mlink = kmalloc(sizeof(struct socket *) + sizeof(int),
+								GFP_KERNEL);
+		if (!mlink)
+			goto no_memory;
+		mlink->flags = COMM_INFOLINK;
+	}
+	mlink->sock = sock;
+	
+	if ((error = comm_setup_socket(sock, mos)))
+		goto failed;
+
+	if (!connect) { 			/* setup server - listen */
+		if(bind)
+		{
+			error = sock->ops->bind(sock, saddr, sizeof(*saddr));
+			if (error) {
+				if(error == -EADDRINUSE && mos == COMM_MIGD)
+					printk("Migration port (%d) Already in use\n", ntohs(MIG_DAEMON_PORT));
+				goto failed;
+			}
+		}
+		if (listen) {			/* connection required ? */
+			error = sock->ops->listen(sock, SOMAXCONN);
+			if (error) {
+				goto failed;
+			}
+		}
+
+		if (mos == COMM_ACCEPT) {
+			mlink->flags |= COMM_WAITACCEPT;
+			if ((error = comm_getname(sock, saddr))) {
+				goto failed;
+			}
+		}
+	} else {		/* setup client - connect */
+		if (!timo)
+			timo = MAX_SCHEDULE_TIMEOUT;
+		error = sock->ops->connect(sock, saddr, sizeof(*saddr),
+								O_NONBLOCK);
+		add_wait_queue(sock->sk->sleep, &wait);
+		while (sock->state != SS_CONNECTED) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			error = sock->ops->connect(sock, saddr, sizeof(*saddr),
+								O_NONBLOCK);
+			if (error != -EALREADY || (error=sock_error(sock->sk)))
+				break;
+
+			timo = schedule_timeout(timo);
+			if (timo <= 0) {
+				error = -EAGAIN;
+				break;
+			}
+		}
+		remove_wait_queue(sock->sk->sleep, &wait);
+		set_current_state(TASK_RUNNING);
+
+		if (error) {
+			goto failed;
+		}
+		if (sock->sk->err) {
+			error = sock_error(sock->sk);	/* cleans error.. */
+			goto failed;
+		}
+		/* client socket ready */
+	}
+	ENABLE_EVENTS();
+
+	return (mlink);
+
+failed:
+	ENABLE_EVENTS();
+	if (sock)
+		sock_release(sock);
+	if (mlink)
+		kfree(mlink);
+	return (0);
+}
+
+/*
+ * comm_use() - set new "contact" for a process (and get the old one)
+ */
+mosix_link *
+comm_use(struct task_struct *p, mosix_link *mlink)
+{
+	mosix_link *oldmlink;
+
+	spin_lock_irq(&skown_lock);
+	if ((oldmlink = p->mosix.contact))
+		oldmlink->sock->sk->owner = NULL;
+	p->mosix.contact = NULL;
+	if (mlink)
+	{
+		p->mosix.contact = mlink;
+		mlink->sock->sk->owner = p;
+	}
+	spin_unlock_irq(&skown_lock);
+	if(test_bit(SOCK_OOB_IN, &mlink->sock->flags))
+		tell_process(p, DREQ_URGENT);
+	return (oldmlink);
+}
+
+
+/*
+ * comm_close() - close an openMosix communication socket
+ *   if called with NULL argument, close our contact and nullify it
+ */
+void
+comm_close(mosix_link *mlink)
+{
+	unsigned int ours = 0;
+
+	if (!mlink) {
+		ours = 1;
+		mlink = current->mosix.contact;
+	}
+
+	comm_shutdown(mlink);
+	sock_release(mlink->sock);
+
+	if (ours)
+		current->mosix.contact = NULL;
+
+	kfree(mlink);
+}
+
+
+/*
+ * comm_accept() - accept a connection on openMosix socket
+ */
+int
+comm_accept(mosix_link *ml, mosix_link **mlp, mosix_addr *ma, unsigned long t)
+{
+	int error = 0;
+	struct socket *sock;
+	struct sockaddr *saddr = &(ma->saddr);
+
+	if ((*mlp = kmalloc(sizeof(mosix_link), GFP_KERNEL)) == 0)
+		return (-ENOMEM);
+
+	sock = sock_alloc();
+	if (!sock) {
+		kfree(*mlp);
+		return (-EMFILE);
+	}
+	sock->type = ml->sock->type;
+	sock->ops = ml->sock->ops;
+
+	if (t && !comm_poll(POLLIN | POLLRDNORM, 0, t))
+		error = -EAGAIN;
+
+	if (!error)
+		error = ml->sock->ops->accept(ml->sock, sock, 0);
+
+	if (!error && saddr)
+		error = comm_getname(sock, saddr);
+
+	if (error) {
+	failed:
+		kfree(*mlp);
+		sock_release(sock);
+		*mlp = NULL;
+	} else {
+		struct sockaddr saddr;
+		int val;
+
+		if (sock->ops->getname(sock, &saddr, &val, 1)) {
+			error = -ENOTCONN;
+			goto failed;
+		}
+		if (!(val = net_to_mos((mosix_addr *)&saddr))) {
+			comm_report_violation("migration", &saddr);
+			error = -EDIST;
+			goto failed;
+		}
+		(*mlp)->sock = sock;
+		(*mlp)->flags = COMM_FULLLINK;
+		comm_setup_link(*mlp, val);
+
+		if ((error = comm_setup_socket(sock, PE)))
+			goto failed;	
+	}
+	return (error);
+}
+
+/*
+ * comm_waitaccept() - accept a connection on openMosix socket
+ */
+static int
+comm_waitaccept()
+{
+	struct task_struct *p = current;
+	mosix_link *mlink;
+	int error;
+
+	if ((error = comm_accept(p->mosix.contact, &mlink, 0, comm_remote_timo)))
+		return (error);
+
+	comm_close(comm_use(p, mlink));
+	return (0);
+}
+
+
+/*
+ * comm_free() - free a head/data which is no longer used
+ */
+void
+comm_free(void *head)
+{
+	mosix_link *mlink;
+	struct task_struct *p = current;
+
+	if(!head)
+		return;
+
+	mlink = p->mosix.contact;
+	if (mlink->flags & COMM_INFOLINK) {
+		kfree(head);
+		return;
+	}
+
+	if (head == &mlink->head + COMM_HLEN) {
+		mlink->flags &= ~COMM_HEADINUSE;
+		goto out;
+	} else if (head == &(mlink->head)) {
+		/* default head is (supposedly) in use */
+		mlink->flags &= ~COMM_HEADINUSE;
+		goto out;
+	} else {
+		/* must be a head we previously allocated */
+		kfree(head);
+		return;
+	}
+
+	mosix_panic("comm_free() # 1");
+
+out:
+
+}
+
+
+/*
+ * comm_mkhead() - prepares a head of size hlen
+ */
+void *
+comm_mkhead(int hlen)
+{
+	mosix_link *mlink;
+	void *head;
+
+	mlink = current->mosix.contact;
+
+	if ((mlink->flags & COMM_HEADINUSE) || hlen > COMM_DEF_HEADSIZE) {
+		head = kmalloc(hlen, GFP_KERNEL);
+		if(!head)
+			return(NULL);
+		return (head);
+	}
+
+	head = &mlink->head;
+	mlink->flags |= COMM_HEADINUSE;
+	return (head);
+}
+
+#define CMHDR(x)		((struct comm_header *)x)
+
+static char bigbuf[PAGE_SIZE], midbuf[512], smallbuf[128];
+static int bigtaken, midtaken, smalltaken;
+
+/*
+ * comm_send() - send a message (head + data)
+ */
+int
+comm_send(int type, void *head, int hlen, void *data, int dlen, int uspace)
+{
+	mosix_link *mlink;
+#ifdef CONFIG_MOSIX_DFSA
+	struct comm_header header = { 0, 0, 0, 0, 0, 0 };
+	struct iovec iov[4];
+	int dfsalen = 0;
+	char *dfsadata = NULL;
+#else
+	struct comm_header header = { 0, 0, 0, 0, 0, 0 };
+	struct iovec iov[3];
+#endif /* CONFIG_MOSIX_DFSA */
+	struct msghdr msg = { NULL, 0, iov, 0, NULL, 0, MSG_NOSIGNAL };
+	mm_segment_t oldfs = { 0 };
+	int niov = 1;
+	int size = 0;
+	void *free_head = 0;
+	int error = -ENOMEM;
+	void *tofree = NULL;
+	int *tozero = NULL;
+	void *kerdat;
+
+	if(uspace && !dirty_all_remote_pages((unsigned long)data, dlen, 0))
+	{
+		if(!smalltaken && dlen <= sizeof(smallbuf))
+		{
+			kerdat = smallbuf;
+			smalltaken = 1;
+			tozero = &smalltaken;
+		}
+		else if(!midtaken && dlen <= sizeof(midbuf))
+		{
+			kerdat = midbuf;
+			midtaken = 1;
+			tozero = &midtaken;
+		}
+		else if(!bigtaken && dlen <= sizeof(bigbuf))
+		{
+			kerdat = bigbuf;
+			bigtaken = 1;
+			tozero = &bigtaken;
+		}
+		else if(!(kerdat = tofree = kmalloc(dlen, GFP_KERNEL)))
+			return(-ENOMEM);
+		if(copy_from_user(kerdat, data, dlen))
+		{
+			if(tofree)
+				kfree(tofree);
+			return(-EFAULT);
+		}
+		uspace = 0;
+		data = kerdat;
+	}
+	DISABLE_EVENTS();
+
+	if(current->mosix.pass_regs)
+		type |= COMM_MFREGS;
+
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_check_comm_send(&type, &dfsadata, &dfsalen);
+	if(dfsalen < 0)
+	{
+		error = dfsalen;
+		goto failed;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+
+	if (current->mosix.dflags & DREMOTE)
+		current->mosix.dflags |= DPSYNC;
+
+	mlink = current->mosix.contact;
+
+	/* validate address range if in user-space (EFAULT ?) */
+	/*if (data && uspace && !access_ok(VERIFY_READ, data, dlen)) {*/
+	if (data && uspace && !ucache_ok((unsigned long)data, dlen, VM_READ)) {
+		error = -EFAULT;
+		goto failed;
+	}
+
+	if (type & COMM_MFREGS)
+	{
+		if (!(size = comm_packregs(0, 0))) {
+			type &= ~COMM_MFREGS;
+			regs_were_sent();
+		}
+	}
+	if (type & COMM_MFIDENT)
+		size += comm_packident(0);
+	if (!size) {
+		header.type = type;
+		header.hlen = (u_short) hlen;
+		iov[0].iov_base = &header;
+		iov[0].iov_len  = COMM_HLEN;
+		iov[1].iov_base = head;
+		iov[1].iov_len  = hlen;
+		niov++;
+	} else {
+		char *options;
+
+		/* allocate space for options - use default buffer if free */
+		size += COMM_HLEN;
+		iov[0].iov_len = size;
+		if ((mlink->flags & COMM_HEADINUSE) || size>COMM_DEF_HEADSIZE){
+			free_head = iov->iov_base = kmalloc(size, GFP_KERNEL);
+			if (!iov->iov_base)
+				goto failed;	/* xxx - error set above */
+		} else {
+			free_head = iov->iov_base = mlink->head;
+			mlink->flags |= COMM_HEADINUSE;
+		}
+		options = iov->iov_base + COMM_HLEN;
+		size = 0;
+		if (type & COMM_MFREGS)
+			size += comm_packregs(CMHDR(iov->iov_base), options);
+		if (type & COMM_MFIDENT)
+			size += comm_packident(options + size);
+		CMHDR(iov->iov_base)->type = type;
+		CMHDR(iov->iov_base)->hlen = (u_short) hlen;
+		iov[1].iov_base = head;
+		iov[1].iov_len  = hlen;
+		niov++;
+	}
+	CMHDR(iov->iov_base)->olen = size;
+	CMHDR(iov->iov_base)->dlen = 0;
+	size += COMM_HLEN + hlen;
+#ifdef CONFIG_MOSIX_DFSA
+	CMHDR(iov->iov_base)->dfsalen = dfsalen;
+	if(dfsalen)
+	{
+		iov[niov].iov_base = dfsadata;
+		iov[niov].iov_len = dfsalen;
+		size += dfsalen;
+		niov++;
+	}
+#else
+	CMHDR(iov->iov_base)->dfsalen = 0;
+#endif /* CONFIG_MOSIX_DFSA */
+	if (data) {
+		CMHDR(iov->iov_base)->type |= COMM_MFDATA;
+		CMHDR(iov->iov_base)->dlen = dlen;
+		iov[niov].iov_base = data;
+		iov[niov].iov_len  = dlen;
+		size += dlen;
+		niov++;
+	}
+
+	msg.msg_iovlen = niov;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	error = mlink->sock->ops->sendmsg(mlink->sock, &msg, size, NULL);
+	set_fs(oldfs);
+
+	if (free_head)
+		comm_free(free_head);
+
+	if((type & COMM_MFREGS) && error >= 0)
+		regs_were_sent();
+failed:
+	ENABLE_EVENTS();
+#ifdef CONFIG_MOSIX_DFSA
+	if (dfsadata)
+		kfree(dfsadata);
+#endif /* CONFIG_MOSIX_DFSA */
+	if(tofree)
+		kfree(tofree);
+	if(tozero)
+		*tozero = 0;
+	return (error < 0 ? error : 0);
+}
+
+
+/*
+ * comm_dorecv() - reliably read data from socket
+ *   on success, or if error == -EFAULT: returns number of bytes received
+ *   otherwise (any other error): returns negative error.
+ */
+static int
+comm_dorecv(struct socket *sock, struct msghdr *msg, int len)
+{
+	int n = 0;
+	int left = len;
+
+	do {
+		current->mosix.commpri = 1;
+		n = sock->ops->recvmsg(sock, msg, left, msg->msg_flags, 0);
+		current->mosix.commpri = 0;
+		if (n <= 0) {
+			/* if we already got -EFAULT, we must report */
+			if (n == -EFAULT) {
+				for ( ; msg->msg_iovlen; msg->msg_iov++,
+							 msg->msg_iovlen--)
+					 len -= msg->msg_iov->iov_len;
+				return (len);
+			}
+
+			/* .. otherwise - it is fatal - return error */
+			if (n < 0) 
+				return (n);
+			return (-EPIPE);
+		}
+
+		left -= n;
+		if (left) {
+			/* ...->recvmsg() updated iovec, we update msg */
+			while (!msg->msg_iov->iov_len) {
+				msg->msg_iov++;
+				msg->msg_iovlen--;
+			}
+		}
+	} while (left);
+	return (len);
+}
+				
+
+/*
+ * comm_recv() - receive a message head
+ */
+int
+comm_recv(void **headp, int *hlen)
+{
+	struct comm_header header;
+	mosix_link *mlink = current->mosix.contact;
+	char *head = 0, *options = 0;
+	struct iovec iov[2];
+	struct msghdr msg =
+		{ NULL, 0, iov, 1, NULL, 0, MSG_WAITALL | MSG_NOSIGNAL };
+	mm_segment_t oldfs;
+	int niov = 0;
+	int size;
+	int error = -EDIST;
+#ifdef CONFIG_MOSIX_DFSA
+	char *dfsadata = NULL;
+#endif /* CONFIG_MOSIX_DFSA */
+
+	if (!mlink)
+	{
+		if (current->mosix.dflags & (DDEPUTY|DREMOTE))
+			panic("comm_recv: null contact\n");
+		return(-EDIST);
+	}
+	DISABLE_EVENTS();
+
+	/* if we're not connected yet we should first accept a connection */
+	if (mlink->flags & COMM_WAITACCEPT) {
+		if (comm_waitaccept())
+			goto edist;
+		mlink = current->mosix.contact;
+	}
+	
+	iov[0].iov_base = &header;
+	iov[0].iov_len  = COMM_HLEN;
+
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	if ((error = comm_dorecv(mlink->sock, &msg, COMM_HLEN)) != COMM_HLEN) {
+		if (error >= 0)
+			error = -EFAULT;
+		goto failed;
+	}
+
+	size = header.hlen + header.olen;
+	if (size && !(head = comm_mkhead(size)))
+	{
+		error = -ENOMEM;
+		goto failed;
+	}
+
+	if (header.olen || (header.type & COMM_MFHEADOPTS)) {
+
+		/* the options will be placed after the message head */
+		options = head + header.hlen;
+		iov[0].iov_base = options;
+		iov[0].iov_len  = header.olen;
+		niov++;
+	}
+	if (header.hlen) {
+		iov[niov].iov_base = head;
+		iov[niov].iov_len  = header.hlen;
+		niov++;
+	}
+	
+	msg.msg_iovlen = niov;
+	if (niov && (error = comm_dorecv(mlink->sock, &msg, size)) != size) {
+		if (error >= 0)
+			error = -EFAULT;
+		goto failed;
+	}
+
+#ifdef CONFIG_MOSIX_DFSA
+	if (header.dfsalen)
+	{
+		if(!(dfsadata = kmalloc(header.dfsalen, GFP_KERNEL)))
+		{
+			printk("%s-comm_recv: failed to allocate DFSA space\n",
+				desc_mostask(NULL));
+			error = -ENOMEM;
+			goto failed;
+		}
+		iov[0].iov_base = dfsadata;
+		iov[0].iov_len = header.dfsalen;
+		msg.msg_iovlen = 1;
+		if ((error = comm_dorecv(mlink->sock, &msg, header.dfsalen)) !=
+								header.dfsalen)
+		{
+			kfree(dfsadata);
+			if (error >= 0)
+				error = -EFAULT;
+			goto failed;
+		}
+	}
+	if(header.type & COMM_MFDFSAOPTS)
+		dfsa_comm_recv(header.type, dfsadata);
+#endif /* CONFIG_MOSIX_DFSA */
+	if (header.type & COMM_MFDATA)
+		mlink->dlen = header.dlen;
+
+	size = 0;
+	if ((header.type & COMM_MFREGS) &&
+			(size = comm_unpackregs(&header, options)) < 0) {
+		goto edist;
+	}
+	options += size;
+	if ((header.type & COMM_MFIDENT) &&
+			(size = comm_unpackident(options)) < 0) {
+		goto edist;
+	}
+	options += size;
+	error = header.type & ~COMM_MFOPTIONS;	/* return value :-) */
+	if (hlen)
+		*hlen = header.hlen;
+
+	goto done;
+
+edist:
+	error = -EDIST;
+failed:
+	if (head)
+		comm_free(head);
+	comm_shutdown(mlink);
+	head = NULL;
+done:
+	/* the caller knows what she wants; from the type she knows the
+	   message is empty, and will not free it -> we do it ourselves */
+	if (!header.hlen) {
+		comm_free(head);
+		head = NULL;
+	}
+
+	ENABLE_EVENTS();
+	set_fs(oldfs);
+	*headp = head;
+	return (error);
+}
+
+/*
+ * comm_copydata() - copy data from the message (possibly to USPACE)
+ *   if 'uspace': returns 0 on success or result from comm_dorecv()
+ *   else: returns 0 on success, error otherwise (partial read -> panic)
+ */
+int
+comm_copydata(void *data, int len, int uspace)
+{
+	mosix_link *mlink;
+	struct iovec iov;
+	struct msghdr msg =
+		{ NULL, 0, &iov, 1, NULL, 0, MSG_WAITALL | MSG_NOSIGNAL };
+	int error = 0;
+	mm_segment_t oldfs = { 0 };
+	if(uspace && !dirty_all_remote_pages((unsigned long)data, len, 1))
+		return(-ENOMEM);
+	DISABLE_EVENTS();
+
+	mlink = current->mosix.contact;
+	if(mlink->dlen == 0 && mlink->hidebuf)
+	{
+		mlink->flags |= COMM_HIDEDATA;
+		mlink->dlen = mlink->hidelen;
+		mlink->hidelen = 0;
+	}
+
+	if(!mlink->dlen)
+		goto out;
+	len &= ~COMM_ZEROCOPYOK;
+
+	if (mlink->flags & COMM_HIDEDATA) {
+		if (uspace)
+			error = copy_to_user(data, mlink->hideptr, len);
+		else
+			memcpy(data, mlink->hideptr, len);
+		
+		/* NOTE: at this point page-fault *cannot* happen */
+		mlink->dlen -= len;
+		mlink->hideptr += len;
+		if (!mlink->dlen) {
+			kfree(mlink->hidebuf);
+			mlink->hideptr = NULL;
+			mlink->hidebuf = NULL;
+			mlink->flags &= ~COMM_HIDEDATA;
+		}
+		if (error) {
+			error = -EFAULT;
+			goto do_error;
+		}
+		goto out;
+	}
+
+	if (!uspace) {			/* switch to (KSPACE) */
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+	}
+
+	iov.iov_base = data;
+	iov.iov_len  = len;
+
+	error = comm_dorecv(mlink->sock, &msg, len);
+
+	if (error == len) {
+		error = 0;
+		mlink->dlen -= len;
+	} else if (error < 0) {
+
+	do_error:
+		if (error != -EFAULT)
+			comm_shutdown(mlink);
+	} else {
+		mlink->dlen -= error;
+		error = len - error;
+	}
+
+	if (!uspace)
+		set_fs(oldfs);
+
+out:
+	ENABLE_EVENTS();
+	return (error);
+}
+
+
+/*
+ * comm_recvdata() - receive entire data to an allocated buffer 
+ */
+int
+comm_recvdata(void **data)
+{
+	mosix_link *mlink;
+	char *buf;
+	struct iovec iov;
+	struct msghdr msg =
+		{ NULL, 0, &iov, 1, NULL, 0, MSG_WAITALL | MSG_NOSIGNAL};
+	mm_segment_t oldfs;
+	int error = 0;
+
+	DISABLE_EVENTS();
+
+	mlink = current->mosix.contact;
+	if(mlink->dlen == 0 && mlink->hidebuf)
+	{
+		mlink->flags |= COMM_HIDEDATA;
+		mlink->dlen = mlink->hidelen;
+		mlink->hidelen = 0;
+	}
+
+	/* data was hidden: simply hand the hidden data to the caller */
+	if (mlink->flags & COMM_HIDEDATA) {
+		/* actually, we never reach here in real-life */
+
+		*data = mlink->hidebuf;
+
+		/* test for the pathologic case of calling comm_recvdata()
+		   after a partial call to comm_copydata() ...*/
+		if (mlink->hidebuf != mlink->hideptr)
+			panic("comm_recvdata: hide pathology");
+
+		mlink->hideptr = NULL;
+		mlink->hidebuf = NULL;
+
+		goto out;
+	}
+
+	buf = comm_malloc(mlink->dlen);
+	iov.iov_base = buf;
+	iov.iov_len  = mlink->dlen;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	error = comm_dorecv(mlink->sock, &msg, mlink->dlen);
+	set_fs(oldfs);
+	if (error != mlink->dlen) {
+		if (error >= 0)
+			error = -EFAULT;
+		kfree(buf);
+		comm_shutdown(mlink);
+		*data = 0;
+	} else {
+		error = 0;
+		*data = buf;
+	}
+
+out:
+	mlink->dlen = 0;
+	ENABLE_EVENTS();
+
+	return (error);
+}
+
+
+/*
+ * comm_hidedata() - hide data (possibly exisiting) in the socket,
+ * to allow the socket to be used for a page-fault. The data is put
+ * in a buffer pointed to by comm->hide.
+ */
+int
+comm_hidedata()
+{
+	mosix_link *mlink;
+	struct iovec iov;
+	struct msghdr msg =
+		{ NULL, 0, &iov, 1, NULL, 0, MSG_WAITALL | MSG_NOSIGNAL};
+	mm_segment_t oldfs;
+	int error = 0;
+
+	mlink = current->mosix.contact;
+
+	/* if already hidden, or no data - return */
+	if (mlink->hidebuf || !mlink->dlen)
+		return(0);
+
+	DISABLE_EVENTS();
+
+	mlink->hideptr = mlink->hidebuf = comm_malloc(mlink->dlen);
+
+	iov.iov_base = mlink->hidebuf;
+	iov.iov_len  = mlink->dlen;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	error = comm_dorecv(mlink->sock, &msg, mlink->dlen);
+	set_fs(oldfs);
+	if (error != mlink->dlen) {
+		comm_shutdown(mlink);
+	} else
+		error = 0;
+	mlink->hidelen = mlink->dlen;
+	mlink->dlen = 0;
+	ENABLE_EVENTS();
+
+	return (error);
+}
+
+/*
+ * comm_flushdata() - flush remaining data from previous message
+ */
+void
+comm_flushdata(int dlen)
+{
+	mosix_link *mlink;
+	struct iovec iov;
+	struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0, 0 };
+	mm_segment_t oldfs;
+	int n = 0;
+#define COMM_FLUSH_BUF_SIZE	256
+	static char comm_flush_buffer[COMM_FLUSH_BUF_SIZE];	/* global bin */
+
+	mlink = current->mosix.contact;
+	if(mlink->dlen == 0 && mlink->hidebuf)
+	{
+		mlink->flags |= COMM_HIDEDATA;
+		mlink->dlen = mlink->hidelen;
+		mlink->hidelen = 0;
+	}
+	if (dlen == COMM_ALLDATA && !(dlen = mlink->dlen))
+		return;
+
+	if (mlink->flags & COMM_HIDEDATA) {
+		mlink->hideptr += mlink->dlen;
+		mlink->dlen -= dlen;
+		if (!mlink->dlen) {
+			kfree(mlink->hidebuf);
+			mlink->hidebuf = NULL;
+			mlink->hideptr = NULL;
+			mlink->flags &= ~COMM_HIDEDATA;
+		}
+		return;
+	}
+
+	DISABLE_EVENTS();
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	while (dlen)
+	{
+		iov.iov_base = comm_flush_buffer;
+		iov.iov_len = (dlen < COMM_FLUSH_BUF_SIZE) ? dlen :
+							COMM_FLUSH_BUF_SIZE;
+		msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL;
+		if ((n = comm_dorecv(mlink->sock, &msg, iov.iov_len)) <= 0)
+			break;
+		dlen -= n;
+		mlink->dlen -= n;
+	}
+	set_fs(oldfs);
+	if (n <= 0) {
+		comm_shutdown(current->mosix.contact);
+	}
+	ENABLE_EVENTS();
+}
+
+
+#define POLLIN_SET	(POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
+
+/*
+ * comm_peek() - peek the socket looking for data pending 
+ */
+int
+comm_peek(void)
+{
+	struct socket *sock;
+	int mask;
+
+	sock = current->mosix.contact->sock;
+		
+	mask = sock->ops->poll(NULL, sock, NULL);
+	return ((mask & POLLIN_SET) ? 1 : 0);
+}
+
+
+/*
+ * comm_poll() - wait for a communication event, interrupt or openMosix event
+ * returns 1 on communication events, and 0 otherwise
+ */
+static int
+comm_poll(int mask, int interruptible, unsigned long timo)
+{
+	struct socket *sock;
+	int pollmask;
+	static struct file sighfile = {.f_count = ATOMIC_INIT(1)};
+	DECLARE_WAITQUEUE(wait, current);
+
+	/*
+	 * sighfile: we are required to supply a file to "hold" while we poll.
+	 * a bit ridiculous in this context, but nobody will notice because
+	 * f_count will never drop to 0
+	 */
+	sock = current->mosix.contact->sock;
+	if(!timo)
+		timo = MAX_SCHEDULE_TIMEOUT;
+	add_wait_queue(sock->sk->sleep, &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		pollmask = sock->ops->poll(&sighfile, sock, NULL);
+		if ((pollmask & mask) ||
+		    (interruptible && signal_pending(current)))
+			break;
+		current->mosix.commpri = 1;
+		timo = schedule_timeout(timo);
+		current->mosix.commpri = 0;
+		if (timo <= 0)
+			break;
+	}
+	remove_wait_queue(sock->sk->sleep, &wait);
+	set_current_state(TASK_RUNNING);
+	return ((pollmask & mask) ? 1 : 0);
+}
+
+
+/*
+ * comm_wait() - wait for a message, or some other openMosix event
+ * return 1 if there is a message, 0 if another event occured first.
+ */
+int
+comm_wait(void)
+{
+	return (comm_poll(POLLIN_SET, 1, 0UL));
+}
+
+/*
+ * comm_send_urgent() - send notification using urgent data (OOB)
+ */
+int
+comm_send_urgent(void)
+{
+	struct iovec iov;
+	struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0, MSG_OOB|MSG_NOSIGNAL };
+	mm_segment_t oldfs;
+	int error;
+	unsigned char dummy;
+
+	dummy = 0xdb;
+	iov.iov_base = &dummy;
+	iov.iov_len  = 1;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	error = current->mosix.contact->sock->ops->
+			sendmsg(current->mosix.contact->sock, &msg, 1, 0);
+
+	set_fs(oldfs);
+
+	return(0);
+}
+
+/*
+ * comm_test_urgent() - test if urgent data is pending (OOB)
+ */
+int
+comm_test_urgent(void)
+{
+
+	return(test_bit(SOCK_OOB_IN, &current->mosix.contact->sock->flags));
+}
+
+/*
+ * comm_take_urgent() - take the pending OOB out of the stream,
+ *   preventing it from turning into a normal byte.
+ *   Caller must make sure that there is no other data in the stream.
+ */
+void
+comm_take_urgent(void)
+{
+	int was;
+	was = test_and_clear_bit(SOCK_OOB_IN,
+					&current->mosix.contact->sock->flags);
+
+}
+
+void
+mosix_notify_urgent(struct socket *sock)
+{
+	struct task_struct *p;
+
+	set_bit(SOCK_OOB_IN, &sock->flags);
+	if (!(p = find_task_by_sock(sock)))
+		return;
+	spin_unlock(&skown_lock);
+	if (p->mosix.dflags & DDEPUTY)
+	{
+		tell_process(p, DREQ_URGENT);
+		wake_up_mosix(p);
+	}
+	free_task_struct(p);
+}
+
+void
+mosix_notify_receive(struct socket *sock)
+{
+	struct task_struct *p = find_task_by_sock(sock);
+
+	if(!p)
+		return;
+#ifdef CONFIG_MOSIX_FS
+	if(p == mfs_main_server_task)
+	{
+		spin_unlock(&skown_lock);
+		mfs_new_request_arrived();
+		goto free_task;
+	}
+	if(test_bit(SOCK_WAIT_MFSDATA, &sock->flags))
+	{
+		spin_unlock(&skown_lock);
+		wake_up_process(p);
+		goto free_task;
+	}
+#endif /* CONFIG_MOSIX_FS */
+	spin_unlock(&skown_lock);
+
+	if(!(p->mosix.dflags & DREMOTE))
+	{
+		if (!(p->mosix.dflags & (DDEPUTY|DREMOTEDAEMON|DFINISHED)))
+			printk("mosix_notify_receive: pid = %d, "
+				"not DEPUTY or REMOTE\n", p->pid);
+		goto free_task;
+	}
+
+	p->mosix.commpri = 1;
+	current->need_resched = 1;
+	wake_up_mosix(p);
+	free_task:
+	free_task_struct(p);
+}
+
+/*
+ * comm_sendto() - send a datagram to someone
+ */
+int
+comm_sendto(int mos, void *data, int len, mosix_link *mlink, mosix_addr *to)
+{
+	struct iovec iov = {data, len};
+	struct sockaddr sa;
+	struct msghdr msg = {NULL, 0, &iov, 1, NULL, 0, MSG_NOSIGNAL};
+	mm_segment_t oldfs;
+	int error = -EDIST;
+
+	if (to)
+		sa = to->saddr;
+	else if (!comm_set_address(-mos, &sa, 0))
+		return (error);
+
+	msg.msg_name = &sa;
+	msg.msg_namelen = sizeof(sa);
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	error = mlink->sock->ops->sendmsg(mlink->sock, &msg, len, NULL);
+
+	set_fs(oldfs);
+
+	return (error);
+}
+
+
+/*
+ * comm_recvfrom() - receive a datagram from someone
+ * NOTE NOTE NOTE:  the timeout is in microseconds -- NOT ticks!
+ */
+int
+comm_recvfrom(void *data, int len, mosix_link *mlink, mosix_addr *from,
+	unsigned long timo)
+{
+	struct iovec iov = {data, len};
+	struct msghdr msg = { &from->saddr, sizeof(struct sockaddr),
+			      &iov, 1, NULL, 0, 0 };
+	mm_segment_t oldfs;
+	int error;
+	int nrecv = len, msgflg = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if(timo)
+	{
+#if MILLION % HZ
+		timo = timo * HZ / MILLION;
+#else
+		timo = timo / (MILLION/HZ);
+#endif
+	}
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	if (timo)
+		msgflg |= MSG_DONTWAIT;
+	else
+		timo = MAX_SCHEDULE_TIMEOUT;
+
+	add_wait_queue(mlink->sock->sk->sleep, &wait);
+	while (1) {
+		set_current_state(
+			msgflg ? TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
+
+		error = mlink->sock->ops->recvmsg(mlink->sock, &msg,
+							nrecv, msgflg, 0);
+		if(error >= 0 && !net_to_mos((mosix_addr *)&from->saddr))
+		{
+			comm_report_violation("information", &from->saddr);
+			error = -EPERM;
+			break;
+		}
+		if (error > 0)
+			break;
+
+		if (msgflg && timo <= 0) {
+			error = -EWOULDBLOCK;
+			break;
+		}
+
+		timo = schedule_timeout(timo);
+
+		if (signal_pending(current)) {
+			error = -EINTR;
+			break;
+		}
+	}
+	remove_wait_queue(mlink->sock->sk->sleep, &wait);
+	set_current_state(TASK_RUNNING);
+	set_fs(oldfs);
+	
+	if (msg.msg_flags & MSG_TRUNC) {
+		error = -EDIST;
+	}
+	
+	return (error);
+}
+
+
+/*
+ * comm_recvfrompe() - wrapper for comm_recvfrom, fills in mosix id
+ * instead of source address.
+ * NOTE NOTE NOTE:  the timeout is in microseconds -- NOT ticks!
+ */
+int
+comm_recvfrompe(void *data, int len, mosix_link *mlink,
+				  int *from, unsigned long timo)
+{
+	int error;
+	struct mosix_addr maddr;
+
+	error = comm_recvfrom(data, len, mlink, from ? &maddr : NULL, timo);
+	if (from)
+		*from = net_to_mos(&maddr);
+	return (error);
+}
+
+
+/*
+ * routines for debugging (can call from debugger)
+ */
+inline void
+comm_invalidate_address(mosix_addr *ma)
+{
+	ma->saddr.sa_family = AF_UNSPEC;
+}
+
+
+static inline struct socket *
+comm_set_address(int mos, struct sockaddr *sa, int makesock)
+{
+	switch (comm_type) {
+	case AF_INET:
+		return (comm_ip_set_addr(mos, sa, makesock));
+		/* NOT REACHED */
+	case AF_UNSPEC:
+		if (mos == COMM_TOADDR)
+			return (0);
+		/* FALL THROUGH */	
+	default:
+		panic("comm_set_address: unknown comm_type");
+		return(0);
+	}
+}
+
+
+/*
+ * comm_getname: fill in our name
+ */
+static int
+comm_getname(struct socket *sock, struct sockaddr *saddr)
+{
+	switch (comm_type) {
+		case AF_INET:
+			return (comm_ip_getname(sock, saddr));
+			break;
+		default:
+			panic("comm_getname: invalid comm_type");
+	}
+}
+
+/*
+ * comm_shutdown: shutdown socket
+ */
+static void
+comm_shutdown(mosix_link *mlink)
+{
+	struct socket *sock;
+	if (!mlink)
+		return;
+	sock = mlink->sock;
+
+	spin_lock_irq(&skown_lock);
+	sock->sk->owner = NULL;
+	clear_bit(SOCK_INTER_MOSIX, &sock->flags);
+	spin_unlock_irq(&skown_lock);
+	if (mlink->flags & COMM_FULLLINK) {
+		if (mlink->hidebuf) {
+			kfree(mlink->hidebuf);
+			mlink->hidebuf = NULL;
+			mlink->hideptr = NULL;
+			mlink->hidelen = 0;
+		}
+		mlink->dlen = 0;
+	}
+	mlink->flags &= ~(COMM_WAITACCEPT | COMM_HIDEDATA);
+	if (sock->ops)
+		sock->ops->shutdown(sock, SEND_SHUTDOWN);
+}
+
+static inline struct socket *
+comm_ip_set_addr(int mos, struct sockaddr *saddr, int makesock)
+{
+	struct sockaddr_in *sa;
+	struct socket *sock = (struct socket *) 1;	/* xxx - not NULL */
+	int proto = IPPROTO_TCP;
+	int type = SOCK_STREAM;
+	unsigned short port = MIG_DAEMON_PORT;
+
+	sa = (struct sockaddr_in *) saddr;
+	switch (mos) {
+	case COMM_LOOSE:
+		type = SOCK_DGRAM;
+		proto = IPPROTO_UDP;
+		port = INFO_DAEMON_PORT;
+		break;
+	case COMM_TOADDR:
+		/* address was set by the caller */
+		break;
+	case COMM_INFO:
+		proto = IPPROTO_UDP;
+		type = SOCK_DGRAM;
+		/* fall through */
+	case COMM_MIGD:
+		memset((void *)sa, 0, sizeof(struct sockaddr_in));
+	        sa->sin_family = AF_INET;
+		sa->sin_addr.s_addr = INADDR_ANY;
+		if (mos == COMM_MIGD)
+			sa->sin_port = MIG_DAEMON_PORT;
+		else
+			sa->sin_port = INFO_DAEMON_PORT;
+		break;
+	case COMM_ACCEPT:
+		memset((void *)sa, 0, sizeof(struct sockaddr_in));
+	        sa->sin_family = AF_INET;
+		sa->sin_addr.s_addr = INADDR_ANY;
+		sa->sin_port = 0;
+		break;
+	default:
+		if (mos < 0) {
+			type = SOCK_DGRAM;
+			proto = IPPROTO_UDP;
+			port = INFO_DAEMON_PORT;
+			mos = -mos;
+		}
+
+		if (!mos_to_net(mos, saddr)) {
+			return (0);
+		}
+		sa->sin_port = port;
+		break;
+	}
+
+	if (makesock && sock_create(AF_INET, type, proto, &sock)) {
+		return (0);
+	}
+
+	return (sock);
+}
+
+
+/*
+ * comm_ip_getname: fill in our name
+ */
+static inline int
+comm_ip_getname(struct socket *sock, struct sockaddr *saddr)
+{
+	int val;
+	struct sockaddr_in sa;
+	int error;
+
+	val = sizeof(sa);
+	error = sock->ops->getname(sock, (struct sockaddr *)&sa, &val, 0);
+	if(!error)
+	{
+		error = mymos_to_net((void *)saddr);
+		((struct sockaddr_in *)saddr)->sin_port = sa.sin_port;
+	}
+	return (error);
+}
+
+
+/*
+ * comm_migration_mode() - setup parameters for migration mode (on/off)
+ */
+void
+comm_migration_mode(int on)
+{
+	switch (comm_type) {
+	case AF_INET:
+		comm_ip_migration_mode(on);
+		break;
+	default:
+		panic("comm_setup_socket: unknown comm_type");
+	}
+}
+
+
+/*
+ * comm_ip_migration_mode() - setup parameters for migration mode (on/off)
+ */
+void
+comm_ip_migration_mode(int on)
+{
+	int val = on ? 0 : 1;
+	mm_segment_t oldfs;
+	int error;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	error = current->mosix.contact->sock->ops->setsockopt(
+		current->mosix.contact->sock, IPPROTO_TCP,
+		TCP_NODELAY, (char *) &val, sizeof(val));
+
+	set_fs(oldfs);
+}
+
+
+void
+comm_data_ready(struct sock *sk, int len)
+{
+	wake_up_interruptible(sk->sleep);
+}
+
+
+int
+comm_getpeer(mosix_link *mlink)
+{
+	return (mlink->peer);
+}
+
+
+#define MAX_LINK_POOL	30
+#define MIN_LINK_POOL	2
+#define LINK_POOL_AGE	60
+
+static int link_pool_age = LINK_POOL_AGE;
+
+static struct {
+	mosix_link *mlink;
+	int age;
+} link_pool[MAX_LINK_POOL];
+
+spinlock_t linkpool_lock = SPIN_LOCK_UNLOCKED;
+static atomic_t link_pool_used = ATOMIC_INIT(0);
+static int link_pool_next = 0;
+static int linkpool_closed = 1;
+DECLARE_WAIT_QUEUE_HEAD(wait_for_link_pool_used);
+
+void
+comm_init_linkpool(void)
+{
+	unsigned int i;
+
+	for(i = 0 ; i < MIN_LINK_POOL ; i++)
+	if (!(link_pool[i].mlink = comm_open(COMM_LOOSE, NULL, 0)))
+		break;
+	link_pool_next = i;
+	linkpool_closed = 0;
+}
+
+void
+comm_free_linkpool(void)
+{
+	unsigned int i;
+
+	spin_lock(&linkpool_lock);
+	linkpool_closed = 1;
+	spin_unlock(&linkpool_lock);
+	wake_up(&wait_for_link_pool_used);
+	for (i = 0 ; i < link_pool_next ; i++)
+		comm_close(link_pool[i].mlink);
+	link_pool_next = 0;
+}
+
+mosix_link *
+comm_borrow_linkpool()
+{
+	mosix_link *mlink;
+
+	while(1)
+	{
+		spin_lock(&linkpool_lock);
+		if(linkpool_closed)
+		{
+			spin_unlock(&linkpool_lock);
+			return(NULL);
+		}
+		if(link_pool_next)
+		{
+			mlink = link_pool[--link_pool_next].mlink;
+			atomic_inc(&link_pool_used);
+			spin_unlock(&linkpool_lock);
+			return(mlink);
+		}
+		if(atomic_read(&link_pool_used) <= MAX_LINK_POOL)
+		{
+			spin_unlock(&linkpool_lock);
+			atomic_inc(&link_pool_used);
+			if(!(mlink = comm_open(COMM_LOOSE, NULL, 0)))
+			{
+				atomic_dec(&link_pool_used);
+				wake_up(&wait_for_link_pool_used);
+			}
+			return(mlink);
+		}
+		spin_unlock(&linkpool_lock);
+		sleep_on_timeout(&wait_for_link_pool_used, HZ/10);
+		if (signal_pending(current))
+			return(NULL);
+	}
+}
+
+
+void
+comm_return_linkpool(mosix_link *mlink)
+{
+	atomic_dec(&link_pool_used);
+	spin_lock(&linkpool_lock);
+	if (!linkpool_closed &&
+		link_pool_next + atomic_read(&link_pool_used) <= MAX_LINK_POOL)
+	{
+		link_pool[link_pool_next].mlink = mlink;
+		link_pool[link_pool_next].age = link_pool_age;
+		link_pool_next++;
+		spin_unlock(&linkpool_lock);
+	}
+	else
+	{
+		spin_unlock(&linkpool_lock);
+		comm_close(mlink);
+	}
+	wake_up(&wait_for_link_pool_used);
+}
+
+
+void
+comm_age_linkpool()
+{
+	register int i;
+	struct mosix_link *mlink;
+
+	spin_lock(&linkpool_lock);
+	for(i = MIN_LINK_POOL ; i < link_pool_next ; )
+	if(--link_pool[i].age <= 0)
+	{
+		mlink = link_pool[i].mlink;
+		link_pool[i] = link_pool[--link_pool_next];
+		spin_unlock(&linkpool_lock);
+		comm_close(mlink);
+		spin_lock(&linkpool_lock);
+	}
+	else
+		i++;
+	spin_unlock(&linkpool_lock);
+}
+
+int
+reserved_mosix_address(struct sockaddr *addr)
+{
+	int port = ((struct sockaddr_in *)addr)->sin_port;
+
+	if(port != MIG_DAEMON_PORT && port != INFO_DAEMON_PORT)
+#ifdef CONFIG_MOSIX_FS
+	if(port != MFS_MAIN_PORT)
+#endif /* CONFIG_MOSIX_FS */
+		return(0);
+	if(current->mosix.dflags & (DPASSING|DHEAVYSLEEP))
+		return(0);
+#ifdef CONFIG_MOSIX_SECUREPORTS
+	if(!capable(CAP_NET_RAW))
+		return(1);
+#endif /* CONFIG_MOSIX_SECUREPORTS */
+	if (!net_to_mos((mosix_addr *)addr))
+		return(0);
+#ifndef CONFIG_MOSIX_SECUREPORTS
+	if(!capable(CAP_NET_RAW))
+		return(1);
+#endif /* CONFIG_MOSIX_SECUREPORTS */
+	printk("The Super-User is allowed to access openMosix ports -- "
+						"but it is not a good idea!\n");
+	return(0);
+}
+
+void
+debug_commdump(int pid)
+{
+	struct task_struct *p = 0;
+	struct socket *sock = 0 ;
+	mosix_link *mlink = 0;
+
+	if (pid == -1)
+		p = current;
+	else for_each_task(p)
+		if (p->pid == pid)
+			break;
+	if (p) {
+		mlink = p->mosix.contact;
+		if (mlink)
+			sock = mlink->sock;
+		else
+			sock = NULL;
+		printk("task=0x%x, socket=0x%x, sock=0x%x, mlink=0x%x\n",
+			(int)p, (int)sock, sock ? (int)sock->sk : 0,(int)mlink);
+		if (sock)
+			printk("socket-flags=0x%x, owner=%x\n",
+				(int)sock->flags, (int)sock->sk->owner);
+		if (mlink) {
+			printk("mlink:  dlen=%d  flags=0x%x  peer=0x%x",
+				mlink->dlen, mlink->flags, (int)mlink->peer);
+			printk("\n");
+		}
+	} else
+		printk("X: %s\n", current ? "no such pid" : "no current task");
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/config.c linux-openmosix/hpc/config.c
--- linux/hpc/config.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/config.c	2004-03-19 16:59:09.000000000 +0100
@@ -0,0 +1,994 @@
+/* Changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Oren Laadan, Amnon Shiloh.
+ */
+#include <linux/sched.h>
+#include <linux/reboot.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <hpc/debug.h>
+#include <linux/hpc.h>
+#include <linux/hpcctl.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
+static int
+mosix_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
+{
+	if(code == SYS_DOWN || code == SYS_HALT || code == SYS_POWER_OFF ||
+		code == SYS_RESTART)
+		expel(1);
+	return(NOTIFY_DONE);
+}
+
+struct notifier_block mosix_notifier =
+{
+	.notifier_call = mosix_notify_reboot,
+	.priority = 10,	/* Higher than drivers, so network still goes */
+};
+
+int PE;
+int NPE;
+int MAXPE;
+struct sockaddr my_mosix_net_address;
+
+#ifdef CONFIG_SMP
+static spinlock_t modifying = SPIN_LOCK_UNLOCKED;	/* use only TRYLOCK! */
+#endif /* CONFIG_SMP */
+
+static int pe_ready;
+
+int nmosnet;
+struct mosixnet *mosnet;
+static char *mosnetstat;
+rwlock_t mosnetstat_lock = RW_LOCK_UNLOCKED; 
+
+DECLARE_WAIT_QUEUE_HEAD(wait_for_mosix_config);
+DECLARE_WAIT_QUEUE_HEAD(wait_for_all_to_adjust);
+
+/* local subroutines */
+static int config_validate(void);
+static int config_reduce_to_common(struct mosixnet *, int);
+static int config_shutdown(void);
+
+
+/* hooks for IP network */
+static int ip_to_mosix(struct sockaddr *);
+static int ip_consistent(int, struct mosixnet *, int, int);
+static void ip_showconf(int, struct mosixnet *, int);
+static void ip_mos_to_net(int, int, struct sockaddr *);
+static int ip_addr_to_ascii(struct sockaddr *, char *, int);
+static struct mosixnet *ip_reduce_to_common(struct mosixnet *, int *);
+
+int
+config_get_status(int pe)
+{
+	int ret;
+
+	if (!mos_to_net(pe, NULL))
+		return (-ENXIO);
+	pe--;
+	read_lock(&mosnetstat_lock);
+	ret = mosnetstat[pe >> 3] & (1 << (pe & 7));
+	read_unlock(&mosnetstat_lock);
+	return(ret);
+}
+
+int
+config_set_status(int pe)
+{
+	pe--;
+	write_lock(&mosnetstat_lock);
+	mosnetstat[pe >> 3] |= (1 << (pe & 7));
+	write_unlock(&mosnetstat_lock);
+	return (0);
+}
+
+static int
+config_shutdown(void)
+{
+	struct mosixnet *svmton;
+	int svnmton, svpe, svnpe, svmaxpe;
+	int error;
+	struct task_struct *t1, *t2;
+
+	/* temporarily change configuration */
+	lock_mosix();
+	svpe = PE;
+	svnpe = NPE;
+	svmaxpe = MAXPE;
+	svmton = mosnet;
+	svnmton = nmosnet;
+	mosnet = NULL;
+	nmosnet = 0;
+	NPE = MAXPE = 0;
+	unlock_mosix();
+
+	/* bring back our processes, and expel foreign */
+	if ((error = config_validate()))
+		goto fail;
+	lock_mosix();
+	PE = 0;
+	unlock_mosix();
+	info_reconfig();
+
+	/* wakeup our daemons */
+	lock_mosix();
+	if((t1 = info_proc))
+		get_task_struct(t1);
+	if((t2 = mig_proc))
+		get_task_struct(t2);
+	unlock_mosix();
+	if(t1)
+	{
+		send_sig(SIGALRM, t1, 1);
+		free_task_struct(t1);
+	}
+	if(t2)
+	{
+		send_sig(SIGALRM, t2, 1);
+		free_task_struct(t2);
+	}
+
+	lock_mosix();
+	while ((mig_daemon_active || info_daemon_active) &&
+						!signal_pending(current))
+	{
+		unlock_mosix();
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ/10);
+		lock_mosix();
+	}
+	unlock_mosix();
+	set_current_state(TASK_RUNNING);
+	if (signal_pending(current))
+	{
+		error = -ERESTART;
+		goto fail;
+	}
+
+	printk(KERN_NOTICE "openMosix configuration disabled\n");
+	unregister_reboot_notifier(&mosix_notifier);
+
+	if (svnmton) {
+		kfree(svmton);
+		kfree(mosnetstat);
+	}
+	
+	lock_mosix();
+	pe_ready = 0;
+	unlock_mosix();
+#ifdef CONFIG_MOSIX_FS
+	mfs_change_pe();
+#endif /* CONFIG_MOSIX_FS */
+
+	return (0);
+
+fail:
+	lock_mosix();
+	PE = svpe;
+	NPE = svnpe;
+	MAXPE = svmaxpe;
+	mosnet = svmton;
+	nmosnet = svnmton;
+	unlock_mosix();
+	wake_up(&wait_for_mosix_config);
+	return (error);
+}
+
+void
+wait_for_mosix_configuration(int *active)
+{
+	struct task_struct *p = current;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if(active)
+	{
+		lock_mosix();
+		*active = 0;
+		unlock_mosix();
+	}
+	add_wait_queue(&wait_for_mosix_config, &wait);
+	while(1)
+	{
+		if(p->sigpending)
+			flush_signals(p);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if(PE)
+			break;
+		schedule();
+	}
+	remove_wait_queue(&wait_for_mosix_config, &wait);
+	set_current_state(TASK_RUNNING);
+	if(signal_pending(p))
+	{
+		spin_lock_irq(&p->sigmask_lock);
+		flush_signals(p);
+		spin_unlock_irq(&p->sigmask_lock);
+	}
+	if(active)
+	{
+		lock_mosix();
+		*active = 1;
+		unlock_mosix();
+	}
+}
+
+int
+mosix_config_get_table(struct mosixnet **mos, int start, int count)
+{
+	int copy;
+
+	if (count > MAX_MOSNET_ENTS)
+		count = MAX_MOSNET_ENTS;
+	if(!count)
+		count = nmosnet - start;
+	if(!PE || count < 0)
+		return(-ENXIO);
+	if(count == 0)
+		return(0);
+	*mos = (struct mosixnet *)
+		kmalloc(sizeof(struct mosixnet) * count, GFP_USER);
+	if(!*mos)
+		return(-ENOMEM);
+	lock_mosix();
+	if(!PE || !nmosnet || nmosnet < start)
+	{
+		unlock_mosix();
+		kfree(*mos);
+		return(-ENXIO);
+	}
+	if(nmosnet == start)
+	{
+		unlock_mosix();
+		kfree(*mos);
+		return(0);
+	}
+
+	/* create a private copy */
+	copy = nmosnet - start;
+	if (copy > count)
+		copy = count;
+	memcpy(*mos, &mosnet[start], sizeof(struct mosixnet) * copy);
+	unlock_mosix();
+	return (copy);
+}
+
+int
+mosix_config_set_table(struct mosixnet *m, int nents, int newpe)
+{
+	register int i, j;
+	register struct mosixnet *t, *q;
+	char *mstat = NULL;
+	char foundme = 0;
+	int maxpe = 1;
+	int numpe = 0;
+	int error = 0;
+
+	if (!boot_cpu_data.hard_math)
+	{
+		printk("Sorry, openMosix requires a math-unit.\n");
+		return(-ENODEV);
+	}
+	if(!spin_trylock(&modifying))
+		return(-EBUSY);
+	error = -E2BIG;
+	if (nents > MAX_MOSNET_ENTS)
+		goto out;
+
+	/*
+	 * PE == 0: (1)	newpe == 0 || nents == 0  =>  return (0)
+	 * 	    (2)	newpe > 0 && nents != 0   =>  (regular)
+	 * PE != 0: (3) newpe == PE		  =>  (regular)
+	 *	    (4)	newpe == 0 || nents == 0  =>  (shutdown)
+	 *          (5) newpe > 0 (nmosnet == 1)  =>  change PE, (regular)
+	 */
+
+	if(!newpe || !nents)
+	{
+		if(m)
+			kfree(m);
+		error = PE ? config_shutdown() : 0;
+		goto out;
+	}
+
+	error = -EBUSY;
+	if(PE && newpe != PE &&
+		(nmosnet != 1 || m->cnt != 1 || m->base != newpe))
+		goto out;
+
+	if(newpe == PE && nents == nmosnet &&
+		!memcmp(m, mosnet, nmosnet * sizeof(struct mosixnet)))
+	{
+		/* no change */
+		error = 0;
+		kfree(m);
+		goto out;
+	}
+
+
+	/* convention: first entry must hold the network type (AF_xxx) */
+	error = -EINVAL;
+	if (m->saddr.sa_family != AF_INET)
+		goto out;
+	comm_type = m->saddr.sa_family;
+
+	/* consistency checks */
+
+	for (t = m, i = 0; i < nents; i++, t++) {
+		t->saddr.sa_family = comm_type;
+
+		if (t->cnt < 0 || t->base < 1 || t->base + t->cnt < 0 ||
+			t->base + t->cnt - 1 > MOSIX_MAX)
+			goto out;
+
+		if (t->cnt == 0)
+		{
+			for (q = m, j = 0 ; j < nents ; j++ , q++)
+			if (q->cnt > 0 && q->base <= t->base &&
+				q->base + q->cnt > t->base)
+				break;
+			if(j == nents)
+			{
+				error = -ESRCH;
+				goto out;
+			}
+		}
+		else
+		{
+			for (q = m, j = 0; j < i; j++, q++)
+			if (q->cnt && (
+			    (q->base < t->base && q->base + q->cnt > t->base) ||
+			    (q->base >= t->base && q->base < t->base + t->cnt)))
+			{
+				error = -EXDEV;
+				goto out;
+			}
+
+			if (t->base + t->cnt - 1 > maxpe)
+				maxpe = t->base + t->cnt - 1;
+
+			if (newpe >= t->base && newpe < t->base + t->cnt)
+				foundme = 1;
+
+			numpe += t->cnt;
+		}
+	}
+	switch (comm_type) {
+	case AF_INET:
+		error = ip_consistent(newpe, m, nents, numpe);
+		break;
+	default:
+		error = 0;
+	}
+	if (error)
+		goto out;
+	error = -ESRCH;
+	if (!foundme)
+		goto out;
+	error = -ENOMEM;
+	i = (maxpe + 7) >> 3;
+	if (!(mstat = (char *) kmalloc(i, GFP_KERNEL)))
+		goto out;
+	memset(mstat, 0, i);
+
+
+	if(PE && (error = config_reduce_to_common(m, nents)))
+	{
+		kfree(mstat);
+		goto out;
+	}
+
+	/* COMMIT POINT */
+
+	lock_mosix();
+	write_lock(&mosnetstat_lock);
+	if (PE) {
+		unsigned int i, j;
+		int n;
+
+		if(newpe == PE)
+		for (i = 0; i < nents; i++)
+		for (n = m[i].base - 1 , j = 0 ; j < m[i].cnt ; j++ , n++)
+			mstat[n >> 3] |= (mosnetstat[n >> 3] & (1 << (n & 7)));
+		kfree(mosnetstat);
+		kfree(mosnet);
+	}
+
+	mosnetstat = mstat;
+	NPE = numpe;
+	MAXPE = maxpe;
+	nmosnet = nents;
+	mosnet = m;
+	write_unlock(&mosnetstat_lock);
+
+	pe_ready = newpe;
+	if(newpe != PE)
+	{
+		i = PE;
+		PE = newpe;
+		mos_to_net(PE, (void *)&my_mosix_net_address);
+		unlock_mosix();
+		info_startup();
+		if (!i)
+		{
+			comm_startup();
+			register_reboot_notifier(&mosix_notifier);
+			wake_up(&wait_for_mosix_config);
+		}
+	}
+	else
+		unlock_mosix();
+#ifdef CONFIG_MOSIX_FS
+	mfs_change_pe();
+#endif /* CONFIG_MOSIX_FS */
+	printk(KERN_NOTICE "openMosix configuration %s: This is openMosix #%d "
+		"(of %d configured)\n", PE ? "changed" : "set", newpe, NPE);
+	switch (comm_type)
+	{
+		case AF_INET:
+			ip_showconf(newpe, mosnet, nmosnet);
+			break;
+	}
+	error = 0;
+
+	out:
+	spin_unlock(&modifying);
+	return(error);
+}
+
+/* nth_node: n starts at 0 and does not count the local node */
+int
+nth_node(int n)
+{
+	register unsigned int i;
+	struct mosixnet *t;
+	int wanted = n;
+	MOSIX_LOCKED;
+	for(t = mosnet , i = 0 ; i < nmosnet ; i++ , t++)
+	{
+		if(t->base <= PE && t->base + t->cnt > PE)
+		{
+			if(t->base + n < PE)
+				return(t->base + n);
+			n++;
+		}
+		if(t->cnt <= n)
+			n -= t->cnt;
+		else
+			return(t->base + n);
+	}
+	panic("nth_node: attempt to find node %d", wanted);
+}
+
+int
+mosix_config_get_pe(void)
+{
+	return (PE);
+}
+
+int
+mosix_config_get_tentative_pe(void)
+{
+	int ret;
+
+	lock_mosix();
+	ret = pe_ready;
+	unlock_mosix();
+	return(ret);
+}
+
+int
+mosix_config_get_limit(void)
+{
+	int ret;
+
+	lock_mosix();
+	ret = PE ? MAXPE : 0;
+	unlock_mosix();
+	return(ret);
+}
+
+int
+mosix_config_set_pe(int newpe)
+{
+	int error = 0;
+
+	if (newpe < 0 || newpe > MOSIX_MAX)
+		return (-EINVAL);
+	if(!spin_trylock(&modifying))
+		return(-EBUSY);
+
+
+	if (!PE) {
+		lock_mosix();
+		pe_ready = newpe;
+		unlock_mosix();
+		goto out;
+	}
+
+	if (newpe == PE)
+		goto out;
+	
+	error = -EBUSY;
+	if (newpe && (nmosnet > 1 || mosnet->cnt != 1))
+		goto out;
+
+	if (newpe)
+	{
+		struct mosixnet m = *mosnet;
+
+		spin_unlock(&modifying);
+		m.base = newpe;
+		m.cnt = 1;
+		error = mosix_config_set_table(&m, 1, newpe);
+	}
+	else
+	{
+		spin_unlock(&modifying);
+		error = mosix_config_set_table(NULL, 0, 0);
+	}
+	return(error);
+	out:
+	spin_unlock(&modifying);
+	return (error);
+}
+
+/*
+ * mos_to_net:  return 1 if mos# exists (possibly fill sockaddr)
+ */
+int
+mos_to_net(int mos, void *sa)
+{
+	unsigned int n;
+	int ret = 0;
+
+
+	lock_mosix();
+	for (n = 0; n < nmosnet; n++)
+	if (mos >= mosnet[n].base && mos < mosnet[n].base + mosnet[n].cnt)
+	{
+		if(sa)
+		switch (comm_type) {
+		case AF_INET:
+			ip_mos_to_net(mos, n, (struct sockaddr *)sa);
+			break;
+		case AF_INET6:
+			panic("mos_to_net: AF_INET6 unsupported");
+			/* NOT REACHED */
+		default:
+			panic("mos_to_net: unknown type");
+		}
+		ret = 1;
+	}
+	unlock_mosix();
+	return(ret);
+}
+
+int
+mymos_to_net(void *sa)
+{
+	int ret = 0;
+
+	lock_mosix();
+	if(PE)
+		*(struct sockaddr *)sa = my_mosix_net_address;
+	else
+		ret = -ENETDOWN;
+	unlock_mosix();
+	return(ret);
+}
+
+int
+count_mosix_nodes(void)
+{
+	int unsigned i;
+	int n = 0;
+
+	lock_mosix();
+	for(i = 0 ; i < nmosnet ; i++)
+		n += mosnet[i].cnt;
+	unlock_mosix();
+	return(n);
+}
+
+#ifdef CONFIG_MOSIX_FS
+int
+scan_mosix_nodes(int start, int *first, int *last)
+{
+	unsigned int i;
+	int max = MOSIX_MAX + 1;
+
+	lock_mosix();
+	for(i = 0 ; i < nmosnet ; i++)
+	if(mosnet[i].cnt && mosnet[i].base < max &&
+		mosnet[i].base + mosnet[i].cnt > start)
+	{
+		*last = mosnet[i].base + mosnet[i].cnt - 1;
+		if(mosnet[i].base <= start)
+		{
+			*first = start;
+			max = 0;	/* eg. return(1) */
+			break;
+		}
+		*first = mosnet[i].base;
+		max = mosnet[i].base;
+	}
+	unlock_mosix();
+	return(max != MOSIX_MAX+1);
+}
+#endif /* CONFIG_MOSIX_FS */
+
+int
+mos_to_ascii(int mos, char *str, int len)
+{
+	struct sockaddr sa;
+
+	if (!mos_to_net(mos, &sa))
+		return (-EDIST);
+	switch (comm_type) {
+	case AF_INET:
+		return (ip_addr_to_ascii(&sa, str, len));
+	case AF_INET6:
+		panic("mos_to_ascii: AF_INET6 unsupported");
+	default:
+		panic("mos_to_ascii: unknown type");
+	}
+}
+
+
+int
+net_to_mos(mosix_addr *sa)
+{
+	switch (comm_type) {
+	case AF_INET:
+		return (ip_to_mosix(&sa->saddr));
+		/* NOT REACHED */
+	case AF_INET6:
+		panic("net_to_mos: AF_INET6 unsupported");
+		/* NOT REACHED */
+	default:
+		return(0);
+	}
+}
+
+int
+config_validate(void)
+{
+	register struct task_struct *p;
+	DECLARE_WAITQUEUE(wait, current);
+	int err = 0;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if((p->mm || (p->mosix.dflags & (DDEPUTY|DREMOTE))) &&
+		!(p->mosix.dflags & DFINISHED))
+	{
+		tell_process(p, DREQ_CHECKCONF);
+		wake_up_mosix(p);
+	}
+	read_unlock(&tasklist_lock);
+	add_wait_queue(&wait_for_all_to_adjust, &wait);
+	while(1)
+	{
+		set_current_state(TASK_INTERRUPTIBLE);
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if(process_told(p, DREQ_CHECKCONF))
+			break;
+		read_unlock(&tasklist_lock);
+		if(p == &init_task)
+			break;
+		schedule();
+		if (signal_pending(current))
+		{
+			err = -ERESTARTSYS;
+			break;
+		}
+	}
+	remove_wait_queue(&wait_for_all_to_adjust, &wait);
+	set_current_state(TASK_RUNNING);
+	return(err);
+}
+
+static int
+config_reduce_to_common(struct mosixnet *nm, int nmn)
+{
+	struct mosixnet *mt, *svmton;
+	int svnmton, svnumpe, svmaxpe;
+	int error;
+	int newmaxpe=0;
+	int newnumpe=0;
+	int i;
+	
+	switch (comm_type) {
+	case AF_INET:
+		mt = ip_reduce_to_common(nm, &nmn);
+		break;
+	case AF_INET6:
+		panic("config_reduce_to_common: AF_INET6 unsupported");
+		/* NOT REACHED */
+	default:
+		panic("config_reduce_to_common: unknown type");
+	}
+
+	if (!mt)
+		return (-ENOMEM);
+
+	for(svmton = mt, i = 0; i < nmn; i++, svmton++)
+	{
+		newnumpe += svmton->cnt;
+		if (svmton->base + svmton->cnt - 1 > newmaxpe)
+			newmaxpe = svmton->base + svmton->cnt - 1;
+	}
+	svmton = mosnet;
+	svnmton = nmosnet;
+	svnumpe = NPE;
+	svmaxpe = MAXPE;
+	lock_mosix();
+	mosnet = mt;
+	nmosnet = nmn;
+	NPE = newnumpe;
+	MAXPE = newmaxpe;
+	unlock_mosix();
+
+
+	info_reconfig();
+
+	if ((error = config_validate())) {
+		lock_mosix();
+		mosnet = svmton;
+		nmosnet = svnmton;
+		NPE = svnumpe;
+		MAXPE = svmaxpe;
+		unlock_mosix();
+		kfree(mt);
+		return (error);
+	}
+
+
+	kfree(svmton);
+	return(0);
+}
+
+int
+i_am_in_a_wrong_place(void)
+{
+	register struct task_struct *p = current;
+
+	if(p->mosix.dflags & (DPASSING|DINCOMING))
+		return(0);	/* not time to hit yet */
+	switch(p->mosix.dflags & (DDEPUTY|DREMOTE))
+	{
+	case DREMOTE:
+		if (mos_to_net(p->mosix.deppe, 0) == 0)
+		{
+			return(1);
+		}
+		break;
+	case DDEPUTY:
+		if (mos_to_net(p->mosix.whereami, 0) == 0)
+		{
+			return(1);
+		}
+	}
+	done_checking_conf();
+	return(0);
+}
+
+void
+done_checking_conf(void)
+{
+	register struct task_struct *p;
+
+	read_lock(&tasklist_lock);
+	process_ack(current, DREQ_CHECKCONF);
+	for_each_task(p)
+		if(process_told(p, DREQ_CHECKCONF))
+			break;
+	read_unlock(&tasklist_lock);
+	if(p == &init_task)	/* we were last to check */
+		wake_up(&wait_for_all_to_adjust);
+}
+
+
+
+/*
+ * Network dependent part of config:
+ * current implementation support only IP (not including v6).
+ */
+
+#define NET_TO_IP(sa)	(((struct sockaddr_in *) &(sa))->sin_addr.s_addr)
+#define NET_TO_IP_H(sa)	(ntohl(NET_TO_IP(sa)))
+
+static void
+ip_mos_to_net(int mos, int n, struct sockaddr *sa)
+{
+	*sa = mosnet[n].saddr;
+	NET_TO_IP(*sa) = htonl(NET_TO_IP_H(*sa) + mos - mosnet[n].base);
+}
+
+
+static int
+ip_to_mosix(struct sockaddr *sa)
+{
+	int i, ip, mip, c, ret = 0;
+
+	ip = NET_TO_IP_H(*sa);
+
+	lock_mosix();
+	for (i = 0 ; i < nmosnet ; i++)
+	{
+		mip = NET_TO_IP_H(mosnet[i].saddr);
+		c = mosnet[i].cnt ? : 1;
+		if(ip >= mip && ip < mip + c)
+		{
+			ret = mosnet[i].base + ip - mip;
+			break;
+		}
+	}
+	unlock_mosix();
+	return(ret);
+}
+
+static struct mosixnet *
+ip_reduce_to_common(struct mosixnet *nm, int *nmn)
+{
+	struct mosixnet *mt;
+	register int i, j, n = 0;
+	int b1, e1, b2, e2;
+
+	/* 2*MAX_MOSNET_ENTS should cover the worst-case intersection */
+
+	mt = kmalloc(2 * MAX_MOSNET_ENTS * sizeof(struct mosixnet), GFP_KERNEL);
+	if (!mt)
+		return (0);
+	for (i = 0; i < *nmn; i++)
+	for (j = 0; j < nmosnet; j++)
+	if (NET_TO_IP_H(mosnet[j].saddr) - mosnet[j].base ==
+					NET_TO_IP_H(nm[i].saddr) - nm[i].base)
+	{
+		if ((nm[i].cnt != 0) != (mosnet[j].cnt != 0))
+			continue;
+		b1 = nm[i].base;
+		e1 = nm[i].base + nm[i].cnt - 1;
+		b2 = mosnet[j].base;
+		e2 = mosnet[j].base + mosnet[j].cnt - 1;
+
+		if (b2 > b1)
+			b1 = b2;
+		if (e2 < e1)
+			e1 = e2;
+		if (e1 >= b1) {
+			mt[n].base = b1;
+			mt[n].cnt = e1 - b1 + 1;
+			mt[n].saddr.sa_family = AF_INET;
+			NET_TO_IP(mt[n].saddr) = htonl(NET_TO_IP_H(nm[i].saddr)
+							+ b1 - nm[i].base);
+			n++;
+		}
+	}
+	*nmn = n;
+	return (mt);
+}
+
+static int
+ip_consistent(int pe, struct mosixnet *m, int nents, int numpe)
+{
+	unsigned int i, j;
+	struct mosixnet *t, *q;
+
+	for (t = m, i = 0; i < nents; i++, t++)
+	if (t->cnt == 0)		/* an ALIAS address */
+	for (q = m , j = 0 ; j < i ; j++ , q++)
+	{
+		/* check if this IP appears more than once */
+		if (q->cnt == 0 &&
+			NET_TO_IP_H(q->saddr) == NET_TO_IP_H(t->saddr))
+		{
+			if (q->base != t->base)
+				return (-EXDEV);
+		}
+		else if (q->cnt != 0 &&
+			NET_TO_IP_H(q->saddr) <= NET_TO_IP_H(t->saddr) &&
+			NET_TO_IP_H(q->saddr) + q->cnt > NET_TO_IP_H(t->saddr)
+			&& q->base + NET_TO_IP_H(t->saddr) -
+				NET_TO_IP_H(q->saddr) != t->base)
+				return (-EXDEV);
+	}
+	else				/* a normal range */
+	{
+		if (NET_TO_IP_H(t->saddr) + t->cnt <= NET_TO_IP_H(t->saddr))
+			return (-EINVAL);
+
+		for (q = m , j = 0 ; j < i ; j++ , q++)
+		if (q->cnt == 0 &&
+		    NET_TO_IP_H(t->saddr) <= NET_TO_IP_H(q->saddr) &&
+		    NET_TO_IP_H(t->saddr)+t->cnt > NET_TO_IP_H(q->saddr)
+		    && t->base + NET_TO_IP_H(q->saddr) - NET_TO_IP_H(t->saddr)
+		       != q->base)
+			return (-EXDEV);
+		else if (q->cnt != 0 && (
+		    (NET_TO_IP_H(q->saddr) < NET_TO_IP_H(t->saddr) &&
+		     NET_TO_IP_H(q->saddr) + q->cnt > NET_TO_IP_H(t->saddr)) ||
+		    (NET_TO_IP_H(q->saddr) >= NET_TO_IP_H(t->saddr) &&
+		     NET_TO_IP_H(q->saddr) < NET_TO_IP_H(t->saddr) + t->cnt)))
+			return (-EXDEV);
+	}
+
+	if (PE && numpe > 1)
+	/* allow change of address only if PE remains alone */
+	for (t = m, i = 0; i < nents; i++, t++)
+	{
+		struct sockaddr sa;
+
+		if (t->cnt != 0 && pe >= t->base && pe < t->base + t->cnt &&
+			(!mos_to_net(pe, &sa) || NET_TO_IP_H(sa) !=
+				NET_TO_IP_H(t->saddr) + (pe - t->base)))
+				return (-EBUSY);
+	}
+
+	return (0);
+}
+
+
+static int
+ip_addr_to_ascii(struct sockaddr *sa, char *buf, int len)
+{
+	int a, b, c, d;
+	char tmp[20];	/* should be enough for ALL inet addresses */
+	unsigned long ipaddr;
+	
+	ipaddr = htonl(((struct sockaddr_in *) sa)->sin_addr.s_addr);
+
+	a = (ipaddr & 0xff000000) >> 24;
+	b = (ipaddr & 0x00ff0000) >> 16;
+	c = (ipaddr & 0x0000ff00) >> 8;
+	d = (ipaddr & 0x000000ff);
+
+	sprintf(tmp, "%d.%d.%d.%d", a, b, c, d);
+	strncpy(buf, tmp, len - 1);
+	buf[len - 1] = '\0';
+	return (strlen(tmp));
+}
+
+
+static void
+ip_showconf(int pe, struct mosixnet *m, int nents)
+{
+	unsigned int i;
+	int a, b, c, d;
+	long ipaddr;
+
+	for(i = 0 ; i < nents ; i++, m++)
+	{
+		ipaddr = ntohl(NET_TO_IP(m->saddr));
+		a = (ipaddr & 0xff000000) >> 24;
+		b = (ipaddr & 0x00ff0000) >> 16;
+		c = (ipaddr & 0x0000ff00) >> 8;
+		d = ipaddr & 0xff;
+		if (m->cnt == 0)
+			printk(KERN_NOTICE "openMosix #%d is aliased to IP address "
+					"%d.%d.%d.%d\n", m->base, a, b, c, d);
+		else if (m->cnt == 1)
+			printk(KERN_NOTICE "openMosix #%d is at IP address "
+					"%d.%d.%d.%d\n", m->base, a, b, c, d);
+		else
+			printk(KERN_NOTICE "openMosix range: %d-%d begins at "
+					"%d.%d.%d.%d\n", m->base,
+					m->base + m->cnt - 1, a, b, c, d);
+	}
+}
+
diff -Naur --exclude=CVS --exclude=configs linux/hpc/copy_unconf linux-openmosix/hpc/copy_unconf
--- linux/hpc/copy_unconf	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/copy_unconf	2002-06-24 09:17:47.000000000 +0200
@@ -0,0 +1,14 @@
+#!/bin/sh -
+echo "/* alternate.c: automatically generated with copy of unconfigured routines */"
+echo
+if [ "$1" != y ]
+then
+	awk ' \
+		/^#include/ {print $0; next; } \
+		/^aout_remote_init_mm\(/ { on=1 ; print "\nvoid" ; } \
+		/^unsigned long .*create_aout_tables\(/ { on=1 ; print "\n#ifdef CONFIG_MOSIX"; } \
+		/^static void set_brk/ { on=1; print ""; }
+		/^}/ { if(on) print "}" ; on=0; next; } \
+		on == 1  { print $0; }
+		' < $2
+fi
diff -Naur --exclude=CVS --exclude=configs linux/hpc/decay.c linux-openmosix/hpc/decay.c
--- linux/hpc/decay.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/decay.c	2002-07-10 15:20:15.000000000 +0200
@@ -0,0 +1,243 @@
+/* All changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/hpc.h>
+#include <linux/hpcctl.h>
+#include <linux/smp_lock.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <hpc/balance.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+
+int slow_alpha = DEFAULT_SLOW_ALPHA;
+int fast_alpha = DEFAULT_FAST_ALPHA;
+int decay_interval = DEFAULT_DECAY_INTERVAL;
+
+void
+mosix_decay_exec(void)
+{
+	register typeof (current->mosix.dpolicy) *p = &current->mosix.dpolicy;
+
+	if(!(*p & (DADV_EXEC|DADV_EXECONCE)))
+		*p = (*p & ~DADV_POLICY) | DADV_DEFAULT;
+	*p &= ~DADV_EXECONCE;
+}
+
+int
+decay_modify_bit(int on, int bit)
+{
+	if(on == -1)
+		return((current->mosix.dpolicy & bit) != 0);
+	if((on != 0) == ((current->mosix.dpolicy & bit) != 0))
+		return(0);
+	if(on)
+		current->mosix.dpolicy |= bit;
+	else
+		current->mosix.dpolicy &= ~bit;
+	if(current->mosix.dflags & DDEPUTY)
+		deputy_update_remote_decay();
+	return(0);
+}
+
+int
+decay_inherit(int on)
+{
+	return(decay_modify_bit(on, DADV_INHERIT));
+}
+
+int
+decay_exec(int on)
+{
+	return(decay_modify_bit(on, DADV_EXEC));
+}
+
+int
+decay_execonce(int on)
+{
+	return(decay_modify_bit(on, DADV_EXECONCE));
+}
+
+int
+decay_set(int policy, int quotient, int seconds)
+{
+	register struct task_struct *p = current;
+	int prev;
+
+	if(policy == (p->mosix.dpolicy & DADV_POLICY) &&
+		(policy != DADV_OWNDECAY || (quotient == p->mosix.decay &&
+			seconds == p->mosix.deccycle)))
+		return(0);
+	if(seconds < 1 || seconds > 65535 ||
+		quotient < 0 || quotient > DECAY_QUOTIENT)
+		return(-EINVAL);
+	if(policy == DADV_CPU || policy == DADV_NOCPU ||
+		(prev = (p->mosix.dpolicy & DADV_POLICY)) == DADV_CPU ||
+			prev == DADV_NOCPU)
+			mosix_clear_statistics();
+	p->mosix.dpolicy = (p->mosix.dpolicy & ~DADV_POLICY) | policy;
+	p->mosix.decay = quotient;
+	p->mosix.deccycle = seconds;
+	if(p->mosix.dflags & DDEPUTY)
+		deputy_update_remote_decay();
+	return(0);
+}
+
+int
+decay_get(int policy)
+{
+	return((current->mosix.dpolicy & DADV_POLICY) == policy);
+}
+
+void
+decay_clear(void)
+{
+	struct decay_h d;
+
+	d.policy = DADV_CLEAR;
+	if(current->mosix.dflags & DDEPUTY)
+		deputy_request(DEP_UPDATE_DECAY, &d, sizeof(d), NULL, 0, 0, NULL, 0);
+	else
+		mosix_clear_statistics();
+}
+
+void
+deputy_update_remote_decay(void)
+{
+	struct decay_h d;
+	struct mosix_task *m = &current->mosix;
+
+	d.policy = m->dpolicy;
+	d.deccycle = m->deccycle;
+	d.decay = m->decay;
+	deputy_request(DEP_UPDATE_DECAY, &d, sizeof(d), NULL, 0, 0, NULL, 0);
+}
+
+int
+remote_setdecay(struct decay_h *d)
+{
+	int prev, new;
+	struct mosix_task *m = &current->mosix;
+
+	if(d->policy == DADV_CLEAR)
+		mosix_clear_statistics();
+	else
+	{
+		prev = m->dpolicy & DADV_POLICY;
+		new = d->policy & DADV_POLICY;
+		if(prev == DADV_CPU || prev == DADV_NOCPU
+			|| new == DADV_CPU || new == DADV_NOCPU)
+			mosix_clear_statistics();
+		m->dpolicy = d->policy;
+		m->deccycle = d->deccycle;
+		m->decay = d->decay;
+	}
+	comm_free(d);
+	return(comm_send(DEP_UPDATE_DECAY|REPLY, NULL, 0, NULL, 0, 0));
+}
+ 
+void
+inc_decays(void)
+{
+	struct task_struct *p;
+	register struct mosix_task *m;
+	register unsigned char policy;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	{
+		m = &p->mosix;
+		if(!(m->dflags & DDEPUTY) &&
+			((policy = m->dpolicy & DADV_POLICY) == DADV_SLOWDECAY
+				|| policy == DADV_FASTDECAY ||
+				policy == DADV_OWNDECAY) &&
+			m->decsecs != 0xffff)
+			m->decsecs++;
+	}
+	read_unlock(&tasklist_lock);
+}
+
+void
+do_decay(void)
+{
+	register struct mosix_task *m = &current->mosix;
+	int d;
+	int64_t ms;
+#ifdef CONFIG_MOSIX_FS
+	int i;
+#endif /* CONFIG_MOSIX_FS */
+	/* an expensive 64-bit-division saving macro: */
+#define	proportionate(fld) if(m->fld > (0xffffffffUL/DECAY_QUOTIENT)) \
+	m->fld = m->fld * d / DECAY_QUOTIENT; \
+	else m->fld = ((unsigned long)m->fld) * d / DECAY_QUOTIENT
+
+	switch(m->dpolicy & DADV_POLICY)
+	{
+	case DADV_SLOWDECAY:
+		if(m->decsecs < decay_interval)
+			return;
+		d = slow_alpha;
+		break;
+	case DADV_FASTDECAY:
+		if(m->decsecs < decay_interval)
+			return;
+		d = fast_alpha;
+		break;
+	case DADV_OWNDECAY:
+		if(m->decsecs < m->deccycle)
+			return;
+		d = m->decay;
+		break;
+	default:
+		return;
+	}
+	read_lock(&tasklist_lock);
+	m->decsecs = 0;
+	read_unlock(&tasklist_lock);
+	lock_mosix();
+	proportionate(cutime);
+	proportionate(ndemandpages);
+	proportionate(nsyscalls);
+	proportionate(ncopyins);
+	proportionate(copyinbytes);
+	proportionate(ncopyouts);
+	proportionate(copyoutbytes);
+	proportionate(pagetime);
+#ifdef CONFIG_MOSIX_FS
+	if(m->mfs_stats)
+	for(i = m->mfs_stats->nnodes-1 ; i >= 0 ; i--)
+	{
+		proportionate(mfs_stats->conns[i]);
+		proportionate(mfs_stats->inbytes[i]);
+		proportionate(mfs_stats->outbytes[i]);
+		if(m->mfs_stats->conns[i] == 0)
+		{
+			int last = --m->mfs_stats->nnodes;
+
+			if(i == last)
+				continue;
+			m->mfs_stats->nodes[i] = m->mfs_stats->nodes[last];
+			m->mfs_stats->conns[i] = m->mfs_stats->conns[last];
+			m->mfs_stats->inbytes[i] = m->mfs_stats->inbytes[last];
+			m->mfs_stats->outbytes[i] = m->mfs_stats->outbytes[last];
+			if(m->mfs_stats->hint == last)
+				m->mfs_stats->hint = i;
+		}
+	}
+#endif /* CONFIG_MOSIX_FS */
+
+	ms = ticks_to_ms(current->times.tms_utime + m->uttime) - m->dctime;
+	if(ms > 0)
+		m->dctime += ms * (DECAY_QUOTIENT - d) / DECAY_QUOTIENT;
+	unlock_mosix();
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/deputy.c linux-openmosix/hpc/deputy.c
--- linux/hpc/deputy.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/deputy.c	2004-02-05 02:48:27.000000000 +0100
@@ -0,0 +1,1451 @@
+/* Changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh
+ */
+
+
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <linux/hpc.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <asm/unistd.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/in6.h>
+#include <asm/checksum.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <linux/smp_lock.h>
+#include <linux/highmem.h>
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
+static inline int
+HAS_ASYNC(struct task_struct *p)
+{
+	process_ack(p, DREQ_CHECKSTAY);
+	return(p->mosix.prequest || p->mosix.whereto ||
+		process_told(p, (DREQ_CAPCNG|DREQ_DFSASYNC|DREQ_NICECNG|
+				DREQ_INFOCNG|DREQ_UPDOVERHEADS|DREQ_URGENT)) ||
+	(p->mosix.stay & DSTAY) ||
+	(process_told(p, DREQ_CHECKCONF) && i_am_in_a_wrong_place())
+	);
+}
+
+void
+mosix_inform_remote_of_info(void)
+{
+	struct disclosure_h d;
+	struct task_struct *p = current;
+
+	d.disclosure = p->mosix.disclosure;
+	d.uid = p->uid;
+	d.gid = p->gid;
+	d.pgrp = p->pgrp;
+	d.session = p->session;
+	d.tgid = p->tgid;
+	memcpy(d.comm, p->comm, sizeof(d.comm));
+	if(deputy_request(DEP_INFO, &d, sizeof(d), NULL, 0, 0, NULL, 0))
+		deputy_die_on_communication();
+}
+
+void
+deputy_async_requests(void)
+{
+	register struct task_struct *p = current;
+	register struct mosix_task *m = &p->mosix;
+	int w;
+
+	check_again:
+	process_ack(p, DREQ_CHECKSTAY);
+	while(m->prequest)
+		process_requests();
+	if(process_told(p, DREQ_URGENT))
+	{
+		process_ack(p, DREQ_URGENT);
+		comm_take_urgent();
+		if(deputy_request(DEP_TAKEURGENT, NULL, 0, NULL, 0, 0,
+			(void **)&w, -sizeof(w)))
+			goto check_again;
+		if(w)
+			mosix_add_to_whereto(p, w);
+	}
+	if(m->whereto)
+	{
+		follow_whereto();
+		if(!(m->dflags & DDEPUTY))
+			return;
+		goto check_again;
+	}
+	if(process_told(p, DREQ_CAPCNG))
+		sync_caps();
+#ifdef CONFIG_MOSIX_DFSA
+	if(process_told(p, DREQ_DFSASYNC))
+		deputy_resync_dfsa();
+#endif /* CONFIG_MOSIX_DFSA */
+	if(process_told(p, DREQ_NICECNG))
+	{
+		process_ack(p, DREQ_NICECNG);
+		mosix_inform_remote_of_nice();
+		goto check_again;
+	}
+	if(process_told(p, DREQ_INFOCNG))
+	{
+		process_ack(p, DREQ_INFOCNG);
+		mosix_inform_remote_of_info();
+		goto check_again;
+	}
+	if(process_told(p, DREQ_UPDOVERHEADS))
+	{
+		process_ack(p, DREQ_UPDOVERHEADS);
+		deputy_inform_remote_of_overheads();
+		goto check_again;
+	}
+	if((m->stay & DSTAY) ||
+		((process_told(p, DREQ_CHECKCONF)) && i_am_in_a_wrong_place()))
+	{
+		if(!mosix_go_home(1))
+		{
+			printk("Process %s, uid=%d, killed because it failed to migrate back \n",
+				desc_mostask(m), p->uid);
+			printk("(possible reasons are fill-up of swap-space, or network disconnection)\n");
+			send_sig(SIGKILL, p, 1);
+		}
+		done_checking_conf();
+		return;
+	}
+}
+
+static inline void
+deputy_communication_failed_msg(void)
+{
+	printk("Process %s, uid=%d, killed because it lost communication\n"
+		"with the remote node where it was running\n",
+		desc_mostask(NULL), current->uid);
+}
+
+void
+deputy_communication_failed(void)
+{
+	deputy_communication_failed_msg();
+	force_sig(SIGKILL, current);
+}
+
+NORET_TYPE void
+deputy_die_on_communication(void)
+{
+	deputy_communication_failed_msg();
+	do_exit(SIGKILL);
+}
+
+extern asmlinkage int FASTCALL(do_signal(struct pt_regs *, sigset_t *));
+
+void
+deputy_main_loop()
+{
+	register struct task_struct *p = current;
+	extern asmlinkage void do_syscall_trace(void);
+	void *head;
+	int hlen, type = 0;	/* compiler bug requires the =0 */
+	int delay_sigs = (p->mosix.dflags & (DTRACESYS1|DTRACESYS2)) != 0;
+	int has;
+
+	p->mosix.dflags &= ~(DTRACESYS1|DTRACESYS2);
+	while(p->mosix.dflags & DDEPUTY)
+	if(p->mosix.dflags & DSYNC)
+	{
+		if(HAS_ASYNC(p))
+			deputy_async_requests();
+		else if(!delay_sigs && signal_pending(p))
+			do_signal(mos_to_regs(&p->mosix), 0);
+		else
+		{
+			p->mosix.pass_regs = ALL_REGISTERS;
+			comm_send(DEP_USERMODE|USERMODE, NULL, 0, NULL, 0, 0);
+			p->mosix.dflags &= ~DSYNC;
+		}
+	}
+	else
+	{
+		has = comm_wait();
+		if(p->mosix.dflags & DFAKESIGNAL)
+		{
+			p->mosix.dflags &= ~DFAKESIGNAL;
+			evaluate_pending_signals_in_mosix_context();
+		}
+		if(!has)
+		{
+			if(!HAS_ASYNC(p))
+			{
+				if(!signal_pending(p))
+				{
+					/* so why did we wake?
+					 * the only good reason would
+					 * be a DREQ_CHECKCONF while
+					 * we are NOT in a wrong place */
+					continue;
+				}
+				if(delay_sigs)
+				{
+					spin_lock_irq(&p->sigmask_lock);
+					p->sigpending = 0;
+					spin_unlock_irq(&p->sigmask_lock);
+					continue;	/* back to sleep */
+				}
+			}
+			p->mosix.dflags |= DSYNC;
+			if(comm_send(DEP_SYNC, NULL, 0, NULL, 0, 0))
+				deputy_die_on_communication();
+		}
+		p->mosix.dflags |= DSYNC;
+		if(delay_sigs)
+			evaluate_pending_signals_in_mosix_context();
+		if((type = comm_recv(&head, &hlen)) < 0)
+			deputy_die_on_communication();
+		if(type & ANYTIME)
+		{
+			if(deputy_handle_interim_request(type, head, hlen))
+				deputy_die_on_communication();
+		}
+		else switch(type)
+		{
+		case REM_NULLMSG:
+			comm_free(head);
+			continue;
+		case REM_ASIG:
+			deputy_analyse_remote_signals((struct asig_h *)head);
+			continue;
+		case REM_SYSCALL_TRACE:
+			delay_sigs ^= 1;
+			deputy_add_rusage((struct rusage *)head);
+			comm_free(head);
+			do_syscall_trace();
+			if(!(p->mosix.dflags & DDEPUTY))
+				break;
+			if(deputy_reply(REM_SYSCALL_TRACE, NULL, 0, NULL, 0, 0,
+				delay_sigs))
+				deputy_die_on_communication();
+			continue;
+		case REM_SYSCALL:
+			deputy_syscall(head, delay_sigs);
+			p = current;	/* for "fork" son */
+			continue;
+		case REM_BRING_ME_HOME:
+		case REM_MUST_COME_HOME:
+			mosix_go_home(type == REM_MUST_COME_HOME ? 2 : 1);
+			if((p->mosix.dflags & DDEPUTY) &&
+				comm_send(type|REPLY, NULL, 0, NULL, 0, 0))
+				deputy_die_on_communication();
+			continue;
+		default:
+			printk("Process %s, uid=%d, killed because it received"
+				" an unrecognized\n" "message type (0x%x) from"
+				" the remote site where it was running\n",
+				desc_mostask(NULL), current->uid, type);
+			do_exit(SIGKILL);
+		}
+	}
+}
+
+int
+deputy_reply(int type, void *hd, int hlen, void *dat, int dlen, int um, int delay_sigs)
+{
+	register struct task_struct *p = current;
+	int err;
+
+	type |= REPLY;
+	if(!(p->mosix.dflags & DNESTED) && (delay_sigs == 2 ||
+		(!HAS_ASYNC(p) && (delay_sigs || !signal_pending(p)))))
+	{
+		p->mosix.pass_regs = ALL_REGISTERS;
+		type |= USERMODE;
+	}
+	err = comm_send(type, hd, hlen, dat, dlen, um);
+	if(type & USERMODE)
+		p->mosix.dflags &= ~DSYNC;
+	return(err);
+}
+
+void
+mosix_inform_remote_of_nice(void)
+{
+	if(deputy_request(DEP_NICE, &current->nice, sizeof(current->nice),
+							NULL, 0, 0, NULL, 0))
+		deputy_die_on_communication();
+}
+
+void
+deputy_inform_remote_of_overheads(void)
+{
+	if(deputy_request(DEP_OPCOSTS, (caddr_t)deputy_here,
+		sizeof(deputy_here), NULL, 0, 0, NULL, 0))
+		deputy_die_on_communication();
+}
+
+void
+mosix_deputy_rusage(int final)
+{
+	struct rusage *r;
+
+	if(deputy_request(DEP_RUSAGE, &final, sizeof(final), NULL, 0, 0,
+						(void **)&r, sizeof(*r)))
+	{
+		if(!(current->mosix.dflags & DFINISHED))
+			deputy_communication_failed();
+		return;
+	}
+	deputy_add_rusage(r);
+	if(final)
+		current->mosix.exit_mem = r->ru_maxrss;
+	comm_free(r);
+}
+
+int
+mosix_deputy_restore_sigcontext(struct sigcontext *frame, int *eax)
+{
+	struct restore_sigcontext_ret_h r;
+
+	current->mosix.pass_regs = ALL_REGISTERS;
+	if(deputy_request(DEP_RESTORESIGCONTEXT, &frame, sizeof(frame), NULL,
+		0, 0, (void **)&r, -sizeof(r)))
+		r.result = 1;
+	*eax = r.eax;
+	return(r.result);
+}
+
+void
+mosix_deputy_setup_frame(unsigned long sig, struct k_sigaction *ka,
+	siginfo_t info, sigset_t *oldset)
+{
+	struct setupframe_parameters_h s;
+
+	s.sig = sig;
+	s.flags = ka->sa.sa_flags;
+	s.handler = ka->sa.sa_handler;
+	s.restorer = ka->sa.sa_restorer;
+	s.set = *oldset;
+	s.ss_sp = current->sas_ss_sp;
+	s.ss_size = current->sas_ss_size;
+	if(ka->sa.sa_flags & SA_SIGINFO)
+		s.info = info;
+	current->mosix.pass_regs = ALL_REGISTERS;
+	if(deputy_request(DEP_SETUPFRAME, &s, sizeof(s), NULL, 0, 0, NULL, 0))
+		deputy_die_on_communication();
+}
+
+int
+deputy_handle_interim_request(int type, void *head, int hlen)
+{
+	switch(type)
+	{
+	case REM_NOTHING:
+		comm_free(head);
+		return(comm_send(REM_NOTHING|REPLY, NULL, 0, NULL, 0, 0));
+	case REM_PAGE:
+		return(deputy_bring_page((struct bring_page_h *)head));
+	case REM_GETTSC:
+		return(deputy_tsc());
+	case REM_MORESTRINGS:
+		return(deputy_more_strings((struct execve_more_strings_h *)head));
+	case REM_BRING_ME_REGS:
+		return(deputy_bring_me_regs((unsigned long *)head));
+	case REM_GETALOAD:
+		return(send_local_aload(REM_GETALOAD|REPLY));
+	default:
+		printk("Process %s, uid=%d, received an unexpected "
+		       "urgent request\n" "(type 0x%x) from the "
+		       "remote site where it was running\n",
+		       desc_mostask(NULL), current->uid, type);
+		comm_free(head);
+		return(-EDIST);
+	}
+}
+
+int
+deputy_wait(int expect, void **head, int *hlen)
+{
+	int type, err;
+
+	while((type = comm_recv(head, hlen)) != expect)
+	if(type < 0)
+		return(type);
+	else if(type & ANYTIME)
+	{
+		if((err = deputy_handle_interim_request(type, *head, *hlen)))
+			return(err);
+	}
+	else
+	{
+		printk("DEPUTY: Unexpected non-urgent request type %x\n", type);
+		mosix_panic("deputy_wait");
+		comm_free(*head);
+		comm_flushdata(COMM_ALLDATA);
+	}
+	return(0);
+}
+
+int
+deputy_request(int type, void *header, int hlen, void *data, int dlen,
+	int uspace, void **result, int reslen)
+{
+	register struct task_struct *p = current;
+	int wasnested = (p->mosix.dflags & DNESTED);
+	int error;
+	void *head;
+	int rhlen;
+
+	p->mosix.dflags |= DNESTED;
+	if((error = comm_send(type, header, hlen, data, dlen, uspace)))
+		goto out;
+	if((error = deputy_wait(type|REPLY, &head, &rhlen)))
+		goto out;
+	if(reslen > 0)
+	{
+		if(rhlen > reslen)
+			goto lenerr;
+		if(result)
+			*result = head;
+	}
+	else
+	{
+		if(rhlen > -reslen && reslen)
+		{
+			comm_free(head);
+			lenerr:
+			printk("deputy_request type %x: %d instead of %d\n",
+				type, rhlen, reslen);
+			error = -EDIST;
+			goto out;
+		}
+		if(reslen)
+			memcpy(result, head, rhlen);
+		comm_free(head);
+	}
+	out:
+	if(!wasnested)
+		p->mosix.dflags &= ~DNESTED;
+	return(error);
+}
+
+unsigned long
+mosix_deputy_mmap(struct file *fp, unsigned long addr, int fixed,
+	unsigned long len, unsigned long flags, unsigned long off, off_t isize,
+	nopage_t nopage)
+{
+	struct mmap_parameters_h mp;
+	int error;
+	unsigned long result;
+
+	mp.addr = addr;
+	mp.fixed = fixed;
+	mp.len = len;
+	mp.flags = flags;
+	mp.pgoff = off;
+	mp.origin = PE;
+	if((mp.fp = fp))
+	{
+		mp.dp = fp->f_dentry;
+		mp.uniq = mp.fp->f_dentry->d_inode->i_unique;
+		mp.isize = mp.fp->f_dentry->d_inode->i_size;
+	}
+	mp.nopage = nopage;
+	if((error = deputy_request(DEP_MMAP, &mp, sizeof(mp), NULL, 0, 0,
+					(void **)&result, -sizeof(result))))
+		return(error);
+	return(result);
+}
+
+long
+mosix_deputy_brk(unsigned long addr, unsigned long len)
+{
+	struct brk_parameters_h b;
+	long error;
+	long result;
+
+	b.addr = addr;
+	b.len = len;
+	if((error = deputy_request(DEP_BRK, &b, sizeof(b), NULL, 0, 0,
+		(void **)&result, -sizeof(result))))
+		result = error;
+	return(result);
+}
+
+int
+deputy_munmap(unsigned long addr, size_t len)
+{
+	struct munmap_parameters_h mp;
+	int error;
+	int result;
+
+	mp.addr = addr;
+	mp.len = len;
+	if((error = deputy_request(DEP_MUNMAP, &mp, sizeof(mp), NULL, 0, 0,
+					(void **)&result, -sizeof(result))))
+		result = error;
+	return(result);
+}
+
+int
+deputy_mprotect(unsigned long addr, size_t len, unsigned long prot)
+{
+	struct mprotect_parameters_h mp;
+	int error;
+	int result;
+
+	mp.addr = addr;
+	mp.len = len;
+	mp.prot = prot;
+	if((error = deputy_request(DEP_MPROTECT, &mp, sizeof(mp), NULL, 0, 0,
+					(void **)&result, -sizeof(result))))
+		result = error;
+	return(result);
+}
+
+void
+deputy_analyse_remote_signals(struct asig_h *s)
+{
+	register int i;
+	siginfo_t info;
+	int back = 0;
+
+	while(s->nforced--)
+	{
+		if(comm_copydata(&info, sizeof(info), 0))
+			deputy_die_on_communication();
+		force_sig_info(info.si_signo, &info, current);
+	}
+	while(s->sigs)
+	{
+		switch(i = ffz(~s->sigs) + 1)
+		{
+		case FATAL_SIGSEGV:
+			force_sig(SIGSEGV, current);
+			break;
+		case REMOTE_FILE_RELEASED:
+			mosix_rebuild_file_list();
+			break;
+		case SIGSEGV:
+		case SIGKILL:
+		case SIGVTALRM:
+		case SIGPROF:
+		case SIGBUS:
+		case SIGIOT:
+		case SIGFPE:
+		case SIGILL:
+		case SIGXCPU:
+		case SIGXFSZ:
+		case SIGPWR:
+		case SIGTRAP:
+			send_sig(i, current, 1);
+			break;
+		case SIGTERM:
+			back = 1;
+			break;
+		default:
+			printk("%s - How did signal #%d arrive at REMOTE???\n",
+			       desc_mostask(NULL), i);
+		}
+		s->sigs &= ~(1 << (i-1));
+	}
+	if(current->mosix.dflags & DINCOMING)
+		return;
+	comm_free(s);
+	if(back)
+		mosix_go_home(2);
+}
+
+#define	MAX_COPY_FROM_USER	(PAGE_SIZE)
+
+unsigned long
+deputy_copy_from_user(void *to, void *from, unsigned long size, int verify)
+{
+	struct user_copy_h u;
+	int result, non_cache;
+
+	while(size > 0)
+	{
+		if((result = copy_from_cache(to, (unsigned long)from, size,
+								&non_cache)))
+		{
+			if(!(size -= result))
+				break;
+			((char *)from) += result;
+			((char *)to) += result;
+			if(!non_cache)
+				continue;
+		}
+		u.addr = from;
+		u.size = non_cache > MAX_COPY_FROM_USER ? MAX_COPY_FROM_USER : non_cache;
+		u.verify = verify;
+		if(deputy_request(DEP_COPY_FROM_USER, &u, sizeof(u), NULL, 0, 0,
+			(void **)&result, -sizeof(result)))
+			break;
+		if(result)
+		{
+			if(result < u.size &&
+				comm_copydata(to, u.size - result, 0))
+				result = u.size;
+			size += result - u.size;
+			break;
+		}
+		if(comm_copydata(to, u.size, 0))
+			break;
+		size -= u.size;
+		((char *)from) += u.size;
+		((char *)to) += u.size;
+	}
+	return(size);
+}
+
+#define	MAX_COPY_TO_USER	(2*PAGE_SIZE)
+
+unsigned long
+deputy_copy_to_user(void *to, void *from, unsigned long size, int verify)
+{
+	struct user_copy_h u;
+	int result;
+	int non_cache;
+
+	while(size > 0)
+	{
+		if((result = copy_to_cache((unsigned long)to, from, size,
+								&non_cache)))
+		{
+			if(!(size -= result))
+				break;
+			((char *)from) += result;
+			((char *)to) += result;
+			if(!non_cache)
+				continue;
+		}
+		u.addr = to;
+		u.size = non_cache > MAX_COPY_TO_USER ? MAX_COPY_TO_USER : non_cache;
+		u.verify = verify;
+		if(deputy_request(DEP_COPY_TO_USER, &u, sizeof(u),
+			from, u.size, 0, (void **)&result, -sizeof(result)))
+			break;
+		if(result)
+		{
+			size += result - u.size;
+			break;
+		}
+		size -= u.size;
+		((char *)from) += u.size;
+		((char *)to) += u.size;
+	}
+	return(size);
+}
+
+unsigned long
+deputy_clear_user(void *to, int size, int verify)
+{
+	struct user_copy_h u;
+	int result;
+	int non_cache;
+
+	while(size > 0)
+	{
+		if((result = zero_cache(to, size, &non_cache)))
+		{
+			if(!(size -= result))
+				break;
+			((char *)to) += u.size;
+			if(!non_cache)
+				continue;
+		}
+		u.addr = to;
+		u.size = non_cache;
+		u.verify = verify;
+		if(deputy_request(DEP_CLEAR_USER, &u, sizeof(u), NULL, 0, 0,
+			(void **)&result, -sizeof(result)))
+			break;
+		if(result < 0)
+		{
+			size = result;
+			break;
+		}
+		size -= non_cache;
+		if(result)
+		{
+			size += result;
+			break;
+		}
+	}
+	return(size);
+}
+
+long
+deputy_strncpy_from_user(char *to, char *from, int max, int verify)
+{
+	struct user_copy_h u;
+	int result;
+	int non_cache;
+	int read = 0;
+	char *oto = to;
+	int omax = max;
+
+	while(max > 0)
+	{
+		if((result = copy_from_cache(to, (unsigned long)from, -max,
+								&non_cache)))
+		{
+			if(non_cache == -1)
+				result--;
+			read += result;
+			if(!(max -= result))
+				break;
+			to += result;
+			from += result;
+			if(!non_cache)
+				continue;
+		}
+		if(non_cache == -1)	/* 0 encountered */
+			break;
+		u.addr = from;
+		u.size = non_cache;
+		u.verify = verify;
+		if(deputy_request(DEP_STRNCPY_FROM_USER, &u, sizeof(u), NULL, 0, 0,
+			(void **)&result, -sizeof(result)))
+		{
+			result = -EFAULT;
+			break;
+		}
+		if(result < 0)
+			break;
+		if(result && comm_copydata(to, result, 0))
+		{
+			result = -EFAULT;
+			break;
+		}
+		from += result;
+		to += result;
+		read += result;
+		max -= result;
+		if(result != non_cache)
+			break;
+	}
+	if(result >= 0)
+	{
+		result = read;
+		if(omax && read < omax)
+			oto[read] = '\0';
+	}
+	return(result);
+}
+
+long
+deputy_strnlen_user(char *from, long len)
+{
+	long result;
+	long read = 0;
+	int non_cache;
+	struct strnlen_user_h h;
+	int error = 0;
+
+	while(1)
+	{
+		result = strlen_cache(from, &non_cache);
+		read += result;
+		if(non_cache == -1)	/* 0 encountered */
+			break;
+		from += result;
+		if(read > len)
+			break;
+		if(!non_cache)
+			continue;
+		h.addr = from;
+		h.len = len - read;
+		if(deputy_request(DEP_STRNLEN_USER, (void *)&h, sizeof(h),
+			NULL, 0, 0, (void **)&result, -sizeof(result)) ||
+				result == 0)
+		{
+			error = 1;
+			break;
+		}
+		if(result > non_cache)
+			result = non_cache;
+		read += result;
+		if(read > len)
+			break;
+		from += result;
+	}
+	result = error ? 0 : (read > len ? len+1 : read);
+	return(result);
+}
+
+int
+deputy_verify_write(void *addr, unsigned long size)
+{
+	struct user_copy_h u;
+	int result;
+
+	u.addr = addr;
+	u.size = size;
+	if(all_in_cache((unsigned long)addr, size, 1))
+		result = 1;
+	else if(deputy_request(DEP_VERIFY_WRITE, &u, sizeof(u), NULL, 0, 0,
+		(void **)&result, -sizeof(result)))
+		result = 0;
+	return(result);
+}
+
+unsigned int
+deputy_csum_partial_copy_from_user(const char *src, char *dst, int len, int sum,
+							int *err_ptr)
+{
+	struct user_csum_copy_h u;
+	struct user_csum_copy_ret_h r;
+
+	/* must not play around with partial results, because unlike
+	 * "deputy_copy_from_user", we may not break the buffer
+	 * (at least not into non-4-byte-aligned segments, for now).
+	 */
+	if(any_in_cache((unsigned long)src, len))
+	{
+		if(deputy_copy_from_user(dst, (char *)src, len, 1))
+		{
+			*err_ptr |= 1;
+			return(sum);
+		}
+		return(csum_partial(dst, len, sum));
+	}
+	while(len > 0)
+	{
+		u.addr = (void *)src;
+		u.len = len > MAX_COPY_FROM_USER ? MAX_COPY_FROM_USER : len;
+		u.sum = sum;
+		if(deputy_request(DEP_CSUM_COPY_FROM_USER, &u, sizeof(u),
+			NULL, 0, 0, (void **)&r, -sizeof(r)))
+		{
+			*err_ptr |= 1;
+			return(0);
+		}
+		sum = r.newsum;
+		if(r.error || comm_copydata(dst, len, 0))
+		{
+			*err_ptr |= 1;
+			return(sum);
+		}
+		len -= u.len;
+		((char *)src) += u.len;
+		dst += u.len;
+	}
+	return(sum);
+}
+
+unsigned int
+deputy_csum_partial_copy_to_user(const char *src, char *dst, int len, int sum,
+							int *err_ptr)
+{
+	unsigned int newsum = csum_partial(src, len, sum);
+
+	if(deputy_copy_to_user(dst, (char *)src, len, 1))
+		*err_ptr = -EINVAL;
+	return(newsum);
+}
+
+struct int6 {int x[6];};
+
+void
+deputy_syscall(struct syscall_h *s, int delay_sigs)
+{
+	register struct task_struct *p = current;
+	extern void *sys_call_table[];
+	long (*func)(struct int6);
+	struct syscall_ret_h r;
+	int n = s->n;
+	struct pt_regs regs;
+	char *cdata, *tofree;
+	int l;
+
+	if(p->mosix.deputy_regs)
+		regs = *(mos_to_regs(&p->mosix));
+	memcpy((caddr_t)&regs, (caddr_t)s->args, sizeof(s->args));
+	open_ucache_envelope(s);
+	comm_free(s);
+	switch(n)
+	{
+		/* Add to this list all machine-dependent system-calls that
+		 * take the parameters' address, assuming it is the process'
+		 * registers: Such routines are all in "arch/i386/ * / *"
+		 */
+	case __NR_fork:
+	case __NR_vfork:
+	case __NR_clone:
+	case __NR_execve:
+	case __NR_iopl:
+	case __NR_ioperm:
+	case __NR_sigsuspend:
+	case __NR_rt_sigsuspend:
+	case __NR_sigreturn:
+	case __NR_rt_sigreturn:
+	case __NR_sigaltstack:
+	case __NR_vm86old:
+	case __NR_vm86:
+		if(delay_sigs)
+			p->mosix.dflags |= DTRACESYS1;
+		/* (for the son to set "delay_sigs") */
+		r.ret = call_with_regs((void *)sys_call_table[n],
+				       &regs, &regs);
+		p->mosix.dflags &= ~DTRACESYS1;
+		if(p->mosix.deputy_regs ||
+		   !(current->mosix.dflags & DDEPUTY))
+			/* sorry, cannot keep it in "regs" after we return */
+			*(mos_to_regs(&p->mosix)) = regs;
+		break;
+	default:
+		func = (__typeof__(func)) sys_call_table[n];
+		r.ret = func(*((struct int6 *)&regs));
+		p = current;
+		break;
+	}
+	if(!(p->mosix.dflags & DDEPUTY))
+	{
+		mos_to_regs(&current->mosix)->eax = r.ret;
+		return;
+	}
+	cdata = deputy_pack_read_cache_data(&l, &r, &tofree);
+	cli();
+	r.deputytime = p->mosix.deputytime;
+	p->mosix.deputytime = 0;
+	sti();
+	if(deputy_reply(REM_SYSCALL, &r, sizeof(r), cdata, l, 0, delay_sigs))
+	{
+		if(tofree)
+			kfree(tofree);
+		deputy_die_on_communication();
+	}
+	if(tofree)
+		kfree(tofree);
+}
+
+void
+mosix_deputy_rlimit(int resource, struct rlimit r)
+{
+	struct rlimit_h l;
+
+	l.resource = resource;
+	l.limit = r;
+	deputy_request(DEP_RLIMIT, &l, sizeof(l), NULL, 0, 0, NULL, 0);
+}
+
+int
+deputy_bring_page(struct bring_page_h *b)
+{
+	struct file *fp = b->fp;
+	struct vm_area_struct v;
+	struct page_ret_h r;
+	int err;
+	int address = b->offset;
+	struct page *page;
+	register struct task_struct *p = current;
+
+	v.vm_start = v.vm_pgoff = 0;
+	v.vm_end = address + PAGE_SIZE;
+	v.vm_mm = p->mm;	/* (eg. NULL) */
+	v.vm_file = fp;
+	v.vm_flags = 0;		/* anything really, but VM_SHARED */
+
+	deeper_sleep();
+	page = b->nopage(&v, address, 0);
+	lighter_sleep();
+	if(page == NOPAGE_OOM)
+	{
+		r.ret = -ENOMEM;
+		page = 0;
+	}
+	else
+		r.ret = page ? 0 : -EFBIG;
+	comm_free(b);
+	cli();
+	r.deputytime = p->mosix.deputytime;
+	p->mosix.deputytime = 0;
+	sti();
+	err = deputy_reply(REM_PAGE, &r, sizeof(r),
+		page ? kmap(page) : NULL, page ? PAGE_SIZE : 0, 0, 2);
+	if(page)
+	{
+		kunmap(page);
+		__free_page(page);
+	}
+	return(err);
+}
+
+int
+deputy_tsc(void)
+{
+	u64 r;
+
+	rdtsc(*((unsigned long *)&r), *(((unsigned long *)&r) + 1));
+	return(deputy_reply(REM_GETTSC|REPLY, &r, sizeof(r), NULL, 0, 0, 2));
+}
+
+void
+deputy_add_rusage(struct rusage *r)
+{
+	register struct task_struct *p = current;
+	int64_t ut = r->ru_utime.tv_sec * (int64_t)HZ +
+						r->ru_utime.tv_usec*HZ/MILLION;
+	int64_t st = r->ru_stime.tv_sec * (int64_t)HZ +
+						r->ru_stime.tv_usec*HZ/MILLION;
+
+	cli();
+	p->times.tms_utime += ut;
+	p->times.tms_stime += st;
+	sti();
+	p->min_flt += r->ru_minflt;
+	p->maj_flt += r->ru_majflt;
+	p->nswap += r->ru_nswap;
+}
+
+void
+mosix_deputy_count_args(char **argp, char **envp, int *argc, int *envc)
+{
+	struct execve_counts_h e;
+	struct execve_counts_ret_h r;
+
+	e.argp = argp;
+	e.envp = envp;
+	if(deputy_request(DEP_EXECVE_COUNTS, &e, sizeof(e), NULL, 0, 0,
+		(void **)&r, -sizeof(r)))
+		*argc = -EFAULT;
+	else
+	{
+		*argc = r.argc;
+		*envc = r.envc;
+	}
+}
+
+static inline int
+fill_strings_page(int pgno, int len)
+{
+	struct linux_binprm *bprm;
+	struct page *page;
+	char *kaddr;
+	int ret;
+
+	if(!pgno || len == 0)
+		return(0);
+	if(!(bprm = current->mosix.inexec) || pgno < 0 ||
+		pgno > MAX_ARG_PAGES ||
+		len < 0 || len > PAGE_SIZE || bprm->page[pgno-1])
+	{
+		printk("%s - Improper strings-page(%d:%d)\n",
+			desc_mostask(NULL), pgno, len);
+		comm_flushdata(COMM_ALLDATA);
+		return(-EFAULT);
+	}
+	if(!(page = alloc_page(GFP_HIGHUSER)))
+	{
+		comm_flushdata(COMM_ALLDATA);
+		return(0); /* error will be detected by missing the page */
+	}
+	bprm->page[pgno-1] = page;
+	kaddr = kmap(page);
+	ret = comm_copydata(kaddr + (PAGE_SIZE - len), len, 0);
+	kunmap(page);
+	return(ret);
+}
+
+int
+mosix_deputy_bring_strings(struct linux_binprm *bprm, char *filename,
+						char **envp, char **argp)
+{
+	struct execve_bring_strings_h b;
+	struct execve_bring_strings_ret_h r;
+	int i;
+
+	b.p = bprm->p;
+	b.filename = filename;
+	b.envp = envp;
+	b.envc = bprm->envc;
+	b.argp = argp;
+	b.argc = bprm->argc;
+	if(deputy_request(DEP_BRING_STRINGS, &b, sizeof(b), NULL, 0, 0,
+		(void **)&r, -sizeof(r)))
+		return(-ENOMEM);
+	if(r.result)
+	{
+		comm_flushdata(COMM_ALLDATA);
+		return(r.result);
+	}
+	bprm->p = r.p;
+	bprm->exec = r.exec;
+	fill_strings_page(r.pgno, r.len);
+	for(i = r.p / PAGE_SIZE ; i < MAX_ARG_PAGES ; i++)
+	if(!bprm->page[i])
+	  /* "fill_strings_page" or one of the "deputy_more_strings" failed */
+		return(-EAGAIN);
+	return(0);
+}
+
+int
+deputy_more_strings(struct execve_more_strings_h *m)
+{
+	int result = fill_strings_page(m->pgno, m->len);
+
+	comm_free(m);
+	if(result == -EAGAIN)
+		result = 0;
+	return(result);
+}
+
+int
+deputy_bring_me_regs(unsigned long *bring)
+{
+	current->mosix.pass_regs |= *bring & current->mosix.deputy_regs;
+	comm_free(bring);
+	return(comm_send(REM_BRING_ME_REGS|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+mosix_deputy_setup_args(int how, unsigned long *start_stack_p)
+{
+	struct execve_setup_args_h e;
+	struct execve_setup_args_ret_h r;
+	register struct linux_binprm *bprm = current->mosix.inexec;
+	unsigned int i;
+	int err;
+	struct page *page;
+	char *kaddr = NULL;
+
+	e.create = 1;
+	for(i = 0 ; i < MAX_ARG_PAGES-1 ; i++)
+	if((page = bprm->page[i]))
+	{
+		e.how = SETUP_ARGS_NOTYET;
+		e.pgno = i+1;
+		e.len = (i+1) * PAGE_SIZE - bprm->p;
+		if(e.len > PAGE_SIZE)
+			e.len = PAGE_SIZE;
+		kaddr = kmap(page);
+		err = comm_send(DEP_SETUP_ARGS, &e, sizeof(e),
+					kaddr + (PAGE_SIZE - e.len), e.len, 0);
+		kunmap(page);
+		if(err)
+			return(-EDIST);
+		e.create = 0;
+	}
+	e.exec = bprm->exec;
+	e.argc = bprm->argc;
+	e.envc = bprm->envc;
+	e.personality = current->personality;
+	e.how = how;
+	if((page = bprm->page[MAX_ARG_PAGES-1]))
+	{
+		e.pgno = MAX_ARG_PAGES;
+		e.len = MAX_ARG_PAGES * PAGE_SIZE - bprm->p;
+		if(e.len > PAGE_SIZE)
+			e.len = PAGE_SIZE;
+		kaddr = kmap(page);
+	}
+	else
+		e.len = e.pgno = 0;
+	e.p = bprm->p;
+	err = deputy_request(DEP_SETUP_ARGS, &e, sizeof(e),
+		e.len ? kaddr + (PAGE_SIZE - e.len) : NULL, e.len, 0,
+						(void **)&r, -sizeof(r));
+	if(page)
+		kunmap(page);
+	if(err)
+		return(-EDIST);
+	bprm->loader = r.loader;
+	bprm->exec = r.exec;
+	bprm->p = r.p;
+	for(i = 0 ; i < MAX_ARG_PAGES ; i++)
+	if(bprm->page[i])
+	{
+		__free_page(bprm->page[i]);
+		bprm->page[i] = 0;
+	}
+	if(start_stack_p)
+		*start_stack_p = r.start_stack;
+	return(r.reply);
+}
+
+int
+mosix_deputy_exec_mmap(char *filename)
+{
+	int r;
+
+	flush_ucache();
+	if(deputy_request(DEP_EXEC_MMAP, NULL, 0, NULL, 0, 0,
+						(void **)&r, -sizeof(r)))
+		return(-ENOMEM);
+	if(!r)
+		mosix_clear_all_held_files(current);
+	return(r);
+}
+
+int
+mosix_deputy_dump_thread(struct user *u)
+{
+	return(deputy_request(DEP_DUMP_THREAD, NULL, 0, NULL, 0, 0,
+		(void **)u, -sizeof(struct user)));
+}
+
+void
+mosix_deputy_init_aout_mm(struct exec *ex)
+{
+	deputy_request(DEP_INIT_AOUT_MM, ex, sizeof(*ex), NULL, 0, 0, NULL, 0);
+}
+
+unsigned long
+mosix_deputy_elf_setup(char *p, int argc, int envc, struct elfhdr *exec,
+	unsigned long addr, unsigned long load_bias,
+	unsigned long interp_load_addr, int ibcs,
+	int add_arg_start, unsigned long elf_brk, unsigned long end_code,
+	unsigned long start_code, unsigned long start_data,
+	unsigned long end_data, unsigned long elf_bss,
+	unsigned long personality, struct elf_tables_extras *extras)
+{
+	struct execve_elf_setup_h e;
+	unsigned long r;
+
+	e.p = p;
+	e.argc = argc;
+	e.envc = envc;
+	if((e.hasexec = (exec != NULL)))
+	{
+		e.exec_e_phoff = exec->e_phoff;
+		e.exec_e_phnum = exec->e_phnum;
+		e.exec_e_entry = exec->e_entry;
+	}
+	e.addr = addr;
+	e.load_bias = load_bias;
+	e.interp_load_addr = interp_load_addr;
+	e.ibcs = ibcs;
+	e.extras = *extras;
+	e.add_arg_start = add_arg_start,
+	e.elf_brk = elf_brk;
+	e.end_code = end_code;
+	e.start_code = start_code;
+	e.end_data = end_data;
+	e.start_data = start_data;
+	e.elf_bss = elf_bss;
+	e.personality = personality;
+
+	if(deputy_request(DEP_ELF_SETUP, &e, sizeof(e), NULL, 0, 0,
+		(void **)&r, -sizeof(r)))
+	{
+		if(current->mosix.dflags & DDEPUTY)
+			deputy_communication_failed();
+		r = (unsigned long)e.p;	/* we did nothing, keep same */
+	}
+	return(r);
+}
+
+void
+mosix_deputy_fix_elf_aout_interp(unsigned bss, unsigned data, unsigned text)
+{
+	struct execve_fix_elf_aout_h f;
+
+	f.bss = bss;
+	f.data = data;
+	f.text = text;
+	deputy_request(DEP_FIX_ELF_AOUT, &f, sizeof(f), NULL, 0, 0, NULL, 0);
+}
+
+int
+mosix_deputy_list_vmas(struct vmalist **vmasp, unsigned long *argstartp,
+	unsigned long *argendp)
+{
+	struct list_vmas_ret_h r;
+
+	if(deputy_request(DEP_LIST_VMAS, NULL, 0, NULL, 0, 0, (void **)&r,
+		-sizeof(r)) || r.n < 0)
+		return(-1);
+	if(r.n == 0)
+		*vmasp = NULL;
+	else
+	{
+		if(!(*vmasp = kmalloc(r.n*sizeof(struct vmalist), GFP_KERNEL)))
+			return(-1);
+		if(comm_copydata(*vmasp, r.n * sizeof(struct vmalist), 0))
+			return(-1);
+	}
+	*argstartp = r.argstart;
+	*argendp = r.argend;
+	return(r.n);
+}
+
+/*
+ * migrated away - shed memory etc.
+ */
+void
+deputy_startup(void)
+{
+	register struct task_struct *p = current;
+
+	exit_mm(p);
+	p->mosix.pages_i_bring = 0;
+	read_lock(&tasklist_lock);
+	p->mosix.ancesstor = NULL;
+	read_unlock(&tasklist_lock);
+#ifdef CONFIG_MOSIX_DFSA
+	tell_process(p, DREQ_NOTUPTODATE);
+#endif /* CONFIG_MOSIX_DFSA */
+}
+
+int
+mosix_deputy_personality(unsigned long personality)
+{
+	int result;
+
+	if(deputy_request(DEP_PERSONALITY, &personality, sizeof(personality),
+		NULL, 0, 0, (void **)&result, -sizeof(result)))
+		return(-1);
+	return(result);
+}
+
+int
+mosix_deputy_dump_fpu(struct user_i387_struct *f)
+{
+	int r;
+
+	if(deputy_request(DEP_DUMP_FPU, NULL, 0, NULL, 0, 0,
+		(void **)&r, -sizeof(r)))
+		return(0);
+	if(r && comm_copydata(f, sizeof(*f), 0))
+		return(0);
+	return(r);
+}
+
+int
+mosix_deputy_fork(struct task_struct *son, int migrated, unsigned long usp)
+{
+	struct mosix_task *m = &current->mosix;
+	void *head;
+	int hlen;
+	int type;
+	int where;
+	mosix_link *sonsock = NULL;
+	struct fork_h f;
+	int n;
+
+	f.usp = usp;
+	f.do_forkmigrate = !migrated;
+	f.pid = son->pid;
+	f.tgid = son->tgid;
+	resend:
+	m->pass_regs = ALL_REGISTERS & ~BIT_OF_REGISTER(eax);
+	if(comm_send(DEP_PLEASE_FORK, &f, sizeof(f), NULL, 0, 0))
+	{
+		bad:
+		if(sonsock)
+			comm_close(sonsock);
+		deputy_communication_failed();
+		return(-EDIST);
+	}
+	son->mosix.deputy_regs = m->deputy_regs;
+	while(1)
+		switch(type = comm_recv(&head, &hlen))
+		{
+		default:
+			if(type < 0)
+				goto bad;
+			if(!(type & ANYTIME))
+			{
+				printk("Unexpected reply (0x%x) to fork request"
+				       "\n", type);
+				goto bad;
+			}
+			if(deputy_handle_interim_request(type, head, hlen))
+				goto bad;
+			break;
+		case REM_MUST_COME_HOME:
+		case REM_BRING_ME_HOME:
+			/* comm_free(head); not needed - it's empty */ 
+		go_home_first:
+			if(sonsock)
+			{
+				comm_close(sonsock);
+				sonsock = NULL;
+			}
+			if(passto((type == REM_MUST_COME_HOME) ?
+				  MUSTGOHOME : GOBACKHOME, 0))
+				return(-EAGAIN);
+		came_home:
+			if(sonsock)
+			{
+				comm_close(sonsock);
+				sonsock = NULL;
+			}
+			son->mosix.whereami = 0;
+			undeputy(son);
+			return(0);
+		case REM_BRING_ME_TO:
+			where = *((int *)head);
+			comm_free(head);
+			if(sonsock)
+			{
+				comm_close(sonsock);
+				sonsock = NULL;
+			}
+			if(!passto(where, 0))
+			{
+				if(!(m->dflags & DDEPUTY))
+					goto came_home;
+				son->mosix.whereami = m->whereami;
+				f.do_forkmigrate = 0;
+				goto resend;
+			}
+			if(comm_send(REM_BRING_ME_TO|REPLY, NULL, 0, NULL, 0,0))
+				goto bad;
+			break;
+		case REM_CONSIDERING:
+			/* comm_free(head); not needed - it's empty */ 
+			if(sonsock)
+			{
+				comm_close(sonsock);
+				sonsock = NULL;
+			}
+			n = m->nmigs;
+			coordinate(BALANCE, 1);
+			f.do_forkmigrate = 0;	/* once only */
+			if(!(m->dflags & DDEPUTY))
+				goto came_home;
+			son->mosix.whereami = m->whereami;
+			if(m->nmigs != n)
+				goto resend;
+			break;
+		case REM_CONNECT_TO:
+			if(sonsock)
+				mosix_panic("Dup REM_CONNECT_TO");
+			sonsock = comm_open(COMM_TOADDR, (mosix_addr *)head,
+					    comm_connect_timo);
+			comm_free(head);
+			n = (sonsock != NULL);
+			if(comm_send(REM_CONNECT_TO|REPLY, &n, sizeof(n),
+				     NULL, 0, 0))
+				goto bad;
+			break;
+		case DEP_PLEASE_FORK|REPLY:
+			n = *((int *)head);
+			comm_free(head);
+			if(n)
+				goto go_home_first;
+			if(!sonsock)
+			{
+				mosix_panic("deputy_fork: no sonsock");
+				goto go_home_first;
+			}
+			son->mosix.dflags |= (DDEPUTY|DSYNC|
+					      (m->dflags & DDUMPABLE));
+			comm_use(son, sonsock);
+			return(0);
+		}
+}
+
+//EXPORT_SYMBOL(deputy_copy_from_user);
+//EXPORT_SYMBOL(deputy_copy_to_user);
diff -Naur --exclude=CVS --exclude=configs linux/hpc/dfsa.c linux-openmosix/hpc/dfsa.c
--- linux/hpc/dfsa.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/dfsa.c	2003-09-10 20:50:13.000000000 +0200
@@ -0,0 +1,2692 @@
+/* All changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/hpc.h>
+#include <hpc/protocol.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/proc_fs.h>
+
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+
+#define	CLEAR_ALL(fls,fld)	memset(fls->fld, 0, fls->max_fdset/8)
+
+struct dfsatab *dfsatab;
+struct vfsmount *dfsa_mounts[MAXDFSAFS];
+struct
+{
+	struct vfsmount *mnt;
+	struct dentry *dentry;
+} dfsa_links[MAXDFSALINKS];
+char dfsa_being_cancelled[MAXDFSAFS];
+char dfsa_recheck_mount[MAXDFSAFS];
+struct dentry *bad_deputy_dfsaentry;
+int dfsa_disabled = 1;
+DECLARE_MUTEX(dfsa_modify_lock);
+
+extern struct inode_operations all_bad_inode_operations;
+extern struct file_operations all_bad_file_operations;
+extern struct super_block bad_super_block;
+
+void
+dfsa_init(void)
+{
+	struct inode *ip;
+
+	if(!(dfsatab = kmalloc(sizeof(struct dfsatab), GFP_KERNEL)))
+		panic("dfsa_init");
+	dfsatab->len = sizeof(struct dfsatab);
+	dfsatab->ndefs = 0;
+	if(!(bad_deputy_dfsaentry =
+			d_alloc(NULL, &(const struct qstr) { "/", 1, 0 })))
+		panic("dfsa_init: d_alloc");
+	if(!(ip = new_inode(&bad_super_block)))
+		panic("dfsa_init: empty inode");
+	ip->i_mode = S_IFREG;
+	ip->i_op = &all_bad_inode_operations;
+	ip->i_fop = &all_bad_file_operations;
+	bad_deputy_dfsaentry->d_inode = ip;
+	bad_deputy_dfsaentry->d_parent = bad_deputy_dfsaentry;
+	dfsa_disabled = 0;
+}
+
+int
+dfsa_option(char *data, int *result)
+{
+	int n;
+	int has = 0;
+
+	if(!data)
+		return(0);
+	while(1)
+	{
+		while(*data && (*data != 'd' || *(data+1) != 'f' ||
+			*(data+2) != 's' || *(data+3) != 'a' ||
+			*(data+4) != '='))
+			data++;
+		if(!*data)
+			return(has);
+		data += 5;
+		if(*data < '0' || *data > '9')
+		{
+			printk("WARNING: Invalid 'dfsa=' value <%s>\n", data);
+			continue;
+		}
+		for(n = 0 ; *data >= '0' && *data <= '9' ; data++)
+		{
+			n = n * 10 + *data - '0';
+			if(n > 32767)
+				break;
+		}
+		if(n <= 32767)
+		{
+			has = 1;
+			*result = n;
+		}
+		else
+			printk("DFSA-number option overflow!\n");
+	}
+	return(has);
+}
+
+void
+dfsa_is_not_up_to_date(void)
+{
+	tell_process(current, DREQ_NOTUPTODATE);
+}
+
+void
+dfsa_pwd_changed(void)
+{
+	current->mosix.dupdates |= DFSA_UPDCDIR;
+}
+
+#define	DFSA_MOUNT_MOUNTED	1
+#define	DFSA_MOUNT_RDONLY	2
+#define	DFSA_MOUNT_SYNC		4
+#define	DFSA_MOUNT_NOATIME	8
+#define	DFSA_MOUNT_NODIRATIME	16
+#define	DFSA_MOUNT_SYMLINK	32
+
+int
+important_fs_flags(unsigned long flags)
+{
+	int f = DFSA_MOUNT_MOUNTED;
+
+	if(flags & MS_RDONLY)
+		f |= DFSA_MOUNT_RDONLY;
+	if(flags & MS_SYNCHRONOUS)
+		f |= DFSA_MOUNT_SYNC;
+	if(flags & MS_NOATIME)
+		f |= DFSA_MOUNT_NOATIME;
+	if(flags & MS_NODIRATIME)
+		f |= DFSA_MOUNT_NODIRATIME;
+	return(f);
+}
+
+/*
+ * 0 = same
+ * 1 = first string comes first
+ * -1 = second string comes first
+ * normally sorted alphabetically -
+ * but if one string begins with the other, the LONGER comes first.
+ */
+static inline int
+dfsa_name_compare(char *n1, char *n2)
+{
+	register unsigned char *u1, *u2;
+	int a, b;
+
+	for(u1 = n1 , u2 = n2 ; *u1 && *u1 == *u2 ; u1++ , u2++)
+		;
+	a = *u1;
+	b = *u2;
+	if(!a)
+		return(b ? -1 : 0);
+	if(!b || a < b)
+		return(1);
+	return(-1);
+}
+
+static inline char *
+mntpath(struct vfsmount *mnt)
+{
+	char *page = (char *)__get_free_page(GFP_KERNEL);
+	struct vfsmount *rootmnt;
+	struct dentry *root;
+
+	if(!page)
+		return(NULL);
+	read_lock(&init_task.fs->lock);
+	rootmnt = mntget(init_task.fs->rootmnt);
+	root = dget(init_task.fs->root);
+	read_unlock(&init_task.fs->lock);
+	spin_lock(&dcache_lock);
+	page = __d_path(mnt->mnt_root, mnt, root, rootmnt, page, PAGE_SIZE);
+	spin_unlock(&dcache_lock);
+	dput(root);
+	mntput(rootmnt);
+	return(page);
+}
+
+static inline void
+dfsa_set_dfsa(struct vfsmount *mnt, int now, int prev)
+{
+	int differ = (mnt->mnt_dfsano != now);
+
+	MOSIX_LOCKED;
+	mnt->mnt_dfsaprev = prev;
+	mnt->mnt_dfsano = now;
+	if(differ && mnt->mnt_sb->s_op->dfsa_changed)
+		mnt->mnt_sb->s_op->dfsa_changed(mnt, now);
+}
+
+int
+dfsa_setmnt(struct vfsmount *mnt, int num, unsigned long flags)
+{
+	int ind, sz, oldnum = 0;
+	register int i, j;
+	char *x, *y;
+	struct dfsatab *new, *old;
+	int error = 0;
+	int c;
+	unsigned int done;
+	char *dir;
+	struct super_block *sb;
+
+	if(num < 0 || num > MAXDFSAFS)
+	{
+		printk("Invalid DFSA index (%d), range is 1-%d "
+			"(or 0 to cancel)\n", num, MAXDFSAFS);
+		return(-EINVAL);
+	}
+	sb = mnt->mnt_sb;
+	if(num && (!sb->s_op || !sb->s_op->identify || !sb->s_op->reconstruct))
+	{
+		printk("%s: Not a DFSA-compatible file-system\n",
+							sb->s_type->name);
+		return(-EPERM);
+	}
+	if(!(dir = mntpath(mnt)))
+		return(-ENOMEM);
+	error = -EBUSY;
+	if(down_interruptible(&dfsa_modify_lock))
+		goto freedir;
+	lock_mosix();
+	if(dfsa_disabled)
+	{
+		if(num == 0)
+			error = 0;
+		goto out;
+	}
+	sz = sizeof(struct dfsatab);
+	ind = -1;
+	for(i = 0 ; i < dfsatab->ndefs ; i++)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		if(!strcmp(dir, x))
+		{
+			oldnum = dfsatab->dfsdef[i].defno;
+			if(oldnum == num && dfsatab->dfsdef[i].mounted ==
+						important_fs_flags(flags))
+			{
+				error = 0;	/* nothing to do */
+				goto out;
+			} 
+			if(oldnum > MAXDFSAFS)
+			{
+				printk("Conflict: mount-point <%s> is declared "
+					"as a DFSA symbolic link\n", dir);
+				error = -EBUSY;
+				goto out;
+			}
+			ind = i;
+		}
+		else if(dfsatab->dfsdef[i].defno == num)
+		{
+			printk("DFSA entry #%d already held for <%s>\n",num, x);
+			error = -EBUSY;
+			goto out;
+		}
+		else
+			sz += sizeof(struct dfsdef) + strlen(x) + 1;
+	}
+	if(ind == -1 && num == 0)
+	{
+		error = 0;	/* nothing to do */
+		goto out;
+	}
+	if(num)
+		sz += sizeof(struct dfsdef) + strlen(dir) + 1;
+	unlock_mosix();
+	new = (sz >= 65535) ? NULL : kmalloc(sz, GFP_KERNEL);
+	lock_mosix();
+	if(!new)
+	{
+		error = -ENOMEM;
+		goto out;
+	}
+	if(ind != -1)
+	{
+		if(num)
+			printk("Changing DFSA index of <%s> from %d to %d\n",
+				dir, oldnum, num);
+		else
+			printk("Cancelling DFSA entry #%d (was <%s>)\n",
+				oldnum, dir);
+		dfsa_being_cancelled[oldnum-1] = 1;
+		dfsa_set_dfsa(mnt, 0, mnt->mnt_dfsano);
+		unlock_mosix();
+		error = dfsa_sync(1);
+		lock_mosix();
+		if(error)
+		{
+			printk("DFSA interrupted: not %s <%s>\n",
+				num ? "Changing" : "Cancelling", dir);
+			dfsa_set_dfsa(mnt, mnt->mnt_dfsaprev, 0);
+			dfsa_being_cancelled[oldnum-1] = 0;
+			dfsa_sync(0);
+			kfree(new);
+			goto out;
+		}
+		mntput(dfsa_mounts[oldnum-1]);
+		dfsa_mounts[oldnum-1] = NULL;
+		dfsa_set_dfsa(mnt, num, 0);
+		dfsa_being_cancelled[oldnum-1] = 0;
+	}
+	else
+	{
+		printk("Adding <%s> as DFSA entry #%d\n", dir, num);
+		dfsa_set_dfsa(mnt, num, 0);
+	}
+	/* compile the new table */
+	new->len = sz;
+	new->ndefs = dfsatab->ndefs - (ind != -1) + (num != 0);
+	y = (char *)&new->dfsdef[(int)new->ndefs];
+	done = 0;
+	for(j = i = 0 ; i < dfsatab->ndefs ; i++)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		if(!done && (c = dfsa_name_compare(dir, x)) <= 0)
+		{
+			done = 1;
+			if(num)
+			{
+				new->dfsdef[j].defno = num;
+				new->dfsdef[j].mounted =
+						important_fs_flags(flags);
+				new->dfsdef[j].offset = y - (char *)new;
+				strcpy(y, dir);
+				while(*y++)
+					;
+				j++;
+			}
+			if(c == 0)
+				continue;
+		}
+		new->dfsdef[j] = dfsatab->dfsdef[i];
+		new->dfsdef[j].offset = y - (char *)new;
+		while(*x)
+			*y++ = *x++;
+		*y++ = '\0';
+		j++;
+	}
+	if(num && !done)
+	{
+		new->dfsdef[j].defno = num;
+		new->dfsdef[j].mounted = important_fs_flags(flags);
+		new->dfsdef[j].offset = y - (char *)new;
+		strcpy(y, dir);
+	}
+	old = dfsatab;
+	dfsatab = new;
+	if(num)
+		dfsa_mounts[num-1] = mntget(mnt);
+	kfree(old);
+	dfsa_sync(0);
+	error = 0;
+	out:
+	unlock_mosix();
+	up(&dfsa_modify_lock);
+	freedir:
+	free_page(((unsigned long)dir) & PAGE_MASK);
+	return(error);
+}
+
+int
+dfsa_addlink(char *link)
+{
+	int i = strlen(link), j;
+	char *x, *y;
+	int ret;
+	struct nameidata nd;
+	struct vfsmount *mnt;
+	struct dentry *dp;
+	struct dfsatab *new, *old;
+	int sz = sizeof(struct dfsatab) + sizeof(struct dfsdef) + i + 1;
+	int linkno;
+	unsigned int added = 0;
+	umode_t mode;
+
+	if(i > MAXDFSALINKLEN)
+		return(-ENAMETOOLONG);
+	if(*link != '/')
+	{
+		printk("DFSA: <%s> must be an absolute path-name.\n", link);
+		return(-EINVAL);
+	}
+	if (path_init(link, LOOKUP_POSITIVE, &nd) && (ret=path_walk(link, &nd)))
+		return(ret);
+	ret = -EINVAL;
+	if(!S_ISLNK(nd.dentry->d_inode->i_mode))
+	{
+		printk("DFSA: <%s> is not a link!\n", link);
+		goto release;
+	}
+	path_release(&nd);
+	if (path_init(link, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd) &&
+		(ret = path_walk(link, &nd)))
+	{
+		printk("DFSA: <%s> symlink is loose (errno=%d)\n", link, ret);
+		return(-EINVAL);
+	}
+	mode = nd.dentry->d_inode->i_mode;
+	if(!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
+	{
+		printk("DFSA: <%s> points to a special file!\n", link);
+		goto release;
+	}
+	if(!nd.mnt->mnt_sb->s_op->identify)
+	{
+		printk("<%s> points to a file-system not supported by DFSA.\n",
+									link);
+		goto release;
+	}
+	ret = -EINTR;
+	if(down_interruptible(&dfsa_modify_lock))
+		goto release;
+	lock_mosix();
+	for(i = 0 ; i < dfsatab->ndefs ; i++)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		if(!strcmp(x, link))
+		{
+			if(dfsatab->dfsdef[i].defno <= MAXDFSAFS)
+			{
+				printk("Conflict: DFSA link <%s> is declared "
+					"as a mount-point\n", link);
+				ret = -EBUSY;
+				goto out;
+			}
+			linkno = dfsatab->dfsdef[i].defno - (MAXDFSAFS+1);
+			mnt = dfsa_links[linkno].mnt;
+			dp = dfsa_links[linkno].dentry;
+			ret = 0;
+			if(mnt == nd.mnt && dp->d_inode == nd.dentry->d_inode)
+				goto out;
+			printk("Updating DFSA link <%s>\n", link);
+			printk("[But please, next time delete the DFSA-link "
+				"BEFORE changing the symbolic-link]!\n");
+			dfsa_links[linkno].mnt = mntget(nd.mnt);
+			dfsa_links[linkno].dentry = dget(nd.dentry);
+			unlock_mosix();
+			mntput(mnt);
+			dput(dp);
+			lock_mosix();
+			goto sync;
+		}
+		sz += sizeof(struct dfsdef) + strlen(x) + 1;
+	}
+	ret = -EMLINK;
+	for(linkno = 0 ; linkno < MAXDFSALINKS ; linkno++)
+	if(!dfsa_links[linkno].mnt)
+		break;
+	if(linkno == MAXDFSALINKS)
+		goto out;
+	unlock_mosix();
+	new = (struct dfsatab *)kmalloc(sz, GFP_KERNEL);
+	lock_mosix();
+	ret = -ENOMEM;
+	if(!new)
+		goto out;
+	printk("Adding DFSA link <%s>\n", link);
+	dfsa_links[linkno].mnt = mntget(nd.mnt);
+	dfsa_links[linkno].dentry = dget(nd.dentry);
+	ret = 0;
+	new->len = sz;  /* bug??? */
+
+	new->ndefs = dfsatab->ndefs + 1;
+	y = (char *)&new->dfsdef[(int)new->ndefs];
+	for(j = i = 0 ; i < dfsatab->ndefs ; i++)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		if(!added && dfsa_name_compare(link, x) == 1)
+		{
+			added = 1;
+			new->dfsdef[j].defno = linkno + MAXDFSAFS + 1;
+			new->dfsdef[j].mounted = 0;
+			new->dfsdef[j].offset = y - (char *)new;
+			strcpy(y, link);
+			while(*y++)
+				;
+			j++;
+		}
+		new->dfsdef[j] = dfsatab->dfsdef[i];
+		new->dfsdef[j].offset = y - (char *)new;
+		while(*x)
+			*y++ = *x++;
+		*y++ = '\0';
+		j++;
+	}
+	if(!added)
+	{
+		new->dfsdef[j].defno = linkno + MAXDFSAFS + 1;
+		new->dfsdef[j].mounted = 0;
+		new->dfsdef[j].offset = y - (char *)new;
+		strcpy(y, link);
+		while(*y++)
+			;
+	}
+	old = dfsatab;
+	dfsatab = new;
+	kfree(old);
+	sync:
+	dfsa_sync(0);
+	out:
+	unlock_mosix();
+	up(&dfsa_modify_lock);
+	release:
+	path_release(&nd);
+	return(ret);
+}
+
+int
+dfsa_dellink(char *link)
+{
+	int i, j;
+	char *x, *y;
+	int ret;
+	struct vfsmount *mnt;
+	struct dentry *dp;
+	struct dfsatab *new, *old;
+	int sz = sizeof(struct dfsatab);
+	int ind = -1;
+	int linkno = 0;
+
+	if(down_interruptible(&dfsa_modify_lock))
+		return(-EINTR);
+	lock_mosix();
+	for(i = 0 ; i < dfsatab->ndefs ; i++)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		if(dfsatab->dfsdef[i].defno <= MAXDFSAFS || strcmp(x, link))
+			sz += sizeof(struct dfsdef) + strlen(x) + 1;
+		else
+		{
+			ind = i;
+			linkno = dfsatab->dfsdef[i].defno - MAXDFSAFS - 1;
+		}
+	}
+	ret = -EINVAL;
+	if(ind == -1)
+		goto out;
+	unlock_mosix();
+	new = (struct dfsatab *)kmalloc(sz, GFP_KERNEL);
+	lock_mosix();
+	ret = -ENOMEM;
+	if(!new)
+		goto out;
+	ret = 0;
+	printk("Deleting DFSA link <%s>\n", link);
+	new->len = sz;
+	new->ndefs = dfsatab->ndefs - 1;
+	y = (char *)&new->dfsdef[(int)new->ndefs];
+	for(j = i = 0 ; i < dfsatab->ndefs ; i++)
+	if(i != ind)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		new->dfsdef[j] = dfsatab->dfsdef[i];
+		new->dfsdef[j].offset = y - (char *)new;
+		while(*x)
+			*y++ = *x++;
+		*y++ = '\0';
+		j++;
+	}
+	old = dfsatab;
+	dfsatab = new;
+	unlock_mosix();
+	i = dfsa_sync(1);
+	lock_mosix();
+	if(i)
+	{
+		printk("Clearing of DFSA links interrupted!\n");
+		dfsatab = old;
+		kfree(new);
+		ret = -EINTR;
+		goto out;
+	}
+	kfree(old);
+	mnt = dfsa_links[linkno].mnt;
+	dfsa_links[linkno].mnt = NULL;
+	dp = dfsa_links[linkno].dentry;
+	dfsa_links[linkno].dentry = NULL;
+	unlock_mosix();
+	mntput(mnt);
+	dput(dp);
+	lock_mosix();
+	out:
+	unlock_mosix();
+	up(&dfsa_modify_lock);
+	return(ret);
+}
+
+int
+dfsa_clearlinks(void)
+{
+	int i, j;
+	char *x, *y;
+	int ret;
+	struct vfsmount *mnt;
+	struct dentry *dp;
+	struct dfsatab *new = NULL, *old;
+	int sz = sizeof(struct dfsatab);
+	unsigned int found = 0;
+
+	if(down_interruptible(&dfsa_modify_lock))
+		return(-EINTR);
+	lock_mosix();
+	for(i = 0 ; i < dfsatab->ndefs ; i++)
+	{
+		if(dfsatab->dfsdef[i].defno <= MAXDFSAFS)
+		{
+			x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+			sz += sizeof(struct dfsdef) + strlen(x) + 1;
+		}
+		else
+			found++;
+	}
+	if(!found)
+	{
+		printk("No DFSA links to clear\n");
+		ret = 0;
+		goto out;
+	}
+	ret = -ENOMEM;
+	unlock_mosix();
+	new = (struct dfsatab *)kmalloc(sz, GFP_KERNEL);
+	lock_mosix();
+	if(!new)
+		goto out;
+	printk("Clearing all DFSA links\n");
+	ret = 0;
+	new->len = sz;
+	new->ndefs = dfsatab->ndefs - found;
+	y = (char *)&new->dfsdef[(int)new->ndefs];
+	for(j = i = 0 ; i < dfsatab->ndefs ; i++)
+	if(dfsatab->dfsdef[i].defno <= MAXDFSAFS)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		new->dfsdef[j] = dfsatab->dfsdef[i];
+		new->dfsdef[j].offset = y - (char *)new;
+		while(*x)
+			*y++ = *x++;
+		*y++ = '\0';
+		j++;
+	}
+	old = dfsatab;
+	dfsatab = new;
+	unlock_mosix();
+	i = dfsa_sync(1);
+	lock_mosix();
+	if(i)
+	{
+		printk("Clearing of DFSA links interrupted!\n");
+		dfsatab = old;
+		kfree(new);
+		ret = -EINTR;
+		goto out;
+	}
+	kfree(old);
+	for(i = 0 ; i < MAXDFSALINKS ; i++)
+	if((mnt = dfsa_links[i].mnt))
+	{
+		dp = dfsa_links[i].dentry;
+		dfsa_links[i].mnt = NULL;
+		dfsa_links[i].dentry = NULL;
+		unlock_mosix();
+		mntput(mnt);
+		dput(dp);
+		lock_mosix();
+	}
+	out:
+	unlock_mosix();
+	up(&dfsa_modify_lock);
+	return(ret);
+}
+
+char *
+dfsa_showlinks(void)
+{
+	unsigned int i;
+	int sz;
+	char *x;
+	char *links = NULL, *p;
+
+	lock_mosix();
+	again:
+	for(sz = 1 , i = 0 ; i < dfsatab->ndefs ; i++)
+	if(dfsatab->dfsdef[i].defno > MAXDFSAFS)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		sz += strlen(x) + 1;
+	}
+	unlock_mosix();
+	if(!(links = kmalloc(sz, GFP_KERNEL)))
+		return(NULL);
+	lock_mosix();
+	p = links;
+	for(i = 0 ; i < dfsatab->ndefs ; i++)
+	if(dfsatab->dfsdef[i].defno > MAXDFSAFS)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		while(*x)
+		{
+			*p++ = *x++;
+			if(--sz < 2)
+			{
+				kfree(links);
+				goto again;
+			}
+		}
+		*p++ = '\n';
+		sz--;
+	}
+	*p = '\0';
+	unlock_mosix();
+	return(links);
+}
+
+int
+disable_dfsa(void)
+{
+	unsigned int i;
+	int ret;
+	struct vfsmount *mnt;
+	struct dentry *dp;
+
+	if(down_interruptible(&dfsa_modify_lock))
+		return(-EINTR);
+	lock_mosix();
+	ret = 0;
+	if(dfsa_disabled++)
+		goto out;
+	printk("Disabling DFSA\n");
+	for(i = 0 ; i < MAXDFSAFS ; i++)
+	{
+		dfsa_being_cancelled[i] = 1;
+		if((mnt = dfsa_mounts[i]))
+			dfsa_set_dfsa(mnt, 0, mnt->mnt_dfsa);
+	}
+	if((ret = dfsa_sync(1)))
+	{
+		printk("Disabling DFSA interrupted\n");
+		for(i = 0 ; i < MAXDFSAFS ; i++)
+		if((mnt = dfsa_mounts[i]))
+			dfsa_set_dfsa(mnt, mnt->mnt_dfsaprev, 0);
+		unlock_mosix();
+		enable_dfsa();
+		goto out2;
+	}
+	dfsatab->ndefs = 0;
+	dfsatab->len = sizeof(struct dfsatab);
+	for(i = 0 ; i < MAXDFSAFS ; i++)
+	if((mnt = dfsa_mounts[i-1]))
+	{
+		dfsa_mounts[i-1] = NULL;
+		dfsa_set_dfsa(mnt, 0, 0);
+		unlock_mosix();
+		mntput(mnt);
+		lock_mosix();
+	}
+	for(i = 0 ; i < MAXDFSALINKS ; i++)
+	if((mnt = dfsa_links[i].mnt))
+	{
+		dp = dfsa_links[i].dentry;
+		dfsa_links[i].mnt = NULL;
+		dfsa_links[i].dentry = NULL;
+		unlock_mosix();
+		mntput(mnt);
+		dput(dp);
+		lock_mosix();
+	}
+	out:
+	unlock_mosix();
+	out2:
+	up(&dfsa_modify_lock);
+	return(ret);
+}
+
+void
+enable_dfsa()
+{
+	unsigned int i;
+
+	lock_mosix();
+	if(--dfsa_disabled == 0)
+	{
+		for(i = 0 ; i < MAXDFSAFS ; i++)
+			dfsa_being_cancelled[i] = 0;
+		dfsa_sync(0);
+	}
+	unlock_mosix();
+}
+
+char *
+dfsa_getdir(int num, int *tofree)
+{
+	register unsigned int i, l;
+	char *x, *copy;
+	char *ret;
+
+	*tofree = 0;
+	lock_mosix();
+	again:
+	ret = "\n";
+	for(i = 0 ; i < dfsatab->ndefs ; i++)
+	if(dfsatab->dfsdef[i].defno == num)
+	{
+		x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset];
+		/* try to copy - just in case of changes during copy_to_user: */
+		l = strlen(x);
+		unlock_mosix();
+		copy = kmalloc(l+2, GFP_KERNEL);
+		lock_mosix();
+		if(!copy)
+		{
+			ret = "Sorry: no memory\n";
+			break;
+		}
+		/* paranoid test - did the table change? */
+		if((dfsatab) ||
+			i >= dfsatab->ndefs || dfsatab->dfsdef[i].defno != num ||
+			strlen(x = &((char *)dfsatab)[dfsatab->dfsdef[i].offset]) > l)
+		{
+			kfree(copy);
+			goto again;
+		}
+		sprintf(copy, "%s\n", x);
+		ret = copy;
+		*tofree = 1;
+		break;
+	}
+	unlock_mosix();
+	return(ret);
+}
+
+DECLARE_WAIT_QUEUE_HEAD(wait_for_all_to_dfsasync);
+
+int
+dfsa_all_know(void)
+{
+	register struct task_struct *p;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if(process_told(p, DREQ_DFSASYNC))
+		break;
+	read_unlock(&tasklist_lock);
+	return(p == &init_task);
+}
+
+int
+dfsa_sync(int wait)
+{
+	struct task_struct *p;
+	unsigned int any = 0;
+	int ret = 0;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if((p->mosix.dflags&(DDEPUTY|DREMOTE)) && !(p->mosix.dflags&DFINISHED))
+	{
+		any = 1;
+		tell_process(p, DREQ_DFSASYNC);
+		wake_up_mosix(p);
+	}
+	read_unlock(&tasklist_lock);
+	if(!any)
+		wake_up(&wait_for_all_to_dfsasync);
+	if(wait)
+	{
+		DECLARE_WAITQUEUE(wait, current);
+
+		add_wait_queue(&wait_for_all_to_dfsasync, &wait);
+		while(1)
+		{
+			set_current_state(TASK_INTERRUPTIBLE);
+			if(dfsa_all_know())
+				break;
+			schedule();
+			if(signal_pending(current))
+			{
+				ret = -EINTR;
+				break;
+			}
+		}
+		remove_wait_queue(&wait_for_all_to_dfsasync, &wait);
+		set_current_state(TASK_RUNNING);
+	}
+	return(ret);
+}
+
+void
+clear_dfsasync(void)
+{
+	if(process_told(current, DREQ_DFSASYNC))
+	{
+		process_ack(current, DREQ_DFSASYNC);
+		if(dfsa_all_know())	/* we were the last to ack */
+			wake_up(&wait_for_all_to_dfsasync);
+		tell_process(current, DREQ_NOTUPTODATE);
+	}
+}
+
+/*
+ * keep only those entries in "*tab" that also appear in our main "dfsatab"
+ * and have the same [important] mount-flags.
+ * both tables are already sorted.
+ */
+void
+dfsa_adapt(struct dfsatab *tab)
+{
+	unsigned int i, j = 0, k = 0;
+	int n1 = tab->ndefs, n2;
+	struct dfsdef *def1, *def2;
+	char *x, *y;
+
+	lock_mosix();
+	n2 = dfsatab->ndefs;
+	def2 = &dfsatab->dfsdef[0];
+	if(n2)
+		for(def1 = tab->dfsdef , i = 0 ; i < n1 ; i++ , def1++)
+		{
+			x = &((char *)tab)[def1->offset];
+		next2:
+			y = &((char *)dfsatab)[def2->offset];
+			switch(dfsa_name_compare(x, y))
+			{
+			case 0:
+				if(def1->mounted == def2->mounted)
+				{
+					if(k != i)
+						tab->dfsdef[k] = tab->dfsdef[i];
+					k++;
+					j++;
+					def2++;
+				}
+			case -1:
+				continue;
+			case 1:
+				j++;
+				def2++;
+				if(j == n2)
+					break;
+				goto next2;
+			}
+		}
+	unlock_mosix();
+	tab->ndefs = k;
+}
+
+int
+name_starts_in_dfsa(char **nam, struct nameidata *nd)
+{
+	register struct dfsatab *tab;
+	register unsigned int i;
+	char *n, *x;
+	struct vfsmount *mnt;
+	int ind;
+
+	lock_mosix();
+	tab = (current->mosix.dflags & DREMOTE) ? current->mosix.ttab : dfsatab;
+	if(tab && !dfsa_disabled)
+	for(i = 0 ; i < tab->ndefs ; i++)
+	{
+		n = *nam;
+		x = &((char *)tab)[tab->dfsdef[i].offset];
+		while(*n && *n == *x)
+		{
+			if(*n == '/')
+			{
+				while(*x == '/')
+					x++;
+				if(*x == '\0')
+					break;
+				while(*n == '/')
+				{
+					n++;
+					if(*n == '.' && (*(n+1) == '\0' ||
+								*(n+1) == '/'))
+						n++;
+				}
+			}
+			else
+			{
+				n++;
+				x++;
+			}
+		}
+		if(*x || (*n && *n != '/'))
+			continue;
+		if((nd->flags & LOOKUP_PARENT) || (!tab->dfsdef[i].mounted &&
+			 !*n && !(nd->flags & LOOKUP_FOLLOW)))
+		{
+			while(*n == '/')
+				n++;
+			if(!*n)
+				continue;
+		}
+		else while(*n == '/')
+			n++;
+		ind = tab->dfsdef[i].defno - 1;
+		if(ind < MAXDFSAFS)
+		{
+			if(dfsa_being_cancelled[ind] ||
+						!(mnt = dfsa_mounts[ind]))
+				break;
+			nd->mnt = mntget(mnt);
+			nd->dentry = dget(mnt->mnt_root); 
+		}
+		else
+		{
+			ind -= MAXDFSAFS;
+			if(!(mnt = dfsa_links[ind].mnt))
+				break;
+			if(!mnt->mnt_dfsano)
+				break;
+			nd->mnt = mntget(mnt);
+			nd->dentry = dget(dfsa_links[ind].dentry);
+		}
+		*nam = n;
+		unlock_mosix();
+		return(1);
+	}
+	unlock_mosix();
+	return(0);
+}
+
+int
+within_dfsa(struct nameidata *nd)
+{
+	int dfsano;
+	struct dfsatab *tab;
+	struct dfsdef *def;
+	int i;
+	int ret;
+
+	lock_mosix();
+	if(dfsa_disabled || !(dfsano = nd->mnt->mnt_dfsano) ||
+		dfsa_being_cancelled[dfsano-1] || !(dfsa_mounts[dfsano-1]))
+		ret = 0;
+	else if(!(current->mosix.dflags & DREMOTE))
+		ret = 1;
+	else if(!(tab = current->mosix.ttab) || nd->mnt->mnt_dfsaprev)
+		ret = 0;
+	else
+	{
+		ret = 0;
+		for(def = tab->dfsdef , i = tab->ndefs ; i > 0 ; i-- , def++)
+		if(def->defno == dfsano)
+		{
+			ret = 1;
+			break;
+		}
+	}
+	unlock_mosix();
+	return(ret);
+}
+
+void
+dfsa_close_file(int fd)
+{
+	register struct task_struct *p = current;
+	register struct files_struct *files = current->files;
+
+	if(atomic_read(&files->users) > 1)
+	{
+		tell_process(p, DREQ_NOTUPTODATE);
+		return;
+	}
+	if(fd >= files->maxclosed)
+		files->maxclosed = fd + 1;
+	FD_SET(fd, files->closed);
+	p->mosix.dupdates |= DFSA_UPDCLOSE;
+}
+
+void
+dfsa_open_file(int fd)
+{
+	struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	struct file *f;
+	int n;
+
+	if(atomic_read(&files->users) > 1)
+	{
+		tell_process(p, DREQ_NOTUPTODATE);
+		return;
+	}
+	/* since nobody shares our files, no locking is necessary */
+	if(!can_dfsa_file(fd))
+	{
+		p->mosix.dupdates |= DFSA_UPDUSED;
+		return;
+	}
+	p->mosix.dupdates |= DFSA_UPDOPEN;
+	f = files->fd[fd];
+	if((n = file_count(f)) > 1)
+	{
+		/* must find all DUPs: */
+		register int i, l, li;
+		struct file **dups = files->fd;
+		unsigned long *bits = files->open_fds->fds_bits;
+		int lim = files->max_fds, llim;
+
+		if(lim > files->max_fdset)
+			lim = files->max_fdset;
+		llim = (lim + BITS_PER_LONG - 1) / BITS_PER_LONG;
+		for(i = l = 0 ; l < llim ; l++)
+		if(*bits++)
+		{
+			li = i + BITS_PER_LONG;
+			if(li > lim)
+				li = lim;
+			for(; i < li ; i++)
+			if(dups[i] == f)
+			{
+				if(i >= files->maxopened)
+					files->maxopened = i + 1;
+				FD_SET(i, files->opened);
+				FD_CLR(i, files->modified);
+				if(--n == 0)
+					return;
+			}
+		}
+		else
+			i += BITS_PER_LONG;
+	}
+	else
+	{
+		if(fd >= files->maxopened)
+			files->maxopened = fd + 1;
+		FD_SET(fd, files->opened);
+		FD_CLR(fd, files->modified);
+	}
+}
+
+void
+dfsa_touch_file(int fd)
+{
+	struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	struct file *f;
+	int n;
+
+	if(atomic_read(&files->users) > 1)
+	{
+		tell_process(p, DREQ_NOTUPTODATE);
+		return;
+	}
+	/* since nobody shares our files, no locking is necessary */
+	if(!can_dfsa_file(fd))
+		return;
+	p->mosix.dupdates |= DFSA_UPDMODS;
+	f = files->fd[fd];
+	if((n = file_count(f)) > 1)
+	{
+		/* must find all DUPs: */
+		register int i, l, li;
+		struct file **dups = files->fd;
+		unsigned long *bits = files->open_fds->fds_bits;
+		int lim = files->max_fds;
+		int llim;
+
+		if(lim > files->max_fdset)
+			lim = files->max_fdset;
+		llim = (lim + BITS_PER_LONG - 1) / BITS_PER_LONG;
+		for(i = l = 0 ; l < llim ; l++)
+		if(*bits++)
+		{
+			li = i + BITS_PER_LONG;
+			if(li > lim)
+				li = lim;
+			for(; i < li ; i++)
+			if(dups[i] == f)
+			{
+				if(FD_ISSET(i, files->opened))
+					continue;
+				if(i >= files->maxmod)
+					files->maxmod = i + 1;
+				FD_SET(i, files->modified);
+				if(--n == 0)
+					return;
+			}
+		}
+		else
+			i += BITS_PER_LONG;
+	}
+	else
+	{
+		if(FD_ISSET(fd, files->opened))
+			return;
+		if(fd >= files->maxmod)
+			files->maxmod = fd + 1;
+		FD_SET(fd, files->modified);
+	}
+}
+
+/*
+ * callers to "can_dfsa_file" must first make sure (perhaps with "CAN_DFSA")
+ * that their files_struct is not shared with clones:
+ * hence, neither the caller nor "can_dfsa_file" need to lock the files
+ * (which could deadlock the mosix-lock)
+ */
+int
+can_dfsa_file(int fd)
+{
+	register int i, l, li;
+	struct file *file = fcheck(fd);
+	struct vfsmount *mnt;
+	int fs, mode, n;
+
+	if(!file)
+		return(0);
+	mnt = file->f_vfsmnt;
+	lock_mosix();
+	if(current->mosix.dflags & DREMOTE)
+	{
+		/* well, since it is open, it MUST be a DFSA file! */
+		if(!(fs = mnt->mnt_dfsaprev) && !(fs = mnt->mnt_dfsano))
+			panic("remote loose DFSA fd");
+		unlock_mosix();
+		return(fs);
+	}
+	if(!(fs = mnt->mnt_dfsano) || dfsa_being_cancelled[fs-1])
+	{
+		unlock_mosix();
+		return(0);
+	}
+	unlock_mosix();
+	mode = file->f_dentry->d_inode->i_mode;
+	if(!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
+		return(0);
+	n = file_count(file);
+	if(n != 1)
+	{
+		/* Are all links merily our own DUPs? */
+		struct file **files = current->files->fd;
+		unsigned long *bits = current->files->open_fds->fds_bits;
+		int lim = current->files->max_fds;
+		int llim;
+
+		if(lim > current->files->max_fdset)
+			lim = current->files->max_fdset;
+		llim = (lim + BITS_PER_LONG - 1) / BITS_PER_LONG;
+		for(i = l = 0 ; l < llim ; l++)
+		if(*bits++)
+		{
+			li = i + BITS_PER_LONG;
+			if(li > lim)
+				li = lim;
+			for(; i < li ; i++)
+			if(files[i] == file && --n == 0)
+				return(fs);
+		}
+		else
+			i += BITS_PER_LONG;
+		return(0);
+	}
+	return(fs);
+}
+
+void
+dfsa_tinit(void)
+{
+	struct task_struct *p = current;
+	struct files_struct *files = p->files;
+
+	CLEAR_ALL(files, closed);
+	files->maxclosed = 0;
+	CLEAR_ALL(files, modified);
+	files->maxmod = 0;
+	p->mosix.dupdates = 0;
+	p->fs->pwd_changed = 0;
+	p->mosix.ttab = NULL;
+}
+
+/*
+ * Is it OK to accept and open a file/directory opened on the other side?
+ * A DEPUTY must always accept.
+ * A REMOTE is more reserved.
+ */
+int
+ok_to_accept_in_dfsa(int dfsano)
+{
+	struct task_struct *p = current;
+	struct vfsmount *mnt;
+	struct dfsatab *tab;
+	struct dfsdef *def;
+	unsigned int i;
+
+	MOSIX_LOCKED;
+	if(dfsano < 1 || dfsano > MAXDFSAFS || !(mnt = dfsa_mounts[dfsano-1]))
+		return(0);
+	if(!(p->mosix.dflags & DREMOTE))
+		return(1);
+	if(dfsa_disabled)
+		return(0);
+	if(!(tab = p->mosix.ttab))
+		return(0);
+	if(dfsa_being_cancelled[dfsano-1])
+		return(0);
+	if(mnt->mnt_dfsaprev)
+		return(0);
+	for(def = tab->dfsdef , i = 0 ; i < tab->ndefs ; i++ , def++)
+	if(def->defno == dfsano)
+		return(1);
+	return(0);
+}
+
+void
+reconstruct(int dfsano, void *info, int infolen, struct vfsmount **mnt,
+							struct dentry **dp)
+{
+	char comma;
+
+	lock_mosix();
+	if(!ok_to_accept_in_dfsa(dfsano))
+	{
+		unlock_mosix();
+		goto bad;
+	}
+	*mnt = mntget(dfsa_mounts[dfsano-1]);
+	unlock_mosix();
+	*dp = (*mnt)->mnt_sb->s_op->reconstruct(*mnt, info, infolen);
+	if(*dp)
+		return;
+	mntput(*mnt);
+	bad:
+	if(current->mosix.dflags & DREMOTE)
+	{
+		*mnt = NULL;
+		*dp = NULL;
+		return;
+	}
+	printk("%s: Failed to reopen DFSA file (dfsano=%d, info",
+						desc_mostask(NULL), dfsano);
+	comma = '=';
+	while(infolen >= sizeof(int))
+	{
+		printk("%c%X", comma, *((int *)info++));
+		infolen -= sizeof(int);
+		comma=',';
+	}
+	printk(")\n");
+	*mnt = mntget(current->fs->rootmnt);
+	*dp = dget(bad_deputy_dfsaentry);
+}
+
+void
+dfsa_file_install(int fd, mode_t mode, loff_t pos, unsigned int flags,
+					int dfsano, void *info, int infolen)
+{
+	struct vfsmount *mnt;
+	struct dentry *dp;
+	register struct file *fp;
+	register struct inode *ip;
+	struct files_struct *files = current->files;
+	int failure;
+
+	reconstruct(dfsano, info, infolen, &mnt, &dp);
+	if(!dp)	/* (can only happen on REMOTE) */
+		return;
+	if(atomic_read(&files->users) != 1)
+		panic("dfsa_file_install: sharing");
+	write_lock(&files->file_lock);
+	failure = (fd >= files->max_fdset && expand_fdset(files, fd));
+	write_unlock(&files->file_lock);
+	if(failure)
+		goto bad1;
+	if((fp = get_empty_filp()))
+	{
+		fp->f_dentry = dp;
+		fp->f_vfsmnt = mnt;
+		ip = dp->d_inode;
+		fp->f_op = fops_get(ip->i_fop);
+		if((fp->f_op && fp->f_op->open && fp->f_op->open(ip, fp)))
+		{
+			fput(fp);
+			goto bad;
+		}
+		flags &= ~O_NOWRITEACCESS;
+		if(mode & FMODE_WRITE)
+		{
+			if(get_write_access(ip))
+				flags |= O_NOWRITEACCESS;
+		}
+		fp->f_flags = flags;
+		fp->f_pos = pos;
+		fp->f_mode = mode;
+		fp->f_reada = 0;
+		write_lock(&files->file_lock);
+		files->fd[fd] = fp;
+		FD_SET(fd, files->open_fds);
+		FD_CLR(fd, files->close_on_exec);
+		write_unlock(&files->file_lock);
+		/* the following "should not" happen, but it could due to an
+		 * inconsistency in the file-system - at least we must now
+		 * instruct our REMOTE to stop using that file!
+		 */
+		if((current->mosix.dflags & DDEPUTY) && !can_dfsa_file(fd))
+			dfsa_close_file(fd);
+	}
+	else
+	{
+		bad1:
+		dput(dp);
+		mntput(mnt);
+		bad:
+		if(!(current->mosix.dflags & DREMOTE))
+			printk("%s: Failed to allocate DFSA file for reopen\n",
+				desc_mostask(NULL));
+	}
+}
+
+void
+deputy_resync_dfsa(void)
+{
+	register struct task_struct *p = current;
+	char *update;
+	int sz;
+
+	again:
+	p->mosix.dupdates |= DFSA_UPDATE;
+	clear_dfsasync();
+	if(CAN_DFSA(p) && (update = deputy_pack_dfsa_changes(&sz)))
+	{
+		if(deputy_request(DEP_DFSA_CHANGES, &sz, sizeof(sz),
+							update, sz, 0, NULL, 0))
+			deputy_communication_failed();
+		kfree(update);
+		if(process_told(p, DREQ_DFSASYNC)) /* a new one (race) */
+			goto again;
+	}
+	else if(deputy_request(DEP_DFSA_CLEAR, NULL, 0, NULL, 0, 0, NULL, 0))
+		deputy_communication_failed();
+}
+
+void
+remote_clear_dfsa(void)
+{
+	register struct task_struct *p = current;
+	extern void close_files(struct files_struct *);
+
+	if(p->mosix.ttab)
+	{
+		kfree(p->mosix.ttab);
+		p->mosix.ttab = NULL;
+	}
+	close_files(p->files);
+	CLEAR_ALL(p->files, open_fds);
+	p->files->next_fd = 0;
+	if(p->fs->pwd)
+	{
+		dput(p->fs->pwd);
+		p->fs->pwd = NULL;
+		mntput(p->fs->pwdmnt);
+		p->fs->pwdmnt = NULL;
+	}
+}
+
+int
+dfsa_optimized_read(struct file *f, loff_t off, unsigned long addr,
+							unsigned long len)
+{
+	struct task_struct *p = current;
+	struct read_yourself_h r;
+	struct vfsmount *mnt;
+	char data[MAX_IDENT_RECORD_LEN];
+	int result;
+
+	if(!(p->mosix.dflags & DDEPUTY) || !CAN_DFSA(p))
+		goto read;
+	mnt = f->f_vfsmnt;
+	lock_mosix();
+	if(!(r.dfsano = mnt->mnt_dfsano) || dfsa_being_cancelled[r.dfsano-1])
+	{
+		unlock_mosix();
+		goto read;
+	}
+	unlock_mosix();
+	if(!(r.infolen = mnt->mnt_sb->s_op->identify(f->f_dentry, data)))
+		goto read;
+	r.off = off;
+	r.addr = addr;
+	r.len = len;
+	if(deputy_request(DEP_READ_YOURSELF, &r, sizeof(r), data, r.infolen, 0,
+		(void **)&result, -sizeof(result)))
+	{
+		deputy_communication_failed();
+		return(-EIO);
+	}
+	if(result == -ENOENT)
+	{
+		read:
+		return(f->f_op->read(f, (char *)addr, len, &off));
+	}
+	return(result);
+}
+
+int
+remote_read_yourself(struct read_yourself_h *r)
+{
+	int result = -ENOENT;
+	char data[MAX_IDENT_RECORD_LEN];
+	struct dentry *dp;
+	struct vfsmount *mnt;
+	struct file file;
+	struct inode *ip;
+
+	if(r->infolen > MAX_IDENT_RECORD_LEN ||
+		verify_area(VERIFY_WRITE, (char *)r->addr, r->len))
+	{
+		comm_flushdata(COMM_ALLDATA);
+		goto reply;
+	}
+	if(comm_copydata(data, r->infolen, 0))
+		goto reply;
+	reconstruct(r->dfsano, data, r->infolen, &mnt, &dp);
+	if(!dp)
+		goto reply;
+	ip = dp->d_inode;
+	if(ip->i_fop && ip->i_fop->read && !init_private_file(&file, dp, 1))
+	{
+		result = file.f_op->read(&file, (char *)r->addr, r->len,
+								&r->off);
+		if(file.f_op->release)
+			file.f_op->release(ip, &file);
+	}
+	dput(dp);
+	mntput(mnt);
+	reply:
+	comm_free(r);
+	result = comm_send(DEP_READ_YOURSELF|REPLY, &result, sizeof(int),
+								NULL, 0, 0);
+	return(result);
+}
+
+int
+enter_remote_dfsa_mode(void)
+{
+	struct task_struct *p = current;
+
+	if(!p->mosix.ttab)
+		return(0);
+	spin_lock_irq(&runqueue_lock);	/* ensures DREQ_EXITDFSA not lost */
+	p->mosix.dflags |= DREMOTEDFSA;
+	spin_unlock_irq(&runqueue_lock);
+	if(remote_deputy_has_something_for_us(p) ||
+		remote_need_while_asleep(p) ||
+		(process_told(p, (DREQ_DFSASYNC|DREQ_NOTUPTODATE))) ||
+		(p->mosix.dflags & DFAKESIGNAL))
+	{
+		leave_remote_dfsa_mode();
+		return(0);
+	}
+	return(1);
+}
+
+void
+leave_remote_dfsa_mode(void)
+{
+	register struct task_struct *p = current;
+
+	spin_lock_irq(&runqueue_lock);	/* ensures no new "DREQ_EXITDFSA" */
+	p->mosix.dflags &= ~(DREMOTEDFSA|DFAKESIGNAL);
+	spin_unlock_irq(&runqueue_lock);
+	process_ack(p, DREQ_EXITDFSA);
+	spin_lock_irq(&p->sigmask_lock);
+	p->sigpending = 0;
+	spin_unlock_irq(&p->sigmask_lock);
+}
+
+void
+dfsa_syscall_on_file(int fd, int touching)
+{
+	register struct task_struct *p = current;
+	static unsigned char rand;
+
+	if(!(p->mosix.dflags & (DDEPUTY|DREMOTE)) && CAN_DFSA(p) &&
+				(fd >= p->files->max_fds || can_dfsa_file(fd)))
+		p->mosix.dflags |= DSTATSDOWN;
+
+	/* consider a remote process that with regard to this file only runs a
+	 * combination of fstat(), fcntl(F_GETFL), fchdir(), fchmod(), fchown(),
+	 * fsync() and ftrunc() - but does lots of the above: if its parent
+	 * initially held the file open, but not any more, there is no other
+	 * way that the son will become aware of the fact that it may now do
+	 * all those things remotely.  Adding a file-flag on close is not very
+	 * helpful because a chain of relatives may be constantly closing this
+	 * file (or simply exiting).  On the other hand, running CAN_DFSA +
+	 * can_dfsa_file + dfsa_touch_file (including its communication
+	 * overhead) is expensive.
+	 * The compromise is to run them at random, once in about 256 times,
+	 * and eventually the process will come to know.
+	 */
+	if(touching || ((p->mosix.dflags & DDEPUTY) && !rand++ &&
+		CAN_DFSA(p) && can_dfsa_file(fd)))
+		dfsa_touch_file(fd);
+}
+
+void
+dfsa_exit(void)
+{
+	struct task_struct *p = current;
+
+	if(process_told(p, DREQ_DFSASYNC))
+		clear_dfsasync();
+	if(p->mosix.ttab)
+	{
+		kfree(p->mosix.ttab);
+		p->mosix.ttab = NULL;
+	}
+}
+
+/*** PACKING/UNPACKING UPDATES SECTION ***/
+
+enum
+{
+	/* general info: */
+	REC_CREDITS, REC_UMASK, REC_SELECT, REC_DFSATAB,
+	/* current directory */
+	REC_CDIR,
+	/* file table */
+	REC_MAX, REC_USED,
+	/* individual files */
+	REC_CLOSED, REC_NONDFSA, REC_FILE, REC_MOD, REC_DUP
+};
+
+struct credits_rec
+{
+	uid_t uid, euid, suid, fsuid;
+	gid_t gid, egid, sgid, fsgid;
+	int ngroups;
+	gid_t groups[NGROUPS];
+};
+
+/* the following is defined even if MFS is not configured,
+ * because it may possibly be configured by the peer node! */
+struct select_rec
+{
+	int selected;
+	int lastexec;
+	int lastmagic;
+};
+
+struct cdir_rec
+{
+	int dfsano;
+	int infolen;
+};
+
+struct max_rec
+{
+	int max_fds;
+	int max_fdset;
+};
+
+struct file_rec
+{
+	short fd;
+	mode_t mode;
+	loff_t pos;
+	unsigned int flags;
+	int dfsano;
+	int infolen;
+};
+
+struct mod_rec
+{
+	short fd;
+	mode_t mode;
+	loff_t pos;
+	unsigned int flags;
+};
+
+struct dup_rec
+{
+	short fd;
+	short orig;
+};
+
+static char *
+add_changes_record(char *old, char type, void *add, int addlen)
+{
+	char *rec;
+	int sz, minsz;
+
+	again:
+	if(old)
+	{
+		minsz = ((int *)old)[1] + sizeof(type) + addlen;
+		if(((int *)old)[0] < minsz)
+		{
+			sz = 2 * minsz;
+			if((sz & PAGE_MASK) >= minsz)
+				sz &= PAGE_MASK;
+			if(!(rec = kmalloc(sz, GFP_KERNEL)))
+			{
+				sz = minsz;
+				if(!(rec = kmalloc(sz, GFP_KERNEL)))
+				{
+					kfree(old);
+					return(NULL);
+				}
+			}
+			memcpy(rec, old, ((int *)old)[1]);
+			((int *)rec)[0] = sz;
+			kfree(old);
+			old = rec;
+			if(type == REC_DFSATAB)/* make sure it is still valid */
+			{
+				if(addlen < dfsatab->len)
+					goto again;
+				add = dfsatab;
+				addlen = dfsatab->len;
+			}
+		}
+		old[((int *)old)[1]] = type;
+		memcpy(old+((int *)old)[1] + sizeof(type), (char *)add, addlen);
+		((int *)old)[1] += addlen + sizeof(type);
+		return(old);
+	}
+	else
+	{
+		minsz = 2 * sizeof(int) + sizeof(type) + addlen;
+		sz = 2 * sizeof(int) + 3 * (addlen + sizeof(type));
+		if((sz & PAGE_MASK) >= minsz)
+			sz &= PAGE_MASK;
+		if(!(rec = kmalloc(sz, GFP_KERNEL)))
+		{
+			sz = minsz;
+			if(!(rec = kmalloc(sz, GFP_KERNEL)))
+				return(NULL);
+		}
+		((int *)rec)[0] = sz;
+		if(type == REC_DFSATAB)	/* make sure it is still valid */
+		{
+			if(addlen < dfsatab->len)
+			{
+				kfree(rec);
+				goto again;
+			}
+			add = dfsatab;
+			addlen = dfsatab->len;
+		}
+		((int *)rec)[1] = 2 * sizeof(int) + sizeof(type) + addlen;
+		rec[2*sizeof(int)] = type;
+		memcpy(rec+2*sizeof(int) + sizeof(type), (char *)add, addlen);
+		return(rec);
+	}
+}
+
+static void *
+get_record(char *buf, int *type)
+{
+	int pos = ((int *)buf)[0];
+	int tot = ((int *)buf)[1];
+	void *ret;
+
+	if(pos == 0)		/* "all done" mark */
+	{
+		all_done:
+		kfree(buf);
+		return(NULL);
+	}
+	if(pos >= tot)		/* first call */
+		pos = 2 * sizeof(int);
+	*type = buf[pos++];
+	ret = buf + pos;
+	switch(*type)
+	{
+	case REC_CREDITS:
+		pos += sizeof(struct credits_rec);
+		break;
+	case REC_UMASK:
+		pos += sizeof(int);
+		break;
+	case REC_SELECT:
+		pos += sizeof(struct select_rec);
+		break;
+	case REC_DFSATAB:
+		pos += ((struct dfsatab *)ret)->len;
+		break;
+	case REC_CDIR:
+		pos += sizeof(struct cdir_rec) +
+			((struct cdir_rec *)ret)->infolen;
+		break;
+	case REC_MAX:
+		pos += sizeof(struct max_rec);
+		break;
+	case REC_CLOSED:
+	case REC_NONDFSA:
+		pos += sizeof(int);
+		break;
+	case REC_FILE:
+		pos += sizeof(struct file_rec) +
+			((struct file_rec *)ret)->infolen;
+		break;
+	case REC_MOD:
+		pos += sizeof(struct mod_rec);
+		break;
+	case REC_DUP:
+		pos += sizeof(struct dup_rec);
+		break;
+	case REC_USED:
+		if((current->mosix.dflags & DDEPUTY) ||
+		   current->mosix.ttab)
+			pos += current->files->max_fdset / 8;
+		else
+			/* we can't be sure about size - and it does not matter
+			   anyway: an expansion must have failed earlier */
+			goto all_done;
+		break;
+	default:
+		printk("buf = 0x%x, type=%d\n", (int)buf, *type);
+		panic("get_record");
+	}
+	((int *)buf)[0] = (pos >= tot) ? 0 : pos;
+	return(ret);
+}
+
+int
+add_closed_files(char **bufp)
+{
+	int i;
+	unsigned long bit = 1;
+	register struct files_struct *files = current->files;
+	unsigned long *mask = files->closed->fds_bits;
+	unsigned long bits = *mask;
+	char *buf = *bufp;
+
+	*mask = 0;
+	for(i = 0 ; i < files->maxclosed ; i++)
+	{
+		if((bits & bit) && !(buf =
+			add_changes_record(buf, REC_CLOSED, &i, sizeof(i))))
+		{
+			*bufp = NULL;
+			return(-ENOMEM);
+		}
+		bits &= ~bit;
+		if(bits)
+			bit <<= 1;
+		else
+		{
+			i = (i + __NFDBITS) & ~(__NFDBITS-1);
+			bit = 1;
+			while(1)
+			{
+				if(i >= files->maxclosed - 1)
+					break;
+				bits = *(++mask);
+				*mask = 0;
+				if(bits)
+					break;
+				i += __NFDBITS;
+			}
+		}
+	}
+	files->maxclosed = 0;
+	*bufp = buf;
+	return(0);
+}
+
+int
+add_opened_files(char **bufp)
+{
+	int i, j, dfsano;
+	struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	unsigned long *mask = files->opened->fds_bits;
+	unsigned long bits = *mask;
+	unsigned long bit = 1;
+	struct
+	{
+		struct file_rec f;
+		char info[MAX_IDENT_RECORD_LEN];
+	} fplus;
+	struct dup_rec d;
+	struct file **fds = files->fd;
+	char *buf = *bufp;
+	struct dentry *dp;
+
+	*mask = 0;
+	for(i = 0 ; i < files->maxopened ; i++)
+	{
+		if(!(bits & bit))
+			goto file_done;
+		if(!fds[i])
+		{
+			if(p->mosix.dflags & DREMOTE)
+			/* tell DEPUTY that REMOTE needs full file-info */
+				goto non_dfsa;
+			goto file_done;
+		}
+		if(!(dfsano = can_dfsa_file(i)))
+		{
+			non_dfsa:
+			if(!(buf = add_changes_record(buf, REC_NONDFSA, &i,
+								sizeof(i))))
+			{
+				fail:
+				return(-ENOMEM);
+			}
+			goto file_done;
+		}
+		if(file_count(fds[i]) > 1)
+		for(j = 0 ; j < i ; j++)
+		if(fds[j] == fds[i])
+		{
+			d.fd = i;
+			d.orig = j;
+			buf = add_changes_record(buf, REC_DUP, &d, sizeof(d));
+			if(!buf)
+				goto fail;
+			goto file_done;
+		}
+		dp = fds[i]->f_dentry;
+		fplus.f.infolen = fds[i]->f_vfsmnt->mnt_sb->s_op->identify(
+						fds[i]->f_dentry, &fplus.info);
+		if(!fplus.f.infolen)
+			goto fail;
+		fplus.f.fd = i;
+		fplus.f.mode = fds[i]->f_mode;
+		fplus.f.pos = fds[i]->f_pos;
+		fplus.f.flags = fds[i]->f_flags;
+		fplus.f.dfsano = dfsano;
+		if(!(buf = add_changes_record(buf, REC_FILE, &fplus,
+				sizeof(struct file_rec) + fplus.f.infolen)))
+			goto fail;
+		file_done:
+		bits &= ~bit;
+		if(bits)
+			bit <<= 1;
+		else
+		{
+			i = (i + __NFDBITS) & ~(__NFDBITS-1);
+			bit = 1;
+			while(1)
+			{
+				if(i >= files->maxmod - 1)
+					break;
+				bits = *(++mask);
+				*mask = 0;
+				if(bits)
+					break;
+				i += __NFDBITS;
+			}
+		}
+	}
+	files->maxmod = 0;
+	*bufp = buf;
+	return(0);
+}
+
+int
+add_modified_files(char **bufp)
+{
+	int i;
+	unsigned int j;
+	struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	unsigned long *mask = files->modified->fds_bits;
+	unsigned long bits = *mask;
+	unsigned long bit = 1;
+	struct mod_rec m;
+	struct file **fds = files->fd;
+	char *buf = *bufp;
+
+	*mask = 0;
+	for(i = 0 ; i < files->maxmod ; i++)
+	{
+		if(!(bits & bit) || !fds[i])
+			goto file_done;
+		if(!can_dfsa_file(i))
+		{
+			if(!(buf = add_changes_record(buf, REC_NONDFSA,
+							&i, sizeof(i))))
+			{
+				fail:
+				return(-ENOMEM);
+			}
+			goto file_done;
+		}
+		if(file_count(fds[i]) > 1)
+		for(j = 0 ; j < i ; j++)
+		if(fds[j] == fds[i])	/* touched one - touched all! */
+			goto file_done;
+		m.fd = i;
+		m.mode = fds[i]->f_mode;
+		m.pos = fds[i]->f_pos;
+		m.flags = fds[i]->f_flags;
+		if(!(buf = add_changes_record(buf, REC_MOD, &m, sizeof(m))))
+			goto fail;
+		file_done:
+		bits &= ~bit;
+		if(bits)
+			bit <<= 1;
+		else
+		{
+			i = (i + __NFDBITS) & ~(__NFDBITS-1);
+			bit = 1;
+			while(1)
+			{
+				if(i >= files->maxmod - 1)
+					break;
+				bits = *(++mask);
+				*mask = 0;
+				if(bits)
+					break;
+				i += __NFDBITS;
+			}
+		}
+	}
+	files->maxmod = 0;
+	*bufp = buf;
+	return(0);
+}
+
+char *
+deputy_pack_dfsa_changes(int *retsz)
+{
+	char *buf = NULL;
+	register struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	register unsigned int i;
+	register uint32_t updates;
+
+	if(files->count_dropped_to_one || current->fs->count_dropped_to_one ||
+		(process_told(p, DREQ_NOTUPTODATE)))
+	{
+		/* so this is the first time after a while that CAN_DFSA */
+		/* was TRUE: changes might have occured by our "partners" */
+		/* so we must assume that our REMOTE does not know anything */
+		/* (or its knowledge is obsolete) */
+		
+		files->count_dropped_to_one = 0;
+		p->fs->count_dropped_to_one = 0;
+		process_ack(p, DREQ_NOTUPTODATE);
+		p->mosix.dupdates |= DFSA_UPDATE;
+	}
+	if(!(updates = (p->mosix.dupdates & DFSA_UPDATE)))
+		goto out;
+	if(updates & DFSA_UPDCRED)
+	{
+		struct credits_rec c;
+
+		c.uid = p->uid;
+		c.euid = p->euid;
+		c.suid = p->suid;
+		c.fsuid = p->fsuid;
+		c.gid = p->gid;
+		c.egid = p->egid;
+		c.sgid = p->sgid;
+		c.fsgid = p->fsgid;
+		/* dirty compatibility-keeper: */
+		c.ngroups = p->ngroups;
+		for(i = 0 ; i < c.ngroups ; i++)
+			c.groups[i] = p->groups[i];
+		if(!(buf = add_changes_record(buf, REC_CREDITS, &c, sizeof(c))))
+		{
+			fail:
+			*retsz = -ENOMEM;
+			return(NULL);
+		}
+	}
+	if(updates & DFSA_UPDUMASK)
+	{
+		if(!(buf = add_changes_record(buf, REC_UMASK, &p->fs->umask,
+								sizeof(int))))
+			goto fail;
+	}
+#ifdef CONFIG_MOSIX_FS
+	if(updates & DFSA_UPDSEL)
+	{
+		struct select_rec s;
+
+		s.selected = p->mosix.selected;
+		s.lastexec = p->mosix.lastexec;
+		s.lastmagic = p->mosix.lastmagic;
+		if(!(buf = add_changes_record(buf, REC_SELECT, &s, sizeof(s))))
+			goto fail;
+	}
+#endif /* CONFIG_MOSIX_FS */
+	if(updates & DFSA_UPDTABLE)
+	{
+		if(!(buf = add_changes_record(buf, REC_DFSATAB, dfsatab,
+								dfsatab->len)))
+			goto fail;
+		/* this causes the REMOTE to flush all it knows, so: */
+		updates |= (DFSA_UPDCDIR|DFSA_UPDMAX|DFSA_UPDMODS|DFSA_UPDUSED);
+		memcpy(files->modified, files->open_fds, files->max_fdset / 8);
+		files->maxmod = (files->max_fds > files->max_fdset) ?
+					files->max_fdset : files->max_fds;
+		updates &= ~DFSA_UPDCLOSE;	/* all will be closed anyway */
+		CLEAR_ALL(files, closed);
+		files->maxclosed = 0;
+	}
+	if(updates & DFSA_UPDCDIR)
+	{
+		struct
+		{
+			struct cdir_rec c;
+			char info[MAX_IDENT_RECORD_LEN];
+		} cplus;
+		struct vfsmount *mnt = p->fs->pwdmnt;
+
+		if((cplus.c.dfsano = mnt->mnt_dfsano))
+			cplus.c.infolen = mnt->mnt_sb->s_op->identify(
+							p->fs->pwd, cplus.info);
+		else
+			cplus.c.infolen = 0;
+		buf = add_changes_record(buf, REC_CDIR, &cplus,
+					sizeof(cplus.c) + cplus.c.infolen);
+		if(!buf)
+			goto fail;
+	}
+	if(updates & DFSA_UPDMAX)
+	{
+		struct max_rec m;
+
+		m.max_fds = files->max_fds;
+		m.max_fdset = files->max_fdset;
+		if(!(buf = add_changes_record(buf, REC_MAX, &m, sizeof(m))))
+			goto fail;
+	}
+	if(updates & DFSA_UPDCLOSE)
+	{
+		if(add_closed_files(&buf))
+			goto fail;
+	}
+	if(updates & DFSA_UPDOPEN)
+	{
+		if(add_opened_files(&buf))
+			goto fail;
+	}
+	if(updates & DFSA_UPDMODS)
+	{
+		if(add_modified_files(&buf))
+			goto fail;
+	}
+	if(updates & DFSA_UPDUSED)
+	{
+		if(!(buf = add_changes_record(buf, REC_USED,
+			files->open_fds, files->max_fdset / 8)))
+			goto fail;
+	}
+	current->mosix.dupdates &= ~DFSA_UPDATE;
+	out:
+	*retsz = buf ? ((int *)buf)[1] : 0;
+	return(buf);
+}
+
+static void
+close_remote_fd(int fd, int code)
+{
+	register struct files_struct *files = current->files;
+	register struct file *fp = files->fd[fd];
+
+	/* no locking is required, since files->users is always 1 */
+	if(fp)
+	{
+		files->fd[fd] = NULL;
+		filp_close(fp, files);
+	}
+	if(code == REC_CLOSED)
+	{
+		FD_CLR(fd, files->open_fds);
+		if(fd < files->next_fd)
+			files->next_fd = fd;
+	}
+	else
+		FD_SET(fd, files->open_fds);
+}
+
+void
+remote_unpack_dfsa_changes(char *changes)
+{
+	int type;
+	void *rec;
+	register struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	register int i, j;
+	int dfsano;
+	struct file *fp;
+	struct dfsatab *tab;
+	mode_t mode;
+	loff_t pos;
+	unsigned int flags;
+	void *info;
+	int infolen;
+	gid_t *grp;
+
+	deeper_sleep();
+	while((rec = get_record(changes, &type)))
+		switch(type)
+		{
+		case REC_CREDITS:
+			p->uid = ((struct credits_rec *)rec)->uid;
+			p->euid = ((struct credits_rec *)rec)->euid;
+			p->suid = ((struct credits_rec *)rec)->suid;
+			p->fsuid = ((struct credits_rec *)rec)->fsuid;
+			p->gid = ((struct credits_rec *)rec)->gid;
+			p->egid = ((struct credits_rec *)rec)->egid;
+			p->sgid = ((struct credits_rec *)rec)->sgid;
+			p->fsgid = ((struct credits_rec *)rec)->fsgid;
+			p->ngroups = ((struct credits_rec *)rec)->ngroups;
+			grp = ((struct credits_rec *)rec)->groups;
+			for(i = 0 ; i < p->ngroups ; i++)
+				p->groups[i] = *grp++;
+			break;
+		case REC_UMASK:
+			p->fs->umask = *((int *)rec);
+			break;
+		case REC_SELECT:
+#ifdef CONFIG_MOSIX_FS
+			p->mosix.selected =
+				((struct select_rec *)rec)->selected;
+			p->mosix.lastexec =
+				((struct select_rec *)rec)->lastexec;
+			p->mosix.lastmagic =
+				((struct select_rec *)rec)->lastmagic;
+#endif /* CONFIG_MOSIX_FS */
+			break;
+		case REC_DFSATAB:
+			remote_clear_dfsa();
+			i = ((struct dfsatab *)rec)->len;
+			if(!(tab = kmalloc(i, GFP_KERNEL)))
+				break;
+			memcpy((caddr_t)tab, (caddr_t)rec, i);
+			dfsa_adapt(tab);
+			p->mosix.ttab = tab;
+			process_ack(p, DREQ_NOTUPTODATE);
+			break;
+		case REC_CDIR:
+			if(p->fs->pwd)
+			{
+				dput(p->fs->pwd);
+				p->fs->pwd = NULL;
+				mntput(p->fs->pwdmnt);
+				p->fs->pwdmnt = NULL;
+			}
+			if(!(dfsano = ((struct cdir_rec *)rec)->dfsano))
+				break;
+			info = (void *)(((char *)rec)+sizeof(struct cdir_rec));
+			infolen = ((struct cdir_rec *)rec)->infolen;
+			reconstruct(dfsano, info, infolen, &p->fs->pwdmnt,
+				    &p->fs->pwd);
+			break;
+		case REC_MAX:
+			i = ((struct max_rec *)rec)->max_fdset;
+			j = ((struct max_rec *)rec)->max_fds;
+			write_lock(&files->file_lock);
+			i = ((i > files->max_fdset && expand_fdset(files, i-1))
+			     ||
+			     (j > files->max_fds && expand_fd_array(files, j-1)));
+			write_unlock(&files->file_lock);
+			if(i)
+			{
+				remote_clear_dfsa();
+				tell_process(p, DREQ_NOTUPTODATE);
+			}
+			break;
+		case REC_CLOSED:
+		case REC_NONDFSA:
+			if(current->mosix.ttab)
+				close_remote_fd(*((int *)rec), type);
+			break;
+		case REC_FILE:
+			if(!current->mosix.ttab)
+				break;
+			i = ((struct file_rec *)rec)->fd;
+			mode = ((struct file_rec *)rec)->mode;
+			pos = ((struct file_rec *)rec)->pos;
+			flags = ((struct file_rec *)rec)->flags;
+			if(p->files->fd[i])
+			{
+				close_remote_fd(i, REC_FILE);
+			}
+			dfsano = ((struct file_rec *)rec)->dfsano;
+			info = (void *)(((char *)rec)+sizeof(struct file_rec));
+			infolen = ((struct file_rec *)rec)->infolen;
+			dfsa_file_install(i, mode, pos, flags, dfsano, info,
+					  infolen);
+			/* even if we failed, file was still opened on DEPUTY */
+			FD_SET(i, files->open_fds);
+			break;
+		case REC_MOD:
+			if(!current->mosix.ttab)
+				break;
+			i = ((struct file_rec *)rec)->fd;
+			if(!(fp = p->files->fd[i]))
+			{
+				/* asking DEPUTY to send REC_FILE */
+				p->mosix.dupdates |= DFSA_UPDOPEN;
+				if(i >= files->maxopened)
+					files->maxopened = i + 1;
+				FD_SET(i, files->opened);
+				break;
+			}
+			mode = ((struct file_rec *)rec)->mode;
+			pos = ((struct file_rec *)rec)->pos;
+			flags = ((struct file_rec *)rec)->flags;
+			fp->f_mode = mode;
+			fp->f_pos = pos;
+			fp->f_flags = flags;
+			break;
+		case REC_DUP:
+			if(!current->mosix.ttab)
+				break;	/* previous expanding-failure */
+			i = ((struct dup_rec *)rec)->fd;
+			close_remote_fd(i, REC_DUP);
+			if((fp = files->fd[((struct dup_rec *)rec)->orig]))
+			{
+				get_file(fp);
+				current->files->fd[i] = fp;
+			}
+			break;
+		case REC_USED:
+			if(!current->mosix.ttab)
+				break;	/* previous expanding-failure */
+			memcpy((caddr_t)files->open_fds, (caddr_t)rec,
+			       files->max_fdset / 8);
+			break;
+		}
+	lighter_sleep();
+}
+
+char *
+remote_pack_dfsa_changes(int *retsz)
+{
+	char *buf = NULL;
+	register struct task_struct *p = current;
+	register uint32_t updates;
+
+	if(!(updates = (p->mosix.dupdates & DFSA_UPDATE)))
+		goto out;
+	/* NOTE: we do not allow max_fds or max_fdset to grow REMOTELY,
+	 * so we do not act on this flag here */
+#ifdef CONFIG_MOSIX_FS
+	if(updates & DFSA_UPDSEL)
+	{
+		struct select_rec s;
+
+		s.selected = p->mosix.selected;
+		s.lastexec = p->mosix.lastexec;
+		s.lastmagic = p->mosix.lastmagic;
+		if(!(buf = add_changes_record(buf, REC_SELECT, &s, sizeof(s))))
+			goto fail;
+	}
+#endif /* CONFIG_MOSIX_FS */
+	if((updates & DFSA_UPDCDIR) && p->fs->pwd)
+	{
+		struct
+		{
+			struct cdir_rec c;
+			char info[MAX_IDENT_RECORD_LEN];
+		} cplus;
+		struct vfsmount *mnt = p->fs->pwdmnt;
+
+		lock_mosix();
+		if(!(cplus.c.dfsano = mnt->mnt_dfsaprev ? : mnt->mnt_dfsano))
+			panic("REMOTE non-DFSA cdir");
+		unlock_mosix();
+		cplus.c.infolen = mnt->mnt_sb->s_op->identify(p->fs->pwd,
+								cplus.info);
+		buf = add_changes_record(buf, REC_CDIR, &cplus,
+					sizeof(cplus.c) + cplus.c.infolen);
+		if(!buf)
+			goto fail;
+	}
+	if(updates & DFSA_UPDCLOSE)
+	{
+		if(add_closed_files(&buf))
+		{
+			fail:
+			*retsz = -ENOMEM;
+			return(NULL);
+		}
+	}
+	if(updates & DFSA_UPDOPEN)
+	{
+		if(add_opened_files(&buf))
+			goto fail;
+	}
+	if(updates & DFSA_UPDMODS)
+	{
+		if(add_modified_files(&buf))
+			goto fail;
+	}
+	p->mosix.dupdates &= ~DFSA_UPDATE;
+	out:
+	*retsz = buf ? ((int *)buf)[1] : 0;
+	return(buf);
+}
+
+static void
+close_deputy_fd(int fd)
+{
+	register struct files_struct *files = current->files;
+	register struct file *fp;
+
+	/* files->users must be 1, but we lock against /proc/{mypid}/fd */
+	write_lock(&files->file_lock);
+	if((fp = files->fd[fd]))
+	{
+		files->fd[fd] = NULL;
+		FD_CLR(fd, files->open_fds);
+		FD_CLR(fd, files->close_on_exec);
+		if(fd < files->next_fd)
+			files->next_fd = fd;
+		filp_close(fp, files);
+	}
+	write_unlock(&files->file_lock);
+}
+
+void
+deputy_unpack_dfsa_changes(char *changes)
+{
+	int type;
+	void *rec;
+	register struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	register int i;
+	int dfsano;
+	struct file *fp;
+	void *info;
+	int infolen;
+	mode_t mode;
+	loff_t pos;
+	unsigned int flags;
+
+	deeper_sleep();
+	while((rec = get_record(changes, &type)))
+		switch(type)
+		{
+		case REC_SELECT:
+#ifdef CONFIG_MOSIX_FS
+			p->mosix.selected =
+				((struct select_rec *)rec)->selected;
+			p->mosix.lastexec =
+				((struct select_rec *)rec)->lastexec;
+			p->mosix.lastmagic =
+				((struct select_rec *)rec)->lastmagic;
+#endif /* CONFIG_MOSIX_FS */
+			break;
+		case REC_CDIR:
+			dfsano = ((struct cdir_rec *)rec)->dfsano;
+			info = (void *)(((char *)rec)+sizeof(struct cdir_rec));
+			infolen = ((struct cdir_rec *)rec)->infolen;
+			write_lock(&p->fs->lock);
+			dput(p->fs->pwd);
+			p->fs->pwd = NULL;
+			mntput(p->fs->pwdmnt);
+			p->fs->pwdmnt = NULL;
+			reconstruct(dfsano, info, infolen, &p->fs->pwdmnt,
+				    &p->fs->pwd);
+			write_unlock(&p->fs->lock);
+			break;
+		case REC_CLOSED:
+			i = *((int *)rec);
+			close_deputy_fd(i);
+			break;
+		case REC_FILE:
+			i = ((struct file_rec *)rec)->fd;
+			mode = ((struct file_rec *)rec)->mode;
+			pos = ((struct file_rec *)rec)->pos;
+			flags = ((struct file_rec *)rec)->flags;
+			if((fp = files->fd[i]))
+				/* only a change (or we would have to close first!) */
+			{
+				close_deputy_fd(i);
+			}
+			dfsano = ((struct file_rec *)rec)->dfsano;
+			info = (void *)(((char *)rec)+sizeof(struct file_rec));
+			infolen = ((struct file_rec *)rec)->infolen;
+			dfsa_file_install(i, mode, pos, flags, dfsano, info,
+					  infolen);
+			break;
+		case REC_NONDFSA:
+			/* this is a request for fuller info */
+			i = *((int *)rec);
+			p->mosix.dupdates |= DFSA_UPDOPEN;
+			if(i >= files->maxopened)
+				files->maxopened = i + 1;
+			FD_SET(i, files->opened);
+			FD_CLR(i, files->modified);
+			break;
+		case REC_MOD:
+			i = ((struct file_rec *)rec)->fd;
+			mode = ((struct file_rec *)rec)->mode;
+			pos = ((struct file_rec *)rec)->pos;
+			flags = ((struct file_rec *)rec)->flags;
+			if(!(fp = files->fd[i]))
+				break;
+			fp->f_mode = mode;
+			fp->f_pos = pos;
+			fp->f_flags = flags;
+			break;
+		case REC_DUP:
+			i = ((struct dup_rec *)rec)->fd;
+			close_deputy_fd(i);
+			if((fp = files->fd[((struct dup_rec *)rec)->orig]))
+			{
+				write_lock(&files->file_lock);
+				FD_SET(i, files->open_fds);
+				get_file(fp);
+				files->fd[i] = fp;
+				write_unlock(&files->file_lock);
+			}
+			else
+			{
+				printk("%s: DFSA told that FD #%d is a DUP "
+				       "of FD #%d... which is NULL\n",
+				       desc_mostask(NULL), i,
+				       ((struct dup_rec *)rec)->orig);
+				dfsa_file_install(i, 0, 0, 0, 0, NULL, 0);
+			}
+			break;
+		default:
+			printk("record type = %d\n", type);
+			panic("deputy_unpack_dfsa_changes");
+		}
+	lighter_sleep();
+}
+
+void
+dfsa_check_comm_send(int *type, char **result, int *reslen)
+{
+	register struct task_struct *p = current;
+	register struct mosix_task *m = &p->mosix;
+
+	if(*type & DFSA_NOUPDATE)
+	{
+		*result = NULL;
+		*reslen = 0;
+		return;
+	}
+	if((m->dflags & (DREMOTE|DPSYNC|DINCOMING)) == DREMOTE)
+	{
+		if((*result = remote_pack_dfsa_changes(reslen)))
+			*type |= COMM_MFDFSA;
+		if(!m->ttab || (process_told(p, DREQ_NOTUPTODATE)))
+			*type |= COMM_MFNODFSA;
+		return;
+	}
+	*result = NULL;
+	*reslen = 0;
+	if(!(*type & USERMODE))
+		return;
+	if(process_told(p, DREQ_DFSASYNC))
+		clear_dfsasync();
+	if(process_told(p, DREQ_NOTUPTODATE))
+		m->dupdates |= DFSA_UPDATE;
+	if(!(m->dupdates & DFSA_UPDATE))
+		return;
+	again:
+	if(!CAN_DFSA(p))
+		goto no_dfsa;
+	*result = deputy_pack_dfsa_changes(reslen);
+	if(process_told(p, DREQ_DFSASYNC))	/* a new one (race) */
+	{
+		clear_dfsasync();
+		m->dupdates |= DFSA_UPDATE;
+		if(*result)
+			kfree(*result);
+		goto again;
+	}
+	if(*result)
+	{
+		*type |= COMM_MFDFSA;
+		return;
+	}
+	if(*reslen == 0)
+		return;
+	no_dfsa:
+	*type |= COMM_MFNODFSA;
+	*reslen = 0;
+}
+
+void
+dfsa_comm_recv(int type, char *changes)
+{
+	register struct task_struct *p = current;
+	if(type & COMM_MFNODFSA)
+	{
+		if(p->mosix.dflags & DREMOTE)
+			remote_clear_dfsa();
+		tell_process(p, DREQ_NOTUPTODATE);
+	}
+	if(type & COMM_MFDFSA)
+	{
+		if(p->mosix.dflags & DREMOTE)
+			remote_unpack_dfsa_changes(changes);
+		else
+			deputy_unpack_dfsa_changes(changes);
+	}
+}
+
+static void printset(char *title, int max, fd_set *set)
+{
+	register int i;
+
+	printk("%s (max=%d): ", title, max);
+	for(i = 0 ; i < max ; i++)
+	if(FD_ISSET(i, set))
+		printk(" %d", i);
+	printk("\n");
+}
+
+void
+dfsa_dump(int pid)
+{
+	register struct task_struct *p = current;
+	register struct files_struct *files = p->files;
+	register unsigned int i;
+	register int fs;
+	struct file *f;
+
+	if(pid)
+	{
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if(p->pid == pid || (int)p == pid)
+			break;
+		read_unlock(&tasklist_lock);
+		if(p == &init_task)
+		{
+			printk("Pid %d not found.\n", pid);
+			return;
+		}
+		files = p->files;
+	}
+	printk("%s : CAN_DFSA=%d\n", desc_mostask(&p->mosix), CAN_DFSA(p));
+	printk("Update flags:");
+	if(p->mosix.dupdates & DFSA_UPDCRED)
+		printk(" UPDCRED");
+	if(p->mosix.dupdates & DFSA_UPDSEL)
+		printk(" UPDSEL");
+	if(p->mosix.dupdates & DFSA_UPDTABLE)
+		printk(" UPDTABLE");
+	if(p->mosix.dupdates & DFSA_UPDCDIR)
+		printk(" UPDCDIR");
+	if(p->mosix.dupdates & DFSA_UPDCDIR)
+		printk(" UPDCDIR");
+	if(p->mosix.dupdates & DFSA_UPDCLOSE)
+		printk(" UPDCLOSE");
+	if(p->mosix.dupdates & DFSA_UPDMODS)
+		printk(" UPDMODS");
+	if(p->mosix.dupdates & DFSA_UPDUSED)
+		printk(" UPDUSED");
+	printk("\n");
+	printset("Files to close", files->maxclosed, files->closed);
+	printset("Files to modify", files->maxmod, files->modified);
+	if(p->mosix.ttab)
+		printk("DFSA table at 0x%x of size %d\n",
+			(int)p->mosix.ttab, p->mosix.ttab->len);
+	else
+		printk("No DFSA table.\n");
+	printset("Open files", p->files->max_fdset, p->files->open_fds);
+	if(p == current)
+	{
+		printk("DFSA files:\n");
+		for(i = 0 ; i < files->max_fds ; i++)
+		if((fs = can_dfsa_file(i)))
+		{
+			printk("%d: #%d/%d\n", i, fs,
+				(int)files->fd[i]->f_dentry->d_inode->i_ino);
+		}
+	}
+	else
+	{
+		printk("file/count/dfsano/ino:");
+		for(i = 0 ; i < files->max_fds ; i++)
+		if((f = files->fd[i]))
+		{
+			printk(" %d:%d/#%d/%d", i, file_count(f),
+				f->f_vfsmnt->mnt_dfsano ? : -9,
+				(int)f->f_dentry->d_inode->i_ino);
+		}
+		printk("\n");
+	}
+}
+
+#endif /* CONFIG_MOSIX_DFSA */
diff -Naur --exclude=CVS --exclude=configs linux/hpc/div.c linux-openmosix/hpc/div.c
--- linux/hpc/div.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/div.c	2003-06-13 23:54:29.000000000 +0200
@@ -0,0 +1,124 @@
+/* Changes since Feb 12 2002, copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+
+#define	low(x)	(((unsigned int *)&x)[0])
+#define	high(x)	(((unsigned int *)&x)[1])
+
+/* the slow division by 64-bit is only provided for copleteness */
+/* but is not expected to be actually ever required by the kernel except for 64bit platforms*/
+unsigned long long
+__slowdivdi3(unsigned long long a, unsigned long long b)
+{
+	long long result = 0;
+	long long bit = 1;
+
+	while((b << 1) < a)
+	{
+		b <<= 1;
+		bit <<= 1;
+	}
+	while(bit)
+	{
+		if(a > b)
+		{
+			a -= b;
+			result |= bit;
+		}
+		b >>= 1;
+		bit >>= 1;
+	}
+	return(result);
+}
+
+long long
+__divdi3(long long a, long long b)
+{
+	int sign;
+	long long result;
+	unsigned int al, ah, dl, dh;
+	int hd;
+	long long bit;
+	int i;
+
+	if(!high(b) && !high(a))	/* by far the most common case */
+		return(low(a) / low(b));
+	sign = 1;
+	if(high(b) & 0x80000000)
+	{
+		b = -b;
+		if(!high(b) && !high(a))
+			return(-low(a) / low(b));
+		sign = -1;
+	}
+	if(high(a) & 0x80000000)
+	{
+		sign = -sign;
+		a = -a;
+		if(!high(a) && !high(b))
+			return(sign * low(a) / low(b));
+	}
+	dh = high(b);
+	if(dh)
+		return(sign * __slowdivdi3(a, b));
+	dl = low(b);
+	if(!dl)
+		dh /= dl;	/* divide by 0! */
+	al = low(a);
+	ah = high(a);
+	for(i = 0 ; dh < ah || (dh == ah && dl <= al) ; i++)
+	{
+		dh += dh;
+		if(dl & 0x80000000)
+			dh++;
+		dl += dl;
+		if(i)
+		{
+			high(b) <<= 1;
+			if(low(b) & 0x80000000)
+				high(b)++;
+			low(b) <<= 1;
+		}
+	}
+	if(i == 0)
+		return(0);
+	if(i <= 32)
+	{
+		low(bit) = 1 << (i-1);
+		high(bit) = 0;
+	}
+	else
+	{
+		low(bit) = 0;
+		high(bit) = 1 << (i-33);
+	}
+	result = 0;
+	while(i--)
+	{
+		hd = high(a) - high(b);
+		if((hd = high(a) - high(b)) >= 0 &&
+			(low(a) >= low(b) || hd--))
+		{
+			high(a) = hd;
+			low(a) = low(a) - low(b);
+			result |= bit;
+		}
+		low(bit) >>= 1;
+		if(high(bit) == 1)
+			low(bit) = 0x80000000;
+		high(bit) >>= 1;
+		low(b) >>= 1;
+		if(high(b) & 1)
+			low(b) |= 0x80000000;
+		high(b) >>= 1;
+	}
+	if(sign < 0)
+		result = -result;
+	return(result);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/export.c linux-openmosix/hpc/export.c
--- linux/hpc/export.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/export.c	2003-09-10 20:50:13.000000000 +0200
@@ -0,0 +1,46 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/hpc.h>
+#include <hpc/routines.h>
+
+EXPORT_SYMBOL(deputy_copy_to_user);
+EXPORT_SYMBOL(deputy_copy_from_user);
+EXPORT_SYMBOL(deputy_clear_user);
+EXPORT_SYMBOL(deputy_strncpy_from_user);
+EXPORT_SYMBOL(deputy_strnlen_user);
+EXPORT_SYMBOL(deputy_verify_write);
+EXPORT_SYMBOL(mosix_deputy_init_aout_mm);
+EXPORT_SYMBOL(mosix_obtain_registers);
+EXPORT_SYMBOL(mosix_deputy_setup_args);
+EXPORT_SYMBOL(mosix_deputy_dump_thread);
+EXPORT_SYMBOL(mosix_config_get_table);
+EXPORT_SYMBOL(adjust_task_mosix_context);
+
+#ifdef CONFIG_MOSIX_DFSA
+EXPORT_SYMBOL(dfsa_open_file);
+EXPORT_SYMBOL(dfsa_touch_file);
+EXPORT_SYMBOL(dfsa_close_file);
+#endif /* CONFIG_MOSIX_DFSA */
+
+#if !defined(DO_NOT_FIX_LINUX_BUGS)
+#include <linux/personality.h>
+EXPORT_SYMBOL(lookup_exec_domain);
+#endif
+
+#ifdef CONFIG_DRM_I810_MODULE
+extern asmlinkage long sys_munmap(unsigned long,size_t);
+EXPORT_SYMBOL(mosix_go_home);
+EXPORT_SYMBOL(sys_munmap);
+#endif /* CONFIG_DRM_I810_MODULE */
diff -Naur --exclude=CVS --exclude=configs linux/hpc/freemem.c linux-openmosix/hpc/freemem.c
--- linux/hpc/freemem.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/freemem.c	2002-11-24 21:57:58.000000000 +0100
@@ -0,0 +1,443 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/swapctl.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/hpc.h>
+#include <linux/slab.h>
+#include <asm/pgtable.h>
+#include <hpc/routines.h>
+#include <hpc/debug.h>
+#include <hpc/defs.h>
+#include <hpc/balance.h>
+
+int pages_to_keep_free;
+int latest_free_mem;
+static int sort_age_maxchunk;
+static int marker;
+
+static inline int
+current_free_mem(void)
+{
+        return(latest_free_mem);
+}
+
+int
+export_mem(void)
+{
+	register int i, n;
+	struct task_struct *p;
+
+	n = current_free_mem() - pages_to_keep_free;
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if((i = p->mosix.pages_i_bring) > 0)
+		n -= i;
+	read_unlock(&tasklist_lock);
+	if(n < 0)
+		n = 0;
+	return(n);
+}
+
+int
+memory_badly_required(void)
+{
+	register int n, s = 0;
+	struct task_struct *p;
+	struct mm_struct *mm;
+
+	n = current_free_mem() - pages_to_keep_free;
+	write_lock_irq(&tasklist_lock);
+	++marker;
+	for_each_task(p)
+	{
+		n -= p->mosix.pages_i_bring;
+		task_lock(p);
+		if((mm = p->mm) && mm->mark != marker && mm->last_memsort)
+		{
+			s += mm->swapped;
+			mm->mark = marker;
+		}
+		task_unlock(p);
+	}
+	write_unlock_irq(&tasklist_lock);
+	if(n < 0 && n > -MIN_EXPECTED_PROC_SIZE)
+		n = -MIN_EXPECTED_PROC_SIZE;
+	if(n < 0)
+		n -= s;
+	return(-n);
+}
+
+#define	MDP_HIGHEST_QUALITY	(MIN_EXPECTED_PROC_SIZE * 10)
+
+/* "memory_relief_quality" is called with tasklist_lock read-locked */
+int
+memory_relief_quality(struct task_struct *p, int need)
+{
+	int q;
+	int used, unused, swapped;	/* (dirty pages only) */
+	struct mm_struct *mm;
+
+	read_lock(&tasklist_lock);
+	task_lock(p);
+	if(!(mm = p->mm) || !mm->last_memsort)
+	{
+		task_unlock(p);
+		read_unlock(&tasklist_lock);
+		return(0);
+	}
+	used = mm->used;
+	unused = mm->unused;
+	swapped = mm->swapped;
+	task_unlock(p);
+	read_unlock(&tasklist_lock);
+	if (used >= need && used < 2 * need)
+		q = MDP_HIGHEST_QUALITY * (150 - used * 50 / need) / 100;
+	else if(used >= need)
+		q = MDP_HIGHEST_QUALITY * need / (1 + used - need);
+	else if (used < need)
+	{
+		if(need > MDP_HIGHEST_QUALITY/2)
+			q = MDP_HIGHEST_QUALITY / 2 * used / need;
+		else
+			q = used;
+	}
+	if(swapped)
+		q = q * used / (used + swapped);
+
+	return(q);
+}
+
+/*
+ * The memory-sorting daemon is only loosely connected with MOSIX:
+ * it should have been part of Linux, but Linux does not age pages
+ * belonging to processes (unless memory is under pressure) and in
+ * openMosix we do need to know how much memory is really free ALL THE TIME.
+ * The code here is largely stolen from "mm/vmscan.c".
+ */
+
+void
+compute_freemem(void)
+{
+	int count;
+	static int trouble_time;
+	int kernel, inactive;
+	unsigned int tasked;
+
+	if(acpuse < MF * smp_num_cpus * UTIL_TOLLERANCE)
+		trouble_time = 11;
+	tasked = 0;
+	if(trouble_time && --trouble_time > 0)
+		kernel = inactive = 0;
+	else
+	{
+		struct task_struct *p;
+		struct mm_struct *mm;
+
+		kernel = (dentry_stat.nr_unused * sizeof(struct dentry) +
+			  inodes_stat.nr_unused * sizeof(struct inode))
+			  >> PAGE_SHIFT;
+		inactive = nr_inactive_pages;
+		write_lock_irq(&tasklist_lock);
+		++marker;
+		for_each_task(p)
+		{
+			task_lock(p);
+			if((mm = p->mm) && mm->mark != marker &&
+				time_before(jiffies, mm->last_memsort + 15*HZ))
+			{
+				tasked += mm->private_unused;
+				mm->mark = marker;
+			}
+			task_unlock(p);
+		}
+		write_unlock_irq(&tasklist_lock);
+	}
+	count = nr_free_pages() + kernel + inactive + tasked;
+	if(count >= num_physpages)	/* whatever went wrong... */
+		count = num_physpages - 1;
+	if(count < 0)
+		count = 0;
+	latest_free_mem = count;
+}
+
+static inline int
+sort_interval(int initial)
+{
+	if(latest_free_mem < pages_to_keep_free)
+		return(initial ? 0 : 3*HZ);
+	else if(latest_free_mem < 2 * pages_to_keep_free)
+		return(initial ? 2*HZ : 4*HZ);
+	else if(latest_free_mem < 4 * pages_to_keep_free)
+		return(initial ? 4*HZ : 8*HZ);
+	else
+		return(10*HZ);
+}
+
+/*
+ * sort pages into 3 piles: "used", "unused" and "swapped"
+ * plus another distinction for unused pages not otherwise accounted for
+ */
+void
+sort_and_age_pages(struct mm_struct *mm)
+{
+	int used = 0, unused = 0, swapped = 0, private_unused = 0;
+	int need_flush = 0;
+	register struct vm_area_struct *vma;
+	pgd_t *pgdir;
+	pmd_t *pmdir;
+	pte_t *pte;
+	struct page *page;
+	unsigned long addr, start, pgd_end, pmd_end;
+	static int let_go = -1;
+	int interval = sort_interval(1);
+
+	if(!mm->last_memsort && interval)
+	{
+		if(!mm->used)
+			mm->used = (jiffies & 0xffff) ? : 0xffff;
+		if((u16)((jiffies & 0xffff) - mm->used) < interval)
+			return;
+	}
+	addr = 0;
+	loop:
+	if(let_go == -1)
+		let_go = sort_age_maxchunk;
+	spin_lock(&mm->page_table_lock);
+	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next)
+	if(addr < vma->vm_end)
+	{
+		start = vma->vm_start;
+		if(start < addr)
+			start = addr;
+		pgdir = pgd_offset(mm, start);
+		for(addr = start ; addr < vma->vm_end ;
+			addr = pgd_end , pgdir++)
+		{
+			if(let_go-- == 0)
+			{
+				spin_unlock(&mm->page_table_lock);
+				current->policy |= SCHED_YIELD;
+				schedule();
+				goto loop;
+			}
+			pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
+			if(pgd_end > vma->vm_end)
+				pgd_end = vma->vm_end;
+			if(pgd_none(*pgdir) || pgd_bad(*pgdir))
+				continue;
+			pmdir = pmd_offset(pgdir, addr);
+			for(; addr < pgd_end ; addr = pmd_end , pmdir++)
+			{
+				pmd_end = (addr + PMD_SIZE) & PMD_MASK;
+				if(pmd_end > pgd_end)
+					pmd_end = pgd_end;
+				if(pmd_none(*pmdir) || pmd_bad(*pmdir))
+					continue;
+				pte = pte_offset(pmdir, addr);
+					page = pte_page(*pte);
+				for(; addr < pmd_end ; addr += PAGE_SIZE, pte++)
+	{
+		if(pte_none(*pte))
+			continue;
+		if(!pte_present(*pte))
+		{
+			swapped++;
+			continue;
+		}
+		page = pte_page(*pte);
+		if(!VALID_PAGE(page) || PageReserved(page))
+			continue;
+		if(PageActive(page))
+		{
+			used++;
+			continue;
+		}
+		if(!PageActive(page))
+		{
+			unused++;
+			continue;
+		}
+		if(time_before(jiffies, page->last_young + OLD_SECONDS * HZ))
+		{
+			used++;
+			continue;
+		}
+		if(ptep_test_and_clear_young(pte))
+		{
+			page->young = 1;
+			page->last_young = jiffies;
+			need_flush = 1;
+			used++;
+			continue;
+		}
+		unused++;
+		private_unused++;
+	}
+			}
+		}
+	}
+	if(need_flush)
+		flush_tlb_mm(mm);
+	spin_unlock(&mm->page_table_lock);
+	write_lock_irq(&tasklist_lock);
+	mm->used = used;
+	mm->unused = unused;
+	mm->swapped = swapped;
+	mm->private_unused = private_unused;
+	mm->last_memsort = jiffies ? : 1;
+	write_unlock_irq(&tasklist_lock);
+}
+
+#define	SORT_AGE_MAGIC		2490368
+
+int
+mosix_mem_daemon(void *nothing)
+{
+	struct task_struct *p;
+	struct mm_struct *mm;
+	struct mm_struct **mms, **newmms;
+	unsigned int i, n;
+	int mmno = 100;
+	unsigned need_increase = 0;
+	int interval;
+
+	common_daemon_setup("memsorter", 0);
+	neutralize_my_load(1);
+	if(!(mms = (struct mm_struct **)kmalloc(mmno * sizeof(mms[0]),
+								GFP_KERNEL)))
+		panic("no mem for mms");
+	pages_to_keep_free = num_physpages / KEEP_FREE_PORTION;
+	if(pages_to_keep_free > MAX_PAGES_TO_KEEP_FREE)
+		pages_to_keep_free = MAX_PAGES_TO_KEEP_FREE;
+	compute_freemem();
+
+	/* "sort_and_age_pages" can take very long for large memories:
+	 * we must therefore allow other processes to take over at least
+	 * about every millisecond.
+	 */
+	sort_age_maxchunk = loops_per_jiffy / SORT_AGE_MAGIC;
+	if(!sort_age_maxchunk)	/* very slow processors */
+		sort_age_maxchunk = 1;
+	while (1)
+	{
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(mosadmin_mode_quiet ? 100 * HZ : HZ);
+		if(current->sigpending)
+			flush_signals(current);
+		loop:
+                if (!PE)
+			wait_for_mosix_configuration(NULL);
+		if(mosadmin_mode_quiet)
+			continue;
+		compute_freemem();
+		interval = sort_interval(0);
+		n = 0;
+		write_lock_irq(&tasklist_lock);
+		++marker;
+		for_each_task(p)
+		if(!(p->mosix.stay & DSTAY_PER_MM))
+		{
+			task_lock(p);
+			mm = p->mm;
+			if((mm = p->mm) && mm != &init_mm && mm->mark != marker
+				&& time_before(mm->last_memsort + interval,
+								jiffies))
+			{
+				if(n >= mmno)
+					need_increase = 1;
+				else
+				{
+					atomic_inc(&mm->mm_users);
+					mms[n++] = mm;
+					mm->mark = marker;
+				}
+			}
+			task_unlock(p);
+		}
+		write_unlock_irq(&tasklist_lock);
+		for(i = 0 ; i < n ; i++)
+		{
+			mm = mms[i];
+			if(atomic_read(&mm->mm_realusers) > 0)
+				sort_and_age_pages(mm);
+			mmput(mm);
+		}
+		if(need_increase)
+		{
+			if((newmms = (struct mm_struct **)kmalloc(
+				(mmno + 50) * sizeof(mms[0]), GFP_KERNEL)))
+			{
+				kfree(mms);
+				mms = newmms;
+				mmno += 50;
+			}
+			need_increase = 0;
+			goto loop;
+		}
+		wake_up_interruptible(&kswapd_wait);
+	}
+}
+
+#if 0
+/* needed once-only to calibrate the "sort_age_maxchunk" calculation */
+/* not bothering using locks here, since we are only called from the debugger */
+int
+calibrate_sort_age(int pid)
+{
+	int sv = sort_age_maxchunk;
+	struct task_struct *p = find_task_by_pid(pid);
+	struct mm_struct *mm;
+	unsigned int chunks = 0;
+	register struct vm_area_struct *vma;
+	unsigned long addr, pgd_end;
+	__typeof__ (jiffies) before;
+	int milli, magic;
+	int i;
+
+	if(!p || !(mm = p->mm))
+	{
+		printk("No PID %d\n", pid);
+		return(0);
+	}
+
+	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next)
+	for(addr = vma->vm_start ; addr < vma->vm_end ; addr = pgd_end)
+	{
+		chunks++;
+		pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
+		if(pgd_end > vma->vm_end)
+			pgd_end = vma->vm_end;
+	}
+	printk("%d chunks: starting 1000 times...", chunks);
+	sort_age_maxchunk = 0x7fffffff;	/* unlimit */
+	if(!mm->last_memsort)
+		mm->last_memsort = 1;
+	sti();
+	before = jiffies;
+	for(i = 0 ; i < 1000 ; i++)
+		sort_and_age_pages(mm);
+	milli = (jiffies - before) * 1000 / HZ;
+	printk("%d miliseconds, ", milli);
+	sort_age_maxchunk = sv;
+	if(milli < 100)
+	{
+		printk("That was too quick -- try a larger process!\n");
+		return((int)milli);
+	}
+	magic = loops_per_jiffy / (chunks * 1000 / milli);
+	printk("SORT_AGE_MAGIC=%d\n", magic);
+	return(magic);
+}
+#endif /* MOSIX_ONCE_ONLY */
diff -Naur --exclude=CVS --exclude=configs linux/hpc/hpcadmin.c linux-openmosix/hpc/hpcadmin.c
--- linux/hpc/hpcadmin.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/hpcadmin.c	2003-04-09 00:43:23.000000000 +0200
@@ -0,0 +1,350 @@
+/* Changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+#include <linux/config.h>
+#include <linux/hpcctl.h>
+#include <linux/hpc.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/debug.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
+int mosadmin_mode_stay;
+int mosadmin_mode_lstay;
+int mosadmin_mode_block;
+int mosadmin_mode_quiet;
+int mosadmin_mode_nomfs;
+int mosadmin_gateways;
+
+int backed_block;
+int backed_lstay;
+
+char bootexpel, expel_progress;
+static int in_bring, in_expel;
+
+int
+admin_set_mode(int mode, int on)
+{
+	int *m;
+
+	lock_mosix();
+	switch(mode)
+	{
+	case DS_STAY:
+		m = &mosadmin_mode_stay;
+		break;
+	case DS_LSTAY:
+		m = in_bring ? &backed_lstay : &mosadmin_mode_lstay;
+		break;
+	case DS_BLOCK:
+		m = in_expel ? &backed_block : &mosadmin_mode_block;
+		break;
+	case DS_QUIET:
+		m = &mosadmin_mode_quiet;
+		break;
+	case DS_NOMFS:
+		m = &mosadmin_mode_nomfs;
+		break;
+	default:
+		panic("admin_set_unknown_mode");
+		/*NOTREACHED*/
+	}
+	on = (on != 0);	/* sanity */
+	if(on == *m)
+	{
+		unlock_mosix();
+		return(0);
+	}
+	if(on)
+		switch (mode)
+		{
+		case DS_STAY:
+			printk(KERN_NOTICE "openMosix: Automatic process-migration from this node disabled.\n");
+			break;
+		case DS_LSTAY:
+			printk(KERN_NOTICE "openMosix: Auto-migration of local-processes from this node disabled.\n");
+			break;
+		case DS_BLOCK:
+			printk(KERN_NOTICE "openMosix: This node will not accept further guest-processes.\n");
+			break;
+		case DS_QUIET:
+			printk(KERN_NOTICE "openMosix: Automatic load-dissemination stopped.\n");
+			break;
+		case DS_NOMFS:
+			printk(KERN_NOTICE "openMosix: This node will stop providing MFS services.\n");
+			break;
+		}
+	else
+	{
+		switch(mode)
+		{
+		case DS_STAY:
+			if(in_bring ? backed_lstay:mosadmin_mode_lstay)
+				printk(KERN_NOTICE "openMosix: Auto-migration of guest-processes from this node re-enabled.\n");
+			else
+				printk(KERN_NOTICE "openMosix: Auto-migration from this node re-enabled.\n");
+			break;
+		case DS_LSTAY:
+			if(mosadmin_mode_stay)
+				printk(KERN_NOTICE "openMosix: Once auto-migration is enabled, local-processes may migrate as well.\n");
+			else
+				printk(KERN_NOTICE "openMosix: Auto-migration of local-processes from this node re-enabled.\n");
+			break;
+		case DS_BLOCK:
+			printk(KERN_NOTICE "openMosix: guest-processes now accepted again.\n");
+			break;
+		case DS_QUIET:
+			printk(KERN_NOTICE "openMosix: Automatic load-gossipping resumed.\n");
+			break;
+		case DS_NOMFS:
+			printk(KERN_NOTICE "openMosix: This node  may now provide oMFS services.\n");
+			break;
+		}
+	}
+	*m = on;
+	unlock_mosix();
+#ifdef CONFIG_MOSIX_FS
+	if(mode == DS_NOMFS)
+		mfs_change_pe();
+#endif /* CONFIG_MOSIX_FS */
+	return (0);
+}
+
+int
+admin_get_mode(int mode)
+{
+	int ret;
+
+	switch(mode)
+	{
+	case DS_STAY:
+		return(mosadmin_mode_stay);
+	case DS_LSTAY:
+		lock_mosix();
+		ret = in_bring ? backed_lstay : mosadmin_mode_lstay;
+		unlock_mosix();
+		return(ret);
+	case DS_BLOCK:
+		lock_mosix();
+		ret = in_expel ? backed_block : mosadmin_mode_block;
+		unlock_mosix();
+		return(ret);
+	case DS_QUIET:
+		return(mosadmin_mode_quiet);
+	case DS_NOMFS:
+		return(mosadmin_mode_nomfs);
+	}
+	return (-EINVAL);
+}
+
+int
+my_mosix_status(void)
+{
+	int s = DS_MOSIX_UP;
+
+	if(mosix_config_get_pe())
+		s |= DS_MOSIX_DEF;
+	if(mosadmin_mode_stay)
+		s |= DS_STAY;
+	lock_mosix();
+	if(in_bring ? backed_lstay : mosadmin_mode_lstay)
+		s |= DS_LSTAY;
+	if(in_expel ? backed_block : mosadmin_mode_block)
+		s |= DS_BLOCK;
+	unlock_mosix();
+	if(mosadmin_mode_quiet)
+		s |= DS_QUIET;
+	if(mosadmin_mode_nomfs)
+		s |= DS_NOMFS;
+	return(s);
+}
+
+int
+expel(int boot)
+{
+	unsigned int left = 0, oleft;
+	unsigned int round = 0;
+	struct task_struct *p;
+	int err = 0;
+
+	if(boot)
+	{
+		if(current->mosix.dflags & DREMOTE)
+			printk("Foops: cannot expel myself.\n");
+
+		tasklist_lock = RW_LOCK_UNLOCKED;
+	}
+	else
+	{
+		lock_mosix();
+		if(in_expel)
+		{
+			unlock_mosix();
+			return(-EBUSY);
+		}
+		in_expel = 1;
+	}
+	backed_block = mosadmin_mode_block;
+	mosadmin_mode_block = 1;
+	if(!boot)
+		unlock_mosix();
+	while(1)
+	{
+		oleft = left;
+		left = 0;
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if((p->mosix.dflags & DREMOTE) && p != current &&
+			!(p->mosix.dflags & DFINISHED))
+		{
+			if(boot)
+				mosix_do_add_to_whereto(p, MUSTGOHOME);
+			else
+				mosix_add_to_whereto(p, MUSTGOHOME);
+			if(p->mosix.deppe != PE) /* don't count cheaters */
+				left++;
+		}
+		read_unlock(&tasklist_lock);
+		if(!left)
+		{
+			if(boot && round)
+				printk("Done. ");
+			else if(!backed_block)
+				printk(KERN_NOTICE "openMosix: "
+					"All guest processes evacuated and"
+					" no further guests allowed in\n");
+			break;
+		}
+		if(boot && round++ == 0)
+		{
+			int this_cpu = smp_processor_id();
+
+			printk("Expelling...");
+			bootexpel = 1;
+			cli();
+			if(local_irq_count(this_cpu))
+			{
+				local_irq_count(this_cpu)--;
+#ifdef CONFIG_SMP
+				release_irqlock(this_cpu);
+#endif /* CONFIG_SMP */
+			}
+			while(in_softirq())
+				local_bh_enable();
+			sti();
+		}
+		if(boot)
+			printk("%d ", left);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+		if(signal_pending(current))
+		{
+			if(boot) /* do not worry about locking */
+				flush_signals(current);
+			else
+			{
+				lock_mosix();
+				mosadmin_mode_block = backed_block;
+				unlock_mosix();
+				in_expel = 0;
+				return(-EINTR);
+			}
+		}
+		if((boot && expel_progress) || left < oleft)
+			round = 1;
+		expel_progress = 0;
+		if(round == 100)
+		{
+			printk("Giving up\n");
+			lock_mosix();
+			mosadmin_mode_block = backed_block;
+			unlock_mosix();
+			err = -EINTR;
+			break;
+		}
+	}
+	if(!boot)
+	{
+		lock_mosix();
+		in_expel = 0;
+		unlock_mosix();
+	}
+	return(err);
+}
+
+int
+bring(void)
+{
+	register struct task_struct *p, *w = NULL;
+	unsigned int left;
+	int err = -EBUSY;
+
+	lock_mosix();
+	if(in_bring)
+	{
+		unlock_mosix();
+		return(-EBUSY);
+	}
+	in_bring = 1;
+	backed_lstay = mosadmin_mode_lstay;
+	mosadmin_mode_lstay = 1;
+	unlock_mosix();
+	while(1)
+	{
+		left = 0;
+		w = NULL;
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if((p->mosix.dflags & DDEPUTY) ||
+			(p->mosix.whereto && !(p->mosix.dflags & DREMOTE)))
+		{
+			mosix_add_to_whereto(p, MUSTGOHOME);
+			if(p->mosix.deppe != PE) /* don't count cheating_for_test */
+			{
+				left++;
+				if(!w)
+				{
+					w = p;
+					get_task_struct(w);
+				}
+			}
+		}
+		read_unlock(&tasklist_lock);
+		if(!left)
+		{
+			if(!backed_lstay)
+				printk(KERN_NOTICE "openMosix: "
+					"All local processes brought home"
+					" and will not auto-migrate away\n");
+			err = 0;
+			break;
+		}
+		tell_process(w, DREQ_HOMEWAKE);
+		interruptible_sleep_on_timeout(mos_to_waitp(&w->mosix), HZ);
+		free_task_struct(w);
+		if(signal_pending(current))
+		{
+			lock_mosix();
+			mosadmin_mode_lstay = backed_lstay;
+			unlock_mosix();
+			err = -EINTR;
+			break;
+		}
+	}
+	lock_mosix();
+	in_bring = 0;
+	unlock_mosix();
+	return(err);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/hpcproc.c linux-openmosix/hpc/hpcproc.c
--- linux/hpc/hpcproc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/hpcproc.c	2004-04-13 14:37:43.000000000 +0200
@@ -0,0 +1,2434 @@
+/* Changes since February 12, 2002 copyright by Moshe Bar (moshe@moelabs.com)
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Oren Laadan, Amnon Shiloh, Moshe Bar
+ * Some stuff 'borrowed' from "fs/proc".
+ */
+
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/hpc.h>
+#include <linux/hpcctl.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/hpcversion.h>
+#include <linux/swap.h>
+#include <hpc/protocol.h>
+#include <hpc/debug.h>
+#include <hpc/request.h>
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+
+/* general interface */
+
+static int zero = 0;
+static int one = 1;
+static int uintmax = 0x7fffffff;
+
+typedef struct ctl_mosix ctl_mosix;
+
+typedef ssize_t ctl_mosix_t (ctl_mosix *, int, struct file *, void *, size_t *);
+
+struct ctl_mosix {
+	int ctl_name;
+	const char *procname;
+	void *data;
+	int maxlen;
+	mode_t mode;
+	ctl_mosix_t *handler;
+	struct inode_operations *alt_iops;
+	struct file_operations *alt_fops;
+	void *extra[2];
+};
+
+/* values of 'do_intarr' 'write' argument: */
+#define CTLF_SIMPLE	0x01	/* nothing special */
+#define CTLF_UNSIGNED	0x02	/* use unsigned semantics */
+#define CTLF_MINMAXP	0x04	/* use min/max (via pointer) */
+#define CTLF_MINMAXV	0x08	/* use min/max (via values) */
+#define CTLF_BOOLEAN	0x10	/* boolean values (0/1) */
+#define	CTLF_POSITIVE	0x20	/* > 1 */
+
+static void proc_mosix_register(struct proc_dir_entry *de, ctl_mosix *table);
+
+static ssize_t do_intarr(ctl_mosix *, int, struct file*, void *, size_t *, int);
+static inline ssize_t get_intarr(struct file *, const char *, size_t,
+				 struct ctl_mosix *);
+static inline ssize_t put_intarr(struct file *, const char *, size_t,
+				 struct ctl_mosix *);
+
+static inline ctl_mosix_t ctl_boolean;
+static inline ctl_mosix_t ctl_uintarr;
+static inline ctl_mosix_t ctl_positive;
+static inline ctl_mosix_t ctl_minmaxv;
+
+/* dynamic directories: */
+/* the following are Or'ed with the pid/node << 16 */
+enum
+{
+	PROC_REMPID_INO = PROC_MOSIX_USE_START,
+	PROC_REMPID_FROM,
+	PROC_REMPID_GOTO,
+	PROC_REMPID_STATM,
+	PROC_REMPID_STATS,
+	PROC_REMPID_IDENT,
+	PROC_NODEID_INO,
+	PROC_NODEID_CPUS,
+	PROC_NODEID_INFO,
+	PROC_NODEID_LOAD,
+	PROC_NODEID_MEM,
+	PROC_NODEID_RMEM,
+	PROC_NODEID_SPEED,
+	PROC_NODEID_TMEM,
+	PROC_NODEID_STATUS,
+	PROC_NODEID_UTIL,
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	PROC_NODEID_LOADLIMIT,
+	PROC_NODEID_LLIMITMODE,
+	PROC_NODEID_LOADREMOTE,
+	PROC_NODEID_LOADLOCAL,
+	PROC_NODEID_CPULIMIT,
+	PROC_NODEID_CPULIMITMODE,
+	PROC_NODEID_CPUREMOTE,
+	PROC_NODEID_CPULOCAL,
+#endif
+};
+
+struct subnames
+{
+	int id;
+	char *name;
+	int namelen;
+};
+
+struct subnames rempid_subs[] =
+{
+	{PROC_REMPID_FROM, "from", 4},
+	{PROC_REMPID_GOTO, "goto", 4},
+	{PROC_REMPID_STATM, "statm", 5},
+	{PROC_REMPID_STATS, "stats", 5},
+	{PROC_REMPID_IDENT, "identity", 8},
+	{}
+}, nodeid_subs[] =
+{
+	{PROC_NODEID_CPUS, "cpus", 4},
+	{PROC_NODEID_LOAD, "load", 4},
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	{PROC_NODEID_LOADLIMIT, "loadlimit", 9},
+	{PROC_NODEID_LLIMITMODE, "llimitmode", 10},
+	{PROC_NODEID_LOADLOCAL, "loadlocal", 9},
+	{PROC_NODEID_LOADREMOTE,"loadremote", 10},
+	{PROC_NODEID_CPULIMIT, "cpulimit", 8},
+	{PROC_NODEID_CPULIMITMODE, "cpulimitmode", 12},
+	{PROC_NODEID_CPULOCAL, "cpulocal", 8},
+	{PROC_NODEID_CPUREMOTE,"cpuremote", 9},
+#endif
+	{PROC_NODEID_MEM, "mem", 3},
+	{PROC_NODEID_RMEM, "rmem", 4},
+	{PROC_NODEID_SPEED, "speed", 5},
+	{PROC_NODEID_TMEM, "tmem", 4},
+	{PROC_NODEID_STATUS, "status", 6},
+	{PROC_NODEID_UTIL, "util", 4},
+	{}
+};
+
+static ssize_t proc_mosix_sub_read(struct file *, char *, size_t, loff_t *);
+static ssize_t proc_mosix_sub_write(struct file *, const char *, size_t, loff_t *);
+
+static struct file_operations proc_mosix_sub_file_operations =
+{
+	.read = proc_mosix_sub_read,
+	.write = proc_mosix_sub_write,
+};
+
+static struct inode_operations proc_mosix_sub_inode_operations =
+{
+};
+
+static int proc_mosix_sub_readdir(struct file *, void *, filldir_t);
+static struct dentry *proc_mosix_sub_lookup(struct inode *, struct dentry *);
+
+static struct file_operations proc_mosix_subdir_file_operations =
+{
+	.readdir = proc_mosix_sub_readdir,
+};
+
+static struct inode_operations proc_mosix_subdir_inode_operations =
+{
+	.lookup = proc_mosix_sub_lookup,
+};
+
+static int proc_mosix_nodes_readdir(struct file *, void *, filldir_t);
+static struct dentry *proc_mosix_nodes_lookup(struct inode *,struct dentry *);
+
+static struct file_operations proc_mosix_nodes_file_operations =
+{
+	.readdir = proc_mosix_nodes_readdir,
+};
+
+static struct inode_operations proc_mosix_nodes_inode_operations =
+{
+	.lookup = proc_mosix_nodes_lookup,
+};
+
+static int proc_mosix_remote_readdir(struct file *, void *, filldir_t);
+static struct dentry *proc_mosix_remote_lookup(struct inode *,struct dentry *);
+
+static struct file_operations proc_mosix_remote_file_operations =
+{
+	.readdir = proc_mosix_remote_readdir,
+};
+
+static struct inode_operations proc_mosix_remote_inode_operations =
+{
+	.lookup = proc_mosix_remote_lookup,
+};
+
+static struct proc_dir_entry proc_mosix_nodes = {
+        0, 5, "nodes",
+        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+        0, &proc_mosix_nodes_inode_operations,
+	&proc_mosix_nodes_file_operations
+};
+
+static struct proc_dir_entry proc_mosix_remote = {
+        0, 6, "remote",
+        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+        0, &proc_mosix_remote_inode_operations,
+	&proc_mosix_remote_file_operations
+};
+
+static ssize_t proc_mosix_set_remote_goto(struct file*,int,const char*,size_t);
+static int proc_mosix_get_remote_from(struct task_struct *, char *);
+static int proc_mosix_get_remote_stats(struct task_struct *, char *);
+static int proc_mosix_get_remote_identity(struct task_struct *, char *);
+
+static int
+proc_mosix_delete_dentry(struct dentry *dentry)
+{
+	return(1);
+}
+
+static struct dentry_operations proc_mosix_dynamic_dentry_operations =
+{
+	.d_delete = proc_mosix_delete_dentry
+};
+
+/* static directories: */
+
+static inline ssize_t proc_readmosix(struct file*,char*,size_t,loff_t*);
+static inline ssize_t proc_writemosix(struct file*,const char*,size_t,loff_t*);
+
+static struct file_operations proc_mosix_file_operations =
+{
+	.read = proc_readmosix,
+	.write = proc_writemosix,
+};
+
+static loff_t proc_lseekmosixinfo(struct file *, long long, int);
+
+static struct file_operations proc_mosix_info_file_operations =
+{
+	.llseek = proc_lseekmosixinfo,
+	.read = proc_readmosix,
+	.write = proc_writemosix,
+};
+
+/* /proc/hpc/admin: */
+
+enum {
+	ADMIN_CONFIG = 1, ADMIN_STAY, ADMIN_LSTAY, ADMIN_BLOCK, ADMIN_QUIET,
+	ADMIN_NOMFS, ADMIN_EXPEL, ADMIN_BRING, ADMIN_SPEED, ADMIN_SSPEED,
+	ADMIN_OVERHEADS, ADMIN_SLOWDECAY, ADMIN_FASTDECAY, ADMIN_DECAYINTERVAL,
+	ADMIN_GATEWAYS, ADMIN_MOSPE, ADMIN_VERSION,
+#ifdef CONFIG_MOSIX_DFSA
+	ADMIN_DFSALINKS,
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+	ADMIN_MFSCOSTS, ADMIN_MFS_TUNEINFO, ADMIN_MFSKILL,
+#endif /* CONFIG_MOSIX_FS */
+#if CONFIG_MOSIX_LOADLIMIT
+	ADMIN_LOADLIMIT,
+	ADMIN_LLMODE,
+	ADMIN_CPULIMIT,
+	ADMIN_CPULMODE,
+#endif
+};
+
+static ctl_mosix_t ctl_admin_gateways;
+static ctl_mosix_t ctl_admin_mospe;
+static ctl_mosix_t ctl_admin_config;
+static ctl_mosix_t ctl_admin_expel;
+static ctl_mosix_t ctl_admin_bring;
+static ctl_mosix_t ctl_admin_speed;
+static ctl_mosix_t ctl_admin_mode;
+static ctl_mosix_t ctl_admin_slowdecay;
+static ctl_mosix_t ctl_admin_fastdecay;
+static ctl_mosix_t ctl_admin_decayinterval;
+static ctl_mosix_t ctl_admin_overheads;
+static ctl_mosix_t ctl_admin_version;
+#ifdef CONFIG_MOSIX_DFSA
+static ctl_mosix_t ctl_admin_dfsalinks;
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+static ctl_mosix_t ctl_admin_mfskill;
+static ctl_mosix_t ctl_admin_mfscosts;
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_LOADLIMIT
+extern unsigned long load_limit;
+extern unsigned long cpu_limit;
+unsigned long mosadmin_mode_loadlimit = 0;
+unsigned long mosadmin_mode_cpulimit = 0;
+static ctl_mosix_t ctl_admin_loadlimit;
+static ctl_mosix_t ctl_admin_llimitmode;
+static ctl_mosix_t ctl_admin_cpulimitmode;
+static ctl_mosix_t ctl_admin_cpulimit;
+#endif
+static struct ctl_mosix admin_ctl[] = {
+	{ ADMIN_CONFIG, "config", NULL, 0, 0644, ctl_admin_config },
+	{ ADMIN_STAY, "stay", NULL, sizeof(int), 0644, ctl_admin_mode },
+	{ ADMIN_LSTAY, "lstay", NULL, sizeof(int), 0644, ctl_admin_mode },
+	{ ADMIN_BLOCK, "block", NULL, sizeof(int), 0644, ctl_admin_mode },
+	{ ADMIN_QUIET, "quiet", NULL, sizeof(int), 0644, ctl_admin_mode },
+	{ ADMIN_NOMFS, "nomfs", NULL, sizeof(int), 0644, ctl_admin_mode },
+	{ ADMIN_EXPEL, "expel", NULL, 0, 0200, ctl_admin_expel },
+	{ ADMIN_BRING, "bring", NULL, 0, 0200, ctl_admin_bring },
+	{ ADMIN_SPEED, "speed", NULL, sizeof(unsigned long), 0644, ctl_admin_speed },
+	{ ADMIN_SSPEED, "sspeed", &standard_speed, sizeof(int), 0644,
+		ctl_positive },
+	{ ADMIN_OVERHEADS, "overheads", mosix_cost, sizeof(mosix_cost), 0644,
+		ctl_admin_overheads },
+	{ ADMIN_SLOWDECAY, "slowdecay", NULL, sizeof(int), 0644,
+		ctl_admin_slowdecay },
+	{ ADMIN_FASTDECAY, "fastdecay", NULL, sizeof(int), 0644,
+		ctl_admin_fastdecay },
+	{ ADMIN_DECAYINTERVAL, "decayinterval", NULL, sizeof(int), 0644,
+		ctl_admin_decayinterval },
+	{ ADMIN_GATEWAYS, "gateways", NULL, 0, 0644, ctl_admin_gateways },
+	{ ADMIN_MOSPE, "mospe", NULL, 0, 0644, ctl_admin_mospe },
+	{ ADMIN_VERSION, "version", NULL, 0, 0444, ctl_admin_version },
+#ifdef CONFIG_MOSIX_DFSA
+	{ ADMIN_DFSALINKS, "dfsalinks", NULL, 0, 0644, ctl_admin_dfsalinks },
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+	{ ADMIN_MFSCOSTS, "mfscosts", mfs_cost, sizeof(mfs_cost), 0644,
+		ctl_admin_mfscosts },
+	{ ADMIN_MFSKILL, "mfskill", NULL, 0, 0200, ctl_admin_mfskill },
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	{ ADMIN_LOADLIMIT, "loadlimit", &load_limit, sizeof(unsigned long), 0644,
+		ctl_admin_loadlimit },
+	{ ADMIN_LLMODE, "llimitmode", &mosadmin_mode_loadlimit, sizeof(unsigned long), 
+		0644, ctl_admin_llimitmode },
+	{ ADMIN_CPULIMIT, "cpulimit", &cpu_limit, sizeof(unsigned long), 0644,
+		ctl_admin_cpulimit },
+	{ ADMIN_CPULMODE, "cpulimitmode", &mosadmin_mode_cpulimit, sizeof(unsigned long), 
+		0644, ctl_admin_cpulimitmode },
+#endif
+	{ 0 }
+};
+
+enum {
+	DECAY_CPUJOB = 1, DECAY_IOJOB, DECAY_SLOW, DECAY_FAST, DECAY_OWN,
+	DECAY_INHERIT, DECAY_EXEC, DECAY_EXECONCE, DECAY_CLEAR
+};
+
+/* /proc/hpc/decay: */
+
+static ctl_mosix_t ctl_decay;
+
+static struct ctl_mosix decay_ctl[] = {
+	{ DECAY_CPUJOB,	   "cpujob",   NULL, 0, 0666, ctl_decay },
+	{ DECAY_IOJOB,	   "iojob",    NULL, 0, 0666, ctl_decay },
+	{ DECAY_SLOW,	   "slow",     NULL, 0, 0666, ctl_decay },
+	{ DECAY_FAST,	   "fast",     NULL, 0, 0666, ctl_decay },
+	{ DECAY_OWN,	   "own",      NULL, 0, 0666, ctl_decay },
+	{ DECAY_INHERIT,   "inherit",  NULL, 0, 0666, ctl_decay },
+	{ DECAY_EXEC,	   "exec",     NULL, 0, 0666, ctl_decay },
+	{ DECAY_EXECONCE,  "execonce", NULL, 0, 0666, ctl_decay },
+	{ DECAY_CLEAR,	   "clear",    NULL, 0, 0222, ctl_decay },
+	{ 0 }
+};
+
+/* /proc/hpc/info: */
+enum
+{
+	INFO_CPUS = 1, INFO_INFOS, INFO_LOADS, INFO_MEMS, INFO_RMEMS,
+	INFO_SPEEDS, INFO_TMEMS, INFO_STATA, INFO_UTILS, 
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	INFO_LOADLIMIT,
+	INFO_LLIMITMODE,
+	INFO_LOADLOCAL,
+	INFO_LOADREMOTE,
+	INFO_CPULIMIT,
+	INFO_CPULIMITMODE,
+	INFO_CPULOCAL,
+	INFO_CPUREMOTE,
+#endif
+};
+
+static ctl_mosix_t ctl_info_fill;
+static ctl_mosix_t ctl_info_infos;
+
+static struct ctl_mosix info_ctl[] = {
+	{ INFO_LOADS,	"loads",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_SPEEDS,	"speeds", NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_CPUS,	"cpus",   NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_MEMS,	"mems",   NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_RMEMS,	"rmems",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_TMEMS,	"tmems",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_UTILS,	"utils",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_STATA,	"stata",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_INFOS,	"infos",  NULL, 0, 0444, ctl_info_infos,
+		NULL, &proc_mosix_info_file_operations },
+#ifdef CONFIG_MOSIX_LOADLIMIT
+  	{ INFO_LOADLIMIT,"loadlimit",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_LLIMITMODE,"llimitmode",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_LOADLOCAL,"loadlocal",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_LOADREMOTE,"loadremote",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_CPULIMIT,"cpulimit",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_CPULIMITMODE,"cpulimitmode",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_CPULOCAL,"cpulocal",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+	{ INFO_CPUREMOTE,"cpuremote",  NULL, 0, 0444, ctl_info_fill,
+		NULL, &proc_mosix_info_file_operations },
+#endif
+	{ 0 }
+};
+
+#ifdef CONFIG_MOSIX_DFSA
+static ssize_t
+ctl_admin_dfsalinks(ctl_mosix *ctl, int write, struct file *filp,
+	       void *buf, size_t *len)
+{
+	ssize_t error = 0;
+	int l;
+	char *filename = NULL, c, *e;
+	loff_t pos = filp->f_pos;
+	int done = 0;
+	unsigned int more = 1;
+
+	while(write)
+	{
+		if(!filename && !(filename = __getname()))
+			return(done ? : -ENOMEM);
+		for(e = filename , l = 0 ; l < *len ; l++)
+		if(get_user(c, ((char *)buf)++))
+		{
+			putname(filename);
+			return(done ? : -EFAULT);
+		}
+		else if(c == '\0')
+		{
+			more = 0;
+			*e++ = '\0';
+			break;
+		}
+		else if(c == '\n')
+		{
+			*e++ = '\0';
+			break;
+		}
+		else if(l == PAGE_SIZE-1)
+		{
+			putname(filename);
+			return(done ? : -ENAMETOOLONG);
+		}
+		else
+			*e++ = c;
+		if(l == *len)
+		{
+			putname(filename);
+			return(done ? : -EINVAL);
+		}
+		l = e - filename;
+		if(filename[0] == '-')
+		{
+			if(filename[1])
+				error = dfsa_dellink(&filename[1]);
+			else
+				error = dfsa_clearlinks();
+		}
+		else
+			error = dfsa_addlink(&filename[filename[0] == '+']);
+		putname(filename);
+		if(error)
+			return(done ? : error);
+		pos += l;
+		filp->f_pos = pos;
+		done += l;
+		if(!more || !(*len -= l))
+			return(done);
+	}
+	/* READ */
+	if(!*len)
+		return(0);
+	if(!(filename = dfsa_showlinks()))
+		error = -ENOMEM;
+	else if(pos < (l = strlen(filename)))
+	{
+		filename += pos;
+		l -= pos;
+		if(l > *len)
+			l = *len;
+		if(copy_to_user(buf, filename, l))
+			error = -EFAULT;
+		else
+			*len = l;
+	}
+	else
+		*len = 0;
+	if(filename)
+		kfree(filename);
+	if(!error)
+		filp->f_pos = pos + *len;
+	return (error ? : 0);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
+void
+mosix_proc_init(void)
+{
+	struct proc_dir_entry *parent;
+
+	proc_register(proc_mosix, &proc_mosix_remote);
+
+	proc_register(proc_mosix, &proc_mosix_nodes);
+
+	parent = proc_mkdir("hpc/info", NULL);
+	proc_mosix_register(parent, info_ctl);
+
+	parent = proc_mkdir("hpc/decay", NULL);
+	proc_mosix_register(parent, decay_ctl);
+
+	parent = proc_mkdir("hpc/admin", NULL);
+	proc_mosix_register(parent, admin_ctl);
+}
+
+static void
+proc_mosix_register(struct proc_dir_entry *root, ctl_mosix *table)
+{
+	int mode;
+	struct proc_dir_entry *de;
+
+	for ( ; table->procname ; table++)
+	{
+		mode = table->mode | S_IFREG;
+		de = create_proc_entry(table->procname, mode, root);
+		if (!de) {
+			printk("proc_openmosix_register: create_proc_entry"
+				" failed for %s!\n", table->procname);
+			mosix_panic("proc_openmosix_register: null de");
+			continue;
+		}
+		de->data = (void *) table;
+		de->proc_iops = table->alt_iops ? : NULL;
+		de->proc_fops = table->alt_fops ? : &proc_mosix_file_operations;
+	}
+}
+
+static ssize_t
+do_rw_mosix(int write, struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *de;
+	struct ctl_mosix *ctl;
+	ssize_t res;
+	ssize_t error;
+
+
+	de = (struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip;
+	if (!de || !de->data)
+		return (-ENOTDIR);
+	ctl = (struct ctl_mosix *) de->data;
+	if (!ctl || !ctl->handler)
+		return (-ENOTDIR);
+
+	
+	res = count;
+	if((error = (*ctl->handler) (ctl, write, file, buf, &res)))
+		res = error;
+	return (res);
+}
+
+static inline ssize_t
+proc_readmosix(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	return (do_rw_mosix(0, file, buf, count, ppos));
+}
+
+static inline ssize_t
+proc_writemosix(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	return(do_rw_mosix(1, file, (char *) buf, count, ppos));
+}
+
+#define TMPBUFLEN 20
+
+static ssize_t
+do_intarr(ctl_mosix *ctl, int write, struct file *filp,
+	  void *buffer, size_t *lenp, int scale)
+{
+	int *datap, vleft, first=1, len, left, neg, val;
+	int *min = NULL, *max = NULL;
+	char buf[TMPBUFLEN], *p;
+
+
+	if (!ctl->data || !ctl->maxlen || !*lenp ||
+	    (filp->f_pos && !write)) {
+		*lenp = 0;
+		return 0;
+	}
+	
+
+	datap = (int *) ctl->data;
+	if (write & CTLF_BOOLEAN) {
+		min = &zero;
+		max = &one;
+	} else if(write & CTLF_POSITIVE) {
+		min = &one;
+		max = &uintmax;
+	} else if (write & CTLF_UNSIGNED) {
+		min = &zero;
+		max = &uintmax;
+	} else if (write & CTLF_MINMAXP) {
+		min = ((int *) ctl->extra[0]) - 1;
+		max = ((int *) ctl->extra[1]) - 1;
+	} else if (write & CTLF_MINMAXV) {
+		min = (int *) &(ctl->extra[0]);
+		max = (int *) &(ctl->extra[1]);
+	}
+		
+	vleft = ctl->maxlen / sizeof(int);
+	left = *lenp;
+	
+	for (; left && vleft--; datap++, first=0) {
+
+
+		if (write) {
+			
+			int nex = TMPBUFLEN;
+			while (left) {
+				char c;
+				if(nex == TMPBUFLEN)
+				{
+					len = left;
+					if(len > TMPBUFLEN)
+						len = TMPBUFLEN;
+					if(copy_from_user(buf, buffer, len))
+						return(-EFAULT);
+					nex = 0;
+				}
+				c = buf[nex++];
+				if (!isspace(c))
+					break;
+				left--;
+				((char *) buffer)++;
+			}
+			if (!left)
+				break;
+			neg = 0;
+			len = left;
+			if (len > TMPBUFLEN-1)
+				len = TMPBUFLEN-1;
+			if(copy_from_user(buf, buffer, len))
+				return -EFAULT;
+			buf[len] = 0;
+			p = buf;
+			if (*p == '-' && left > 1) {
+				neg = 1;
+				left--, p++;
+			}
+			if (*p < '0' || *p > '9')
+				break;
+			val = simple_strtoul(p, &p, 0) * scale;
+			len = p-buf;
+			if ((len < left) && *p && !isspace(*p))
+				break;
+			if (neg)
+				val = -val;
+			buffer += len;
+			left -= len;
+
+			if (write & CTLF_MINMAXP) {
+				min++;
+				max++;
+			}
+
+
+			if (min && val < *min)
+				continue;
+			if (max && val > *max)
+				continue;
+
+
+			*datap = val;
+		} else {
+			p = buf;
+			if (!first)
+				*p++ = '\t';
+			sprintf(p, "%d", (*datap) / scale);
+			len = strlen(buf);
+			if (len > left)
+				len = left;
+			if(copy_to_user(buffer, buf, len))
+				return -EFAULT;
+			left -= len;
+			buffer += len;
+		}
+	}
+
+	if (!write && !first && left) {
+		if(put_user('\n', (char *) buffer))
+			return -EFAULT;
+		left--, buffer++;
+	}
+
+	if (write) {
+		int nex = TMPBUFLEN;
+
+		p = (char *) buffer;
+		while (left) {
+			char c;
+
+			if(nex == TMPBUFLEN)
+			{
+				len = left;
+				if(len > TMPBUFLEN)
+					len = TMPBUFLEN;
+				if(copy_from_user(buf, p, len))
+					return(-EFAULT);
+				nex = 0;
+			}
+			c = buf[nex++];
+			p++;
+			if (!isspace(c))
+				break;
+			left--;
+		}
+	}
+	if (write && first)
+		return -EINVAL;
+	*lenp -= left;
+	filp->f_pos += *lenp;
+	return 0;
+}
+
+static inline ssize_t
+get_intarr(struct file *file,const char *buf,size_t count,struct ctl_mosix *ctl)
+{
+	ssize_t res;
+	ssize_t error;
+
+	res = count;
+	error = (*ctl->handler) (ctl, 1, file, (char *)buf, &res);
+
+	if (error)
+		return (error);
+	return (res);
+}
+
+static inline ssize_t
+put_intarr(struct file *file,const char *buf,size_t count,struct ctl_mosix *ctl)
+{
+	ssize_t res;
+	ssize_t error;
+
+	res = count;
+	error = (*ctl->handler) (ctl, 0, file, (char *)buf, &res);
+
+	if (error)
+		return (error);
+	return (res);
+}
+
+static inline ssize_t
+ctl_boolean(ctl_mosix *ctl,int write,struct file *filp,void *buf,size_t *len)
+{
+	return (do_intarr(ctl, write ? CTLF_BOOLEAN : 0, filp, buf, len, 1));
+}
+
+static inline ssize_t
+ctl_uintarr(ctl_mosix *ctl,int write,struct file *filp,void *buf,size_t *len)
+{
+	return (do_intarr(ctl, write ? CTLF_UNSIGNED : 0, filp, buf, len, 1));
+}
+
+static inline ssize_t
+ctl_positive(ctl_mosix *ctl,int write,struct file *filp,void *buf,size_t *len)
+{
+	return (do_intarr(ctl, write ? CTLF_POSITIVE : 0, filp, buf, len, 1));
+}
+
+static inline ssize_t
+ctl_minmaxv(ctl_mosix *ctl,int write,struct file *filp,void *buf,size_t *len)
+{
+	return (do_intarr(ctl, write ? CTLF_MINMAXV : 0, filp, buf, len, 1));
+}
+
+static ssize_t
+ctl_admin_gateways(ctl_mosix *ctl, int write, struct file *filp,
+		   void *buf, size_t *len)
+{
+	int val = mosadmin_gateways;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(int), 0, ctl_minmaxv};
+
+	tmpctl.data = &val;
+	tmpctl.extra[0] = (void *)0;
+	tmpctl.extra[1] = (void *)2;
+
+	if (write)
+		error = get_intarr(filp, buf, *len, &tmpctl);
+	else
+		error = put_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+		return (error);
+	*len = error;
+	if(write)
+	{
+		lock_mosix();
+		mosadmin_gateways = val;
+		mosinfo_update_gateways();
+		unlock_mosix();
+	}
+	return (0);
+}
+
+static ssize_t
+ctl_admin_mospe(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	int this, tent;
+
+	if (!*len || (filp->f_pos && !write)) {
+		*len = 0;
+		return 0;
+	}
+	if (write) {
+		int pe, error;
+		struct ctl_mosix tmpctl =
+			{ 0, "goto", NULL, sizeof(int), 0, ctl_minmaxv };
+
+		tmpctl.data = &pe;
+		tmpctl.extra[0] = (void *) 0;
+		tmpctl.extra[1] = (void *) MOSIX_MAX;
+
+		error = get_intarr(filp, buf, *len, &tmpctl);
+		if (error < 0)
+			return (error);
+		if(pe < 0)
+			return(-ENOSYS);
+		return (mosix_config_set_pe(pe));
+	} else {
+		int n;
+		char tmpbuf[20];
+
+		if (filp->f_pos)
+			return (0);
+		this = mosix_config_get_pe();
+		tent = mosix_config_get_tentative_pe();
+		if (this == tent)
+			sprintf(tmpbuf, "%d\n", this);
+		else
+			sprintf(tmpbuf, "%d (%d)\n", this, tent);
+		n = strlen(tmpbuf);
+		if(n > *len)
+			n = *len;
+		if (copy_to_user(buf, tmpbuf, n))
+			return(-EFAULT);
+		*len = n;
+		filp->f_pos += n;
+		return (0);
+	}
+}
+
+#ifdef CONFIG_MOSIX_FS
+static ssize_t
+ctl_admin_mfscosts(ctl_mosix *ctl, int write, struct file *filp,
+			void *buf, size_t *len)
+{
+	ssize_t result = ctl_uintarr(ctl, write, filp, buf, len);
+
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	if(write)
+		info_update_mfscosts();
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	return(result);
+}
+
+static ssize_t
+ctl_admin_mfskill(ctl_mosix *ctl, int write, struct file *filp,
+	       void *buf, size_t *len)
+{
+	ssize_t error = 0;
+	int l;
+	char *filename;
+
+	if(!write)
+		return(-EPERM);
+	if(filp->f_pos)
+		return(0);
+	filename = getname(buf);
+	if(IS_ERR(filename))
+		return((int)filename);
+	l = strlen(filename);
+	if(l > *len)
+	{
+		filename[*len] = '\0';
+		l = *len;
+	}
+	if(l && filename[l-1] == '\n')
+		filename[--l] = '\0';
+	if(strchr(filename, '\n') || l >= *len)
+		error = -EINVAL;
+	else
+		error = mfs_kill(filename);
+	putname(filename);
+	if(!error)
+		filp->f_pos += *len;
+	return (error ? : 0);
+}
+#endif /* CONFIG_MOSIX_FS */
+
+static ssize_t
+ctl_admin_version(ctl_mosix *ctl, int write, struct file *filp,
+		  void *buf, size_t *len)
+{
+	int n, left;
+	char tmpbuf[100];
+
+	if ((filp->f_pos) || !*len) {
+		*len = 0;
+		return (0);
+	}
+
+	left = *len;
+	*len = 0;
+
+	sprintf(tmpbuf, "openMosix Version %d.%d.%d\nDFSA is %sabled\n"
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		"Maximum network topology = %d\n"
+#else
+		"Simple network topology\n"
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		, MOSIX_VERSION_PARTS(MOSIX_KERNEL_VERSION),
+#ifdef CONFIG_MOSIX_DFSA
+		"en"
+#else
+		"dis"
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		, MAX_MOSIX_TOPOLOGY
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		);
+	n = strlen(tmpbuf);
+	if(n > left)
+		n = left;
+	if (copy_to_user(buf, tmpbuf, n))
+		return (-EFAULT);
+	*len += n;
+	filp->f_pos += *len;
+	return (0);
+}
+
+static ssize_t
+ctl_admin_config(ctl_mosix *ctl, int write, struct file *filp,
+		 void *buf, size_t *len)
+{
+	struct mosixnet *mos;
+	int copy = *len;
+	int pos = copy / sizeof(struct mosixnet);
+	int fpos = filp->f_pos / sizeof(struct mosixnet);
+	int error = 0;
+
+	/* position in this file is entry # in the config */
+
+
+	/* truncate read/write to multiples of sizeof(strcut mosixnet) */
+	if (*len % sizeof(struct mosixnet))
+		*len -= *len % sizeof(struct mosixnet);
+
+	if ((write && filp->f_pos) || !*len) {
+		*len = 0;
+		return (0);
+	}
+
+
+	if (write) {
+		pos = copy / sizeof(struct mosixnet);
+		if(pos <= 0)
+		{
+			*len = 0;
+			return(0);
+		}
+		if (!(mos = (struct mosixnet *) kmalloc(copy, GFP_USER)))
+			return (-ENOMEM);
+		if (copy_from_user((char *) mos, buf, copy))
+		{
+			kfree(mos);
+			return (-EFAULT);
+		}
+		error = mosix_config_set_table(mos, pos,
+					mosix_config_get_tentative_pe());
+		if (error)
+			kfree((void *) mos);
+	} else {
+		pos = mosix_config_get_table(&mos, fpos, pos);
+		if (pos < 0)
+			return (pos);
+		copy = pos * sizeof(struct mosixnet);
+		if (copy)
+		{
+			if(copy_to_user(buf, (char *) mos, copy))
+				error = -EFAULT;
+			kfree((void *) mos);
+		}
+	}
+
+	if (error < 0)
+		return (error);
+	*len = copy;
+	filp->f_pos += copy;
+	return (0);
+}
+
+static ssize_t
+ctl_admin_expel(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	int val = 0;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(int), 0, ctl_boolean};
+
+	if (!write)
+		return (-EPERM);
+	
+	tmpctl.data = &val;
+	error = get_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+		return (error);
+	*len = error;
+	return (val ? expel(0) : 0);
+}
+
+static ssize_t
+ctl_admin_bring(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	int val = 0;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(int), 0, ctl_boolean};
+
+	if (!write)
+		return (-EPERM);
+	
+	tmpctl.data = &val;
+	error = get_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+		return (error);
+	*len = error;
+	return (val ? bring() : 0);
+}
+
+static ssize_t
+ctl_admin_speed(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	int val = cpuspeed;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(int), 0, ctl_minmaxv};
+
+	tmpctl.data = &val;
+	tmpctl.extra[0] = (void *)1;
+	tmpctl.extra[1] = (void *)65535;
+
+	if (write)
+		error = get_intarr(filp, buf, *len, &tmpctl);
+	else
+		error = put_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+		return (error);
+	*len = error;
+	if(write)
+	{
+		lock_mosix();
+		cpuspeed = val;
+		set_my_cpuspeed();
+		unlock_mosix();
+	}
+	return (0);
+}
+#ifdef CONFIG_MOSIX_LOADLIMIT
+extern void set_loadlimit(void);
+extern void set_loadlimitmode(void);
+extern void set_cpulimit(void);
+extern void set_cpulimitmode(void);
+static ssize_t
+ctl_admin_loadlimit(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	unsigned long val = load_limit;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(unsigned long), 0, ctl_uintarr};
+
+	tmpctl.data = &val;
+	if (write)
+		error = get_intarr(filp, buf, *len, &tmpctl);
+	else
+		error = put_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+		return (error);
+	*len = error;
+	if(write)
+	{
+		lock_mosix();
+		load_limit = val;
+		set_loadlimit();
+		/*set_my_cpuspeed();*/
+		unlock_mosix();
+	}
+	return (0);
+}
+static ssize_t
+ctl_admin_llimitmode(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	unsigned long val = mosadmin_mode_loadlimit;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(unsigned long), 
+	  0, ctl_minmaxv};
+	tmpctl.extra[0] = (void *)0;
+	tmpctl.extra[1] = (void *)2;
+	tmpctl.data = &val;
+	if (write)
+  	  error = get_intarr(filp, buf, *len, &tmpctl);
+	else
+	  error = put_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+	  return (error);
+	*len = error;
+	if(write)
+  	  {
+	    lock_mosix();
+	    mosadmin_mode_loadlimit = val;
+	    set_loadlimitmode();
+	    unlock_mosix();
+  	  }
+	return (0);
+}
+static ssize_t
+ctl_admin_cpulimit(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	unsigned long val = cpu_limit;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(unsigned long), 0, ctl_uintarr};
+
+	tmpctl.data = &val;
+	if (write)
+		error = get_intarr(filp, buf, *len, &tmpctl);
+	else
+		error = put_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+		return (error);
+	*len = error;
+	if(write)
+	{
+		lock_mosix();
+		cpu_limit = val;
+		set_cpulimit();
+		unlock_mosix();
+	}
+	return (0);
+}
+static ssize_t
+ctl_admin_cpulimitmode(ctl_mosix *ctl, int write, struct file *filp,
+		void *buf, size_t *len)
+{
+	unsigned long val = mosadmin_mode_loadlimit;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(unsigned long), 
+	  0, ctl_minmaxv};
+	tmpctl.extra[0] = (void *)0;
+	tmpctl.extra[1] = (void *)2;
+	tmpctl.data = &val;
+	if (write)
+  	  error = get_intarr(filp, buf, *len, &tmpctl);
+	else
+	  error = put_intarr(filp, buf, *len, &tmpctl);
+	if (error < 0)
+	  return (error);
+	*len = error;
+	if(write)
+  	  {
+	    lock_mosix();
+	    mosadmin_mode_cpulimit = val;
+	    set_cpulimitmode();
+	    unlock_mosix();
+  	  }
+	return (0);
+}
+#endif
+
+static ssize_t
+ctl_admin_mode(ctl_mosix *ctl, int write, struct file *filp,
+	       void *buf, size_t *len)
+{
+	int val, mode;
+	int error;
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(int), 0, ctl_boolean};
+
+	tmpctl.data = &val;
+
+	switch (ctl->ctl_name) {
+	case ADMIN_STAY:
+		mode = DS_STAY;
+		break;
+	case ADMIN_LSTAY:
+		mode = DS_LSTAY;
+		break;
+	case ADMIN_BLOCK:
+		mode = DS_BLOCK;
+		break;
+	case ADMIN_QUIET:
+		mode = DS_QUIET;
+		break;
+	case ADMIN_NOMFS:
+		mode = DS_NOMFS;
+		break;
+	default:
+		panic("ctl_admin_mode: invalid ctl_name");
+	}
+
+	if (write) {
+		error = get_intarr(filp, buf, *len, &tmpctl);
+		if (error < 0)
+			return (error);
+		*len = error;
+		return (admin_set_mode(mode, val));
+	} else {
+		val = admin_get_mode(mode);
+		error = put_intarr(filp, buf, *len, &tmpctl);
+		if (error < 0)
+			return (error);
+		*len = error;
+		return (0);
+	}
+}
+
+static ssize_t
+ctl_admin_slowdecay(ctl_mosix *ctl, int write, struct file *filp,
+		    void *buf, size_t *len)
+{
+	ctl->data = (void *) &slow_alpha;
+	ctl->extra[0] = (void *) fast_alpha;
+	ctl->extra[1] = (void *) DECAY_QUOTIENT;
+	return (do_intarr(ctl, write ? CTLF_MINMAXV : 0, filp, buf, len, 1));
+}
+
+static ssize_t
+ctl_admin_fastdecay(ctl_mosix *ctl, int write, struct file *filp,
+		    void *buf, size_t *len)
+{
+	ctl->data = (void *) &fast_alpha;
+	ctl->extra[0] = (void *) 0;
+	ctl->extra[1] = (void *) slow_alpha;
+	return (do_intarr(ctl, write ? CTLF_MINMAXV : 0, filp, buf, len, 1));
+}
+
+static ssize_t
+ctl_admin_decayinterval(ctl_mosix *ctl, int write, struct file *filp,
+		        void *buf, size_t *len)
+{
+	ctl->data = (void *) &decay_interval;
+	ctl->extra[0] = (void *) 1;
+	ctl->extra[1] = (void *) 65535;
+	return (do_intarr(ctl, write ? CTLF_MINMAXV : 0, filp, buf, len, 1));
+}
+
+void
+proc_update_costs(void)
+{
+	register int i;
+	register struct task_struct *p;
+
+	lock_mosix();
+	for(i = 0 ; i < MAX_MOSIX_TOPOLOGY ; i++)
+	{
+		deputy_here[i].page = mosix_cost[i].PAGE_D;
+		deputy_here[i].syscall = mosix_cost[i].SYSCALL_D;
+		deputy_here[i].out = mosix_cost[i].COPYOUT_BASE_D;
+		deputy_here[i].outkb = mosix_cost[i].COPYOUT_PER_KB_D;
+		deputy_here[i].in = mosix_cost[i].COPYIN_BASE_D;
+		deputy_here[i].inkb = mosix_cost[i].COPYIN_PER_KB_D;
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		deputy_here[i].first = mosix_cost[i].first;
+		deputy_here[i].last = mosix_cost[i].last;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	}
+	info_update_costs();
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if(p->mosix.dflags & DDEPUTY)
+	{
+		tell_process(p, DREQ_UPDOVERHEADS);
+		wake_up_mosix(p);
+	}
+	read_unlock(&tasklist_lock);
+	unlock_mosix();
+}
+
+static ssize_t
+ctl_admin_overheads(ctl_mosix *ctl, int write, struct file *filp,
+			void *buf, size_t *len)
+{
+	ssize_t result = ctl_uintarr(ctl, write, filp, buf, len);
+
+	if(write)
+		proc_update_costs();
+	return(result);
+}
+
+static loff_t
+proc_lseekmosixinfo(struct file *filp, loff_t offset, int orig)
+{
+	switch (orig) {
+		case 0:
+			break;
+		case 1:
+			offset += filp->f_pos;
+			break;
+		case 2:
+			offset += mosix_config_get_limit();
+			break;
+		default:
+			return (-EINVAL);
+        }
+	if(offset < 0 || offset > MOSIX_MAX)
+		return(-EINVAL);
+	filp->f_pos = offset;
+	return (offset);
+}
+
+static ssize_t
+ctl_info_infos(ctl_mosix *ctl, int write, struct file *filp,
+	       void *buf, size_t *len)
+{
+	int end;
+	int n, err;
+
+	end = (*len / sizeof(struct mosix_info)) + filp->f_pos;
+	if(end > (n = mosix_config_get_limit()))
+		end = n;
+	*len = 0;
+	if((n = end - filp->f_pos) > 0)
+	{
+		if((err = balance_get_infos(filp->f_pos + 1, n,
+						(struct mosix_info *)buf, 1)))
+			return(err);
+		filp->f_pos += n;
+		*len = n * sizeof(struct mosix_info);
+	}
+
+	return (0);
+}
+
+#define	get_item(x, node, undef, notup) ( { \
+		struct mosix_info info; \
+		(void) balance_get_info(node, &info); \
+		(info.status & DS_MOSIX_UP) ? info.x : \
+		(info.status & DS_MOSIX_DEF) ? notup : undef; } )
+
+static ssize_t
+ctl_info_fill(ctl_mosix *ctl, int write, struct file *filp,
+	      void *buf, size_t *len)
+{
+	int i, end;
+	int total = 0;
+	s64 val;
+
+	end = (*len / sizeof(u64)) + filp->f_pos;
+	if(end > (i = mosix_config_get_limit()))
+		end = i;
+	for (i = filp->f_pos + 1; i <= end; i++) {
+		switch (ctl->ctl_name) {
+		case INFO_LOADS:
+			val = get_item(load, i, -ENXIO, -ENETUNREACH);
+			break;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		case INFO_LOADLIMIT:
+			val = get_item(load_limit, i, -ENXIO, -ENETUNREACH);
+ 			break;
+		case INFO_LLIMITMODE:
+			val = get_item(llimitmode, i, -ENXIO, -ENETUNREACH);
+ 			break;
+		case INFO_LOADREMOTE:
+			val = get_item(loadremote, i, -ENXIO, -ENETUNREACH);
+ 			break;
+		case INFO_LOADLOCAL:
+			val = get_item(loadlocal, i, -ENXIO, -ENETUNREACH);
+ 			break;
+		case INFO_CPULIMIT:
+			val = get_item(cpu_limit, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_CPULIMITMODE:
+			val = get_item(cpulimitmode, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_CPUREMOTE:
+			val = get_item(cpuremote, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_CPULOCAL:
+			val = get_item(cpulocal, i, -ENXIO, -ENETUNREACH);
+			break;
+#endif
+		case INFO_SPEEDS:
+			val = get_item(speed, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_CPUS:
+			val = get_item(ncpus, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_MEMS:
+			val = get_item(mem, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_RMEMS:
+			val = get_item(rmem, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_TMEMS:
+			val = get_item(tmem, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_UTILS:
+			val = get_item(util, i, -ENXIO, -ENETUNREACH);
+			break;
+		case INFO_STATA:
+			val = get_item(status, i, 0, DS_MOSIX_DEF);
+			break;
+		default:
+			mosix_panic("ctl_info_fill - bad name");
+			return (-EDIST);
+		}
+		if (copy_to_user(buf, (char *) &val, sizeof(u64)))
+			return (-EFAULT);
+		filp->f_pos++;
+		buf += sizeof(u64);
+		total += sizeof(u64);
+	}
+	*len = total;
+	return (0);
+}
+
+static ssize_t
+ctl_decay(ctl_mosix *ctl, int write, struct file *filp, void *buf, size_t *len)
+{
+	int val, policy;
+	int error;
+	int (*func)(int);
+	int decay[2];
+	struct ctl_mosix tmpctl = {0, NULL, NULL, sizeof(int), 0, ctl_boolean};
+
+	tmpctl.data = &val;
+
+	switch (ctl->ctl_name) {
+	case DECAY_INHERIT:
+		func = decay_inherit;
+		goto r01w01;
+	case DECAY_EXEC:
+		func = decay_exec;
+		goto r01w01;
+	case DECAY_EXECONCE:
+		func = decay_execonce;
+	r01w01:
+		if (write) {
+			error = get_intarr(filp, buf, *len, &tmpctl);
+			if (error < 0)
+				return (error);
+			(*func)(val);
+		} else {
+			val = (*func)(-1);
+			error = put_intarr(filp, buf, *len, &tmpctl);
+			if (error < 0)
+				return (error);
+		}
+		break;
+
+	case DECAY_CPUJOB:
+		policy = DADV_CPU;
+		goto r01w1;
+	case DECAY_IOJOB:
+		policy = DADV_NOCPU;
+		goto r01w1;
+	case DECAY_SLOW:
+		policy = DADV_SLOWDECAY;
+		goto r01w1;
+	case DECAY_FAST:
+		policy = DADV_FASTDECAY;
+	r01w1:
+		if (write) {
+			error = get_intarr(filp, buf, *len, &tmpctl);
+			if (error < 0)
+				return (error);
+			if (val != 1)
+				return (-EINVAL);
+			decay_set(policy, 0, 1);
+		} else {
+			val = decay_get(policy);
+			error = put_intarr(filp, buf, *len, &tmpctl);
+			if (error < 0)
+				return (error);
+		}
+		break;
+
+	case DECAY_OWN:
+		tmpctl.data = (void *) decay;
+		tmpctl.maxlen = 2 * sizeof(int);
+		tmpctl.handler = ctl_uintarr;
+
+		/* to force an error in case of partial data */
+		decay[0] = decay[1] = 0;
+
+		if (write) {
+			error = get_intarr(filp, buf, *len, &tmpctl);
+			if (error < 0)
+				return (error);
+			if (decay[0] < 0 || decay[0] > DECAY_QUOTIENT
+			    || decay[1] < 1 || decay[1] > 65535)
+				return (-EINVAL);
+			decay_set(DADV_OWNDECAY, decay[0], decay[1]);
+		} else {
+			if (decay_get(DADV_OWNDECAY)) {
+				decay[0] = current->mosix.decay;
+				decay[1] = current->mosix.deccycle;
+			} else
+				tmpctl.maxlen = sizeof(int);
+			error = put_intarr(filp, buf, *len, &tmpctl);
+			if (error < 0)
+				return (error);
+		}
+		break;
+
+	case DECAY_CLEAR:
+		if (!write)
+			return (-EPERM);
+		error = get_intarr(filp, buf, *len, &tmpctl);
+		if (error < 0)
+			return (error);
+		if (val != 1)
+			return (-EINVAL);
+		decay_clear();
+		break;
+	default:
+		return (-EBADF);
+	}
+	*len = error;
+	return (0);
+}
+
+
+#define for_each_remote_task(p) \
+        for (p = &init_task ; (p = p->next_task) != &init_task ; ) \
+	        if(p->mosix.dflags & DREMOTE)
+
+
+#define NUMBUF	10
+
+static int
+proc_mosix_remote_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct task_struct *p;
+	char buf[NUMBUF];
+	unsigned int nr = filp->f_pos;
+	pid_t *pids;
+	int k, n = 0;
+
+	if(filp->f_pos == 0)
+	{
+		if(filldir(dirent, ".", 1, 0, filp->f_dentry->d_inode->i_ino,
+								DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 1;
+	}
+	if(filp->f_pos == 1)
+	{
+		if(filldir(dirent, "..", 2, 1,
+			filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 2;
+	}
+
+	n = 1;
+	while(1)
+	{
+		k = count_guests(); /* usually correct, but not 100% reliable */
+		if(k > n)
+			n = k;
+		if(!(pids = (pid_t *)kmalloc(n * sizeof(pid_t), GFP_KERNEL)))
+			return(-ENOMEM);
+		read_lock(&tasklist_lock);
+		/* new guest(s) could come in while we waited for memory! */
+		k = 0;
+		for_each_remote_task(p)
+		{
+			if(k < n)
+				pids[k++] = p->pid;
+			else
+				k++;
+		}
+		read_unlock(&tasklist_lock);
+		if(k <= n)
+		{
+			n = k;
+			break;
+		}
+		n = k + 1;
+	}
+	nr = 2;
+	for(k = 0 ; k < n ; k++) {
+		unsigned int pid;
+		unsigned long i, j;
+
+		if(nr++ < filp->f_pos)
+			continue;
+		pid = pids[k];
+
+		for (j = NUMBUF, i = pid; i; i /= 10) {
+			j--;
+			buf[j] = '0' + (i % 10);
+		}
+		if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos,
+				(pid << 16) + PROC_REMPID_INO, DT_DIR) < 0)
+			break;
+		filp->f_pos++;
+	}
+	kfree(pids);
+	return(0);
+}
+
+static int
+proc_mosix_sub_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct dentry *dp = filp->f_dentry;
+	int id = dp->d_inode->i_ino & ~0xffff;
+	struct subnames *s;
+	int i;
+
+	switch(dp->d_inode->i_ino & 0xffff)
+	{
+	case PROC_REMPID_INO:
+		s = rempid_subs;
+		break;
+	case PROC_NODEID_INO:
+		s = nodeid_subs;
+		break;
+	default:
+		printk("ino=0x%lx\n", dp->d_inode->i_ino);
+		panic("proc_mosix_sub_readdir");
+	}
+	if(filp->f_pos == 0)
+	{
+		if(filldir(dirent, ".", 1, 0, dp->d_inode->i_ino, DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 1;
+	}
+	if(filp->f_pos == 1)
+	{
+		if(filldir(dirent, "..", 2, 1, dp->d_parent->d_inode->i_ino,
+								DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 2;
+	}
+	for(i = 2 ; i < filp->f_pos ; i++)
+	if(s->name)
+		s++;
+	else
+		return(0);
+	while(s->name && filldir(dirent, s->name, strlen(s->name), filp->f_pos,
+						id | s->id, DT_REG) >= 0)
+	{
+		filp->f_pos++;
+		s++;
+	}
+	return(0);
+}
+
+static struct dentry *
+proc_mosix_sub_lookup(struct inode *dir, struct dentry *dentry)
+{
+	unsigned long dino = dir->i_ino;
+	struct subnames *s;
+	const char *name = dentry->d_name.name;
+	int len = dentry->d_name.len;
+	struct inode *inode = NULL;
+
+	switch(dino & 0xffff)
+	{
+	case PROC_REMPID_INO:
+		s = rempid_subs;
+		break;
+	case PROC_NODEID_INO:
+		s = nodeid_subs;
+		break;
+	default:
+		printk("ino=0x%lx\n", dino);
+		panic("proc_mosix_sub_lookup");
+	}
+	while(s->name)
+		if(s->namelen == len && !strncmp(s->name, name, len))
+		{
+			inode = proc_get_inode(dir->i_sb, (dino & ~0xffff)|s->id, NULL);
+			if(!inode)
+				return(ERR_PTR(-EINVAL));
+			switch(s->id)
+			{
+			case PROC_REMPID_GOTO:
+				inode->i_mode = S_IFREG | 0222;
+				break;
+			default:
+				inode->i_mode = S_IFREG | 0444;
+				break;
+			}
+			inode->i_op = &proc_mosix_sub_inode_operations;
+			inode->i_fop = &proc_mosix_sub_file_operations;
+			break;
+		}
+		else
+			s++;
+	dentry->d_op = &proc_mosix_dynamic_dentry_operations;
+	d_add(dentry, inode);
+	return(NULL);
+}
+
+int
+atoi16(const char *num, int len)
+{
+	int n = 0;
+	char c;
+
+	while(len-- > 0)
+	{
+		c = *num++;
+		if(c < '0' || c > '9')
+			return(0);
+		n = n * 10 + c - '0';
+		if(n & 0xffff0000)
+			return(0);
+	}
+	return(n);
+}
+
+static struct dentry *
+proc_mosix_remote_lookup(struct inode *dir, struct dentry *dentry)
+{
+	unsigned int pid, n;
+	struct task_struct *p;
+	struct inode *inode = NULL;
+
+	n = proc_mosix_remote.nlink;
+	read_lock(&tasklist_lock);
+	for_each_remote_task(p)
+		n++;
+	read_unlock(&tasklist_lock);
+	dir->i_nlink = n;
+
+	pid = atoi16(dentry->d_name.name, dentry->d_name.len);
+	if(!pid)
+		goto out;
+
+	read_lock(&tasklist_lock);
+	p = find_any_task_by_pid(pid);
+	if (p && !(p->mosix.dflags & DREMOTE))
+		p = NULL;
+	read_unlock(&tasklist_lock);
+
+	inode = NULL;
+	if (pid && p) {
+		inode = proc_get_inode(dir->i_sb,
+			(pid << 16) | PROC_REMPID_INO, NULL);
+		if (!inode)
+			return ERR_PTR(-EINVAL);
+		inode->i_mode = S_IFDIR | 0555;
+		inode->i_op = &proc_mosix_subdir_inode_operations;
+		inode->i_fop = &proc_mosix_subdir_file_operations;
+	}
+
+	out:
+	dentry->d_op = &proc_mosix_dynamic_dentry_operations;
+	d_add(dentry, inode);
+	return(NULL);
+}
+
+static int
+proc_mosix_nodes_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct mosixnet *mos;
+	char buf[NUMBUF];
+	unsigned int nr = filp->f_pos;
+	int nmos, k, l, node;
+
+	if(filp->f_pos == 0)
+	{
+		if(filldir(dirent, ".", 1, 0, filp->f_dentry->d_inode->i_ino,
+								DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 1;
+	}
+	if(filp->f_pos == 1)
+	{
+		if(filldir(dirent, "..", 2, 1,
+				filp->f_dentry->d_parent->d_inode->i_ino,
+								DT_DIR) < 0)
+			return(0);
+		filp->f_pos = 2;
+	}
+
+	if((nmos = mosix_config_get_table(&mos, 0, 0)) <= 0)
+		return (nmos);
+	
+	nr = 2;
+	for(k = 0 ; k < nmos ; k++)
+		for (l = 0; l < mos[k].cnt; l++) {
+			unsigned long i, j;
+
+			if(nr++ < filp->f_pos)
+				continue;
+
+			node = mos[k].base + l;
+			for (j = NUMBUF, i = node; i; i /= 10) {
+				j--;
+				buf[j] = '0' + (i % 10);
+			}
+			if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos,
+				(node << 16)+PROC_NODEID_INO, DT_REG) < 0)
+				goto out;
+			filp->f_pos++;
+		}
+out:
+	if(nmos)
+		kfree(mos);
+	return (0);
+}
+
+static struct dentry *
+proc_mosix_nodes_lookup(struct inode *dir, struct dentry *dentry)
+{
+	unsigned int node;
+	struct inode *inode = NULL;
+
+	dir->i_nlink = proc_mosix_nodes.nlink + count_mosix_nodes();
+
+	node = atoi16(dentry->d_name.name, dentry->d_name.len);
+
+	if(!mos_to_net(node, NULL))
+		node = 0;
+	if (node)
+	{
+		inode = proc_get_inode(dir->i_sb,
+			(node << 16) | PROC_NODEID_INO, NULL);
+		if (!inode)
+			return ERR_PTR(-EINVAL);
+		inode->i_mode = S_IFDIR | 0555;
+		inode->i_op = &proc_mosix_subdir_inode_operations;
+		inode->i_fop = &proc_mosix_subdir_file_operations;
+	}
+
+	dentry->d_op = &proc_mosix_dynamic_dentry_operations;
+	d_add(dentry, inode);
+	return(NULL);
+}
+
+ssize_t
+proc_mosix_sub_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+	struct task_struct *r;
+	char *page;
+	unsigned long rino = filp->f_dentry->d_inode->i_ino;
+	unsigned long ino = rino & 0xffff;
+	int pid_or_node = rino >> 16;
+	int result;
+	int (*func)(struct task_struct *, char *);
+
+	if(!(page = (char *)__get_free_page(GFP_KERNEL)))
+		return(-ENOMEM);
+	switch(ino)
+	{
+	case PROC_REMPID_FROM:
+		func = proc_mosix_get_remote_from;
+		break;
+	case PROC_REMPID_STATM:
+		func = proc_pid_statm;
+		break;
+	case PROC_REMPID_STATS:
+		func = proc_mosix_get_remote_stats;
+		break;
+	case PROC_REMPID_IDENT:
+		func = proc_mosix_get_remote_identity;
+		break;
+	case PROC_NODEID_CPUS:
+		result = sprintf(page, "%d\n", (int)get_item(ncpus,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_LOAD:
+		result = sprintf(page, "%d\n", (int)get_item(load,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	case PROC_NODEID_LOADLIMIT:
+		result = sprintf(page, "%d\n", (int)get_item(load_limit,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_LLIMITMODE:
+		result = sprintf(page, "%d\n", (int)get_item(llimitmode,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_LOADLOCAL:
+		result = sprintf(page, "%d\n", (int)get_item(loadlocal,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_LOADREMOTE:
+		result = sprintf(page, "%d\n", (int)get_item(loadremote,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_CPULIMIT:
+		result = sprintf(page, "%d\n", (int)get_item(cpu_limit,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_CPULIMITMODE:
+		result = sprintf(page, "%d\n", (int)get_item(cpulimitmode,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_CPULOCAL:
+		result = sprintf(page, "%d\n", (int)get_item(cpulocal,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_CPUREMOTE:
+		result = sprintf(page, "%d\n", (int)get_item(cpuremote,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+#endif
+	case PROC_NODEID_MEM:
+		result = sprintf(page, "%lld\n",
+		    		(s64)get_item(mem, pid_or_node,
+					-ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_RMEM:
+		result = sprintf(page, "%lld\n",
+				(s64)get_item(rmem, pid_or_node,
+					-ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_SPEED:
+		result = sprintf(page, "%d\n", (int)get_item(speed,
+		      				pid_or_node,
+					-ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_TMEM:
+		result = sprintf(page, "%lld\n",
+			     	(s64) get_item(tmem, pid_or_node,
+					-ENXIO, -ENETUNREACH));
+		goto copy;
+	case PROC_NODEID_STATUS:
+		result = sprintf(page, "%d\n", (int)get_item(status,
+							     pid_or_node, 0, DS_MOSIX_DEF));
+		goto copy;
+	case PROC_NODEID_UTIL:
+		result = sprintf(page, "%d\n", (int)get_item(util,
+							     pid_or_node, -ENXIO, -ENETUNREACH));
+		goto copy;
+	default:
+		result = -EPERM;	/* write-only */
+		goto out;
+	}
+	result = -EBADF;
+	read_lock(&tasklist_lock);
+	r = find_any_task_by_pid(pid_or_node);
+	if(r && !(r->mosix.dflags & DREMOTE))
+		r = NULL;
+	if(r)
+		get_task_struct(r);
+	read_unlock(&tasklist_lock);
+	if(!r)
+		goto out;
+	result = (*func)(r, page);
+	free_task_struct(r);
+	copy:
+	if(result > 0)
+	{
+		if(*ppos + count > result)
+		{
+			count = result - *ppos;
+			if(count < 0)
+				count = 0;
+		}
+		if(count && copy_to_user(buf, page, count))
+			return(-EFAULT);
+		*ppos += count;
+		result = count;
+	}
+	out:
+	free_page((unsigned long)page);
+	return(result);
+}
+
+ssize_t
+proc_mosix_sub_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+	unsigned long rino = filp->f_dentry->d_inode->i_ino;
+	unsigned long ino = rino & 0xffff;
+	int pid_or_node = rino >> 16;
+			
+	switch(ino) {
+	case PROC_REMPID_GOTO:
+		return(proc_mosix_set_remote_goto(filp, pid_or_node,
+						  buf, count));
+	default:
+		return(-EPERM);		/* read-only */
+	}
+}
+
+ssize_t
+proc_mosix_pid_set_migrate(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int mig, error, len;
+	struct ctl_mosix tmpctl =
+		{ 0, "migrate", NULL, sizeof(int), 0, ctl_minmaxv };
+
+	if(task != current)
+		return(-EPERM);
+
+	tmpctl.data = &mig;
+	tmpctl.extra[0] = (void *) DM_BALANCE;
+	tmpctl.extra[1] = (void *) MOSIX_MAX;
+	error = get_intarr(filp, buf, cnt, &tmpctl);
+	if (error < 0)
+		return (error);
+	len = error;
+
+	if ((error = mig_migrate(mig)))
+		return (error);
+	else
+		return (len);
+}
+
+ssize_t
+proc_mosix_pid_set_goto(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int whereto, error;
+	struct ctl_mosix tmpctl =
+		{ 0, "goto", NULL, sizeof(int), 0, ctl_minmaxv };
+
+	/* the rule is: if you can send it a signal, you may also migrate it: */
+	/* so keep looking for changes in "kernel/signal.c" */
+
+	if ((current->euid ^ task->suid) && (current->euid ^ task->uid) &&
+		(current->uid ^ task->suid) && (current->uid ^ task->uid) &&
+		!capable(CAP_KILL))
+		return(-EPERM);
+
+	tmpctl.data = &whereto;
+	tmpctl.extra[0] = (void *) DM_BALANCE;
+	tmpctl.extra[1] = (void *) MOSIX_MAX;
+	error = get_intarr(filp, buf, cnt, &tmpctl);
+	if (error < 0)
+		return (error);
+	if(whereto > 0 && !mos_to_net(whereto, NULL))
+		return(-ENODEV);
+
+	if (whereto <= 0) {
+		switch (whereto) {
+		case DM_GOBACKHOME:
+			whereto = GOBACKHOME;
+			break;
+		case DM_BALANCE:
+			whereto = BALANCE;
+			break;
+
+		default:
+			return(-EINVAL);
+		}
+	}
+	if (task->mosix.stay & DSTAY)
+		return (-EROFS);
+	mosix_add_to_whereto(task, whereto);
+	return (error);
+}
+
+ssize_t
+proc_mosix_pid_set_lock(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int lock, len;
+	struct ctl_mosix ctl =
+		{ 0, "lock", NULL, sizeof(int), 0, ctl_boolean };
+
+	ctl.data = (void *)&lock;
+
+	if(task == current)
+	{
+		len = get_intarr(filp, buf, cnt, &ctl);
+		if (len < 0)
+			return (len);
+		mig_set_lock(lock);
+		return (len);
+	}
+	if(!suser())
+		return(-EPERM);
+	/* The SU has the special privillege of unlocking local processes */
+	len = get_intarr(filp, buf, cnt, &ctl);
+	if(len < 0)
+		return(len);
+	if(lock)
+		return(-EINVAL);
+	task_lock(task);
+	if (task->mosix.dflags & (DDEPUTY|DFINISHED))
+		len = -EACCES;
+	else
+		task->mosix.stay &= ~DNOMIGRATE;
+	task_unlock(task);
+	return(len);
+}
+
+ssize_t
+proc_mosix_pid_set_migfilter(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int migfilter, len;
+	struct ctl_mosix ctl =
+		{ 0, "migfilter", NULL, sizeof(int), 0, ctl_boolean };
+
+	ctl.data = (void *)&migfilter;
+
+	if(task == current)
+	{
+		len = get_intarr(filp, buf, cnt, &ctl);
+		if (len < 0)
+			return (len);
+		mig_set_migfilter(migfilter);
+		return (len);
+	}
+	if(!suser())
+		return(-EPERM);
+	len = get_intarr(filp, buf, cnt, &ctl);
+	if(len < 0)
+		return(len);
+	if(migfilter)
+		return(-EINVAL);
+	task_lock(task);
+	task->mosix.dflags &= ~DMIGFILTER;
+	task_unlock(task);
+	return(len);
+}
+
+ssize_t
+proc_mosix_pid_set_migpolicy(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int migpolicy, len;
+	struct ctl_mosix ctl = { 0, "migpolicy", NULL, sizeof(int), 0, ctl_positive };
+	ctl.data = (void *)&migpolicy;
+
+	if(task == current)
+	{
+		len = get_intarr(filp, buf, cnt, &ctl);
+		if (len < 0)
+			return (len);
+		mig_set_migpolicy(migpolicy);
+		return (len);
+	}
+	if(!suser())
+		return(-EPERM);
+	len = get_intarr(filp, buf, cnt, &ctl);
+	if(len < 0)
+		return(len);
+	task_lock(task);
+	task->mosix.mask.migpolicy = migpolicy;
+	task_unlock(task);
+	return(len);
+}
+
+ssize_t
+proc_mosix_pid_set_mignodes(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int mignodes, len;
+	struct ctl_mosix ctl =
+		{ 0, "mignodes", NULL, sizeof(int), 0, ctl_uintarr };
+
+	ctl.data = (void *)&mignodes;
+
+	if(task == current)
+	{
+		len = get_intarr(filp, buf, cnt, &ctl);
+		if (len < 0)
+			return (len);
+		mig_set_mignodes(mignodes);
+		return (len);
+	}
+	if(!suser())
+		return(-EPERM);
+	len = get_intarr(filp, buf, cnt, &ctl);
+	if(len < 0)
+		return(len);
+	task_lock(task);
+	task->mosix.mask.mignodes = mignodes;
+	task_unlock(task);
+	return(len);
+}
+
+ssize_t
+proc_mosix_pid_set_miggroup(struct file *filp, struct task_struct *task,
+                                                const char *buf, size_t cnt)
+{
+        int miggroup, len;
+        struct ctl_mosix ctl = { 0, "miggroup", NULL, sizeof(int), 0, ctl_positive };
+        ctl.data = (void *)&miggroup;
+
+        if(task == current)
+        {
+                len = get_intarr(filp, buf, cnt, &ctl);
+                if (len < 0)
+                        return (len);
+                mig_set_miggroup(miggroup);
+                return (len);
+        }
+        if(!suser())
+                return(-EPERM);
+        len = get_intarr(filp, buf, cnt, &ctl);
+        if(len < 0)
+                return(len);
+        task_lock(task);
+        task->mosix.mask.miggroup = miggroup;
+        task_unlock(task);
+        return(len);
+}
+
+
+
+ssize_t
+proc_mosix_pid_set_disclosure(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int disclosure, len;
+	struct ctl_mosix ctl =
+		{ 0, "disclosure", NULL, sizeof(int), 0, ctl_minmaxv };
+
+	ctl.data = (void *)&disclosure;
+	ctl.extra[0] = (void *) 0;
+	ctl.extra[1] = (void *) 3;
+
+	if(task != current)
+		return(-EPERM);
+	len = get_intarr(filp, buf, cnt, &ctl);
+	if (len < 0)
+		return (len);
+	current->mosix.disclosure = disclosure;
+	tell_process(current, DREQ_INFOCNG);
+	return(len);
+}
+
+ssize_t
+proc_mosix_pid_set_sigmig(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int sig = current->mosix.sigmig, len;
+	struct ctl_mosix tmpctl =
+		{ 0, "sigmig", NULL, sizeof(int), 0, ctl_minmaxv };
+
+	if(task != current)
+		return(-EPERM);
+
+	tmpctl.data = &sig;
+	tmpctl.extra[0] = (void *) 0;
+	tmpctl.extra[1] = (void *) _NSIG;
+	len = get_intarr(filp, buf, cnt, &tmpctl);
+	if(len >= 0)
+		current->mosix.sigmig = sig;
+	return (len);
+}
+
+#ifdef CONFIG_MOSIX_FS
+ssize_t
+proc_mosix_pid_set_selected(struct file *filp, struct task_struct *task,
+						const char *buf, size_t cnt)
+{
+	int sel, len;
+	struct ctl_mosix ctl =
+		{ 0, "lock", NULL, sizeof(int), 0, ctl_minmaxv };
+
+	if(task != current)
+		return(-EPERM);
+
+	ctl.data = (void *) &sel;
+	ctl.extra[0] = (void *) 0;
+	ctl.extra[1] = (void *) MOSIX_MAX;
+	sel = current->mosix.selected;
+	len = get_intarr(filp, buf, cnt, &ctl);
+	if (len >= 0 && sel != current->mosix.selected)
+	{
+		current->mosix.selected = sel;
+#ifdef CONFIG_MOSIX_DFSA
+		current->mosix.dupdates |= DFSA_UPDSEL;
+#endif /* CONFIG_MOSIX_DFSA */
+	}
+	return (len);
+}
+#endif /* CONFIG_MOSIX_FS */
+
+static ssize_t
+proc_mosix_set_remote_goto(struct file *filp, int pid,
+			   const char *buf, size_t cnt)
+{
+	struct task_struct *task;
+	int error, whereto;
+	struct ctl_mosix tmpctl =
+		{ 0, "goto", NULL, sizeof(int), 0, ctl_minmaxv };
+
+	if(!suser())
+		return(-EACCES);
+	read_lock(&tasklist_lock);
+	task = find_any_task_by_pid(pid);
+	if(task && !(task->mosix.dflags & DREMOTE))
+		task = NULL;
+	if(task)
+		get_task_struct(task);
+	read_unlock(&tasklist_lock);
+	if (!task)
+		return(-EBADF);
+
+	tmpctl.data = &whereto;
+	tmpctl.extra[0] = (void *) DM_BALANCE;
+	tmpctl.extra[1] = (void *) MOSIX_MAX;
+	error = get_intarr(filp, buf, cnt, &tmpctl);
+	if (error < 0)
+		goto free;
+	if(whereto > 0)
+	{
+		error = -ENODEV;
+		if(!mos_to_net(whereto, NULL))
+			goto free;
+	}
+	else switch(whereto)
+	{
+	case DM_GOBACKHOME:
+		whereto = GOBACKHOME;
+		break;
+	case DM_BALANCE:
+		whereto = BALANCE;
+		break;
+	default:
+		mosix_panic("remote_goto: invalid negative");
+	}
+
+	lock_mosix();
+	if(!(task->mosix.dflags & DFINISHED))
+		mosix_add_to_whereto(task, whereto);
+	unlock_mosix();
+	error = 0;
+	free:
+	free_task_struct(task);
+	return (error);
+}
+
+static int
+proc_mosix_get_remote_from(struct task_struct *task, char *buf)
+{
+	int node;
+	int len;
+
+	node = task->mosix.deppe;
+	sprintf(buf, "%-6d", node);
+	if (mos_to_ascii(node, buf + 6, 1000) < 0) {
+		return (-EDIST);
+	}
+	len = strlen(buf);
+	buf[len++] = '\n';
+	return (len);
+}
+
+static int
+proc_mosix_get_remote_stats(struct task_struct *tsk, char *buf)
+{
+	struct mm_struct *mm;
+	struct vm_area_struct *vma;
+	unsigned long vsize;
+	unsigned long s = LOGICAL_STATE(tsk);
+	char state;
+
+	if(s == TASK_RUNNING)
+		state = 'R';
+	else if(s & TASK_INTERRUPTIBLE)
+		state = 'S';
+	else if(s & TASK_UNINTERRUPTIBLE)
+		state = 'D';
+	else
+	{
+		printk("Oops, remote-status = 0x%lx\n", s);
+		state = '?';
+	}
+	vsize = 0;
+	mm = tsk->mm;
+	if (mm && mm != &init_mm)
+	{
+		down_read(&mm->mmap_sem);
+		for(vma = mm->mmap ; vma ; vma = vma->vm_next)
+			vsize += vma->vm_end - vma->vm_start;
+		up_read(&mm->mmap_sem);
+	}
+
+	return(sprintf(buf, "utime=%lu\ncutime=%lu\n"
+			"nice=%ld\nstate=%c\nvsize=%lu\nrss=%lu\n"
+			"nswap=%lu\ncnswap=%lu\n",
+		(unsigned long)(tsk->times.tms_utime + tsk->mosix.uttime),
+		(unsigned long)(tsk->times.tms_cutime + tsk->mosix.cutime),
+		tsk->nice,
+		state,
+		vsize,
+		tsk->mm ? tsk->mm->rss : 0,
+		tsk->nswap,
+		tsk->cnswap) + 1);
+}
+
+static int
+proc_mosix_get_remote_identity(struct task_struct *tsk, char *buf)
+{
+	char *obuf = buf;
+
+	buf[0] = '\0';
+	if(tsk->mosix.disclosure)
+	{
+		buf += sprintf(buf, "pid=%d\n", tsk->mosix.mypid);
+		if(tsk->mosix.depinfo.tgid != tsk->mosix.mypid)
+			buf += sprintf(buf, "tgid=%d\n",
+						tsk->mosix.depinfo.tgid);
+	}
+	if(tsk->mosix.disclosure > 1)
+		buf += sprintf(buf, "uid=%d\ngid=%d\n", tsk->uid, tsk->gid);
+	if(tsk->mosix.disclosure > 2)
+		buf += sprintf(buf, "pgrp=%d\nsession=%d\nnmigs=%d\ncommand=%.16s\n",
+			tsk->mosix.depinfo.pgrp, tsk->mosix.depinfo.session,
+			tsk->mosix.nmigs, tsk->mosix.depinfo.comm);
+	return(buf - obuf);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/info.c linux-openmosix/hpc/info.c
--- linux/hpc/info.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/info.c	2004-04-06 21:19:38.000000000 +0200
@@ -0,0 +1,980 @@
+/* changes since Feb 12, 2002 by Moshe Bar
+ *
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh, Amnon Barak, Oren Laadan.
+ */
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/hpcctl.h>
+#include <net/sock.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <hpc/protocol.h>
+#include <linux/hpc.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <hpc/hpcversion.h>
+#include <hpc/balance.h>
+
+static int info_seed1, info_seed2;
+
+rwlock_t loadinfo_lock = RW_LOCK_UNLOCKED;
+spinlock_t uplist_lock = SPIN_LOCK_UNLOCKED;
+
+struct uplist {
+	struct uplist *next;
+	unsigned short pe;
+	short age;
+};
+#ifdef CONFIG_MOSIX_LOADLIMIT
+extern unsigned long load_limit;
+extern unsigned long cpu_limit;
+extern unsigned long mosadmin_mode_loadlimit;
+extern unsigned long mosadmin_mode_cpulimit;
+#endif
+
+static struct uplist uplist[MAXKNOWNUP];
+static struct uplist *uphead, *upfree;
+static int info_nup;		/* number of processes in uplist */
+
+struct loadinfo loadinfo[INFO_WIN];
+
+static int info_recv_message(struct infomsg *, int);
+static int info_send_message(int, struct infomsg *);
+static void update_uplist(struct loadinfo *);
+static void update_window(struct loadinfo *);
+static void inform(void);
+static void not_responding(int);
+static void age_uplist(void);
+static int rand(int, int);
+
+static char INFODSTR[] = "oM_infoD";
+
+#define INFO_BUFSIZE	8192
+
+int
+mosix_info_daemon(void *nothing)
+{
+	struct task_struct *p = current;
+	struct loadinfo *load;
+	struct infomsg *msg;
+	static char info_buf[INFO_BUFSIZE]; /* (large) buffer for info load */
+
+	common_daemon_setup(INFODSTR, 1);
+	lock_mosix();
+	info_proc = current;
+	unlock_mosix();
+
+restart:
+	wait_for_mosix_configuration(&info_daemon_active);
+	comm_init_linkpool();
+	if (!p->mosix.contact) {
+		comm_use(p, comm_open(COMM_INFO, 0, 0UL));
+		if (!p->mosix.contact)
+		{
+			printk("%s: failed comm_open - exiting\n", INFODSTR);
+			comm_free_linkpool();
+			if(p->mosix.contact)
+				comm_close(NULL);
+			lock_mosix();
+			info_daemon_active = 0;
+			info_proc = NULL;
+			unlock_mosix();
+			do_exit(0);
+		}
+	}
+
+	msg = (struct infomsg *) info_buf;
+	load = (struct loadinfo *) &msg->load;
+
+	while (1) {
+		comm_wait();
+
+		/* if openMosix was shut down - restart everything */
+                if (!PE) {
+                        comm_close(NULL);
+			comm_free_linkpool();
+                        goto restart;
+                }
+
+		while (info_recv_message(msg, INFO_BUFSIZE))
+		{
+			update_uplist(load);
+			update_window(load);
+			if (!mosadmin_mode_quiet) {
+				load_balance();
+				memory_balance();
+			}
+		}
+
+		if(sigismember(&p->pending.signal, SIGALRM))
+		{
+			spin_lock_irq(&p->sigmask_lock);
+			flush_signals(p);
+			spin_unlock_irq(&p->sigmask_lock);
+
+			if(mosadmin_mode_quiet)
+				continue;
+
+			if(PE)
+				inform();
+			inc_decays();
+			comm_age_linkpool();
+			age_uplist();
+			loadinfo[0].mem = latest_free_mem;
+			loadinfo[0].rmem = nr_free_pages();
+			age_balancing();
+		}
+	}
+}
+
+static void
+age_uplist(void)
+{
+	struct uplist *up, *prev, *cutpoint;
+	int old = 10 * (NPE-1);
+	/* (the more nodes around, the less often they are
+	 * likely to come up again, so we hold them longer) */
+
+	if(old > 32767)
+		old = 32767;
+	spin_lock(&uplist_lock);
+	for (prev = NULL, up = uphead; up; prev = up , up = up->next)
+	if (++up->age >= old)
+	{
+		/* the list is sorted by age, so all the rest are too old! */
+		if (prev)
+			prev->next = NULL;
+		else
+			uphead = NULL;
+		cutpoint = up;
+		while(1)
+		{
+			info_nup--;
+			if(up->next)
+				up = up->next;
+			else
+				break;
+		}
+		prev = upfree;
+		upfree = cutpoint;
+		up->next = prev;
+		break;
+	}
+	spin_unlock(&uplist_lock);
+}
+
+static void
+update_uplist(struct loadinfo *load)
+{
+	struct uplist *up, *prev;
+
+	spin_lock(&uplist_lock);
+	for (prev = NULL , up = uphead ; up ; prev = up , up = up->next)
+	if (up->pe == load->pe)
+	{
+		up->age = 0;
+		if (prev)	/* put it first */
+		{
+			prev->next = up->next;
+			up->next = uphead;
+			uphead = up;
+		}
+		break;
+	}
+	if (!up) {
+		if (upfree) {
+			up = upfree;
+			upfree = upfree->next;
+			info_nup++;
+		} else {
+			for (prev = uphead ; prev->next->next ;
+				prev = prev->next)
+				; /* nothing */
+			up = prev->next;
+			prev->next = NULL;
+		}
+		up->pe = load->pe;
+		up->age = 0;
+		up->next = uphead;
+		uphead = up;
+	}
+	spin_unlock(&uplist_lock);
+        schedule(); /* since a lot of time passed, let's see if there is anything to run in the meantime */
+}
+static void
+update_window(struct loadinfo *load)
+{
+	static int info_slot; /* pointer to next information to fill */
+	unsigned int i;
+
+	info_slot = (info_slot % (INFO_WIN - 1)) + 1;
+	loadinfo[info_slot] = *load;
+
+	for (i = 1 ; i < INFO_WIN ; i++)
+	if (i != info_slot && loadinfo[i].pe == load->pe)
+	{
+		write_lock_bh(&loadinfo_lock);
+		loadinfo[i].pe = 0;
+		write_unlock_bh(&loadinfo_lock);
+		break;
+	}
+
+}
+
+#define	speed_adjust(x)		((x) * ((int64_t)STD_SPD) / loadinfo[0].speed)
+void
+info_update_costs(void)
+{
+	register unsigned int i;
+
+	write_lock_bh(&loadinfo_lock);
+	for(i = 0 ; i < MAX_MOSIX_TOPOLOGY ; i++)
+	{
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		loadinfo[0].costs[i].page = mosix_cost[i].PAGE_R;
+		loadinfo[0].costs[i].syscall = mosix_cost[i].SYSCALL_R;
+		loadinfo[0].costs[i].out = mosix_cost[i].COPYOUT_BASE_R;
+		loadinfo[0].costs[i].outkb = mosix_cost[i].COPYOUT_PER_KB_R;
+		loadinfo[0].costs[i].in = mosix_cost[i].COPYIN_BASE_R;
+		loadinfo[0].costs[i].inkb = mosix_cost[i].COPYIN_PER_KB_R;
+		loadinfo[0].costs[i].first = mosix_cost[i].first;
+		loadinfo[0].costs[i].last = mosix_cost[i].last;
+#else
+		remote_here.page = mosix_cost[i].PAGE_R;
+		remote_here.syscall = mosix_cost[i].SYSCALL_R;
+		remote_here.out = mosix_cost[i].COPYOUT_BASE_R;
+		remote_here.outkb = mosix_cost[i].COPYOUT_PER_KB_R;
+		remote_here.in = mosix_cost[i].COPYIN_BASE_R;
+		remote_here.inkb = mosix_cost[i].COPYIN_PER_KB_R;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+		remote_here_adjusted[i].page =
+					speed_adjust(mosix_cost[i].PAGE_R);
+		remote_here_adjusted[i].syscall =
+					speed_adjust(mosix_cost[i].SYSCALL_R);
+		remote_here_adjusted[i].out =
+				speed_adjust(mosix_cost[i].COPYOUT_BASE_R);
+		remote_here_adjusted[i].outkb =
+				speed_adjust(mosix_cost[i].COPYOUT_PER_KB_R);
+		remote_here_adjusted[i].in =
+				speed_adjust(mosix_cost[i].COPYIN_BASE_R);
+		remote_here_adjusted[i].inkb =
+				speed_adjust(mosix_cost[i].COPYIN_PER_KB_R);
+#ifdef CONFIG_MOSIX_TOPOLOGY
+		remote_here_adjusted[i].first = mosix_cost[i].first;
+		remote_here_adjusted[i].last = mosix_cost[i].last;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+	}
+	write_unlock_bh(&loadinfo_lock);
+}
+
+void
+info_update_mfscosts(void)
+{
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	memcpy(loadinfo[0].mfscosts, mfs_cost, sizeof(mfs_cost));
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+}
+#ifdef CONFIG_MOSIX_LOADLIMIT
+void set_loadlimit(void)
+{
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].load_limit = load_limit;
+	write_unlock_bh(&loadinfo_lock);
+}
+void set_loadlimitmode(void)
+{
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].llimitmode = mosadmin_mode_loadlimit;
+	write_unlock_bh(&loadinfo_lock);
+}
+void set_cpulimitmode(void)
+{
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].cpulimitmode = mosadmin_mode_cpulimit;
+	write_unlock_bh(&loadinfo_lock);
+}
+void set_cpulimit(void)
+{
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].cpu_limit = cpu_limit;
+	write_unlock_bh(&loadinfo_lock);
+}
+
+#endif
+void
+set_my_cpuspeed(void)
+{
+	int s = cpuspeed;
+
+	if(sizeof(loadinfo[0].speed) < 4 && s > 65535)
+	{
+		printk("Computer Too Fast!  Time to Update Standard-Speed.\n");
+		s = 65535;
+	}
+	stable_export = (MF+2) * STD_SPD / (s * smp_num_cpus);
+	if(stable_export == MF * STD_SPD / (s * smp_num_cpus))
+		stable_export++;
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].speed = s;
+	write_unlock_bh(&loadinfo_lock);
+	info_update_costs();
+	info_update_mfscosts();
+}
+
+void
+info_init(void)
+{
+	loadinfo[0].ncpus = smp_num_cpus;
+	loadinfo[0].tmem = num_physpages;
+	set_my_cpuspeed();
+}
+
+void
+info_startup(void)
+{
+	unsigned int i;
+
+	info_seed1 = PE;
+	info_seed2 = PE*PE*PE*PE;
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].pe = PE;
+	for (i = 1 ; i < INFO_WIN ; i++) {
+		loadinfo[i].pe = 0;
+		loadinfo[i].load = 0xffffffff;
+	}
+	write_unlock_bh(&loadinfo_lock);
+
+	spin_lock(&uplist_lock);
+	upfree = uphead = NULL;
+	info_nup = 0;
+
+	memset(uplist, 0, sizeof(struct uplist) * MAXKNOWNUP);
+	for (i = 0; i < MAXKNOWNUP; i++) {
+		uplist[i].next = upfree;
+		upfree = &uplist[i];
+	}
+	spin_unlock(&uplist_lock);
+}
+
+void
+info_reconfig()
+{
+	unsigned int i;
+	struct uplist *up, *prev;
+
+	lock_mosix();	/* because "mos_to_net" does! */
+	spin_lock(&uplist_lock);
+recheck:
+	prev = NULL;
+	for (up = uphead ; up ; prev = up, up = up->next)
+	if (!mos_to_net(up->pe, NULL)) {
+		if (prev)
+			prev->next = up->next;
+		else
+			uphead = up->next;
+		up->next = upfree;
+		upfree = up;
+		info_nup--;
+		goto recheck;
+	}
+	spin_unlock(&uplist_lock);
+	write_lock_bh(&loadinfo_lock);
+	for (i = 1; i < INFO_WIN; i++)
+		if (loadinfo[i].pe && !mos_to_net(loadinfo[i].pe, NULL))
+			loadinfo[i].pe = 0;
+	write_unlock_bh(&loadinfo_lock);
+	unlock_mosix();
+}
+
+static int
+info_recv_message(struct infomsg *info, int bufsize)
+{
+	static mosix_addr ra;		/* reply address */
+	struct mosix_link *l = current->mosix.contact;
+	struct loadinfo *load = &(info->load);
+	int n;
+	int sender;
+
+	while (1) {
+		n = comm_recvfrom(info, bufsize, l, &ra, 0);
+
+		if (n == -EDIST)
+			continue;	/* message > bufsize */
+
+		if (n < 0)
+			return (0);
+
+		if (n < sizeof(*info)) {
+			continue;
+		}
+
+		if (info->version != MOSIX_BALANCE_VERSION) {
+			continue;
+		}
+		if (info->topology != MAX_MOSIX_TOPOLOGY) {
+			continue;
+		}
+
+		sender = load->pe ? : load->speed;
+		if (sender > MAXPE || sender != net_to_mos(&ra)) {
+			continue;
+		}
+
+		if (sender == PE)
+		{
+			printk("WARNING: Another computer is masquerading as same openMosix node as this (%d)!\n", PE);
+			continue;
+		}
+	
+
+		if (load->pe)
+			return (1);
+
+		/*
+		 * Ugly convention: !load->pe ==> this is a GETLOAD request
+		 */
+
+		lock_mosix();
+		write_lock_bh(&loadinfo_lock);
+		loadinfo[0].status = my_mosix_status();
+		loadinfo[0].free_slots = get_free_guest_slots();
+		unlock_mosix();
+		loadinfo[0].mem = latest_free_mem;
+		loadinfo[0].rmem = nr_free_pages();
+		loadinfo[0].util = acpuse;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		loadinfo[0].load_limit = load_limit;
+		loadinfo[0].cpu_limit = cpu_limit;
+		loadinfo[0].llimitmode = mosadmin_mode_loadlimit;
+		loadinfo[0].cpulimitmode = mosadmin_mode_cpulimit;
+#endif
+#ifdef CONFIG_MOSIX_RESEARCH
+		loadinfo[0].rio = io_read_rate;
+ 		loadinfo[0].wio = io_write_rate;
+#endif /* CONFIG_MOSIX_RESEARCH */
+		*load = loadinfo[0];
+		write_unlock_bh(&loadinfo_lock);
+
+		
+		comm_sendto(COMM_TOADDR, info, sizeof(*info), l, &ra);
+	}
+	return(0);
+}
+
+static int
+info_send_message(int mos, struct infomsg *info)
+{
+
+	return(comm_sendto(mos, info, sizeof(*info), current->mosix.contact,
+								NULL) < 0);
+}
+
+int
+load_to_mosix_info(struct loadinfo l, struct mosix_info *info, int touser)
+{
+	struct mosix_info tmp, *uaddr;
+	int error;
+
+	if(touser)
+	{
+		uaddr = info;
+		info = &tmp;
+	}
+	else
+		uaddr = NULL;	/* pacify angry stupid gcc */
+	info->load = ((int64_t)l.load) * standard_speed / STD_SPD;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	info->load_limit = l.load_limit;
+	info->llimitmode = l.llimitmode;
+	info->loadlocal = l.loadlocal;
+	info->loadremote = l.loadremote;
+	info->cpulimitmode = l.cpulimitmode;
+	info->cpu_limit = l.cpu_limit;
+	info->cpulocal = l.cpulocal;
+	info->cpuremote = l.cpuremote;
+#endif
+	info->speed = l.speed;
+	info->ncpus = l.ncpus;
+	info->mem = (s64) l.mem * PAGE_SIZE;
+	info->rmem = (s64) l.rmem * PAGE_SIZE;
+	info->tmem = (s64) l.tmem * PAGE_SIZE;
+	info->util = l.util;
+
+	info->status = l.status;
+	if(touser && (error = copy_to_user((char *)uaddr, (char *)info,
+								sizeof(*info))))
+		return(-EFAULT);
+	return(0);
+}
+
+static int info_serialno = 0;
+static int info_timo;
+static int info_retry;
+static int info_retry_cnt;
+
+#define	INFO_TIMO 50000		/* ms */
+#define	INFO_RETRY 20000	/* after 20 & 40 ms */
+
+#define	SIMULTANEOUS_QUERIES		10
+
+void
+mosinfo_update_gateways(void)
+{
+	/* the following may be further optimized in the future: */
+	info_timo = INFO_TIMO * (mosadmin_gateways + 1);
+#if INFO_RETRY * 3 > 65535
+#error: "timtosend" below must be made "unsigned int".
+#endif
+	info_retry = INFO_RETRY * (mosadmin_gateways + 1);
+	info_retry_cnt = (info_timo + info_retry - 1) / info_retry;
+}
+
+int
+balance_get_infos(int first, int num, struct mosix_info *info, int touser)
+{
+	char *donebits, fewbits[20]; /* 20*8=160 seems to cover most cases */
+	struct progress
+	{
+		unsigned short node;
+		unsigned short timtosend;
+		unsigned int timo;
+		int serialno;
+	} progress[SIMULTANEOUS_QUERIES];
+	unsigned int hint = 0;
+	unsigned int ntaken = 0;
+	unsigned int ndone = 0;
+	unsigned int inpot = 0;
+	int node, from, n;
+	unsigned int i;
+	int error = 0;
+	int timo;
+	now_t before;
+	mosix_link *mlink;
+	struct loadinfo l;
+	struct infomsg infomsg;
+
+	if(num <= 8*sizeof(fewbits))
+		donebits = fewbits;
+	else if(!(donebits = (char *)kmalloc((num+7)/8, GFP_KERNEL)))
+		return(-ENOMEM);
+	memset(donebits, 0, (num+7)/8);
+	if (!(mlink = comm_borrow_linkpool()))
+		error = -EDIST;
+	loop:
+	while(!error && ndone < num)
+	{
+		while(inpot < SIMULTANEOUS_QUERIES && ntaken < num)
+		{
+			while(donebits[hint/8] & (1 << (hint%8)))
+			if(++hint == num)
+				hint = 0;
+			donebits[hint/8] |= (1 << (hint%8));
+			ntaken++;
+			node = first + hint;
+			if (node == PE)
+			{
+				read_lock_bh(&loadinfo_lock);
+				l = loadinfo[0];
+				read_unlock_bh(&loadinfo_lock);
+				l.status = my_mosix_status();
+#ifdef CONFIG_MOSIX_LOADLIMIT
+				l.load_limit = load_limit;
+				l.llimitmode = mosadmin_mode_loadlimit;
+				l.cpulimitmode = mosadmin_mode_cpulimit; 
+				l.cpu_limit = cpu_limit;
+#endif
+				l.util = acpuse;
+#ifdef CONFIG_MOSIX_RESEARCH 
+				l.rio = io_read_rate;
+				l.wio = io_write_rate;
+#endif /* CONFIG_MOSIX_RESEARCH  */
+				ready_immediate:
+				ndone++;
+				if((error = load_to_mosix_info(l, &info[hint],
+								touser)))
+					break;
+				continue;
+			}
+			if (!mos_to_net(node, NULL))
+			{
+				l.status = 0;
+				goto ready_immediate;
+			}
+			progress[inpot].node = node;
+			progress[inpot].timo = info_timo;
+			progress[inpot].timtosend = 0;
+			progress[inpot].serialno = info_serialno++;
+			inpot++;
+		}
+		if(error || ndone == num)
+			break;
+		timo = info_retry;
+		for(i = 0 ; i < inpot ; i++)
+		{
+			if(progress[i].timo < timo)
+				timo = progress[i].timo;
+			if(progress[i].timo && progress[i].timtosend <= 0)
+			{
+				progress[i].timtosend = info_retry;
+				infomsg.version = MOSIX_BALANCE_VERSION;
+				infomsg.serialno = progress[i].serialno;
+				infomsg.topology = MAX_MOSIX_TOPOLOGY;
+				infomsg.load.pe = 0;	/* eg. GETLOAD */
+				infomsg.load.speed = PE;
+				if(comm_sendto(progress[i].node, &infomsg,
+					sizeof(infomsg), mlink, NULL) <= 0)
+				{
+					node = progress[i].node;
+					progress[i] = progress[--inpot];
+					ndone++;
+					l.status = DS_MOSIX_DEF;
+					error = load_to_mosix_info(l,
+						&info[node - first], touser);
+					goto loop;
+				}
+			}
+			if(progress[i].timtosend < timo)
+				timo = progress[i].timtosend;
+		}
+		before = time_now();
+		n = comm_recvfrompe(&infomsg, sizeof(infomsg), mlink, &from,
+								info_retry);
+		if (n == sizeof(infomsg))
+		for (i = 0; i < inpot; i++) {
+			if (from == progress[i].node &&
+			    infomsg.load.pe == progress[i].node &&
+			    infomsg.serialno == progress[i].serialno) {
+			    	ndone++;
+				node = progress[i].node;
+				progress[i] = progress[--inpot];
+				error = load_to_mosix_info(infomsg.load,
+						&info[node - first], touser);
+				break;
+			}
+		} else if (signal_pending(current))
+			error = -EINTR;
+		if (error)
+			break;
+
+		before = time_since(before);
+		if(before > timo)
+			before = timo;
+		if(before)
+		for(i = 0 ; i < inpot ; i++)
+		{
+			progress[i].timo -= before;
+			if(progress[i].timtosend < before)
+				progress[i].timtosend = 0;
+			else
+				progress[i].timtosend -= before;
+		}
+		if(n <= 0)
+		for(i = 0 ; i < inpot ; i++)
+		if(progress[i].timo <= 0)	/* cannot realy be < */
+		{
+			node = progress[i].node;
+			progress[i] = progress[--inpot];
+			ndone++;
+			l.status = DS_MOSIX_DEF;
+			if((error = load_to_mosix_info(l,
+				&info[node - first], touser)))
+				break;
+			i--;
+		}
+	}
+	if (mlink)
+		comm_return_linkpool(mlink);
+	if(num > 8*sizeof(fewbits))
+		kfree(donebits);
+	return(error);
+}
+int
+balance_ask_node(int node, struct infomsg *info)
+{
+	mosix_link *mlink = NULL;
+	int from, n, error = 0;
+	int serialno;
+	int tries;
+	now_t before;
+	int timo;
+
+	if (!(mlink = comm_borrow_linkpool()))
+		error = -EDIST;
+	serialno = info_serialno++;
+	tries = info_retry_cnt;
+	timo = info_retry;
+	while (!error && tries--) {
+		info->version = MOSIX_BALANCE_VERSION;
+		info->serialno = serialno;
+		info->topology = MAX_MOSIX_TOPOLOGY;
+		info->load.pe = 0;	/* eg. GETLOAD */
+		info->load.speed = PE;
+		error = comm_sendto(node, info, sizeof(*info), mlink, NULL);
+		if (error < sizeof(*info))
+		{
+			if(error >= 0)
+				error = -EDIST;
+			goto out;
+		}
+		error = 0;
+		before = time_now();
+		n = comm_recvfrompe(info, sizeof(*info), mlink, &from, timo);
+		if (n == sizeof(*info) && from == node &&
+			info->load.pe == node && info->serialno == serialno)
+			goto out;
+		before = time_since(before);
+		if(before < timo)
+		{
+			timo -= before;
+			tries++;
+		}
+		else
+			timo = info_retry;
+	}
+	error = -EAGAIN;
+out:
+	if (mlink)
+		comm_return_linkpool(mlink);
+	return (error);
+}
+
+int
+balance_get_info(int node, struct mosix_info *info)
+{
+	struct infomsg infomsg;
+	int error;
+
+	if (node == PE || node == 0) 		/* local info */
+	{
+		read_lock_bh(&loadinfo_lock);
+		infomsg.load = loadinfo[0];
+		read_unlock_bh(&loadinfo_lock);
+		infomsg.load.status = my_mosix_status();
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		infomsg.load.load_limit = load_limit;
+		infomsg.load.llimitmode = mosadmin_mode_loadlimit; 
+		infomsg.load.cpulimitmode = mosadmin_mode_cpulimit;
+		infomsg.load.cpu_limit = cpu_limit;
+#endif
+		infomsg.load.util = acpuse;
+#ifdef CONFIG_MOSIX_RESEARCH
+		infomsg.load.rio  = io_read_rate;
+ 		infomsg.load.wio  = io_write_rate;
+#endif /* CONFIG_MOSIX_RESEARCH */
+
+		load_to_mosix_info(infomsg.load, info, 0);
+	}
+	else if (!mos_to_net(node, NULL))
+		info->status = 0;
+	else if((error = balance_ask_node(node, &infomsg)))
+	{
+		info->status = DS_MOSIX_DEF;
+		return(error);
+	}
+	else
+		load_to_mosix_info(infomsg.load, info, 0);
+	return(0);
+}
+
+int
+balance_get_load(int node, struct loadinfo *l)
+{
+	struct infomsg infomsg;
+
+	if (node == PE || node == 0)
+	{
+		*l = loadinfo[0];
+		return(0);
+	}
+	else if (!mos_to_net(node, NULL))
+		return(-1);
+	else if(balance_ask_node(node, &infomsg))
+		return(-1);
+	*l = infomsg.load;
+	return(0);
+}
+
+static void
+inform()
+{
+	int to;
+	int i;
+	struct uplist *up;
+	struct infomsg info;
+
+	info.version = MOSIX_BALANCE_VERSION;
+	info.topology = MAX_MOSIX_TOPOLOGY;
+	info.serialno = 0;		/* meaning no serial number */
+	write_lock_bh(&loadinfo_lock);
+	loadinfo[0].free_slots = get_free_guest_slots();
+	info.load = loadinfo[0];
+	write_unlock_bh(&loadinfo_lock);
+	info.load.load = export_load;
+
+	/* first select any node, and send the load */
+	lock_mosix();
+	to = (NPE > 1) ? nth_node(rand(NPE-1, 1)) : 0;
+	unlock_mosix();
+	if(to && info_send_message(to, &info))
+		not_responding(to);
+
+	/* then select a node that seems to be up */
+	spin_lock(&uplist_lock);
+	if (info_nup)
+	{
+		for (up = uphead , i = rand(info_nup, 0) ; i-- ; up = up->next)
+			; /* just stop at random element */
+		to = (up->pe == to) ? 0 : up->pe;
+	}
+	else
+		to = 0;
+	spin_unlock(&uplist_lock);
+	if (to && info_send_message(to, &info))
+		not_responding(to);
+}
+
+void
+not_responding(int pe)
+{
+	unsigned int i;
+	struct uplist *up, *prev;
+
+	spin_lock(&uplist_lock);
+	prev = NULL;
+	for (up = uphead ; up ; prev = up , up = up->next)
+	if (up->pe == pe)
+	{
+		if (prev)
+			prev->next = up->next;
+		else
+			uphead = up->next;
+		up->next = upfree;
+		upfree = up;
+		info_nup--;
+		break;
+	}
+	spin_unlock(&uplist_lock);
+	write_lock_bh(&loadinfo_lock);
+	for (i = 1; i < INFO_WIN; i++)
+	if (loadinfo[i].pe == pe)
+		loadinfo[i].pe = 0;
+	write_unlock_bh(&loadinfo_lock);
+}
+
+void
+this_machine_is_favourite(int which)
+{
+	register struct uplist *up;
+
+	spin_lock(&uplist_lock);
+	for(up = uphead ; up ; up = up->next)
+		if(up->pe == which)
+			break;
+	if(!up && upfree)
+#ifdef CONFIG_MOSIX_CHEAT_MIGSELF
+	if(which != PE)
+#endif /* CONFIG_MOSIX_CHEAT_MIGSELF */
+	{
+		up = upfree;
+		upfree = upfree->next;
+		up->next = uphead;
+		up->pe = which;
+		up->age = 0;
+		uphead = up;
+		info_nup++;
+	}
+	spin_unlock(&uplist_lock);
+}
+
+static int
+rand(int modulo, int regen)
+{
+	if(regen)
+	{
+		info_seed2++;
+		/* alternating even/odd values: */
+		info_seed1 = info_seed1*info_seed2 + 1;
+		return((info_seed1 & 0x7fffffff) % modulo);
+	}
+	else
+		return((((info_seed2+1)*info_seed1+1) & 0x7fffffff) % modulo);
+}
+
+/*
+ * we are 99.99% going to migrate and let other processes be migrated,
+ * but not before we adjust the local and remote loads to discourage
+ * further migrations.
+ */
+void
+release_migrations(int whereto)
+{
+	register struct mosix_task *m = &current->mosix;
+	register int load;
+	unsigned int i;
+	int pages = m->migpages ? : count_migrating_pages();
+
+	this_machine_is_favourite(whereto);
+
+	/* Decrease the local load by the load caused by this process,
+	 * to avoid over-migration.
+	 */
+	write_lock_bh(&loadinfo_lock);
+	spin_lock_irq(&runqueue_lock);
+	load = m->load * STD_SPD / 4 / cpuspeed;
+	load /= smp_num_cpus;
+	  /* It is ON PURPOSE that `acpuse' is not taken into account */
+	if(loadinfo[0].load < load)   /* should not happen, but ... */
+		load = loadinfo[0].load;
+	load_left += load;
+	spin_unlock_irq(&runqueue_lock);
+
+	loadinfo[0].load -= load;
+
+	/* increase the receiver's-load */
+	for(i = 1 ; i < INFO_WIN ; i++)
+	if(loadinfo[i].pe == whereto)
+	{
+		/* add slightly more than 1 process worth of load */
+		loadinfo[i].load += MF * 102 * STD_SPD/
+			(loadinfo[i].speed * loadinfo[i].ncpus * 100);
+		loadinfo[i].mem -= pages;
+		break;
+	}
+	write_unlock_bh(&loadinfo_lock);
+	m->pages_i_bring = -pages; /* discourage 'memory_badly_required' */
+	unchoose_me();
+}
+
+void
+info_someone_came_in(void)
+{
+	write_lock_bh(&loadinfo_lock);
+	coming_in++;
+	came_lately4 += 4;
+	export_load += MF * STD_SPD / (smp_num_cpus * cpuspeed);
+	write_unlock_bh(&loadinfo_lock);
+}
+
+void
+end_coming_in(int error)
+{
+	write_lock_bh(&loadinfo_lock);
+	coming_in--;
+	if(error)
+	{
+		if((int)(came_lately4 -= 4) < 0)
+			came_lately4 = 0;
+	}
+	write_unlock_bh(&loadinfo_lock);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/init.c linux-openmosix/hpc/init.c
--- linux/hpc/init.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/init.c	2002-11-24 21:45:57.000000000 +0100
@@ -0,0 +1,52 @@
+/* All changes since Feb 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <hpc/hpcversion.h>
+#include <hpc/balance.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
+#define	STD_LOOPS	9961472  /* loops per jiffy on standard processor */
+
+void
+init_mosix(void)
+{
+	extern int x86_udelay_tsc;
+	cpuspeed = ((int64_t)loops_per_jiffy) * STD_SPD / STD_LOOPS;
+	if(!x86_udelay_tsc)
+		cpuspeed *= 2;
+	info_init();
+	proc_update_costs();
+#ifdef CONFIG_MOSIX_FS
+	init_mfs();
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_init();
+#endif /* CONFIG_MOSIX_DFSA */
+	kernel_thread(mosix_mig_daemon, NULL, 0);
+	info_startup();
+	mosix_load_init();
+	mosinfo_update_gateways();
+	kernel_thread(mosix_info_daemon, NULL, 0);
+	kernel_thread(mosix_mem_daemon, NULL, 0);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/kernel.c linux-openmosix/hpc/kernel.c
--- linux/hpc/kernel.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/kernel.c	2004-04-06 21:19:38.000000000 +0200
@@ -0,0 +1,1117 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh.
+ */
+#include <linux/sched.h>
+#include <linux/hpcctl.h>
+#include <linux/hpc.h>
+#include <net/tcp.h>
+#include <hpc/dscosts.h>
+#include <hpc/mfscosts.h>
+#include <hpc/protocol.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/hpcversion.h>
+#include <hpc/comm.h>
+#include <hpc/balance.h>
+#include <hpc/debug.h>
+#include <asm/ptrace.h>
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
+/************* some MOSIX global variables: *************/
+
+spinlock_t mosix_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t whereto_lock = SPIN_LOCK_UNLOCKED;
+int active_cpus;
+int cpuspeed = STD_SPD;
+int standard_speed = STD_SPD;
+int mosix_running; /* is openMosix running 1=yes */
+struct task_struct *chosen_for_balance, *chosen_for_mdp;
+
+
+struct mosix_cost mosix_cost[MAX_MOSIX_TOPOLOGY] =
+{{
+	PAGE_COST_D, PAGE_COST_R,
+	SYSCALL_COST_D, SYSCALL_COST_R,
+	COPYOUT_COST_BASE_D, COPYOUT_COST_PER_KB_D,
+	COPYOUT_COST_BASE_R, COPYOUT_COST_PER_KB_R,
+	COPYIN_COST_BASE_D, COPYIN_COST_PER_KB_D,
+	COPYIN_COST_BASE_R, COPYIN_COST_PER_KB_R,
+	MIGRATION_COST_BASIC, MIGRATION_COST_PER_PAGE
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	, 0, 0
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+}};
+
+struct mfs_cost mfs_cost[MAX_MOSIX_TOPOLOGY] =
+{{
+	MFS_COST_CONN_S, MFS_COST_CONN_C,
+	MFS_COST_INKB_S, MFS_COST_INKB_C,
+	MFS_COST_OUTKB_S, MFS_COST_OUTKB_C,
+}};
+
+struct opcost deputy_here[MAX_MOSIX_TOPOLOGY];
+struct task_struct *info_proc;
+int info_daemon_active = 0;
+
+/**************************************************/
+
+int
+balpriority(int w)
+{
+	switch(w)
+	{
+	case MUSTGOHOME:
+		return(7);
+	case GOBACKHOME:
+		return(6);
+	default:
+		return(5);
+	case MFSBALANCE:
+		return(4);
+	case IOBALANCE:
+		return(3);
+	case MEMBALANCE:
+		return(2);
+	case BALANCE:
+		return(1);
+	case 0:
+		return(0);
+	}
+	/*NOTREACHED*/
+}
+
+inline void
+mosix_do_add_to_whereto(struct task_struct *p, int w)
+{
+	if(balpriority(p->mosix.whereto) >= balpriority(w))
+		return;
+	p->mosix.whereto = w;
+	if(w != BALANCE && p == chosen_for_balance)
+	{
+		free_task_struct(p);
+		chosen_for_balance = NULL;
+	}
+	if(w != MEMBALANCE && p == chosen_for_mdp)
+	{
+		free_task_struct(p);
+		chosen_for_mdp = NULL;
+	}
+	if((p->mosix.dflags & (DREMOTE|DSENTURGENT)) != (DREMOTE|DSENTURGENT))
+		wake_up_mosix(p);
+}
+
+void
+mosix_add_to_whereto(struct task_struct *p, int w)
+{
+	spin_lock_irq(&whereto_lock);
+	mosix_do_add_to_whereto(p, w);
+	spin_unlock_irq(&whereto_lock);
+}
+
+/*
+ * must = 0: normal priority - if it fails, return.
+ * must = 1: high priority - but still return if it fails.
+ * must = 2: high priority and die (never return) on failure.
+ * otherwise, return 1 on success, 0 on failure.
+ * WARNING: do not call with "must==2" where resources were allocated.
+ */
+int
+mosix_go_home(int must)
+{
+	register struct task_struct *p = current;
+
+	if(p->mosix.dflags & DDEPUTY)
+	{
+		if(current->mosix.dflags & DINCOMING)
+			/* (eg. within do_mmap while migrating back) */
+			return(1);
+		passto(must ? MUSTGOHOME : GOBACKHOME, 0);
+	}
+	else if(p->mosix.dflags & DREMOTE)
+	{
+		remote_request(must ? REM_MUST_COME_HOME : REM_BRING_ME_HOME,
+			NULL, 0, NULL, 0, 0, NULL, 0);
+		/* should not return, but */
+	}
+	if(p->mosix.dflags & (DDEPUTY|DREMOTE))
+	{
+		printk("%s: Failed to Go Back Home.\n", desc_mostask(NULL));
+		if(must < 2)
+			return(0);
+		if(p->mosix.dflags & DDEPUTY)
+		{
+			printk("Process %s, uid=%d, killed because it failed to migrate back here\n",
+				desc_mostask(NULL), p->uid);
+			printk("(possible reasons are lack of space on swap-space, or network disconnection)\n");
+			do_exit(SIGKILL);
+		}
+		else
+			remote_disappear();
+	}
+	return(1);
+}
+
+int
+mosix_go_home_for_reason(int must, int reason)
+{
+	struct task_struct *p = current;
+	int ret;
+
+	task_lock(p);
+	if((p->mosix.stay & reason) && (p->mosix.dflags & (DDEPUTY|DREMOTE)))
+		panic("mosix_go_home_for_reason: why not earlier?");
+	p->mosix.stay |= reason;
+	task_unlock(p);
+	if(!(ret = mosix_go_home(must)))
+	{
+		task_lock(p);
+		p->mosix.stay &= ~reason;
+		task_unlock(p);
+	}
+	return(ret);
+}
+
+int
+stay_me_and_my_clones(uint32_t reasons)
+{
+	struct task_struct *p, *me = current;
+	struct mm_struct *mm = me->mm;
+
+	if(me->mosix.dflags & DDEPUTY)
+		return(!mosix_go_home(1));	/* there are no clones! */
+	task_lock(me);
+	me->mosix.stay |= reasons;
+	task_unlock(me);
+	if(atomic_read(&mm->mm_realusers) > 1)
+	{
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if(p->mm == mm && p != me)
+		{
+			task_lock(p);
+			if(p->mm == mm)
+				p->mosix.stay |= reasons;
+			task_unlock(p);
+		}
+		read_unlock(&tasklist_lock);
+	}
+	return(0);
+}
+
+void
+unstay_mm(struct mm_struct *mm)
+{
+	struct task_struct *p;
+
+	if(atomic_read(&mm->mm_realusers) == 1 && mm == current->mm)
+	{
+		if(!(current->mosix.dflags & DREMOTE))
+			tell_process(current, DREQ_CHECKSTAY);
+		return;
+	}
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if(p->mm == mm)
+		tell_process(p, DREQ_CHECKSTAY);
+	read_unlock(&tasklist_lock);
+}
+
+int
+mosix_wakeable(struct task_struct *p)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	/* the following side-effect of this boolean function is allowed
+	 * because it is only called by "wake_up_mosix" and it is a good
+	 * practice to hide such MOSIX details from "wake_up_mosix".
+	 * note that we are already protected by runqueue_lock,
+	 * making DREMOTEDFSA, DINSCHED and DHEAVYSLEEP stable.
+	 */
+	if(p->mosix.dflags & DREMOTEDFSA)
+	{
+		tell_process(p, DREQ_EXITDFSA);
+		return(!(p->state & TASK_UNINTERRUPTIBLE) &&
+			!(p->mosix.dflags & (DINSCHED|DHEAVYSLEEP)));
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	if(p->mosix.dflags & (DINSCHED|DFAKESIGNAL|DHEAVYSLEEP|DFINISHED))
+		return(0);
+	if(p->state & TASK_UNINTERRUPTIBLE)
+		return(0);
+	if(p->mosix.dflags & DREMOTE)
+	{
+		if(!remote_need_while_asleep(p))
+			return(0);
+	}
+	return(1);
+}
+
+/*
+ * the following two boolean routines are very sensitive,
+ * it may not even lock the kernel or mosix, so if there is any need to do so,
+ * it must return 1.
+ */
+
+int
+remote_need_while_asleep(struct task_struct *p)
+{
+	/* if DREQ_CHECKCONF is set, we can't even call
+	 * "i_am_in_a_wrong_place()", since it uses locks
+	 */
+	return((process_told(p, DREQ_CHECKCONF) &&
+			p->mosix.whereto != MUSTGOHOME) ||
+		process_told(p, DREQ_EXITDFSA) ||
+		(URGENT_REMOTE_CONDITIONS(p) &&
+		!(p->mosix.dflags & (DSENTURGENT|DPASSING|DINCOMING))));
+}
+
+/*
+ * called from schedule() with the runqueue_lock locked.
+ */
+int
+mosix_need_while_asleep(void)
+{
+	register struct task_struct *p = current;
+	register struct mosix_task *m = &p->mosix;
+
+#ifdef CONFIG_MOSIX_DFSA
+	if((m->dflags & DREMOTEDFSA) && (process_told(p, DREQ_EXITDFSA)))
+	{
+		process_ack(p, DREQ_EXITDFSA);
+		spin_lock_irq(&p->sigmask_lock);
+		m->dflags |= DFAKESIGNAL;
+		if(!(m->dflags & DHEAVYSLEEP))
+		{
+			p->sigpending = 1;
+			set_current_state(TASK_RUNNING);
+		}
+		spin_unlock_irq(&p->sigmask_lock);
+		return(0);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	if(m->dflags & (DINSCHED|DFAKESIGNAL|DHEAVYSLEEP))
+		return(0);
+	if(m->dflags & DREMOTE)
+		return(remote_need_while_asleep(p));
+	if(m->dirty_bits & MMAP_MMDOWNED)
+		return(0);
+	if(m->prequest)
+		return(1);
+	if(process_told(p, (DREQ_NICECNG|DREQ_UPDOVERHEADS|DREQ_CHECKCONF|
+		DREQ_INFOCNG|DREQ_DFSASYNC|DREQ_CAPCNG|DREQ_CHECKSTAY|
+		DREQ_URGENT)))
+		return(1);
+	if(m->whereto)
+		return(1);
+	if((m->dflags & DDEPUTY) && (m->stay & DSTAY))
+		return(1);
+	return(0);
+}
+
+void
+remote_run_while_asleep(void)
+{
+	struct task_struct *p = current;
+
+	if(process_told(p, DREQ_CHECKCONF))
+	{
+		if(i_am_in_a_wrong_place())
+			mosix_add_to_whereto(current, MUSTGOHOME);
+		/* else DREQ_CHECKCONF is cleared */
+	}
+	if(URGENT_REMOTE_CONDITIONS(p) &&
+			!(p->mosix.dflags & (DSENTURGENT|DPASSING|DINCOMING)))
+		inform_deputy_of_urgent();
+}
+
+void
+deputy_run_while_asleep(void)
+{
+	register struct task_struct *p = current;
+
+	if(p->mosix.dflags & DSYNC)
+		deputy_async_requests();
+	else
+	{
+		p->mosix.dflags |= DFAKESIGNAL;
+		evaluate_pending_signals_in_mosix_context();
+	}
+}
+
+void
+mosix_run_while_asleep(void)
+{
+	register struct task_struct *p = current;
+	register struct mosix_task *m = &p->mosix;
+
+	if(m->dflags & DREMOTE)
+	{
+		remote_run_while_asleep();
+		return;
+	}
+	scan:
+	if(m->dflags & DDEPUTY)
+	{
+		deputy_run_while_asleep();
+		if(mosix_need_while_asleep())
+			goto scan;
+		return;
+	}
+	/* LOCAL PROCESSES */
+	if(m->prequest)
+	{
+		process_requests();
+		goto scan;
+	}
+	process_ack(p, DREQ_NICECNG|DREQ_INFOCNG|DREQ_UPDOVERHEADS|DREQ_URGENT);
+	if(m->whereto)
+	{
+		follow_whereto();
+		goto scan;
+	}
+	if(process_told(p, DREQ_CHECKCONF))
+	{
+		done_checking_conf();
+		goto scan;
+	}
+	if(process_told(p, DREQ_CHECKSTAY))
+	{
+		if(p->mm)
+			down_read(&p->mm->mmap_sem);
+		mosix_check_for_freedom_to_move();
+		if(p->mm)
+			up_read(&p->mm->mmap_sem);
+		goto scan;
+	}
+	if(process_told(p, DREQ_CAPCNG))
+	{
+		sync_caps();
+		goto scan;
+	}
+#ifdef CONFIG_MOSIX_DFSA
+	if(process_told(p, DREQ_DFSASYNC))
+	{
+		clear_dfsasync();
+		goto scan;
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+}
+
+int
+remote_pre_usermode_actions(void)
+{
+	struct task_struct *p = current;
+	struct mosix_task *m = &p->mosix;
+	int i, nfsigs;
+	siginfo_t *fsigs;
+
+	loop:
+	do_decay();
+	if(remote_deputy_has_something_for_us(p))
+	{
+		wait_for_permission_to_continue();
+		goto loop;
+	}
+	if(process_told(p, DREQ_CHECKCONF) && i_am_in_a_wrong_place())
+		mosix_add_to_whereto(p, MUSTGOHOME);
+	if(URGENT_REMOTE_CONDITIONS(p) && !(m->dflags & DSENTURGENT))
+	{
+		inform_deputy_of_urgent();
+		goto loop;
+	}
+	if(m->asig || m->nforced_sigs)
+	{
+		spin_lock_irq(&p->sigmask_lock);
+		i = m->asig;
+		m->asig = 0;
+		fsigs = m->forced_sigs;
+		nfsigs = m->nforced_sigs;
+		m->forced_sigs = NULL;
+		m->nforced_sigs = 0;
+		spin_unlock_irq(&p->sigmask_lock);
+		transfer_signals_to_deputy((unsigned int) i, fsigs, nfsigs);
+		if(fsigs)
+			kfree(fsigs);
+		goto loop;
+	}
+	return(0);
+}
+
+int
+local_pre_usermode_actions(void)
+{
+	struct task_struct *p = current;
+	int any = 0;
+
+	while(1)
+	{
+		do_decay();
+		if(p->mosix.whereto)
+		{
+			follow_whereto();
+			any = 1;
+			if(p->mosix.dflags & DDEPUTY)
+				return(1);
+			continue;
+		}
+		if(process_told(p, DREQ_CHECKCONF))
+		{
+			done_checking_conf();
+			any = 1;
+			continue;
+		}
+		if(process_told(p, DREQ_CAPCNG))
+		{
+			sync_caps();
+			any = 1;
+			continue;
+		}
+#ifdef CONFIG_MOSIX_DFSA
+		if(process_told(p, DREQ_DFSASYNC))
+		{
+			clear_dfsasync();
+			any = 1;
+			continue;
+		}
+#endif /* CONFIG_MOSIX_DFSA */
+		if(process_told(p, DREQ_CHECKSTAY))
+		{
+			down_read(&p->mm->mmap_sem);
+			mosix_check_for_freedom_to_move();
+			up_read(&p->mm->mmap_sem);
+			any = 1;
+			continue;
+		}
+		process_ack(p, DREQ_NICECNG|DREQ_INFOCNG|DREQ_UPDOVERHEADS|
+								DREQ_URGENT);
+		return(any);
+	}
+}
+
+int
+mosix_pre_usermode_actions(struct pt_regs regs)
+{
+	register struct task_struct *p = current;
+	int any = 0;
+
+	if((regs.xcs & 3) != 3)	/* going back to kernel -- not to user mode */
+		return(0);
+	__sti();		/* could be called after an interrupt */
+
+	if(p->mosix.dflags & DREMOTE)
+		return(remote_pre_usermode_actions());
+
+	while(1)
+	{
+		if(p->mosix.dflags & DDEPUTY)
+		{
+			deputy_main_loop();
+			p = current;	/* fork? */
+			any = 1;
+			continue;
+		}
+		if(local_pre_usermode_actions())
+		{
+			any = 1;
+			continue;
+		}
+		if(p->mosix.prequest)
+		{
+			process_requests();
+			any = 1;
+			continue;
+		}
+		return(any);
+	}
+}
+
+int
+mosix_fork_init_fields(struct task_struct *p)
+{
+	struct mosix_task *m = &p->mosix;
+	struct task_struct *parent = current;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	int ii;
+#endif
+#ifdef CONFIG_MOSIX_DFSA
+	tell_process(parent, DREQ_NOTUPTODATE);
+	tell_process(p, DREQ_NOTUPTODATE);
+	if(parent->mosix.dflags & (DREMOTEDAEMON|DREMOTE))
+		dfsa_tinit();
+	m->ttab = NULL;
+#endif /* CONFIG_MOSIX_DFSA */
+	if(!(parent->mosix.dflags & DDEPUTY))
+		tell_process(p, DREQ_CHECKSTAY);
+	m->dflags = parent->mosix.dflags & ~(DREMOTEDAEMON|DSENTURGENT);
+	process_ack(p, DREQ_HOMEWAKE|DREQ_URGENT);
+	m->commpri = 0;
+	if(parent->mosix.dflags & DREMOTEDAEMON)
+	{
+		m->dflags |= DREMOTE|DHEAVYSLEEP;
+		m->hsleep_count = 1;
+	}
+	else if(parent->mosix.dflags & DREMOTE)
+	{ 
+		/* this information comes from the parent task struct,
+                   which we copied into out task struct in kernel/do_fork.c 
+		*/
+                m->mypid = m->sonpid;
+                m->depinfo.tgid = m->sontgid;
+                sprintf(p->comm, "remote(%d)", m->mypid);
+	}
+	if(parent->mosix.dflags & DDEPUTY)
+		m->dflags &= ~(DDEPUTY|DSYNC);
+	if(!(parent->mosix.dpolicy & DADV_INHERIT))
+	{
+		m->dpolicy = DADV_DEFAULT;
+#if DADV_DEFAULT == DADV_OWNDECAY
+		m->decay = DECAY_QUOTIENT;
+		m->deccycle = DEFAULT_DECAY_INTERVAL;
+#endif
+	}
+	if(p->pid == 1)
+		m->stay |= DSTAY_SYSTEM;
+	else
+		m->stay &= ~DSTAY_SYSTEM;
+	m->held_files = NULL;
+	m->held_allocated = 0;
+	rwlock_init(&m->state_lock);
+	m->contact = 0;
+	m->ucache = NULL;
+	m->prequest = NULL;
+	if(parent->mm == &init_mm || !parent->mm ||
+		(parent->mosix.dflags & DDEPUTY) ||
+		(parent->mosix.stay & DSTAY_SYSTEM))
+		m->ancesstor = NULL;
+	else
+		m->ancesstor = parent;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	for (ii = 0; ii < smp_num_cpus; ii++)
+	{
+		m->last_per_cpu_utime[ii] = 0;
+		m->last_per_cpu_stime[ii] = 0;
+	}
+#endif
+	m->last_sigxcpu = 0;
+	m->deputytime = 0;
+	m->passedtime = 0;
+	m->uttime = 0;
+	m->dctime = 0;
+	m->ndemandpages = 0;
+	m->nsyscalls = 0;
+	m->ncopyouts = 0;
+	m->copyoutbytes = 0;
+	m->ncopyins = 0;
+	m->copyinbytes = 0;
+	m->iocounter = 0;
+	m->cutime = 0;
+	m->last_consider = 0;
+	m->last_mconsider = 0;
+	m->decsecs = 0;
+	memset((caddr_t)&m->asig, 0, sizeof(m->asig));
+	m->forced_sigs = 0;
+	m->nforced_sigs = 0;
+	m->pages_i_bring = 0;
+	m->page_allocs = 0;
+	m->ran = 0;
+	m->runstart = 0;
+	m->load = 0;
+	m->inexec = NULL;
+	m->nmigs = 0;
+	m->pass_regs = 0;
+	init_waitqueue_head(mos_to_waitp(m));
+	m->mosix_log = NULL;
+	m->dirty_bits = 0;
+#ifdef CONFIG_MOSIX_FS
+	m->mfs_stats = NULL;
+#endif /* CONFIG_MOSIX_FS */
+	return(fork_mosix_remote_files(p));
+}
+
+void
+mosix_fork_free_fields(struct task_struct *p)
+{
+	if(p->mosix.dflags & DDEPUTY)
+		undeputy(p);
+}
+
+void
+mosix_exit(void)
+{
+	struct task_struct *p = current;
+	struct mosix_task *m = &p->mosix;
+	unsigned int i;
+	struct linux_binprm *bprm = m->inexec;
+
+	lock_mosix();
+	write_lock_irq(&tasklist_lock);
+	spin_lock(&runqueue_lock);
+	m->dflags |= DFINISHED;
+	m->bstate = TASK_SAME;/* we are not going back to original sleep/stop */
+	spin_unlock(&runqueue_lock);
+	write_unlock_irq(&tasklist_lock);
+	unlock_mosix();
+	m->pages_i_bring = 0;
+	unchoose_me();
+	free_ucache();
+	if(m->dflags & DDEPUTY)
+		mosix_deputy_rusage(1); /* (includes setting "m->exit_mem") */
+	if(m->dflags & DREMOTE)
+		expel_progress = 1;
+	if(m->dflags & (DDEPUTY|DREMOTE))
+		comm_close(NULL); /* for a DEPUTY, this will kill our REMOTE */
+	if(m->dflags & DDEPUTY)
+		undeputy(p);
+	if(process_told(p, DREQ_CHECKCONF))
+		done_checking_conf();
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_exit();
+#endif /* CONFIG_MOSIX_DFSA */
+	if(bprm)
+	{
+		for(i = 0 ; i < MAX_ARG_PAGES ; i++)
+		if(bprm->page[i])
+			__free_page(bprm->page[i]);
+		if(m->dflags & DREMOTE)
+			kfree(bprm);
+	}
+	if(m->prequest)
+		discard_requests();
+}
+
+void
+mosix_very_exit(void)
+{
+	struct task_struct *p = current, *a;
+	struct mosix_task *m = &p->mosix;
+	struct task_struct *q;
+#ifdef CONFIG_MOSIX_FS
+	struct mfs_stats *mfst;
+#endif /* CONFIG_MOSIX_FS */
+
+#ifdef CONFIG_MOSIX_FS
+	lock_mosix();
+	mfst = m->mfs_stats;
+	m->mfs_stats = NULL;
+	unlock_mosix();
+	if(mfst)
+		kfree(mfst);
+#endif /* CONFIG_MOSIX_FS */
+	read_lock(&tasklist_lock);
+	if((a = m->ancesstor))
+		get_task_struct(a);
+	for_each_task(q)
+	if(q->mosix.ancesstor == p)
+		q->mosix.ancesstor = a;
+	read_unlock(&tasklist_lock);
+	if(a)
+	{
+		add_statistics_to_ancesstor(p, a);
+		free_task_struct(a);
+	}
+	if(m->forced_sigs)
+	{
+		kfree(m->forced_sigs);
+		m->nforced_sigs = 0;
+	}
+}
+
+void
+mosix_obtain_registers(unsigned long mask)
+{
+	register struct mosix_task *m = &current->mosix;
+	unsigned int bringme;
+
+	if(mask & ~ALL_REGISTERS)
+		panic("(open)mosix_obtain_registers, mask=0x%x", (int)mask);
+	if(m->dflags & DDEPUTY)
+	{
+		if((bringme = mask & ~m->deputy_regs))
+		{
+			if(deputy_request(DEP_BRING_ME_REGS, &bringme,
+				sizeof(bringme), NULL, 0, 0, NULL, 0))
+				deputy_communication_failed();
+			else if((m->deputy_regs & mask) != mask)
+			{
+				send_sig(SIGKILL, current, 1);
+			}
+		}
+	}
+	else if(m->dflags & DREMOTE)
+	{
+		if((bringme = mask & m->deputy_regs))
+		{
+			if(remote_request(REM_BRING_ME_REGS, &bringme,
+				sizeof(bringme), NULL, 0, 0, NULL, 0))
+				send_sig(SIGKILL, current, 1);
+			else if((~m->deputy_regs & mask) != mask)
+			{
+				send_sig(SIGKILL, current, 1);
+				mosix_panic("remote-regs");
+			}
+		}
+	}
+}
+
+unsigned int
+which_regs_to_send()
+{
+	register struct mosix_task *m = &current->mosix;
+
+	if(!m->pass_regs)
+		return(0);
+	return(m->pass_regs &
+		((m->dflags & DDEPUTY) ? m->deputy_regs : ~m->deputy_regs));
+}
+
+void
+regs_were_sent(void)
+{
+	register struct mosix_task *m = &current->mosix;
+
+	if(m->dflags & DDEPUTY)
+		m->deputy_regs &= ~m->pass_regs;
+	else
+		m->deputy_regs |= m->pass_regs; 
+	m->pass_regs = 0;
+}
+
+void
+mosix_bring_monkey_users_back(struct inode *ip)
+{
+	register struct task_struct *p, *found, *me = current;
+	DECLARE_WAITQUEUE(wait, me);
+
+	while(1)
+	{
+		found = NULL;
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if(p != me && !(p->mosix.dflags & DREMOTE) &&
+			task_maps_ip(p, ip))
+		{
+			task_lock(p);
+			p->mosix.stay |= DSTAY_FOR_MONKEY;
+			task_unlock(p);
+			if(p->mosix.dflags & DDEPUTY)
+			{
+				tell_process(p, DREQ_HOMEWAKE);
+				wake_up_mosix(p);
+				if(!found)
+				{
+					found = p;
+					get_task_struct(p);
+				}
+			}
+		}
+		if(!found)
+		{
+			read_unlock(&tasklist_lock);
+			/* VMODIFIED is needed against a nearly-impossible
+			 * REMOTE race, when ip is modified, then unmonkied
+			 * and a process migrates there even before the
+			 * previous completed exiting:
+			 */
+			OPENMOSIX_VMODIFIED(ip);
+			return;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		add_wait_queue(mos_to_waitp(&found->mosix), &wait);
+		read_unlock(&tasklist_lock);
+		schedule();
+		remove_wait_queue(mos_to_waitp(&found->mosix), &wait);
+		set_current_state(TASK_RUNNING);
+		free_task_struct(found);
+	}
+}
+
+void
+mosix_no_longer_monkey(struct inode *ip)
+{
+	register struct task_struct *p;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if(!(p->mosix.dflags & (DREMOTE|DDEPUTY)) && task_maps_ip(p, ip))
+	{
+		tell_process(p, DREQ_CHECKSTAY);
+		wake_up_mosix(p);
+	}
+	read_unlock(&tasklist_lock);
+}
+
+/*
+ * caller is responsible to down_[read|write](&current->mm->mmap_sem)
+ * (unless deemed unnecessary - as in "exec" or after migrating back,
+ * when we are sure to have no clones.
+ */
+void
+mosix_check_for_freedom_to_move(void)
+{
+	struct task_struct *p = current;
+	register struct vm_area_struct *mpnt;
+	register struct inode *ip;
+	int stay;
+	struct mm_struct *mm;
+
+	if(p->mosix.dflags & DDEPUTY)
+	{
+		return;
+	}
+	process_ack(p, DREQ_CHECKSTAY);
+	if(!(p->mosix.stay & (DSTAY_PER_MM|DSTAY_FOR_CLONE)))
+		return;
+	task_lock(p);
+	stay = p->mosix.stay & ~(DSTAY_PER_MM|DSTAY_FOR_CLONE);
+	if(!(mm = current->mm))
+		stay |= DSTAY_FOR_CLONE;
+	else
+	{
+		if(atomic_read(&mm->mm_kiocount))
+			stay |= DSTAY_FOR_KIOBUF;
+		if(atomic_read(&mm->mm_realusers) > 1)
+			stay |= DSTAY_FOR_CLONE;
+		if(mm->def_flags & VM_LOCKED)
+			stay |= DSTAY_FOR_MLOCK;
+		for(mpnt = mm->mmap ; mpnt ; mpnt = mpnt->vm_next)
+		{
+			if(mpnt->vm_file)
+			{
+				mode_t mode;
+
+				ip = mpnt->vm_file->f_dentry->d_inode;
+				mode = ip->i_mode;
+				if(ip->i_mapping->i_mmap_shared)
+					stay |= DSTAY_FOR_MONKEY;
+				if(S_ISCHR(mode) || S_ISFIFO(mode) ||
+								S_ISSOCK(mode))
+					stay |= DSTAY_FOR_DEV;
+			}
+			if(mpnt->vm_flags & VM_LOCKED)
+				stay |= DSTAY_FOR_MLOCK;
+		}
+	}
+	p->mosix.stay = stay;
+	task_unlock(p);
+}
+
+/*
+ * caller must use 'get_task_struct(p)'
+ */
+int
+mosix_send_back_home(struct task_struct *p)
+{
+	struct task_struct *me = current;
+	int timeout = 20 * HZ;
+	DECLARE_WAITQUEUE(wait, me);
+
+	if(p == me)
+		return(mosix_go_home(1) ? 0 : -ENOMEM);
+
+	/* there is a paranoidic possibility of a tricky deadlock: if two
+	 * (or more) remote processes send each other home simultaneously:
+	 * we want to sleep interruptibly, so we can migrate, but no signals
+	 * should stop us - unless the other process failed to migrate for a
+	 * very long time.  e.g. we are to give up only with the combination
+	 * of a signal + timeout.
+	 */
+	add_wait_queue(mos_to_waitp(&p->mosix), &wait);
+	while(p->mosix.dflags & DDEPUTY)
+	{
+		tell_process(p, DREQ_HOMEWAKE);
+		mosix_add_to_whereto(p, MUSTGOHOME);
+		spin_lock_irq(&me->sigmask_lock);
+		me->mosix.ignoreoldsigs = 1;
+		me->sigpending = 0;
+		spin_unlock_irq(&me->sigmask_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		task_lock(p);
+		if(!(p->mosix.dflags & DDEPUTY))
+			set_current_state(TASK_RUNNING);
+		task_unlock(p);
+		timeout = schedule_timeout(timeout);
+		if(timeout <= 0)
+		{
+			spin_lock_irq(&me->sigmask_lock);
+			recalc_sigpending(me);
+			spin_unlock_irq(&me->sigmask_lock);
+			if(signal_pending(current))
+			{
+				remove_wait_queue(mos_to_waitp(&p->mosix),
+									&wait);
+				free_task_struct(p);
+				return(-EINTR);
+			}
+			timeout = HZ;
+		}
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(mos_to_waitp(&p->mosix), &wait);
+	spin_lock_irq(&me->sigmask_lock);
+	recalc_sigpending(me);
+	spin_unlock_irq(&me->sigmask_lock);
+	return(0);
+}
+
+void
+mosix_pre_dropping_mm(struct task_struct *myself, struct mm_struct *mm)
+{
+	register struct task_struct *p;
+
+	if(!mm)
+		return;
+	atomic_dec(&mm->mm_realusers);
+	if(atomic_read(&mm->mm_realusers) == 1)
+	{
+		read_lock(&tasklist_lock);
+		for_each_task(p)
+		if(p != myself && p->mm == mm)
+		{
+			tell_process(p, DREQ_CHECKSTAY);
+			break;
+		}
+		read_unlock(&tasklist_lock);
+	}
+}
+
+void
+mosix_exit_mm(struct task_struct *p)
+{
+	if((p->mosix.dflags & (DPASSING|DREMOTE)) == DPASSING)
+		return;
+	if(p->mosix.held_files)
+		mosix_clear_all_held_files(p);
+	if(!(p->mosix.dflags & DDEPUTY))
+		mosix_pre_dropping_mm(p, p->mm);
+	task_lock(p);
+	p->mosix.stay = (p->mosix.stay | DSTAY_FOR_CLONE) & ~DSTAY_PER_MM;
+	task_unlock(p);
+	p->mosix.pages_i_bring = 0;
+}
+
+void
+mosix_exec_mmap(struct mm_struct *old_mm)
+{
+	struct task_struct *p = current;
+
+	if(p->mosix.dflags & DDEPUTY)
+		return;
+		
+	mosix_pre_dropping_mm(p, old_mm);
+	task_lock(p);
+	p->mosix.stay &= ~(DSTAY_PER_MM|DSTAY_FOR_CLONE);
+	task_unlock(p);
+	p->mosix.pages_i_bring = 0;
+	if(p->mosix.held_files)
+		mosix_clear_all_held_files(p);
+}
+
+int
+mosix_pre_clone(void)
+{
+	struct task_struct *p = current;
+
+	if(!mosix_go_home(0))
+		return(-ENOMEM);
+	
+	/* prevent race with "mosix_pre_dropping_mm" */
+	if(p->mm)
+		atomic_inc(&p->mm->mm_realusers);
+	read_lock(&tasklist_lock);
+	task_lock(p);
+	p->mosix.stay |= DSTAY_FOR_CLONE;
+	task_unlock(p);
+	read_unlock(&tasklist_lock);
+	return(0);
+}
+
+void
+mosix_post_clone(void)
+{
+	struct task_struct *p = current;
+	struct mm_struct *mm = p->mm;
+
+	if(mm)
+	{
+		atomic_dec(&mm->mm_realusers);
+		read_lock(&tasklist_lock);
+		if(atomic_read(&mm->mm_realusers) == 1)
+		{
+			task_lock(p);
+			p->mosix.stay &= ~DSTAY_FOR_CLONE;
+			task_unlock(p);
+		}
+		read_unlock(&tasklist_lock);
+	}
+}
+
+/* 'run_on' and 'run_off' must be called with the runqueue_lock! */
+void
+run_on(struct task_struct *p)
+{
+	if(!(p->mosix.dflags & DPAGEIN))
+	{
+		mosix_running++;
+		p->mosix.runstart = load_ticks + 1;
+	}
+}
+
+void
+run_off(struct task_struct *p)
+{
+	if(!(p->mosix.dflags & DPAGEIN))
+	{
+		mosix_running--;
+		p->mosix.ran += load_ticks + 1 - p->mosix.runstart;
+		p->mosix.runstart = 0;
+	}
+}
+
+void
+down_half_interruptible(struct semaphore *sem)
+{
+	struct task_struct *p = current;
+
+	do
+	{
+		spin_lock_irq(&p->sigmask_lock);
+		p->mosix.ignoreoldsigs = 1;
+		p->sigpending = 0;
+		spin_unlock_irq(&p->sigmask_lock);
+	}
+	while(down_interruptible(sem) == -EINTR);
+	recalc_sigpending(p);
+}
+
+/* still to be implemented: to adapt to the changes made in 2.4.19 - Amit. */
+/*
+void
+down_half_rw_interruptible(struct rw_semaphore *sem)
+{
+	struct task_struct *p = current;
+
+	do {
+		spin_lock_irq(&p->sigmask_lock);
+		p->mosix.ignoreoldsigs = 1;
+		p->sigpending = 0;
+		spin_unlock_irq(&p->sigmask_lock);
+	}
+	while(down_interruptible(sem) == -EINTR);
+	recalc_sigpending(p);
+}
+*/
diff -Naur --exclude=CVS --exclude=configs linux/hpc/load.c linux-openmosix/hpc/load.c
--- linux/hpc/load.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/load.c	2004-04-06 21:19:38.000000000 +0200
@@ -0,0 +1,243 @@
+/* Changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Amnon Barak, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#include <linux/hpcctl.h>
+#include <net/sock.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <hpc/protocol.h>
+#include <linux/hpc.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <hpc/balance.h>
+#include <linux/kernel_stat.h>
+
+#define VV1     5
+#define VV2     8
+#define DECAY   VV1/VV2         /* decay of load */
+#define NEWDATA (VV2-VV1)/VV2   /* weight of new load data */
+
+unsigned load_adder;    /* accumulator of `running' every clock tick */
+unsigned load_ticks;    /* # of ticks included in load_adder */
+unsigned cpuse;         /* # of ticks when CPU was not thrashing */
+unsigned acpuse = MF;   /* long term non-trashing (start value = non-0) */
+unsigned coming_in;     /* number of arriving processes */
+unsigned came_lately4;  /* processes that arrived lately (*4) */
+unsigned load_left;     /* load of processes that just left */
+
+int export_load;	/* load reported to other processors */
+int stable_export;	/* machine dependent stabilizing factor */
+
+int Tvis;
+int Tload;
+
+
+
+void
+mosix_calc_load(unsigned long unused)
+{
+	struct task_struct *p;
+	register struct mosix_task *m;
+	register int ladd, cpu, ticks;
+	unsigned long flags;
+	unsigned long newload;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	unsigned long loadremote, loadlocal, cpulocal, cpuremote;
+	int ii;
+#endif
+	int new_expload;
+	unsigned new_cpuse;
+	unsigned new_came;
+	static unsigned upper_load;    /* over estimated load */
+	static unsigned accload;       /* accumulated load (*128) */
+	static int display_counter = 0;
+#ifdef CONFIG_MOSIX_RESEARCH
+	unsigned int new_io_read;
+	unsigned int new_io_write;
+	unsigned int major;
+	unsigned int disk;
+#endif /* CONFIG_MOSIX_RESEARCH */
+
+	ticks = load_ticks;
+	cpu = cpuse;
+	ladd = load_adder;
+	cpuse = load_adder = load_ticks = 0;
+
+	ladd = ladd * ((long long)(MF * STD_SPD)) /
+		(ticks * cpuspeed * smp_num_cpus);
+	if(ladd * 128 > accload)	/* slowly up */
+		accload = accload * DECAY + ladd * 128 * NEWDATA;
+	else				/* quickly down */
+		accload = ladd * 128;
+	if(ladd >= upper_load)		/* quickly up */
+		upper_load = ladd;
+	else				/* very slowly down */
+		upper_load = (upper_load * 7 + ladd) / 8;
+	new_cpuse = (acpuse * 3 + cpu * MF / ticks + 3) / 4;
+	newload = (accload+64) / 128;
+	new_expload = (upper_load + stable_export +
+		came_lately4 * MF * STD_SPD /
+			(4 * cpuspeed * smp_num_cpus)) *
+			MF * smp_num_cpus / new_cpuse;
+	if(newload < load_left)
+		newload = 0;
+	else
+		newload -= load_left;
+	newload = newload * MF * smp_num_cpus / new_cpuse;
+	new_came = came_lately4 * DECAY + coming_in * 4 * NEWDATA;
+	spin_lock_irqsave(&runqueue_lock, flags);
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	loadlocal = loadremote = cpulocal = cpuremote = 0;	
+#endif
+	for_each_task(p)
+	{
+		m = &p->mosix;
+		if(m->runstart)
+		{
+			m->ran += ticks + 1 - m->runstart;
+			m->runstart = 1;
+		}
+		m->load = m->load * DECAY + m->ran * MF * 4*NEWDATA/ticks;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+		if (m->dflags & DREMOTE)
+		{
+			if (m->last_per_cpu_utime[0])
+			{
+				/* this means that at least one time we were already here */
+				for (ii = 0;  ii < smp_num_cpus; ii++)
+				{
+					cpuremote += p->per_cpu_utime[ii] - 
+					m->last_per_cpu_utime[ii];
+					cpuremote += p->per_cpu_stime[ii] -
+					m->last_per_cpu_stime[ii];
+				}
+			}
+			loadremote += m->load; 
+		}
+		else
+		{
+			if (m->last_per_cpu_utime[0])
+			{
+				for (ii = 0 ; ii < smp_num_cpus; ii++)
+				{
+					cpulocal += p->per_cpu_utime[ii] - 
+					m->last_per_cpu_utime[ii];
+					cpulocal += p->per_cpu_stime[ii] - 
+					m->last_per_cpu_stime[ii];
+				}
+			}
+		    loadlocal += m->load;
+		}
+		for (ii = 0;  ii < smp_num_cpus; ii++)
+		{
+			m->last_per_cpu_utime[ii] = p->per_cpu_utime[ii];
+			m->last_per_cpu_stime[ii] = p->per_cpu_stime[ii]; 
+		}
+#endif
+		m->ran = 0;
+		m->page_allocs >>= 1;	/* decay in time */
+	}
+	spin_unlock_irqrestore(&runqueue_lock, flags);
+
+	if(Tvis)
+		printk("\0337\033[22;55HL=%d,E=%d,R=%d,U=%d  \0338",
+			(int)newload, new_expload, mosix_running,
+			new_cpuse);
+	if(Tload) {
+		if (!(display_counter = (display_counter + 1) & 0xf))
+			printk("\naccload upper_load\tload_adder\tload_ticks\n");
+		printk("%7d\t%10d\t%10d\t%d\n",
+			accload, upper_load, ladd, ticks);
+	}
+	write_lock(&loadinfo_lock);
+	loadinfo[0].load = newload;
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	loadinfo[0].loadremote = loadremote;
+	loadinfo[0].loadlocal = loadlocal;
+	loadinfo[0].cpulocal = cpulocal*MF / ticks;
+	loadinfo[0].cpuremote = cpuremote*MF / ticks;
+#endif
+	export_load = new_expload;
+	acpuse = new_cpuse;
+	came_lately4 = new_came;
+	load_left = 0;
+
+	write_unlock(&loadinfo_lock);
+
+	if((p = (struct task_struct *)info_proc))
+		send_sig(SIGALRM, p, 1);
+}
+
+void
+mosix_load_init(void)
+{
+	acpuse = MF * smp_num_cpus;
+	load_ticks = MF;	/* fake it to begin with (must be non-zero) */
+	cpuse = MF * smp_num_cpus;
+	load_adder = mosix_running * MF;
+	mosix_calc_load(0);
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	loadinfo[0].load_limit = 0;
+	loadinfo[0].llimitmode = 0;
+	loadinfo[0].cpu_limit = 0;
+	loadinfo[0].cpulimitmode = 0;
+	loadinfo[0].cpulocal = 0;
+	loadinfo[0].cpuremote = 0;
+	loadinfo[0].loadlocal = 0;
+	loadinfo[0].loadremote = 0;
+#else
+	loadinfo[0].load_limit = 0; 
+	loadinfo[0].llimitmode = 255;/* 255 = no load limit */
+	loadinfo[0].cpu_limit = 0;
+	loadinfo[0].cpulimitmode = 255;
+	loadinfo[0].cpulocal = 0;
+	loadinfo[0].cpuremote = 0;
+	loadinfo[0].loadlocal = 0;
+	loadinfo[0].loadremote = 0;
+#endif
+}
+
+void
+mosix_snap_load(int ticks)
+{
+	unsigned long flags;
+	extern struct list_head runqueue_head;
+
+	load_adder += mosix_running;
+	if(mosix_running <= active_cpus)
+		cpuse += ticks * smp_num_cpus;
+	else
+	{
+		/* a possible race between the time of making a process runable
+		 * and actual picking up by a processor: so count runable
+		 * processes as if already occupying a processor:
+		 */
+		int n;
+		register struct task_struct *p;
+		struct list_head *tmp;
+
+		spin_lock_irqsave(&runqueue_lock, flags);
+		if((n = active_cpus) < smp_num_cpus)
+		for(tmp = runqueue_head.next ; tmp != &runqueue_head ;
+								tmp = tmp->next)
+		{
+			p = list_entry(tmp, struct task_struct, run_list);
+			if(p->mosix.runstart && ++n == smp_num_cpus)
+				break;
+		}
+		spin_unlock_irqrestore(&runqueue_lock, flags);
+		cpuse += ticks * n;
+	}
+	load_ticks += ticks;
+	if(load_ticks >= MF)
+		mosix_calc_load(0);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/Makefile linux-openmosix/hpc/Makefile
--- linux/hpc/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/Makefile	2003-07-13 14:26:02.000000000 +0200
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+#
+# Permission to use this software is hereby granted under the terms of the
+# GNU General Public License, as published by the Free Software Foundation.
+#
+# THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+# WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+# FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+#
+#
+# Makefile for HPC permanent interface.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+O_TARGET := hpc.o
+obj-y    := alternate.o auto_syscalls.o balance.o comm.o config.o decay.o \
+	    deputy.o div.o export.o freemem.o init.o info.o kernel.o load.o \
+	    mig.o hpcadmin.o hpcproc.o prequest.o remote.o rinode.o \
+	    service.o syscalls.o ucache.o badops.o
+
+obj-$(CONFIG_MOSIX_DFSA) += dfsa.o
+
+export-objs = export.o
+
+include $(TOPDIR)/Rules.make
+
+auto_syscalls.c: mkdefcalls $(TOPDIR)/arch/i386/kernel/entry.S syscalls.c
+	./mkdefcalls
+
+mkdefcalls: mkdefcalls.c $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/types.h $(TOPDIR)/include/linux/sched.h $(TOPDIR)/include/linux/signal.h $(TOPDIR)/include/linux/sys.h $(TOPDIR)/include/linux/kernel.h
+	$(HOSTCC) $(HOSTCFLAGS) -I$(HPATH) -o mkdefcalls -DENTRY_IN=\"$(TOPDIR)/arch/i386/kernel/entry.S\" -DSYSCALLS_IN=\"$(TOPDIR)/hpc/syscalls.c\" -DSYSCALLS_OUT=\"$(TOPDIR)/hpc/auto_syscalls.c\" mkdefcalls.c
+
+alternate.c: copy_unconf $(TOPDIR)/fs/binfmt_aout.c $(TOPDIR)/.config
+	/bin/sh ./copy_unconf "$(CONFIG_BINFMT_AOUT)" $(TOPDIR)/fs/binfmt_aout.c > alternate.c
diff -Naur --exclude=CVS --exclude=configs linux/hpc/mig.c linux-openmosix/hpc/mig.c
--- linux/hpc/mig.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/mig.c	2004-04-05 17:39:45.000000000 +0200
@@ -0,0 +1,1580 @@
+/* Changes since Feb 12, 2002 by Moshe Bar (moshe@moelabs.com)
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Oren Laadan, Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <hpc/routines.h>
+#include <linux/hpc.h>
+#include <linux/personality.h>
+#include <linux/hpcctl.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/swapctl.h>
+#include <linux/highmem.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+#include <hpc/defs.h>
+#include <hpc/hpcversion.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <asm/softirq.h>
+#include <asm/mman.h>
+#include <asm/mmu_context.h>
+#include <asm/ldt.h>
+#include <linux/vmalloc.h>
+#include <asm/desc.h>
+#include <linux/module.h>
+#include <asm/processor.h>
+#include <asm/i387.h>
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
+static int mig_remote_receive_proc(void *);
+static int mig_local_passto_remote(int, int);
+static int mig_remote_passto_remote(int, int);
+static int mig_remote_passto_local(int, int);
+
+#define MIGDSTR "oM_migd"
+static char REMOTESTR[] = "remote";
+static char REMOTESTR2[] = "remote(%d)";
+
+int mig_daemon_active = 0;
+struct task_struct *mig_proc = NULL;
+
+int
+mosix_mig_daemon(void *dummy)
+{
+	struct task_struct *p = current;
+	mosix_link *mlink;
+	mosix_addr saddr;
+	int error;
+
+	common_daemon_setup(MIGDSTR, 0);
+	p->mosix.dflags |= DREMOTEDAEMON;
+	init_guest_user_struct();
+	p->rlim[RLIMIT_STACK].rlim_cur = p->rlim[RLIMIT_STACK].rlim_max;
+	lock_mosix();
+	mig_proc = p;
+	unlock_mosix();
+
+ restart:
+	wait_for_mosix_configuration(&mig_daemon_active);
+	error = 0;
+	if (!p->mosix.contact &&
+		!(p->mosix.contact = comm_open(COMM_MIGD, 0, 0)))
+		{
+			if(PE)
+				printk(MIGDSTR ": failed to open migration service"
+					   " -- retrying\n");
+			spin_lock_irq(&p->sigmask_lock);
+			flush_signals(p);
+			spin_unlock_irq(&p->sigmask_lock);
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(HZ);
+			goto restart;
+		}
+
+	while (1)
+		{
+			if(!PE)
+				{
+					comm_close(NULL);
+					goto restart;
+				}
+
+			error = comm_accept(p->mosix.contact, &mlink, &saddr, 0UL);
+			if (error == -EINTR || error == -ERESTART || error == -EAGAIN
+				|| error == -ERESTARTSYS || error == -EDIST)
+				{
+					spin_lock_irq(&p->sigmask_lock);
+					flush_signals(p);
+					spin_unlock_irq(&p->sigmask_lock);
+					continue;
+				}
+			else if (error)
+				{
+					printk("%s: failed to accept connection (err = %d)"
+						   " - re-initializing the servicei now\n", MIGDSTR, error);
+					comm_close(NULL);
+					goto restart;
+				}
+
+			if(!PE || mosadmin_mode_block)
+				{
+					comm_close(mlink);
+					continue;
+				}
+
+			current->mosix.deppe = comm_getpeer(mlink);
+			error = user_thread(mig_remote_receive_proc, (void *)mlink, 0);
+			if (error < 0)
+				{
+					comm_close(mlink);
+					continue;
+				}
+		}
+}
+
+static int
+mig_remote_receive_proc(void *ptr)
+{
+	struct mosix_link *contact = (struct mosix_link *)ptr;
+	struct mosix_link *remlink = NULL;
+	struct task_struct *p = current;
+	struct mosix_task *m = &p->mosix;
+	struct mig_request_h *mrp;
+	int type;
+	int error;
+	int reply = 0;
+	unsigned int load_came_in = 0;
+
+	memcpy(p->comm, REMOTESTR, sizeof(REMOTESTR));
+	p->mosix.stay = 0;
+	comm_use(p, contact);
+
+	lighter_sleep();
+	if((error = obtain_mm()))
+		goto failed;
+
+	if (p->mosix.dflags & DREMOTE)
+		p->mosix.dflags |= DPSYNC;
+	if ((error = mig_recv_request(&mrp)))
+		goto failed;
+	type = mrp->request_type;
+	if(type != DEPUTY_PROBE)
+		load_came_in = 1;
+
+	if(mrp->wp_works_ok && !boot_cpu_data.wp_works_ok)
+		reply = -ENOEXEC;
+
+	set_personality(mrp->personality);
+	if(current->personality != mrp->personality)
+		reply = -EDIST;
+	comm_free((void *) mrp);
+
+	if (type == DEPUTY_PROBE && reply == 0) {
+		mosix_addr sa;
+
+		/*
+		 * prepare another mosix_link for the REMOTE and send its
+		 * address through the DEPUTY.
+		 */
+
+		remlink = comm_open(COMM_ACCEPT, &sa, comm_remote_timo);
+		if (!remlink) {
+			reply = -EDIST;
+			goto send_reply;
+		}
+		if ((error = comm_send(MIG_REQUEST|REPLY, (void *)&reply,
+							   sizeof(int), (void *)&sa, sizeof(sa), 0)))
+			goto failed;
+		comm_use(p, remlink);
+		reply = mig_recv_request(&mrp);
+
+		/* 'remlink' was possibly switched by comm_recv(): */
+		remlink = p->mosix.contact;
+
+		if (reply)
+			goto failed;
+		load_came_in = 1;
+		comm_free((void *) mrp);
+		goto send_reply;
+	} else {
+	send_reply:
+		if ((error = comm_send(MIG_REQUEST|REPLY, (void *)&reply,
+							   sizeof(int), NULL, 0, 0)))
+			goto failed;
+	}
+
+	if (reply)
+		goto failed;
+
+
+	error = mig_do_receive();
+
+	if (remlink) {
+		comm_use(p, contact);
+		comm_close(remlink);
+	}
+	if (error)
+		{
+			end_coming_in(error);
+			m->pages_i_bring = 0;
+			remote_disappear();
+		}
+	mosix_clear_statistics();
+	end_coming_in(0);
+	m->pages_i_bring = 0;
+#ifdef CONFIG_MOSIX_DFSA
+	tell_process(p, DREQ_NOTUPTODATE);
+	dfsa_tinit();
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef SHOW_MIGRATIONS
+	if(SHOW_MIGRATIONS)
+		printk("Process migration occured now...\n");
+#endif /* SHOW_MIGRATIONS */
+	kickstart();
+	panic("kickstart returned");
+	/*NOTREACHED*/
+
+ failed:
+	if (load_came_in)
+	{
+		end_coming_in(-EDIST);	/* any error would do */
+		m->pages_i_bring = 0;
+	}
+	if (remlink) {
+		comm_use(p, contact);
+		comm_close(remlink);
+	}
+	do_exit(SIGKILL);
+	/*NOTREACHED*/
+}
+
+void
+follow_whereto()
+{
+	int t;
+	register struct task_struct *p = current;
+
+	spin_lock_irq(&whereto_lock);
+	t = p->mosix.whereto;
+	p->mosix.whereto = 0;
+	spin_unlock_irq(&whereto_lock);
+	if(!t)
+		return;
+	if(t > 0 || t == GOBACKHOME || t == MUSTGOHOME)
+		passto(t, 0);
+	else if(p->mosix.dflags & DDEPUTY)
+		coordinate(t, 0);
+	else
+		consider(t, NULL);
+}
+
+int
+passto(int whereto, int reason)
+{
+	register struct task_struct *p = current;
+	int error;
+
+
+	if (!PE)
+		return (whereto && whereto != GOBACKHOME &&
+				whereto != MUSTGOHOME ? -EDIST : 0);
+	if (whereto == MUSTGOHOME)
+		{
+			whereto = GOBACKHOME;
+			p->mosix.dflags |= DMUSTBEBACK;
+		}
+#ifdef CONFIG_MOSIX_CHEAT_MIGSELF
+	if (whereto == GOBACKHOME)
+		{
+			if(!p->mosix.whereami)
+				{
+					p->mosix.dflags &= ~DMUSTBEBACK;
+					return(0);
+				}
+			whereto = 0;
+		}
+#else
+	if (whereto == GOBACKHOME || whereto == PE)
+		whereto = 0;
+	if (whereto == p->mosix.whereami)
+		{
+			p->mosix.dflags &= ~DMUSTBEBACK;
+			return(0);
+		}
+#endif /* CONFIG_MOSIX_CHEAT_MIGSELF */
+	if (whereto && ((p->mosix.stay & DSTAY) || !mos_to_net(whereto, 0)))
+		return (-EDIST);
+
+
+	spin_lock_irq(&runqueue_lock);
+	p->mosix.dflags |= DPASSING;
+	spin_unlock_irq(&runqueue_lock);
+	store_common_ps_info();
+
+	if (!p->mosix.whereami)
+		error = mig_local_passto_remote(whereto, reason);
+	else if (!whereto)
+		error = mig_remote_passto_local(whereto, reason);
+	else
+		error = mig_remote_passto_remote(whereto, reason);
+
+
+	stop_storing_common_ps_info();
+	spin_lock_irq(&runqueue_lock);	/* for DPASSING (not for DMUSTBEBACK) */
+	p->mosix.dflags &= ~(DPASSING|DMUSTBEBACK);
+	spin_unlock_irq(&runqueue_lock);
+
+	if(error)
+		return (-EDIST);
+
+	task_lock(p);
+	p->mosix.whereami = whereto;
+	p->mosix.nmigs++;
+	task_unlock(p);
+	if(p->mosix.sigmig)
+		{
+			struct siginfo info;
+
+			info.si_signo = p->mosix.sigmig;
+			info.si_errno = 0;
+			info.si_code = SI_MIGRATED;
+			info.si_newplace = whereto;
+			info.si_reason = reason;
+			send_sig_info(p->mosix.sigmig, &info, p);
+		}
+	mosix_clear_statistics();
+	return(0);
+}
+
+void
+coordinate(int reason, int already_in)
+{
+	struct mosix_task *m = &current->mosix;
+	void *head;
+	int hdln;
+	int where;
+
+	while(1)
+		{
+			if(already_in)
+				{
+					if(deputy_wait(DEP_CONSIDER|REPLY, &head, &hdln))
+						goto die;
+					where = *((int *)head);
+					comm_free(head);
+					already_in = 0;
+				}
+			else if(deputy_request(DEP_CONSIDER, &reason, sizeof(reason),
+								   NULL, 0, 0, (void *)&where, -sizeof(where)))
+				{
+				die:
+					deputy_communication_failed();
+					return;
+				}
+			if(!where)
+				return;
+			if(reason && where != GOBACKHOME &&
+			   (m->whereto == GOBACKHOME || m->whereto == MUSTGOHOME))
+				{
+					where = m->whereto;
+					reason = 0;
+				}
+			if(!passto((where == GOBACKHOME || where == MUSTGOHOME) ? 0 :
+					   where, reason))
+				return;
+		}
+}
+
+int
+mig_send_request(int reason, int type)
+{
+	struct mig_request_h mrp;
+	int *nack;
+	int mfident = (current->mosix.dflags & DDEPUTY) ? COMM_MFIDENT : 0;
+	int command = MIG_REQUEST | mfident;
+	int error;
+	int len;
+
+	mrp.version = MOSIX_MIGRATION_VERSION;
+	mrp.topology = MAX_MOSIX_TOPOLOGY;
+	mrp.reason = reason;
+	mrp.personality = current->personality;
+	mrp.wp_works_ok = boot_cpu_data.wp_works_ok;
+	mrp.request_type = type;
+#ifdef CONFIG_MOSIX_DFSA
+	mrp.has_dfsa = 1;
+#else
+	mrp.has_dfsa = 0;
+#endif /* CONFIG_MOSIX_DFSA */
+
+	if(type == DEPUTY_PROBE)
+		error = comm_send(command, &mrp, sizeof(mrp), NULL, 0, 0);
+	else
+		{
+			mrp.pages_sent =
+				current->mosix.migpages ? : count_migrating_pages();
+			error = send_with_miginfo(command, &mrp, sizeof(mrp));
+		}
+	if(error)
+		return (error);
+	if ((error = comm_recv((void **)&nack, &len)) < 0)
+		return (error);
+	if (error != (MIG_REQUEST|REPLY)) {
+		error = -EDIST;
+		goto out;
+	}
+
+	/* at this point the other party *knows* us */
+	if (mfident)
+		config_set_status(comm_getpeer(current->mosix.contact));
+
+	error = *nack;		/* should be: 0 or -EDIST */
+ out:
+	comm_free((void *) nack);
+	return (error);
+}
+
+int
+mig_recv_request(struct mig_request_h **mrp)
+{
+	int type, hlen;
+	int reply = -EDIST;
+
+	if ((type = comm_recv((void **) mrp, &hlen)) < 0)
+		return (type);
+
+
+	if (type != MIG_REQUEST || hlen != sizeof(struct mig_request_h)) {
+		goto failed;
+	}
+
+	if ((*mrp)->version != MOSIX_MIGRATION_VERSION)
+		{
+			static int complained;
+
+			if(++complained < 10 || complained % 10000 == 0)
+				printk("Migration request denied: "
+					   "Incompatible versions of openMosix.\n");
+			goto failed;
+		}
+	if ((*mrp)->topology != MAX_MOSIX_TOPOLOGY)
+		{
+			static int complained;
+
+			if(++complained < 10 || complained % 10000 == 0)
+				printk("Migration request denied: Incompatible topology"
+					   " (here=%d, there=%d)\n", MAX_MOSIX_TOPOLOGY,
+					   (*mrp)->topology);
+			goto failed;
+		}
+#ifdef CONFIG_MOSIX_DFSA
+	if(!(*mrp)->has_dfsa)
+#else
+		if((*mrp)->has_dfsa)
+#endif /* CONFIG_MOSIX_DFSA */
+			{
+				static int complained;
+
+				if(++complained < 10 || complained % 10000 == 0)
+					printk("Migration request denied: "
+						   "Cannot mix DFSA and NON-DFSA kernels\n");
+				goto failed;
+			}
+
+	if ((*mrp)->request_type != DEPUTY_PROBE)
+		{
+			if (!balance_commit_mig((*mrp)->reason, (*mrp)->pages_sent))
+				goto failed;
+			current->mosix.pages_i_bring = (*mrp)->pages_sent;
+		}
+
+	return (0);
+
+ failed:
+	comm_flushdata(COMM_ALLDATA);
+	comm_free(*mrp);
+	*mrp = NULL;
+
+
+	comm_send(MIG_REQUEST|REPLY, (void *) &reply, sizeof(int), NULL, 0, 0);
+	return (reply);
+}
+
+/*
+ * mig_local_passto_remote:  migrate local -> remote
+ */
+
+static int
+mig_local_passto_remote(int whereto, int reason)
+{
+	struct task_struct *p = current;
+	struct mosix_link *mlink;
+	int error;
+	int omigpages;
+
+	if(!p->mosix.held_files && (error = mosix_rebuild_file_list()))
+		return(error);
+
+	lock_mosix();
+	write_lock_irq(&tasklist_lock);
+	p->mosix.remote_caps = current->cap_effective;
+	task_lock(p);
+	spin_lock(&runqueue_lock);
+	if(p->task_dumpable)
+	        p->mosix.dflags |= DTDUMPABLE;
+	else
+	        p->mosix.dflags &= ~DTDUMPABLE;
+	if(p->mm->dumpable)
+		p->mosix.dflags |= DDUMPABLE;
+	else
+		p->mosix.dflags &= ~DDUMPABLE;
+	p->mosix.dflags |= (DDEPUTY | DSYNC);
+	spin_unlock(&runqueue_lock);
+	task_unlock(p);
+	write_unlock_irq(&tasklist_lock);
+	unlock_mosix();
+	p->mosix.deputy_regs = ALL_REGISTERS;
+	p->mosix.pass_regs = 0;
+
+	if (!(mlink = comm_open(whereto, 0, comm_connect_timo))) {
+		error = -EDIST;
+		goto failed;
+	}
+	if (comm_use(p, mlink))
+		panic("local_passto_remote: previous contact not null");
+
+	if(!(omigpages = p->mosix.migpages))
+		p->mosix.migpages = count_migrating_pages();
+	if ((error = mig_send_request(reason, FROM_DEPUTY)))
+		{
+			p->mosix.migpages = omigpages;
+			goto failed;
+		}
+
+
+	release_migrations(whereto);
+	if (mig_do_send()) {
+		error = -EDIST;
+		p->mosix.migpages = omigpages;
+		goto failed;
+	}
+	p->mosix.migpages = omigpages;
+
+	deputy_startup();
+	return (0);
+
+ failed:
+	if(mlink)
+		comm_close(NULL);
+	undeputy(current);
+	return (error);
+}
+
+
+/*
+ * mig_remote_passto_local:  migrate remote -> local
+ */
+
+static int
+mig_remote_passto_local(int whereto, int reason)
+{
+	struct task_struct *p = current;
+	struct mig_request_h *mrp;
+	int error = 0;
+	long orlim_as;
+	long orlim_rss;
+	long orlim_stack;
+	unsigned int load_came_in = 0;
+
+	mosix_deputy_rusage(0);
+	if(obtain_mm())
+		{
+			return(-EDIST);
+		}
+
+	/* rlimits are no excuse to prevent coming back home: */
+	/* save old values for the case of failure */
+	orlim_as = p->rlim[RLIMIT_AS].rlim_cur;
+	orlim_rss = p->rlim[RLIMIT_RSS].rlim_cur;
+	orlim_stack = p->rlim[RLIMIT_STACK].rlim_cur;
+	p->rlim[RLIMIT_AS].rlim_cur = RLIM_INFINITY;
+	p->rlim[RLIMIT_RSS].rlim_cur = RLIM_INFINITY;
+	p->rlim[RLIMIT_STACK].rlim_cur = RLIM_INFINITY;
+
+	if ((error = comm_send(DEP_COME_BACK, (void *) &reason, sizeof(reason),
+						   NULL, 0, 0))) {
+		end_coming_in(error);
+		current->mosix.pages_i_bring = 0;
+		deputy_die_on_communication();
+	}
+
+	if ((error = mig_recv_request(&mrp)))
+		goto fail;
+	load_came_in = 1;
+	comm_free((void *) mrp);
+	if ((error = comm_send(MIG_REQUEST|REPLY, (void *)&error, sizeof(int),
+						   NULL, 0, 0))) {
+		end_coming_in(error);
+		current->mosix.pages_i_bring = 0;
+		deputy_die_on_communication();
+		/*NOTREACHED*/
+	}
+
+	if (!(error = mig_do_receive())) {
+		comm_close(NULL);
+		undeputy(p);
+		mosix_clear_statistics();
+#ifdef SHOW_MIGRATIONS
+		if(SHOW_MIGRATIONS)
+			printk("Wooooooooo.....\n");
+#endif /*SHOW_MIGRATIONS*/
+		end_coming_in(0);
+		current->mosix.pages_i_bring = 0;
+		if(p->mosix.dflags & DDELAYHELD)
+			{
+				p->mosix.dflags &= ~DDELAYHELD;
+				mosix_rebuild_file_list();
+			}
+		return(0);
+	}
+
+ fail:
+	p->rlim[RLIMIT_AS].rlim_cur = orlim_as;
+	p->rlim[RLIMIT_RSS].rlim_cur = orlim_rss;
+	p->rlim[RLIMIT_STACK].rlim_cur = orlim_stack;
+	exit_mm(p);
+	if(load_came_in)
+		{
+			end_coming_in(error);
+			current->mosix.pages_i_bring = 0;
+		}
+
+	return (error);
+}
+
+
+/*
+ * mig_remote_passto_remote:  migrate remote -> remote
+ *
+ * (1) open mosix_link to mig-daemon at new remote site (and use it)
+ * (2) send migration request, obtain remote's mosix_link address.
+ * (3) send DEP_PLEASE_MIGRATE request to old remote site, with "reason"
+ *     and the mosix_link address to which it should connect
+ * (4) if the reply is zero - close old mosix_link and use the new one (SUCCESS)
+ * FAILURE: if not fatal - close new connection and return error
+ *          if fatal - close connection and call deputy_die_on_communication()
+ */
+
+static int
+mig_remote_passto_remote(int whereto, int reason)
+{
+	struct task_struct *p = current;
+	struct mosix_link *newmlink = 0, *oldmlink = 0;
+	struct please_migrate_h pm;
+	int status;
+	int error;
+
+	/* connect to remote mig daemon */
+
+
+	p->mosix.pass_regs = 0;
+
+
+	if (!(newmlink = comm_open(whereto, 0, comm_connect_timo)))
+		return (-EDIST);
+
+
+	if (!(oldmlink = comm_use(p, newmlink)))
+		panic("remote_passto_remote: no previous contact");
+
+	if ((error = mig_send_request(reason, DEPUTY_PROBE)))
+		goto failed;
+
+
+	if ((error = comm_copydata((void *)&pm.ma, sizeof(pm.ma), 0)))
+		goto failed;
+
+	comm_use(p, oldmlink);
+
+
+	pm.reason = reason;
+	pm.to = whereto;
+	mosix_deputy_rusage(0);
+	if ((error = deputy_request(DEP_PLEASE_MIGRATE, &pm, sizeof(pm),
+								NULL, 0, 0, (void **)&status, -sizeof(status))))
+		goto fatal;
+	if ((error = status))
+		goto failed;
+
+	comm_use(p, newmlink);
+	comm_close(oldmlink);
+
+
+	return (0);
+
+ failed:
+	comm_use(p, oldmlink);
+	comm_close(newmlink);
+	return (error);
+
+ fatal:
+	comm_use(p, oldmlink);
+	comm_close(newmlink);
+	deputy_die_on_communication();
+	/* NOTREACHED */
+}
+
+
+void
+undeputy(struct task_struct *p)
+{
+	struct mosix_task *m = &p->mosix;
+	unsigned int myself = (p == current);/* else it is a new-son, not yet on lists */
+
+
+	if(myself)
+		{
+			spin_lock_irq(&p->sigmask_lock);
+			m->dflags &= ~DFAKESIGNAL;
+			spin_unlock_irq(&p->sigmask_lock);
+			lock_mosix();
+			write_lock_irq(&tasklist_lock);
+			task_lock(p);
+			spin_lock(&runqueue_lock);
+		}
+	if(p->mm)
+		p->mm->dumpable = (m->dflags & DDUMPABLE) != 0;
+	m->dflags &= ~(DDEPUTY|DSYNC|DDUMPABLE);
+	/* restore segment registers.
+	   FIXME: do this only if remote modified LDT */
+	loadsegment(gs, m->altgs);
+	loadsegment(fs, m->altgs);
+	if(myself)
+		{
+			spin_unlock(&runqueue_lock);
+			task_unlock(p);
+			write_unlock_irq(&tasklist_lock);
+			if(process_told(p, DREQ_HOMEWAKE))
+				{
+					process_ack(p, DREQ_HOMEWAKE);
+					wake_up(mos_to_waitp(m));
+				}
+			unlock_mosix();
+			evaluate_pending_signals_in_mosix_context();
+			absorb_deptime(m->deputytime);
+			m->deputytime = 0;
+			stop_storing_common_ps_info();
+			flush_read_cache();
+			free_ucache();
+			if(m->stay & DSTAY_FOR_MONKEY)
+				mosix_check_for_freedom_to_move();
+		}
+	else
+		{
+			if(m->contact)
+				{
+					comm_close(m->contact);
+					m->contact = NULL;
+				}
+		}
+	m->commpri = 0;
+	m->pages_i_bring = 0;
+}
+
+int
+mig_send_mm_stats(void)
+{
+	struct mm_stats_h s;
+
+	if(sizeof(struct mm_stats_h) !=
+	   offsetof(struct mm_struct, env_end) -
+	   offsetof(struct mm_struct, start_code) + sizeof(long))
+		/* something changed in the Linux header - need to fix! */
+		panic("mig_send_mm_stats");
+	memcpy((caddr_t)&s, (caddr_t)&current->mm->start_code, sizeof(s));
+	expel_progress = 1;
+	return(comm_send(MIG_MM_STATS, &s, sizeof(s), NULL, 0, 0));
+}
+
+int
+mig_send_mm_areas(void)
+{
+	struct task_struct *p = current;
+	register struct vm_area_struct *vma;
+	struct file *fp;
+	struct mmap_parameters_h m;
+
+	m.origin = (p->mosix.dflags & DDEPUTY) ? PE : p->mosix.deppe;
+	m.fixed = 1;
+	for(vma = p->mm->mmap ; vma != NULL ; vma = vma->vm_next)
+		{
+			m.addr = vma->vm_start;
+			m.len = vma->vm_end - vma->vm_start;
+			m.flags = vma->vm_flags;
+			if((fp = vma->vm_file))
+				{
+					struct inode *ip = fp->f_dentry->d_inode;
+
+					m.pgoff = vma->vm_pgoff;
+					if(p->mosix.dflags & DREMOTE)
+						{
+							m.fp = home_file(fp);
+							m.dp = ip->u.remote_i.dp;
+							m.uniq = ip->u.remote_i.unique;
+							m.isize = ip->i_size;
+							m.nopage = ip->u.remote_i.nopage;
+						}
+					else
+						{
+							m.fp = vma->vm_file;
+							m.dp = m.fp->f_dentry;
+							m.uniq = ip->i_unique;
+							m.isize = ip->i_size;
+							m.nopage = vma->vm_ops->nopage;
+						}
+				}
+			else
+				{
+					m.fp = NULL;
+					m.pgoff = 0;
+				}
+			if(comm_send(MIG_MM_AREA, &m, sizeof(m), NULL, 0, 0))
+				return(-1);
+		}
+	expel_progress = 1;
+	return(0);
+}
+
+int
+mig_send_page(unsigned long addr, int size)
+{
+	expel_progress = 1;
+	/*
+	 * Although the page is in user-space, we deliberately send it from
+	 * kernel-space to prevent requesting it from the "REMOTE"
+	 * (because we are already marked as DEPUTY...)
+	 * This is safe since we just checked that the page is there.
+	 */
+	return(comm_send(MIG_PAGE, &addr, sizeof(addr), (void *)addr, size, 0));
+}
+
+int
+mig_send_pages(void)
+{
+	int credit;
+
+	credit = run_over_dirty_pages(mig_send_page, 1);
+	return(credit);
+}
+
+int
+mig_send_fp(void)
+{
+	unlazy_fpu(current);
+	expel_progress = 1;
+	return(comm_send(has_fxsr() ? MIG_XFP : MIG_FP, &current->thread.i387,
+					 sizeof(current->thread.i387), NULL, 0, 0));
+}
+
+int
+mig_send_ldt(void)
+{
+	expel_progress = 1;
+	return(comm_send(MIG_LDT, NULL, 0,
+					 current->mm->context.segments, LDT_ENTRIES*LDT_ENTRY_SIZE, 0));
+}
+
+int
+mig_send_misc(int credit)
+{
+	struct mig_misc_h m;
+	clock_t utime, stime;
+	extern unsigned long do_it_virt(struct task_struct *, unsigned long);
+	void *hd;
+	int hdln;
+	register struct task_struct *p = current;
+	siginfo_t *forced_sigs;
+
+	m.ptrace = p->ptrace;
+	m.dflags = p->mosix.dflags & (DTRACESYS1|DTRACESYS2);
+	memcpy((caddr_t)m.debugreg, (caddr_t)p->thread.debugreg,
+		   sizeof(m.debugreg));
+	m.nice = p->nice;
+	m.caps = p->cap_effective;
+	p->mosix.remote_caps = m.caps;
+	m.it_prof_incr = p->it_prof_incr;
+	m.it_virt_incr = p->it_virt_incr;
+	if(((p->mosix.dflags & DDEPUTY) && p->mosix.deputy_regs) ||
+	   ((p->mosix.dflags & DREMOTE) &&
+		p->mosix.deputy_regs != ALL_REGISTERS)) {
+		memcpy((caddr_t)&m.regs, (caddr_t)p->mosix.altregs, sizeof(m.regs));
+	} 	/* else do not bother - DEPUTY will bring */
+
+	/* send task segment registers.
+	                                                 */
+	m.fs = p->thread.fs;
+	m.gs = p->thread.gs;
+	/* send task  limits */
+	m.rlim_cpu = p->rlim[RLIMIT_CPU];
+	m.rlim_data = p->rlim[RLIMIT_DATA];
+	m.rlim_stack = p->rlim[RLIMIT_STACK];
+	m.rlim_rss = p->rlim[RLIMIT_RSS];
+	m.rlim_as = p->rlim[RLIMIT_AS];
+#ifdef CONFIG_MOSIX_DFSA
+	m.rlim_nofile = p->rlim[RLIMIT_NOFILE];
+	m.rlim_fsz = p->rlim[RLIMIT_FSIZE];
+#endif /* CONFIG_MOSIX_DFSA */
+	m.stay = (p->mosix.stay & DNOMIGRATE) != 0;
+	if(p->mosix.dflags & DDEPUTY)
+		{
+			m.deppe = PE;
+			m.mypid = p->pid;
+			memcpy(m.features, boot_cpu_data.x86_capability,
+				   sizeof(m.features));
+		}
+	else
+		{
+			m.deppe = p->mosix.deppe;
+			m.mypid = p->mosix.mypid;
+			memcpy(m.features, p->mosix.features, sizeof(m.features));
+			m.passedtime = p->mosix.passedtime;
+		}
+	m.deputy_regs = p->mosix.deputy_regs;
+	m.deccycle = p->mosix.deccycle;
+	m.decay = p->mosix.decay;
+	m.dpolicy = p->mosix.dpolicy;
+	memcpy(m.depcost, deputy_here, sizeof(deputy_here));
+	m.depspeed = cpuspeed;
+	m.nmigs = p->mosix.nmigs + 1;
+	m.info.disclosure = p->mosix.disclosure;
+	m.info.uid = p->uid;
+	m.info.gid = p->gid;
+	m.info.pgrp = p->pgrp;
+	m.info.session = p->session;
+	memcpy(m.info.comm, p->comm, sizeof(m.info.comm));
+	m.info.tgid = p->tgid;
+	cli();
+	m.it_virt_value = p->it_virt_value;
+	m.it_prof_value = p->it_prof_value;
+	p->it_prof_value = 0;
+	p->it_virt_value = 0;
+	if(p->mosix.dflags & DDEPUTY)
+		m.passedtime = p->times.tms_utime + p->times.tms_stime;
+	utime = p->times.tms_utime;
+	stime = p->times.tms_stime;
+	m.asig.sigs = p->mosix.asig;
+	m.asig.nforced = p->mosix.nforced_sigs;
+	forced_sigs = p->mosix.forced_sigs;
+	m.pagecredit = credit;
+	m.lastxcpu = p->mosix.last_sigxcpu;
+	sti();
+	if(comm_send(MIG_MISC, &m, sizeof(m), forced_sigs,
+				 m.asig.nforced * sizeof(siginfo_t), 0))
+		goto fail;
+	comm_migration_mode(0);
+	expel_progress = 1;
+	if(comm_recv(&hd, &hdln) == (MIG_MISC|REPLY))
+		return(0); /* commit point */
+
+ fail:
+	cli();
+	p->it_prof_value = m.it_prof_value;
+	p->it_virt_value = m.it_virt_value;
+	/* maintain accurate correlation between process-times and timers: */
+	utime = p->times.tms_utime - utime;
+	stime = p->times.tms_stime - stime;
+	sti();
+	if(utime > 0)
+		{
+			extern rwlock_t xtime_lock;
+
+			write_lock_irq(&xtime_lock);
+			do_it_virt(p, utime);
+			write_unlock_irq(&xtime_lock);
+		}
+	if(!(p->mosix.dflags & DDEPUTY) && /* (DEPUTY gets it in "depticks") */
+	   utime + stime > 0)
+		absorb_deptime(utime + stime);
+	return(-1);
+}
+
+void
+neutralize_my_load(int neut)
+{
+	struct task_struct *p = current;
+
+	spin_lock_irq(&runqueue_lock);
+	if(neut)
+		{
+			run_off(p);
+			p->mosix.dflags |= DPAGEIN;	/* disabling run_on/off */
+		}
+	else if(p->mosix.dflags & DPAGEIN)
+		{
+			p->mosix.dflags &= ~DPAGEIN;
+			run_on(p);
+		}
+	spin_unlock_irq(&runqueue_lock);
+}
+
+int
+mig_do_send(void)
+{
+	int credit;	/* # of clean demand-pages */
+        if(current->mm->context.segments)
+		clear_LDT();
+
+	comm_migration_mode(1);
+	neutralize_my_load(1); /* don't count me: I'm going to disappear */
+	if(mig_send_mm_stats() || mig_send_mm_areas() ||
+	   (credit = mig_send_pages()) < 0 ||
+	   (current->used_math && mig_send_fp()) ||
+	   (current->mm->context.segments && mig_send_ldt()) ||
+	   mig_send_misc(credit))
+		{
+			comm_send(MIG_NOT_COMING, NULL, 0, NULL, 0, 0);
+			comm_migration_mode(0);
+			neutralize_my_load(0);
+			changed_my_mind_and_staying();
+			return(-1);
+		}
+	/* "comm_migration_mode(0);" was done by "mig_send_misc" */
+	if(current->mm->context.segments)
+		load_LDT(current->mm);
+	neutralize_my_load(0);
+	return(0);
+}
+
+void
+mig_do_receive_mm_stats(struct mm_stats_h *s)
+{
+	if(sizeof(struct mm_stats_h) !=
+	   offsetof(struct mm_struct, env_end) -
+	   offsetof(struct mm_struct, start_code) + sizeof(long))
+		/* something changed in the Linux header - need to fix! */
+		panic("mig_do_receive_mm_stats");
+	memcpy((caddr_t)&current->mm->start_code, (caddr_t)s, sizeof(*s));
+	current->mosix.rfreepages = 0;
+}
+
+int
+deputy_remmap(struct mmap_parameters_h *m, int dummy)
+{
+	unsigned long result;
+	unsigned long prot, flags;
+	extern asmlinkage long sys_madvise(unsigned long, size_t, int);
+
+	/* unconvert prot+flags: */
+	flags = MAP_FIXED|MAP_PRIVATE;
+	prot = 0;
+	if(m->flags & VM_GROWSDOWN)
+		flags |= MAP_GROWSDOWN;
+	if(m->flags & VM_DENYWRITE)
+		flags |= MAP_DENYWRITE;
+	if(m->flags & VM_EXECUTABLE)
+		flags |= MAP_EXECUTABLE;
+	if(m->flags & VM_READ)
+		prot |= VM_READ;
+	if(m->flags & VM_WRITE)
+		prot |= VM_WRITE;
+	if(m->flags & VM_EXEC)
+		prot |= VM_EXEC;
+	if(m->flags & VM_MAYSHARE)
+		current->mosix.dirty_bits |= MMAP_MAYSHARE;
+	deeper_sleep();
+	result = do_mmap_pgoff(m->fp, m->addr, m->len, prot, flags, m->pgoff);
+	lighter_sleep();
+	if(m->flags & VM_MAYSHARE)
+		current->mosix.dirty_bits &= ~MMAP_MAYSHARE;
+	if(m->flags & VM_READHINTMASK)
+		sys_madvise(m->addr, m->len, (m->flags & VM_SEQ_READ) ?
+					MADV_RANDOM : MADV_SEQUENTIAL);
+	return(IS_ERR((const void *)result));
+}
+
+#define	AVAILABLE_PAGES	(nr_free_pages() + page_cache_size + \
+			nr_swap_pages + swapper_space.nrpages)
+#define	VERY_LOW_ON_MEMORY (nr_swap_pages < p->mosix.pages_i_bring && \
+					AVAILABLE_PAGES <= num_physpages / 30)
+#define	I_CAN_FIT	(AVAILABLE_PAGES > p->mosix.pages_i_bring)
+
+int
+mig_do_receive_page(unsigned long addr)
+{
+	pgd_t * pgd;
+	pmd_t * pmd;
+	pte_t * pte;
+	struct page *page = NULL;
+	struct vm_area_struct *vma;
+	static int stuck_here;
+	unsigned int tries = 0;
+	long pri, mypri;
+	struct task_struct *p = current, *pp;
+	struct mm_struct *mm = p->mm;
+	int must = (p->mosix.dflags & DMUSTBEBACK);
+	static DECLARE_WAIT_QUEUE_HEAD(wait_for_someone_to_give_up);
+
+	if(!(vma = find_vma(mm, addr)))
+		{
+			comm_flushdata(COMM_ALLDATA);
+			return(-1);
+		}
+	while(VERY_LOW_ON_MEMORY)
+		{
+			stuck_here++;
+			tries++;
+			if(must ? (tries > 200 && stuck_here >= 300) :
+			   (tries > 5 && stuck_here >= 100))
+				{
+				give_up:
+					stuck_here = 0;
+					wake_up(&wait_for_someone_to_give_up);
+					printk("%s: Arrival rejected due to severe memory "
+						   "shortage.\n", desc_mostask(NULL));
+					comm_flushdata(COMM_ALLDATA);
+					return(-1);
+				}
+			mypri = ((p->mosix.dflags & DREMOTE) ? 0x20000000 : 0) +
+				(must ? 0 : 0x40000000) +
+				p->mosix.pages_i_bring + mm->rss;
+			pri = 0;
+			read_lock(&tasklist_lock);
+			for_each_task(pp)
+				if(pp != p && (pp->mosix.dflags & DINCOMING))
+					{
+						pri = ((pp->mosix.dflags & DREMOTE) ? 0x20000000 : 0) +
+							((pp->mosix.dflags & DMUSTBEBACK) ? 0 : 0x40000000) +
+							pp->mosix.pages_i_bring + pp->mm->rss;
+						if(pri >= mypri)
+							break;
+					}
+			if(must && tries > 5)
+				for_each_task(pp)
+					if((pp->mosix.dflags & (DREMOTE | DREMOTEDAEMON)) == DREMOTE &&
+					   (tries < 50 || !pp->mosix.stay))
+						{
+							mosix_add_to_whereto(pp, GOBACKHOME);
+							pri = mypri + 1;
+						}
+			read_unlock(&tasklist_lock);
+			if(pri >= mypri || (must ? (tries < 50 || stuck_here < 100) :
+								(stuck_here < 2 ||
+								 ((p->mosix.dflags & DDEPUTY) && tries < 3))))
+				{
+					sleep_on_timeout(&wait_for_someone_to_give_up, HZ/20);
+					continue;
+				}
+			if(must && I_CAN_FIT && (page = alloc_page(GFP_HIGHUSER)))
+				break;
+			goto give_up;
+		}
+	if(stuck_here)
+		{
+			wake_up(&wait_for_someone_to_give_up);
+			stuck_here = 0;
+		}
+	if(--p->mosix.pages_i_bring < 0)
+		mosix_panic("too many pages arrived");
+	p->mosix.rfreepages--;
+	if(!page && !(page = alloc_page(GFP_HIGHUSER)))
+		{
+			comm_flushdata(COMM_ALLDATA);
+			return(-1);
+		}
+	if(comm_copydata(kmap(page), PAGE_SIZE, 0))
+		{
+			kunmap(page);
+			__free_page(page);
+			return(-1);
+		}
+	kunmap(page);
+	pgd = pgd_offset(mm, addr);
+	spin_lock(&mm->page_table_lock);
+	if (!(pmd = pmd_alloc(mm, pgd, addr)))
+		{
+			spin_unlock(&mm->page_table_lock);
+			__free_page(page);
+			return(-1);
+		}
+	if (!(pte = pte_alloc(mm, pmd, addr)))
+		{
+			__free_page(page);
+			spin_unlock(&mm->page_table_lock);
+			return(-1);
+		}
+	if (!pte_none(*pte)) {
+		printk("%s-mig_do_receive_page: double page at addr 0x%x\n",
+			   desc_mostask(NULL), (int)addr);
+		__free_page(page);
+		spin_unlock(&mm->page_table_lock);
+		return(-1);
+	}
+	set_pte(pte, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	mm->rss++;
+	spin_unlock(&mm->page_table_lock);
+	flush_page_to_ram(page);
+	return(0);
+}
+
+void
+mig_do_receive_fp(union i387_union *i)
+{
+	current->used_math = 1;
+	unlazy_fpu(current);
+	if(has_fxsr())
+		fsave_to_fxsave(i, &current->thread.i387);
+	else
+		memcpy((caddr_t)&current->thread.i387, (caddr_t)i, sizeof(*i));
+}
+
+void
+mig_do_receive_xfp(union i387_union *i)
+{
+	current->used_math = 1;
+	unlazy_fpu(current);
+	if(has_fxsr())
+		memcpy((caddr_t)&current->thread.i387, (caddr_t)i, sizeof(*i));
+	else
+		fxsave_to_fsave(i, &current->thread.i387);
+}
+
+int
+mig_do_receive_ldt(void)
+{
+	struct mm_struct *mm = current->mm;
+        void *segments;
+
+        if (!(segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE)))
+		                return(-1);
+         memset(segments, 0, LDT_ENTRIES*LDT_ENTRY_SIZE);
+        wmb();
+        mm->context.segments = segments;
+        mm->context.cpuvalid = 1UL << smp_processor_id();
+        load_LDT(mm);
+        if(comm_copydata(mm->context.segments, LDT_ENTRIES*LDT_ENTRY_SIZE, 0))
+        {
+         release_segments(mm);
+	}
+	 return(0);
+}
+
+void
+mig_do_receive_misc(struct mig_misc_h *m)
+{
+	unsigned int i;
+	int bit;
+	register struct task_struct *p = current;
+
+	if(p->mosix.dflags & DREMOTE)
+		{
+			p->ptrace |= m->ptrace;
+			p->nice = m->nice;
+			p->cap_effective = (p->cap_effective & ~REMOTE_CAPS) |
+				(m->caps & REMOTE_CAPS);
+			memcpy(p->mosix.features, m->features, sizeof(m->features));
+			task_lock(p);
+			if(m->stay)
+				p->mosix.stay |= DNOMIGRATE;
+			else
+				p->mosix.stay &= ~DNOMIGRATE;
+			task_unlock(p);
+			p->mosix.nmigs = m->nmigs;
+			remote_do_updinfo(&m->info);
+		}
+	else
+		{
+			p->ptrace &= ~PT_TRACESYS;
+			p->ptrace |= (m->ptrace & PT_TRACESYS);
+		}
+	p->mosix.dflags &= ~(DTRACESYS1|DTRACESYS2);
+	p->mosix.dflags |= m->dflags;
+	memcpy((caddr_t)p->thread.debugreg, (caddr_t)m->debugreg,
+		   sizeof(m->debugreg));
+	p->it_prof_incr = m->it_prof_incr;
+	p->it_virt_incr = m->it_virt_incr;
+	p->mosix.deputy_regs = m->deputy_regs;
+	for(bit = 1, i = 0 ; i < sizeof(struct pt_regs) / sizeof(int) ;
+		i++ , bit <<= 1)
+		if(!(m->deputy_regs & bit))
+			((int *)p->mosix.altregs)[i] = ((int *)&m->regs)[i];
+	/* recieve task segment registers
+	   FIXME: only do this if task modified the LDT.*/
+	p->mosix.altfs = m->fs;
+	p->mosix.altgs = m->gs;
+	/* recieve rlims*/
+	p->rlim[RLIMIT_CPU] = m->rlim_cpu;
+	p->rlim[RLIMIT_DATA] = m->rlim_data;
+	p->rlim[RLIMIT_STACK] = m->rlim_stack;
+	p->rlim[RLIMIT_RSS] = m->rlim_rss;
+	p->rlim[RLIMIT_AS] = m->rlim_as;
+#ifdef CONFIG_MOSIX_DFSA
+	p->rlim[RLIMIT_NOFILE] = m->rlim_nofile;
+	p->rlim[RLIMIT_FSIZE] = m->rlim_fsz;
+#endif /* CONFIG_MOSIX_DFSA */
+	if((p->mosix.deppe = m->deppe) != PE)
+		this_machine_is_favourite(p->mosix.deppe);
+	p->mosix.deccycle = m->deccycle;
+	p->mosix.decay = m->decay;
+	p->mosix.dpolicy = m->dpolicy;
+	p->mosix.mypid = m->mypid;
+	memcpy(p->mosix.depcost, m->depcost, sizeof(m->depcost));
+	p->mosix.depspeed = m->depspeed;
+	if(p->mosix.dflags & DREMOTE)
+		p->mosix.passedtime = m->passedtime;
+	else
+		p->mosix.passedtime = 0;
+	p->mosix.rpagecredit = m->pagecredit;
+	if(p->mosix.dflags & DREMOTE)
+		{
+			sprintf(p->comm, REMOTESTR2, m->mypid);
+			spin_lock_irq(&p->sigmask_lock);
+			p->mosix.asig |= m->asig.sigs;
+			spin_unlock_irq(&p->sigmask_lock);
+			while(m->asig.nforced--)
+				{
+					siginfo_t info;
+
+					comm_copydata(&info, sizeof(info), 0);
+					force_sig_info(info.si_signo, &info, p);
+				}
+		}
+	cli();
+	p->it_virt_value = m->it_virt_value;
+	p->it_prof_value = m->it_prof_value;
+	p->mosix.last_sigxcpu = m->lastxcpu;
+	sti();
+	if(p->mosix.dflags & DDEPUTY)
+		deputy_analyse_remote_signals(&m->asig);
+}
+
+int
+mig_do_receive(void)
+{
+	struct mosix_task *m = &current->mosix;
+	int type;
+	void *head;
+	int hlen;
+	int (*mmap_func)(struct mmap_parameters_h *, int);
+	unsigned int got_not_coming = 0;
+
+	spin_lock_irq(&runqueue_lock);
+	m->dflags |= DINCOMING;
+	spin_unlock_irq(&runqueue_lock);
+	current->used_math = 0;
+	while(1) {
+		switch(type = comm_recv(&head, &hlen)) {
+		case MIG_MM_STATS:
+			mig_do_receive_mm_stats((struct mm_stats_h *)head);
+			break;
+		case MIG_MM_AREA:
+			if(m->dflags & DREMOTE)
+				mmap_func = remote_mmap;
+			else
+				mmap_func = deputy_remmap;
+			if(mmap_func((struct mmap_parameters_h *)head, 1))
+			{
+				comm_free(head);
+				goto fail;
+			}
+			break;
+		case MIG_PAGE:
+			if(mig_do_receive_page(*((unsigned long *)head)))
+			{
+				comm_free(head);
+				goto fail;
+			}
+			break;
+		case MIG_FP:
+			mig_do_receive_fp((union i387_union *)head);
+			break;
+		case MIG_XFP:
+			mig_do_receive_xfp((union i387_union *)head);
+			break;
+		case MIG_LDT:
+			if(mig_do_receive_ldt())
+			{
+				comm_free(head);
+				goto fail;
+			}
+			break;
+		case MIG_MISC:
+			mig_do_receive_misc((struct mig_misc_h *)head);
+			comm_free(head);
+			spin_lock_irq(&runqueue_lock);
+			m->dflags &= ~DINCOMING;
+			spin_unlock_irq(&runqueue_lock);
+			flush_tlb();	/* for all the new pages */
+			comm_send(MIG_MISC|REPLY, NULL, 0, NULL, 0, 0);
+			return(0);
+		case MIG_NOT_COMING:
+			got_not_coming = 1;
+			goto fail;
+		default:
+			if(m->dflags & DDEPUTY)
+				deputy_communication_failed();
+			comm_free(head);
+			goto fail;
+		}
+		comm_free(head);
+		if((m->dflags & DREMOTE) && (mosadmin_mode_block || !NPE))
+			goto fail;
+	}
+ fail:
+
+	if(type >= 0)
+		comm_flushdata(COMM_ALLDATA);
+	spin_lock_irq(&runqueue_lock);
+	m->dflags &= ~DINCOMING;
+	spin_unlock_irq(&runqueue_lock);
+	if((m->dflags & DDEPUTY) && !got_not_coming)
+	{
+		/* receiving all the debris can take time and
+		   someone may need the memory meanwhile! */
+		current->mosix.pages_i_bring = 0;
+		do_munmap(current->mm, 0, PAGE_OFFSET);
+		while((type = comm_recv(&head, &hlen)) >= 0 &&
+		      type != MIG_NOT_COMING)
+		{
+			comm_free(head);
+			comm_flushdata(COMM_ALLDATA);
+			if(type == MIG_MISC)
+				/* send anything but MIG_MISC|REPLY: */
+				/* they will then send MIG_NOT_COMING! */
+				comm_send(DEP_SYNC, NULL, 0, NULL, 0, 0);
+		}
+	}
+	return(-1);
+}
+
+void
+mig_set_lock(int lock)
+{
+	struct task_struct *p = current;
+
+	task_lock(p);
+	if (lock)
+		p->mosix.stay |= DNOMIGRATE;
+	else
+		p->mosix.stay &= ~DNOMIGRATE;
+	task_unlock(p);
+	if(current->mosix.dflags & DDEPUTY)
+		deputy_request(DEP_UPDATE_LOCK, &lock, sizeof(int), NULL, 0, 0,
+					   NULL, 0);
+}
+
+int
+remote_set_lock(int *lockp)
+{
+	mig_set_lock(*lockp);
+	comm_free(lockp);
+	return(comm_send(DEP_UPDATE_LOCK|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+void
+mig_set_migfilter(int migfilter)
+{
+	struct task_struct *p = current;
+
+	task_lock(p);
+	if (migfilter)
+		p->mosix.dflags |= DMIGFILTER;
+	else
+		p->mosix.dflags &= ~DMIGFILTER;
+	task_unlock(p);
+	if(current->mosix.dflags & DDEPUTY)
+		deputy_request(DEP_UPDATE_MIGFILTER, &migfilter, sizeof(int), NULL, 0, 0,
+					   NULL, 0);
+}
+
+int
+remote_set_migfilter(int *migfilterp)
+{
+	mig_set_migfilter(*migfilterp);
+	comm_free(migfilterp);
+	return(comm_send(DEP_UPDATE_MIGFILTER|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+void
+mig_set_migpolicy(int migpolicy)
+{
+	struct task_struct *p = current;
+
+	task_lock(p);
+	p->mosix.mask.migpolicy = migpolicy;
+	task_unlock(p);
+	if(current->mosix.dflags & DDEPUTY)
+		deputy_request(DEP_UPDATE_MIGPOLICY, &migpolicy, sizeof(int), NULL, 0, 0,
+					   NULL, 0);
+}
+
+int
+remote_set_migpolicy(int *migpolicyp)
+{
+	mig_set_migpolicy(*migpolicyp);
+	comm_free(migpolicyp);
+	return(comm_send(DEP_UPDATE_MIGPOLICY|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+void
+mig_set_mignodes(uint32_t mignodes)
+{
+	struct task_struct *p = current;
+
+	task_lock(p);
+	p->mosix.mask.mignodes = mignodes;
+	task_unlock(p);
+	if(current->mosix.dflags & DDEPUTY)
+		deputy_request(DEP_UPDATE_MIGNODES, &mignodes, sizeof(int), NULL, 0, 0,
+					   NULL, 0);
+}
+
+int
+remote_set_mignodes(uint32_t *mignodesp)
+{
+	mig_set_mignodes(*mignodesp);
+	comm_free(mignodesp);
+	return(comm_send(DEP_UPDATE_MIGNODES|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+void
+mig_set_miggroup(int miggroup)
+{
+        struct task_struct *p = current;
+
+        task_lock(p);
+        p->mosix.mask.miggroup = miggroup;
+        task_unlock(p);
+        if(current->mosix.dflags & DDEPUTY)
+                deputy_request(DEP_UPDATE_MIGPOLICY, &miggroup, sizeof(int), NULL, 0, 0,
+                                           NULL, 0);
+}
+
+int
+remote_set_miggroup(int *miggroup)
+{
+        mig_set_miggroup(*miggroup);
+        comm_free(miggroup);
+        return(comm_send(DEP_UPDATE_MIGGROUP|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+
+
+
+int
+mig_migrate(int to)
+{
+	if (to > 0)
+		return(passto(to, 0) ?
+			   (mos_to_net(to, NULL) ? -ENETUNREACH : -ENXIO) : 0);
+
+	switch(to)
+	{
+	case DM_GOBACKHOME:
+		return(passto(GOBACKHOME, 0) ? -EDIST : 0);
+	case DM_BALANCE:
+		if(current->mosix.dflags & DDEPUTY)
+			coordinate(0, 0);
+		else
+			consider(0, NULL);
+		return(0);
+	}
+	return(-EINVAL);
+}
+
+int
+count_migrating_pages(void)
+{
+	return(run_over_dirty_pages(NULL, 0));
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/mkdefcalls.c linux-openmosix/hpc/mkdefcalls.c
--- linux/hpc/mkdefcalls.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/mkdefcalls.c	2004-02-05 02:48:27.000000000 +0100
@@ -0,0 +1,79 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sys.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef _STDIO_H
+extern int fprintf(FILE *, char *, ...);
+extern int fgets(char *, int, FILE *);
+extern int perror(char *);
+extern FILE *fopen(char *, char *);
+#endif /* _STDIO_H */
+
+char line[2048];
+char sys_name[NR_syscalls][60];
+
+FILE *
+myopen(char *file, char *mode)
+{
+	FILE *ret = fopen(file, mode);
+
+	if(!ret)
+		perror(file);
+	return(ret);
+}
+
+int
+main(void)
+{
+	FILE *entry = myopen(ENTRY_IN, "r");
+	FILE *sysin = myopen(SYSCALLS_IN, "r");
+	FILE *sysout = myopen(SYSCALLS_OUT, "w");
+	register char *c;
+	register unsigned int i;
+	long t, time(long *);
+	char *ctime(long *);
+
+	time(&t);
+	while(fgets(line, 2048, entry) &&
+		strcmp(line, "ENTRY(sys_call_table)\n"))
+			;
+	for(i = 0 ; i < NR_syscalls && fgets(line, 2048, entry) ; i++)
+		if(!strncmp(line, "\t.long SYMBOL_NAME(", 19))
+		{
+			for(c = &line[19] ; *c && *c != ')' ; c++);
+			*c = '\0';
+			if(strcmp(&line[19], "sys_ni_syscall"))
+				strcpy(sys_name[i], &line[19]);
+		}
+	while(fgets(line, 2048, sysin))
+		if(!strncmp(line, "remote_sys_", 11) || !strncmp(line, "remote_old_", 11))
+			for(i = 0 ; i < NR_syscalls ; i++)
+				if(!strncmp(&line[7], sys_name[i], strlen(sys_name[i])) &&
+						line[7+strlen(sys_name[i])] == '(')
+				{
+					sys_name[i][0] = '\0';
+					break;
+				}
+	fprintf(sysout, "/* Please do not edit -- this file is created automatically */\n");
+	fprintf(sysout, "/* %.24s */\n\n", ctime(&t));
+	fprintf(sysout, "#include <linux/sched.h>\n");
+	fprintf(sysout, "#include <asm/ptrace.h>\n");
+	fprintf(sysout, "#include <hpc/routines.h>\n\n");
+	for(i = 0 ; i < NR_syscalls ; i++)
+		if(sys_name[i][0])
+		{
+			fprintf(sysout, "long remote_%s(int n, struct pt_regs regs){\n", sys_name[i]);
+			fprintf(sysout, "return(remote_standard_system_call(n, &regs));\n}\n");
+		}
+	exit(0);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/prequest.c linux-openmosix/hpc/prequest.c
--- linux/hpc/prequest.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/prequest.c	2002-07-10 15:20:15.000000000 +0200
@@ -0,0 +1,807 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#include <linux/sched.h>
+#include <linux/hpc.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/file.h>
+#include <asm/uaccess.h>
+#include <hpc/request.h>
+#include <hpc/routines.h>
+#include <hpc/protocol.h>
+#include <hpc/defs.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+
+int request_on_remote(struct prequest *);
+
+static inline void
+issue_request(struct prequest *pr, struct task_struct *to)
+{
+	sigset_t blocked;
+	register struct task_struct *p = current;
+	unsigned long flags;
+	DECLARE_WAITQUEUE(wait, p);
+
+	if(to->mosix.dflags & DFINISHED)
+	{
+		pr->rflags = PR_ERROR;
+		goto out;
+	}
+	pr->rflags = PR_WAITING;
+	init_waitqueue_head(&pr->waitq);
+	pr->rnext = to->mosix.prequest;
+	to->mosix.prequest = pr;
+	wake_up_mosix(to);
+	if(!p->sig)	/* can happen when calling from EXIT */
+	{
+		pr->rflags &= ~PR_WAITING;
+		goto out;
+	}
+	spin_lock_irqsave(&p->sigmask_lock, flags);
+	blocked = p->blocked;
+	siginitsetinv(&p->blocked, sigmask(SIGKILL));
+	if(p->sig->action[SIGTERM-1].sa.sa_handler == SIG_DFL)
+		p->blocked.sig[0] &= ~sigmask(SIGTERM);
+	if(p->sig->action[SIGINT-1].sa.sa_handler == SIG_DFL)
+		p->blocked.sig[0] &= ~sigmask(SIGINT);
+	if(p->sig->action[SIGQUIT-1].sa.sa_handler == SIG_DFL)
+		p->blocked.sig[0] &= ~sigmask(SIGQUIT);
+	if(p->sig->action[SIGHUP-1].sa.sa_handler == SIG_DFL)
+		p->blocked.sig[0] &= ~sigmask(SIGHUP);
+	recalc_sigpending(p);
+	spin_unlock_irqrestore(&p->sigmask_lock, flags);
+	add_wait_queue(&pr->waitq, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while((pr->rflags == PR_WAITING) && !signal_pending(p))
+	{
+		unlock_mosix();
+		schedule();
+		set_current_state(TASK_INTERRUPTIBLE);
+		lock_mosix();
+	}
+	remove_wait_queue(&pr->waitq, &wait);
+	set_current_state(TASK_RUNNING);
+	spin_lock_irqsave(&p->sigmask_lock, flags);
+	p->blocked = blocked;
+	recalc_sigpending(p);
+	spin_unlock_irqrestore(&p->sigmask_lock, flags);
+	pr->rflags &= ~PR_WAITING;
+ out:
+	free_task_struct(to);
+}
+
+char *
+request_process_to_buf_arg(struct task_struct *p, char *buffer, int command, int arg)
+{
+	struct prequest *pr;
+	char *reply = buffer;
+
+	get_task_struct(p);
+	if(!(pr = kmalloc(sizeof(struct prequest), GFP_KERNEL)))
+	{
+		free_task_struct(p);
+		return(reply);
+	}
+	pr->command = command;
+	pr->param = arg;
+	pr->ereply = buffer;
+	pr->len = 0;
+	pr->reply = 0;
+	if(command == PR_PROCFS_TASK_MEM && pick_ps(p, pr))
+	{
+		reply = (char *)pr->reply;
+		kfree(pr);
+		free_task_struct(p);
+		return(reply);
+	}
+	lock_mosix();
+	issue_request(pr, p);
+	if(pr->rflags == PR_DONE)
+		reply = (char *)pr->reply;
+	if(pr->rflags & (PR_DONE|PR_ERROR))
+		kfree(pr);
+	unlock_mosix();
+	return(reply);
+}
+
+int
+request_process_arg2(struct task_struct *p, void *indata, int command, int arg, int arg2)
+{
+	struct prequest *pr;
+	int reply = -ENOMEM;
+
+	get_task_struct(p);
+	if(!(pr = kmalloc(sizeof(struct prequest), GFP_KERNEL)))
+	{
+		free_task_struct(p);
+		return(reply);
+	}
+	reply = -EIO;
+	pr->command = command;
+	pr->param = arg;
+	pr->param2 = arg2;
+	pr->ereply = indata;
+	pr->len = 0;
+	pr->reply = 0;
+	switch(command)
+	{
+	case PR_PROCFS_GET_ARG:
+	case PR_PROCFS_GET_ENV:
+	case PR_PROCFS_GET_STAT_PARTS:
+	case PR_PROCFS_GET_STATM:
+		if(pick_ps(p, pr))
+		{
+			reply = pr->reply;
+			kfree(pr);
+			free_task_struct(p);
+			return(reply);
+		}
+		break;
+#ifdef CONFIG_MOSIX_DFSA
+	case PR_DFSA_SYNCHRONIZE:
+		if(p->mosix.ps)
+		{
+			kfree(pr);
+			free_task_struct(p);
+			return(0);
+		}
+#endif /* CONFIG_MOSIX_DFSA */
+	}
+	lock_mosix();
+	issue_request(pr, p);
+	if(pr->rflags == PR_DONE)
+		reply = pr->reply;
+	if(pr->rflags & (PR_DONE|PR_ERROR))
+		kfree(pr);
+	else
+		reply = -EINTR;
+	unlock_mosix();
+	return(reply);
+}
+
+int
+request_on_local(struct prequest *pr)
+{
+	switch(pr->command)
+	{
+	case PR_PROCFS_TASK_MEM:
+		pr->reply = (long)(current->mm ?
+				   task_mem(current->mm, pr->ereply) : pr->ereply);
+		break;
+	case PR_PROCFS_GET_ENV:
+		pr->reply = proc_pid_environ(current, pr->ereply);
+		break;
+	case PR_PROCFS_GET_ARG:
+		pr->reply = proc_pid_cmdline(current, pr->ereply);
+		break;
+	case PR_PROCFS_GET_STAT_PARTS:
+		proc_get_stat_parts(current, current->mm,
+				    (struct proc_remote_stat_parts *)pr->ereply);
+		pr->reply = 0;
+		break;
+	case PR_PROCFS_GET_STATM:
+		pr->reply = proc_pid_statm(current, pr->ereply);
+		break;
+	case PR_PROCFS_GET_EXE:
+		pr->reply = (int)first_executable();
+		break;
+	case PR_PROCFS_MAP_INFO:
+		pr->reply = proc_list_maps((struct vmamaps *)pr->ereply,
+					   pr->param);
+		ref_mapped_files((struct vmamaps *)pr->ereply,
+				 pr->reply);
+		break;
+	case PR_PROCFS_MEM_READ:
+		pr->reply = access_process_vm(current,
+					      (unsigned long)pr->param, pr->ereply,
+					      pr->param2, 0);
+		break;
+	case PR_PROCFS_MEM_WRITE:
+		pr->reply = access_process_vm(current,
+					      (unsigned long)pr->param, pr->ereply,
+					      pr->param2, 1);
+		break;
+#ifdef CONFIG_MOSIX_DFSA
+	case PR_DFSA_SYNCHRONIZE:
+#endif /* CONFIG_MOSIX_DFSA */
+	case PR_PTRACE_NOT_TRACED:
+	case PR_PROCFS_UPDATE_TIMES:
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_GET_STACK_LONG:
+		pr->reply = get_stack_long(current, pr->param);
+		break;
+	case PR_PTRACE_PUT_STACK_LONG:
+		pr->reply = put_stack_long(current, pr->param,
+					   (unsigned long)pr->param2);
+		break;
+	case PR_PTRACE_GETREGS:
+		ptrace_getregs((unsigned long *)pr->ereply);
+		break;
+	case PR_PTRACE_SETREGS:
+		ptrace_putregs((unsigned long *)pr->ereply);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_PEEKUSER:
+		*((unsigned long *)pr->ereply) =
+			ptrace_peekuser(pr->param);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_POKEUSER:
+		ptrace_pokeuser(pr->param, pr->param2);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_CONT:
+		ptrace_cont(pr->param);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_SINGLE_STEP:
+		ptrace_single_step();
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_GETFPREGS:
+		ptrace_getfpregs((struct user_i387_struct *)pr->ereply);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_SETFPREGS:
+		ptrace_setfpregs((struct user_i387_struct *)pr->ereply);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_GETFPXREGS:
+		ptrace_getfpxregs(
+			(struct user_fxsr_struct *)pr->ereply);
+		pr->reply = 0;
+		break;
+	case PR_PTRACE_SETFPXREGS:
+		ptrace_setfpxregs(
+			(struct user_fxsr_struct *)pr->ereply);
+		pr->reply = 0;
+		break;
+	}
+	return(PR_DONE);
+}
+
+void
+free_unwanted_request(struct prequest *pr)
+{
+	struct file *filp;
+
+	if((pr->rflags & (PR_WAITING|PR_DONE|PR_ERROR)) == PR_DONE)
+		switch(pr->command)
+		{
+		case PR_PROCFS_GET_EXE:
+			filp = (struct file *)pr->reply;
+			if(filp)
+				fput(filp);
+			break;
+		}
+	kfree(pr);
+}
+
+void
+process_requests(void)
+{
+	register struct prequest *pr;
+	int res;
+
+	lock_mosix();
+	while((pr = current->mosix.prequest))
+	{
+		current->mosix.prequest = pr->rnext;
+		if(!(pr->rflags & PR_WAITING))
+		{
+			kfree(pr);
+			continue;
+		}
+		unlock_mosix();
+		pr->reply = 0;
+		if(current->mosix.dflags & DDEPUTY)
+			res = request_on_remote(pr);
+		else
+			res = request_on_local(pr);
+		lock_mosix();
+		pr->rflags |= res;
+		if(pr->rflags & PR_WAITING)
+			wake_up(&pr->waitq);
+		else
+		{
+			unlock_mosix();
+			free_unwanted_request(pr);
+			lock_mosix();
+		}
+	}
+	unlock_mosix();
+}
+
+void
+discard_requests(void)
+{
+	register struct prequest *pr;
+
+	lock_mosix();
+	while((pr = current->mosix.prequest))
+	{
+		current->mosix.prequest = pr->rnext;
+		if(pr->rflags & PR_WAITING)
+		{
+			pr->rflags |= PR_ERROR;
+			wake_up(&pr->waitq);
+		}
+		else
+		{
+			unlock_mosix();
+			free_unwanted_request(pr);
+			lock_mosix();
+		}
+	}
+	unlock_mosix();
+}
+
+int
+request_on_remote(struct prequest *pr)
+{
+	struct prequest_h p;
+	struct prequest_reply_h r;
+	void *snd;
+	int sndlen;
+	int err = 0;
+
+	p.command = pr->command;
+	p.param = pr->param;
+	p.param2 = pr->param2;
+	p.len = pr->len;
+	snd = NULL;
+	sndlen = 0;
+	switch(pr->command)
+	{
+	case PR_PROCFS_MEM_READ:
+		flush_read_cache();
+		break;
+	case PR_PROCFS_MEM_WRITE:
+		flush_ucache();
+		snd = pr->ereply;
+		sndlen = pr->param2;
+		break;
+#ifdef CONFIG_MOSIX_DFSA
+	case PR_DFSA_SYNCHRONIZE:
+		/* once we are here - we have already achieved
+		 * the purpose of synchronization!
+		 */
+		pr->reply = 0;
+		goto done;
+#endif /* CONFIG_MOSIX_DFSA */
+	case PR_PTRACE_SETREGS:
+		snd = pr->ereply;
+		sndlen = 17 * sizeof(long);
+		break;
+	case PR_PTRACE_SETFPREGS:
+		snd = pr->ereply;
+		sndlen = sizeof(struct user_i387_struct);
+		break;
+	case PR_PTRACE_SETFPXREGS:
+		snd = pr->ereply;
+		sndlen = sizeof(struct user_fxsr_struct);
+		break;
+		/* the following may be done locally */
+	case PR_PROCFS_GET_STAT_PARTS:
+	case PR_PROCFS_GET_STATM:
+	case PR_PROCFS_TASK_MEM:
+		if(pick_ps(current, pr))
+			goto done;
+		break;
+		/* the following read from user: */
+	case PR_PROCFS_GET_ARG:
+	case PR_PROCFS_GET_ENV:
+		if(pick_ps(current, pr))
+			goto done;
+		flush_read_cache();
+		break;
+	case PR_PROCFS_UPDATE_TIMES:
+		mosix_deputy_rusage(0);
+		pr->reply = 0;
+		goto done;
+	}
+	if(deputy_request(DEP_PREQUEST, &p, sizeof(p), snd, sndlen, 0,
+			  (void **)&r, -sizeof(r)) || r.error)
+	{
+		err = PR_ERROR;
+		goto done;
+	}
+	pr->reply = r.reply;
+	if(r.datalen > 0 && comm_copydata(pr->ereply, r.datalen, 0))
+		err = PR_ERROR;
+	else
+		switch(pr->command)
+		{
+		case PR_PROCFS_TASK_MEM:
+			pr->reply = (int)(pr->ereply + r.reply);
+			break;
+		case PR_PROCFS_GET_STAT_PARTS:
+			mosix_deputy_rusage(0);
+			break;
+		case PR_PROCFS_GET_ENV:
+		case PR_PROCFS_GET_ARG:
+		case PR_PROCFS_GET_STATM:
+		case PR_PTRACE_GET_STACK_LONG:
+		case PR_PTRACE_PUT_STACK_LONG:
+		case PR_PTRACE_GETREGS:
+		case PR_PTRACE_SETREGS:
+		case PR_PTRACE_PEEKUSER:
+		case PR_PTRACE_POKEUSER:
+		case PR_PTRACE_CONT:
+		case PR_PTRACE_SINGLE_STEP:
+		case PR_PTRACE_GETFPREGS:
+		case PR_PTRACE_SETFPREGS:
+		case PR_PTRACE_GETFPXREGS:
+		case PR_PTRACE_SETFPXREGS:
+		case PR_PROCFS_MEM_READ:
+		case PR_PROCFS_MEM_WRITE:
+			break;
+		case PR_PROCFS_MAP_INFO:
+			ref_mapped_files((struct vmamaps *)pr->ereply,
+					 pr->reply);
+			break;
+		case PR_PROCFS_GET_EXE:
+		{
+			struct file *filp = (struct file *)pr->reply;
+			if(filp)
+				get_file(filp);
+		}
+		break;
+		default:
+			printk("request on remote - unknown code\n");
+		}
+ done:
+	return(PR_DONE|err);
+}
+
+int
+remote_prequest(struct prequest_h *p)
+{
+	struct prequest_reply_h r;
+	char *buffer;
+	int err;
+	unsigned long data[17];
+	unsigned int allocated = 0;
+
+	r.error = r.datalen = 0;
+	switch(p->command)
+	{
+	case PR_PROCFS_TASK_MEM:
+	case PR_PROCFS_GET_ENV:
+	case PR_PROCFS_GET_ARG:
+	case PR_PROCFS_GET_STAT_PARTS:
+	case PR_PROCFS_GET_STATM:
+	case PR_PROCFS_MAP_INFO:
+	case PR_PROCFS_MEM_READ:
+	case PR_PTRACE_GETFPREGS:
+	case PR_PTRACE_GETFPXREGS:
+		if((buffer = (char *)__get_free_page(GFP_KERNEL)))
+			allocated = 1;
+		else
+		{
+			r.error = -ENOMEM;
+			buffer = NULL;
+		}
+		break;
+	case PR_PTRACE_GETREGS:
+	case PR_PTRACE_PEEKUSER:
+		buffer = (char *)data;
+		break;
+	default:
+		buffer = NULL;
+		break;
+	}
+	if(!r.error)
+		switch(p->command)
+		{
+		case PR_PROCFS_TASK_MEM:
+			r.datalen = r.reply = current->mm ?
+				task_mem(current->mm, buffer) - buffer : 0;
+			break;
+		case PR_PROCFS_GET_ENV:
+			r.datalen = r.reply = proc_pid_environ(current, buffer);
+			break;
+		case PR_PROCFS_GET_ARG:
+			r.datalen = r.reply = proc_pid_cmdline(current, buffer);
+			break;
+		case PR_PROCFS_GET_STAT_PARTS:
+			proc_get_stat_parts(current, current->mm,
+					    (struct proc_remote_stat_parts *)buffer);
+			r.reply = 0;
+			r.datalen = sizeof(struct proc_remote_stat_parts);
+			break;
+		case PR_PROCFS_GET_STATM:
+			r.datalen = r.reply = proc_pid_statm(current, buffer);
+			break;
+		case PR_PROCFS_GET_EXE:
+			r.reply = (int)first_executable();
+			break;
+		case PR_PROCFS_MAP_INFO:
+			r.datalen = r.reply = proc_list_maps(
+				(struct vmamaps *)buffer, p->param);
+			break;
+		case PR_PROCFS_MEM_READ:
+			r.datalen = r.reply = access_process_vm(current,
+								p->param, (void *)buffer, p->param2, 0);
+			break;
+		case PR_PROCFS_MEM_WRITE:
+			if(comm_recvdata((void **)&buffer))
+				r.reply = 0;
+			else
+			{
+				r.reply = access_process_vm(current, p->param,
+							    (void *)buffer, p->param2, 1);
+				comm_free(buffer);
+			}
+			break;
+		case PR_PTRACE_GET_STACK_LONG:
+			r.reply = get_stack_long(current, p->param);
+			break;
+		case PR_PTRACE_PUT_STACK_LONG:
+			r.reply = put_stack_long(current, p->param,
+						 (unsigned long)p->param2);
+			break;
+		case PR_PTRACE_GETREGS:
+			ptrace_getregs((unsigned long *)buffer);
+			r.datalen = 17 * sizeof(unsigned long);
+			r.reply = 0;
+			break;
+		case PR_PTRACE_SETREGS:
+			r.reply = 0;
+			if(!comm_recvdata((void **)&buffer))
+			{
+				ptrace_putregs((unsigned long *)buffer);
+				comm_free(buffer);
+			}
+			break;
+		case PR_PTRACE_PEEKUSER:
+			data[0] = ptrace_peekuser(p->param);
+			r.datalen = sizeof(unsigned long);
+			r.reply = 0;
+			break;
+		case PR_PTRACE_POKEUSER:
+			ptrace_pokeuser(p->param, p->param2);
+			r.datalen = r.reply = 0;
+			break;
+		case PR_PTRACE_CONT:
+			ptrace_cont(p->param);
+			r.datalen = r.reply = 0;
+			break;
+		case PR_PTRACE_NOT_TRACED:
+			current->ptrace = 0;
+			r.datalen = r.reply = 0;
+			break;
+		case PR_PTRACE_SINGLE_STEP:
+			ptrace_single_step();
+			r.datalen = r.reply = 0;
+			break;
+		case PR_PTRACE_GETFPREGS:
+			ptrace_getfpregs((struct user_i387_struct *)buffer);
+			r.datalen = sizeof(struct user_i387_struct);
+			r.reply = 0;
+			break;
+		case PR_PTRACE_SETFPREGS:
+			r.reply = 0;
+			if(!comm_recvdata((void **)&buffer))
+			{
+				ptrace_setfpregs(
+					(struct user_i387_struct *)buffer);
+				comm_free(buffer);
+			}
+			break;
+		case PR_PTRACE_GETFPXREGS:
+			ptrace_getfpxregs((struct user_fxsr_struct *)buffer);
+			r.datalen = sizeof(struct user_fxsr_struct);
+			r.reply = 0;
+			break;
+		case PR_PTRACE_SETFPXREGS:
+			r.reply = 0;
+			if(!comm_recvdata((void **)&buffer))
+			{
+				ptrace_setfpxregs(
+					(struct user_fxsr_struct *)buffer);
+				comm_free(buffer);
+			}
+			break;
+		}
+	err = comm_send(DEP_PREQUEST|REPLY, &r, sizeof(r),
+			r.datalen ? buffer : NULL, r.datalen, 0);
+	if(allocated)
+		free_page((unsigned long)buffer);
+	comm_free(p);
+	return(err);
+}
+
+void
+process_only_easy_requests(void)
+{
+	register struct prequest *pr, *prev, *next;
+
+	if(!current->mosix.ps)
+		return;
+	lock_mosix();
+	for(prev = NULL, pr = current->mosix.prequest ; pr ; )
+		switch(pr->command)
+		{
+#ifdef CONFIG_MOSIX_DFSA
+		case PR_DFSA_SYNCHRONIZE:
+			pr->reply = 0;
+			pr->rflags |= PR_DONE;
+			goto next_one;
+#endif /* CONFIG_MOSIX_DFSA */
+		case PR_PROCFS_GET_ARG:
+		case PR_PROCFS_GET_ENV:
+		case PR_PROCFS_TASK_MEM:
+		case PR_PROCFS_GET_STAT_PARTS:
+		case PR_PROCFS_GET_STATM:
+			pick_ps(current, pr);
+#ifdef CONFIG_MOSIX_DFSA
+		next_one:
+#endif /* CONFIG_MOSIX_DFSA */
+			next = pr->rnext;
+			if(prev)
+				prev->rnext = next;
+			else
+				current->mosix.prequest = next;
+			if(pr->rflags & PR_WAITING)
+				wake_up(&pr->waitq);
+			else
+				kfree(pr);
+			pr = next;
+			break;
+		default:
+			prev = pr;
+			pr = pr->rnext;
+		}
+	unlock_mosix();
+}
+
+/* Saved record structure:
+ * 1: args (null terminated)
+ * 2: env (null terminated)
+ * 3: task_mem (null terminated)
+ * 4: struct proc_remote_stat_parts (32 bytes at the moment)
+ * 5: statm output (null terminated)
+ * Below is an overkill estimate of 3+4+5:
+ */
+#define	MAX_REQ_FOR_STATS	350
+
+char *
+fill_common_ps_info(int *n)
+{
+	char *buffer = kmalloc(2*PAGE_SIZE+MAX_REQ_FOR_STATS, GFP_KERNEL);
+	char *e, *p;
+	struct task_struct *t = current;
+	int l1, l2, l3;
+
+	if(n)
+		*n = 0;
+	if(!buffer)
+		return(NULL);
+	e = buffer + (l1 = proc_pid_cmdline(t, buffer));
+	e += (l2 = proc_pid_environ(t, e));
+	e += (l3 = task_mem(t->mm, e) - e);
+	proc_get_stat_parts(t, t->mm, (struct proc_remote_stat_parts *)e);
+	e += sizeof(struct proc_remote_stat_parts);
+	e += proc_pid_statm(t, e);
+	*e++ = '\0';
+	if((p = kmalloc(e - buffer + 3*sizeof(short), GFP_KERNEL)))
+	{
+		((short *)p)[0] = l1;
+		((short *)p)[1] = l2;
+		((short *)p)[2] = l3;
+		memcpy(p + 3 * sizeof(short), buffer, l1 = e - buffer);
+	}
+	kfree(buffer);
+	if(n)
+		*n = p ? l1 + 3*sizeof(short) : 0;
+	return(p);
+}
+void
+store_common_ps_info(void)
+{
+	int n;
+	char *p;
+
+	if(current->mosix.dflags & DDEPUTY)
+	{
+		flush_read_cache();
+		if(deputy_request(DEP_PSINFO, NULL, 0, NULL, 0, 0,
+				  (void **)&n, -sizeof(n)) || n <= 0)
+			return;
+		if(!(p = kmalloc(n, GFP_KERNEL)))
+		{
+			comm_flushdata(COMM_ALLDATA);
+			return;
+		}
+		if(comm_copydata(p, n, 0))
+			kfree(p);
+		else
+		{
+			lock_mosix();
+			current->mosix.ps = p;
+			unlock_mosix();
+		}
+	}
+	else
+	{
+		p = fill_common_ps_info(NULL);
+		lock_mosix();
+		current->mosix.ps = p;
+		unlock_mosix();
+	}
+	if(current->mosix.prequest)
+		process_only_easy_requests();
+}
+
+void
+stop_storing_common_ps_info(void)
+{
+	char *ps;
+
+	lock_mosix();
+	ps = current->mosix.ps;
+	current->mosix.ps = NULL;
+	unlock_mosix();
+	if(ps)
+		kfree(ps);
+}
+
+int
+pick_ps(struct task_struct *task, struct prequest *pr)
+{
+	register char *p, *t;
+	int l1, l2, l3;
+
+	lock_mosix();
+	if(!(p = task->mosix.ps))
+	{
+		unlock_mosix();
+		return(0);
+	}
+	l1 = *((short *)p)++;
+	l2 = *((short *)p)++;
+	l3 = *((short *)p)++;
+	switch(pr->command)
+	{
+	case PR_PROCFS_GET_STATM:
+		p += l1+l2+l3 + sizeof(struct proc_remote_stat_parts);
+		t = pr->ereply;
+		while(*p)
+			*t++ = *p++;
+		pr->reply = t - pr->ereply;
+		break;
+	case PR_PROCFS_GET_STAT_PARTS:
+		p += l1 + l2 + l3;
+		memcpy(pr->ereply, p,
+		       sizeof(struct proc_remote_stat_parts));
+		pr->reply = sizeof(struct proc_remote_stat_parts);
+		break;
+	case PR_PROCFS_TASK_MEM:
+		memcpy(pr->ereply, p + l1 + l2, l3);
+		pr->reply = (int)(pr->ereply + l3);
+		break;
+	case PR_PROCFS_GET_ENV:
+		memcpy(pr->ereply, p + l1, l2);
+		pr->reply = l2;
+		break;
+	case PR_PROCFS_GET_ARG:
+		memcpy(pr->ereply, p, l1);
+		pr->reply = l1;
+		break;
+	default:
+		panic("pick_ps: command");
+	}
+	pr->rflags |= PR_DONE;
+	unlock_mosix();
+	return(1);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/remote.c linux-openmosix/hpc/remote.c
--- linux/hpc/remote.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/remote.c	2004-02-05 02:48:27.000000000 +0100
@@ -0,0 +1,1451 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/hpc.h>
+#include <linux/personality.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <hpc/routines.h>
+#include <hpc/defs.h>
+#include <hpc/debug.h>
+#include <asm/processor.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <asm/uaccess.h>
+#include <linux/in6.h>
+#include <asm/checksum.h>
+#include <linux/slab.h>
+#include <linux/elf.h>
+#include <asm/mman.h>
+#include <linux/unistd.h>
+#include <linux/module.h>
+#include <linux/file.h>
+#include <hpc/balance.h>
+#include <hpc/dfsa.h>
+
+int
+remote_wait(int expect, void **head, int *hlen)
+{
+	int type, error = 0;
+	register struct task_struct *p = current;
+	struct syscall_ret_h *rp;
+	unsigned int has_ret_value = 0;
+	int ret_value = 0;	/* value set only to pacify compiler */
+
+	while(1)
+	{
+		if(URGENT_REMOTE_CONDITIONS(p) &&
+					!(p->mosix.dflags & DSENTURGENT))
+			inform_deputy_of_urgent();
+		if((type = comm_recv(head, hlen)) < 0)	/* an error */
+			return(type);
+		if(expect == DEP_USERMODE)
+		/* after migration from REMOTE to REMOTE, certain "replies"
+		 * can arrive as a result from the original call.
+		 * Fortunately, there are not too many of them:
+		 */
+			switch(type & ~USERMODE)
+			{
+			case REM_SYSCALL|REPLY:
+				rp = *head;
+				absorb_deptime(rp->deputytime);
+				remote_unpack_read_cache_data(rp);
+				has_ret_value = 1;
+				ret_value = rp->ret;
+				/* fall through */
+			case REM_SYSCALL_TRACE|REPLY:
+				if(!(type & USERMODE))
+				{
+					comm_free(*head);
+					*head = NULL;
+					continue;
+				}
+			}
+		if(type & USERMODE)
+		{
+			p->mosix.dflags &= ~DPSYNC;
+			if(expect == DEP_USERMODE)
+			{
+				if(has_ret_value)
+					mos_to_regs(&p->mosix)->eax = ret_value;
+				return(0);
+			}
+			if(type != (expect | USERMODE))
+			{
+				printk("REMOTE-%d: Unexected USERMODE while waiting for 0x%x\n",
+					p->pid, expect);
+				mosix_panic("Unexpected USERMODE");
+				return(-EINVAL);
+			}
+		}
+		if((type & ~USERMODE) == expect)
+			return(0);
+		switch(type & ~USERMODE)
+		{
+		case DEP_SYNC:
+			comm_free(*head);
+			break;
+		case DEP_NOTHING:
+			comm_free(*head);
+			error = comm_send(DEP_NOTHING|REPLY, NULL, 0,
+					  NULL, 0, 0);
+			break;
+		case DEP_MMAP:
+			error = remote_mmap((struct mmap_parameters_h *)*head, 0);
+			break;
+		case DEP_BRK:
+			error = remote_brk((struct brk_parameters_h *)*head);
+			break;
+		case DEP_MUNMAP:
+			error = remote_munmap((struct munmap_parameters_h *)*head);
+			break;
+		case DEP_MPROTECT:
+			error = remote_mprotect((struct mprotect_parameters_h *)*head);
+			break;
+		case DEP_LISTHOLD:
+			comm_free(*head);
+			error = remote_report_files();
+			break;
+		case DEP_SETUPFRAME:
+			error = remote_setup_frame((struct setupframe_parameters_h *)*head);
+			break;
+		case DEP_NICE:
+			error = remote_nice((long *)*head);
+			break;
+		case DEP_INFO:
+			error = remote_updinfo((struct disclosure_h *)*head);
+			break;
+		case DEP_CAPS:
+			error = remote_caps((kernel_cap_t *)*head);
+			break;
+		case DEP_OPCOSTS:
+			error = remote_depcosts(*head);
+			break;
+		case DEP_RESTORESIGCONTEXT:
+			error = remote_restore_sigcontext((struct sigcontext **)*head);
+			break;
+		case DEP_PREQUEST:
+			error = remote_prequest((struct prequest_h *)*head);
+			break;
+		case DEP_COPY_FROM_USER:
+			error = remote_copy_from_user((struct user_copy_h *)*head);
+			break;
+		case DEP_COPY_TO_USER:
+			error = remote_copy_to_user((struct user_copy_h *)*head);
+			break;
+		case DEP_DATA_TO_USER:
+			error = remote_data_to_user((struct user_copy_h *)*head);
+			break;
+		case DEP_CLEAR_USER:
+			error = remote_clear_user((struct user_copy_h *)*head);
+			break;
+		case DEP_STRNCPY_FROM_USER:
+			error = remote_strncpy_from_user((struct user_copy_h *)*head);
+			break;
+		case DEP_STRNLEN_USER:
+			error = remote_strnlen_user((struct strnlen_user_h *)*head);
+			break;
+		case DEP_VERIFY_WRITE:
+			error = remote_verify_write((struct user_copy_h *)*head);
+			break;
+		case DEP_CSUM_COPY_FROM_USER:
+			error = remote_csum_copy_from_user((struct user_csum_copy_h *)*head);
+			break;
+		case DEP_CACHE_READ_DATA:
+			error = remote_unpack_read_cache_data(NULL);
+			/* NO REPLY! */
+			break;
+		case DEP_RLIMIT:
+			error = remote_rlimit((struct rlimit_h *)*head);
+			break;
+		case DEP_TAKEURGENT:
+			comm_free(*head);
+			error = remote_urgent();
+			break;
+		case DEP_RUSAGE:
+			error = remote_rusage((int *)*head);
+			break;
+		case DEP_PERSONALITY:
+			error = remote_personality((unsigned long *)*head);
+			break;
+		case DEP_EXECVE_COUNTS:
+			error = remote_execve_counts((struct execve_counts_h *)*head);
+			break;
+		case DEP_BRING_STRINGS:
+			error = remote_bring_strings((struct execve_bring_strings_h *)*head);
+			break;
+		case DEP_SETUP_ARGS:
+			error = remote_setup_args((struct execve_setup_args_h *)*head);
+			break;
+		case DEP_EXEC_MMAP:
+			error = remote_exec_mmap();
+			break;
+		case DEP_INIT_AOUT_MM:
+			error = remote_init_aout_mm((struct exec *)*head);
+			break;
+		case DEP_ELF_SETUP:
+			error = remote_elf_setup((struct execve_elf_setup_h *)*head);
+			break;
+		case DEP_FIX_ELF_AOUT:
+			error = remote_fix_elf_aout((struct execve_fix_elf_aout_h *)*head);
+			break;
+		case DEP_DUMP_THREAD:
+			/* comm_free(*head); is not needed (NULL) */
+			error = remote_dump_thread();
+			break;
+		case DEP_LIST_VMAS:
+			/* comm_free(*head); is not needed (NULL) */
+			error = remote_list_vmas();
+			break;
+		case DEP_PLEASE_FORK:
+			error = remote_fork((struct fork_h *)*head);
+			break;
+		case DEP_BRING_ME_REGS:
+			error = remote_bring_me_regs((unsigned long *)*head);
+			break;
+		case DEP_DUMP_FPU:
+			/* comm_free(*head); is not needed (NULL) */
+			error = remote_dump_fpu();
+			break;
+		case DEP_COME_BACK:
+			if (!remote_come_back(*head) || bootexpel)
+				remote_disappear();
+			break;
+		case DEP_PLEASE_MIGRATE:
+			error = remote_goto_remote(*head);
+			break;
+		case DEP_CONSIDER:
+			error = remote_consider((int *)*head);
+			break;
+		case DEP_UPDATE_DECAY:
+			error = remote_setdecay((struct decay_h *)*head);
+			break;
+		case DEP_UPDATE_LOCK:
+			error = remote_set_lock((int *)*head);
+			break;
+		case DEP_UPDATE_MIGFILTER:
+			error = remote_set_migfilter((int *)*head);
+			break;
+		case DEP_UPDATE_MIGPOLICY:
+			error = remote_set_migpolicy((int *)*head);
+			break;
+		case DEP_UPDATE_MIGNODES:
+			error = remote_set_mignodes((int *)*head);
+			break;
+		case DEP_PSINFO:
+			/* comm_free(*head); is not needed (NULL) */
+			error = remote_psinfo();
+			break;
+#ifdef CONFIG_MOSIX_DFSA
+		case DEP_DFSA_CLEAR:
+			remote_clear_dfsa();
+			error = comm_send(DEP_DFSA_CLEAR|REPLY, NULL, 0,
+					  NULL, 0, 0);
+			break;
+		case DEP_DFSA_CHANGES:
+			error = remote_receive_dfsachanges((int *)*head);
+			break;
+		case DEP_READ_YOURSELF:
+			error = remote_read_yourself(
+				(struct read_yourself_h *)*head);
+			break;
+#endif /* CONFIG_MOSIX_DFSA */
+		default:
+			printk("openMosix: remote type %x unexpected\n", type);
+
+			if(type != MIG_REQUEST)
+				mosix_panic("deputy_wait");
+			return(-EINVAL);
+		}
+		if(error)
+		{
+			return(error);
+		}
+	}
+}
+
+int
+remote_request(int type, void *header, int hlen, void *data, int dlen,
+	int uspace, void **result, int reslen)
+{
+	void *head;
+	int rhlen;
+	int error;
+
+	if((error = comm_send(type, header, hlen, data, dlen, uspace)))
+		return(error);
+	if((error = remote_wait(type|REPLY, &head, &rhlen)))
+		return(error);
+	if(reslen > 0)
+	{
+		if(rhlen > reslen)
+			goto lenerr;
+		if(result)
+			*result = head;
+	}
+	else
+	{
+		if(rhlen > -reslen)
+		{
+			comm_free(head);
+			lenerr:
+			printk("remote_request type %x: %d instead of %d\n",
+				type, rhlen, reslen);
+			return(-EDIST);
+		}
+		if(reslen)
+			memcpy(result, head, rhlen);
+		comm_free(head);
+	}
+	return(error);
+}
+
+int
+remote_deputy_has_something_for_us(struct task_struct *p)
+{
+	return((p->mosix.dflags & DPSYNC) || comm_peek());
+}
+
+void
+wait_for_permission_to_continue()
+{
+	struct task_struct *p = current;
+	void *head;
+	int hlen;
+
+	if(!p->mosix.contact)
+	{
+		DECLARE_WAITQUEUE(wait, current);
+
+		add_wait_queue(mos_to_waitp(&p->mosix), &wait);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		while(!p->mosix.contact)
+		{
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			if(p->mosix.contact)
+				break;
+			schedule();
+		}
+		remove_wait_queue(mos_to_waitp(&p->mosix), &wait);
+		set_current_state(TASK_RUNNING);
+	}
+	if(!(p->mosix.dflags & DPSYNC))
+	{
+		if(!comm_peek())
+			return;
+		if(URGENT_REMOTE_CONDITIONS(p) &&
+					!(p->mosix.dflags & DSENTURGENT))
+			inform_deputy_of_urgent();
+		if(comm_send(REM_NULLMSG, NULL, 0, NULL, 0, 0))
+			remote_disappear();
+	}
+	if(remote_wait(DEP_USERMODE, &head, &hlen))
+		remote_disappear();
+	comm_free(head);
+	if(p->mosix.deputy_regs)
+	{
+		printk("%s: Missing registers on User-Mode",desc_mostask(NULL));
+		mosix_panic("missing regs");
+		remote_disappear();
+	}
+}
+
+void
+inform_deputy_of_urgent(void)
+{
+	struct mosix_task *m = &current->mosix;
+
+	if(m->dflags & (DPASSING|DINCOMING))
+		return;
+
+	spin_lock_irq(&runqueue_lock);
+	m->dflags |= DSENTURGENT;
+	spin_unlock_irq(&runqueue_lock);
+	comm_send_urgent();
+	/* (any errors will be detected by a later communication failure) */
+}
+
+void
+transfer_signals_to_deputy(unsigned int sigs, siginfo_t *info, int ninfo)
+{
+	struct asig_h a;
+
+	a.sigs = sigs;
+	a.nforced = ninfo;
+	comm_send(REM_ASIG, &a, sizeof(a), info, ninfo * sizeof(siginfo_t), 0);
+}
+
+NORET_TYPE void
+remote_disappear(void)
+{
+	do_exit(SIGKILL);
+	/*NOTREACHED*/
+}
+
+long
+remote_standard_system_call(int n, struct pt_regs *regs)
+{
+	struct syscall_h s;
+	struct syscall_ret_h r;
+	char *p, *tofree;
+	int l;
+	int data_from_user;
+	void *head;
+	int rhlen;
+	int error;
+
+	s.n = n;
+	memcpy((caddr_t)s.args, (caddr_t)regs, sizeof(s.args));
+	switch(n)
+	{
+		/* the following system-calls are supposed to ask for the
+		 * following registers - but why wait for them to ask?
+		 */
+	case __NR_fork:
+	case __NR_vfork:
+	case __NR_clone:
+	case __NR_sigaltstack:
+		current->mosix.pass_regs |= BIT_OF_REGISTER(esp);
+		break;
+	case __NR_execve:
+		current->mosix.pass_regs |= BIT_OF_REGISTER(edx);
+		break;
+	case __NR_sigsuspend:
+	case __NR_rt_sigsuspend:
+		current->mosix.pass_regs |= BIT_OF_REGISTER(orig_eax) |
+			BIT_OF_REGISTER(eax) | BIT_OF_REGISTER(eip);
+		break;
+	case __NR_sigreturn:
+	case __NR_rt_sigreturn:
+		current->mosix.pass_regs = ALL_REGISTERS;
+		break;
+	}
+	p = construct_ucache_envelope(&l, &data_from_user, &s, &tofree);
+	bump_syscalls();
+	if(p)
+		bump_copyin(l);
+	/* Cannot use "remote_request" here, because we MUST free "tofree" */
+	error = comm_send(REM_SYSCALL, &s, sizeof(s), p, l, data_from_user);
+	if(tofree)
+		kfree(tofree);
+	if(error || remote_wait(REM_SYSCALL|REPLY, &head, &rhlen))
+		remote_disappear();
+	memcpy(&r, head, sizeof(r));
+	comm_free(head);
+	absorb_deptime(r.deputytime);
+	remote_unpack_read_cache_data(&r);
+	return(r.ret);
+}
+
+void
+mosix_remote_syscall_trace(void)
+{
+	struct rusage r;
+
+	remote_fill_rusage(&r, 0);
+	if(remote_request(REM_SYSCALL_TRACE, &r, sizeof(r), NULL, 0, 0,
+								NULL, 0))
+		remote_disappear();
+	bump_syscalls();	/* no accurate numbers, but it costs! */
+	wait_for_permission_to_continue();
+}
+
+int
+remote_readpage(struct file *fp, struct page *page)
+{
+	int error;
+	char *buffer = kmap(page);
+	struct bring_page_h b;
+	struct page_ret_h r;
+	int dpagein = (current->mosix.dflags & DPAGEIN) ^ DPAGEIN;
+	register struct task_struct *p = current;
+
+	if(!PageLocked(page))
+		PAGE_BUG(page);
+	b.fp = home_file(fp);
+	b.offset = page->index << PAGE_CACHE_SHIFT;
+	b.nopage = fp->f_dentry->d_inode->u.remote_i.nopage;
+	if(p->mosix.rfreepages > 0)
+		p->mosix.rfreepages--;
+	else
+		bump_demandpages();
+	if(p->mosix.rpagecredit > 0)
+		p->mosix.rpagecredit--;
+	else
+	{
+		spin_lock_irq(&runqueue_lock);
+		p->mosix.dflags |= dpagein;
+		spin_unlock_irq(&runqueue_lock);
+	}
+	if(!b.nopage)	/* home rebooted, we should be dead anyway */
+		error = -EIO;
+	else if(!(error = remote_request(REM_PAGE, &b, sizeof(b), NULL, 0, 0,
+		(void **)&r, -sizeof(r))))
+		error = r.ret;
+	if(!error)
+		error = comm_copydata(buffer, PAGE_SIZE, 0);
+	else if(error == -EFBIG)
+	{
+		memset(buffer, 0, PAGE_SIZE);
+		error = 0;
+	}
+	if(error)
+	{
+		ClearPageUptodate(page);
+		SetPageError(page);
+	}
+	else
+		SetPageUptodate(page);
+	UnlockPage(page);
+	kunmap(page);
+	spin_lock_irq(&runqueue_lock);
+	p->mosix.dflags &= ~dpagein;
+	spin_unlock_irq(&runqueue_lock);
+	absorb_deptime(r.deputytime);
+	return(error);
+}
+
+u64
+mosix_remote_tsc(void)
+{
+	u64 r;
+
+	if(remote_request(REM_GETTSC, NULL, 0, NULL, 0, 0,
+						(void **)&r, -sizeof(r)))
+		force_sig(SIGSEGV, current);
+	bump_syscalls();
+	return(r);
+}
+
+int
+remote_setup_frame(struct setupframe_parameters_h *s)
+{
+	struct k_sigaction ka;
+	extern void setup_frame(int, struct k_sigaction *,
+						sigset_t *, struct pt_regs *);
+	extern void setup_rt_frame(int, struct k_sigaction *, siginfo_t *,
+						sigset_t *, struct pt_regs *);
+
+	ka.sa.sa_flags = s->flags;
+	ka.sa.sa_handler = s->handler;
+	ka.sa.sa_restorer = s->restorer;
+	current->sas_ss_sp = s->ss_sp;
+	current->sas_ss_size = s->ss_size;
+	if(s->flags & SA_SIGINFO)
+		setup_rt_frame(s->sig, &ka, &s->info, &s->set, mos_to_regs(&current->mosix));
+	else
+		setup_frame(s->sig, &ka, &s->set, mos_to_regs(&current->mosix));
+	comm_free(s);
+	return(comm_send(DEP_SETUPFRAME|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_nice(long *n)
+{
+	current->nice = *n;
+	comm_free(n);
+	return(comm_send(DEP_NICE|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+void
+remote_do_updinfo(struct disclosure_h *info)
+{
+	unsigned int i, j;
+	struct task_struct *p = current;
+
+	p->mosix.disclosure = info->disclosure;
+	p->uid = info->uid;
+	p->gid = info->gid;
+	p->mosix.depinfo.pgrp = info->pgrp;
+	p->mosix.depinfo.session = info->session;
+	p->mosix.depinfo.tgid = info->tgid; 
+	for(i = j = 0 ; j < 16 ; i++)
+		switch(info->comm[i])
+		{
+		case '\0':
+			p->mosix.depinfo.comm[j] = '\0';
+			return;
+		case '\n':
+			if(j == 15)
+				p->mosix.depinfo.comm[j] = '\0';
+			p->mosix.depinfo.comm[j++] = '\\';
+			p->mosix.depinfo.comm[j++] = 'n';
+			break;
+		default:
+			p->mosix.depinfo.comm[j++] = info->comm[i];
+		}
+}
+
+int
+remote_updinfo(struct disclosure_h *info)
+{
+	remote_do_updinfo(info);
+	comm_free(info);
+	return(comm_send(DEP_INFO|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_caps(kernel_cap_t *caps)
+{
+	kernel_cap_t effective = *caps & REMOTE_CAPS;
+
+	comm_free(caps);
+	current->cap_effective &= ~REMOTE_CAPS;
+	current->cap_effective |= effective;
+	return(comm_send(DEP_CAPS|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_depcosts(void *info)
+{
+	memcpy((caddr_t)current->mosix.depcost, info,
+		sizeof(current->mosix.depcost));
+	comm_free(info);
+	return(comm_send(DEP_OPCOSTS|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_restore_sigcontext(struct sigcontext **frame)
+{
+	extern int restore_sigcontext(struct pt_regs *, struct sigcontext *,
+									int *);
+	struct restore_sigcontext_ret_h r;
+
+	r.result = restore_sigcontext(mos_to_regs(&current->mosix), *frame,
+									&r.eax);
+
+	comm_free(frame);
+	current->mosix.pass_regs |= BIT_OF_REGISTER(esp);
+	return(comm_send(DEP_RESTORESIGCONTEXT|REPLY, &r, sizeof(r),
+								NULL, 0, 0));
+}
+
+/*
+ * the following routine, if called within process-migration,
+ * returns the fact of an error, rather than sends back a reply:
+ */
+int
+remote_mmap(struct mmap_parameters_h *m, int inmig)
+{
+	unsigned long result;
+	struct file *rf;
+	unsigned long prot, flags;
+	extern asmlinkage long sys_madvise(unsigned long, size_t, int);
+
+	if(m->fp)
+	{
+		if(!(rf = get_remote_file(m->origin, m->fp, m->dp, m->uniq,
+							m->isize, m->nopage)))
+		{
+			result = -EDOITATHOME;
+			goto err;
+		}
+	}
+	else
+		rf = NULL;
+	/* unconvert prot+flags: */
+	prot = 0;
+	flags = MAP_PRIVATE;
+	if(m->fixed)
+		flags |= MAP_FIXED;
+	if(m->flags & VM_GROWSDOWN)
+		flags |= MAP_GROWSDOWN;
+	if(m->flags & VM_DENYWRITE)
+		flags |= MAP_DENYWRITE;
+	if(m->flags & VM_EXECUTABLE)
+		flags |= MAP_EXECUTABLE;
+	if(m->flags & VM_READ)
+		prot |= VM_READ;
+	if(m->flags & VM_WRITE)
+		prot |= VM_WRITE;
+	if(m->flags & VM_EXEC)
+		prot |= VM_EXEC;
+	if(m->flags & VM_MAYSHARE)
+		current->mosix.dirty_bits |= MMAP_MAYSHARE;
+	result = do_mmap_pgoff(rf, m->addr, m->len, prot, flags, m->pgoff);
+	if(m->flags & VM_MAYSHARE)
+		current->mosix.dirty_bits &= ~MMAP_MAYSHARE;
+	if(rf && !IS_ERR((const void *)result))
+	{
+		int pages = (m->len + PAGE_SIZE - 1) / PAGE_SIZE;
+
+		current->mosix.rpagecredit += pages;
+		if(current->mosix.dflags & DINCOMING)
+			current->mosix.rfreepages += pages;
+	}
+	if(m->flags & VM_READHINTMASK)
+		sys_madvise(m->addr, m->len, (m->flags & VM_SEQ_READ) ?
+						MADV_RANDOM : MADV_SEQUENTIAL);
+	err:
+	if(rf)
+		fput(rf);
+	if(inmig)
+		return(IS_ERR((const void *)result));
+	comm_free(m);
+	return(comm_send(DEP_MMAP|REPLY, &result, sizeof(result), NULL, 0, 0));
+}
+
+int
+remote_brk(struct brk_parameters_h *b)
+{
+	long result = do_brk(b->addr, b->len);
+
+	comm_free(b);
+	return(comm_send(DEP_BRK|REPLY, &result, sizeof(result), NULL, 0, 0));
+}
+
+int
+remote_munmap(struct munmap_parameters_h *m)
+{
+	int result = do_munmap(current->mm, m->addr, m->len);
+
+	comm_free(m);
+	return(comm_send(DEP_MUNMAP|REPLY, &result, sizeof(result), NULL, 0, 0));
+}
+
+int
+remote_mprotect(struct mprotect_parameters_h *m)
+{
+	extern asmlinkage int sys_mprotect(unsigned long,size_t,unsigned long);
+	int result = sys_mprotect(m->addr, m->len, m->prot);
+
+	comm_free(m);
+	return(comm_send(DEP_MPROTECT|REPLY, &result, sizeof(result), NULL, 0, 0));
+}
+
+int
+remote_copy_from_user(struct user_copy_h *u)
+{
+	int result;
+	void *to;
+	int direct = ucache_ok((unsigned long)u->addr, (unsigned long)u->size,
+								VM_READ);
+
+	if(direct)
+	{
+		result = 0;
+		to = u->addr;
+	}
+	else
+	{
+		if(!(to = kmalloc(u->size, GFP_KERNEL)))
+			result = u->size;
+		else if(u->verify)
+			result = copy_from_user(to, u->addr, u->size);
+		else
+			result = __copy_from_user(to, u->addr, u->size);
+	}
+	result = comm_send(DEP_COPY_FROM_USER|REPLY, &result, sizeof(result),
+		(result == u->size) ? NULL : to, u->size - result, direct);
+	bump_copyin(u->size);
+	comm_free(u);
+	if(!direct && to)
+		kfree(to);
+	return(result);
+}
+
+int
+remote_copy_to_user(struct user_copy_h *u)
+{
+	int result;
+
+	if(u->verify && !access_ok(VERIFY_WRITE, u->addr, u->size))
+		result = u->size;
+	else
+	{
+		result = comm_copydata(u->addr, u->size, 1);
+		if(result < 0)
+			result = u->size;
+	}
+	if(result)
+		comm_flushdata(COMM_ALLDATA);
+	bump_copyout(u->size);
+	comm_free(u);
+	return(comm_send(DEP_COPY_TO_USER|REPLY, &result, sizeof(result),
+		NULL, 0, 0));
+}
+
+int
+remote_data_to_user(struct user_copy_h *u)
+{
+	int error = (comm_copydata(u->addr, u->size, 1) != 0);
+
+	bump_copyout(u->size);
+	comm_free(u);
+	if(error)
+		comm_flushdata(COMM_ALLDATA);
+	/* No Reply! */
+	return(error);
+}
+
+int
+remote_clear_user(struct user_copy_h *u)
+{
+	int result = u->verify ? clear_user(u->addr, u->size) :
+				__clear_user(u->addr, u->size);
+
+	comm_free(u);
+	return(comm_send(DEP_CLEAR_USER|REPLY, &result, sizeof(result),
+		NULL, 0, 0));
+}
+
+int
+remote_strncpy_from_user(struct user_copy_h *u)
+{
+	int result;
+	void *to = kmalloc(u->size, GFP_KERNEL);
+
+	if(!to)
+		result = -ENOMEM;
+	else if(u->verify)
+		result = strncpy_from_user(to, u->addr, u->size);
+	else
+		result = __strncpy_from_user(to, u->addr, u->size);
+	comm_free(u);
+	result = comm_send(DEP_STRNCPY_FROM_USER|REPLY, &result, sizeof(result),
+		result > 0 ? to : NULL, result > 0 ? result : 0, 0);
+	if(to)
+		kfree(to);
+	if(result > 0)
+		bump_copyin(result);
+	return(result);
+}
+
+int
+remote_strnlen_user(struct strnlen_user_h *u)
+{
+	long result;
+	char c;
+
+	if(u->len)
+		result = strnlen_user(u->addr, u->len);
+	else  /* "strnlen_user" does not handle "0 bytes remaining" correctly */
+		result = !copy_from_user(&c, u->addr, 1);
+	comm_free(u);
+	return(comm_send(DEP_STRNLEN_USER|REPLY, &result, sizeof(result),
+		NULL, 0, 0));
+}
+
+int
+remote_verify_write(struct user_copy_h *u)
+{
+	int result = __verify_write(u->addr, u->size);
+
+	comm_free(u);
+	return(comm_send(DEP_VERIFY_WRITE|REPLY, &result, sizeof(result),
+		NULL, 0, 0));
+}
+
+int
+remote_csum_copy_from_user(struct user_csum_copy_h *u)
+{
+	struct user_csum_copy_ret_h r;
+	void *to = kmalloc(u->len, GFP_KERNEL);
+	int result;
+
+	r.error = 0;
+	if(!to)
+		r.error = -ENOMEM;
+	else
+		r.newsum = csum_partial_copy_from_user(u->addr, to, u->len,
+			u->sum, &r.error);
+	result = comm_send(DEP_CSUM_COPY_FROM_USER|REPLY, &r, sizeof(r),
+		r.error ? NULL : to, r.error ? 0 : u->len, 0);
+	bump_copyin(u->len);
+	comm_free(u);
+	if(to)
+		kfree(to);
+	return(result);
+}
+
+int
+remote_rlimit(struct rlimit_h *l)
+{
+	current->rlim[l->resource] = l->limit;
+	comm_free(l);
+	return(comm_send(DEP_RLIMIT|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_urgent(void)
+{
+	register struct task_struct *p = current;
+	int w;
+
+	spin_lock_irq(&runqueue_lock);
+	p->mosix.dflags &= ~DSENTURGENT;
+	spin_unlock_irq(&runqueue_lock);
+	spin_lock_irq(&whereto_lock);
+	w = p->mosix.whereto;
+	p->mosix.whereto = 0;
+	spin_unlock_irq(&whereto_lock);
+#ifdef CONFIG_MOSIX_DFSA
+	if(process_told(p, DREQ_DFSASYNC))
+	{
+		remote_clear_dfsa();
+		clear_dfsasync();
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(comm_send(DEP_TAKEURGENT|REPLY, &w, sizeof(w), NULL, 0, 0));
+}
+
+int
+remote_rusage(int *finalp)
+{
+	struct rusage r;
+
+	/* "*finalp" just means that calculation of "exit_mem" is required */
+	remote_fill_rusage(&r, *finalp);
+	comm_free(finalp);
+	return(comm_send(DEP_RUSAGE|REPLY, &r, sizeof(r), NULL, 0, 0));
+}
+
+void
+remote_fill_rusage(struct rusage *r, int final)
+{
+	register struct task_struct *p = current;
+	struct vm_area_struct *vma;
+	clock_t ut, st;
+
+	cli();
+	ut = p->times.tms_utime;
+	st = p->times.tms_stime;
+	p->times.tms_utime = 0;
+	p->times.tms_stime = 0;
+	sti();
+	r->ru_utime.tv_sec = CT_TO_SECS(ut);
+	r->ru_utime.tv_usec = CT_TO_USECS(ut);
+	p->mosix.passedtime += ut;
+	p->mosix.uttime += ut;
+	r->ru_stime.tv_sec = CT_TO_SECS(st);
+	r->ru_stime.tv_usec = CT_TO_USECS(st);
+	p->mosix.passedtime += st;
+	r->ru_minflt = p->min_flt;
+	p->min_flt = 0;
+	r->ru_majflt = p->maj_flt;
+	p->maj_flt = 0;
+	r->ru_nswap = p->nswap;
+	p->nswap = 0;
+	if(final)
+	{
+		r->ru_maxrss = 0;
+		if (current->mm)
+		for(vma = current->mm->mmap ; vma ; vma = vma->vm_next)
+			r->ru_maxrss += vma->vm_end - vma->vm_start;
+	}
+}
+
+int
+remote_execve_counts(struct execve_counts_h *e)
+{
+	struct execve_counts_ret_h r;
+
+	execve_remote_counts(e->argp, e->envp, &r.argc, &r.envc);
+	comm_free(e);
+	return(comm_send(DEP_EXECVE_COUNTS|REPLY, &r, sizeof(r), NULL, 0, 0));
+}
+
+int
+remote_bring_strings(struct execve_bring_strings_h *b)
+{
+	struct linux_binprm bprm;
+	struct execve_bring_strings_ret_h r;
+	struct execve_more_strings_h m;
+	unsigned int i;
+	int err = 0;
+	char *kaddr;
+
+	bprm.p = b->p;
+	bprm.filename = b->filename;
+	bprm.envc = b->envc;
+	bprm.argc = b->argc;
+	memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
+	current->mosix.inexec = &bprm;
+	r.result = execve_remote_bring_strings(&bprm, b->envp, b->argp);
+	r.p = bprm.p;
+	r.exec = bprm.exec;
+	comm_free(b);
+	if(r.result == 0)
+	{
+		for(i = r.p / PAGE_SIZE ; i < MAX_ARG_PAGES - 1 ; i++)
+		if(bprm.page[i])
+		{
+			m.pgno = i + 1;
+			m.len = (i + 1) * PAGE_SIZE - r.p;
+			if(m.len > PAGE_SIZE)
+				m.len = PAGE_SIZE;
+			if(!err)
+			{
+				kaddr = kmap(bprm.page[i]);
+				err = comm_send(REM_MORESTRINGS, &m, sizeof(m),
+				      kaddr + (PAGE_SIZE - m.len), m.len, 0);
+				kunmap(bprm.page[i]);
+			}
+			__free_page(bprm.page[i]);
+			bprm.page[i] = 0;
+		}
+	}
+	if(!err)
+	{
+		if(r.result == 0 && bprm.page[MAX_ARG_PAGES-1])
+		{
+			r.pgno = MAX_ARG_PAGES;
+			r.len = MAX_ARG_PAGES * PAGE_SIZE - r.p;
+			if(r.len > PAGE_SIZE)
+				r.len = PAGE_SIZE;
+			kaddr = kmap(bprm.page[MAX_ARG_PAGES-1]);
+		}
+		else
+		{
+			r.pgno = 0;
+			kaddr = NULL;	/* only to pacify the compiler */
+		}
+		err = comm_send(DEP_BRING_STRINGS|REPLY, &r, sizeof(r), r.pgno ?
+			(kaddr + (PAGE_SIZE-r.len)) : 0, r.pgno ? r.len : 0, 0);
+		if(r.pgno)
+			kunmap(bprm.page[MAX_ARG_PAGES-1]);
+	}
+	for(i = 0 ; i < MAX_ARG_PAGES ; i++)
+	if(bprm.page[i])
+		__free_page(bprm.page[i]);
+	current->mosix.inexec = NULL;
+	return(err);
+}
+
+int
+remote_setup_args(struct execve_setup_args_h *e)
+{
+	int i;
+	struct task_struct *p = current;
+	register struct linux_binprm *bprm = p->mosix.inexec;
+	struct execve_setup_args_ret_h r;
+	int err = 0;
+	struct page *page;
+	char *kaddr;
+
+	if(e->create)
+	{
+		if((bprm = p->mosix.inexec = kmalloc(sizeof(*bprm),GFP_KERNEL)))
+			memset(bprm->page, 0,
+					MAX_ARG_PAGES * sizeof(bprm->page[0]));
+	}
+	if(bprm && e->pgno)
+	{
+		if(!(page = alloc_page(GFP_HIGHUSER)))
+		{
+			comm_flushdata(e->len);
+			goto fail;
+		}
+		bprm->page[e->pgno-1] = page;
+		kaddr = kmap(page);
+		i = comm_copydata(kaddr + (PAGE_SIZE - e->len), e->len, 0);
+		if(e->len < PAGE_SIZE)
+			memset(kaddr, 0, PAGE_SIZE - e->len);
+		kunmap(page);
+		if(i)
+		{
+			fail:
+			for(i = 0 ; i < MAX_ARG_PAGES ; i++)
+			if(bprm->page[i])
+				__free_page(bprm->page[i]);
+			kfree(bprm);
+			bprm = p->mosix.inexec = NULL;
+		}
+	}
+	else if(e->pgno)
+		comm_flushdata(e->len);
+	if(e->how == SETUP_ARGS_NOTYET)
+		goto out;
+	if(!p->mosix.inexec)	/* one of the allocations failed */
+		r.reply = -ENOMEM;
+	else
+	{
+		if(e->how == SETUP_ARGS_AS_ELF)
+		{
+			p->mm->start_data = 0;
+			p->mm->end_data = 0;
+			p->mm->end_code = 0;
+			p->mm->rss = 0;
+			p->mm->mmap = NULL;
+		}
+		bprm->p = e->p;
+		bprm->loader = e->loader;
+		bprm->exec = e->exec;
+		bprm->argc = e->argc;
+		bprm->envc = e->envc;
+		p->personality = e->personality;
+		r.reply = setup_arg_pages(bprm);
+		if(e->how == SETUP_ARGS_AS_AOUT)
+		{
+			if(r.reply == 0)
+				p->mm->start_stack = (unsigned long)
+				create_aout_tables((char *)bprm->p, bprm);
+		}
+		else
+			p->mm->start_stack = bprm->p;
+		r.p = bprm->p;
+		r.loader = bprm->loader;
+		r.exec = bprm->exec;
+		if(r.reply == 0)
+			p->ptrace &= ~PT_DTRACE;
+		r.start_stack = p->mm->start_stack;
+	}
+	p->mosix.pass_regs |= BIT_OF_REGISTER(xds)|BIT_OF_REGISTER(xes)|
+		BIT_OF_REGISTER(xss)|BIT_OF_REGISTER(xcs)|BIT_OF_REGISTER(eip)|
+		BIT_OF_REGISTER(esp);
+	err = comm_send(DEP_SETUP_ARGS|REPLY, &r, sizeof(r), NULL, 0, 0);
+	mosix_decay_exec();
+	out:
+	if(e->how != SETUP_ARGS_NOTYET && bprm)
+	{
+		kfree(bprm);
+		p->mosix.inexec = NULL;
+	}
+	comm_free(e);
+	return(err);
+}
+
+int
+remote_exec_mmap(void)
+{
+	int r;
+
+	if(!(r = exec_mmap()))
+	{
+		flush_thread();
+		mosix_clear_statistics();
+		current->mosix.rpagecredit = 0;
+		current->mosix.rfreepages = 0;
+		current->sas_ss_sp = current->sas_ss_size = 0;
+	}
+	return(comm_send(DEP_EXEC_MMAP|REPLY, &r, sizeof(r), NULL, 0, 0));
+}
+
+int
+remote_dump_thread(void)
+{
+	extern void dump_thread(struct pt_regs *, struct user *);
+	struct user u;
+	/* (size == 286 bytes -- should be OK while allocation can fail) */
+
+	dump_thread(mos_to_regs(&current->mosix), &u);
+	return(comm_send(DEP_DUMP_THREAD|REPLY, &u, sizeof(u), NULL, 0, 0));
+}
+
+int
+remote_init_aout_mm(struct exec *ex)
+{
+	aout_remote_init_mm(ex);
+	comm_free(ex);
+	return(comm_send(DEP_INIT_AOUT_MM|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_elf_setup(struct execve_elf_setup_h *e)
+{
+	unsigned long r;
+	struct elfhdr h;
+
+	h.e_phoff = e->exec_e_phoff;
+	h.e_phnum = e->exec_e_phnum;
+	h.e_entry = e->exec_e_entry;
+	r = elf_remote_setup(e->p, e->argc, e->envc, e->hasexec ? &h : NULL,
+		e->addr, e->load_bias, e->interp_load_addr, e->ibcs,
+		e->add_arg_start, e->elf_brk, e->end_code,
+		e->start_code, e->start_data, e->end_data, e->elf_bss,
+		e->personality, &e->extras);
+	comm_free(e);
+	return(comm_send(DEP_ELF_SETUP|REPLY, &r, sizeof(r), NULL, 0, 0));
+}
+
+int
+remote_fix_elf_aout(struct execve_fix_elf_aout_h *f)
+{
+	current->mm->brk = f->bss +
+		(current->mm->end_data = f->data +
+			(current->mm->end_code = f->text));
+	comm_free(f);
+	return(comm_send(DEP_FIX_ELF_AOUT|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_list_vmas(void)
+{
+	register int i;
+	register struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	struct vmalist *lis = NULL;
+	struct list_vmas_ret_h r;
+	int error;
+
+	if(!mm)
+		mosix_panic("remote_list_vmas: no mm");
+	r.argstart = current->mm->arg_start;
+	r.argend = current->mm->arg_end;
+	for(i = 0 , vma = mm->mmap ; vma ; vma = vma->vm_next)
+		i++;
+	if(i && !(lis = kmalloc(i * sizeof(struct vmalist), GFP_KERNEL)))
+		i = -1;
+	if((r.n = i) <= 0)
+		return(comm_send(DEP_LIST_VMAS|REPLY, &r, sizeof(r), NULL,0,0));
+	for(i = 0 , vma = mm->mmap ; vma && i < r.n ; vma = vma->vm_next , i++)
+	{
+		lis[i].vmstart = vma->vm_start;
+		lis[i].vmend = vma->vm_end;
+		lis[i].vmflags = vma->vm_flags;
+		lis[i].maydump = elf_maydump(vma);
+	}
+	error = comm_send(DEP_LIST_VMAS|REPLY, &r, sizeof(r),
+		lis, i * sizeof(struct vmalist), 0);
+	kfree(lis);
+	return(error);
+}
+
+int
+remote_fork(struct fork_h *f)
+{
+	struct mosix_task *me = &current->mosix;
+	struct fork_h lf = *f;
+	mosix_addr a;
+	mosix_link *sonsock;
+	int pid;
+	register struct task_struct *son;
+	int err;
+	unsigned int tries;
+	int done, ret;
+
+	comm_free(f);
+	mosix_obtain_registers(ALL_REGISTERS & ~BIT_OF_REGISTER(eax));
+	if(lf.do_forkmigrate)
+		mosix_forkmigrate();	/* may not return */
+	ret = -EAGAIN;
+	for(tries = 0 ; ; tries++)
+	{
+		if(tries >= 100 || !(sonsock =
+				comm_open(COMM_ACCEPT, &a, comm_remote_timo)))
+			goto out;
+		if((err = remote_request(REM_CONNECT_TO, &a, sizeof(a),
+				NULL, 0, 0, (void **)&done, -sizeof(done))))
+		{
+			comm_close(sonsock);
+			return(err);
+		}
+		if(done)
+			break;
+		comm_close(sonsock);
+	}
+	me->sonpid = lf.pid;
+	me->sontgid = lf.tgid;
+	if((pid = do_fork(SIGCHLD|CLONE_SIGHAND
+#ifndef CONFIG_MOSIX_DFSA
+		|CLONE_FS|CLONE_FILES
+#endif /* CONFIG_MOSIX_DFSA */
+		, lf.usp, mos_to_regs(me), 0)) < 0)
+	{
+		comm_close(sonsock);
+		goto out;
+	}
+	read_lock(&tasklist_lock);
+	for_each_task(son)
+	if(son->pid == pid)
+		break;
+	read_unlock(&tasklist_lock);
+	comm_use(son, sonsock);
+	wake_up(mos_to_waitp(&son->mosix));
+	ret = 0;
+	out:
+	return(comm_send(DEP_PLEASE_FORK|REPLY, &ret, sizeof(ret), NULL, 0, 0));
+}
+
+int
+remote_personality(unsigned long *pp)
+{
+	int res;
+	unsigned long personality = *pp;
+
+	comm_free(pp);
+	set_personality(personality);
+	res = (current->personality == personality) ? 0 : -1;
+	return(comm_send(DEP_PERSONALITY|REPLY, &res, sizeof(res), NULL, 0, 0));
+}
+
+int
+remote_bring_me_regs(unsigned long *bring)
+{
+	struct mosix_task *m = &current->mosix;
+
+	m->pass_regs |= *bring & ~m->deputy_regs;
+	comm_free(bring);
+	return(comm_send(DEP_BRING_ME_REGS|REPLY, NULL, 0, NULL, 0, 0));
+}
+
+int
+remote_dump_fpu(void)
+{
+	extern int dump_fpu (struct pt_regs *, struct user_i387_struct *);
+	struct user_i387_struct f;
+	int r = dump_fpu(mos_to_regs(&current->mosix), &f);
+
+	return(comm_send(DEP_DUMP_FPU|REPLY, &r, sizeof(r),
+		r ? &f : NULL, r ? sizeof(f) : 0, 0));
+}
+
+int
+remote_come_back(void *head)
+{
+	struct mosix_task *m = &current->mosix;
+	int reason = *((int *) head);
+	int reply;
+	int omigpages;
+
+	comm_free(head);
+	if(!(omigpages = current->mosix.migpages))
+		m->migpages = count_migrating_pages();
+	if (mig_send_request(reason, FROM_REMOTE))
+	{
+		m->migpages = omigpages;
+		return (-EDIST);
+	}
+	spin_lock_irq(&runqueue_lock);
+	m->dflags |= DPASSING;
+	spin_unlock_irq(&runqueue_lock);
+	
+	release_migrations(m->deppe);
+	reply = mig_do_send();
+	m->migpages = omigpages;
+	spin_lock_irq(&runqueue_lock);
+	m->dflags &= ~DPASSING;
+	spin_unlock_irq(&runqueue_lock);
+	return(reply);
+}
+
+int
+remote_goto_remote(void *head)
+{
+	struct task_struct *p = current;
+	mosix_link *remsock = NULL;
+	mosix_link *depsock;
+	struct please_migrate_h *pm = (struct please_migrate_h *)head;
+	int reason = pm->reason;
+	int status = 1;
+	int error;
+	int whereto = pm->to;
+	int omigpages;
+
+	spin_lock_irq(&runqueue_lock);
+	p->mosix.dflags |= DPASSING;
+	spin_unlock_irq(&runqueue_lock);
+	remsock = comm_open(COMM_TOADDR, &pm->ma, comm_reconn_timo);
+	comm_free(head);
+	if (!remsock)
+		goto reply;
+
+	depsock = comm_use(p, remsock);
+	if(!(omigpages = p->mosix.migpages))
+		current->mosix.migpages = count_migrating_pages();
+	if ((error = mig_send_request(reason, FROM_REMOTE)))
+		goto cont;
+
+	release_migrations(whereto);
+	if (!mig_do_send())
+		status = 0;
+cont:
+	p->mosix.migpages = omigpages;
+	comm_use(p, depsock);
+	comm_close(remsock);
+
+reply:
+	error = comm_send(DEP_PLEASE_MIGRATE | REPLY, (void *)&status,
+						sizeof(status), NULL, 0, 0);
+	if (!(status || error))
+		remote_disappear();
+	spin_lock_irq(&runqueue_lock);
+	p->mosix.dflags &= ~DPASSING;
+	spin_unlock_irq(&runqueue_lock);
+	return (error);
+}
+
+int
+remote_consider(int *reasonp)
+{
+	int reason = *reasonp;
+
+	comm_free(reasonp);
+	consider(reason, NULL);
+	return(0);
+}
+
+int
+remote_psinfo(void)
+{
+	int n;
+	char *p = fill_common_ps_info(&n);
+	int err;
+
+	if(!p)
+		return(comm_send(DEP_PSINFO|REPLY, &n, sizeof(n), NULL, 0, 0));
+	err = comm_send(DEP_PSINFO|REPLY, &n, sizeof(n), p, n, 0);
+	kfree(p);
+	return(err);
+}
+
+#ifdef CONFIG_MOSIX_DFSA
+int
+remote_receive_dfsachanges(int *head)
+{
+	int len = *head;
+	char *changes;
+	int error = 0;
+
+	comm_free(head);
+	if((changes = kmalloc(len, GFP_KERNEL)))
+	{
+		if((error = comm_copydata(changes, len, 0)))
+		{
+			remote_clear_dfsa();
+			kfree(changes);
+		}
+		else
+			remote_unpack_dfsa_changes(changes);
+	}
+	else
+		remote_clear_dfsa();
+	
+	if(!error)
+		error = comm_send(DEP_DFSA_CHANGES|REPLY, NULL, 0, NULL, 0, 0);
+	return(error);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
+void
+absorb_deptime(unsigned long ticks)
+{
+	register struct task_struct *p = current;
+	unsigned long it_prof = p->it_prof_value;
+
+	if(it_prof)
+	{
+		cli();
+		if(it_prof > ticks)
+		{
+			p->it_prof_value -= ticks;
+			sti();
+		}
+		else
+		{
+			p->it_prof_value = p->it_prof_incr;
+			sti();
+			send_sig(SIGPROF, p, 1);
+		}
+	}
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/rinode.c linux-openmosix/hpc/rinode.c
--- linux/hpc/rinode.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/rinode.c	2003-06-14 07:18:11.000000000 +0200
@@ -0,0 +1,622 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ *  Author(s): Amnon Shiloh, Moshe Bar
+ */
+#include <linux/sched.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <linux/hpc.h>
+#include <linux/smp_lock.h>
+#include <linux/file.h>
+#include <linux/dcache.h>
+#include <linux/slab.h>
+#include <hpc/routines.h>
+#include <hpc/debug.h>
+
+/* REMOTE section: */
+
+spinlock_t rinode_list_lock = SPIN_LOCK_UNLOCKED;
+
+
+#define	next_entry(dp)	((struct dentry *)(dp)->d_fsdata)
+
+static struct dentry *rinode_list = NULL;
+
+static int remote_dentry_delete(struct dentry *);
+static void remote_dentry_iput(struct dentry *, struct inode *);
+static int mosix_remote_file_mmap(struct file *, struct vm_area_struct *);
+
+extern struct super_block bad_super_block;
+
+static struct dentry_operations remote_dentry_ops =
+{
+	.d_delete = remote_dentry_delete,
+	.d_iput = remote_dentry_iput
+};
+
+static struct file_operations remote_file_operations =
+{
+	.mmap = mosix_remote_file_mmap,
+};
+
+struct address_space_operations remote_aops =
+{
+	.readpage = remote_readpage,
+};
+
+void
+invalidate_old_remote_pages(struct inode *ip)
+{
+	down(&ip->i_sem);
+	/* we prefer "invalidate_inode_pages",
+	   but it does not work on locked pages */
+	truncate_inode_pages(ip->i_mapping, 0);
+	up(&ip->i_sem);
+}
+
+struct file *
+get_remote_file(int origin, struct file *fpr, struct dentry *dpr, uint64_t uniq, off_t isize,
+								nopage_t nopage)
+{
+	register struct file *f;
+	register struct dentry *d, *d2;
+	register struct inode *ip, *i2;
+	struct vm_area_struct *vma;
+	int cng;
+	struct dentry *to_dput = NULL;
+	struct inode *to_iput = NULL;
+
+	for(vma = current->mm->mmap ; vma ; vma = vma->vm_next)
+	if((f = vma->vm_file) && home_file(f) == fpr)
+	{
+		ip = f->f_dentry->d_inode;
+		if(ip->u.remote_i.origin == origin && ip->u.remote_i.dp == dpr
+			&& ip->u.remote_i.unique == uniq && ip->i_size == isize
+			&& ip->u.remote_i.nopage == nopage)
+		{
+			get_file(f);
+			return(f);
+		}
+	}
+	if(!(f = get_empty_filp()))
+		return(NULL);
+	spin_lock(&dcache_lock);
+	spin_lock(&rinode_list_lock);
+	for(d = rinode_list ; d ; d = next_entry(d))
+	{
+		ip = d->d_inode;
+		if(ip->u.remote_i.origin == origin && ip->u.remote_i.dp == dpr)
+		{
+			join_in:
+			cng = (ip->u.remote_i.unique != uniq) ||
+				(ip->u.remote_i.nopage != nopage) ||
+				(isize < ip->i_size);
+			ip->i_size = isize;
+			if(cng)
+			{
+				ip->u.remote_i.unique = uniq;
+				ip->u.remote_i.nopage = nopage;
+			}
+			dget(d);
+			spin_unlock(&rinode_list_lock);
+			spin_unlock(&dcache_lock);
+			if(to_iput)
+				iput(to_iput);
+			if(to_dput)
+				dput(to_dput);
+			if(cng)
+				invalidate_old_remote_pages(ip);
+			f->f_dentry = d;
+			f->f_op = &remote_file_operations;
+			f->f_mode = FMODE_READ;
+			home_file(f) = fpr;
+			return(f);
+		}
+	}
+	spin_unlock(&rinode_list_lock);
+	spin_unlock(&dcache_lock);
+	if(!(ip = new_inode(&bad_super_block)))
+	{
+		put_filp(f);
+		return(NULL);
+	}
+	ip->i_mode = S_IFREG;
+	ip->u.remote_i.origin = origin;
+	ip->u.remote_i.dp = dpr;
+	ip->u.remote_i.unique = uniq;
+	ip->u.remote_i.nopage = nopage;
+	ip->i_size = isize;
+	ip->i_fop = &remote_file_operations;
+	ip->i_mapping->a_ops = &remote_aops;
+	if(!(d = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 })))
+	{
+		put_filp(f);
+		iput(ip);
+		return(NULL);
+	}
+	d->d_parent = d;
+	/* any copy created while we slept? */
+	spin_lock(&dcache_lock);
+	spin_lock(&rinode_list_lock);
+	for(d2 = rinode_list ; d2 ; d2 = next_entry(d2))
+	{
+		i2 = d2->d_inode;
+		if(i2->u.remote_i.origin == origin && i2->u.remote_i.dp == dpr)
+		{
+			to_iput = ip;
+			to_dput = d;
+			d = d2;
+			ip = i2;
+			goto join_in;
+		}
+	}
+	d->d_op = &remote_dentry_ops;
+	d->d_inode = ip;
+	next_entry(d) = rinode_list;
+	rinode_list = d;
+	f->f_dentry = d;
+	f->f_op = &remote_file_operations;
+	f->f_mode = 1;
+	home_file(f) = fpr;
+	spin_unlock(&rinode_list_lock);
+	spin_unlock(&dcache_lock);
+	return(f);
+}
+
+/*
+ * called by fput(fd) ==> dput(d)
+ */
+
+static int
+remote_dentry_delete(struct dentry *del)
+{
+	register struct dentry *dp;
+
+	spin_lock(&rinode_list_lock);
+	if(del == rinode_list)
+		rinode_list = next_entry(del);
+	else
+	{
+		for(dp = rinode_list ; dp && next_entry(dp) != del ;
+							dp = next_entry(dp))
+		if(!dp)
+			panic("remote dentry not listed");
+		next_entry(dp) = next_entry(del);
+	}
+	spin_unlock(&rinode_list_lock);
+	return(1);
+}
+
+static void
+remote_dentry_iput(struct dentry *dp, struct inode *ip)
+{
+	invalidate_old_remote_pages(ip);
+	iput(ip);
+}
+
+struct vm_operations_struct rinode_mmap =
+{
+	.nopage = filemap_nopage,
+};
+
+static int
+mosix_remote_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (vma->vm_flags & VM_SHARED)
+		panic("REMOTE VM_SHARED mmap");
+	vma->vm_ops = &rinode_mmap;
+	return(0);
+}
+
+int
+remote_report_files(void)
+{
+	register struct vm_area_struct *vma, *vmb;
+	struct mm_struct *mm = current->mm;
+	struct file **fp = NULL;
+	int n = 0;
+	int result;
+
+	down_read(&mm->mmap_sem);
+	for(vma = mm->mmap ; vma ; vma = vma->vm_next)
+	if(vma->vm_file)
+	{
+		for(vmb = mm->mmap ; vmb != vma ; vmb = vmb->vm_next)
+		if(vmb->vm_file == vma->vm_file)
+			break;
+		if(vmb == vma)
+			n++;
+	}
+	up_read(&mm->mmap_sem);
+	if(n && !(fp = kmalloc(n * sizeof(struct file *), GFP_KERNEL)))
+		n = -EAGAIN;
+	else
+	{
+		down_read(&mm->mmap_sem);
+		for(n = 0 , vma = mm->mmap ; vma ; vma = vma->vm_next)
+		if(vma->vm_file)
+		{
+			for(vmb = mm->mmap ; vmb != vma ; vmb = vmb->vm_next)
+			if(vmb->vm_file == vma->vm_file)
+				break;
+			if(vmb == vma)
+				fp[n++] = home_file(vma->vm_file);
+		}
+		up_read(&mm->mmap_sem);
+	}
+	result = comm_send(DEP_LISTHOLD|REPLY, &n, sizeof(int),
+		fp, n > 0 ? n * sizeof(struct file *) : 0, 0);
+	if(n > 0)
+		kfree(fp);
+	return(result);
+}
+
+void
+rinode_flush_files(int pe)
+{
+	register struct dentry *dp;
+	register struct inode *ip;
+
+
+	loop:
+	spin_lock(&rinode_list_lock);
+	for(dp = rinode_list ; dp ; dp = next_entry(dp))
+	{
+		ip = dp->d_inode;
+		if(ip->u.remote_i.origin == pe && ip->u.remote_i.nopage)
+		{
+			ip->u.remote_i.dp = NULL;
+			/* (the pointer is no good and any process
+			 * still using this inode is doomed anyway) */
+			ip->u.remote_i.unique = 0xffffffffffffffffULL;
+			ip->u.remote_i.nopage = NULL;
+			spin_unlock(&rinode_list_lock);
+			invalidate_old_remote_pages(ip);
+			goto loop;
+		}
+	}
+	spin_unlock(&rinode_list_lock);
+}
+
+/* DEPUTY section: */
+
+#define DEFAULT_ALLOCATION	10
+
+#define	ALLOCATED_NEW		1
+#define	ALLOCATED_NEW_AND_DENY	2
+#define	ADDED_A_DENY		3
+#define	FOUND_OLD		4
+
+int
+mosix_register_a_file(struct file *fp, int denywrite)
+{
+	struct task_struct *p = current;
+	register int i, new;
+	struct held_files *nh, *oh;
+	struct mm_struct *mm;
+
+	if(!p->mosix.held_allocated)
+	{
+		if((mm = p->mm) && atomic_read(&mm->mm_realusers) > 1)
+			return(0);
+		nh = NULL;	/* COMPILER BUG -- hope it is optimized out */
+		for(i = DEFAULT_ALLOCATION ; i > 0 ; i >>= 1)
+		if((nh = (struct held_files *)
+			kmalloc(i * sizeof(struct held_files), GFP_KERNEL)))
+			break;
+		if(!nh)
+			return(-ENOMEM);
+		memset(nh, 0, i * sizeof(struct held_files));
+		task_lock(p);
+		p->mosix.held_files = nh;
+		p->mosix.held_allocated = i;
+		task_unlock(p);
+		new = 0;
+	}
+	else
+	{
+		new = -1;
+		for(i = 0 ; i < p->mosix.held_allocated ; i++)
+		if((struct file *)p->mosix.held_files[i].f == fp)
+		{
+			if(!denywrite || p->mosix.held_files[i].denywrite)
+				return(FOUND_OLD);
+			if(deny_write_access(fp))
+				return(-ETXTBSY);
+			p->mosix.held_files[i].denywrite = 1;
+			return(ADDED_A_DENY);
+		}
+		else if(new == -1 && !p->mosix.held_files[i].f)
+			new = i;
+		if(new == -1)
+		{
+			nh = NULL;/* COMPILER BUG -- hope it is optimized out */
+			for(i = DEFAULT_ALLOCATION ; i > 0 ; i >>= 1)
+			if((nh = kmalloc((i + p->mosix.held_allocated) *
+				sizeof(struct held_files), GFP_KERNEL)))
+				break;
+			if(!i)
+				return(-ENOMEM);
+			for(new = p->mosix.held_allocated + i - 1 ;
+				new >= p->mosix.held_allocated ; new--)
+				nh[new].f = NULL;
+			for(new = 0 ; new < p->mosix.held_allocated ; new++)
+				nh[new] = p->mosix.held_files[new];
+			oh = p->mosix.held_files;
+			task_lock(p);
+			p->mosix.held_files = nh;
+			p->mosix.held_allocated += i;
+			task_unlock(p);
+			kfree(oh);
+		}
+	}
+	get_file(fp);
+	task_lock(p);
+	p->mosix.held_files[new].f = fp;
+	task_unlock(p);
+	if((p->mosix.held_files[new].denywrite = denywrite))
+	{
+		if(deny_write_access(fp))
+		{
+			task_lock(p);
+			p->mosix.held_files[new].f = NULL;
+			task_unlock(p);
+			return(-ETXTBSY);
+		}
+		return(ALLOCATED_NEW_AND_DENY);
+	}
+	else
+		return(ALLOCATED_NEW);
+}
+
+void
+mosix_undo_last_file_registration(struct file *fp, int result)
+{
+	register unsigned int i;
+	struct mosix_task *m = &current->mosix;
+
+	if(result == FOUND_OLD)
+		return;
+	for(i = 0 ; i < m->held_allocated ; i++)
+	if((struct file *)m->held_files[i].f == fp)
+	{
+		switch(result)
+		{
+		case ADDED_A_DENY:
+		case ALLOCATED_NEW_AND_DENY:
+			if(!m->held_files[i].denywrite)
+				printk("%s: mosix_undo_last_file_registration - no denywrite\n",
+				       desc_mostask(m));
+			else
+				allow_write_access(fp);
+			if(result == ADDED_A_DENY)
+				break;
+		case ALLOCATED_NEW:
+			fput(fp);
+			task_lock(current);
+			m->held_files[i].f = NULL;
+			task_unlock(current);
+			break;
+		}
+		return;
+	}
+	printk("%s: mosix_undo_last_file_registration - not found\n",
+		desc_mostask(m));
+}
+
+void
+mosix_update_remote_files(void)
+{
+	struct task_struct *p = current;
+	register struct held_files *h = p->mosix.held_files;
+	register unsigned int i, j;
+	int op, np;
+	struct file **rf;
+	struct file *fp;
+
+	if(!(op = p->mosix.held_allocated))
+		return;
+	if(deputy_request(DEP_LISTHOLD, NULL, 0, NULL, 0, 0,
+						(void **)&np, -sizeof(int)))
+		deputy_die_on_communication();
+	if(np < 0 || (np && comm_recvdata((void **)&rf) < 0))
+		deputy_die_on_communication();
+	for(j = 0 ; j < op ; j++)
+		h[j].denywrite = (h[j].denywrite != 0) | 2;
+	for(i = 0 ; i < np ; i++)
+	{
+		for(j = 0 ; j < op ; j++)
+		if(h[j].f == rf[i])
+		{
+			h[j].denywrite &= ~2;
+			break;
+		}
+		if(j == op)
+			panic("mosix_update_remote_files: not listed");
+	}
+	for(j = 0 ; j < op ; j++)
+	if((fp = h[j].f) && (h[j].denywrite & 2))
+	{
+		task_lock(p);
+		h[j].f = NULL;
+		task_unlock(p);
+		if(h[j].denywrite & 1)
+			allow_write_access(fp);
+		fput(fp);
+	}
+	if(np)
+		comm_free(rf);
+}
+
+int
+mosix_rebuild_file_list(void)
+{
+	struct task_struct *p = current;
+	register struct vm_area_struct *vma, *vmb;
+	struct mm_struct *mm = p->mm;
+	struct held_files *hf = NULL, *old;
+	unsigned int i, n;
+	int oldn;
+	unsigned int denywrite;
+	struct file *this;
+
+	if(p->mosix.dflags & DDEPUTY)
+	{
+		if(p->mosix.dflags & DINCOMING)
+			p->mosix.dflags |= DDELAYHELD;
+		else
+			mosix_update_remote_files();
+		return(0);
+	}
+	if(atomic_read(&mm->mm_realusers) > 1)
+	{
+		mosix_clear_all_held_files(p);	/* discard old */
+		return(-EBUSY);	/* thread */
+	}
+	/* because we are the only clone, no MM lock is needed */
+	/* and the initial count cannot change */
+
+	for(n = 0 , vma = mm->mmap ; vma ; vma = vma->vm_next)
+	if((this = vma->vm_file))
+	{
+		for(vmb = mm->mmap ; vmb != vma ; vmb = vmb->vm_next)
+		if(vmb->vm_file == vma->vm_file)
+			break;
+		if(vmb == vma)
+		{
+			if(this->f_dentry->d_inode->i_mapping->i_mmap_shared)
+			{
+				monkey:
+				mosix_clear_all_held_files(p);
+				tell_process(p, DREQ_CHECKSTAY);
+				return(-EDIST);
+			}
+			n++;
+		}
+	}
+	if(n && !(hf = kmalloc(n*sizeof(struct held_files), GFP_KERNEL)))
+	{
+		mosix_clear_all_held_files(p);	/* discard old */
+		return(-ENOMEM);
+	}
+	for(n = 0 , vma = mm->mmap ; vma ; vma = vma->vm_next)
+	if((this = vma->vm_file))
+	{
+		for(vmb = mm->mmap ; vmb != vma ; vmb = vmb->vm_next)
+		if(vmb->vm_file == this)
+			goto already_placed;
+		denywrite = 0;
+		for(; vmb ; vmb = vmb->vm_next)
+		if(vmb->vm_file == this && (vmb->vm_flags & VM_DENYWRITE))
+		{
+			denywrite = 1;
+			atomic_dec(&this->f_dentry->d_inode->i_writecount);
+			break;
+		}
+		get_file(this);
+		hf[n].f = this;
+		hf[n++].denywrite = denywrite;
+		already_placed:;
+	}
+	/* must not use "mosix_clear_all_held_files" because it could sleep */
+	/* in 'fput' when another held file becomes VMONKEY */
+	oldn = p->mosix.held_allocated;
+	old = p->mosix.held_files;
+	task_lock(p);
+	p->mosix.held_files = hf;
+	p->mosix.held_allocated = n;
+	task_unlock(p);
+	if(old)
+	{
+		for(i = 0 ; i < oldn ; i++)
+		if((this = old[i].f))
+		{
+			if(old[i].denywrite)
+				allow_write_access(this);
+			fput(this);
+		}
+		kfree(old);
+	}
+	/* final race check: has any file been made monkey meanwhile? */
+	for(i = 0 ; i < n ; i++)
+	if(hf[i].f->f_dentry->d_inode->i_mapping->i_mmap_shared)
+		goto monkey;
+	return(0);
+}
+
+int
+fork_mosix_remote_files(struct task_struct *p)
+{
+	register unsigned int i;
+	register struct file *fp;
+
+	if(!(p->mosix.held_allocated = current->mosix.held_allocated))
+		return(0);
+	if(!(p->mosix.held_files = kmalloc(p->mosix.held_allocated *
+		sizeof(struct held_files), GFP_KERNEL)))
+	{
+		p->mosix.held_allocated = 0;
+		return(-ENOMEM);
+	}
+	for(i = 0 ; i < current->mosix.held_allocated ; i++)
+	if((fp = (struct file *)current->mosix.held_files[i].f))
+	{
+		get_file(fp);
+		p->mosix.held_files[i].f = fp;
+		if((p->mosix.held_files[i].denywrite =
+			current->mosix.held_files[i].denywrite))
+			atomic_dec(&fp->f_dentry->d_inode->i_writecount);
+	}
+	else
+		p->mosix.held_files[i].f = NULL;
+	return(0);
+}
+
+void
+mosix_clear_all_held_files(struct task_struct *p)
+{
+	register unsigned int i;
+	register int n;
+	struct held_files *h;
+
+	if(!(n = p->mosix.held_allocated))
+		return;
+	h = p->mosix.held_files;
+	task_lock(p);
+	p->mosix.held_files = NULL;
+	p->mosix.held_allocated = 0;
+	task_unlock(p);
+	for(i = 0 ; i < n ; i++)
+	if(h[i].f)
+	{
+		if(h[i].denywrite)
+			allow_write_access(h[i].f);
+		fput(h[i].f);
+	}
+	kfree(h);
+}
+
+int
+task_maps_ip(struct task_struct *p, struct inode *ip)
+{
+	register unsigned int i;
+	register int n;
+	int ret = 0;
+	struct held_files *h;
+
+	task_lock(p);
+	if((n = p->mosix.held_allocated))
+	for(h = p->mosix.held_files , i = 0 ; i < n ; i++)
+	if(h[i].f && (h[i].f)->f_dentry->d_inode == ip)
+	{
+		ret = 1;
+		break;
+	}
+	task_unlock(p);
+	return(ret);
+}
+
diff -Naur --exclude=CVS --exclude=configs linux/hpc/service.c linux-openmosix/hpc/service.c
--- linux/hpc/service.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/service.c	2004-02-05 02:48:27.000000000 +0100
@@ -0,0 +1,463 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+
+
+#include <linux/sched.h>
+#include <linux/hpcctl.h>
+#include <net/sock.h>
+#include <hpc/defs.h>
+#include <hpc/routines.h>
+#include <hpc/debug.h>
+#include <hpc/protocol.h>
+#include <linux/hpc.h>
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <linux/smp_lock.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <asm/pgtable.h>
+
+/* all sorts of operating-system dependent mob */
+
+void
+common_daemon_setup(char *name, int highpri)
+{
+	register struct task_struct *p = current;
+	struct fs_struct *fs;
+	struct files_struct *fl;
+
+	strcpy(p->comm, name);
+	exit_mm(p);
+	exit_files(p);
+	fl = init_task.files;
+	p->files = fl;
+	atomic_inc(&fl->count);
+	exit_fs(p);
+	fs = init_task.fs;
+	p->fs = fs;
+	atomic_inc(&fs->count);
+#ifdef CONFIG_MOSIX_DFSA
+	atomic_inc(&fs->users);
+#endif /* CONFIG_MOSIX_DFSA */
+
+	p->pgrp = 1;
+	p->session = 1;
+	p->tty = NULL;
+	reparent_to_init();
+	p->it_real_incr = 0;
+	p->it_prof_incr = 0;
+	p->it_virt_incr = 0;
+	p->it_real_value = 0;
+	p->it_prof_value = 0;
+	p->it_virt_value = 0;
+	if(p->uid)
+	{
+		free_uid(p->user);
+		p->uid = 0;
+		alloc_uid(0);
+	}
+	p->euid = 0;
+	p->suid = 0;
+	p->gid = 0;
+	p->ngroups = 0;
+	spin_lock_irq(&p->sigmask_lock);
+	sigemptyset(&p->blocked);
+	recalc_sigpending(p);
+	spin_unlock_irq(&p->sigmask_lock);
+	memcpy(p->rlim, init_task.rlim, sizeof(p->rlim));
+	task_lock(p);
+	if(highpri)
+	{
+		p->policy = SCHED_FIFO;
+		p->mosix.stay |= DSTAY_FOR_RT;
+		p->rt_priority = 0;
+	}
+	else
+	{
+		p->policy = SCHED_OTHER;
+		p->mosix.stay &= ~DSTAY_FOR_RT;
+		p->nice = DEF_NICE;
+	}
+	p->mosix.stay |= DSTAY_SYSTEM;
+	task_unlock(p);
+}
+
+char *
+desc_mostask(struct mosix_task *m)
+{
+	register struct task_struct *p = m ? MOSIX_TO_TASK(m) : current;
+	/* paranoid: save space for each SMP + interrupts */
+	static char descbuf[NR_CPUS+2][14+sizeof(p->comm)];
+	static int ind;
+	static spinlock_t desc_lock = SPIN_LOCK_UNLOCKED;
+	int i;
+
+	spin_lock_irq(&desc_lock);
+	i = ind;
+	ind = (i + 1) % (NR_CPUS+2);
+	spin_unlock_irq(&desc_lock);
+
+	sprintf(descbuf[i], "%d(%s)", p->pid, p->comm);
+	return(descbuf[i]);
+}
+
+asmlinkage void ret_from_kickstart(void) __asm__("ret_from_kickstart");
+
+#define loaddebug(tsk,register) \
+		__asm__("movl %0,%%db" #register  \
+			: /* no output */ \
+			:"r" (tsk->thread.debugreg[register]))
+
+void
+kickstart(void)
+{
+	register struct task_struct *p = current;
+	struct pt_regs *regs, *curegs = mos_to_regs(&p->mosix);
+	/* load segment registers
+	   FIXME: do this only if remote modified LDT */
+	loadsegment(gs, p->mosix.altgs);
+	loadsegment(fs, p->mosix.altgs);
+	set_fs(USER_DS);
+	regs = ((struct pt_regs *) (2*PAGE_SIZE + (unsigned long)p)) - 1;
+	if(regs != curegs)
+	{
+		task_lock(current);
+		*regs = *(curegs);
+		p->mosix.altregs = (uint32_t *)regs;
+		task_unlock(current);
+	}
+	/* the contents of our registers may at this stage still be held
+	 * by our DEPUTY, hence our registers contain junk.
+	 * (which is OK - we are not going to user-mode yet)
+	 * the silly thing about it is that we may get to "ret_from_intr"
+	 * via "do_bottom_half", which might then believe we had a kernel-mode
+	 * interrupt and avoid returning via ret_with_reschedule...
+	 * the remedy is:
+	 */
+	regs->xcs |= 3;
+
+	if(current->thread.debugreg[7])
+	{
+		loaddebug(current,0);
+		loaddebug(current,1);
+		loaddebug(current,2);
+		loaddebug(current,3);
+		loaddebug(current,6);
+		loaddebug(current,7);
+	}
+	release_kernel_lock(current, smp_processor_id());
+	current->lock_depth = -1;
+	/*current->mosix.lock_depth = -1;*/
+	asm("movl %0,%%esp ; jmp ret_from_kickstart" : : "r" (regs));
+	/*NOTREACHED*/
+}
+
+/*
+ * a page on the swap-cache is dirty: even if it happens to be clean relative
+ * to the swap-page, it is NOT clean relative to the original file.
+ */
+static inline int
+pte_really_dirty(pte_t entry)
+{
+	struct page *page;
+
+	if(pte_dirty(entry))
+		return(1);	/* the simple case */
+	page = pte_page(entry);
+	if(!VALID_PAGE(page))
+	{
+		return(1);
+	}
+	return(PageDirty(page) || PageSwapCache(page));
+}
+
+#define	RUN_OVER_MAGIC	126094
+
+static int run_over_maxchunk;
+
+int
+run_over_dirty_pages(int (*func)(unsigned long, int), int count_in_file)
+{
+	struct task_struct *p = current;
+	struct mm_struct *mm = p->mm;
+	struct vm_area_struct *vma;
+	int count = 0;
+	int isfile;
+	unsigned long start, addr, pgd_end, pmd_end, pte_end;
+	pgd_t *pgdir;
+	pmd_t *pmdir;
+	pte_t *pte;
+	int err;
+	int let_go;
+
+	if(!run_over_maxchunk)
+	{
+		/* this routine can take very long for huge processes:
+		 * we must allow other processes to take over at least
+		 * about every millisecond.
+		 */
+		run_over_maxchunk = loops_per_jiffy / RUN_OVER_MAGIC;
+		if(!run_over_maxchunk)	/* slow processors */
+			run_over_maxchunk = 1;
+	}
+
+	addr = 0;
+	loop:
+	let_go = run_over_maxchunk;
+	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next)
+	if(addr < vma->vm_end)
+	{
+	    start = vma->vm_start;
+	    if(start < addr)
+		start = addr;
+	    pgdir = pgd_offset(mm, start);
+	    isfile = (vma->vm_file != NULL);
+	    for(addr = start ; addr < vma->vm_end ; addr = pgd_end , pgdir++)
+	    {
+		if(let_go-- == 0)
+		{
+			p->policy |= SCHED_YIELD;
+			schedule();
+			goto loop;
+		}
+		pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
+		if(pgd_end > vma->vm_end)
+			pgd_end = vma->vm_end;
+		if(pgd_none(*pgdir) || pgd_bad(*pgdir))
+			continue;
+		spin_lock(&mm->page_table_lock);
+		pmdir = pmd_offset(pgdir, addr);
+		for(; addr < pgd_end ; addr = pmd_end , pmdir++)
+		{
+		    pmd_end = (addr + PMD_SIZE) & PMD_MASK;
+		    if(pmd_end > pgd_end)
+			    pmd_end = pgd_end;
+		    if(pmd_none(*pmdir) || pmd_bad(*pmdir))
+			    continue;
+		    pte = pte_offset(pmdir, addr);
+		    for(; addr < pmd_end ; addr = pte_end , pte++)
+		    {
+			pte_end = addr + PAGE_SIZE;
+			if(pte_end > pmd_end)
+				pte_end = pmd_end;
+			if(pte_present(*pte) ?
+				(isfile && !pte_really_dirty(*pte)) :
+				pte_none(*pte))
+			{
+				if(isfile && count_in_file)
+					count++;
+				continue;
+			}
+			if(!count_in_file)
+				count++;
+			if(func)
+			{
+				spin_unlock(&mm->page_table_lock);
+				if((err = (*func)(addr, PAGE_SIZE)))
+					return(err);
+				spin_lock(&mm->page_table_lock);
+			}
+		    }
+		}
+		spin_unlock(&mm->page_table_lock);
+	    }
+	}
+	return(count);
+}
+
+#if 0
+/* needed once-only to calibrate the "run_over_maxchunk" calculation */
+/* not bothering using locks here, since we are only called from the debugger */
+int
+calibrate_run_over(void)
+{
+	int sv = run_over_maxchunk;
+	struct mm_struct *mm = current->mm;
+	unsigned int chunks = 0;
+	register struct vm_area_struct *vma;
+	unsigned long addr, pgd_end;
+	__typeof__ (jiffies) before;
+	int milli, magic;
+	int i;
+
+	if(!mm)
+	{
+		printk("No MM\n");
+		return(0);
+	}
+
+	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next)
+	for(addr = vma->vm_start ; addr < vma->vm_end ; addr = pgd_end)
+	{
+		chunks++;
+		pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
+		if(pgd_end > vma->vm_end)
+			pgd_end = vma->vm_end;
+	}
+	printk("%d chunks: starting 1000 times...", chunks);
+	run_over_maxchunk = 0x7fffffff;	/* unlimit */
+	sti();
+	before = jiffies;
+	for(i = 0 ; i < 1000 ; i++)
+		run_over_dirty_pages(NULL, 0);
+	milli = (jiffies - before) * 1000 / HZ;
+	printk("%d miliseconds, ", milli);
+	run_over_maxchunk = sv;
+	if(milli < 100)
+	{
+		printk("That was too quick -- try a larger process!\n");
+		return((int)milli);
+	}
+	magic = loops_per_jiffy / (chunks * 1000 / milli);
+	printk("RUN_OVER_MAGIC=%d\n", magic);
+	return(magic);
+}
+#endif /* MOSIX_ONCE_ONLY */
+
+/* provide accurate time in microseconds, even when jiffies wraps around */
+now_t
+time_now(void)
+{
+	static int64_t cycles;
+	static typeof(jiffies) lastj;
+	now_t now;
+	typeof(jiffies) prev;
+	static spinlock_t time_lock = SPIN_LOCK_UNLOCKED;
+
+	if(jiffies == 0 && cycles == 0)
+		return(1);
+	spin_lock_irq(&time_lock);
+	prev = lastj;
+	lastj = jiffies;
+	if(lastj < prev)
+		cycles += 0x100000000LL * MILLION / HZ;
+	now = ticks_to_ms(lastj) + cycles;
+	spin_unlock_irq(&time_lock);
+	return(now);
+}
+
+void
+adjust_task_mosix_context(struct task_struct **tp)
+{
+	struct task_struct *t = *tp;
+
+	if(t->mosix.dflags & DINSCHED)
+		*tp = MOSIX_CONTEXT(t);
+}
+
+int
+obtain_mm(void)
+{
+	struct mm_struct *mm, *active_mm;
+	struct task_struct *p = current;
+	int err;
+
+	if(p->mm)
+		panic("obtain_mm: had already");
+	if(!(mm = mm_alloc()))
+		return(-ENOMEM);
+	if((err = init_new_context(p, mm)))
+	{
+		task_unlock(p);
+		mmdrop(mm);
+		return(err);
+	}
+	spin_lock(&mmlist_lock);
+	list_add(&mm->mmlist, &init_mm.mmlist);
+	mmlist_nr++;
+	spin_unlock(&mmlist_lock);
+	task_lock(p);
+	active_mm = p->active_mm;
+	p->mm = mm;
+	p->active_mm = mm;
+	task_unlock(p);
+	activate_mm(active_mm, mm);
+	mmdrop(active_mm);
+	return(0);
+}
+
+DECLARE_WAIT_QUEUE_HEAD(wait_for_capsync);
+
+void
+sync_caps(void)
+{
+	struct task_struct *p = current;
+	kernel_cap_t prev;
+
+	if(process_told(p, DREQ_CAPCNG))
+	{
+		write_lock_irq(&tasklist_lock);
+		prev = p->mosix.remote_caps;
+		p->mosix.remote_caps = p->cap_effective;
+		process_ack(p, DREQ_CAPCNG);
+		write_unlock_irq(&tasklist_lock);
+		wake_up(&wait_for_capsync);
+		if((p->mosix.dflags & DDEPUTY) &&
+			((prev ^ p->mosix.remote_caps) & REMOTE_CAPS))
+			deputy_request(DEP_CAPS, &p->mosix.remote_caps,
+				sizeof(p->mosix.remote_caps), NULL, 0, 0,
+				NULL, 0);
+	}
+}
+
+int
+mosix_sync_caps(kernel_cap_t effective)
+{
+	unsigned int any = 0;
+	struct task_struct *p;
+	DECLARE_WAITQUEUE(wait, current);
+
+	write_lock_irq(&tasklist_lock);
+	for_each_task(p)
+	if((p->mosix.dflags & (DDEPUTY|DFINISHED)) == DDEPUTY &&
+		p->cap_effective == effective &&
+		((p->mosix.remote_caps ^ effective) & REMOTE_CAPS))
+	{
+		tell_process(p, DREQ_CAPCNG);
+		if(p != current)
+		{
+			any = 1;
+			wake_up_mosix(p);
+		}
+	}
+	write_unlock_irq(&tasklist_lock);
+	sync_caps();	/* affecting ourselves is the most common case */
+	if(!any)
+		return(0);
+	add_wait_queue(&wait_for_capsync, &wait);
+	loop:
+	set_current_state(TASK_INTERRUPTIBLE);
+	any = 0;
+	read_lock(&tasklist_lock);
+	for_each_task(p)
+	if((p->mosix.dflags & (DDEPUTY|DFINISHED)) == DDEPUTY &&
+		p->cap_effective == effective &&
+		(process_told(p, DREQ_CAPCNG)) &&
+		((p->mosix.remote_caps ^ effective) & REMOTE_CAPS))
+	{
+		any = 1;
+		break;
+	}
+	read_unlock(&tasklist_lock);
+	if(any)
+	{
+		schedule();
+		set_current_state(TASK_RUNNING);
+		if(signal_pending(current))
+		{
+			remove_wait_queue(&wait_for_capsync, &wait);
+			return(-EINTR);
+		}
+		goto loop;
+	}
+	remove_wait_queue(&wait_for_capsync, &wait);
+	return(0);
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/syscalls.c linux-openmosix/hpc/syscalls.c
--- linux/hpc/syscalls.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/syscalls.c	2003-09-10 20:50:13.000000000 +0200
@@ -0,0 +1,2520 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+#include <linux/sched.h>
+#include <linux/hpc.h>
+#include <linux/timex.h>
+#include <linux/utime.h>
+#include <linux/utsname.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/random.h>
+#include <linux/quotacompat.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/socket.h>
+#include <linux/nfs.h>
+#include <linux/net.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/syscall.h>
+#include <hpc/protocol.h>
+#include <hpc/routines.h>
+#include <asm/processor.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+#include <asm/poll.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/hdreg.h>
+#include <linux/capability.h>
+#include <linux/module.h>
+#include "../ipc/util.h"
+#ifdef CONFIG_MOSIX_DFSA
+#include <hpc/dfsa.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
+
+
+/* In this file we have actually most of DFSA's capability, namely to locally execute
+ * some file system related system calls. You'll notice that for each fs related syscall
+ * there is a DFSA handling variant (the long way) or the non DFSA variant (the short way 
+ * because we are just shipping the syscall number and the registers back. 
+ * When integrating a new file system with openMosix' DFSA, make sure to drop by this file and
+ * have a look around 
+ * Moshe Bar */
+
+extern caddr_t sys_call_table[];
+
+#define	set_file_name(x)	do { \
+				unsigned long fn = ((int *)&regs)[x]; \
+				set_write_region(fn, strlen_user((char *)fn)); \
+				} while(0);
+#define	ARG(x)			(((int *)&regs)[x])
+#if BITS_PER_LONG == 32
+#define	LARG(x)			(*((long long *)(((int *)&regs)+(x))))
+#else
+#define	LARG(x)			(*((long *)(((int *)&regs)+(x))))
+#endif
+
+#ifdef CONFIG_MOSIX_DFSA
+#define	RESULT_IS_FINAL(result)	((result) >= 0 || ( \
+	(result) != -EDOITATHOME && (result) != -EINTR && \
+	(result) != -ERESTARTSYS && (result) != -ERESTARTNOINTR && \
+	(result) != -ERESTARTNOHAND && (result) != -EAGAIN))
+#endif /* CONFIG_MOSIX_DFSA */
+
+int
+remote_sys_getpid(int n, struct pt_regs regs)
+{
+	return(current->mosix.depinfo.tgid);
+}
+
+int
+remote_sys_gettid(int n, struct pt_regs regs)
+{
+	return(current->mosix.mypid);
+}
+
+long
+remote_sys_getitimer(int n, struct pt_regs regs)
+{
+	extern asmlinkage long sys_getitimer(int, struct itimerval *);
+
+	if(*((int *)&regs) == ITIMER_REAL)
+	{
+		set_read_region(ARG(1), sizeof(struct itimerval));
+		return(remote_standard_system_call(n, &regs));
+	}
+	return(sys_getitimer(ARG(0), (struct itimerval *)ARG(1)));
+}
+
+long
+remote_sys_setitimer(int n, struct pt_regs regs)
+{
+	extern asmlinkage long sys_setitimer(int, struct itimerval *,
+							struct itimerval *);
+
+	if(*((int *)&regs) == ITIMER_REAL)
+	{
+		if(ARG(1))
+			set_write_region(ARG(1), sizeof(struct itimerval));
+		if(ARG(2))
+			set_read_region(ARG(2), sizeof(struct itimerval));
+		return(remote_standard_system_call(n, &regs));
+	}
+	return(sys_setitimer(ARG(0), (struct itimerval *)ARG(1),
+		(struct itimerval *)ARG(2)));
+}
+
+unsigned long
+remote_sys_brk(int n, struct pt_regs regs)
+{
+	extern asmlinkage unsigned long sys_brk(unsigned long);
+
+	return(sys_brk((unsigned long)ARG(0)));
+}
+
+long
+remote_sys_mprotect(int n, struct pt_regs regs)
+{
+	extern asmlinkage long sys_mprotect(unsigned long, size_t,
+								unsigned long);
+
+	return(sys_mprotect((unsigned long)ARG(0), (size_t)ARG(1),
+		(unsigned long)ARG(2)));
+}
+
+long
+remote_sys_msync(int n, struct pt_regs regs)
+{
+	return(0);	/* no writeable file-mapping allowed remotely! */
+}
+
+long
+remote_sys_munlock(int n, struct pt_regs regs)
+{
+	/* since remote mlocking is not allowed, but we are still here,
+	 * this must only be a "make-sure" call */
+	return(0);
+}
+
+long
+remote_sys_munlockall(int n, struct pt_regs regs)
+{
+	/* since remote mlocking is not allowed, but we are still here,
+	 * this must only be a "make-sure" call */
+	return(0);
+}
+
+unsigned long
+remote_sys_mremap(int n, struct pt_regs regs)
+{
+	extern asmlinkage unsigned long sys_mremap(unsigned long, unsigned long,
+				 unsigned long, unsigned long, unsigned long);
+
+	return(sys_mremap((unsigned long)ARG(0), (unsigned long)ARG(1),
+		(unsigned long)ARG(2), (unsigned long)ARG(3),
+		(unsigned long)ARG(4)));
+}
+
+int
+remote_sys_modify_ldt(int n, int func, void *ptr, unsigned long bytecount)
+{
+	extern asmlinkage int sys_modify_ldt(int, void *, unsigned long);
+
+	return(sys_modify_ldt(func, ptr, bytecount));
+}
+
+long
+remote_sys_sched_yield(void)
+{
+	extern asmlinkage long sys_sched_yield(void);
+
+	return(sys_sched_yield());
+}
+
+long
+remote_sys_mincore(int n, struct pt_regs regs)
+{
+	extern asmlinkage long sys_mincore(unsigned long, size_t,
+							unsigned char *);
+
+	return(sys_mincore((unsigned long)ARG(0), (size_t)ARG(1),
+		(unsigned char *)ARG(2)));
+}
+
+long
+remote_sys_madvise(int n, struct pt_regs regs)
+{
+	extern asmlinkage long sys_madvise(unsigned long, size_t, int);
+
+	return(sys_madvise((unsigned long)ARG(0), (size_t)ARG(1), (int)ARG(2)));
+}
+
+long
+#ifdef CONFIG_MOSIX_DFSA
+remote_sys_close_syscall(int n, struct pt_regs regs)
+#else
+remote_sys_close(int n, struct pt_regs regs)
+#endif /* CONFIG_MOSIX_DFSA */
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_close(unsigned int);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if((p->files->fd[fd] ||
+		(p->mosix.ttab && !FD_ISSET(fd, p->files->open_fds))) &&
+		enter_remote_dfsa_mode())
+	{
+		result = sys_close((unsigned int)ARG(0));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fchdir(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fchdir(unsigned int);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->fs->pwd && p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fchdir(fd);
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_ftruncate(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_ftruncate(unsigned int, unsigned long);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_ftruncate(fd, (unsigned long)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_ftruncate64(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_ftruncate64(unsigned int, loff_t);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_ftruncate64(fd, (loff_t)LARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fchmod(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fchmod(unsigned int, mode_t);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fchmod(fd, (mode_t)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fchown(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fchown(unsigned int, uid_t, gid_t);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fchown(fd, (uid_t)ARG(1), (gid_t)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fchown16(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fchown16(unsigned int, old_uid_t, old_gid_t);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fchown16(fd, (old_uid_t)ARG(1), (old_gid_t)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_dup(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_dup(unsigned int);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_dup(fd);
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_dup2(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_dup2(unsigned int, unsigned int);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_dup2(fd, (unsigned int)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fsync(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fsync(unsigned int);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fsync(fd);
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fdatasync(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fdatasync(unsigned int);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fdatasync(fd);
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_write(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	ssize_t result;
+	extern asmlinkage ssize_t sys_write(unsigned int, char *, size_t);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_write(fd, (char *)ARG(1), ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_write_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_read(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	ssize_t result;
+	extern asmlinkage ssize_t sys_read(unsigned int, char *, size_t);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_read(fd, (char *)ARG(1), ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_open(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_open((char *)ARG(0), ARG(1), ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_waitpid(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(int));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_creat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_creat(char *, int);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_creat((char *)ARG(0), ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_link(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_link(const char *, const char *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_link((const char *)ARG(0), (const char *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_file_name(1);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_unlink(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_unlink(const char *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_unlink((const char *)ARG(0));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_execve(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_chdir(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_chdir(char *);
+
+	if(current->fs->pwd && current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_chdir((char *)ARG(0));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_time(int n, struct pt_regs regs)
+{
+	if(ARG(0))
+		set_read_region(ARG(0), sizeof(int));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_mknod(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_chmod(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_chmod(const char *, mode_t);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_chmod((const char *)ARG(0), (mode_t)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_lchown(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_lchown(const char *, uid_t, gid_t);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_lchown((const char *)ARG(0), (uid_t)ARG(1),
+								(gid_t)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_lchown16(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_lchown16(const char *, old_uid_t, old_gid_t);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_lchown16((const char *)ARG(0), (old_uid_t)ARG(1),
+							(old_gid_t)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_stat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_stat(char *, struct __old_kernel_stat *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_stat((char *)ARG(0),
+					(struct __old_kernel_stat *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct __old_kernel_stat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_stat64(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_stat64(char *, struct stat64 *, long);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_stat64((char *)ARG(0), (struct stat64 *)ARG(1),
+								(long)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct stat64));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_mount(int n, struct pt_regs regs)
+{
+	unsigned long arg, len;
+	set_file_name(0);
+	set_file_name(1);
+	if((arg = ARG(2)))
+	{
+		len = TASK_SIZE - arg;
+		if(len > PAGE_SIZE-1)
+			len = PAGE_SIZE-1;
+		set_write_region(ARG(2), len);
+	}
+	if((arg = ARG(4)))
+	{
+		len = TASK_SIZE - arg;
+		if(len > PAGE_SIZE-1)
+			len = PAGE_SIZE-1;
+		set_write_region(ARG(4), PAGE_SIZE-1);
+	}
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_oldumount(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_stime(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(int));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fstat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fstat(unsigned int,
+						struct __old_kernel_stat *);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fstat(fd, (struct __old_kernel_stat *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), sizeof(struct __old_kernel_stat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fstat64(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_fstat64(unsigned int, struct stat64 *, long);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_fstat64(fd, (struct stat64 *)ARG(1), (long)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), sizeof(struct stat64));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_utime(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_utime(char *, struct utimbuf *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_utime((char *)ARG(0), (struct utimbuf *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	if(ARG(1))
+		set_read_region(ARG(1), sizeof(struct utimbuf));
+	return(remote_standard_system_call(n, &regs));
+}
+
+/* NOTE: sys_utimes is not supported for i386,
+ * but should be implemented for Alpha/Sparc */
+
+long
+remote_sys_access(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_access(const char *, int);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_access((const char *)ARG(0), (int)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rename(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_rename(const char *, const char *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_rename((const char *)ARG(0), (const char *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_file_name(1);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_mkdir(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_mkdir(const char *, int);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_mkdir((const char *)ARG(0), ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rmdir(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_rmdir(const char *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_rmdir((const char *)ARG(0));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_pipe(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), 2 * sizeof(long));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_times(int n, struct pt_regs regs)
+{
+	if(ARG(0))
+		set_read_region(ARG(0), sizeof(struct tms));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_acct(int n, struct pt_regs regs)
+{
+	if(ARG(0))
+		set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_umount(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_ioctl(int n, struct pt_regs regs)
+{
+	switch(ARG(1))
+	{
+		/* so many more -- feel free to add: */
+		/* if ambiguous -- add both! */
+		/* but do not include ioctls whose definitions is configurable*/
+		/* also, it is better to not include rare non-tty ioctls,
+		   because it would slow-down the other's performance */
+	case TCGETS:
+	case TIOCGLCKTRMIOS:
+		set_read_region(ARG(2), sizeof(struct termios));
+		break;
+	case TCSETS:
+	case TCSETSF:
+	case TCSETSW:
+	case TIOCSLCKTRMIOS:
+		set_write_region(ARG(2), sizeof(struct termios));
+		break;
+	case TCGETA:
+		set_read_region(ARG(2), sizeof(struct termio));
+		break;
+	case TCSETA:
+	case TCSETAW:
+	case TCSETAF:
+		set_write_region(ARG(2), sizeof(struct termio));
+		break;
+	case TIOCOUTQ:
+	case TIOCGSOFTCAR:
+	case FIONREAD:
+	case FIGETBSZ:
+	case TIOCGETD:
+	case TIOCMGET:
+	case TIOCSERGWILD:
+	case TIOCSERGETLSR:
+	case RNDGETENTCNT:
+		set_read_region(ARG(2), sizeof(int));
+		break;
+	case FIBMAP:
+		set_write_region(ARG(2), sizeof(int));
+		set_read_region(ARG(2), sizeof(int));
+		break;
+	case TIOCPKT:
+	case TIOCSETD:
+	case TIOCSSOFTCAR:
+	case FIONBIO:
+	case TIOCMSET:
+	case TIOCSERSWILD:
+		set_write_region(ARG(2), sizeof(int));
+		break;
+	case TIOCSTI:
+		set_write_region(ARG(2), sizeof(char));
+		break;
+	case TIOCGWINSZ:
+		set_read_region(ARG(2), sizeof(struct winsize));
+		break;
+	case TIOCSWINSZ:
+		set_write_region(ARG(2), sizeof(struct winsize));
+		break;
+	case TIOCGPGRP:
+	case TIOCGSID:
+		set_read_region(ARG(2), sizeof(pid_t));
+		break;
+	case TIOCSPGRP:
+		set_write_region(ARG(2), sizeof(pid_t));
+		break;
+	case TIOCLINUX:
+		/* there are many cases - use the extreme ones: */
+		set_read_region(ARG(2), 1);
+		set_write_region(ARG(2), 36);
+		break;
+	case TIOCTTYGSTRUCT:
+		set_read_region(ARG(2), sizeof(struct tty_struct));
+		break;
+	case TIOCGSERIAL:
+		set_read_region(ARG(2), sizeof(struct serial_struct));
+		break;
+	case TIOCSSERIAL:
+		set_write_region(ARG(2), sizeof(struct serial_struct));
+		break;
+	case TIOCSERGSTRUCT:
+		set_read_region(ARG(2), sizeof(struct async_struct));
+		break;
+	case TIOCGICOUNT:
+		set_read_region(ARG(2), sizeof(struct serial_icounter_struct));
+		break;
+	case HDIO_GETGEO:
+		set_read_region(ARG(2), sizeof(struct hd_geometry));
+		break;
+               /* Socket ioctls see sockios.h and man ioctl_list(2) */
+   
+                   case FIOGETOWN:
+                   case SIOCGPGRP:
+                   case SIOCATMARK:
+                           set_read_region(ARG(2), sizeof(int));
+                           /* fall thru! */
+                   case FIOSETOWN:
+                   case SIOCSPGRP:
+                           set_write_region(ARG(2), sizeof(int));
+                           break;
+                   case SIOCGSTAMP:
+                           set_read_region(ARG(2), sizeof(struct timeval));
+                           break;
+	}
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fcntl(int n, struct pt_regs regs)
+{
+	unsigned long f = ARG(1);
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+	long result;
+	extern asmlinkage long sys_fcntl(unsigned int, unsigned int,
+								unsigned long);
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(FD_ISSET(fd, p->files->open_fds) && p->files->fd[fd])
+		switch(f)
+		{
+		case F_DUPFD:
+		case F_GETFL:
+		case F_SETFL:
+			if(!enter_remote_dfsa_mode())
+				break;
+			result = sys_fcntl(fd, f, (unsigned long)ARG(2));
+			leave_remote_dfsa_mode();
+			if(RESULT_IS_FINAL(result))
+				return(result);
+			break;
+		}
+#endif /* CONFIG_MOSIX_DFSA */
+	switch(f)
+	{
+	case F_GETLK:
+		set_read_region(ARG(2), sizeof(struct flock));
+		break;
+	case F_SETLK:
+	case F_SETLKW:
+		set_write_region(ARG(2), sizeof(struct flock));
+		break;
+	}
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fcntl64(int n, struct pt_regs regs)
+{
+	unsigned long f = ARG(1);
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+	long result;
+	extern asmlinkage long sys_fcntl64(unsigned int, unsigned int,
+					   unsigned long);
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(FD_ISSET(fd, p->files->open_fds) && p->files->fd[fd])
+		switch(f)
+		{
+		case F_DUPFD:
+		case F_GETFD:
+		case F_SETFD:
+		case F_GETFL:
+		case F_SETFL:
+			if(!enter_remote_dfsa_mode())
+				break;
+			result = sys_fcntl64(fd, f, (unsigned long)ARG(2));
+			leave_remote_dfsa_mode();
+			if(RESULT_IS_FINAL(result))
+				return(result);
+			break;
+		}
+#endif /* CONFIG_MOSIX_DFSA */
+	switch(f)
+	{
+	case F_GETLK:
+		set_read_region(ARG(2), sizeof(struct flock));
+		break;
+	case F_SETLK:
+	case F_SETLKW:
+		set_write_region(ARG(2), sizeof(struct flock));
+		break;
+	case F_GETLK64:
+		set_read_region(ARG(2), sizeof(struct flock64));
+		break;
+	case F_SETLK64:
+	case F_SETLKW64:
+		set_write_region(ARG(2), sizeof(struct flock64));
+		break;
+	}
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_olduname(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(struct oldold_utsname));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_chroot(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_ustat(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct ustat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sigpending(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(old_sigset_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_sigaction(int n, struct pt_regs regs)
+{
+	if(ARG(1))
+		set_write_region(ARG(1), sizeof(struct old_sigaction));
+	if(ARG(2))
+		set_read_region(ARG(2), sizeof(struct old_sigaction));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_setrlimit(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(1), sizeof(struct rlimit));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getrlimit(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct rlimit));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_old_getrlimit(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct rlimit));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getrusage(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct rusage));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_gettimeofday(int n, struct pt_regs regs)
+{
+	if(ARG(0))
+		set_read_region(ARG(0), sizeof(struct timeval));
+	if(ARG(1))
+		set_read_region(ARG(1), sizeof(struct timezone));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_settimeofday(int n, struct pt_regs regs)
+{
+	if(ARG(0))
+		set_write_region(ARG(0), sizeof(struct timeval));
+	if(ARG(1))
+		set_write_region(ARG(1), sizeof(struct timezone));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getgroups(int n, struct pt_regs regs)
+{
+	unsigned int ng = ARG(0);
+
+	if(ng > 0 && ARG(1))
+		set_read_region(ARG(1), ng * sizeof(gid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getgroups16(int n, struct pt_regs regs)
+{
+	unsigned int ng = ARG(0);
+
+	if(ng > 0 && ARG(1))
+		set_read_region(ARG(1), ng * sizeof(old_gid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_setgroups(int n, struct pt_regs regs)
+{
+	unsigned int ng = ARG(0);
+
+	if(ng > 0)
+		set_write_region(ARG(1), ng * sizeof(gid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_setgroups16(int n, struct pt_regs regs)
+{
+	unsigned int ng = ARG(0);
+
+	if(ng > 0)
+		set_write_region(ARG(1), ng * sizeof(old_gid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+void
+set_select_regions(int n, unsigned long inp, unsigned long outp,
+					unsigned long exp, unsigned long tvp)
+{
+	n = (n + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long);
+	if(inp)
+	{
+		set_read_region(inp, n);
+		set_write_region(inp, n);
+	}
+	if(outp)
+	{
+		set_read_region(outp, n);
+		set_write_region(outp, n);
+	}
+	if(exp)
+	{
+		set_read_region(exp, n);
+		set_write_region(exp, n);
+	}
+	if(tvp)
+	{
+		set_read_region(tvp, sizeof(struct timeval));
+		set_write_region(tvp, sizeof(struct timeval));
+	}
+}
+
+int
+remote_old_select(int n, struct pt_regs regs)
+{
+	unsigned long a[5];
+
+	if(copy_from_user(a, (char *)ARG(0), sizeof(a)))
+		return(-EFAULT);
+
+	set_write_region(ARG(0), sizeof(a));
+	set_select_regions(a[0], a[1], a[2], a[3], a[4]);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_symlink(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_symlink(const char *, const char *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_symlink((const char *)ARG(0),
+							(const char *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_file_name(1);
+	return(remote_standard_system_call(n, &regs));
+}
+
+
+long
+remote_sys_lstat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_lstat(char *, struct __old_kernel_stat *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_lstat((char *)ARG(0),
+					(struct __old_kernel_stat *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct __old_kernel_stat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_lstat64(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_lstat64(char *, struct stat64 *, long);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_lstat64((char *)ARG(0), (struct stat64 *)ARG(1),
+								(long)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct stat64));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_readlink(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_readlink(const char *, char *, int);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_readlink((const char *)ARG(0), (char *)ARG(1),
+								(int)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_uselib(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_swapon(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_old_readdir(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	int result;
+	extern asmlinkage int old_readdir(unsigned int, void *, unsigned int);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = old_readdir(fd, (void *)ARG(1), (unsigned int)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_old_mmap(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), 6 * sizeof(int));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_truncate(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_truncate(const char *, unsigned long);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_truncate((const char *)ARG(0),
+							(unsigned long)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_truncate64(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_truncate64(const char *, loff_t);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_truncate64((const char *)ARG(0), (loff_t)LARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_statfs(int n, struct pt_regs regs)
+{
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct statfs));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_fstatfs(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct statfs));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_socketcall(int n, struct pt_regs regs)
+{
+	unsigned long a[6];
+	unsigned long alen;
+	struct msghdr hdr;
+	int i;
+	struct iovec io;
+
+	set_write_region(ARG(1), 6 * sizeof(int));
+	if(!copy_from_user(a, (char *)ARG(1), 6 * sizeof(int)))
+		switch(ARG(0)) {
+		case SYS_BIND:
+		case SYS_CONNECT:
+			set_write_region(a[1], a[2]);
+			break;
+		case SYS_ACCEPT:
+		case SYS_GETSOCKNAME:
+		case SYS_GETPEERNAME:
+			if(!get_user(alen, (int *)a[2]))
+			{
+				set_write_region(a[2], sizeof(int));
+				set_read_region(a[2], sizeof(int));
+				set_read_region(a[1], alen);
+			     } else{
+                             return (ARG(0)==SYS_ACCEPT)? -EINVAL : -EFAULT;
+			}
+			break;
+		case SYS_SOCKETPAIR:
+			set_read_region(a[3], 2 * sizeof(int));
+			break;
+		case SYS_SEND:
+			set_write_region(a[1], a[2]);
+			break;
+		case SYS_SENDTO:
+			set_write_region(a[1], a[2]);
+			set_write_region(a[4], a[5]);
+			break;
+		case SYS_RECV:
+			set_read_region(a[1], a[2]);
+			break;
+		case SYS_RECVFROM:
+			set_read_region(a[1], a[2]);
+			if(a[4] && !get_user(alen, (int *)a[5]))
+			{
+				set_write_region(a[5], sizeof(int));
+				set_read_region(a[5], sizeof(int));
+				set_read_region(a[4], alen);
+			}
+			break;
+		case SYS_SETSOCKOPT:
+			set_write_region(a[3], a[4]);
+			break;
+		case SYS_GETSOCKOPT:
+			if(!get_user(alen, (int *)a[4]))
+			{
+				set_write_region(a[4], sizeof(int));
+				set_read_region(a[4], sizeof(int));
+				set_read_region(a[3], alen);
+			}
+			break;
+		case SYS_SENDMSG:
+			if(copy_from_user(&hdr, (char *)a[1], sizeof(hdr)))
+				break;
+			set_write_region(a[1], sizeof(hdr));
+			if(hdr.msg_name)
+				set_write_region((unsigned long)hdr.msg_name, hdr.msg_namelen);
+			if(hdr.msg_controllen)
+				set_write_region((unsigned long)hdr.msg_control, hdr.msg_controllen);
+			if(hdr.msg_iovlen > 0)
+			{
+				set_write_region((unsigned long)hdr.msg_iov, hdr.msg_iovlen * sizeof(struct iovec));
+				if(hdr.msg_iovlen > 100)
+					hdr.msg_iovlen = 100;
+				for(i = 0 ; i < hdr.msg_iovlen &&
+					    !copy_from_user(&io, hdr.msg_iov + i,
+							    sizeof(io)) ; i++)
+					set_write_region((unsigned long)io.iov_base, io.iov_len);
+			}
+			break;
+		case SYS_RECVMSG:
+			if(copy_from_user(&hdr, (char *)a[1], sizeof(hdr)))
+				break;
+			set_write_region(a[1], sizeof(hdr));
+			set_read_region(a[1], sizeof(hdr));
+			if(hdr.msg_name)
+				set_read_region((unsigned long)hdr.msg_name, hdr.msg_namelen);
+			if(hdr.msg_control)
+				set_read_region((unsigned long)hdr.msg_control, hdr.msg_controllen);
+			if(hdr.msg_iovlen > 0)
+			{
+				set_write_region((unsigned long)hdr.msg_iov, hdr.msg_iovlen * sizeof(struct iovec));
+				if(hdr.msg_iovlen > 100)
+					hdr.msg_iovlen = 100;
+				for(i = 0 ; i < hdr.msg_iovlen &&
+					    !copy_from_user(&io, hdr.msg_iov + i,
+							    sizeof(io)) ; i++)
+					set_read_region((unsigned long)io.iov_base, io.iov_len);
+			}
+			break;
+		}
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_syslog(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_newstat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_newstat(char *, struct stat *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_newstat((char *)ARG(0), (struct stat *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct stat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_newlstat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_newlstat(char *, struct stat *);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_newlstat((char *)ARG(0),
+					(struct stat *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	set_read_region(ARG(1), sizeof(struct stat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_newfstat(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_newfstat(unsigned int, struct stat *);
+	unsigned int fd = ARG(0);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_newfstat(fd, (struct stat *)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), sizeof(struct stat));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_uname(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(struct old_utsname));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_wait4(int n, struct pt_regs regs)
+{
+	if(ARG(1))
+		set_read_region(ARG(1), sizeof(int));
+	if(ARG(3))
+		set_read_region(ARG(3), sizeof(struct rusage));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sysinfo(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(struct sysinfo));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_ipc(int n, struct pt_regs regs)
+{
+	int call = ARG(0) & 0xffff;
+	int version = ARG(0) >> 16;
+
+	switch (call)
+	{
+	case SEMOP:
+		set_write_region(ARG(4), ARG(2)*sizeof(struct sembuf));
+		break;
+	case SEMCTL: 
+	{
+		unsigned long fourth;
+		int arg3 = ARG(3);
+		ipc_parse_version(&arg3);
+
+		if(get_user(fourth, (unsigned long *)ARG(4)))
+			break;
+		set_read_region(ARG(4), sizeof(long));
+		switch(arg3)
+		{
+		case IPC_INFO:
+		case SEM_INFO:
+			set_read_region(fourth,
+					sizeof(struct seminfo));
+			break;
+		case IPC_STAT:
+		case SEM_STAT:
+			set_read_region(fourth,
+					sizeof(struct semid_ds));
+			break;
+		case IPC_SET:
+			set_write_region(fourth,
+					 sizeof(struct semid_ds));
+		case GETALL:
+			set_read_region(fourth,
+					SEMMNS * sizeof(ushort));
+			break;
+		case SETALL:
+			set_write_region(fourth,
+					 SEMMNS * sizeof(ushort));
+			break;
+		}
+		break;
+	}
+	case MSGSND:
+		set_write_region(ARG(4), sizeof(long) + ARG(2));
+		break;
+	case MSGRCV:
+		switch (version) {
+		case 0: {
+			struct ipc_kludge tmp;
+
+			if (!ARG(4))
+				break;
+			if (copy_from_user(&tmp,(struct ipc_kludge *)
+					   ARG(4), sizeof (tmp)))
+				break;
+			set_read_region(ARG(4), sizeof(tmp));
+			set_read_region((unsigned long)tmp.msgp,
+					sizeof(long) + ARG(2));
+		}
+			break;
+		case 1: default:
+			set_read_region(ARG(4), sizeof(long) + ARG(2));
+			break;
+		}
+		break;
+	case MSGGET:  /* added this so we can return -EINVAL in the default */
+		break;
+	case MSGCTL:
+		switch(ARG(2))
+		{
+		case IPC_INFO:
+		case MSG_INFO:
+			set_read_region(ARG(4),
+					sizeof(struct msginfo));
+			break;
+		case IPC_STAT:
+		case MSG_STAT:
+			set_read_region(ARG(4),
+					sizeof(struct msqid_ds));
+			break;
+		case IPC_SET:
+			set_write_region(ARG(4),
+					 sizeof(struct msqid_ds));
+			break;
+		}
+		break;
+	case SHMCTL:
+		switch(ARG(2))
+		{
+		case IPC_SET:
+			set_write_region(ARG(4),
+					 sizeof(struct shmid_ds));
+			break;
+		case IPC_INFO:
+			set_read_region(ARG(4),
+					sizeof(struct shminfo));
+			break;
+		case SHM_INFO:
+			set_read_region(ARG(4),
+					sizeof(struct shm_info));
+			break;
+		case SHM_STAT:
+			set_read_region(ARG(4),
+					sizeof(struct shmid_ds));
+			break;
+		case IPC_STAT:
+			set_read_region(ARG(4),
+					sizeof(struct shmid_ds));
+		}
+		break;
+		default:
+			return -EINVAL;
+	}
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_sigreturn(int n, struct pt_regs regs)
+{
+	set_write_region(regs.esp - 8, 732);
+	/* Eek, struct sigframe not defined outside arch/i386/kernel/signal.c */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_setdomainname(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), ARG(1));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_newuname(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(struct new_utsname));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_adjtimex(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(struct timex));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sigprocmask(int n, struct pt_regs regs)
+{
+	if(ARG(1))
+		set_write_region(ARG(1), sizeof(old_sigset_t));
+	if(ARG(2))
+		set_read_region(ARG(2), sizeof(old_sigset_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+unsigned long
+remote_sys_create_module(int n, struct pt_regs regs)
+{
+	set_file_name(0);	/* not really a file, but still a string */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_init_module(int n, struct pt_regs regs)
+{
+	set_file_name(0);	/* not really a file, but still a string */
+	set_write_region(ARG(1), sizeof(struct module) + 64);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_delete_module(int n, struct pt_regs regs)
+{
+	set_file_name(0);	/* not really a file, but still a string */
+	return(remote_standard_system_call(n, &regs));
+}
+
+void
+set_max_readable(unsigned long addr)
+{
+	struct vm_area_struct * vma;
+
+	vma = find_vma(current->mm, addr);
+	if (vma && (vma->vm_flags & VM_WRITE) && addr >= vma->vm_start)
+		set_read_region(addr, vma->vm_end - addr);
+}
+
+long
+remote_sys_get_kernel_syms(int n, struct pt_regs regs)
+{
+	set_max_readable(ARG(0));
+	return(remote_standard_system_call(n, &regs));
+}
+
+#ifdef CONFIG_QUOTA
+
+#ifdef CONFIG_QFMT_V2
+
+#define Q_COMP_GETQUOTA Q_V2_GETQUOTA
+#define Q_COMP_GETSTATS Q_V2_GETSTATS
+#define Q_COMP_SETQUOTA Q_V2_SETQUOTA
+#define Q_COMP_SETUSE Q_V2_SETUSE
+#define Q_COMP_SETQLIM Q_V2_SETQLIM
+typedef struct v2c_mem_dqblk comp_dqblk;
+typedef struct v2c_dqstats comp_dqstats;
+
+#else
+
+#define Q_COMP_GETQUOTA Q_V1_GETQUOTA
+#define Q_COMP_GETSTATS Q_V1_GETSTATS
+#define Q_COMP_SETQUOTA Q_V1_SETQUOTA
+#define Q_COMP_SETUSE Q_V1_SETUSE
+#define Q_COMP_SETQLIM Q_V1_SETQLIM
+typedef struct v1c_mem_dqblk comp_dqblk;
+typedef struct v1c_dqstats comp_dqstats;
+
+#endif /* CONFIG_QFMT_V2 */
+#endif /* CONFIG_QUOTA */
+
+long
+remote_sys_quotactl(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_QUOTA
+	set_file_name(1);
+	switch(ARG(0))
+	{
+	case Q_COMP_QUOTAON:
+		set_file_name(3);
+		break;
+	case Q_COMP_GETQUOTA:
+		set_read_region(ARG(3), sizeof(comp_dqblk));
+		break;
+	case Q_COMP_GETSTATS:
+		set_read_region(ARG(3), sizeof(comp_dqstats));
+		break;
+	case Q_COMP_SETQUOTA:
+	case Q_COMP_SETUSE:
+	case Q_COMP_SETQLIM:
+		set_write_region(ARG(3), sizeof(comp_dqblk));
+		break;
+	}
+#endif /* CONFIG_QUOTA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_bdflush(int n, struct pt_regs regs)
+{
+	if(ARG(0) >= 2 && !(ARG(0) & 1))
+		set_read_region(ARG(1), sizeof(int));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sysfs(int n, struct pt_regs regs)
+{
+	switch(ARG(0))
+	{
+		case 1:
+			set_file_name(1);
+			break;
+		case 2:
+			set_max_readable(2);
+			break;
+	}
+	return(remote_standard_system_call(n, &regs));
+}
+
+off_t
+remote_sys_lseek(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	off_t result;
+	extern asmlinkage off_t sys_lseek(unsigned int, off_t, unsigned int);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_lseek(fd, ARG(1), ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_llseek(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	long result;
+	extern long sys_llseek(unsigned int, unsigned long, unsigned long,
+		loff_t *, int);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_llseek(fd, ARG(1), ARG(2), (loff_t *)ARG(3),
+									ARG(4));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(3), sizeof(loff_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getdents(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	long result;
+	extern asmlinkage long sys_getdents(unsigned int, void *, unsigned int);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_getdents(fd, (void *)ARG(1), (unsigned int)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getdents64(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	long result;
+	extern asmlinkage long sys_getdents64(unsigned int, void *,
+								unsigned int);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_getdents64(fd, (void *)ARG(1),
+							(unsigned int)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_select(int n, struct pt_regs regs)
+{
+	set_select_regions(ARG(0), ARG(1), ARG(2), ARG(3), ARG(4));
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_readv(int n, struct pt_regs regs)
+{
+	int i, l = ARG(2);
+	struct iovec io;
+
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	ssize_t result;
+	extern asmlinkage ssize_t sys_readv(unsigned int, struct iovec*,
+								unsigned long);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_readv(fd, (struct iovec *)ARG(1),
+							(unsigned long)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	if(l > 0)
+		set_read_region(ARG(1), l * sizeof(struct iovec));
+	if(l > 100)
+		l = 100;	/* do not loop forever here */
+	for(i = 0 ; i < l &&
+		!copy_from_user(&io, ((struct iovec *)ARG(1)) + i, sizeof(io)) ;
+									i++)
+		set_read_region((unsigned long)io.iov_base, io.iov_len);
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_writev(int n, struct pt_regs regs)
+{
+	int i, l = ARG(2);
+	struct iovec io;
+
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	ssize_t result;
+	extern asmlinkage ssize_t sys_writev(unsigned int, struct iovec *,
+								unsigned long);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_writev(fd, (struct iovec *)ARG(1),
+							(unsigned long)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	if(l > 0)
+		set_read_region(ARG(1), l * sizeof(struct iovec));
+	if(l > 100)
+		l = 100;	/* do not loop forever here */
+	for(i = 0 ; i < l &&
+		!copy_from_user(&io, ((struct iovec *)ARG(1)) + i, sizeof(io)) ;
+									i++)
+		set_write_region((unsigned long)io.iov_base, io.iov_len);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sysctl(int n, struct pt_regs regs)
+{
+	struct __sysctl_args args;
+	int oldlen;
+
+	if(copy_from_user((char *)&args, (char *)ARG(0), sizeof(args)))
+		return(-EFAULT);
+	set_read_region(ARG(0), sizeof(args));
+	set_write_region((unsigned long)args.name, args.nlen);
+	if(args.oldval && args.oldlenp && !get_user(oldlen, args.oldlenp))
+	{
+		set_write_region((unsigned long)args.oldlenp, sizeof(int));
+		if(oldlen)
+		{
+			set_read_region((unsigned long)args.oldlenp, sizeof(int));
+			set_read_region((unsigned long)args.oldval, oldlen);
+		}
+	}
+	if(args.newval)
+		set_write_region((unsigned long)args.newval, args.newlen);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sched_setparam(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(1), sizeof(struct sched_param));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sched_getparam(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct sched_param));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sched_setscheduler(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(2), sizeof(struct sched_param));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sched_getscheduler(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(2), sizeof(struct sched_param));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_sched_rr_get_interval(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), sizeof(struct timespec));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_nanosleep(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(struct timespec));
+	set_read_region(ARG(1), sizeof(struct timespec));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getresuid(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(uid_t));
+	set_read_region(ARG(1), sizeof(uid_t));
+	set_read_region(ARG(2), sizeof(uid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getresuid16(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(old_uid_t));
+	set_read_region(ARG(1), sizeof(old_uid_t));
+	set_read_region(ARG(2), sizeof(old_uid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_query_module(int n, struct pt_regs regs)
+{
+	if(ARG(0))
+		set_file_name(0); /* not really a file, but still a string */
+	if(ARG(2))
+		set_read_region(ARG(2), ARG(3));
+	set_read_region(ARG(4), sizeof(size_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_poll(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), ARG(1) * sizeof(struct pollfd));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_nfsservctl(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(1), sizeof(struct nfsctl_arg));
+	set_write_region(ARG(2), sizeof(union nfsctl_res));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_getresgid(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(gid_t));
+	set_read_region(ARG(1), sizeof(gid_t));
+	set_read_region(ARG(2), sizeof(gid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_getresgid16(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(old_gid_t));
+	set_read_region(ARG(1), sizeof(old_gid_t));
+	set_read_region(ARG(2), sizeof(old_gid_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_rt_sigreturn(int n, struct pt_regs regs)
+{
+	set_write_region(regs.esp - 8, 892);
+	/*Eek,struct rt_sigframe not defined outside arch/i386/kernel/signal.c*/
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rt_sigaction(int n, struct pt_regs regs)
+{
+	if(ARG(1))
+		set_write_region(ARG(1), sizeof(struct k_sigaction));
+	if(ARG(2))
+		set_read_region(ARG(2), sizeof(struct k_sigaction));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rt_sigprocmask(int n, struct pt_regs regs)
+{
+	if(ARG(1))
+		set_write_region(ARG(1), sizeof(sigset_t));
+	if(ARG(2))
+		set_read_region(ARG(2), sizeof(sigset_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rt_sigpending(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(0), sizeof(sigset_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rt_sigtimewait(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(sigset_t));
+	if(ARG(1))
+		set_read_region(ARG(1), sizeof(siginfo_t));
+	if(ARG(2))
+		set_write_region(ARG(2), sizeof(struct timespec));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_rt_sigqueueinfo(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(2), sizeof(siginfo_t));
+	if(ARG(1))
+		set_read_region(ARG(1), sizeof(siginfo_t));
+	if(ARG(2))
+		set_write_region(ARG(2), sizeof(struct timespec));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_rt_sigsuspend(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(siginfo_t));
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_pread(int n, struct pt_regs regs)
+{
+	set_read_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_pwrite(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(1), ARG(2));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_chown(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_chown(const char *, uid_t, gid_t);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_chown((const char *)ARG(0), (uid_t)ARG(1),
+								(gid_t)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_chown16(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_chown16(const char *, old_uid_t, old_gid_t);
+
+	if(current->mosix.ttab && enter_remote_dfsa_mode())
+	{
+		result = sys_chown16((const char *)ARG(0), (uid_t)ARG(1),
+								(gid_t)ARG(2));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_file_name(0);
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_getcwd(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	long result;
+	extern asmlinkage long sys_getcwd(char *, unsigned long);
+
+	if(current->mosix.ttab && current->fs->pwd && enter_remote_dfsa_mode())
+	{
+		result = sys_getcwd((char *)ARG(0), (unsigned long)ARG(1));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	set_read_region(ARG(0), ARG(1));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_capget(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(struct __user_cap_header_struct));
+	set_read_region(ARG(1), sizeof(struct __user_cap_data_struct));
+	return(remote_standard_system_call(n, &regs));
+}
+
+long
+remote_sys_capset(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(struct __user_cap_header_struct));
+	set_write_region(ARG(1), sizeof(struct __user_cap_data_struct));
+	return(remote_standard_system_call(n, &regs));
+}
+
+int
+remote_sys_sigaltstack(int n, struct pt_regs regs)
+{
+	set_write_region(ARG(0), sizeof(struct sigaltstack));
+	set_read_region(ARG(1), sizeof(struct sigaltstack));
+	return(remote_standard_system_call(n, &regs));
+}
+
+ssize_t
+remote_sys_readahead(int n, struct pt_regs regs)
+{
+#ifdef CONFIG_MOSIX_DFSA
+	unsigned int fd = ARG(0);
+	ssize_t result;
+	extern asmlinkage ssize_t sys_readahead(unsigned int, loff_t, size_t);
+	struct task_struct *p = current;
+
+	if(fd >= p->files->max_fds)
+	{
+		if(p->mosix.ttab)
+			return(-EBADF);
+	}
+	else if(p->files->fd[fd] && enter_remote_dfsa_mode())
+	{
+		result = sys_readahead(fd, (loff_t)LARG(1), (size_t)ARG(3));
+		leave_remote_dfsa_mode();
+		if(RESULT_IS_FINAL(result))
+			return(result);
+	}
+#endif /* CONFIG_MOSIX_DFSA */
+	return(remote_standard_system_call(n, &regs));
+}
diff -Naur --exclude=CVS --exclude=configs linux/hpc/ucache.c linux-openmosix/hpc/ucache.c
--- linux/hpc/ucache.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/hpc/ucache.c	2002-12-03 06:16:46.000000000 +0100
@@ -0,0 +1,1452 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+/* needs adapting for ia64, especially pointer arithmetics */
+
+
+#include <linux/sched.h>
+#include <linux/hpc.h>
+#include <hpc/defs.h>
+#include <hpc/protocol.h>
+#include <hpc/comm.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <hpc/debug.h>
+#include <hpc/routines.h>
+#include <hpc/balance.h>
+
+#define	breakpoint1(x,a)	do {} while(0)
+#define	breakpoint(x)	breakpoint1(x, 0)
+
+#define	CACHE_ENTRIES	10
+
+struct cblock
+{
+	/*
+	 * DIRTY but useful NOTE: we actually rely on having at least 3
+	 * longwords before the data! (so don't make it less)
+         * in ohter words; don't change this
+	 */
+	unsigned long offset;
+	int len;
+	int count;
+	char data[1];
+};
+
+struct data_cache
+{
+	short first;			/* first entry in list, -1 = NONE */
+	short free;			/* first entry in freelist, -1 = NONE */
+	short next[CACHE_ENTRIES];	/* next on list of entries, -1=none */
+	short prev[CACHE_ENTRIES];	/* prev on list of entries, -1=none */
+	char type[CACHE_ENTRIES];	/* see below */
+	unsigned long addr[CACHE_ENTRIES];	/* start address */
+	unsigned long len[CACHE_ENTRIES];	/* end address */
+	struct cblock *bp[CACHE_ENTRIES]; /* where data (if any) is held */
+};
+
+/* types: */
+
+#define	WRITEABLE	1	/* data available from user to kernel */
+#define	WRITEDATA	2	/* data in cache from user to kernel */
+#define WRITE_STATUS	(WRITEABLE|WRITEDATA)	/* user ==> kernel */
+#define	READABLE	4	/* user address valid for reading */
+#define	READDATA	8	/* data for user cached */
+#define	READ_STATUS	(READABLE|READDATA)	/* kernel ==> user */
+#define	SKIP_MARK	16
+
+#define	END_MARK	(-1)
+
+#define	MAX_POSITIVE	0x7ffffffe	/* max value to return in *non_cache */
+#define	MAX_SEGMENT	32768
+#define	READ_SEND_THRESHOLD	MAX_SEGMENT
+
+extern char *pack_read_cache_data(int *);
+
+struct cblock *
+cblock_alloc(unsigned long offset, int len)
+{
+	struct cblock *cb;
+
+	if((cb = kmalloc(len + offsetof(struct cblock, data[0]), GFP_NOIO)))
+	{
+		cb->offset = offset;
+		cb->len = len;
+		cb->count = 1;
+	}
+	return(cb);
+}
+
+int
+alloc_ucache(void)
+{
+	struct mosix_task *m = &current->mosix;
+	register struct data_cache *d;
+	register unsigned int i;
+
+	if(!(d = m->ucache))
+	{ 
+		/* + * Specfic rules for how to decide which mem_flags to use:
+		 + *
+		 + *    - start_xmit, timeout, and receive methods of network drivers must
+		 + *      use GFP_ATOMIC (spinlock)
+		 + *    - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
+		 + *    - If you use a kernel thread with a network driver you must use
+		 + *      GFP_NOIO, unless b) or c) apply
+		 + *    - After you have done a down() you use GFP_KERNEL, unless b) or c)
+		 + *      apply or your are in a storage driver's block io path
+		 + *    - probe and disconnect use GFP_KERNEL unless b) or c) apply
+		 + *    - Changing firmware on a running storage or net device uses
+		 + *      GFP_NOIO, unless b) or c) apply. In this case we have to use NOIO */
+		m->ucache = kmalloc(sizeof (struct data_cache), GFP_NOIO);
+		if(!(d = m->ucache))
+			return(0);
+	}
+	/* on free list */
+	d->first = END_MARK;
+	d->free = 0;
+	for(i = 0 ; i < CACHE_ENTRIES ; i++)
+	{
+		d->next[i] = i+1;
+		d->prev[i] = i-1;
+		d->bp[i] = NULL;
+	}
+	d->next[CACHE_ENTRIES-1] = END_MARK;
+	d->prev[0] = END_MARK;
+	breakpoint("ucache allocated");
+	return(1);
+}
+
+inline void
+write_read_cache(struct data_cache *d, int ent)
+{
+	struct user_copy_h u;
+	register struct cblock *bp = d->bp[ent];
+	caddr_t from = &bp->data[d->addr[ent] - bp->offset];
+	int dflags = current->mosix.dflags;
+
+	breakpoint1("write_read_cache, entry %d", ent);
+	u.addr = (char *)d->addr[ent];
+	u.size = d->len[ent];
+	if(dflags & DDEPUTY)
+		comm_send(DEP_DATA_TO_USER, &u, sizeof(u), from, u.size, 0);
+	else if(!(dflags & DFINISHED))
+		copy_to_user(u.addr, from, u.size);
+}
+
+void
+free_ucache(void)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+	struct cblock *cb;
+
+	if(d)
+	{
+		breakpoint("free ucache");
+		for(i = d->first ; i != END_MARK ; i = d->next[i])
+		if((cb = d->bp[i]))
+		{
+			if(d->type[i] & READDATA)
+				write_read_cache(d, i);
+			if(--cb->count == 0)
+				kfree(cb);
+		}
+		kfree(d);
+		current->mosix.ucache = NULL;
+	}
+}
+
+int
+alloc_ucache_entry(struct data_cache *d, int after, int type,
+						unsigned long addr, int len)
+{
+	int ent = d->free;
+	int nex;
+
+	if(ent == END_MARK)
+		return(END_MARK);
+	d->free = d->next[ent];
+	if(d->free != END_MARK)
+		d->prev[d->free] = END_MARK;
+	d->type[ent] = type;
+	d->addr[ent] = addr;
+	d->len[ent] = len;
+	d->bp[ent] = NULL;
+	d->prev[ent] = after;
+	nex = d->next[ent] = (after == END_MARK) ? d->first : d->next[after];
+	if(after == END_MARK)
+		d->first = ent;
+	else
+		d->next[after] = ent;
+	if(nex != END_MARK)
+		d->prev[nex] = ent;
+	d->next[ent] = nex;
+	breakpoint1("allocated entry #%d", ent);
+	return(ent);
+}
+
+void
+free_ucache_entry(struct data_cache *d, int ent)
+{
+	struct cblock *cb;
+
+	if(ent == END_MARK)
+		return;
+	if(d->type[ent] & READDATA)
+		write_read_cache(d, ent);
+	if((cb = d->bp[ent]) && --cb->count == 0)
+		kfree(cb);
+	d->bp[ent] = NULL;
+
+	if(d->next[ent] != END_MARK)
+		d->prev[d->next[ent]] = d->prev[ent];
+	if(d->prev[ent] == END_MARK)
+		d->first = d->next[ent];
+	else
+		d->next[d->prev[ent]] = d->next[ent];
+	d->prev[ent] = END_MARK;
+	d->next[ent] = d->free;
+	d->free = ent;
+	breakpoint1("freed entry #%d", ent);
+}
+
+void
+data_was_read(struct data_cache *d, int ent)
+{
+	unsigned long beg, end;
+	int prev, next;
+	unsigned int newlen;
+	/*
+	 * The data from this entry was read and brought back to the REMOTE,
+	 * so it can be discarded - however, if this entry can bridge its
+	 * neighbours on both sides (a common case), it is even better to
+	 * do it and save 2 entries rather than 1!
+	 */
+	d->type[ent] &= ~(READDATA|WRITEDATA);
+	d->type[ent] |= READABLE;
+	if((prev = d->prev[ent]) != END_MARK &&
+		(next = d->next[ent]) != END_MARK &&
+		(d->type[prev] & ~SKIP_MARK) == d->type[ent] &&
+		(d->type[next] & ~SKIP_MARK) == d->type[ent] &&
+		d->bp[prev] == d->bp[ent] &&
+		d->bp[next] == d->bp[ent] &&
+		(beg = d->addr[ent]) == d->addr[prev] + d->len[prev] &&
+		(end = beg + d->len[ent]) == d->addr[next] &&
+		(newlen = end + d->len[next] - d->addr[prev]) <= MAX_POSITIVE)
+	{
+		breakpoint1("data_was_read: Joining around %d", ent);
+		free_ucache_entry(d, ent);
+		/* mostly one non-READDATA entry can have a SKIP_MARK */
+		if(d->type[next] & SKIP_MARK)
+		{
+			d->addr[next] = d->addr[prev];
+			d->len[next] = newlen;
+			free_ucache_entry(d, prev);
+		}
+		else
+		{
+			d->len[prev] = newlen;
+			free_ucache_entry(d, next);
+		}
+	}
+	else if(!(d->type[ent] & WRITEABLE))	/* still of a value... */
+		free_ucache_entry(d, ent);
+}
+
+/*
+ * Flush only the read-cache:
+ * 
+ * mostly, there is no more than one entry involved, so we use
+ * "write_read_cache" to send it back, but if there is more than one entry,
+ * all entries must be packed to minimize the number of communication packets
+ * (unless we are no longer DEPUTY - then we also use "write_read_cache").
+ *
+ * Any entry(ies) marked SKIP_MARK are not flushed.
+ */
+void
+flush_read_cache(void)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+	int j = 0;		/* only for the compiler's sake */
+	int n;
+	char *p;
+
+	if(!d)
+		return;
+	breakpoint("flushing read_cache");
+	if(!(current->mosix.dflags & DDEPUTY))
+	{
+		one_by_one:
+		for(i = d->first ; i != END_MARK ; i = d->next[i])
+		if((d->type[i] & (READDATA|SKIP_MARK)) == READDATA)
+		{
+			write_read_cache(d, i);
+			data_was_read(d, i);
+			goto one_by_one;	/* list may be scrambled */
+		}
+		breakpoint("read cache flushed one by one");
+		return;
+	}
+	for(n = 0 , i = d->first ; i != END_MARK ; i = d->next[i])
+	if((d->type[i] & (READDATA|SKIP_MARK)) == READDATA)
+	{
+		if(!n++)
+			j = i;
+	}
+	if(!n)
+	{
+		breakpoint("there was no read-cache to free");
+		return;
+	}
+	if(n == 1)
+	{
+		write_read_cache(d, j);
+		data_was_read(d, j);
+		breakpoint("there was only one read-cache to free");
+		return;
+	}
+	if((p = pack_read_cache_data(&n)))
+	{
+		comm_send(DEP_CACHE_READ_DATA, NULL, 0, p, n, 0);
+		kfree(p);
+		breakpoint("freed multiple read-cache entries");
+	}
+	else	/* no memory -- too bad: */
+		goto one_by_one;
+}
+
+/*
+ * free some entry except the one we are dealing with,
+ * obtaining at least one free entry.
+ * Because CACHE_ENTRIES > 1, there is ALWAYS SOMETHING to free,
+ * but priorities may apply
+ * (the lower, the dearer; the higher, the more disposable).
+ */
+void
+free_some_entry_except(struct data_cache *d, int not_this)
+{
+	register int i;
+	int pri = -1, p;
+	int e = END_MARK;
+	struct cblock *cb;
+	unsigned int n = 0;
+	unsigned int m = 0;
+
+	breakpoint1("free_some_entry_except #%d", not_this);
+	/*
+	 * first try to flush all complete READDATA entries:
+	 * if all the cblock was filled, all operations on that region were
+	 * very likely completed:
+	 */
+	for(i = d->first ; i != END_MARK ; i = d->next[i])
+	if(d->type[i] & READDATA)
+	{
+		m++;
+		if(i == not_this || d->addr[i] != (cb = d->bp[i])->offset ||
+			d->len[i] != cb->len)
+			d->type[i] |= SKIP_MARK;
+		else if(!n++)
+			e = i;
+	}
+	if(n == 1)
+	{
+		write_read_cache(d, e);
+		d->type[not_this] |= SKIP_MARK;	/* (even if not READDATA) */
+		data_was_read(d, e);
+	}
+	else if(n)	/* should be pretty rare, but still save on packets */
+		flush_read_cache();
+	if(m)
+	for(i = d->first ; i != END_MARK ; i = d->next[i])
+		d->type[i] &= ~SKIP_MARK;
+	if(d->free != END_MARK)
+		return;
+	again:
+	for(e = END_MARK , i = d->first ; i != END_MARK ; i = d->next[i])
+	if(i != not_this)
+	{
+		/* PRIORITY POLICY:
+		 * generally, WRITEDATA is more valuable than READDATA because it would
+		 * be a pity to lose the already existing data.
+		 * In both cases, the SHORTER the data the more valuable, because
+		 * the extra communication would cost more per-byte.
+		 * (remember that the data is incomplete within its cblock -
+		 * when complete, it can be joined with other entries)
+		 * Also, READABLE is more valuable than WRITEABLE because more
+		 * system-calls bring data to the user in tiny parts.
+		 * In both cases, the LONGER the data the more valuable, because we
+		 * have more helpful information.
+		 * Data segments are between 1-MAX_SEGMENT size
+		 * (READABLE|WRITEABLE can be more)
+		 * In the mixed cases (both data and pure information),
+		 * there is no easy way to evaluate, so we provide fixed values.
+		 */
+		switch(d->type[i])
+		{
+			/* throwing data - the shorter the dearer */
+		case READDATA:
+			p = MAX_SEGMENT/2 + 40 + d->len[i] / (MAX_SEGMENT / 10);
+			break;
+		case WRITEDATA:
+			p = MAX_SEGMENT/2 + 30 + d->len[i] / (MAX_SEGMENT / 10);
+			break;
+		case WRITEDATA|READDATA:
+			p = MAX_SEGMENT/2 + 20 + d->len[i] / (MAX_SEGMENT / 10);
+			break;
+			/* mixed case: hard, so just a fixed value: */
+		case READDATA|WRITEABLE:
+			p = MAX_SEGMENT/2 + 39;
+			break;
+		case WRITEDATA|READABLE:
+			p = MAX_SEGMENT/2 + 29;
+			break;
+			/* declaration only - the longer the more valuable: */
+		case WRITEABLE:
+			p = MAX_SEGMENT / d->len[i];
+			break;
+		case READABLE:
+			p = MAX_SEGMENT / (2 * d->len[i]);
+			break;
+		case READABLE|WRITEABLE:
+			p = MAX_SEGMENT * 2 / (3 * d->len[i]);
+			break;
+		default:
+			printk("free_some_entry_except: type %d encountered\n", d->type[i]);
+			p = 1;
+		}
+		if(!d->bp[i] || d->bp[i] != d->bp[not_this] ||
+		   d->addr[i] < d->addr[not_this])
+			p++;
+		if(p > pri)
+		{
+			pri = p;
+			e = i;
+		}
+	}
+	if(e == END_MARK)
+		panic("free_some_entry_except: none found");
+	if(d->type[e] & READDATA)
+	{
+		write_read_cache(d, e);
+		d->type[not_this] |= SKIP_MARK;
+		data_was_read(d, e);
+		d->type[not_this] &= ~SKIP_MARK;
+		if(d->free == END_MARK)
+			goto again;
+	}
+	else
+		free_ucache_entry(d, e);
+}	
+
+void
+split_ucache(int ent, unsigned long at, int back)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	int e2;
+	struct cblock *cb;
+
+	breakpoint1("split entry at %X", at);
+	if(d->free == END_MARK)
+		free_some_entry_except(d, ent);
+	if(back)
+	{
+		e2 = alloc_ucache_entry(d, d->prev[ent], d->type[ent],
+			d->addr[ent], at - d->addr[ent]);
+		d->len[ent] = d->addr[ent] + d->len[ent] - at;
+		d->addr[ent] = at;
+	}
+	else
+	{
+		e2 = alloc_ucache_entry(d, ent, d->type[ent], at,
+			d->addr[ent] + d->len[ent] - at);
+		d->len[ent] = at - d->addr[ent];
+	}
+	if((cb = d->bp[ent]))
+	{
+		d->bp[e2] = cb;
+		cb->count++;
+	}
+	breakpoint1("Split of Entry #%d Complete", ent);
+}
+
+int
+obtain_ucache_block(struct data_cache *d, int ent, unsigned long at)
+{
+	if(d->len[ent] > MAX_SEGMENT)
+	{
+		if(at - d->addr[ent] < MAX_SEGMENT)
+			split_ucache(ent, d->addr[ent] + MAX_SEGMENT, 0);
+		else if(at + MAX_SEGMENT >= d->addr[ent] + d->len[ent])
+			split_ucache(ent, (d->type[ent] & READABLE) ? at :
+				d->addr[ent] + d->len[ent] - MAX_SEGMENT, 1);
+		else
+		{
+			split_ucache(ent, at, 1);
+			split_ucache(ent, at + MAX_SEGMENT, 0);
+		}
+	}
+	return((d->bp[ent] = cblock_alloc(d->addr[ent], d->len[ent])) != NULL);
+}
+
+void
+flush_ucache(void)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register unsigned int i;
+	struct cblock *cb;
+
+	if(!d || d->first == END_MARK)
+		return;
+	breakpoint("flush_ucache");
+	if(!(current->mosix.dflags & DREMOTE)) /* save time - no READDATA */
+		flush_read_cache();
+	for(i = 0 ; i < CACHE_ENTRIES ; i++)
+	if((cb = d->bp[i]))
+	{
+		if(--cb->count == 0)
+			kfree(cb);
+		d->bp[i] = NULL;
+	}
+	for(i = 0 ; i < CACHE_ENTRIES ; i++)
+	{
+		d->next[i] = i+1;
+		d->prev[i] = i-1;
+	}
+	d->first = END_MARK;
+	d->free = 0;
+	d->next[CACHE_ENTRIES-1] = END_MARK;
+	d->prev[0] = END_MARK;
+}
+
+int
+ask_for_write_data(int ent)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	struct cblock *cb = d->bp[ent];
+	struct user_copy_h u;
+	int result;
+
+	breakpoint1("ask_for_write_data on entry #%d", ent);
+	u.addr = (char *)d->addr[ent];
+	u.size = d->len[ent];
+	u.verify = 0;	/* we wouldn't ask if we had no WRITEABLE! */
+	if(deputy_request(DEP_COPY_FROM_USER, &u, sizeof(u), NULL, 0, 0,
+		(void **)&result, -sizeof(result)))
+		return(0);
+	if(result)
+	{
+		comm_flushdata(COMM_ALLDATA);
+		return(0);
+	}
+	if(comm_copydata(&cb->data[d->addr[ent] - cb->offset], u.size, 0))
+		return(0);
+	d->type[ent] &= ~WRITE_STATUS;
+	d->type[ent] |= WRITEDATA;
+	return(1);
+}
+
+void
+try_to_merge_ucache(int ent)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	int o;
+	int t = d->type[ent];
+	struct cblock *cb = d->bp[ent];
+
+	if((o = d->prev[ent]) != END_MARK &&
+		d->type[o] == t && d->bp[o] == cb &&
+		d->addr[o] + d->len[o] == d->addr[ent] &&
+		d->len[ent] + d->len[o] <= MAX_POSITIVE)
+	{
+		d->addr[ent] = d->addr[o];
+		d->len[ent] += d->len[o];
+		d->type[o] &= ~READDATA;
+		free_ucache_entry(d, o);
+		breakpoint1("Merged #%d with previous", ent);
+	}
+	if((o = d->next[ent]) != END_MARK &&
+		d->type[o] == t && d->bp[o] == cb &&
+		d->addr[ent] + d->len[ent] == d->addr[o] &&
+		d->len[ent] + d->len[o] <= MAX_POSITIVE)
+	{
+		d->len[ent] += d->len[o];
+		d->type[o] &= ~READDATA;
+		free_ucache_entry(d, o);
+		breakpoint1("Merged #%d with next", ent);
+	}
+}
+
+inline int
+find_non_cached(struct data_cache *d, int types, unsigned int addr, int max)
+{
+	register int i;
+	int nc;
+
+	if(!max)
+		return(0);
+	breakpoint1("Finding non-cached from address %X", addr);
+	for(i = d->first ; i != END_MARK &&
+		(!(d->type[i] & types) || d->addr[i] + d->len[i] <= addr) ;
+		i = d->next[i])
+		;
+	if(i == END_MARK)
+		return(max);
+	if((nc = d->addr[i] - addr) > MAX_POSITIVE)
+		return(MAX_POSITIVE);
+	if(nc > max)
+		nc = max;
+	breakpoint1("non-cached=0x%X", nc);
+	return(nc);
+}
+
+int
+copy_from_cache(char *to, unsigned long from, int len, int *non_cache)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	int rlen = (len < 0 ? -len : len);
+	unsigned int orlen = rlen;
+	register int i;
+	struct cblock *cb;
+	char *cp;
+	int n;
+	int zero_found = 0;
+
+	if(!d)
+	{
+		none:
+		*non_cache = rlen;
+#ifdef WHY_NOT_CACHED
+if(ds_debug & DSDEB_NOTCACHED){printk("%X(%x) not in cache!",(int)from,rlen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+		return(0);
+	}
+	for(i = d->first ; i != END_MARK &&
+		(!(d->type[i] & (WRITE_STATUS|READDATA)) ||
+			d->addr[i] + d->len[i] <= from) ;
+		i = d->next[i])
+		;
+	if(i == END_MARK)
+		goto none;
+	if(d->addr[i] > from)
+	{
+		n = d->addr[i] - from;
+		if(((unsigned int)n) > orlen)
+			n = orlen;
+		*non_cache = n;
+		breakpoint1("copy_from_cache from 0x%X - way before cache", from);
+#ifdef WHY_NOT_CACHED
+if(ds_debug & DSDEB_NOTCACHED){printk("%X(%x) not in cache!",(int)from,rlen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+		return(0);
+	}
+	breakpoint1("copy_from_cache from 0x%X - something relevant", from);
+	if(!d->bp[i] && !obtain_ucache_block(d, i, from))
+	{
+		breakpoint("copy_from_cache: failed allocating a cblock");
+		free_ucache_entry(d, i);
+		*non_cache = find_non_cached(d, WRITE_STATUS|READDATA,
+								from, orlen);
+#ifdef WHY_NOT_CACHED
+if(ds_debug & DSDEB_NOTCACHED){printk("%X(%x) not in cache!",(int)from,rlen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+		return(0);
+	}
+	if(d->addr[i] + d->len[i] < from + rlen)
+		rlen = d->addr[i] + d->len[i] - from;
+	if(!(d->type[i] & (READDATA|WRITEDATA)) && !ask_for_write_data(i))
+	{
+		breakpoint1("Failed obtaining write-data for entry #%d", i);
+		free_ucache_entry(d, i);
+		rlen = 0;
+	}
+	else
+	{
+		breakpoint1("Fetching 0x%x bytes from cache", rlen);
+		cb = d->bp[i];
+		cp = &cb->data[from - cb->offset];
+		if(len > 0)
+			memcpy(to, cp, rlen);
+		else if(to) /* stop at 0, but include it */
+		{
+			for(n = 0 ; n < rlen ; n++)
+			if((*to++ = *cp++) == '\0')
+			{
+				n++;
+				zero_found = 1;
+				break;
+			}
+			rlen = n;
+		}
+		else	/* called from "strlen_cache" */
+		{
+			for(n = 0 ; n < rlen ; n++)
+			if(*cp++ == '\0')
+			{
+				n++;
+				zero_found = 1;
+				break;
+			}
+			rlen = n;
+		}
+		/* finally, can we rid or shorten this entry? */
+		if(d->type[i] == WRITEDATA &&
+			d->first == i && d->next[i] == END_MARK)
+			/* leave the poor single-entry alone -nothing to lose */
+			/* (some tty routines read TWICE) */
+				;
+		else if(d->type[i] & READ_STATUS)
+		{
+			if(from != d->addr[i])
+				split_ucache(i, from, 1);
+			if(len < d->len[i])
+				split_ucache(i, from + len, 0);
+			d->type[i] &= ~WRITEDATA;
+			if(!(d->type[i] & READDATA))
+			{
+				if(cb && --cb->count == 0)
+					kfree(cb);
+				d->bp[i] = NULL;
+			}
+			try_to_merge_ucache(i);
+			breakpoint1("some (or all) of block #%d was only left for reading", i);
+		}
+		else if(from == d->addr[i] && d->len[i] == rlen)
+		{
+			free_ucache_entry(d, i);
+			breakpoint1("All block #%d was consumed", i);
+		}
+		else
+		{
+			if(from == d->addr[i])
+			{
+				d->addr[i] += rlen;
+				d->len[i] -= rlen;
+			}
+			else if(from + rlen == d->addr[i] + d->len[i])
+				d->len[i] = from - d->addr[i];
+			breakpoint1("some of block #%d was consumed", i);
+		}
+	}
+	if(zero_found)
+	{
+		breakpoint("zero found");
+		*non_cache = -1;
+	}
+	else
+		*non_cache = find_non_cached(d, WRITE_STATUS|READDATA,
+						from+rlen, orlen - rlen);
+#ifdef WHY_NOT_CACHED
+if(*non_cache && !zero_found && (ds_debug & DSDEB_NOTCACHED)){printk("from %X(%x) not in cache!",(int)(from+rlen),orlen-rlen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+	return(rlen);
+}
+
+void
+check_whether_to_read_flush(void)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+	int l = 0, n = 0;
+	register struct cblock *cb;
+
+	for(i = d->first ; i != END_MARK ; i = d->next[i])
+	if(d->type[i] & READDATA)
+	{
+		cb = d->bp[i];
+		if(d->len[i] == cb->len && d->addr[i] == cb->offset)
+			l += cb->len;
+		else
+			n += cb->len;
+	}
+	else if(d->type[i] & READABLE)
+		n += d->len[i];
+	if(l >= READ_SEND_THRESHOLD && n >= READ_SEND_THRESHOLD)
+		flush_read_cache();
+}
+
+int
+copy_to_cache(unsigned long to, char *from, int len, int *non_cache)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	unsigned int olen = len;
+	register int i;
+	unsigned int lim;
+	struct cblock *cb;
+
+	if(!d)
+	{
+		none:
+		*non_cache = len;
+#ifdef WHY_NOT_CACHED
+if(ds_debug & DSDEB_NOTCACHED){printk("%X(%x) not in cache!",(int)to,olen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+		return(0);
+	}
+	for(i = d->first ; i != END_MARK &&
+		(!(d->type[i] & (READ_STATUS|WRITEDATA)) ||
+			d->addr[i] + d->len[i] <= to) ;
+		i = d->next[i])
+		;
+	if(i == END_MARK)
+		goto none;
+	if(d->addr[i] > to)
+	{
+		if(d->addr[i] - to > olen)
+			*non_cache = olen;
+		else
+			*non_cache = d->addr[i] - to;
+#ifdef WHY_NOT_CACHED
+if(ds_debug & DSDEB_NOTCACHED){printk("%X(%x) not in cache!",(int)to,olen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+		return(0);
+	}
+	breakpoint1("copy_to_cache from 0x%X - something relevant", to);
+	if(!d->bp[i] && !obtain_ucache_block(d, i, to))
+	{
+		breakpoint("copy_to_cache: failed allocating a cblock");
+		cant_do_it:
+		free_ucache_entry(d, i);
+		*non_cache = find_non_cached(d, READ_STATUS|WRITEDATA,
+								to, olen);
+		breakpoint1("cant_do_it: *non_cache=%d", *non_cache);
+#ifdef WHY_NOT_CACHED
+if(ds_debug & DSDEB_NOTCACHED){printk("%X(%x) not in cache!",(int)to,olen);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+		return(0);
+	}
+	if(d->addr[i] != to && !(d->type[i] & READDATA))
+		split_ucache(i, to, 1);
+	lim = d->addr[i] + d->len[i];
+	if(lim != to + len)
+	{
+		if(lim < to + len)
+			len = d->addr[i] + d->len[i] - to;
+		else if(!(d->type[i] & READDATA))
+			split_ucache(i, to + len, 0);
+	}
+	if(!(d->type[i] & READ_STATUS))
+	/* we have user-read permission but not user-write:
+	 * we did need to get thus far to minimize the data-loss,
+	 * but now we must discard this entry.
+	 */
+	{
+		breakpoint("copy_to_cache: Sorry Only read-permission");
+		goto cant_do_it;
+	}
+	breakpoint1("copy_to_cache: copying %d bytes", len);
+	cb = d->bp[i];
+	if(from)
+		memcpy(&cb->data[to - cb->offset], from, len);
+	else	/* called from zero_cache() */
+		memset(&cb->data[to - cb->offset], 0, len);
+	d->type[i] &= ~READ_STATUS;
+	d->type[i] |= READDATA;
+	try_to_merge_ucache(i);
+	if(d->addr[i] == cb->offset && d->len[i] == cb->len)
+		check_whether_to_read_flush();
+	*non_cache = find_non_cached(d, READ_STATUS|WRITEDATA, to + len,
+								olen - len);
+	breakpoint1("copy_to_cache: success, non_cache=%d", *non_cache);
+#ifdef WHY_NOT_CACHED
+if(*non_cache && (ds_debug & DSDEB_NOTCACHED)){printk("%X(%x) not in cache!",(int)(to+len),olen-len);mosix_panic("Why");}
+#endif /* WHY_NOT_CACHED */
+	return(len);
+}
+
+int
+zero_cache(char *to, int len, int *non_cache)
+{
+	return(copy_to_cache((unsigned long)to, NULL, len, non_cache));
+}
+
+int
+strlen_cache(char *addr, int *non_cache)
+{
+	return(copy_from_cache(NULL, (unsigned long)addr, -MAX_POSITIVE,
+								non_cache));
+}
+
+int
+all_in_cache(unsigned long addr, unsigned int size, int writeable)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+	unsigned int limit;
+
+	if(!d || addr + size < addr)	/* no cache or overflow */
+		return(0);
+	for(i = d->first ; i != END_MARK && d->addr[i] + d->len[i] < addr ;
+		i = d->next[i])
+			;
+	limit = addr + size;
+	for(; i != END_MARK ; i = d->next[i])
+	if(d->addr[i] > addr || (writeable && !(d->type[i] & READ_STATUS)))
+		return(0);
+	else if((addr = d->addr[i] + d->len[i]) >= limit)
+		return(1);
+	return(0);
+}
+
+int
+any_in_cache(unsigned long addr, unsigned int size)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+
+	if(!d || addr + size < addr)	/* no cache or overflow */
+		return(0);
+	for(i = d->first ; i != END_MARK && d->addr[i] < addr+size ;
+		i = d->next[i])
+	if(d->addr[i] + d->len[i] > addr &&
+		(d->type[i] & (READDATA|WRITEDATA)))
+		return(1);
+	return(0);
+}
+
+/*
+ * the following routine is only used in the first stage of preparing
+ * a cache, therefore "type" may only be "READABLE", "WRITEABLE", or both
+ * and so must be all entries already in the cache before the call.
+ * this is because its complexity is already enough as it is.
+ * If at some time in the future, new entries are to be produced after
+ * initialization, another routine must be used (or this one expanded).
+ *
+ * Also, note that for simplicity-sake, one of the entries, though very
+ * rare, could be merged to become over the size of MAX_POSITIVE,
+ * so this must be weeded-out later.
+ */
+void
+add_ucache_entry(unsigned long addr, int len, int type)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+	int n;
+	int prev;
+	unsigned long next_addr = 0;
+	unsigned long next_len = 0;
+	char msg[50];
+
+	sprintf(msg, "add_ucache_entry at 0x%X, len=0x%X", (int)addr, len);
+	breakpoint(msg);
+	if(len <= 0 || len > MAX_POSITIVE || addr + len < addr)
+		return;
+	if(!d)
+	{
+		if(alloc_ucache())
+			d = current->mosix.ucache;
+		else
+			return;
+	}
+	next_part:
+	for(prev = END_MARK , i = d->first ;
+		i != END_MARK && d->addr[i] + d->len[i] <= addr ;
+		prev = i , i = d->next[i])
+		;
+	if(i == END_MARK || d->addr[i] > addr + len)
+	{
+		/* no overlap, or even touching */
+		if(prev != END_MARK && d->type[prev] == type &&
+			d->addr[prev] + d->len[prev] == addr)
+			d->len[prev] += len;
+		else
+			alloc_ucache_entry(d, prev, type, addr, len);
+		goto all_done;
+	}
+	if(i != END_MARK && addr + len > d->addr[i] + d->len[i])
+	{
+		/* do some now, the rest later */
+		next_len = addr + len - (d->addr[i] + d->len[i]);
+		next_addr = d->addr[i] + d->len[i];
+		len = next_addr - addr;
+	}
+	if(prev != END_MARK && d->type[prev] == type &&
+		d->addr[prev] + d->len[prev] == addr)
+	{
+		/* increase previous entry */
+		if(i != END_MARK && addr + len >= d->addr[i])
+		{
+			n = d->addr[i] - addr;
+			addr = d->addr[i];
+			len -= n;
+			d->len[prev] += n;
+			try_to_merge_ucache(i);
+		}
+		else
+		{
+			d->len[prev] += len;
+			goto all_done;
+		}
+	}
+	if(i == END_MARK || d->addr[i] > addr + len)
+		alloc_ucache_entry(d, prev, type, addr, len);
+	else if(d->type[i] == type)
+	{
+		if(d->addr[i] > addr)
+		{
+			d->len[i] += d->addr[i] - addr;
+			d->addr[i] = addr;
+		}
+		/* else -- already included, nothing to do */
+	}
+	else if(d->type[i] == (READABLE|WRITEABLE) && d->addr[i] <= addr)
+		; /* nothing to do - already included */
+	else if(d->addr[i] == addr && d->len[i] == len)
+	{
+		d->type[i] |= type;
+		try_to_merge_ucache(i);
+	}
+	else if(d->addr[i] == addr)
+	{
+		split_ucache(i, addr + len, 0);	/* now "i"=new entry */
+		d->type[i] |= type;
+	}
+	else if(d->addr[i] > addr)
+	{
+		alloc_ucache_entry(d, prev, type, addr, d->addr[i] - addr);
+		if(d->addr[i] < addr + len)
+		{
+			if(addr + len < d->addr[i] + d->len[i])
+				split_ucache(i, addr + len, 0);
+			d->type[i] |= type;
+		}
+	}
+	else
+	{
+		split_ucache(i, addr, 1);
+		if(d->addr[i] + d->len[i] != addr + len)
+			split_ucache(i, addr + len, 0);
+		d->type[i] |= type;
+	}
+	if(next_len)
+	{
+		breakpoint1("adding split next segment of %d", next_len);
+		len = next_len;
+		addr = next_addr;
+		next_len = 0;
+		goto next_part;
+	}
+	all_done:
+	breakpoint("after add_ucache_entry");
+}
+
+int
+ucache_ok(unsigned long addr, unsigned long size, int mode)
+{
+	struct vm_area_struct * vma;
+	unsigned long pages;
+	int ok = 0;
+	unsigned int need;
+
+	if (!size || addr+size >= TASK_SIZE || addr+size < addr)
+		return(0);
+
+	down_read(&current->mm->mmap_sem);
+	if (!(vma = find_extend_vma(current->mm, addr)) ||
+							!(vma->vm_flags & mode))
+		goto out;
+	need = ((addr & ~PAGE_MASK) + size + PAGE_SIZE-1) >> PAGE_SHIFT;
+	addr &= PAGE_MASK;
+
+	while(1)
+	{
+		pages = (vma->vm_end - addr) >> PAGE_SHIFT;
+		if(need <= pages)
+			break;
+		need -= pages;
+		addr = vma->vm_end;
+		vma = vma->vm_next;
+		if (!vma || vma->vm_start != addr)
+			goto out;
+		if (!(vma->vm_flags & mode))
+			goto out;
+	}
+	ok = 1;
+	out:
+	up_read(&current->mm->mmap_sem);
+	return(ok);
+}
+
+
+void
+set_read_region(unsigned long addr, unsigned int len)
+{
+	if(!ucache_ok(addr, len, VM_WRITE))
+		return;
+	add_ucache_entry(addr, len, READABLE);
+}
+
+void
+set_write_region(unsigned long addr, unsigned int len)
+{
+	if(!ucache_ok(addr, len, VM_READ))
+		return;
+	add_ucache_entry(addr, len, WRITEABLE);
+}
+
+struct ucache_envelope_entry
+{
+	unsigned long addr;
+	unsigned int len;
+	short type;
+#if MAX_SEGMENT < 65536
+	unsigned short actual_len;
+#else
+	int actual_len;
+#endif
+};
+
+char *
+construct_ucache_envelope(int *len, int *from_user, struct syscall_h *s, char **tofree)
+{
+	int l, n;
+	register struct data_cache *d = current->mosix.ucache;
+	struct ucache_envelope_entry e[CACHE_ENTRIES];
+	register int i;
+	char *envelope, *ep;
+	int ent = END_MARK;	/* only to shut-up the compiler */
+	
+	*tofree = NULL;
+	*len = *from_user = s->simple_data_len = 0;
+	if(!d)
+		return(NULL);
+	rare_again:
+	for(l = n = 0 , i = d->first ; i != END_MARK ; i = d->next[i])
+	{
+		if(d->len[i] > MAX_POSITIVE)	/* rare indeed, but check */
+		{
+			split_ucache(i, d->addr[i] + MAX_POSITIVE, 0);
+			goto rare_again; /* because an entry could be lost */
+		}
+		l += sizeof(struct ucache_envelope_entry);
+		e[n].addr = d->addr[i];
+		e[n].len = d->len[i];
+		if((e[n].type = d->type[i]) & WRITEABLE)
+		{
+			e[n].actual_len = (d->len[i] > MAX_SEGMENT ?
+						MAX_SEGMENT : d->len[i]);
+			l += e[n].actual_len;
+		}
+		else
+			e[n].actual_len = 0;
+		if(!n++)
+		{
+			ent = i;
+			l += sizeof(int);
+		}
+	}
+	if(n == 1)
+	{
+		/* no need for package */
+		breakpoint1("construct_ucache_envelope: only one", l);
+		s->simple_data_addr = d->addr[ent];
+		s->simple_data_len = d->len[ent];
+		s->simple_data_type = d->type[ent];
+		if(d->type[ent] & WRITEABLE)
+		{
+			*from_user = 1;
+			if(s->simple_data_len >= MAX_SEGMENT)
+				*len = MAX_SEGMENT;
+			else
+				*len = s->simple_data_len;
+			s->simple_data_actual = *len;
+			ep = (char *)d->addr[ent];
+		}
+		else
+		{
+			ep = NULL;
+			s->simple_data_actual = 0;
+		}
+		flush_ucache();
+		return(ep);
+	}
+	if(!n || !(envelope = kmalloc(l, GFP_NOIO)))
+	{
+		if(n)
+			breakpoint1("construct_ucache_envelope: could not allocate %d bytes", l);
+		flush_ucache();
+		return(NULL);
+	}
+	*((int *)envelope) = n;
+	memcpy(envelope + sizeof(int), (caddr_t)e, n * sizeof(e[0]));
+	ep = envelope + sizeof(int) + n * sizeof(e[0]);
+	for(i = 0 ; i < n ; i++)
+	if(e[i].actual_len)
+	{
+		if(copy_from_user(ep, (char *)e[i].addr, e[i].actual_len))
+		{
+			/* must be a very serious problem, because area was
+			 * already checked, but could happen on a bad page,
+			 * or if disconnected from DEPUTY, anyway:
+			 */
+			kfree(envelope);
+			flush_ucache();
+			return(NULL);
+		}
+		ep += e[i].actual_len;
+	}
+	breakpoint1("construct_ucache_envelope: made %d bytes", l);
+	flush_ucache();
+	*len = l;
+	*tofree = envelope;
+	s->simple_data_len = -1;
+	return(envelope);
+}
+
+int
+open_ucache_envelope(struct syscall_h *s)
+{
+	int n;
+	register int i, j;
+	int ent;
+	struct ucache_envelope_entry e[CACHE_ENTRIES];
+	struct cblock *cb;
+	register struct data_cache *d;
+	struct mosix_task *m = &current->mosix;
+
+	if(!s->simple_data_len)
+		return(0);
+	if(!(d = m->ucache) && !(alloc_ucache()))
+	{
+		comm_flushdata(COMM_ALLDATA);
+		return(-ENOMEM);
+	}
+	d = m->ucache;
+	if(s->simple_data_len == -1)	/* complex */
+	{
+		if(comm_copydata(&n, sizeof(int), 0))
+		{
+			mosix_panic("open_ucache_envelope: no total");
+			return(-EDIST);
+		}
+		if(n < 1 || n > CACHE_ENTRIES)
+		{
+			printk("n in envelope = %d\n", n);
+			mosix_panic("bad n in envelope");
+			comm_flushdata(COMM_ALLDATA);
+			return(-EDIST);
+		}
+		if(comm_copydata(e, n * sizeof(e[0]), 0))
+		{
+			mosix_panic("open_ucache_envelope: non header");
+			return(-EDIST);
+		}
+	}
+	else
+	{
+		n = 1;
+		e[0].type = s->simple_data_type;
+		e[0].addr = s->simple_data_addr;
+		e[0].len = s->simple_data_len;
+		e[0].actual_len = s->simple_data_actual;
+	}
+	for(ent = END_MARK , i = 0 ; i < n ; i++)
+	       ent = alloc_ucache_entry(d, ent, e[i].type, e[i].addr, e[i].len);
+	for(i = 0 ; i < n ; i++)
+	if(e[i].actual_len)
+	{
+		if(!(cb = cblock_alloc(e[i].addr, e[i].actual_len)))
+		{
+			comm_flushdata(COMM_ALLDATA);
+			return(-ENOMEM);
+		}
+		if(comm_copydata(cb->data, e[i].actual_len, 0))
+		{
+			printk("open_ucache_envelope: copy failed\n");
+			kfree(cb);
+			return(-EDIST);
+		}
+		/* find all entries to share the block: */
+		for(j = d->first ; j != END_MARK ; j = d->next[j])
+		if(d->type[j] & WRITEABLE)
+		{
+			if(d->addr[j] >= e[i].addr + e[i].actual_len ||
+				d->addr[j] + d->len[j] <= e[i].addr)
+				continue;
+			if(d->addr[j] < e[i].addr)
+				split_ucache(j, e[i].addr, 1);
+			if(d->addr[j] + d->len[j] > e[i].addr + e[i].actual_len)
+				split_ucache(j, e[i].addr + e[i].actual_len, 0);
+			d->bp[j] = cb;
+			cb->count++;
+			d->type[j] &= ~WRITEABLE;
+			d->type[j] |= WRITEDATA;
+		}
+		if(--cb->count == 0)
+			kfree(cb);
+	}
+	breakpoint("opened_ucache_envelope");
+	return(0);
+}
+
+struct read_cache_header
+{
+	unsigned long addr;
+	unsigned int len;
+};
+
+/*
+ * Attempt to send the data directly whenever there is only one entry.
+ */
+char *
+deputy_pack_read_cache_data(int *len, struct syscall_ret_h *r, char **tofree)
+{
+	register struct data_cache *d = current->mosix.ucache;
+	register int i;
+	int f = END_MARK;
+	char *result;
+	struct cblock *cb;
+
+	*tofree = NULL;
+	*len = r->simple_data_len = 0;
+	if(!d || d->first == END_MARK)
+		return(NULL);
+	for(i = d->first ; i != END_MARK ; i = d->next[i])
+	if((d->type[i] & (READDATA|SKIP_MARK)) == READDATA)
+	{
+		if(f != END_MARK)
+		{
+			/* more than one entry - do it the long way */
+			result = pack_read_cache_data(len);
+			if(result)	/* (could still fail on memory) */
+			{
+				r->simple_data_len = -1;
+				*tofree = result;
+			}
+			flush_ucache();
+			return(result);
+		}
+		else
+			f = i;
+	}
+	if(f == END_MARK)
+	{
+		flush_ucache();
+		return(NULL);
+	}
+	/* OK: Just one READDATA entry "f" */
+	r->simple_data_addr = d->addr[f];
+	*len = r->simple_data_len = d->len[f];
+	cb = d->bp[f];
+	result = &cb->data[r->simple_data_addr - cb->offset];
+	d->bp[f] = NULL;
+	*tofree = (char *)cb;
+	d->type[f] &= ~(READDATA|WRITEDATA);
+	if(!(d->type[f] & WRITEABLE))
+		free_ucache_entry(d, f);
+	breakpoint1("deputy_pack_read_cache_data: One entry found/used (%d)",f);
+	flush_ucache();
+	return(result);
+}
+
+char *
+pack_read_cache_data(int *len)
+{
+	int l, n;
+	register struct data_cache *d = current->mosix.ucache;
+	struct read_cache_header e[CACHE_ENTRIES];
+	caddr_t from[CACHE_ENTRIES];
+	register int i;
+	char *package, *ep;
+	struct cblock *cb;
+	
+	if(!d || d->first == END_MARK)
+	{
+		*len = 0;
+		return(NULL);
+	}
+	for(l = n = 0 , i = d->first ; i != END_MARK ; i = d->next[i])
+	if((d->type[i] & (READDATA|SKIP_MARK)) == READDATA)
+	{
+		cb = d->bp[i];
+		from[n] = &cb->data[d->addr[i] - cb->offset];
+		e[n].addr = d->addr[i];
+		l += sizeof(e[0]) + (e[n].len = d->len[i]);
+		if(!n++)
+			l += sizeof(int);
+	}
+	if(!n || !(package = kmalloc(l, GFP_NOIO)))
+	{
+		breakpoint1("pack_read_cache_data: could not allocate %d bytes", l);
+		*len = 0;
+		return(NULL);
+	}
+	*((int *)package) = n;
+	memcpy(package + sizeof(int), (caddr_t)e, n * sizeof(e[0]));
+	ep = package + sizeof(int) + n * sizeof(e[0]);
+	for(i = 0 ; i < n ; i++)
+	{
+		memcpy(ep, from[i], e[i].len);
+		ep += e[i].len;
+	}
+	*len = l;
+	clear_readdata:
+	for(i = d->first ; i != END_MARK ; i = d->next[i])
+	if((d->type[i] & (READDATA|SKIP_MARK)) == READDATA)
+	{
+		data_was_read(d, i);
+		goto clear_readdata;	/* list may be scrambled */
+	}
+	breakpoint1("pack_read_cache_data: packed %d bytes", *len);
+	return(package);
+}
+
+int
+remote_unpack_read_cache_data(struct syscall_ret_h *r)
+{
+	register int i;
+	int l = 0, n;
+	struct read_cache_header e[CACHE_ENTRIES];
+
+	if(r && !r->simple_data_len)
+		return(0);
+	if(!r || r->simple_data_len == -1)
+	{
+		if(comm_copydata(&n, sizeof(int), 0))
+		{
+			mosix_panic("unpack_read_cache_data: no total");
+			return(-EDIST);
+		}
+		if(n < 1 || n > CACHE_ENTRIES)
+		{
+			printk("n in package = %d\n", n);
+			mosix_panic("bad n in package");
+			comm_flushdata(COMM_ALLDATA);
+			return(-EDIST);
+		}
+		if(comm_copydata(e, n * sizeof(e[0]), 0))
+		{
+			mosix_panic("open_ucache_envelope: non header");
+			return(-EDIST);
+		}
+		l = sizeof(int) + n * sizeof(e[0]);
+	}
+	else
+	{
+		n = 1;
+		e[0].addr = r->simple_data_addr;
+		e[0].len = r->simple_data_len;
+	}
+	for(i = 0 ; i < n ; i++)
+	if(comm_copydata((char *)e[i].addr, e[i].len, 1))
+	{
+		printk("unpack_cache_read_data: copy to user failed\n");
+		comm_flushdata(COMM_ALLDATA);
+		return(-EDIST);
+	}
+	else
+		l += e[i].len;
+	bump_copyout(l);
+	return(0);
+}
+
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-generic/smplock.h linux-openmosix/include/asm-generic/smplock.h
--- linux/include/asm-generic/smplock.h	2000-03-23 21:50:09.000000000 +0100
+++ linux-openmosix/include/asm-generic/smplock.h	2004-02-05 10:51:23.000000000 +0100
@@ -49,3 +49,24 @@
 	if (--current->lock_depth < 0)
 		spin_unlock(&kernel_flag);
 }
+
+#ifdef CONFIG_MOSIX
+
+/* the big MOSIX lock resembles the big kernel lock in the way it is
+ * allowed to be locked multiple times.  It is not allowed, however,
+ * to remain locked when entering "schedule".
+ */
+extern spinlock_t mosix_flag;
+
+extern __inline__ void lock_mosix(void)
+{
+	if (!++current->mosix.lock_depth)
+		spin_lock(&mosix_flag);
+}
+
+extern __inline__ void unlock_mosix(void)
+{
+	if (--current->mosix.lock_depth < 0)
+		spin_unlock(&mosix_flag);
+}
+#endif /* CONFIG_MOSIX */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/a.out.h linux-openmosix/include/asm-i386/a.out.h
--- linux/include/asm-i386/a.out.h	1995-06-16 20:33:06.000000000 +0200
+++ linux-openmosix/include/asm-i386/a.out.h	2004-02-05 10:51:24.000000000 +0100
@@ -21,6 +21,9 @@
 
 #define STACK_TOP	TASK_SIZE
 
+#ifdef CONFIG_MOSIX
+void aout_remote_init_mm(struct exec *);
+#endif /* CONFIG_MOSIX */
 #endif
 
 #endif /* __A_OUT_GNU_H__ */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/checksum.h linux-openmosix/include/asm-i386/checksum.h
--- linux/include/asm-i386/checksum.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/asm-i386/checksum.h	2004-02-05 10:51:24.000000000 +0100
@@ -1,6 +1,13 @@
 #ifndef _I386_CHECKSUM_H
 #define _I386_CHECKSUM_H
 
+#ifndef CONFIG_MOSIX
+#include <linux/config.h>
+#endif /* CONFIG_MOSIX */
+
+#ifdef CONFIG_MOSIX
+#include <asm/uaccess.h>
+#endif /* CONFIG_MOSIX */
 
 /*
  * computes the checksum of a memory block at buff, length len,
@@ -38,13 +45,29 @@
 unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
 					int len, int sum)
 {
+#ifdef CONFIG_MOSIX
+	if(!segment_eq(get_fs(), KERNEL_DS) &&
+		(((unsigned long)src) < PAGE_OFFSET ||
+		((unsigned long)dst) < PAGE_OFFSET))
+		panic("csum_partial_copy_nocheck, src=%x,dst=%x",(int)src,(int)dst);
+#endif /* CONFIG_MOSIX */
 	return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
 }
 
+#ifdef CONFIG_MOSIX
+extern unsigned int deputy_csum_partial_copy_from_user(const char *, char *, int, int, int *);
+extern unsigned int deputy_csum_partial_copy_to_user(const char *, char *, int, int, int *);
+#endif /* CONFIG_MOSIX */
+
 static __inline__
 unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
 						int len, int sum, int *err_ptr)
 {
+#ifdef CONFIG_MOSIX
+	if(memory_not_here(len, FROM_USER))
+		return(deputy_csum_partial_copy_from_user(src, dst, len,
+								sum, err_ptr));
+#endif /* CONFIG_MOSIX */
 	return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
 }
 
@@ -184,6 +207,11 @@
 static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
 				    int len, int sum, int *err_ptr)
 {
+#ifdef CONFIG_MOSIX
+	if(memory_not_here(len, FROM_USER))
+		return(deputy_csum_partial_copy_to_user(src, dst, len,
+								sum, err_ptr));
+#endif /* CONFIG_MOSIX */
 	if (access_ok(VERIFY_WRITE, dst, len))
 		return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
 
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/cpufeature.h linux-openmosix/include/asm-i386/cpufeature.h
--- linux/include/asm-i386/cpufeature.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/asm-i386/cpufeature.h	2004-02-05 10:51:24.000000000 +0100
@@ -101,6 +101,22 @@
 #define cpu_has_centaur_mcr	boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
 #define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE)
 
+#ifdef CONFIG_MOSIX
+#define	FBIT(feature)	(1 << ((feature) % 32))
+#define	USER_MODE_FEATURES0	(FBIT(X86_FEATURE_TSC)|FBIT(X86_FEATURE_CX8)|\
+				FBIT(X86_FEATURE_SEP)|FBIT(X86_FEATURE_CMOV)|\
+				FBIT(X86_FEATURE_MMX)|FBIT(X86_FEATURE_CLFLSH)|\
+				FBIT(X86_FEATURE_FXSR)|FBIT(X86_FEATURE_XMM)|\
+				FBIT(X86_FEATURE_XMM2))
+#define	USER_MODE_FEATURES1	(FBIT(X86_FEATURE_SYSCALL)|\
+				FBIT(X86_FEATURE_MMXEXT)|FBIT(X86_FEATURE_LM)|\
+				FBIT(X86_FEATURE_3DNOWEXT)|\
+				FBIT(X86_FEATURE_3DNOW))
+#define	USER_MODE_FEATURES2	0
+#define	USER_MODE_FEATURES3	(FBIT(X86_FEATURE_CXMMX))
+#define	USER_MODE_FEATURES	{ USER_MODE_FEATURES0, USER_MODE_FEATURES1, \
+				USER_MODE_FEATURES2, USER_MODE_FEATURES3 }
+#endif /* CONFIG_MOSIX */
 #endif /* __ASM_I386_CPUFEATURE_H */
 
 /* 
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/elf.h linux-openmosix/include/asm-i386/elf.h
--- linux/include/asm-i386/elf.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/asm-i386/elf.h	2004-02-05 10:51:24.000000000 +0100
@@ -41,6 +41,12 @@
    We might as well make sure everything else is cleared too (except for %esp),
    just to make things more deterministic.
  */
+#ifdef CONFIG_MOSIX
+#define	ELF_PLAT_INIT_REGS	(BIT_OF_REGISTER(ebx)|BIT_OF_REGISTER(ecx)|\
+				 BIT_OF_REGISTER(edx)|BIT_OF_REGISTER(esi)|\
+				 BIT_OF_REGISTER(edi)|BIT_OF_REGISTER(ebp)|\
+				 BIT_OF_REGISTER(eax))
+#endif /* CONFIG_MOSIX */
 #define ELF_PLAT_INIT(_r, load_addr)	do { \
 	_r->ebx = 0; _r->ecx = 0; _r->edx = 0; \
 	_r->esi = 0; _r->edi = 0; _r->ebp = 0; \
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/fcntl.h linux-openmosix/include/asm-i386/fcntl.h
--- linux/include/asm-i386/fcntl.h	2001-09-17 22:16:30.000000000 +0200
+++ linux-openmosix/include/asm-i386/fcntl.h	2004-02-05 10:51:24.000000000 +0100
@@ -21,6 +21,10 @@
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
 
+#ifdef CONFIG_MOSIX
+#define	O_NOWRITEACCESS	01000000 /* do not put_write_access() */
+#endif /* CONFIG_MOSIX */
+
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
 #define F_SETFD		2	/* set/clear close_on_exec */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/i387.h linux-openmosix/include/asm-i386/i387.h
--- linux/include/asm-i386/i387.h	2002-08-03 02:39:45.000000000 +0200
+++ linux-openmosix/include/asm-i386/i387.h	2004-02-05 10:51:24.000000000 +0100
@@ -86,4 +86,10 @@
 extern int dump_extended_fpu( struct pt_regs *regs,
 			      struct user_fxsr_struct *fpu );
 
+#ifdef CONFIG_MOSIX
+extern int has_fxsr(void);
+extern void fsave_to_fxsave(union i387_union *, union i387_union *);
+extern void fxsave_to_fsave(union i387_union *, union i387_union *);
+#endif /* CONFIG_MOSIX */
+
 #endif /* __ASM_I386_I387_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/processor.h linux-openmosix/include/asm-i386/processor.h
--- linux/include/asm-i386/processor.h	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/include/asm-i386/processor.h	2004-02-05 10:51:24.000000000 +0100
@@ -415,6 +415,12 @@
 	regs->esp = new_esp;					\
 } while (0)
 
+#ifdef CONFIG_MOSIX
+#define START_THREAD_REGS (BIT_OF_REGISTER(xds)|BIT_OF_REGISTER(xes)|\
+			   BIT_OF_REGISTER(xss)|BIT_OF_REGISTER(xcs)|\
+			   BIT_OF_REGISTER(eip)|BIT_OF_REGISTER(esp))
+#endif /* CONFIG_MOSIX */
+
 /* Forward declaration, a strange C thing */
 struct task_struct;
 struct mm_struct;
@@ -425,6 +431,10 @@
  * create a kernel thread without removing it from tasklists
  */
 extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+#ifdef CONFIG_MOSIX
+extern int arch_user_thread(int (*fn)(void *), void * arg, unsigned long flags);
+#endif /* CONFIG_MOSIX */
+
 
 /* Copy and release all segment info associated with a VM */
 extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
@@ -439,8 +449,13 @@
 }
 
 unsigned long get_wchan(struct task_struct *p);
+#ifdef CONFIG_MOSIX
+#define	KSTK_EIP(tsk)	(mos_to_regs(&(tsk)->mosix)->eip)
+#define	KSTK_ESP(tsk)	(mos_to_regs(&(tsk)->mosix)->esp)
+#else
 #define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
 #define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
+#endif /* CONFIG_MOSIX */
 
 #define THREAD_SIZE (2*PAGE_SIZE)
 #define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/rwsem.h linux-openmosix/include/asm-i386/rwsem.h
--- linux/include/asm-i386/rwsem.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/asm-i386/rwsem.h	2004-02-05 10:51:24.000000000 +0100
@@ -6,6 +6,8 @@
  *
  * Trylock by Brian Watson (Brian.J.Watson@compaq.com).
  *
+ * Trylock by Brian Watson 
+ * 
  *
  * The MSW of the count is the negated number of active writers and waiting
  * lockers, and the LSW is the total number of active locks
@@ -62,7 +64,7 @@
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 	spinlock_t		wait_lock;
 	struct list_head	wait_list;
-#if RWSEM_DEBUG
+#if RWSEM_DEBUG /* to be removed shortly */ 
 	int			debug;
 #endif
 };
@@ -73,7 +75,7 @@
 #if RWSEM_DEBUG
 #define __RWSEM_DEBUG_INIT      , 0
 #else
-#define __RWSEM_DEBUG_INIT	/* */
+#define __RWSEM_DEBUG_INIT	
 #endif
 
 #define __RWSEM_INITIALIZER(name) \
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/semaphore.h linux-openmosix/include/asm-i386/semaphore.h
--- linux/include/asm-i386/semaphore.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/asm-i386/semaphore.h	2004-02-05 10:51:24.000000000 +0100
@@ -159,6 +159,11 @@
 	return result;
 }
 
+#ifdef CONFIG_MOSIX
+/* do not be interrupted by signals, but still respond to MOSIX requests */
+extern void down_half_interruptible(struct semaphore *);
+#endif /* CONFIG_MOSIX */
+
 /*
  * Non-blockingly attempt to down() a semaphore.
  * Returns zero if we acquired it
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/siginfo.h linux-openmosix/include/asm-i386/siginfo.h
--- linux/include/asm-i386/siginfo.h	2002-08-03 02:39:45.000000000 +0200
+++ linux-openmosix/include/asm-i386/siginfo.h	2004-02-05 10:51:24.000000000 +0100
@@ -59,6 +59,12 @@
 			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
 			int _fd;
 		} _sigpoll;
+#ifdef CONFIG_MOSIX
+		struct {
+			int _newplace;
+			int _reason;
+		} _sigmig;
+#endif /* CONFIG_MOSIX */
 	} _sifields;
 } siginfo_t;
 
@@ -76,6 +82,10 @@
 #define si_addr		_sifields._sigfault._addr
 #define si_band		_sifields._sigpoll._band
 #define si_fd		_sifields._sigpoll._fd
+#ifdef CONFIG_MOSIX
+#define	si_newplace	_sifields._sigmig._newplace
+#define	si_reason	_sifields._sigmig._reason
+#endif /* CONFIG_MOSIX */
 
 #ifdef __KERNEL__
 #define __SI_MASK	0xffff0000
@@ -85,6 +95,9 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
+#ifdef CONFIG_MOSIX
+#define	__SI_MIGRATION	(6 << 16)
+#endif /* CONFIG_MOSIX */
 #define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
@@ -108,6 +121,9 @@
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 #define SI_TKILL	-6		/* sent by tkill system call */
+#ifdef CONFIG_MOSIX
+#define	SI_MIGRATION	0x100	        /* sent by migration */
+#endif /* CONFIG_MOSIX */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
@@ -182,6 +198,10 @@
 #define POLL_HUP	(__SI_POLL|6)	/* device disconnected */
 #define NSIGPOLL	6
 
+#ifdef CONFIG_MOSIX
+#define	SI_MIGRATED	(__SI_MIGRATION|1)	/* process migrated */
+#endif /* CONFIG_MOSIX */
+
 /*
  * sigevent definitions
  * 
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/smplock.h linux-openmosix/include/asm-i386/smplock.h
--- linux/include/asm-i386/smplock.h	2003-06-13 16:51:38.000000000 +0200
+++ linux-openmosix/include/asm-i386/smplock.h	2004-02-05 10:51:24.000000000 +0100
@@ -78,4 +78,27 @@
 #endif
 }
 
+#ifdef CONFIG_MOSIX
+
+/* the big MOSIX lock resembles the big kernel lock in the way it is
+    + * allowed to be locked multiple times.  It is not allowed, however,
+    + * to remain locked when entering "schedule".
+    + */
+extern spinlock_t mosix_flag;
+
+extern __inline__ void lock_mosix(void)
+{
+       if (!++current->mosix.lock_depth)
+		spin_lock(&mosix_flag);
+}
+
+extern __inline__ void unlock_mosix(void)
+{
+	if (current->mosix.lock_depth < 0)
+		BUG();
+	if (--current->mosix.lock_depth < 0)
+		spin_unlock(&mosix_flag);
+}
+#endif /* CONFIG_MOSIX */
+
 #endif /* __ASM_SMPLOCK_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/spinlock.h linux-openmosix/include/asm-i386/spinlock.h
--- linux/include/asm-i386/spinlock.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/asm-i386/spinlock.h	2004-02-05 10:51:24.000000000 +0100
@@ -209,4 +209,8 @@
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+#define can_read_lock(rw)	((rw)->lock > 0)
+#endif /* CONFIG_MOSIX */
+
 #endif /* __ASM_SPINLOCK_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/stat.h linux-openmosix/include/asm-i386/stat.h
--- linux/include/asm-i386/stat.h	2000-08-01 23:08:00.000000000 +0200
+++ linux-openmosix/include/asm-i386/stat.h	2004-02-05 10:51:24.000000000 +0100
@@ -75,4 +75,12 @@
 	unsigned long long	st_ino;
 };
 
+#ifdef CONFIG_MOSIX_FS
+
+/* more information about MFS: */
+#define STAT64_NODE(_x)		(*((short *)(&(_x).__pad0[2])))
+#define STAT64_ORIGDEV(_x)	(*((short *)(&(_x).__pad0[4])))
+#define STAT64_ORIGINO(_x)	(*((unsigned long *)(&(_x).__pad0[6])))
+
+#endif /* CONFIG_MOSIX_FS */
 #endif
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-i386/uaccess.h linux-openmosix/include/asm-i386/uaccess.h
--- linux/include/asm-i386/uaccess.h	2003-06-13 16:51:38.000000000 +0200
+++ linux-openmosix/include/asm-i386/uaccess.h	2004-02-05 10:51:24.000000000 +0100
@@ -32,6 +32,75 @@
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
+#ifdef CONFIG_MOSIX
+
+enum { FROM_USER, TO_USER };
+
+#define	COPY_COUNTER_MULTIPLIER	1024
+#define	COPY_COUNTER_SHIFT	10
+
+static inline void
+mosix_local_statistic(int __nb, int __dir)
+{
+	extern void cause_link_error_by_routine_that_does_not_exist(void);
+
+	if(__dir == TO_USER)
+	{
+#ifdef CONFIG_MOSIX_DFSA
+		if(current->mosix.dflags & DSTATSDOWN)
+			return;
+#endif /* CONFIG_MOSIX_DFSA */
+		current->mosix.ncopyouts += COPY_COUNTER_MULTIPLIER;
+		current->mosix.copyoutbytes += __nb;
+	}
+	else if(__dir == FROM_USER)
+	{
+#ifdef CONFIG_MOSIX_DFSA
+		if(current->mosix.dflags & DSTATSDOWN)
+		{
+			current->mosix.copy_ins++;
+			current->mosix.bytes_in += __nb;
+		}
+		else
+#endif /* CONFIG_MOSIX_DFSA */
+		{
+			current->mosix.ncopyins += COPY_COUNTER_MULTIPLIER;
+			current->mosix.copyinbytes += __nb;
+		}
+	}
+	else	/* impossible:  look here to fix gcc 3.x problems*/
+          /*   cause_link_error_by_routine_that_does_not_exist(); */
+	panic("openMosix: You should never get this message! (gcc problem)\n");
+}
+
+#define	USER_IS_REMOTE	((current->mosix.dflags & DDEPUTY) && \
+			 segment_eq(get_fs(), USER_DS))
+
+static inline int
+memory_not_here(int bytes, int direction)
+{
+	if(segment_eq(get_fs(), KERNEL_DS))
+		return(0);
+	switch(current->mosix.dflags & (DDEPUTY|DREMOTE))
+	{
+		case DDEPUTY:
+			return(1);
+		default:
+			mosix_local_statistic(bytes, direction);
+			/* fall thru */
+		case DREMOTE:
+			return(0);
+	}
+}
+
+extern unsigned long deputy_copy_from_user(void *, void *, unsigned long, int);
+extern unsigned long deputy_copy_to_user(void *, void *, unsigned long, int);
+extern unsigned long deputy_clear_user(void *, int, int);
+extern long deputy_strncpy_from_user(char *, char *, int, int);
+extern long deputy_strnlen_user(char *, long);
+extern int deputy_verify_write(void *, unsigned long);
+#endif /* CONFIG_MOSIX */
+
 extern int __verify_write(const void *, unsigned long);
 
 #define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
@@ -172,6 +241,23 @@
  * Returns zero on success, or -EFAULT on error.
  * On error, the variable @x is set to zero.
  */
+#ifdef CONFIG_MOSIX
+#define get_user(x,ptr)							\
+({	int __ret_gu,__val_gu;                                          \
+	if(memory_not_here(sizeof(*(ptr)),FROM_USER))                   \
+		__ret_gu = deputy_copy_from_user((void *)&__val_gu,     \
+			(void *)ptr, sizeof(*(ptr)), 1);                \
+	else                                                            \
+	switch(sizeof (*(ptr))) {                                       \
+	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;          \
+	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;          \
+	case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;          \
+	default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;          \
+	}                                                               \
+	(x) = (__typeof__(*(ptr)))__val_gu;                             \
+	__ret_gu;                                                       \
+})
+#else
 #define get_user(x,ptr)							\
 ({	int __ret_gu,__val_gu;						\
 	switch(sizeof (*(ptr))) {					\
@@ -183,6 +269,7 @@
 	(x) = (__typeof__(*(ptr)))__val_gu;				\
 	__ret_gu;							\
 })
+#endif /* CONFIG_MOSIX */
 
 extern void __put_user_1(void);
 extern void __put_user_2(void);
@@ -208,6 +295,36 @@
  *
  * Returns zero on success, or -EFAULT on error.
  */
+
+#ifdef CONFIG_MOSIX
+#define put_user(x,ptr)							\
+({	int __ret_pu;							\
+	if(memory_not_here(sizeof(*(ptr)),TO_USER)) {			\
+		__typeof__(*(ptr)) __val_pu = (__typeof__(*ptr)) x;	\
+		__ret_pu = deputy_copy_to_user((void *)ptr,		\
+			(void *)&__val_pu, sizeof(*(ptr)), 1); }	\
+	else								\
+		__ret_pu =						\
+  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)));	\
+	__ret_pu;							\
+})
+
+#define __get_user(x,ptr) \
+	(memory_not_here(sizeof(*(ptr)),FROM_USER) ?			\
+		({ int __ret_gu,__val_gu;				\
+		__ret_gu = deputy_copy_from_user((void *)&__val_gu,	\
+			(void *)(ptr), sizeof(*(ptr)), 0);		\
+		(x) = (__typeof__(*(ptr)))__val_gu;			\
+		__ret_gu; })						\
+	: __get_user_nocheck((x),(ptr),sizeof(*(ptr))))
+#define __put_user(x,ptr) \
+	(memory_not_here(sizeof(*ptr),TO_USER) ? ({			\
+		__typeof__(*(ptr)) __val_pu = (__typeof__(*ptr)) x;	\
+		deputy_copy_to_user((void *)(ptr),			\
+			(void *)&__val_pu, sizeof(*(ptr)), 0); })	\
+	: __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))))
+#else
+
 #define put_user(x,ptr)							\
   __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
@@ -257,6 +374,7 @@
  */
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#endif /* CONFIG_MOSIX */
 
 #define __put_user_nocheck(x,ptr,size)			\
 ({							\
@@ -708,6 +826,35 @@
  * Returns number of bytes that could not be copied.
  * On success, this will be zero.
  */
+#ifdef CONFIG_MOSIX
+#define copy_to_user(to,from,n)				\
+	(memory_not_here((n),TO_USER) ?			\
+		deputy_copy_to_user((to),(void *)(from),(n),1) : \
+	 __builtin_constant_p(n) ?			\
+	 __constant_copy_to_user((to),(from),(n)) :	\
+	 __generic_copy_to_user((to),(from),(n)))
+
+#define copy_from_user(to,from,n)			\
+	(memory_not_here((n),FROM_USER) ?		\
+		deputy_copy_from_user((to),(void *)(from),(n),1) : \
+	 __builtin_constant_p(n) ?			\
+	 __constant_copy_from_user((to),(from),(n)) :	\
+	 __generic_copy_from_user((to),(from),(n)))
+
+#define __copy_to_user(to,from,n)			\
+	 (memory_not_here((n),TO_USER) ?		\
+		deputy_copy_to_user((to),(void *)(from),(n),0) : \
+	 __builtin_constant_p(n) ?			\
+	 __constant_copy_to_user_nocheck((to),(from),(n)) :	\
+	 __generic_copy_to_user_nocheck((to),(from),(n)))
+
+#define __copy_from_user(to,from,n)			\
+	 (memory_not_here((n),FROM_USER) ?		\
+		deputy_copy_from_user((to),(void *)(from),(n),0) : \
+	 __builtin_constant_p(n) ?			\
+	 __constant_copy_from_user_nocheck((to),(from),(n)) :	\
+	 __generic_copy_from_user_nocheck((to),(from),(n)))
+#else
 #define copy_to_user(to,from,n)				\
 	(__builtin_constant_p(n) ?			\
 	 __constant_copy_to_user((to),(from),(n)) :	\
@@ -774,6 +921,7 @@
 	(__builtin_constant_p(n) ?			\
 	 __constant_copy_from_user_nocheck((to),(from),(n)) :	\
 	 __generic_copy_from_user_nocheck((to),(from),(n)))
+#endif /* CONFIG_MOSIX */
 
 long strncpy_from_user(char *dst, const char *src, long count);
 long __strncpy_from_user(char *dst, const char *src, long count);
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-ia64/offsets.h linux-openmosix/include/asm-ia64/offsets.h
--- linux/include/asm-ia64/offsets.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/asm-ia64/offsets.h	2002-11-30 10:51:12.000000000 +0100
@@ -0,0 +1,142 @@
+#ifndef _ASM_IA64_OFFSETS_H
+#define _ASM_IA64_OFFSETS_H
+/*
+ * DO NOT MODIFY
+ *
+ * This file was generated by arch/ia64/tools/print_offsets.awk.
+ *
+ */
+#define PT_PTRACED_BIT		0
+#define PT_TRACESYS_BIT		1
+#define IA64_TASK_SIZE			3424	/* 0xd60 */
+#define IA64_PT_REGS_SIZE		400	/* 0x190 */
+#define IA64_SWITCH_STACK_SIZE		560	/* 0x230 */
+#define IA64_SIGINFO_SIZE		128	/* 0x80 */
+#define IA64_CPU_SIZE			16384	/* 0x4000 */
+#define SIGFRAME_SIZE			2816	/* 0xb00 */
+#define UNW_FRAME_INFO_SIZE		448	/* 0x1c0 */
+
+#define IA64_TASK_PTRACE_OFFSET		48	/* 0x30 */
+#define IA64_TASK_SIGPENDING_OFFSET	16	/* 0x10 */
+#define IA64_TASK_NEED_RESCHED_OFFSET	40	/* 0x28 */
+#define IA64_TASK_PROCESSOR_OFFSET	96	/* 0x60 */
+#define IA64_TASK_THREAD_OFFSET		992	/* 0x3e0 */
+#define IA64_TASK_THREAD_KSP_OFFSET	992	/* 0x3e0 */
+#define IA64_TASK_PFM_OVFL_BLOCK_RESET_OFFSET 1616	/* 0x650 */
+#define IA64_TASK_PID_OFFSET		228	/* 0xe4 */
+#define IA64_TASK_MM_OFFSET		88	/* 0x58 */
+#define IA64_PT_REGS_CR_IPSR_OFFSET	0	/* 0x0 */
+#define IA64_PT_REGS_CR_IIP_OFFSET	8	/* 0x8 */
+#define IA64_PT_REGS_CR_IFS_OFFSET	16	/* 0x10 */
+#define IA64_PT_REGS_AR_UNAT_OFFSET	24	/* 0x18 */
+#define IA64_PT_REGS_AR_PFS_OFFSET	32	/* 0x20 */
+#define IA64_PT_REGS_AR_RSC_OFFSET	40	/* 0x28 */
+#define IA64_PT_REGS_AR_RNAT_OFFSET	48	/* 0x30 */
+#define IA64_PT_REGS_AR_BSPSTORE_OFFSET	56	/* 0x38 */
+#define IA64_PT_REGS_PR_OFFSET		64	/* 0x40 */
+#define IA64_PT_REGS_B6_OFFSET		72	/* 0x48 */
+#define IA64_PT_REGS_LOADRS_OFFSET	80	/* 0x50 */
+#define IA64_PT_REGS_R1_OFFSET		88	/* 0x58 */
+#define IA64_PT_REGS_R2_OFFSET		96	/* 0x60 */
+#define IA64_PT_REGS_R3_OFFSET		104	/* 0x68 */
+#define IA64_PT_REGS_R12_OFFSET		112	/* 0x70 */
+#define IA64_PT_REGS_R13_OFFSET		120	/* 0x78 */
+#define IA64_PT_REGS_R14_OFFSET		128	/* 0x80 */
+#define IA64_PT_REGS_R15_OFFSET		136	/* 0x88 */
+#define IA64_PT_REGS_R8_OFFSET		144	/* 0x90 */
+#define IA64_PT_REGS_R9_OFFSET		152	/* 0x98 */
+#define IA64_PT_REGS_R10_OFFSET		160	/* 0xa0 */
+#define IA64_PT_REGS_R11_OFFSET		168	/* 0xa8 */
+#define IA64_PT_REGS_R16_OFFSET		176	/* 0xb0 */
+#define IA64_PT_REGS_R17_OFFSET		184	/* 0xb8 */
+#define IA64_PT_REGS_R18_OFFSET		192	/* 0xc0 */
+#define IA64_PT_REGS_R19_OFFSET		200	/* 0xc8 */
+#define IA64_PT_REGS_R20_OFFSET		208	/* 0xd0 */
+#define IA64_PT_REGS_R21_OFFSET		216	/* 0xd8 */
+#define IA64_PT_REGS_R22_OFFSET		224	/* 0xe0 */
+#define IA64_PT_REGS_R23_OFFSET		232	/* 0xe8 */
+#define IA64_PT_REGS_R24_OFFSET		240	/* 0xf0 */
+#define IA64_PT_REGS_R25_OFFSET		248	/* 0xf8 */
+#define IA64_PT_REGS_R26_OFFSET		256	/* 0x100 */
+#define IA64_PT_REGS_R27_OFFSET		264	/* 0x108 */
+#define IA64_PT_REGS_R28_OFFSET		272	/* 0x110 */
+#define IA64_PT_REGS_R29_OFFSET		280	/* 0x118 */
+#define IA64_PT_REGS_R30_OFFSET		288	/* 0x120 */
+#define IA64_PT_REGS_R31_OFFSET		296	/* 0x128 */
+#define IA64_PT_REGS_AR_CCV_OFFSET	304	/* 0x130 */
+#define IA64_PT_REGS_AR_FPSR_OFFSET	312	/* 0x138 */
+#define IA64_PT_REGS_B0_OFFSET		320	/* 0x140 */
+#define IA64_PT_REGS_B7_OFFSET		328	/* 0x148 */
+#define IA64_PT_REGS_F6_OFFSET		336	/* 0x150 */
+#define IA64_PT_REGS_F7_OFFSET		352	/* 0x160 */
+#define IA64_PT_REGS_F8_OFFSET		368	/* 0x170 */
+#define IA64_PT_REGS_F9_OFFSET		384	/* 0x180 */
+#define IA64_SWITCH_STACK_CALLER_UNAT_OFFSET 0	/* 0x0 */
+#define IA64_SWITCH_STACK_AR_FPSR_OFFSET 8	/* 0x8 */
+#define IA64_SWITCH_STACK_F2_OFFSET	16	/* 0x10 */
+#define IA64_SWITCH_STACK_F3_OFFSET	32	/* 0x20 */
+#define IA64_SWITCH_STACK_F4_OFFSET	48	/* 0x30 */
+#define IA64_SWITCH_STACK_F5_OFFSET	64	/* 0x40 */
+#define IA64_SWITCH_STACK_F10_OFFSET	80	/* 0x50 */
+#define IA64_SWITCH_STACK_F11_OFFSET	96	/* 0x60 */
+#define IA64_SWITCH_STACK_F12_OFFSET	112	/* 0x70 */
+#define IA64_SWITCH_STACK_F13_OFFSET	128	/* 0x80 */
+#define IA64_SWITCH_STACK_F14_OFFSET	144	/* 0x90 */
+#define IA64_SWITCH_STACK_F15_OFFSET	160	/* 0xa0 */
+#define IA64_SWITCH_STACK_F16_OFFSET	176	/* 0xb0 */
+#define IA64_SWITCH_STACK_F17_OFFSET	192	/* 0xc0 */
+#define IA64_SWITCH_STACK_F18_OFFSET	208	/* 0xd0 */
+#define IA64_SWITCH_STACK_F19_OFFSET	224	/* 0xe0 */
+#define IA64_SWITCH_STACK_F20_OFFSET	240	/* 0xf0 */
+#define IA64_SWITCH_STACK_F21_OFFSET	256	/* 0x100 */
+#define IA64_SWITCH_STACK_F22_OFFSET	272	/* 0x110 */
+#define IA64_SWITCH_STACK_F23_OFFSET	288	/* 0x120 */
+#define IA64_SWITCH_STACK_F24_OFFSET	304	/* 0x130 */
+#define IA64_SWITCH_STACK_F25_OFFSET	320	/* 0x140 */
+#define IA64_SWITCH_STACK_F26_OFFSET	336	/* 0x150 */
+#define IA64_SWITCH_STACK_F27_OFFSET	352	/* 0x160 */
+#define IA64_SWITCH_STACK_F28_OFFSET	368	/* 0x170 */
+#define IA64_SWITCH_STACK_F29_OFFSET	384	/* 0x180 */
+#define IA64_SWITCH_STACK_F30_OFFSET	400	/* 0x190 */
+#define IA64_SWITCH_STACK_F31_OFFSET	416	/* 0x1a0 */
+#define IA64_SWITCH_STACK_R4_OFFSET	432	/* 0x1b0 */
+#define IA64_SWITCH_STACK_R5_OFFSET	440	/* 0x1b8 */
+#define IA64_SWITCH_STACK_R6_OFFSET	448	/* 0x1c0 */
+#define IA64_SWITCH_STACK_R7_OFFSET	456	/* 0x1c8 */
+#define IA64_SWITCH_STACK_B0_OFFSET	464	/* 0x1d0 */
+#define IA64_SWITCH_STACK_B1_OFFSET	472	/* 0x1d8 */
+#define IA64_SWITCH_STACK_B2_OFFSET	480	/* 0x1e0 */
+#define IA64_SWITCH_STACK_B3_OFFSET	488	/* 0x1e8 */
+#define IA64_SWITCH_STACK_B4_OFFSET	496	/* 0x1f0 */
+#define IA64_SWITCH_STACK_B5_OFFSET	504	/* 0x1f8 */
+#define IA64_SWITCH_STACK_AR_PFS_OFFSET	512	/* 0x200 */
+#define IA64_SWITCH_STACK_AR_LC_OFFSET	520	/* 0x208 */
+#define IA64_SWITCH_STACK_AR_UNAT_OFFSET 528	/* 0x210 */
+#define IA64_SWITCH_STACK_AR_RNAT_OFFSET 536	/* 0x218 */
+#define IA64_SWITCH_STACK_AR_BSPSTORE_OFFSET 544	/* 0x220 */
+#define IA64_SWITCH_STACK_PR_OFFSET	552	/* 0x228 */
+#define IA64_SIGCONTEXT_IP_OFFSET	40	/* 0x28 */
+#define IA64_SIGCONTEXT_AR_BSP_OFFSET	72	/* 0x48 */
+#define IA64_SIGCONTEXT_AR_FPSR_OFFSET	104	/* 0x68 */
+#define IA64_SIGCONTEXT_AR_RNAT_OFFSET	80	/* 0x50 */
+#define IA64_SIGCONTEXT_AR_UNAT_OFFSET	96	/* 0x60 */
+#define IA64_SIGCONTEXT_B0_OFFSET	136	/* 0x88 */
+#define IA64_SIGCONTEXT_CFM_OFFSET	48	/* 0x30 */
+#define IA64_SIGCONTEXT_FLAGS_OFFSET	0	/* 0x0 */
+#define IA64_SIGCONTEXT_FR6_OFFSET	560	/* 0x230 */
+#define IA64_SIGCONTEXT_PR_OFFSET	128	/* 0x80 */
+#define IA64_SIGCONTEXT_R12_OFFSET	296	/* 0x128 */
+#define IA64_SIGCONTEXT_RBS_BASE_OFFSET	2512	/* 0x9d0 */
+#define IA64_SIGCONTEXT_LOADRS_OFFSET	2520	/* 0x9d8 */
+#define IA64_SIGFRAME_ARG0_OFFSET	0	/* 0x0 */
+#define IA64_SIGFRAME_ARG1_OFFSET	8	/* 0x8 */
+#define IA64_SIGFRAME_ARG2_OFFSET	16	/* 0x10 */
+#define IA64_SIGFRAME_HANDLER_OFFSET	24	/* 0x18 */
+#define IA64_SIGFRAME_SIGCONTEXT_OFFSET	160	/* 0xa0 */
+#define IA64_CLONE_VFORK		16384	/* 0x4000 */
+#define IA64_CLONE_VM			256	/* 0x100 */
+#define IA64_CPU_IRQ_COUNT_OFFSET	0	/* 0x0 */
+#define IA64_CPU_BH_COUNT_OFFSET	4	/* 0x4 */
+#define IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET 12	/* 0xc */
+
+#endif /* _ASM_IA64_OFFSETS_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-ia64/sn/geo.h linux-openmosix/include/asm-ia64/sn/geo.h
--- linux/include/asm-ia64/sn/geo.h	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/include/asm-ia64/sn/geo.h	2004-02-05 10:51:25.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-ia64/sn/pci/pic.h linux-openmosix/include/asm-ia64/sn/pci/pic.h
--- linux/include/asm-ia64/sn/pci/pic.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/asm-ia64/sn/pci/pic.h	2004-02-05 10:51:25.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-ia64/sn/sn2/geo.h linux-openmosix/include/asm-ia64/sn/sn2/geo.h
--- linux/include/asm-ia64/sn/sn2/geo.h	2003-08-25 13:44:43.000000000 +0200
+++ linux-openmosix/include/asm-ia64/sn/sn2/geo.h	2004-02-05 10:51:26.000000000 +0100
@@ -1,4 +1,4 @@
-/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+/* $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-ppc64/syscall.h linux-openmosix/include/asm-ppc64/syscall.h
--- linux/include/asm-ppc64/syscall.h	2003-06-13 16:51:38.000000000 +0200
+++ linux-openmosix/include/asm-ppc64/syscall.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-#ifndef _ASM_SYSCALL_H
-#define _ASM_SYSCALL_H
-
-/*
- * Prototypes for architecture-specific Linux syscalls.
- */
-
-#endif /* _ASM_SYSCALL_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/asm-ppc64/systemcfg.h linux-openmosix/include/asm-ppc64/systemcfg.h
--- linux/include/asm-ppc64/systemcfg.h	2003-06-13 16:51:38.000000000 +0200
+++ linux-openmosix/include/asm-ppc64/systemcfg.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,101 +0,0 @@
-#ifndef _SYSTEMCFG_H
-#define _SYSTEMCFG_H
-
-/* 
- * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
- *
- * This program 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.
- */
-
-/* Change Activity:
- * 2002/09/30 : bergner  : Created
- * End Change Activity 
- */
-
-
-#ifndef __KERNEL__
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <linux/types.h>
-#endif
-
-/*
- * If the major version changes we are incompatible.
- * Minor version changes are a hint.
- */
-#define SYSTEMCFG_MAJOR 1
-#define SYSTEMCFG_MINOR 0
-
-struct systemcfg {
-	__u8  eye_catcher[16];		/* Eyecatcher: SYSTEMCFG:PPC64	0x00 */
-	struct {			/* Systemcfg version numbers	     */
-		__u32 major;		/* Major number			0x10 */
-		__u32 minor;		/* Minor number			0x14 */
-	} version;
-
-	__u32 platform;			/* Platform flags		0x18 */
-	__u32 processor;		/* Processor type		0x1C */
-	__u64 processorCount;		/* # of physical processors	0x20 */
-	__u64 physicalMemorySize;	/* Size of real memory(B)	0x28 */
-	__u64 tb_orig_stamp;		/* Timebase at boot		0x30 */
-	__u64 tb_ticks_per_sec;		/* Timebase tics / sec		0x38 */
-	__u64 tb_to_xs;			/* Inverse of TB to 2^20	0x40 */
-	__u64 stamp_xsec;		/*				0x48 */
-	__u64 tb_update_count;		/* Timebase atomicity ctr	0x50 */
-	__u32 tz_minuteswest;		/* Minutes west of Greenwich	0x58 */
-	__u32 tz_dsttime;		/* Type of dst correction	0x5C */
-	__u32 dCacheL1Size;		/* L1 d-cache size		0x60 */
-	__u32 dCacheL1LineSize;		/* L1 d-cache line size		0x64 */
-	__u32 iCacheL1Size;		/* L1 i-cache size		0x68 */
-	__u32 iCacheL1LineSize;		/* L1 i-cache line size		0x6C */
-	__u8  reserved0[3984];		/* Reserve rest of page		0x70 */
-};
-
-#ifdef __KERNEL__
-extern struct systemcfg *systemcfg;
-#else
-
-/* Processor Version Register (PVR) field extraction */
-#define PVR_VER(pvr)  (((pvr) >>  16) & 0xFFFF) /* Version field */
-#define PVR_REV(pvr)  (((pvr) >>   0) & 0xFFFF) /* Revison field */
-
-/* Processor Version Numbers */
-#define PV_NORTHSTAR    0x0033
-#define PV_PULSAR       0x0034
-#define PV_POWER4       0x0035
-#define PV_ICESTAR      0x0036
-#define PV_SSTAR        0x0037
-#define PV_POWER4p      0x0038
-#define PV_630          0x0040
-#define PV_630p         0x0041
-
-/* Platforms supported by PPC64 */
-#define PLATFORM_PSERIES      0x0100
-#define PLATFORM_PSERIES_LPAR 0x0101
-#define PLATFORM_ISERIES_LPAR 0x0201
-
-
-static inline volatile struct systemcfg *systemcfg_init(void)
-{
-	int fd = open("/proc/ppc64/systemcfg", O_RDONLY);
-	volatile struct systemcfg *ret;
-
-	if (fd == -1)
-		return 0;
-	ret = mmap(0, sizeof(struct systemcfg), PROT_READ, MAP_SHARED, fd, 0);
-	close(fd);
-	if (!ret)
-		return 0;
-	if (ret->version.major != SYSTEMCFG_MAJOR || ret->version.minor < SYSTEMCFG_MINOR) {
-		munmap((void *)ret, sizeof(struct systemcfg));
-		return 0;
-	}
-	return ret;
-}
-#endif /* __KERNEL__ */
-
-#endif /* _SYSTEMCFG_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/balance.h linux-openmosix/include/hpc/balance.h
--- linux/include/hpc/balance.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/balance.h	2004-04-06 21:19:41.000000000 +0200
@@ -0,0 +1,131 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#ifndef _MOSIX_BALANCE_H
+#define _MOSIX_BALANCE_H
+
+#ifdef __KERNEL__
+
+/* various tuning definitions: */
+#define	MAXKNOWNUP		45
+#define INFO_WIN		8
+#define	BALANCING_TIMEOUT	8
+
+struct loadinfo {
+	unsigned short pe;
+	unsigned short speed;	/* in SMP: of each CPU (not the total) */
+	unsigned long load;
+	unsigned short ncpus;
+	unsigned short util;	/* in SMP: max=MF*smp_num_cpus */
+	unsigned short status;
+	unsigned short free_slots;
+	unsigned int mem;
+	unsigned int rmem;
+	unsigned int tmem;
+	unsigned long load_limit; /* CONFIG_MOSIX_LOADLIMIT */
+	unsigned long loadremote; /* estimated totale load of remote processes */
+	unsigned long loadlocal;  /* estimated total load of local processes */
+	unsigned long llimitmode;
+	unsigned long cpu_limit;
+	unsigned long cpuremote;
+	unsigned long cpulocal;
+	unsigned long cpulimitmode;
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	struct opcost costs[MAX_MOSIX_TOPOLOGY];
+	struct mfs_cost mfscosts[MAX_MOSIX_TOPOLOGY];
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+};
+
+struct miginfo {
+	int aload;
+	unsigned long pages;
+	int deppe;
+	int remote;
+};
+
+struct infomsg {
+	long version;
+	int topology;
+	int serialno;
+	struct loadinfo load;
+};
+
+
+/* following is a multiple to be used for statistical values - primarily the
+ * number of system-calls.  Statistical values are counted in chunks of
+ * EVENT_COUNTER_VALUE, rather than simply 1, for the following two reasons:
+ * 1) to prevent being lost by decaying
+ * 2) making the contribution of a system-call to "iocounter" reflect its
+ *    impact, which is considerably more relative to 1-byte of I/O:
+ *    "iocounter" need not be accurate since it is only used to trigger
+ *    considerations for IOBALANCE migrations, but it is good to maintain
+ *    a power of 2 to prevent multiplications in "iocounter" computations.
+ */
+#define	EVENT_COUNTER_VALUE	1024
+#define	EVENT_COUNTER_SHIFT	10
+
+/* MDP constants: */
+#define	KEEP_FREE_PORTION	14	/* 1/16 of memory */
+#define	MAX_PAGES_TO_KEEP_FREE	(0x600000/PAGE_SIZE)	/* but no more than 6MB */
+#define	MIN_EXPECTED_PROC_SIZE	(0x80000/PAGE_SIZE)	/* when freeing memory, at least this */
+#define	MIN_MCHOOSE_AGAIN	1000000	/* youngest (RT) to mconsider */
+#define	MAX_MCHOOSE_AGAIN	4000000	/* no elder-advantage beyond this */
+#define	UTIL_TOLLERANCE		8/10	/* under this, sure trashing */
+#define	OLD_SECONDS		50	/* making an untouched page old changed from 60*/
+
+extern struct loadinfo loadinfo[INFO_WIN];
+
+extern int export_load;		/* load reported to other processors */
+extern int stable_export;	/* machine dependent stabilizing factor */
+extern unsigned acpuse;		/* accumulated cpu utilization */
+extern unsigned coming_in;	/* number of arriving processes */
+extern unsigned came_lately4;	/* processes that arrived lately (*4) */
+extern unsigned load_left;	/* load of processes that just left */
+extern int standard_speed;	/* yardstick */
+extern struct opcost deputy_here[MAX_MOSIX_TOPOLOGY]; /* DEPUTY I/O overheads here */
+extern struct opcost remote_here_adjusted[MAX_MOSIX_TOPOLOGY];
+#ifndef CONFIG_MOSIX_TOPOLOGY
+extern struct opcost remote_here;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+extern unsigned load_ticks;
+
+extern int pages_to_keep_free;	/* # of pages to attempt to keep free */
+extern int latest_free_mem;	/* in pages */
+
+extern rwlock_t loadinfo_lock;
+
+#define	BUMP_HEAD do { register struct mosix_task *m = &current->mosix; \
+			unsigned long oldcounter; int dobal; \
+			lock_mosix(); \
+			oldcounter = m->iocounter
+
+#define	BUMP_TAIL dobal = ((m->iocounter ^ oldcounter) & 0xfff00000) != 0; \
+			unlock_mosix(); \
+			if(dobal) { mosix_add_to_whereto(current, IOBALANCE); \
+				m->iocounter = 0; } \
+			} while(0)
+
+#define bump_statistics(s) BUMP_HEAD; \
+	m->s += EVENT_COUNTER_VALUE; \
+	m->iocounter += EVENT_COUNTER_VALUE; \
+	BUMP_TAIL
+#define	bump_statistic_amount(type,b) BUMP_HEAD; \
+	m->n##type##s += COPY_COUNTER_MULTIPLIER; \
+	m->type##bytes += b; \
+	m->iocounter += COPY_COUNTER_MULTIPLIER + b; \
+	BUMP_TAIL
+
+#define	bump_copyout(_n)	bump_statistic_amount(copyout,_n)
+#define	bump_copyin(_n)		bump_statistic_amount(copyin,_n)
+#define	bump_syscalls()		bump_statistics(nsyscalls)
+#define	bump_demandpages()	bump_statistics(ndemandpages)
+
+#endif /*__KERNEL__*/
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/comm.h linux-openmosix/include/hpc/comm.h
--- linux/include/hpc/comm.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/comm.h	2002-06-24 09:22:32.000000000 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Oren Laadan, Amnon Shiloh.
+ */
+
+/* interfacing the MOSIX communication package: */
+
+#ifndef _MOS_COMM_H
+#define _MOS_COMM_H
+
+#ifdef __KERNEL__
+
+struct mosix_link;			/* defined in hpc/comm.c */
+struct mosix_addr;			/* defined in include/hpc/protocol.h */
+struct mosix_task;
+typedef struct mosix_link mosix_link;
+typedef struct mosix_addr mosix_addr;
+
+/*
+ * values for mos# (e.g. in comm_open)
+ * 1..65535	-> valid mos# (mig)
+ * -1..-65535	-> valid mos# (info)
+ */
+
+#define COMM_TOADDR	(70001)
+#define COMM_ACCEPT	(70002)
+#define COMM_MIGD	(70003)
+#define COMM_INFO	(70004)
+#define	COMM_LOOSE	(70005)
+
+/*
+ * message flags:
+ * lower 16 bits used for message types (see hpc/protocol.h)
+ * next 8 bits used for message flags (see below)
+ * upper 8 bits used for mosix logging
+ */
+#define COMM_MFREGS	0x00800000
+#define COMM_MFDATA	0x00400000
+#define COMM_MFIDENT	0x00100000
+#ifdef CONFIG_MOSIX_DFSA
+#define	COMM_MFDFSA	0x00080000
+#define	COMM_MFNODFSA	0x00040000
+#define	COMM_MFDFSAOPTS	(COMM_MFDFSA|COMM_MFNODFSA)
+#endif /* CONFIG_MOSIX_DFSA */
+
+#define COMM_MFOPTIONS	0x00ff0000
+#define	COMM_MFHEADOPTS	(COMM_MFREGS|COMM_MFIDENT)
+
+#define	COMM_ZEROCOPYOK	0x40000000
+
+/*
+ * other flags
+ */
+#define COMM_ALLDATA	(-1)	/* copy/flush all available data */
+
+
+/*
+ * message format
+ */
+struct comm_header {
+	unsigned short olen;
+	unsigned short hlen;
+	int type;
+	int dlen;
+	int regs;
+	int dfsalen;
+};
+
+#define COMM_HLEN	(sizeof(struct comm_header))
+
+/*
+ * exported data
+ */
+extern int comm_type;
+extern unsigned long comm_remote_timo;
+extern unsigned long comm_connect_timo;
+extern unsigned long comm_reconn_timo;
+
+/*
+ * communication module interface
+ */
+
+extern void comm_startup(void);
+extern mosix_link *comm_open(int, mosix_addr *, unsigned long);
+extern mosix_link *comm_use(struct task_struct *, mosix_link *);
+extern void comm_close(mosix_link *);
+extern int comm_accept(mosix_link *,mosix_link **, mosix_addr *,unsigned long);
+extern int comm_send(int, void *, int, void *, int, int);
+extern int comm_recv(void **, int *);
+extern int comm_recvdata(void **);
+extern int comm_copydata(void *, int, int);
+extern int comm_hidedata(void);
+extern void comm_flushdata(int);
+extern void comm_free(void *);
+extern int comm_peek(void);
+extern int comm_wait(void);
+extern int comm_send_urgent(void);
+extern int comm_test_urgent(void);
+extern void comm_take_urgent(void);
+extern int comm_sendto(int, void *, int, mosix_link *, mosix_addr *);
+extern int comm_recvfrom(void *,int, mosix_link *, mosix_addr *, unsigned long);
+extern int comm_recvfrompe(void *,int, mosix_link *, int *, unsigned long);
+extern int net_to_mos(mosix_addr *);
+
+extern inline void comm_invalidate_address(mosix_addr *);
+extern void comm_migration_mode(int);
+extern int comm_getpeer(mosix_link *);
+extern void comm_init_linkpool(void);
+extern void comm_free_linkpool(void);
+extern mosix_link *comm_borrow_linkpool(void);
+extern void comm_return_linkpool(mosix_link *);
+extern void comm_age_linkpool(void);
+extern void rinode_flush_files(int);
+
+extern spinlock_t skown_lock;
+
+#endif /* __KERNEL__ */
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/debug.h linux-openmosix/include/hpc/debug.h
--- linux/include/hpc/debug.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/debug.h	2004-02-05 02:48:29.000000000 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Oren Laadan.
+ */
+
+#ifndef _MOS_DEBUG_H
+#define _MOS_DEBUG_H
+
+#ifdef CONFIG_MOSIX_DEBUG
+
+extern unsigned long ds_debug;
+
+#define DSDEB_ERROR	0x00000001
+#ifdef CONFIG_MOSIX_DFSA
+#define	DSDEB_DFSA	0x00000002
+#endif /* CONFIG_MOSIX_DFSA */
+#define DSDEB_MIG	0x00000010
+#define	DSDEB_EXPEL	0x00000020
+#define	DSDEB_HOLD	0x00000040
+#define	DSDEB_MIGSTAGE	0x00000080
+#define DSDEB_WHERETO	0x00000100
+#define DSDEB_INFO	0x00000200
+#define DSDEB_PROC	0x00000400
+#define	DSDEB_CACHE	0x00000800
+#define	DSDEB_CACHESTOP 0x00001000
+#define DSDEB_CONFIG	0x00002000
+#define	DSDEB_LOAD	0x00004000
+#define	DSDEB_CONSIDER	0x00008000
+#define	DSDEB_LOADS	0x00010000
+#define	DSDEB_ANCESSTOR	0x00020000
+#define	DSDEB_DECAY	0x00040000
+#define	DSDEB_MEM	0x00080000
+#define	DSDEB_NOTCACHED	0x00100000
+#define	DSDEB_SUPERMEM	0x00200000
+
+#define DSDEB_COMMOPEN	0x00400000
+#define DSDEB_COMMACPT	0x00800000
+#define DSDEB_COMMFLAGS	0x01000000
+#define DSDEB_COMMRECV	0x02000000
+#define DSDEB_COMMSEND	0x04000000
+#define DSDEB_COMMADDR	0x08000000
+#define	DSDEB_COMMDORECV 0x10000000
+#define	DSDEB_COMMDOSEND 0x20000000
+#define	DSDEB_DEBUGSEND	0x40000000
+
+
+#define DSDEB_COMM	(DSDEB_COMMOPEN|DSDEB_COMMACPT|DSDEB_COMMFLAGS|	\
+			 DSDEB_COMMRECV|DSDEB_COMMSEND|DSDEB_COMMADDR)
+
+#endif /* CONFIG_MOSIX_DEBUG */
+
+#define mosix_panic	panic
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/defs.h linux-openmosix/include/hpc/defs.h
--- linux/include/hpc/defs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/defs.h	2004-02-05 02:48:29.000000000 +0100
@@ -0,0 +1,121 @@
+/* All changes since  Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+/* all manners of independent variables and definitions required by the
+ * MOSIX package and possibly also by the MOSIX module itself:
+ */
+
+#ifndef _MOS_DEFS_H
+#define _MOS_DEFS_H
+
+extern int mosix_running;
+extern int active_cpus;
+
+extern spinlock_t whereto_lock;
+
+extern struct task_struct *mig_proc;
+extern int mig_daemon_active;
+extern struct task_struct *info_proc;
+extern int info_daemon_active;
+
+extern int slow_alpha, fast_alpha;	/* units over DECAY_QUOTIENT */
+extern int decay_interval;	/* in seconds */
+extern int mosadmin_gateways;	/* number of network segments (gateways) */
+extern int mosadmin_mode_stay;	/* no automatic migration out */
+extern int mosadmin_mode_lstay;	/* same just for local processes */
+extern int mosadmin_mode_block;	/* do not accept guests */
+extern int mosadmin_mode_quiet;	/* stop the load-chat (obsolete) */
+extern int mosadmin_mode_nomfs;	/* disallow MFS access to this node */
+extern char bootexpel, expel_progress;
+extern int latest_free_mem;
+
+extern struct task_struct *chosen_for_balance;
+extern struct task_struct *chosen_for_mdp;
+
+#define	STD_SPD		15000	  /* speed units of a standard processor */
+extern int cpuspeed;		  /* this node's relative processor speed */
+extern int standard_speed;	  /* if sysadmin changes standard-processor */
+extern int PE;			/* MOSIX number for this processor */
+extern int NPE;			/* number of configured MOSIX nodes */
+extern int MAXPE;		/* maximum MOSIX number in the cluster */
+
+#ifdef CONFIG_MOSIX_TOPOLOGY
+#if CONFIG_MOSIX_MAXTOPOLOGY > 10
+#warning MAXIMUM TOPOLOGY too big -- truncated to 10
+#define	MAX_MOSIX_TOPOLOGY	10
+#elif CONFIG_MOSIX_MAXTOPOLOGY < 2
+#warning MAXIMUM TOPOLOGY < 2 -- so why use it at all?
+#define	MAX_MOSIX_TOPOLOGY	1
+#else
+#define	MAX_MOSIX_TOPOLOGY	CONFIG_MOSIX_MAXTOPOLOGY
+#endif /* CONFIG_MOSIX_MAXTOPOLOGY */
+#else
+#define	MAX_MOSIX_TOPOLOGY	1
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+
+extern struct mosix_cost
+{
+	int PAGE_D, PAGE_R;
+	int SYSCALL_D, SYSCALL_R;
+	int COPYOUT_BASE_D, COPYOUT_PER_KB_D;
+	int COPYOUT_BASE_R, COPYOUT_PER_KB_R;
+	int COPYIN_BASE_D, COPYIN_PER_KB_D;
+	int COPYIN_BASE_R, COPYIN_PER_KB_R;
+	int MIGRATION_BASIC, MIGRATION_PER_PAGE;
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	int first, last;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+} mosix_cost[MAX_MOSIX_TOPOLOGY];
+
+extern struct mfs_cost
+{
+	int MFS_CONN_S, MFS_CONN_C;
+	int MFS_INKB_S, MFS_INKB_C;
+	int MFS_OUTKB_S, MFS_OUTKB_C;
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	int first, last;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+} mfs_cost[MAX_MOSIX_TOPOLOGY];
+
+extern struct opcost deputy_here[MAX_MOSIX_TOPOLOGY];
+
+#ifdef CONFIG_MOSIX_FS
+#define	MAX_MFS_STATNODES	10
+
+struct mfs_stats
+{
+	int nnodes;
+	unsigned short hint;
+	unsigned short nodes[MAX_MFS_STATNODES];
+	int64_t conns[MAX_MFS_STATNODES];
+	int64_t inbytes[MAX_MFS_STATNODES];
+	int64_t outbytes[MAX_MFS_STATNODES];
+};
+#else
+#define	MAX_MFS_STATNODES	0
+#endif /* CONFIG_MOSIX_FS */
+
+/* node-disconnection timeout: */
+#define	MOSIX_CONNECTION_KEEPALIVE_INTERVAL	30
+#define	MOSIX_CONNECTION_KEEPALIVE_MAXTRIES	6
+#define	MOSIX_CONNECTION_KEEPALIVE_TOTAL	150 /* changed from 180 */
+
+/* default slow decay brings process-statistics down to 10% in 3 minutes */
+/* default fast decay brings process-statistics down to 10% in 1 minute */
+
+#define	DEFAULT_DECAY_INTERVAL	2		/* seconds */
+#define	DEFAULT_SLOW_ALPHA	(DECAY_QUOTIENT * 975 / 1000)
+#define	DEFAULT_FAST_ALPHA	(DECAY_QUOTIENT * 926 / 1000)
+
+#define	MF	100		/* MOSIX frequency */
+
+#define	MILLION		1000000
+#define	DMILLION	1000000.0
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/dfsa.h linux-openmosix/include/hpc/dfsa.h
--- linux/include/hpc/dfsa.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/dfsa.h	2002-10-07 08:29:53.000000000 +0200
@@ -0,0 +1,61 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+
+
+#ifndef _MOS_DFSA_H
+#define _MOS_DFSA_H
+
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/dfsa_interface.h>
+
+#ifdef CONFIG_MOSIX_DFSA
+
+#define	MAXDFSAFS	8
+#define	MAXDFSALINKS	8
+#define	MAXDFSALINKLEN	128
+
+struct dfsatab
+{
+	unsigned short len;
+	char ndefs;
+	struct dfsdef
+	{
+		char defno;	/* mount=1-MAXDFSAFS, symlink>MAXDFSAFS */
+		char mounted;
+		short offset;
+	} dfsdef[0];
+};
+
+/* update flags (dupdates): */
+
+int dfsa_addlink(char *);
+int dfsa_dellink(char *);
+int dfsa_clearlinks(void);
+char *dfsa_showlinks(void);
+void dfsa_adapt(struct dfsatab *);
+int dfsa_sync(int);
+void dfsa_everyone_was_updated(void);
+void clear_dfsasync(void);
+void remote_clear_dfsa(void);
+void dfsa_tinit(void); 
+void deputy_resync_dfsa(void);
+char *deputy_pack_dfsa_changes(int *);
+void remote_unpack_dfsa_changes(char *);
+char *remote_pack_dfsa_changes(int *);
+void deputy_unpack_dfsa_changes(char *);
+void dfsa_check_comm_send(int *, char **, int *);
+void dfsa_comm_recv(int, char *);
+int enter_remote_dfsa_mode(void);
+void leave_remote_dfsa_mode(void);
+void dfsa_exit(void);
+void dfsa_verify(void); /* verify proper VFS registration */
+#endif
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/dscosts.h linux-openmosix/include/hpc/dscosts.h
--- linux/include/hpc/dscosts.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/dscosts.h	2002-06-24 09:22:32.000000000 +0200
@@ -0,0 +1,24 @@
+/* dscosts.h -- MOSIX */
+/* cost of remote operations (microseconds) */
+
+/* measuring date: Mon Apr 30 20:08:13 IDT 2001 */
+/* between two Pentium-III/1GHz over Ethernet-100 */
+
+#define	PAGE_COST_D	81
+#define	PAGE_COST_R	150
+
+#define	SYSCALL_COST_D	39
+#define	SYSCALL_COST_R	38
+
+#define	COPYOUT_COST_BASE_D	0
+#define	COPYOUT_COST_PER_KB_D	11
+#define	COPYOUT_COST_BASE_R	0
+#define	COPYOUT_COST_PER_KB_R	18
+
+#define	COPYIN_COST_BASE_D	0
+#define	COPYIN_COST_PER_KB_D	18
+#define	COPYIN_COST_BASE_R	0
+#define	COPYIN_COST_PER_KB_R	12
+
+#define	MIGRATION_COST_BASIC	8141
+#define	MIGRATION_COST_PER_PAGE	351
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/hpcctl.h linux-openmosix/include/hpc/hpcctl.h
--- linux/include/hpc/hpcctl.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/hpcctl.h	2004-04-06 21:19:41.000000000 +0200
@@ -0,0 +1,83 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar 
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Oren Laadan, Amnon Shiloh, Moshe Bar
+ */
+
+#ifndef _MOS_MOSCTL_H
+#define _MOS_MOSCTL_H
+
+#include <linux/types.h>
+
+/*
+ * MOSIX API
+ */
+
+/* migration requests via /proc/nnnnn/goto */
+
+#define DM_GOBACKHOME    0       /* just go back home */
+#define DM_BALANCE       (-1)    /* perform load balancing */
+
+
+/* constants for status report (/proc/mosix/nodes/nnn/status) */
+
+#define	DS_MOSIX_DEF	0x001
+#define DS_MOSIX_UP     0x002
+#define DS_STAY         0x004
+#define DS_LSTAY        0x008
+#define DS_BLOCK        0x010
+#define DS_QUIET        0x020
+#define DS_NOMFS        0x040
+
+
+/* constants for statictics decay */
+
+#define DADV_CPU        1       /* a pure CPU task */
+#define DADV_NOCPU      2       /* a non-computational task */
+#define DADV_NODECAY    3       /* task of a uniform mix of rapid changes */
+#define DADV_SLOWDECAY  4       /* task may change its nature over long run */
+#define DADV_FASTDECAY  5       /* task changes its nature frequently */
+#define DADV_OWNDECAY   6       /* task defined its own decay policy */
+
+#define DADV_POLICY     0x00F   /* policy mask */
+
+#define DADV_CLEAR      0x010   /* clear statistics: nature is changing */
+#define DADV_INHERIT    0x020   /* children of same nature */
+#define DADV_EXEC       0x040   /* maintain advice after exec */
+#define DADV_EXECONCE   0x080   /* maintain advice after only the next exec */
+#define DADV_NOINHERIT  0x100   /* cancel inheritance */
+#define DADV_NOEXEC     0x200   /* cancel advice on exec */
+#define DADV_NOEXECONCE 0x400   /* cancel DADV_EXECONCE */
+#define DADV_ENQUIRE    0x1000  /* enquire decay policy */
+
+#define DADV_DEFAULT    DADV_SLOWDECAY
+
+#define DECAY_QUOTIENT  1000    /* quotient for the "decay" argument */
+
+
+/* load information */
+
+struct mosix_info {
+        unsigned long load;
+	unsigned short speed;
+        unsigned short ncpus;
+        unsigned short util;
+        unsigned short status;
+	int64_t mem;
+	int64_t rmem;
+	int64_t tmem;
+ 	unsigned long load_limit; /* MOSIX_LOADLIMIT */
+ 	unsigned long llimitmode;
+ 	unsigned long loadremote;
+ 	unsigned long loadlocal;
+ 	unsigned long cpu_limit; /* MOSIX_LOADLIMIT */
+ 	unsigned long cpulimitmode;
+ 	unsigned long cpuremote;
+ 	unsigned long cpulocal;
+};
+
+#endif
+/* new proc entries after here */
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/hpctask.h linux-openmosix/include/hpc/hpctask.h
--- linux/include/hpc/hpctask.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/hpctask.h	2004-04-06 21:19:41.000000000 +0200
@@ -0,0 +1,351 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+
+#ifndef _LINUX_MOSIXTASK_H
+#define _LINUX_MOSIXTASK_H
+
+#include <hpc/defs.h>
+#include <hpc/comm.h>
+#include <hpc/debug.h>
+
+typedef long long now_t;
+#ifdef CONFIG_MOSIX_DFSA
+struct dfsatab;
+#endif /* CONFIG_MOSIX_DFSA */
+
+#ifdef CONFIG_MOSIX_FS
+struct dentry;
+struct mfs_stats;
+#endif /* CONFIG_MOSIX_FS */
+
+struct opcost
+{
+	int page, syscall, out, outkb, in, inkb;
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	int first, last;
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+};
+
+struct mosix_task
+{
+	volatile uint32_t dflags;	/* distributed (MOSIX) flags */
+	atomic_t dreqs;			/* bits that others may request */
+	/* following chars/bits should be in dflags, but modified within
+	 * interrupt code... if only the compiler generated single-instruction
+	 * codes for "|=" and "&=~" (but it doesn't) */
+	volatile char commpri;		/* prioririty for MOSIX communication */
+	volatile char ignoreoldsigs;	/* deliberately cleared ->sigpending */
+	volatile char catchme;		/* catch for debugging */
+
+	char hsleep_count;		/* count on DHEAVYSLEEP */
+	volatile int whereto;		/* migration request */
+	int lock_depth;			/* of the mosix_flag */
+	volatile uint32_t stay;		/* reasons why process must stay */
+	struct prequest *prequest;	/* requests to this task */
+	int whereami;			/* where the process is */
+	int deppe;			/* where the process came from */
+	volatile long bstate;		/* backed-up state while in MOSIX */
+	rwlock_t state_lock;		/* changes of bstate */
+	kernel_cap_t remote_caps;	/* effective capabilities on REMOTE */
+	struct held_files
+	{
+		struct file *f;		/* a file in use */
+		char denywrite;		/* whether holding i_writecount down */
+	} *held_files;			/* files held by remote VM */
+	int held_allocated;		/* # of entries in "held_inodes" */
+	struct mosix_link *contact;	/* DEPUTY <==> REMOTE connection */
+	struct task_struct *ancesstor;	/* nearest ancesstor when dependent */
+	uint32_t deputytime;		/* ticks spent on DEPUTY */
+	long last_sigxcpu;		/* last [prof] time SIGXCPU was sent */
+	int64_t passedtime;		/* time already passed to DEPUTY */
+	int64_t uttime;		/* time to add(REMOTE)/subtract(LOCAL) to/from
+				 * times->tms_utime for statistic purposes */
+	int64_t dctime;		/* decayed user-time (ms) */
+	int64_t cutime;		/* cummulative dependent-child user-time (ms) */
+	int64_t pagetime;	/* time waiting for free pages (ms) */
+	int64_t ndemandpages;	/* statistical # of demand pages */
+	int64_t nsyscalls;	/* statistical # of of syscalls */
+	int64_t ncopyouts;	/* statistical # of copying kernel to user */
+	int64_t copyoutbytes;	/* statsitical # of bytes to user */
+	int64_t ncopyins;	/* statistical # of copying user to kernel */
+	int64_t copyinbytes;	/* statistical # of bytes from user */
+	uint32_t iocounter;	/* combintaion of above statistics */
+	struct opcost depcost[MAX_MOSIX_TOPOLOGY]; /* costs on DEPUTY */
+	unsigned long  depspeed;		/* speed of DEPUTY */
+	int64_t last_consider;	/* user time since last considered migration */
+	now_t last_mconsider;	/* when last selected for memory-balancing */
+	unsigned short decsecs;	/* seconds within decay cycle */
+	unsigned short deccycle;/* length of decay cycle in seconds */
+	short decay;		/* decay factor (out of DECAY_QUOTIENT) */
+	unsigned char dpolicy;	/* statistic-collection policy */
+	char disclosure;	/* level of disclosure */
+	uint32_t asig;		/* signals arriving on REMOTE */
+	siginfo_t *forced_sigs;	/* REMOTE forced signals */
+	int nforced_sigs;	/* # of REMOTE forced signals */
+	int pages_i_bring;	/* # if pages still to be brought */
+	int rpagecredit;	/* # of expected remote page-faults */
+	int rfreepages;		/* # of mapped-pages to bring without penalty */
+	int page_allocs;	/* page allocation requests decaying counter */
+	short ran;		/* ticks running during last second */
+	unsigned short runstart;/* "load_ticks" (+1) since running */
+	int nmigs;		/* number of [successful] migrations - ever */
+	int load;		/* estimated contribution to load */
+	int sonpid;		/* pid of son in remote-fork */
+	int loadhere;		/* original local load */
+	int migpages;		/* # of migrating pages */
+	void *inexec;		/* structure while in "exec" */
+	wait_queue_head_t wait_dist;/* misc. wait for process */
+	unsigned long exit_mem;	/* memory on REMOTE when exited */
+	unsigned short deputy_regs; /* bit map of regs in charge of DEPUTY */
+	unsigned short pass_regs; /* bit map of regs to pass */
+	__u32 features[NCAPINTS]; /* CPU features on original node */
+	short mypid;		/* original PID */
+	short sigmig;		/* signal to receive on migration */
+	uint32_t *altregs;	/* place of registers when not on stack-top */
+	/* FIXME: these really needs to go inside altregs */
+	unsigned long altfs; /* fs segment register */
+	unsigned long altgs; /* gs segment register */
+	void *mosix_log;
+	struct data_cache *ucache;
+	char *ps;		/* common "ps" information */
+	struct mask
+	{	int miggroup;
+		int migpolicy;	/* the policy of migration condition */
+		uint32_t mignodes; /* list of nodes */
+	} mask;
+	int memused, memunused, memswapped;	/* memory split-up */
+	struct depinfo
+	{
+		pid_t pgrp;
+		pid_t session;
+		char comm[16];
+		pid_t tgid;
+	} depinfo;
+	unsigned int dirty_bits;	/* hidden bit-args to Linux routines */
+	unsigned int dirty_arg;		/* hidden argument to Linux routines */
+	pid_t sontgid;                  /* son tgid in remote-fork */
+	struct file *dirty_file;
+#ifdef CONFIG_MOSIX_DFSA
+	int copy_ins;
+	int bytes_in;
+	uint32_t dupdates;
+	struct dfsatab *ttab;
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+	int iget_mfs_pe;
+	unsigned long long iget_mfs_handle;
+	int selected;
+	int lastexec;
+	int lastmagic;
+	struct mfs_stats *mfs_stats;
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DIAG
+	int mig_page_count;
+#endif /* CONFIG_MOSIX_DIAG */
+#ifdef CONFIG_MOSIX_LOADLIMIT
+	long last_per_cpu_utime[NR_CPUS];
+	long last_per_cpu_stime[NR_CPUS];
+#endif
+};
+
+#ifdef CONFIG_MOSIX_DFSA
+#define	DFSA_INIT_TASK	/* All fields are 0, nothing to declare */
+#else
+#define DFSA_INIT_TASK
+#endif /* CONFIG_MOSIX_DFSA */
+
+#ifdef CONFIG_MOSIX_FS
+#define	MFS_INIT_TASK	/* All fields are 0, nothing to declare */
+#else
+#define	MFS_INIT_TASK
+#endif /* CONFIG_MOSIX_FS */
+
+#define MASK_INIT_TASK	/* All fields are 0, nothing to declare */
+
+/* only non-zero fields are mentioned: */
+#define MOSIX_INIT_TASK(tsk) mosix: { \
+	dreqs:		ATOMIC_INIT(0),		\
+	lock_depth:  	-1,			\
+	bstate:		TASK_SAME, 		\
+	wait_dist: 	__WAIT_QUEUE_HEAD_INITIALIZER(tsk.mosix.wait_dist), \
+	state_lock:	RW_LOCK_UNLOCKED,	\
+	disclosure:     CONFIG_MOSIX_DISCLOSURE, \
+	MASK_INIT_TASK \
+	DFSA_INIT_TASK \
+	MFS_INIT_TASK \
+}
+
+/*
+ * distributed flags (dflags) that are set only by the process itself,
+ * (but may be read by others):
+ * the following locks (in correct order of locking) are required to
+ * modify those bits:
+ *
+ * DINSCHED:		runqueue_lock
+ * DHEAVYSLEEP:		runqueue_lock
+ * DREMOTEDFSA:		runqueue_lock
+ * DPASSING:		runqueue_lock
+ * DINCOMING:		runqueue_lock
+ * DDEPUTY:		lock_mosix, tasklist_lock, runqueue_lock, task_lock
+ * DFINISHED:		lock_mosix, runqueue_lock, task_lock
+ * DPAGEIN:		runqueue_lock
+ * DSENTURGENT:		runqueue_lock
+ * DFAKESIGNAL:		sometimes sigmask_lock
+ */
+#define DDEPUTY		0x00000001	/* process is a DEPUTY stub */
+#define DREMOTE		0x00000002	/* process is running remotely */
+#define	DINSCHED	0x00000004	/* MOSIX task within "schedule" */
+#define DSYNC		0x00000008	/* remote process is synced and waits */
+#define DPSYNC		DSYNC		/* deputy must tell us to continue */
+#define DNESTED		0x00000010	/* nested requests from remote */
+#define	DSENTURGENT	0x00000020	/* REMOTE has already sent OOB */
+#define DINCOMING	0x00000040	/* process coming here */
+#define DPASSING	0x00000080	/* process is in migration */
+#define DPAGEIN		0x00000100	/* in pagein, considered running */
+#define DFINISHED	0x00000200	/* wants to become zombie */
+#define	DREMOTEDAEMON	0x00000400	/* set DREMOTE on "fork" */
+#define	DFAKESIGNAL	0x00000800	/* produce a fake signal */
+#define	DHEAVYSLEEP	0x00001000	/* prevent signals/events when asleep */
+#define	DTRACESYS1	0x00002000	/* PT_TRACESYS done before syscall */
+#define	DTRACESYS2	0x00004000	/* syscall done before 2nd PT_TRACESYS*/
+#define	DMUSTBEBACK	0x00008000	/* MUST arrive back home */
+#define	DDUMPABLE	0x00010000	/* copy of dumpable when DEPUTY */
+#define	DDELAYHELD	0x00020000	/* rebuild held_files later */
+#define DTDUMPABLE      0x00040000      /* copy of task_dumpable when DEPUTY */
+#define DMIGFILTER	0x00040000	/* process migration is conditioned */
+#ifdef CONFIG_MOSIX_DFSA
+#define	DSTATSDOWN	0x00800000	/* turn off local system-call stats */
+#define	DREMOTEDFSA	0x01000000	/* on REMOTE: within a DFSA syscall */
+#endif /* CONFIG_MOSIX_DFSA */
+
+/*
+ * bits in "dreqs" (anything that others can set):
+ */
+
+#define DREQ_NICECNG		0x00000001	/* priority changed */
+#define	DREQ_UPDOVERHEADS	0x00000002	/* update overheads */
+#define	DREQ_HOMEWAKE		0x00000004	/* wake when arrived home */
+#define	DREQ_CHECKCONF		0x00000008	/* check openMosix configuration */
+#define	DREQ_CHECKSTAY		0x00000010	/* check whether still stay */
+#define	DREQ_URGENT		0x00000020	/* something urgent (R=>D) */
+#define	DREQ_CAPCNG		0x00000040	/* capabilities changed */
+#define	DREQ_INFOCNG		0x00000080	/* disclosed info changed */
+#define	DREQ_FILEUNMAP		0x00000100	/* file(s) were unmapped */
+#ifdef CONFIG_MOSIX_DFSA
+#define	DREQ_NOTUPTODATE	0x10000000	/* send it all again */
+#define	DREQ_DFSASYNC		0x20000000	/* DFSA world changed */
+#define	DREQ_EXITDFSA		0x40000000	/* call DEPUTY ASAP */
+#else
+#define	DREQ_DFSASYNC		0
+#define	DREQ_EXITDFSA		0
+#endif /* CONFIG_MOSIX_DFSA */
+
+#define	tell_process(p,what)	atomic_set_mask(what,&(p)->mosix.dreqs)
+#define	process_ack(p,what)	atomic_clear_mask(what,&((p)->mosix.dreqs))
+#define	process_told(p,what)	(atomic_read(&((p)->mosix.dreqs)) & (what))
+
+/*
+ * reasons to stay:
+ */
+
+#define DSTAY_FOR_MONKEY 0x00000001	/* using monkey vnode */
+#define DSTAY_FOR_DEV	 0x00000002	/* mapping a device */
+#define DSTAY_FOR_86	 0x00000004	/* running in 86 mode */
+#define DSTAY_SYSTEM	0x00000008	/* system process (init, oM daemon) */
+#define DSTAY_FOR_PRIV	 0x00000010	/* privilleged inst. access (in/out) */
+#define DSTAY_FOR_MLOCK	 0x00000020	/* has locked memory */
+#define DSTAY_FOR_CLONE	 0x00000040	/* shared VM, eliminate this once DSM*/
+#define DSTAY_FOR_RT	 0x00000080	/* Real-Time scheduling */
+#define	DSTAY_FOR_IOPL	0x00000100	/* direct I/O permission */
+#define	DSTAY_FOR_KIOBUF 0x00000400	/* using kiobuf */
+#define	DSTAY_OTHER1	0x01000000	/* external reason for stay (1) */
+#define	DSTAY_OTHER2	0x02000000	/* external reason for stay (2) */
+#define	DSTAY_OTHER3	0x04000000	/* external reason for stay (3) */
+#define	DSTAY_OTHER4	0x08000000	/* external reason for stay (4) */
+#define DNOMIGRATE	0x80000000	/* user requested no auto-migrations */
+
+#define DSTAY   (~DNOMIGRATE)
+#define	DSTAY_PER_MM	(DSTAY_FOR_MONKEY|DSTAY_FOR_DEV|DSTAY_FOR_MLOCK|DSTAY_FOR_KIOBUF)
+
+/*
+ * where to go (whereto)
+ */
+#define GOBACKHOME	(-1)	/* just go back home */
+#define BALANCE		(-2)	/* perform load balancing */
+#define IOBALANCE	(-3)	/* perform load balancing for I/O */
+#define MEMBALANCE	(-4)	/* perform balancing for memory */
+#define	MFSBALANCE	(-5)	/* must go back home */
+#define	MUSTGOHOME	(-6)	/* must go back home */
+
+#define	evaluate_pending_signals_in_mosix_context() do { \
+	struct task_struct *p = current; \
+	unsigned long flags; \
+	spin_lock_irqsave(&p->sigmask_lock,flags);\
+	if(p->mosix.ignoreoldsigs) \
+		p->sigpending = (p->mosix.dflags & (DFAKESIGNAL|DHEAVYSLEEP)) == DFAKESIGNAL; \
+	else recalc_sigpending(p); \
+	spin_unlock_irqrestore(&p->sigmask_lock,flags); \
+	} while(0)
+
+#define	deeper_sleep() do { \
+	struct task_struct *p = current; \
+	if(!p->mosix.hsleep_count++) { \
+		unsigned long flags; \
+		spin_lock_irq(&runqueue_lock); \
+		p->mosix.dflags |= DHEAVYSLEEP; \
+		spin_unlock_irq(&runqueue_lock); \
+		spin_lock_irqsave(&p->sigmask_lock,flags); \
+		p->sigpending = 0; \
+		spin_unlock_irqrestore(&p->sigmask_lock,flags); \
+	} } while(0)
+
+#define	lighter_sleep() do { \
+	struct task_struct *p = current; \
+	if(!--p->mosix.hsleep_count) { \
+		spin_lock_irq(&runqueue_lock); \
+		p->mosix.dflags &= ~DHEAVYSLEEP; \
+		spin_unlock_irq(&runqueue_lock); \
+		evaluate_pending_signals_in_mosix_context(); \
+	} } while(0)
+
+#define	set_me_dumpable(on) do { \
+		if((on)) { \
+                   current->task_dumpable = (on); \
+                   if(current->mm) current->mm->dumpable = (on); \
+                   else current->mosix.dflags |= (DDUMPABLE|DTDUMPABLE); \
+                } else { \
+		   if(current->mm) current->mm->dumpable = (on); \
+                   else current->mosix.dflags &= ~(DDUMPABLE); \
+                } \
+	} while(0)
+
+#define	i_am_dumpable()	((current->mosix.dflags & DDEPUTY) ? \
+	((current->mosix.dflags & DDUMPABLE) != 0 && \
+        (current->mosix.dflags & DTDUMPABLE) != 0) : \
+	(current->task_dumpable && (current->mm ? current->mm->dumpable : 0)))
+
+/* dirty parameters: */
+/* sorry we are not allowed to add parameters to standard Linux routines */
+/* because they can be called by who knows what - even modules, so instead: */
+#define	MMAP_MMDOWNED		0x01	/* MM was downed prior to mmap() */
+#define	MMAP_MAYSHARE		0x02	/* ornament with VM_MAYSHARE */
+#define	MAPS_NOUSER		0x04	/* do not copy maps to user */
+#ifdef CONFIG_MOSIX_FS
+#define	MFSARG_OLDREADDIR	0x08	/* this is "old_readdir" calling */
+#define	MFSARG_GETDENTS		0x10	/* this is "getdents" calling */
+#define	MFSARG_GETDENTS64	0x20	/* this is "getdents" calling */
+#define	MFSARG_EMPTYF_PRI	0x40	/* obtain empty file even beyond limit*/
+#define	MFSARG_RONLY		0x80	/* no write-permission on anything */
+#define MFSARG_STATFS_FP        0x100   /* pointer to file for statsfs */
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+#define	FILP_OPEN_SYSCALL	0x200	/* filp_open called from sys_open */
+#endif /* CONFIG_MOSIX_DFSA */
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/hpcversion.h linux-openmosix/include/hpc/hpcversion.h
--- linux/include/hpc/hpcversion.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/hpcversion.h	2004-05-23 15:39:46.000000000 +0200
@@ -0,0 +1,24 @@
+/* Changes since Feb 12, 2002 by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s):  Moshe Bar, Amnon Shiloh, Oren Laadan.
+ */
+
+#ifndef _MOS_VERSION_H
+#define _MOS_VERSION_H
+
+/* The following are the EXTERNAL openMosix versions, used to enforce compatibility
+ * between different openMosix nodes when migrating and exchanging information -
+ * as opposed to the later INTERNAL kernel version, being used for reference
+ */
+#define MOSIX_MIGRATION_VERSION	0x000054L /* in 2.4.24 af of 2004523 */
+#define MOSIX_BALANCE_VERSION	0x000041L /* " */
+
+#define MOSIX_KERNEL_VERSION	 10904	/* version 1.9.2 */
+
+#define MOSIX_VERSION_PARTS(x) (x)/10000, ((x)%10000)/100, (x)%100
+	
+#endif /* _MOS_VERSION_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/mfscosts.h linux-openmosix/include/hpc/mfscosts.h
--- linux/include/hpc/mfscosts.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/mfscosts.h	2002-06-24 09:22:32.000000000 +0200
@@ -0,0 +1,14 @@
+/* mfscosts.h -- MOSIX */
+/* cost of MFS operations (microseconds) */
+
+/* measuring date: Mon Apr 30 20:12:28 IDT 2001 */
+/* between two Pentium-III/1GHz over Ethernet-100 */
+
+#define MFS_COST_CONN_S 36
+#define MFS_COST_CONN_C 40
+
+#define MFS_COST_INKB_S 14
+#define MFS_COST_INKB_C 19
+
+#define MFS_COST_OUTKB_S 88
+#define MFS_COST_OUTKB_C 56
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/protocol.h linux-openmosix/include/hpc/protocol.h
--- linux/include/hpc/protocol.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/protocol.h	2003-02-23 19:00:38.000000000 +0100
@@ -0,0 +1,565 @@
+/* changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ * Author(s): Amnon Shiloh, Oren Laadan, Moshe Bar
+ */
+#ifndef _MOS_PROTOCOL_H
+#define _MOS_PROTOCOL_H
+#ifdef CONFIG_MOSIX
+#ifdef __KERNEL__
+
+#include <linux/signal.h>
+#include <linux/resource.h>
+#include <linux/elf.h>
+
+#define	EDIST	EDOM	/* MOSIX general error-code, that is otherwise */
+			/* rarely-if-ever returned by kernel */
+
+struct mosix_addr {
+	struct sockaddr saddr;
+};
+
+
+/* structures passed between DEPUTY and REMOTE: */
+
+struct mig_request_h
+{
+	long version;
+	short reason;
+	short topology;
+	int personality;
+	int wp_works_ok;
+	int pages_sent;
+	int request_type;
+	int has_dfsa;
+};
+
+enum contact_type
+{
+	FROM_DEPUTY, DEPUTY_PROBE, FROM_REMOTE
+};
+
+struct please_migrate_h
+{
+	int reason;
+	int to;
+	struct mosix_addr ma;
+};
+
+struct mmap_parameters_h
+{
+	unsigned long addr;
+	int fixed;
+	unsigned long len;
+	unsigned long flags;
+	unsigned long pgoff;
+	int origin;
+	struct file *fp;
+	struct dentry *dp;
+	uint64_t uniq;
+	off_t isize;
+	nopage_t nopage;
+};
+
+struct brk_parameters_h
+{
+	unsigned long addr;
+	unsigned long len;
+};
+
+struct munmap_parameters_h
+{
+	unsigned long addr;
+	size_t len;
+};
+
+struct mprotect_parameters_h
+{
+	unsigned long addr;
+	size_t len;
+	unsigned long prot;
+};
+
+struct setupframe_parameters_h
+{
+	unsigned long sig;
+	unsigned long flags;
+	__sighandler_t handler;
+	void (*restorer)(void);
+	sigset_t set;
+	struct siginfo info;
+	unsigned long ss_sp;
+	size_t ss_size;
+};
+
+struct restore_sigcontext_ret_h
+{
+	int result;
+	int eax;
+};
+
+struct prequest_h
+{
+	char command;
+	int param;
+	int param2;
+	int len;
+};
+
+struct prequest_reply_h
+{
+	int reply;
+	int error;
+	int datalen;
+};
+
+struct user_copy_h
+{
+	void *addr;
+	unsigned int size;
+	char verify;
+};
+
+struct strnlen_user_h
+{
+	char *addr;
+	long len;
+};
+
+struct user_csum_copy_h
+{
+	void *addr;
+	unsigned int len;
+	int sum;
+};
+
+struct user_csum_copy_ret_h
+{
+	unsigned int newsum;
+	unsigned int error;
+};
+
+struct asig_h
+{
+	unsigned int sigs;
+	int nforced;
+};
+
+struct syscall_h
+{
+	int n;
+	unsigned int args[6];
+	int simple_data_type;
+	unsigned long simple_data_addr;
+	int simple_data_len;
+	int simple_data_actual;
+};
+
+struct syscall_ret_h
+{
+	long ret;
+	unsigned long deputytime;
+	unsigned long simple_data_addr;
+	int simple_data_len;	/* -1 = complex data */
+};
+
+struct bring_page_h
+{
+	struct file *fp;
+	unsigned long offset;
+	nopage_t nopage;
+};
+
+struct page_ret_h
+{
+	int ret;
+	unsigned long deputytime;
+};
+
+struct rlimit_h
+{
+	int resource;
+	struct rlimit limit;
+};
+
+struct execve_counts_h
+{
+	char **argp;
+	char **envp;
+};
+
+struct execve_counts_ret_h
+{
+	int argc;
+	int envc;
+};
+
+struct execve_bring_strings_h
+{
+	unsigned long p;
+	char *filename;
+	char **envp;
+	int envc;
+	char **argp;
+	int argc;
+};
+
+struct execve_bring_strings_ret_h
+{
+	unsigned long p;
+	unsigned long exec;
+	int pgno;
+	int len;
+	int result;
+};
+
+struct execve_more_strings_h
+{
+	int pgno;
+	int len;
+};
+
+struct execve_setup_args_h
+{
+	int create;
+	int pgno;
+	int len;
+	int how;
+	int p;
+	int loader;
+	int exec;
+	int argc;
+	int envc;
+	unsigned long personality;
+};
+
+struct execve_setup_args_ret_h
+{
+	unsigned long p;
+	unsigned long loader;
+	unsigned long exec;
+	int reply;
+	unsigned long start_stack;
+};
+
+struct execve_exec_mmap_ret_h
+{
+	int result;
+	char comm[16];
+};
+
+struct execve_elf_setup_h
+{
+	char *p;
+	int argc;
+	int envc;
+	int hasexec;
+	unsigned long exec_e_phoff;
+	unsigned long exec_e_phnum;
+	unsigned long exec_e_entry;
+	unsigned long addr;
+	unsigned long load_bias;
+	unsigned long interp_load_addr;
+	int ibcs;
+	struct elf_tables_extras extras;
+	int add_arg_start;
+	unsigned long elf_brk;
+	unsigned long end_code;
+	unsigned long start_code;
+	unsigned long start_data;
+	unsigned long end_data;
+	unsigned long elf_bss;
+	unsigned long personality;
+};
+
+struct execve_fix_elf_aout_h
+{
+	unsigned bss;
+	unsigned data;
+	unsigned text;
+};
+
+struct list_vmas_ret_h
+{
+	int n;
+	unsigned long argstart;
+	unsigned long argend;
+};
+
+struct fork_h
+{
+	unsigned long usp;
+	int do_forkmigrate;
+	int pid;
+	pid_t tgid;
+};
+
+struct mm_stats_h
+{
+	unsigned long start_code, end_code, start_data, end_data;
+	unsigned long start_brk, brk, start_stack;
+	unsigned long arg_start, arg_end, env_start, env_end;
+};
+
+struct disclosure_h
+{
+	uid_t uid;
+	gid_t gid;
+	pid_t pgrp;
+	pid_t session;
+	char disclosure;
+	char comm[16];
+	pid_t tgid;
+};
+
+struct mig_misc_h
+{
+	unsigned long ptrace;
+	unsigned long dflags;
+	long debugreg[8];
+	long nice;
+	kernel_cap_t caps;
+	unsigned long it_prof_value, it_prof_incr, it_virt_value, it_virt_incr;
+	struct pt_regs regs;
+	/* segment registers. FIXME: need to go inside regs */
+	unsigned long fs;
+	unsigned long gs;
+	struct rlimit rlim_cpu, rlim_data, rlim_stack, rlim_rss, rlim_as;
+#ifdef CONFIG_MOSIX_DFSA
+	struct rlimit rlim_nofile, rlim_fsz;
+#endif /* CONFIG_MOSIX_DFSA */
+	char stay;
+	unsigned short deppe;
+	unsigned short deputy_regs;
+	u64 passedtime;
+	u16 deccycle;
+	s16 decay;
+	u8 dpolicy;
+	pid_t mypid;
+	struct asig_h asig;
+	struct disclosure_h info;
+	int nmigs;
+	int pagecredit;
+	int lastxcpu;
+	__u32 features[NCAPINTS];
+	u64 tscval;
+	struct opcost depcost[MAX_MOSIX_TOPOLOGY];
+	int depspeed;
+};
+
+struct decay_h
+{
+	int policy;
+	int deccycle;
+	int decay;
+};
+
+struct aload_h
+{
+	int aload;
+	int freepages;
+#ifdef CONFIG_MOSIX_TOPOLOGY
+	struct mfs_cost mfscosts[MAX_MOSIX_TOPOLOGY];
+#endif /* CONFIG_MOSIX_TOPOLOGY */
+};
+
+#ifdef CONFIG_MOSIX_DFSA
+struct read_yourself_h
+{
+	int dfsano;
+	loff_t off;
+	unsigned long addr;
+	unsigned long len;
+	int infolen;
+};
+#endif /* CONFIG_MOSIX_DFSA */
+
+/* COMMAND CLASSES: */
+
+#define	DEP_FLG	0x100
+#define	MIG_FLG	0x200
+#define	REPLY	0x400
+#define	ANYTIME	0x800
+#define	USERMODE 0x1000
+#ifdef CONFIG_MOSIX_DFSA
+#define	DFSA_NOUPDATE	0x2000
+#else
+#define	DFSA_NOUPDATE	0
+#endif /* CONFIG_MOSIX_DFSA */
+
+/* COMMANDS: */
+
+#define	DEP_USERMODE		(DEP_FLG|0x00)
+#define	DEP_SYNC		(DEP_FLG|0x01)
+#define	DEP_NOTHING		(DEP_FLG|0x02)
+#define	DEP_MMAP		(DEP_FLG|0x03)
+#define	DEP_MUNMAP		(DEP_FLG|0x04)
+#define	DEP_LISTHOLD		(DEP_FLG|0x05)
+#define	DEP_SETUPFRAME		(DEP_FLG|0x06)
+#define	DEP_NICE		(DEP_FLG|0x07)
+#define	DEP_CPAS		(DEP_FLG|0x08)
+#define	DEP_RESTORESIGCONTEXT	(DEP_FLG|0x09)
+#define	DEP_PREQUEST		(DEP_FLG|0x10)
+#define	DEP_COPY_FROM_USER	(DEP_FLG|0x11)
+#define	DEP_COPY_TO_USER	(DEP_FLG|0x12)
+#define	DEP_CLEAR_USER		(DEP_FLG|0x13)
+#define	DEP_STRNCPY_FROM_USER	(DEP_FLG|0x14)
+#define	DEP_STRNLEN_USER	(DEP_FLG|0x15)
+#define	DEP_VERIFY_WRITE	(DEP_FLG|0x16)
+#define	DEP_RLIMIT		(DEP_FLG|0x17)
+#define	DEP_TAKEURGENT		(DEP_FLG|0x18)
+#define	DEP_RUSAGE		(DEP_FLG|0x19)
+#define	DEP_EXECVE_COUNTS	(DEP_FLG|0x20)
+#define	DEP_BRING_STRINGS	(DEP_FLG|0x21)
+#define	DEP_SETUP_ARGS		(DEP_FLG|0x22)
+#define	DEP_EXEC_MMAP		(DEP_FLG|0x23)
+#define	DEP_DUMP_THREAD		(DEP_FLG|0x24)
+#define	DEP_INIT_AOUT_MM	(DEP_FLG|0x25)
+#define	DEP_ELF_SETUP		(DEP_FLG|0x26)
+#define	DEP_FIX_ELF_AOUT	(DEP_FLG|0x27)
+#define	DEP_LIST_VMAS		(DEP_FLG|0x28)
+#define	DEP_PLEASE_FORK		(DEP_FLG|0x29)
+#define DEP_CONSIDER		(DEP_FLG|0x30)
+#define	DEP_PERSONALITY		(DEP_FLG|0x31)
+#define	DEP_BRING_ME_REGS	(DEP_FLG|0x32)
+#define	DEP_CSUM_COPY_FROM_USER	(DEP_FLG|0x33)
+#define	DEP_DUMP_FPU		(DEP_FLG|0x34)
+#define	DEP_COME_BACK		(DEP_FLG|0x35)
+#define DEP_PLEASE_MIGRATE	(DEP_FLG|0x36)
+#define	DEP_CACHE_READ_DATA	(DEP_FLG|0x37)
+#define	DEP_DATA_TO_USER	(DEP_FLG|0x38)
+#define	DEP_UPDATE_DECAY	(DEP_FLG|0x39)
+#define	DEP_UPDATE_LOCK		(DEP_FLG|0x40)
+#define	DEP_PSINFO		(DEP_FLG|0x41)
+#define	DEP_OPCOSTS		(DEP_FLG|0x42)
+#define	DEP_MPROTECT		(DEP_FLG|0x43)
+#define	DEP_BRK			(DEP_FLG|0x44)
+#define	DEP_CAPS		(DEP_FLG|0x45)
+#define	DEP_INFO		(DEP_FLG|0x46)
+#define	DEP_UPDATE_MIGFILTER	(DEP_FLG|0x47)
+#define	DEP_UPDATE_MIGPOLICY	(DEP_FLG|0x48)
+#define	DEP_UPDATE_MIGNODES	(DEP_FLG|0x49)
+#define DEP_UPDATE_MIGGROUP	(DEP_FLG|0x50)
+#ifdef CONFIG_MOSIX_DFSA
+#define	DEP_DFSA_CHANGES	(DEP_FLG|0x80)
+#define	DEP_DFSA_CLEAR		(DEP_FLG|0x81)
+#define	DEP_READ_YOURSELF	(DEP_FLG|0x82)
+#endif /* CONFIG_MOSIX_DFSA */
+
+#define	REM_NOTHING		(ANYTIME|0x01)
+#define	REM_PAGE		(ANYTIME|DFSA_NOUPDATE|0x02)
+#define	REM_MORESTRINGS		(ANYTIME|0x03)
+#define	REM_BRING_ME_REGS	(ANYTIME|0x04)
+#define	REM_GETALOAD		(ANYTIME|0x05)
+#define	REM_GETTSC		(ANYTIME|0x06)
+
+#define	REM_NULLMSG		0x01
+#define	REM_ASIG		0x02
+#define	REM_SYSCALL_TRACE	0x03
+#define	REM_SYSCALL		0x04
+#define REM_BRING_ME_HOME	0x05
+#define	REM_BRING_ME_TO		0x06
+#define	REM_CONSIDERING		0x07
+#define	REM_MUST_COME_HOME	0x08
+#define	REM_CONNECT_TO		0x09
+
+#define MIG_REQUEST		(MIG_FLG|0x01)
+
+#define	MIG_MM_STATS		(MIG_FLG|0x10)
+#define	MIG_MM_AREA		(MIG_FLG|0x11)
+#define	MIG_PAGE		(MIG_FLG|0x12)
+#define	MIG_FP			(MIG_FLG|0x13)
+#define	MIG_XFP			(MIG_FLG|0x14)
+#define	MIG_LDT			(MIG_FLG|0x15)
+#define	MIG_MISC		(MIG_FLG|0x16)
+#define	MIG_NOT_COMING		(MIG_FLG|0x17)
+
+/* routines on the DEPUTY side of the protocol: */
+
+extern int deputy_request(int, void *, int, void *, int, int, void **, int);
+extern int deputy_wait(int, void **, int *);
+extern int deputy_reply(int, void *, int, void *, int, int, int);
+extern int deputy_handle_interim_request(int, void *, int);
+extern void deputy_syscall(struct syscall_h *, int);
+extern void deputy_rusage(int);
+extern void deputy_add_rusage(struct rusage *);
+extern void deputy_analyse_remote_signals(struct asig_h *);
+extern int deputy_bring_page(struct bring_page_h *);
+extern int deputy_tsc(void);
+extern int deputy_more_strings(struct execve_more_strings_h *);
+extern int deputy_bring_me_regs(unsigned long *);
+extern void deputy_inform_remote_of_overheads(void);
+
+/* routines on the REMOTE side of the protocol: */
+
+extern int remote_request(int, void *, int, void *, int, int, void **, int);
+extern void wait_for_permission_to_continue(void);
+extern int remote_deputy_has_something_for_us(struct task_struct *);
+extern void inform_deputy_of_urgent(void);
+extern void transfer_signals_to_deputy(unsigned int, siginfo_t *, int);
+extern void absorb_deptime(unsigned long);
+extern int remote_rusage(int *);
+extern int remote_execve_counts(struct execve_counts_h *);
+extern int remote_bring_strings(struct execve_bring_strings_h *);
+extern int remote_setup_args(struct execve_setup_args_h *);
+extern int remote_exec_mmap(void);
+extern int remote_urgent(void);
+extern int remote_readpage(struct file *, struct page *);
+extern int remote_dump_thread(void);
+extern int remote_init_aout_mm(struct exec *);
+extern int remote_elf_setup(struct execve_elf_setup_h *);
+extern int remote_fix_elf_aout(struct execve_fix_elf_aout_h *);
+extern int remote_list_vmas(void);
+extern int remote_fork(struct fork_h *);
+extern int remote_personality(unsigned long *);
+extern int remote_prequest(struct prequest_h *);
+extern int remote_mmap(struct mmap_parameters_h *, int);
+extern int remote_brk(struct brk_parameters_h *);
+extern int remote_munmap(struct munmap_parameters_h *);
+extern int remote_mprotect(struct mprotect_parameters_h *);
+extern int remote_come_back(void *);
+extern int remote_goto_remote(void *);
+extern int remote_copy_from_user(struct user_copy_h *);
+extern int remote_copy_to_user(struct user_copy_h *);
+extern int remote_data_to_user(struct user_copy_h *);
+extern int remote_clear_user(struct user_copy_h *);
+extern int remote_strncpy_from_user(struct user_copy_h *);
+extern int remote_strnlen_user(struct strnlen_user_h *);
+extern int remote_verify_write(struct user_copy_h *);
+extern int remote_csum_copy_from_user(struct user_csum_copy_h *);
+extern int remote_csum_copy_to_user(struct user_csum_copy_h *);
+extern int remote_report_files(void);
+extern int remote_setup_frame(struct setupframe_parameters_h *);
+extern int remote_nice(long *);
+extern int remote_caps(kernel_cap_t *);
+extern int remote_depcosts(void *);
+extern int remote_restore_sigcontext(struct sigcontext **);
+extern int remote_bring_me_regs(unsigned long *);
+extern int remote_dump_fpu(void);
+extern int remote_consider(int *);
+extern int remote_setdecay(struct decay_h *);
+extern int remote_set_lock(int *);
+extern int remote_set_migfilter(int *);
+extern int remote_set_migpolicy(int *);
+extern int remote_set_mignodes(uint32_t *);
+extern int remote_set_miggroup(int *);
+extern int remote_psinfo(void);
+#ifdef CONFIG_MOSIX_DFSA
+extern int remote_receive_dfsachanges(int *);
+extern int remote_read_yourself(struct read_yourself_h *);
+#endif /* CONFIG_MOSIX_DFSA */
+extern int remote_rlimit(struct rlimit_h *);
+extern int remote_updinfo(struct disclosure_h *);
+extern void remote_do_updinfo(struct disclosure_h *);
+extern void remote_fill_rusage(struct rusage *, int);
+
+/* routines used by both sides of the protocol: */
+
+extern unsigned int which_regs_to_send(void);
+extern void regs_were_sent(void);
+
+#endif /*__KERNEL__*/
+#endif /* CONFIG_MOSIX */
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/request.h linux-openmosix/include/hpc/request.h
--- linux/include/hpc/request.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/request.h	2002-06-24 09:22:32.000000000 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh.
+ */
+#ifndef _MOS_REQUEST_H
+#define _MOS_REQUEST_H
+#ifdef CONFIG_MOSIX
+
+struct prequest
+{
+	struct prequest *rnext;		/* next in request chain */
+	struct prequest *cnext;		/* caller chain */
+	volatile char rflags;		/* coordination flags - see below */
+	char command;			/* ... */
+	int param;			/* optional parameter */
+	int param2;			/* optional parameter */
+	caddr_t ereply;		 	/* extended reply address */
+	int len;			/* optional extended reply length */
+	long reply;			/* reply, if only one longword */
+	wait_queue_head_t waitq;	/* who is waiting for the reply */
+};
+
+/* flags: */
+
+#define PR_WAITING	1       /* caller still waiting for the request */
+#define PR_DONE	 	2	/* request complete */
+#define PR_ERROR	4	/* request failed, reply contains errno */
+
+/* commands: */
+
+enum
+{
+PR_PROCFS_TASK_MEM = 1,
+PR_PROCFS_GET_ENV,
+PR_PROCFS_GET_ARG,
+PR_PROCFS_GET_STAT_PARTS,
+PR_PROCFS_GET_STATM,
+PR_PROCFS_MAP_INFO,
+PR_PROCFS_MEM_READ,
+PR_PROCFS_MEM_WRITE,
+PR_PROCFS_UPDATE_TIMES,
+PR_PROCFS_GET_EXE,
+PR_PTRACE_GET_STACK_LONG,
+PR_PTRACE_PUT_STACK_LONG,
+PR_PTRACE_GETREGS,
+PR_PTRACE_SETREGS,
+PR_PTRACE_PEEKUSER,
+PR_PTRACE_POKEUSER,
+PR_PTRACE_CONT,
+PR_PTRACE_SINGLE_STEP,
+PR_PTRACE_GETFPREGS,
+PR_PTRACE_SETFPREGS,
+PR_PTRACE_GETFPXREGS,
+PR_PTRACE_SETFPXREGS,
+PR_PTRACE_NOT_TRACED,
+#ifdef CONFIG_MOSIX_DFSA
+PR_DFSA_SYNCHRONIZE,
+#endif /* CONFIG_MOSIX_DFSA */
+};
+
+#define	SHOULD_ASK_PROCESS(p)	(p && (p->mosix.dflags & DDEPUTY) && (p != current || !(p->mosix.dflags & DINSCHED)))
+
+extern int request_process_arg2(struct task_struct *, void *, int, int, int);
+#define request_process(_t, _b, _c, _a) request_process_arg2(_t, _b, _c, _a, 0)
+extern char *request_process_to_buf_arg(struct task_struct *, char *, int, int);
+#define request_process_to_buf(_p,_b,_c) request_process_to_buf_arg(_p,_b,_c,0)
+
+extern char *fill_common_ps_info(int *);
+extern int pick_ps(struct task_struct *, struct prequest *);
+extern void store_common_ps_info(void);
+extern void stop_storing_common_ps_info(void);
+extern void process_requests(void);
+extern void discard_requests(void);
+extern void process_only_easy_requests(void);
+
+struct proc_remote_stat_parts
+{
+	unsigned long vsize, eip, esp;
+	long priority;
+	unsigned long rss, start_code, end_code, start_stack;
+	long processor;
+};
+
+/* routines in other parts of the kernel that are called by MOSIX: */
+
+extern int proc_pid_environ(struct task_struct *, char *);
+extern int proc_pid_cmdline(struct task_struct *, char *);
+extern char *task_mem(struct mm_struct *, char *);
+extern void proc_get_stat_parts(struct task_struct *, struct mm_struct *, struct proc_remote_stat_parts *);
+extern int proc_pid_statm(struct task_struct *, char *);
+struct vmamaps;
+extern int proc_list_maps(struct vmamaps *, int);
+extern void ref_mapped_files(struct vmamaps *, int);
+extern int get_stack_long(struct task_struct *, int);
+extern int put_stack_long(struct task_struct *, int, unsigned long);
+extern void ptrace_putregs(unsigned long *);
+extern void ptrace_getregs(unsigned long *);
+extern unsigned long ptrace_peekuser(long);
+extern void ptrace_pokeuser(long, long);
+extern void ptrace_cont(int);
+extern void ptrace_single_step(void);
+struct user_i387_struct;
+extern void ptrace_getfpregs(struct user_i387_struct *);
+extern void ptrace_setfpregs(struct user_i387_struct *);
+struct user_fxsr_struct;
+extern void ptrace_getfpxregs(struct user_fxsr_struct *);
+extern void ptrace_setfpxregs(struct user_fxsr_struct *);
+extern struct file *first_executable(void); 
+
+#endif /* CONFIG_MOSIX */
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/hpc/routines.h linux-openmosix/include/hpc/routines.h
--- linux/include/hpc/routines.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/hpc/routines.h	2003-02-23 19:00:56.000000000 +0100
@@ -0,0 +1,232 @@
+/* Changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh, Moshe Bar
+ */
+#ifndef _MOS_ROUTINES_H
+#define _MOS_ROUTINES_H
+#ifdef CONFIG_MOSIX
+
+#include <linux/stddef.h>
+
+/*
+ * a collection of routines in hpc/?*.c that are neither:
+ * 1) used by the rest of the kernel	 --> include/linux/hpc.h
+ * 2) in the communication package	 --> include/hpc/comm.h
+ * 3) part of the DEPUTY/REMOTE protocol --> include/hpc/protocol.h
+ * 4) related to prequests		 --> include/hpc/request.h
+ * 5) related to DFSA			 --> include/hpc/dfsa.h
+ */
+
+struct task_struct;
+struct mosixnet;
+
+/* task management: */
+
+extern int remote_need_while_asleep(struct task_struct *);
+extern int other_needs_while_asleep(void);
+extern void remote_run_while_asleep(void);
+extern void deputy_run_while_asleep(void);
+extern int remote_pre_usermode_actions(void);
+extern int local_pre_usermode_actions(void);
+extern void per_task_ack_mosix_state(void);
+extern char *desc_mostask(struct mosix_task *);
+extern void mosix_do_add_to_whereto(struct task_struct *, int);
+extern void common_daemon_setup(char *, int);
+extern void neutralize_my_load(int);
+extern void wait_for_mosix_configuration(int *);
+extern int obtain_mm(void);
+extern void sync_caps(void);
+
+/* load balancing: */
+
+extern void mosix_load_init(void);
+extern void load_balance(void);
+extern void mosix_clear_statistics(void);
+struct sonstats;
+extern void consider(int, struct sonstats *);
+extern int send_local_aload(int);
+extern int send_with_miginfo(int, void *, int);
+extern void mosix_local_syscall(void);
+extern void release_migrations(int);
+extern void changed_my_mind_and_staying(void);
+extern int balance_commit_mig(int, int);
+extern void info_someone_came_in(void);
+extern void end_coming_in(int);
+extern void add_statistics_to_ancesstor(struct task_struct *, struct task_struct *);
+extern void info_update_costs(void);
+extern void info_update_mfscosts(void);
+extern void load_balance(void);
+extern void memory_balance(void);
+extern void age_balancing(void);
+extern void unchoose_me(void);
+
+/* memory handling: */
+
+extern void init_mdp(void);
+extern void compute_freemem(void);
+extern int export_mem(void);
+extern int memory_badly_required(void);
+extern int memory_relief_quality(struct task_struct *, int);
+extern void memory_balance(void);
+
+/* information dissemination: */
+
+extern void init_mosconfig(void);
+extern int mosix_info_daemon(void *); 
+extern void info_init(void);
+extern void info_startup(void);
+extern void info_reconfig(void);
+struct mosix_info;
+struct loadinfo;
+extern int balance_get_load(int, struct loadinfo *);
+extern int balance_get_infos(int, int, struct mosix_info *, int);
+extern int balance_get_info(int, struct mosix_info *);
+extern void mosinfo_update_gateways(void);
+extern void this_machine_is_favourite(int);
+extern int mosix_mem_daemon(void *); 
+
+/* process migration: */
+
+struct mig_request_h;
+extern int mosix_mig_daemon(void *);
+extern int passto(int, int);
+extern int mosix_do_send_back_home(struct task_struct *);
+extern int mosix_do_go_home(int);
+extern void follow_whereto(void);
+extern int mig_migrate(int);
+extern void mig_set_lock(int);
+extern void mig_set_migfilter(int);
+extern void mig_set_migpolicy(int);
+extern void mig_set_mignodes(uint32_t);
+extern void mig_set_miggroup(int);
+extern int count_migrating_pages(void);
+extern void kickstart(void);
+extern int run_over_dirty_pages(int (*func)(unsigned long, int), int);
+extern void deputy_startup(void);
+extern int mig_send_request(int, int);
+extern int mig_recv_request(struct mig_request_h **);
+extern int mig_do_send(void);
+extern int mig_do_receive(void);
+
+/* deputy: */
+
+extern void deputy_main_loop(void);
+extern void undeputy(struct task_struct *);
+extern void deputy_async_requests(void);
+extern void mosix_clear_all_held_files(struct task_struct *);
+extern int fork_mosix_remote_files(struct task_struct *);
+extern void coordinate(int, int);
+extern long call_with_regs(void *, struct pt_regs *, struct pt_regs *);
+extern int task_maps_ip(struct task_struct *, struct inode *);
+extern void deputy_communication_failed(void);
+extern void deputy_die_on_communication(void) ATTRIB_NORET;
+
+/* remote: */
+
+extern int remote_wait(int, void **, int *);
+extern void wait_for_permission_to_continue(void);
+extern int remote_request(int, void *, int, void *, int, int, void **, int);
+extern long remote_standard_system_call(int, struct pt_regs *);
+extern struct file *get_remote_file(int, struct file *, struct dentry *, unsigned long long, off_t, nopage_t);
+extern void remote_disappear(void) __attribute__((noreturn));
+
+/* data cache: */
+
+struct syscall_h;
+struct syscall_ret_h;
+extern int copy_from_cache(char *, unsigned long, int, int *);
+extern int copy_to_cache(unsigned long, char *, int, int *);
+extern int zero_cache(char *, int, int *);
+extern int strlen_cache(char *, int *);
+extern int all_in_cache(unsigned long, unsigned int, int);
+extern int any_in_cache(unsigned long, unsigned int);
+extern int alloc_ucache(void);
+extern void free_ucache(void);
+extern void flush_ucache(void);
+extern void flush_read_cache(void);
+extern int ucache_ok(unsigned long, unsigned long, int);
+extern int remote_unpack_read_cache_data(struct syscall_ret_h *);
+extern void set_read_region(unsigned long, unsigned int);
+extern void set_write_region(unsigned long, unsigned int);
+extern char *construct_ucache_envelope(int *, int *, struct syscall_h *, char **);
+extern int open_ucache_envelope(struct syscall_h *);
+extern char *deputy_pack_read_cache_data(int *, struct syscall_ret_h *, char **);
+
+/* configuration: */
+
+extern int count_mosix_nodes(void); 
+extern int nth_node(int);
+extern int mos_to_ascii(int, char *, int);
+extern int mos_to_net(int, void *);
+extern int mymos_to_net(void *);
+extern int mosix_config_get_table(struct mosixnet **, int, int);
+extern int mosix_config_set_table(struct mosixnet *, int, int);
+extern int mosix_config_get_pe(void);
+extern int mosix_config_set_pe(int);
+extern int mosix_config_get_tentative_pe(void);
+extern int mosix_config_get_limit(void);
+extern int count_mosix_nodes(void);
+extern int config_get_status(int);
+extern int config_set_status(int);
+extern int i_am_in_a_wrong_place(void);
+extern void done_checking_conf(void);
+#ifdef CONFIG_MOSIX_FS
+extern int scan_mosix_nodes(int, int *, int *);
+#endif /* CONFIG_MOSIX_FS */
+
+/* statistics decay: */
+
+extern int decay_inherit(int);
+extern int decay_exec(int);
+extern int decay_execonce(int);
+extern int decay_set(int, int, int);
+extern int decay_get(int);
+extern void decay_clear(void);
+extern void deputy_update_remote_decay(void);
+extern void do_decay(void);
+extern void inc_decays(void);
+extern now_t time_now(void);
+#define	time_since(_when_)	(time_now() - (_when_))
+
+/* MOSIX administration: */
+
+extern int admin_get_mode(int);
+extern int admin_set_mode(int, int);
+extern int expel(int);
+extern int bring(void);
+extern void proc_update_costs(void);
+extern int my_mosix_status(void);
+extern void set_my_cpuspeed(void);
+
+/* debugging: */
+
+/* macros: */
+
+#define	MOSIX_TO_TASK(m) ((struct task_struct *)(((char *)m)-offsetof(struct task_struct,mosix)))
+
+#ifdef CONFIG_MOSIX_DFSA
+#define	URGENT_REMOTE_CONDITIONS(p)	((p)->mosix.whereto || \
+					process_told((p), DREQ_DFSASYNC))
+#else
+#define	URGENT_REMOTE_CONDITIONS(m)	((p)->mosix.whereto)
+#endif /* CONFIG_MOSIX_DFSA */
+#endif /* CONFIG_MOSIX */
+
+#if MILLION % HZ
+#define ticks_to_ms(ticks)	(((int64_t)(ticks)) * MILLION / HZ)
+#define	ms_to_ticks(ms)		((ms) * HZ / MILLION)
+#else
+#define ticks_to_ms(ticks)	(((int64_t)(ticks)) * (MILLION / HZ))
+#define	ms_to_ticks(ms)		((ms) / (MILLION/HZ))
+#endif
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/binfmts.h linux-openmosix/include/linux/binfmts.h
--- linux/include/linux/binfmts.h	2001-11-22 20:46:19.000000000 +0100
+++ linux-openmosix/include/linux/binfmts.h	2004-02-05 10:51:27.000000000 +0100
@@ -65,5 +65,12 @@
 #define change_ldt(a,b) setup_arg_pages(a,b)
 #endif
 
+#ifdef CONFIG_MOSIX
+extern void execve_remote_counts(char **, char **, int *, int *);
+extern int execve_remote_bring_strings(struct linux_binprm *, char **, char **);
+extern unsigned long *create_aout_tables(char *, struct linux_binprm *);
+extern int exec_mmap(void);
+#endif /* CONFIG_MOSIX */
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_BINFMTS_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/capability.h linux-openmosix/include/linux/capability.h
--- linux/include/linux/capability.h	2001-11-22 20:46:19.000000000 +0100
+++ linux-openmosix/include/linux/capability.h	2004-02-05 10:51:27.000000000 +0100
@@ -348,6 +348,11 @@
 
 #define cap_is_fs_cap(c)     (CAP_TO_MASK(c) & CAP_FS_MASK)
 
+#ifdef CONFIG_MOSIX
+#define	REMOTE_CAPS	(CAP_FS_MASK | CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | \
+						CAP_TO_MASK(CAP_SYS_RESOURCE))
+#endif /* CONFIG_MOSIX */
+
 #endif /* __KERNEL__ */
 
 #endif /* !_LINUX_CAPABILITY_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/completion.h linux-openmosix/include/linux/completion.h
--- linux/include/linux/completion.h	2001-11-22 20:46:19.000000000 +0100
+++ linux-openmosix/include/linux/completion.h	2004-02-05 10:51:27.000000000 +0100
@@ -28,6 +28,9 @@
 }
 
 extern void FASTCALL(wait_for_completion(struct completion *));
+#ifdef CONFIG_MOSIX
+extern void FASTCALL(wait_for_completion_half_interruptible(struct completion *));
+#endif /* CONFIG_MOSIX */
 extern void FASTCALL(complete(struct completion *));
 
 #define INIT_COMPLETION(x)	((x).done = 0)
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/dcache.h linux-openmosix/include/linux/dcache.h
--- linux/include/linux/dcache.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/linux/dcache.h	2004-02-05 10:51:27.000000000 +0100
@@ -125,6 +125,10 @@
 					 */
 #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
 
+#ifdef CONFIG_MOSIX_FS
+#define	DCACHE_NO_CACHE	      0x0010	/* do not hash, do not cache */
+#endif /* CONFIG_MOSIX_FS */
+
 extern spinlock_t dcache_lock;
 
 /**
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/dfsa_interface.h linux-openmosix/include/linux/dfsa_interface.h
--- linux/include/linux/dfsa_interface.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/dfsa_interface.h	2002-02-14 11:35:25.000000000 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh.
+ */
+/* DFSA definitions and functions required anywhere outside of MOSIX */
+#ifndef _MOS_DFSA_INTERFACE_H
+#define _MOS_DFSA_INTERFACE_H
+
+#ifdef CONFIG_MOSIX_DFSA
+
+/* update flags (dupdates): */
+
+#define	DFSA_UPDCRED	1	/* need to update credentials */
+#define	DFSA_UPDTABLE	2	/* need to update DFSA table */
+#define	DFSA_UPDCDIR	4	/* need to update current-directory */
+#define	DFSA_UPDMAX	8	/* need to update "max_fdset" */
+#define	DFSA_UPDCLOSE	16	/* need to update closed files */
+#define	DFSA_UPDOPEN	32	/* need to update opened files */
+#define	DFSA_UPDMODS	64	/* need to update modified files */
+#define	DFSA_UPDUSED	128	/* need to update the "used" bits */
+#define	DFSA_UPDSEL	256	/* need to update MFS node-selections */
+#define	DFSA_UPDUMASK	512	/* need to update umask */
+
+#define	DFSA_UPDATE	(DFSA_UPDCRED|DFSA_UPDTABLE|DFSA_UPDCDIR|DFSA_UPDMAX|\
+			 DFSA_UPDCLOSE|DFSA_UPDOPEN|DFSA_UPDMODS|DFSA_UPDUSED|\
+			 DFSA_UPDSEL|DFSA_UPDUMASK)
+
+#define CAN_DFSA(p)	((p)->fs && atomic_read(&(p)->fs->users) == 1 && \
+			!(p)->fs->altroot && \
+			(p)->files && atomic_read(&(p)->files->users) == 1 && \
+			(p)->fs->root == init_task.fs->root && \
+			(p)->fs->rootmnt == init_task.fs->rootmnt && \
+			!((p)->ptrace) && !(p->flags & PF_EXITING))
+
+/* adjust the following if any file-system requires more identifying bytes: */
+#define	MAX_IDENT_RECORD_LEN	20
+
+struct vfsmount;
+struct dentry;
+struct nameidata;
+struct file;
+
+void dfsa_init(void);
+int dfsa_setmnt(struct vfsmount *, int, unsigned long);
+int dfsa_option(char *, int *);
+void dfsa_close_file(int);
+void dfsa_open_file(int);
+void dfsa_touch_file(int);
+void dfsa_is_not_up_to_date(void);
+void dfsa_pwd_changed(void);
+int can_dfsa_file(int);
+void dfsa_syscall_on_file(int, int);
+int name_starts_in_dfsa(char **, struct nameidata *);
+int within_dfsa(struct nameidata *);
+int dfsa_optimized_read(struct file *, loff_t, unsigned long, unsigned long);
+int disable_dfsa(void);
+void enable_dfsa(void);
+
+#endif /* CONFIG_MOSIX_DFSA */
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/elf.h linux-openmosix/include/linux/elf.h
--- linux/include/linux/elf.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/linux/elf.h	2004-02-05 10:51:27.000000000 +0100
@@ -607,5 +607,18 @@
 
 #endif
 
+#ifdef CONFIG_MOSIX
+#ifdef __KERNEL__
+struct elf_tables_extras
+{
+	int uid, euid, gid, egid;
+	long hwcap;
+	char platform[8];
+};
+
+extern unsigned long elf_remote_setup(char *, int, int, struct elfhdr *, unsigned long, unsigned long, unsigned long, int, int, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, struct elf_tables_extras *);
+extern int elf_maydump(struct vm_area_struct *);
+#endif /*__KERNEL__*/
+#endif /* CONFIG_MOSIX */
 
 #endif /* _LINUX_ELF_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/errno.h linux-openmosix/include/linux/errno.h
--- linux/include/linux/errno.h	2001-02-09 23:46:13.000000000 +0100
+++ linux-openmosix/include/linux/errno.h	2004-02-05 10:51:27.000000000 +0100
@@ -21,6 +21,10 @@
 #define EBADTYPE	527	/* Type not supported by server */
 #define EJUKEBOX	528	/* Request initiated, but will not complete before timeout */
 
+#ifdef CONFIG_MOSIX
+#define	EDOITATHOME	550
+#endif /* CONFIG_MOSIX */
+
 #endif
 
 #endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/file.h linux-openmosix/include/linux/file.h
--- linux/include/linux/file.h	2002-08-03 02:39:45.000000000 +0200
+++ linux-openmosix/include/linux/file.h	2004-02-05 10:51:27.000000000 +0100
@@ -5,6 +5,10 @@
 #ifndef __LINUX_FILE_H
 #define __LINUX_FILE_H
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 extern void FASTCALL(fput(struct file *));
 extern struct file * FASTCALL(fget(unsigned int fd));
  
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/fs.h linux-openmosix/include/linux/fs.h
--- linux/include/linux/fs.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/linux/fs.h	2004-02-05 10:51:27.000000000 +0100
@@ -34,8 +34,8 @@
  * nr_file rlimit, so it's safe to set up a ridiculously high absolute
  * upper limit on files-per-process.
  *
- * Some programs (notably those using select()) may have to be 
- * recompiled to take full advantage of the new limits..  
+ * Some programs (notably those using select()) may have to be
+ * recompiled to take full advantage of the new limits..
  */
 
 /* Fixed constants first: */
@@ -84,7 +84,7 @@
 #define SEL_EX		4
 
 /* public flags for file_system_type */
-#define FS_REQUIRES_DEV 1 
+#define FS_REQUIRES_DEV 1
 #define FS_NO_DCACHE	2 /* Only dcache the necessary things. */
 #define FS_NO_PRELIM	4 /* prevent preloading of dentries, even if
 			   * FS_NO_DCACHE is not set.
@@ -151,7 +151,12 @@
  */
 #define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
 
+#if defined(CONFIG_MOSIX_FS) && defined(__KERNEL__)
+#define IS_RDONLY(inode) (((inode)->i_sb->s_flags & MS_RDONLY) || \
+				(current->mosix.dirty_bits & MFSARG_RONLY))
+#else
 #define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
+#endif /* CONFIG_MOSIX_FS && __KERNEL__ */
 #define IS_SYNC(inode)		(__IS_FLG(inode, MS_SYNCHRONOUS) || ((inode)->i_flags & S_SYNC))
 #define IS_MANDLOCK(inode)	__IS_FLG(inode, MS_MANDLOCK)
 
@@ -235,10 +240,10 @@
  * Try to keep the most commonly used fields in single cache lines (16
  * bytes) to improve performance.  This ordering should be
  * particularly beneficial on 32-bit processors.
- * 
+ *
  * We use the first 16 bytes for the data which is used in searches
  * over the block hash lists (ie. getblk() and friends).
- * 
+ *
  * The second 16 bytes we use for lru buffer scans, as used by
  * sync_buffers() and refill_freelist().  -- sct
  */
@@ -322,6 +327,12 @@
 #include <linux/usbdev_fs_i.h>
 #include <linux/jffs2_fs_i.h>
 #include <linux/cramfs_fs_sb.h>
+#ifdef CONFIG_MOSIX
+#include <linux/remote_fs_i.h>
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs_fs_i.h>
+#endif /* CONFIG_MOSIX_FS */
+#endif /* CONFIG_MOSIX */
 
 /*
  * Attribute flags.  These should be or-ed together to figure out what
@@ -439,7 +450,7 @@
 	struct list_head	i_hash;
 	struct list_head	i_list;
 	struct list_head	i_dentry;
-	
+
 	struct list_head	i_dirty_buffers;
 	struct list_head	i_dirty_data_buffers;
 
@@ -518,7 +529,16 @@
 		struct usbdev_inode_info        usbdev_i;
 		struct jffs2_inode_info		jffs2_i;
 		void				*generic_ip;
+#ifdef CONFIG_MOSIX
+		struct remote_inode_info	remote_i;
+#ifdef CONFIG_MOSIX_FS
+		struct mfs_inode_info		mfs_i;
+#endif /* CONFIG_MOSIX_FS */
+#endif /* CONFIG_MOSIX */
 	} u;
+#ifdef CONFIG_MOSIX
+	uint64_t		i_unique;
+#endif /* CONFIG_MOSIX */
 };
 
 static inline void inode_add_bytes(struct inode *inode, loff_t bytes)
@@ -698,6 +718,46 @@
 	struct qstr last;
 	unsigned int flags;
 	int last_type;
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+	char *name_left;
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_FS
+	unsigned short express_function;
+	union complete_args
+	{
+		struct
+		{
+			int i1;
+			int i2;
+		} ints;
+		struct
+		{
+			time_t a;
+			time_t m;
+		} times;
+		struct
+		{
+			uid_t uid;
+			gid_t gid;
+		} ids;
+		struct
+		{
+			int mode;
+			dev_t dev;
+		} mknod;
+		mode_t mode;
+		loff_t len;
+		struct
+		{
+			char *buf;
+			int bufsiz;
+		} buffer;
+		struct nameidata *oldnd;
+		struct statfs *statfs;
+	} complete_args;
+	void *complete_parg;
+	unsigned int complete_flags;
+#endif /* CONFIG_MOSIX_FS */
 };
 
 /*
@@ -894,6 +954,12 @@
 	int (*revalidate) (struct dentry *);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct dentry *, struct iattr *);
+#ifdef CONFIG_MOSIX_FS
+        int (*express_lookup) (struct nameidata *, char **);
+#endif /* CONFIG_MOSIX_FS */
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+        void (*check_path) (struct dentry *);
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
 	int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -911,7 +977,7 @@
 	void (*destroy_inode)(struct inode *);
 
 	void (*read_inode) (struct inode *);
-  
+
   	/* reiserfs kludge.  reiserfs needs 64 bits of information to
     	** find an inode.  We are using the read_inode2 call to get
    	** that information.  We don't like this, and are waiting on some
@@ -958,6 +1024,11 @@
 	struct dentry * (*fh_to_dentry)(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent);
 	int (*dentry_to_fh)(struct dentry *, __u32 *fh, int *lenp, int need_parent);
 	int (*show_options)(struct seq_file *, struct vfsmount *);
+#ifdef CONFIG_MOSIX_DFSA
+	int (*identify) (struct dentry *, void *);
+	struct dentry * (*reconstruct) (struct vfsmount *, void *, int);
+	void (*dfsa_changed) (struct vfsmount *, int);
+#endif /* CONFIG_MOSIX_DFSA */
 };
 
 /* Inode state bits.. */
@@ -1030,7 +1101,7 @@
 
 /* Return value for VFS lock functions - tells locks.c to lock conventionally
  * REALLY kosha for root NFS and nfs_lock
- */ 
+ */
 #define LOCK_USE_CLNT 1
 
 #define FLOCK_VERIFY_READ  1
@@ -1311,7 +1382,7 @@
 
 extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
 extern struct file * open_exec(const char *);
- 
+
 /* fs/dcache.c -- generic fs support functions */
 extern int is_subdir(struct dentry *, struct dentry *);
 extern ino_t find_inode_number(struct dentry *, struct qstr *);
@@ -1352,6 +1423,47 @@
 #define LOOKUP_POSITIVE		(8)
 #define LOOKUP_PARENT		(16)
 #define LOOKUP_NOALT		(32)
+
+#ifdef CONFIG_MOSIX_DFSA
+#define	LOOKUP_STAYFS		(64)
+#define	LOOKUP_DOITATHOME	(128)
+#define	LOOKUP_REPLACENAME	(256)
+#else
+#define	LOOKUP_STAYFS		(0)
+#endif /* CONFIG_MOSIX_DFSA */
+#ifdef CONFIG_MOSIX_FS
+#define	LOOKUP_MFS		(512)
+#define	LOOKUP_COMPLETE		(1024)
+#define	LOOKUP_MFS_MFS		(2048)
+
+/* complete_flags: */
+#define	COMPLETE_DONE		1
+#define	COMPLETE_MAGICAL	2
+
+/* express functions: */
+enum express_functions
+{
+	EF_OPEN = 1,
+	EF_ACCESS,
+	EF_LINK,
+	EF_UNLINK,
+	EF_SYMLINK,
+	EF_MKDIR,
+	EF_RMDIR,
+	EF_RENAME,
+	EF_READLINK,
+	EF_TRUNCATE,
+	EF_UTIME,
+	EF_UTIMES,
+	EF_CHMOD,
+	EF_CHOWN,
+	EF_STAT,
+	EF_MKNOD,
+	EF_STATFS
+};
+
+#endif /* CONFIG_MOSIX_FS */
+
 /*
  * Type of the last component on LOOKUP_PARENT
  */
@@ -1674,6 +1786,16 @@
 	dput(d2);
 }
 
+#ifdef CONFIG_MOSIX
+extern spinlock_t unique_gen_lock;
+extern uint64_t unique_generator;
+#define	OPENMOSIX_VMODIFIED(_ip) do { \
+				spin_lock(&unique_gen_lock); \
+				_ip->i_unique = ++unique_generator; \
+				spin_unlock(&unique_gen_lock); \
+			} while(0)
+#endif /* CONFIG_MOSIX */
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_FS_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/fs_struct.h linux-openmosix/include/linux/fs_struct.h
--- linux/include/linux/fs_struct.h	2001-07-14 00:10:44.000000000 +0200
+++ linux-openmosix/include/linux/fs_struct.h	2004-02-05 10:51:27.000000000 +0100
@@ -2,12 +2,24 @@
 #define _LINUX_FS_STRUCT_H
 #ifdef __KERNEL__
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 struct fs_struct {
 	atomic_t count;
 	rwlock_t lock;
 	int umask;
 	struct dentry * root, * pwd, * altroot;
 	struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
+#ifdef CONFIG_MOSIX_DFSA
+	atomic_t users;
+	short count_dropped_to_one;
+	short pwd_changed;
+#define	INIT_FS_DFSA	, ATOMIC_INIT(1), 0, 0
+#else
+#define	INIT_FS_DFSA
+#endif /* CONFIG_MOSIX_DFSA */
 };
 
 #define INIT_FS { \
@@ -15,6 +27,7 @@
 	RW_LOCK_UNLOCKED, \
 	0022, \
 	NULL, NULL, NULL, NULL, NULL, NULL \
+	INIT_FS_DFSA \
 }
 
 extern void exit_fs(struct task_struct *);
@@ -41,6 +54,9 @@
 		dput(old_root);
 		mntput(old_rootmnt);
 	}
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_is_not_up_to_date();
+#endif /* CONFIG_MOSIX_DFSA */
 }
 
 /*
@@ -60,6 +76,10 @@
 	fs->pwdmnt = mntget(mnt);
 	fs->pwd = dget(dentry);
 	write_unlock(&fs->lock);
+#ifdef CONFIG_MOSIX_DFSA
+	if(fs->pwdmnt != old_pwdmnt || fs->pwd != old_pwd)
+		dfsa_pwd_changed();
+#endif /* CONFIG_MOSIX_DFSA */
 	if (old_pwd) {
 		dput(old_pwd);
 		mntput(old_pwdmnt);
@@ -68,6 +88,9 @@
 
 struct fs_struct *copy_fs_struct(struct fs_struct *old);
 void put_fs_struct(struct fs_struct *fs);
+#ifdef CONFIG_MOSIX_DFSA
+void put_used_fs_struct(struct fs_struct *fs);
+#endif /* CONFIG_MOSIX_DFSA */
 
 #endif
 #endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/hpcctl.h linux-openmosix/include/linux/hpcctl.h
--- linux/include/linux/hpcctl.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/hpcctl.h	2002-08-26 06:37:27.000000000 +0200
@@ -0,0 +1,38 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Moshe Bar, Oren Laadan.
+ */
+#ifndef _LINUX_MOSCTL_H
+#define _LINUX_MOSCTL_H
+
+#ifdef __KERNEL__
+#include <linux/socket.h>
+#else
+#include <sys/socket.h>
+#endif /*__KERNEL__*/
+
+#include <hpc/hpcctl.h>
+
+/* configuration */
+
+#define MOSIX_MAX	65535 /* max number of hosts in openMosix */
+#define MAX_MOSNET_ENTS	256   /* max number of netx in openMosix */
+
+struct mosixnet
+{
+	int base;
+	struct sockaddr saddr;
+	int cnt;
+};
+
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/hpc.h linux-openmosix/include/linux/hpc.h
--- linux/include/linux/hpc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/hpc.h	2004-02-05 02:48:29.000000000 +0100
@@ -0,0 +1,179 @@
+/* All changes since Feb 12, 2002 copyright by Moshe Bar moshe@moelabs.com
+ *
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * Author(s): Moshe Bar, Amnon Shiloh.
+ */
+#ifndef _LINUX_MOSIX_H
+#define _LINUX_MOSIX_H
+
+#ifdef CONFIG_MOSIX
+
+#ifdef __KERNEL__
+
+#include <linux/sched.h>
+#include <linux/user.h>
+#include <linux/elf.h>
+#include <hpc/defs.h>
+#include <hpc/request.h>
+
+/* operations on DEPUTY's data-base of REMOTE files: */
+
+extern int mosix_register_a_file(struct file *, int);
+extern void mosix_undo_last_file_registration(struct file *, int);
+extern int mosix_rebuild_file_list(void);
+extern void mosix_update_remote_files(void);
+
+struct vmalist
+{
+	unsigned int vmstart;
+	unsigned int vmend;
+	unsigned short vmflags;
+	short	maydump;
+};
+
+struct vmamaps
+{
+	unsigned long vmstart, vmend, vmflags, vmpgoff;
+	struct file *fp;
+};
+
+extern void init_mosix(void);
+extern void wake_up_mosix(struct task_struct *);
+extern int mosix_wakeable(struct task_struct *);
+extern int mosix_go_home(int);
+extern int mosix_go_home_for_reason(int, int);
+extern int mosix_send_back_home(struct task_struct *);
+extern int mosix_need_while_asleep(void);
+extern void mosix_run_while_asleep(void);
+extern void mosix_pre_usermode_functions(void);
+extern int stay_me_and_my_clones(uint32_t);
+extern void unstay_mm(struct mm_struct *);
+extern void mosix_inform_remote_of_nice(void);
+extern void mosix_snap_load(int);
+extern void mosix_clear_statistics(void);
+extern int mosix_fork_init_fields(struct task_struct *);
+extern void mosix_fork_free_fields(struct task_struct *);
+extern void mosix_exit(void);
+extern void mosix_very_exit(void);
+extern void mosix_obtain_registers(unsigned long);
+extern void mosix_bring_monkey_users_back(struct inode *);
+extern void mosix_no_longer_monkey(struct inode *);
+extern void mosix_check_for_freedom_to_move(void);
+extern int mosix_pre_clone(void);
+extern void mosix_post_clone(void);
+extern void mosix_remote_syscall_trace(void);
+extern u64 mosix_remote_tsc(void);
+extern int mosix_forkmigrate(void);
+extern int mosix_deputy_fork(struct task_struct *, int, unsigned long);
+extern void mosix_exit_mm(struct task_struct *);
+extern void mosix_exec_mmap(struct mm_struct *);
+extern void mosix_deputy_rusage(int);
+extern int mosix_deputy_personality(unsigned long);
+extern void mosix_deputy_count_args(char **, char**, int *, int *);
+extern int mosix_deputy_bring_strings(struct linux_binprm *, char *, char **, char **);
+extern int mosix_deputy_setup_args(int, unsigned long *);
+extern int mosix_deputy_exec_mmap(char *);
+extern int mosix_deputy_dump_thread(struct user *);
+extern void mosix_deputy_init_aout_mm(struct exec *);
+extern unsigned long mosix_deputy_elf_setup(char *, int, int, struct elfhdr *, unsigned long, unsigned long, unsigned long, int, int, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, struct elf_tables_extras *);
+extern void mosix_deputy_fix_elf_aout_interp(unsigned, unsigned, unsigned);
+extern int mosix_deputy_list_vmas(struct vmalist **, unsigned long *, unsigned long *);
+extern long mosix_deputy_brk(unsigned long, unsigned long);
+
+extern void mosix_notify_urgent(struct socket *);
+extern void mosix_notify_receive(struct socket *);
+
+extern void mosix_proc_init(void);
+extern int mosix_proc_get_remote_array(char *, int, int);
+extern int mosix_proc_get_node_array(char *, int, int);
+
+extern void mosix_decay_exec(void);
+extern void mosix_add_to_whereto(struct task_struct *, int);
+extern void mosix_do_add_to_whereto(struct task_struct *, int);
+
+struct sockaddr;
+extern int reserved_mosix_address(struct sockaddr *);
+extern void comm_report_violation(char *, struct sockaddr *);
+
+void init_guest_user_struct(void);
+extern int get_free_guest_slots(void);
+extern int count_guests(void);
+#ifdef CONFIG_MOSIX_FS
+int mfs_client_statfs(int, mfs_handle_t, struct statfs *);
+#endif /* CONFIG_MOSIX_FS */
+/* argument of mosix_deputy_setup_args: */
+#define	SETUP_ARGS_PLAIN	0	
+#define	SETUP_ARGS_AS_AOUT	1
+#define	SETUP_ARGS_AS_ELF	2
+#define	SETUP_ARGS_NOTYET	3
+
+extern int mosix_deputy_restore_sigcontext(struct sigcontext *, int *);
+extern void mosix_deputy_setup_frame(unsigned long, struct k_sigaction *, siginfo_t, sigset_t *);
+extern unsigned long mosix_deputy_mmap(struct file *, unsigned long, int, unsigned long, unsigned long, unsigned long, off_t, nopage_t);
+extern int deputy_munmap(unsigned long, size_t);
+extern int deputy_mprotect(unsigned long, size_t, unsigned long);
+extern void mosix_deputy_rlimit(int, struct rlimit);
+extern int mosix_deputy_dump_fpu(struct user_i387_struct *);
+extern int mosix_sync_caps(kernel_cap_t);
+
+#define	ALL_REGISTERS	0x7fff	/* as many as in struct pt_regs */
+#define	BIT_OF_REGISTER(_which) \
+	(1 << (((int)&(((struct pt_regs *)0)->_which)) / sizeof(int)))
+
+/*
+ * meaning of signals on REMOTE
+ */
+
+#define	FATAL_SIGSEGV		SIGINT
+#define	REMOTE_FILE_RELEASED	SIGQUIT
+
+/* other signals that can occur on REMOTE:
+ * SIGKILL, SIGSEGV, SIGPROF, SIGVTALRM, SIGFPE, SIGBUS, SIGIOT, SIGILL,
+ * SIGXCPU, SIGXFSZ, SIGPROF, SIGTRQAP, SIGPWR (a tricky one).
+ * SIGTERM requires the process to migrate back.
+ */
+
+#define	MOSIX_PRIORITY		(100)
+#define	MOSIX_ASLEEP_PRIORITY	(MOSIX_PRIORITY * 3 / 10)
+#define	MOSIX_DEPUTY_PRIORITY	(MOSIX_PRIORITY * 1 / 10)
+#define	MOSIX_RESPOND_PRIORITY	(MOSIX_PRIORITY * 6 / 10)
+
+#define	PROC_MOSIX_USE_START	1024	/* coordinate with proc/fs/base.c */
+
+#if defined(CONFIG_MOSIX_DIAG) && defined(CONFIG_SMP)
+#define KERNEL_LOCKED	do{if(current->lock_depth == -1)panic("not locked %d of " __FILE__, __LINE__);}while(0)
+#define MOSIX_LOCKED	do{if(current->mosix.lock_depth == -1)panic("not locked %d of " __FILE__, __LINE__);}while(0)
+#else
+#define	KERNEL_LOCKED	do {} while(0)
+#define	MOSIX_LOCKED	do {} while(0)
+#endif /* CONFIG_MOSIX_DIAG */
+
+#define	mos_to_contact(m) ((struct socket *)((m)->contact))
+#define	mos_to_waitp(m)	((wait_queue_head_t *)(&(m)->wait_dist))
+#define mos_to_regs(m)	((struct pt_regs *)((m)->altregs))
+
+struct proc_dir_entry;
+extern struct proc_dir_entry *proc_mosix;
+typedef ssize_t (proc_mosix_pid_writer)(struct file *, struct task_struct *, const char *, size_t);
+extern proc_mosix_pid_writer proc_mosix_pid_set_migrate;
+extern proc_mosix_pid_writer proc_mosix_pid_set_goto;
+extern proc_mosix_pid_writer proc_mosix_pid_set_lock;
+extern proc_mosix_pid_writer proc_mosix_pid_set_sigmig;
+extern proc_mosix_pid_writer proc_mosix_pid_set_disclosure;
+extern proc_mosix_pid_writer proc_mosix_pid_set_migfilter;
+extern proc_mosix_pid_writer proc_mosix_pid_set_migpolicy;
+extern proc_mosix_pid_writer proc_mosix_pid_set_mignodes;
+extern proc_mosix_pid_writer proc_mosix_pid_set_miggroup;
+#ifdef CONFIG_MOSIX_FS
+extern proc_mosix_pid_writer proc_mosix_pid_set_selected;
+#endif /* CONFIG_MOSIX_FS */
+
+#endif /*__KERNEL__*/
+
+#endif /* CONFIG_MOSIX */
+
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/iobuf.h linux-openmosix/include/linux/iobuf.h
--- linux/include/linux/iobuf.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/linux/iobuf.h	2004-02-05 10:51:27.000000000 +0100
@@ -48,6 +48,9 @@
 	int		errno;		/* Status of completed IO */
 	void		(*end_io) (struct kiobuf *); /* Completion callback */
 	wait_queue_head_t wait_queue;
+#ifdef CONFIG_MOSIX
+	struct mm_struct *mm;
+#endif /* CONFIG_MOSIX */
 };
 
 
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/kernel.h linux-openmosix/include/linux/kernel.h
--- linux/include/linux/kernel.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/linux/kernel.h	2004-02-05 10:51:27.000000000 +0100
@@ -191,7 +191,8 @@
 	unsigned long totalhigh;	/* Total high memory size */
 	unsigned long freehigh;		/* Available high memory size */
 	unsigned int mem_unit;		/* Memory unit size in bytes */
-	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
+	char _f[20 - 2 * sizeof(long) - sizeof(int)];
+		/* Padding: libc5 uses this.. */
 };
 
 #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/linkage.h linux-openmosix/include/linux/linkage.h
--- linux/include/linux/linkage.h	2000-12-11 21:49:54.000000000 +0100
+++ linux-openmosix/include/linux/linkage.h	2004-02-05 10:51:27.000000000 +0100
@@ -10,7 +10,13 @@
 #endif
 
 #if defined __i386__
+#if defined(CONFIG_MOSIX)
+/* there is a bug in egcs-2.91.66 using "regparm(0)" */
+/* it often crashes the compiler on some MOSIX files */
+#define asmlinkage CPP_ASMLINKAGE
+#else
 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
+#endif /* CONFIG_MOSIX */
 #elif defined __ia64__
 #define asmlinkage CPP_ASMLINKAGE __attribute__((syscall_linkage))
 #else
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/mfs_fs_i.h linux-openmosix/include/linux/mfs_fs_i.h
--- linux/include/linux/mfs_fs_i.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/mfs_fs_i.h	2002-02-14 11:35:25.000000000 +0100
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh.
+ */
+#ifndef _LINUX_MFS_FS_I_H
+#define _LINUX_MFS_FS_I_H
+#ifdef CONFIG_MOSIX
+
+typedef unsigned long long mfs_handle_t;
+
+struct mfs_inode_info
+{
+	int pe;
+	mfs_handle_t handle;
+};
+
+#endif /* CONFIG_MOSIX */
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/mfs.h linux-openmosix/include/linux/mfs.h
--- linux/include/linux/mfs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/mfs.h	2003-12-02 11:01:52.000000000 +0100
@@ -0,0 +1,491 @@
+#ifndef _MFS_H
+#define _MFS_H
+
+#include <linux/mfs_fs_i.h>
+
+#define	MFS_VERSION	2
+
+#define	MFS_GARBAGE_TIME (2700*HZ)
+#define	MFS_REPORT_TIME	(MFS_GARBAGE_TIME/3)
+
+#define	MFS_MAXBLOCK	16384
+
+/* test */
+
+extern int mfs_bh_statfs(mfs_handle_t, struct statfs *);
+
+ struct mfs_server_contact;
+struct mfs_client_contact; 
+
+struct mfs_completion
+{
+	unsigned char needed;
+	unsigned char done;
+	unsigned char func;
+	unsigned char ro;
+	int base_pe;
+	mfs_handle_t base;
+	mfs_handle_t dispose_base;
+	int other_pe;
+	mfs_handle_t other;
+	mfs_handle_t dispose_other;
+	union complete_args args;
+	void *more_data;
+	int more_data_len;
+	int error;
+};
+
+struct subinode
+{
+	unsigned long		si_ino;
+	unsigned int		si_count;
+	umode_t			si_mode;
+	nlink_t			si_nlink;
+	uid_t			si_iuid;
+	gid_t			si_gid;
+	kdev_t			si_rdev;
+	loff_t			si_size;
+	time_t			si_atime;
+	time_t			si_mtime;
+	time_t			si_ctime;
+	unsigned long		si_blksize;
+	unsigned long		si_blocks;
+	unsigned long		si_origino;
+	kdev_t			si_origdev;
+};
+
+struct mfs_dinfo
+{
+	int pe;
+	mfs_handle_t handle;
+	unsigned long latest;
+};
+
+extern int init_mfs(void);
+extern void mfs_change_pe(void);
+extern void mfs_change_root(struct dentry *, struct vfsmount *, struct dentry *, struct vfsmount *);
+extern int is_mfs_root(struct nameidata *);
+extern int mfs_walk_init_root(struct nameidata *);
+extern void mfs_ip_to_subip(struct subinode *, struct inode *);
+extern void mfs_subip_to_ip(struct inode *, struct subinode *);
+extern int mfs_conversion_init(void);
+extern mfs_handle_t local_to_mfs(struct nameidata *);
+extern int mfs_to_local(mfs_handle_t, struct nameidata *);
+extern int mfs_get_handle(mfs_handle_t handle);
+extern void mfs_put_handle(mfs_handle_t handle);
+extern int mfs_access_handle(mfs_handle_t handle);
+extern void mfs_lput(struct dentry *, struct vfsmount *);
+extern int mfs_try_to_cleanup(int);
+extern int mfs_attach_handle(int, mfs_handle_t);
+extern void mfs_dispose_handle(int, mfs_handle_t);
+extern int mfs_touch_handle(int, mfs_handle_t);
+extern ino_t global_inum(struct inode *);
+extern void cp_file_fields(struct file *, struct file *);
+
+extern loff_t mfs_low_llseek(mfs_handle_t, struct file *, loff_t, int);
+extern ssize_t mfs_low_read(mfs_handle_t, struct file *, char *, size_t, loff_t *);
+extern ssize_t mfs_low_write(mfs_handle_t, struct file *, char *, size_t, loff_t *, long);
+extern int mfs_low_open(mfs_handle_t, struct inode *, struct file *);
+extern int mfs_low_close(mfs_handle_t, struct inode *, struct file *);
+extern int mfs_low_readdir(mfs_handle_t, struct file *, void *, filldir_t, int *, int *);
+extern int mfs_low_ioctl(mfs_handle_t, struct file *, unsigned int, unsigned long, int, int *);
+extern int mfs_low_fsync(mfs_handle_t, struct file *, int);
+extern int mfs_low_attach_handle(mfs_handle_t);
+extern int mfs_low_touch_handle(mfs_handle_t);
+extern void mfs_low_dispose_handle(mfs_handle_t);
+extern int mfs_low_revalidate(mfs_handle_t, struct subinode *);
+extern int mfs_low_express_lookup(mfs_handle_t *, char *, unsigned int, int, int, struct subinode *, char **, struct mfs_completion *);
+extern int mfs_low_setattr(mfs_handle_t, struct iattr *);
+extern char *mfs_low_check_path(mfs_handle_t);
+
+extern void mfs_prepare_completion(struct mfs_completion *, struct nameidata *);
+extern int mfs_check_completion(struct mfs_completion *, struct nameidata *);
+extern mfs_handle_t mfs_low_complete(struct mfs_completion *, struct nameidata *);
+extern void mfs_low_complete_error(struct mfs_completion *, int);
+extern int mfs_link_complete(struct mfs_completion *, int, struct nameidata *);
+
+extern struct dentry *mfs_root;
+extern struct vfsmount *mfs_mnt;
+extern ino_t mfs_root_ino;
+extern dev_t mfs_root_dev;
+extern struct super_block *mfs_super;
+extern int MFS_PE;
+extern int mfs_debug;
+extern char mfs_is_ro;
+#ifdef CONFIG_MOSIX_DFSA
+extern char mfs_is_dfsa;
+#endif /* CONFIG_MOSIX_DFSA */
+
+#define	MFS_SUPER_MAGIC	235466776
+#define	MFS_BAD_PE	65536
+#define	MFS_UNKNOWN_PE	65537
+#define	MFS_ROOT_INO	65538
+
+/* protocols: */
+
+enum
+{
+	MFS_NONE = 0,
+	MFS_CLOSE,
+	MFS_CONTINUE,
+	MFS_STOP,
+	MFS_INTERIM_DATA,
+	MFS_REQUEST_LLSEEK,
+	MFS_REPLY_LLSEEK,
+	MFS_REQUEST_READ,
+	MFS_REPLY_READ,
+	MFS_REQUEST_WRITE,
+	MFS_REPLY_WRITE,
+	MFS_REQUEST_OPEN,
+	MFS_REPLY_OPEN,
+	MFS_REQUEST_CLOSE,
+	MFS_REPLY_CLOSE,
+	MFS_REQUEST_READDIR,
+	MFS_INTERIM_READDIR,
+	MFS_REPLY_READDIR,
+	MFS_REQUEST_IOCTL,
+	MFS_REPLY_IOCTL,
+	MFS_REQUEST_FSYNC,
+	MFS_REPLY_FSYNC,
+	MFS_REQUEST_REVALIDATE,
+	MFS_REPLY_REVALIDATE,
+	MFS_REQUEST_EXPRESS,
+	MFS_REPLY_EXPRESS,
+	MFS_REQUEST_CHECKPATH,
+	MFS_REPLY_CHECKPATH,
+	MFS_REQUEST_SETATTR,
+	MFS_REPLY_SETATTR,
+	MFS_REQUEST_ATTACH_HANDLE,
+	MFS_REPLY_ATTACH_HANDLE,
+	MFS_REQUEST_TOUCH_HANDLE,
+	MFS_REPLY_TOUCH_HANDLE,
+	MFS_REQUEST_DISPOSE_HANDLE,
+	MFS_REQUEST_STATFS,
+	MFS_REPLY_STATFS,
+};
+struct mfs_cred
+{
+	        uid_t uid, euid, suid, fsuid;
+	        gid_t gid, egid, sgid, fsgid;
+	        int ngroups;
+	        gid_t groups[NGROUPS];
+	        kernel_cap_t caps;
+	        int whereami;
+	        int deppe;
+};
+struct mfs_request_statfs
+{
+	        struct mfs_cred cred;
+	        mfs_handle_t handle;
+};
+
+struct mfs_reply_statfs
+{
+	        struct statfs stat;
+	        loff_t result;
+};
+struct mfs_request_llseek
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	loff_t offset;
+	int origin;
+};
+
+
+struct mfs_reply_llseek
+{
+	struct file file;
+	int result;
+};
+
+struct mfs_request_read
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	size_t count;
+	loff_t pos;
+};
+
+struct mfs_interim_data
+{
+	size_t count;
+};
+
+struct mfs_reply_read
+{
+	struct file file;
+	loff_t ppos;
+	ssize_t result;
+	size_t datalen;
+};
+
+struct mfs_request_write
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	size_t count;
+	loff_t pos;
+	size_t datalen;
+	long flim;
+};
+
+struct mfs_reply_write
+{
+	struct file file;
+	loff_t ppos;
+	ssize_t result;
+	int hadsigxfsz;
+};
+
+struct mfs_request_readdir
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	int policy;
+	int maxbytes;
+};
+
+#define	MFS_READDIR_UNKNOWN	0
+#define	MFS_READDIR_JUSTONE	1
+#define	MFS_READDIR_GETDENTS	2
+#define	MFS_READDIR_GETDENTS64	3
+
+struct mfs_interim_readdir
+{
+	int error;
+};
+
+struct mfs_reply_readdir
+{
+	struct file file;
+	int result;
+	int datalen;
+};
+
+struct mfs_request_ioctl
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	unsigned int cmd;
+	unsigned long arg;
+	int data;
+	int size;
+};
+
+struct mfs_reply_ioctl
+{
+	struct file file;
+	int data;
+	int result;
+};
+
+struct mfs_request_open
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	struct inode inode;
+};
+
+struct mfs_reply_open
+{
+	struct file file;
+	struct inode inode;
+	int result;
+};
+
+struct mfs_request_fsync
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct file file;
+	int datasync;
+};
+
+struct mfs_reply_fsync
+{
+	struct file file;
+	int result;
+};
+
+struct mfs_request_revalidate
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+};
+
+struct mfs_reply_revalidate
+{
+	struct subinode iinfo;
+	int result;
+};
+
+struct mfs_request_express
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	int namelen;
+	unsigned int follow;
+	int link_count;
+	int total_link_count;
+	struct mfs_completion complete;
+};
+
+struct mfs_reply_express
+{
+	mfs_handle_t handle;
+	struct subinode iinfo;
+	int namelen;
+	struct mfs_completion complete;
+	int result;
+};
+
+struct mfs_request_checkpath
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+};
+
+struct mfs_reply_checkpath
+{
+	int namelen;
+};
+
+struct mfs_request_setattr
+{
+	struct mfs_cred cred;
+	mfs_handle_t handle;
+	struct iattr attr;
+};
+
+struct mfs_reply_setattr
+{
+	int result;
+};
+
+struct mfs_request_attach_handle
+{
+	mfs_handle_t handle;
+};
+
+struct mfs_reply_attach_handle
+{
+	int result;
+};
+
+struct mfs_request_touch_handle
+{
+	mfs_handle_t handle;
+};
+
+struct mfs_reply_touch_handle
+{
+	int result;
+};
+
+struct mfs_request_dispose_handle
+{
+	mfs_handle_t handle;
+};
+
+struct mfs_server_contact *mfs_alloc_service(void);
+void mfs_release_contact(struct mfs_client_contact *);
+int mfs_client_contact_has_data(struct mfs_client_contact *);
+void mfs_end_serve(struct mfs_server_contact *);
+int mfs_server_send(struct mfs_server_contact *, int, void *, int, void *, int, void *, int);
+int mfs_client_send(struct mfs_client_contact *, int, void *, int, void *, int, void *, int);
+int mfs_server_receive(struct mfs_server_contact *, void **, void **, void **);
+int mfs_client_receive(struct mfs_client_contact *, void **, void **, void **);
+struct mfs_client_contact *mfs_new_request(int, int, void *, int, void *, int, void *, int);
+void mfs_make_servers(void);
+void mfs_new_request_arrived(void);
+void mfs_serve(struct mfs_server_contact *, int, void *, void *, void *);
+
+int mfs_client_attach_handle(int, mfs_handle_t);
+void mfs_client_dispose_handle(int, mfs_handle_t);
+int mfs_client_touch_handle(int, mfs_handle_t);
+int mfs_client_open(int, mfs_handle_t, struct inode *, struct file *);
+int mfs_client_close(int, mfs_handle_t, struct inode *, struct file *);
+int mfs_client_llseek(int, mfs_handle_t, struct file *, loff_t, int);
+ssize_t mfs_client_read(int, mfs_handle_t, struct file *, char *, size_t, loff_t *);
+ssize_t mfs_client_write(int, mfs_handle_t, struct file *, char *, size_t, loff_t *, long);
+int mfs_client_readdir(int, mfs_handle_t, struct file *, void *, filldir_t, int, int, int *, int *);
+int mfs_client_ioctl(int, mfs_handle_t, struct file *, unsigned int, unsigned long, int, int *);
+int mfs_client_fsync(int, mfs_handle_t, struct file *, int);
+int mfs_client_revalidate(int, mfs_handle_t, struct subinode *);
+int mfs_client_express_lookup(int, mfs_handle_t *, char *, unsigned int, struct subinode *, char **, struct mfs_completion *);
+char *mfs_client_check_path(int, mfs_handle_t);
+int mfs_client_setattr(int, mfs_handle_t, struct iattr *);
+void mfs_throw_garbage(void);
+int mfs_client_daemon(void *);
+int mfs_kill(char *);
+void mfs_tuneinfo(char *);
+#ifdef CONFIG_MOSIX_DFSA
+int mfs_add_stats(struct mfs_stats *, struct mfs_stats *, struct mosix_task *);
+#else
+static inline int mfs_add_stats(struct mfs_stats *x, struct mfs_stats *y, struct mosix_task *z)
+{
+	return(0);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
+extern struct task_struct *mfs_main_server_task;
+
+static inline int
+file_is_mfs(struct file *file)
+{
+	struct dentry *dp;
+	struct inode *ip;
+	struct super_block *sb;
+
+	return(file && (dp = file->f_dentry) && (ip = dp->d_inode) &&
+		(sb = ip->i_sb) && sb->s_magic == MFS_SUPER_MAGIC);
+}
+
+/* statistic collection: */
+
+#ifdef CONFIG_MOSIX_DFSA
+extern void mfs_count(int, int, int);
+
+#define	mfs_count_attach_handle(w)	mfs_count(w, 0, 0)
+#define	mfs_count_touch_handle(w)	mfs_count(w, 0, 0)
+#define	mfs_count_dispose_handle(w)	mfs_count(w, 0, 0)
+#define	mfs_count_llseek(w)		mfs_count(w, 0, 0)
+#define	mfs_count_read(w,n)		mfs_count(w, n, 0)
+#define	mfs_count_write(w,n)		mfs_count(w, 0, n)
+#define	mfs_count_readdir(w,p,b)	mfs_count(w, b, (p) * sizeof(int))
+#define	mfs_count_ioctl(w)		mfs_count(w, 0, 0)
+#define	mfs_count_open(w)		mfs_count(w, 0, 0)
+#define	mfs_count_fsync(w)		mfs_count(w, 0, 0)
+#define	mfs_count_setattr(w)		mfs_count(w, 0, 0)
+#define	mfs_count_revalidate(w)		mfs_count(w, 0, 0)
+#define	mfs_count_express(w,l) 		mfs_count(w, 0, l)
+#define	mfs_count_check_path(w,l)	mfs_count(w, 0, l)
+#define	mfs_count_notify_change(w)	mfs_count(w, 0, 0)
+#define mfs_count_statfs(w)             mfs_count(w, 0, 0)
+#else
+#define	mfs_count_attach_handle(w)	do {} while(0)
+#define	mfs_count_touch_handle(w)	do {} while(0)
+#define	mfs_count_dispose_handle(w)	do {} while(0)
+#define	mfs_count_llseek(w)		do {} while(0)
+#define	mfs_count_read(w,n)		do {} while(0)
+#define	mfs_count_write(w,n)		do {} while(0)
+#define	mfs_count_readdir(w,p,b)	do {} while(0)
+#define	mfs_count_ioctl(w)		do {} while(0)
+#define	mfs_count_open(w)		do {} while(0)
+#define	mfs_count_fsync(w)		do {} while(0)
+#define	mfs_count_setattr(w)		do {} while(0)
+#define	mfs_count_revalidate(w)		do {} while(0)
+#define	mfs_count_express(w,l)	do {} while(0)
+#define	mfs_count_check_path(w,l)	do {} while(0)
+#define	mfs_count_notify_change(w)	do {} while(0)A
+#define mfs_count_statfs(w) 		do {} while(0)
+#endif /* CONFIG_MOSIX_DFSA */
+
+#endif /* _MFS_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/mfs_socket.h linux-openmosix/include/linux/mfs_socket.h
--- linux/include/linux/mfs_socket.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/mfs_socket.h	2002-02-14 11:35:25.000000000 +0100
@@ -0,0 +1,40 @@
+#ifndef _MFS_SOCKET_H
+#define _MFS_SOCKET_H
+
+struct socket;
+
+struct mfs_message_header
+{
+	char version;
+	char first;
+	short hdsz;
+	int caller;
+	int serial;
+	int type;
+	int dat1sz;
+	int dat2sz;
+};
+
+struct socket *mfs_open_main_socket(void);
+struct socket *mfs_new_connection(struct socket *, int *);
+struct socket *mfs_connect_to(int);
+int mfs_socket_has_data(struct socket *);
+int mfs_socket_is_closed(struct socket *);
+int mfs_send(struct socket *, int, int, int, void *, int, void *, int, void *, int);
+int mfs_receive(struct socket *, int, int *, struct mfs_message_header *, void **, void **, void **);
+int mfs_set_main_ownership(struct socket *, int);
+void mfs_close_socket(struct socket *);
+void mfs_monitor_client_contacts(void);
+
+/* 2nd parameter of mfs_receive: */
+enum
+{
+	MFS_FIRST_RECEIVE,	/* obtain serial */
+	MFS_MUST_MATCH,		/* fail if serial does not match */
+	MFS_SKIP_OTHERS,	/* skip packet if serial does not match */
+	MFS_JUST_HEADER		/* preliminary header check */
+};
+
+#define	MFS_MAIN_PORT	0xD302
+
+#endif /* _MFS__SOCKET_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/mman.h linux-openmosix/include/linux/mman.h
--- linux/include/linux/mman.h	2000-03-15 03:21:56.000000000 +0100
+++ linux-openmosix/include/linux/mman.h	2004-02-05 10:51:27.000000000 +0100
@@ -6,4 +6,7 @@
 #define MREMAP_MAYMOVE	1
 #define MREMAP_FIXED	2
 
+extern int vm_enough_memory(long pages);
+extern void vm_unacct_vma(struct vm_area_struct *vma);
+
 #endif /* _LINUX_MMAN_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/mm.h linux-openmosix/include/linux/mm.h
--- linux/include/linux/mm.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/linux/mm.h	2004-02-05 10:51:27.000000000 +0100
@@ -103,9 +103,10 @@
 #define VM_DONTCOPY	0x00020000      /* Do not copy this vma on fork */
 #define VM_DONTEXPAND	0x00040000	/* Cannot expand with mremap() */
 #define VM_RESERVED	0x00080000	/* Don't unmap it from swap_out */
+#define VM_ACCOUNT	0x00100000	/* Is a VM accounted object */
 
 #ifndef VM_STACK_FLAGS
-#define VM_STACK_FLAGS	0x00000177
+#define VM_STACK_FLAGS	(0x00000177 | VM_ACCOUNT)
 #endif
 
 #define VM_READHINTMASK			(VM_SEQ_READ | VM_RAND_READ)
@@ -179,6 +180,10 @@
 	void *virtual;			/* Kernel virtual address (NULL if
 					   not kmapped, ie. highmem) */
 #endif /* CONFIG_HIGMEM || WANT_PAGE_VIRTUAL */
+#ifdef CONFIG_MOSIX
+	char young;
+	unsigned long last_young;
+#endif /* CONFIG_MOSIX */
 } mem_map_t;
 
 /*
@@ -589,6 +594,48 @@
 		return 0;
 }
 
+#ifdef CONFIG_MOSIX
+static inline unsigned long
+do_mmap_pgoff_down(struct file *file, unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flag, unsigned long pgoff)
+{
+	int initially_local = !(current->mosix.dflags & DDEPUTY);
+	struct mm_struct *mm = current->mm;
+	unsigned long result;
+
+	if(initially_local)
+	{
+		down_write(&mm->mmap_sem);
+#ifdef CONFIG_MOSIX_FS
+		current->mosix.dirty_bits |= MMAP_MMDOWNED;
+#endif /* CONFIG_MOSIX_FS */
+	}
+	result = do_mmap_pgoff(file, addr, len, prot, flag, pgoff);
+	if(initially_local)
+	{
+		up_write(&mm->mmap_sem);
+#ifdef CONFIG_MOSIX_FS
+		current->mosix.dirty_bits &= ~MMAP_MMDOWNED;
+#endif /* CONFIG_MOSIX_FS */
+	}
+	return(result);
+}
+
+static inline unsigned long do_mmap_down(struct file *file, unsigned long addr,
+	unsigned long len, unsigned long prot,
+	unsigned long flag, unsigned long offset)
+{
+	unsigned long ret = -EINVAL;
+	if ((offset + PAGE_ALIGN(len)) < offset)
+		goto out;
+	if (!(offset & ~PAGE_MASK))
+		ret = do_mmap_pgoff_down(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+out:
+	return ret;
+}
+
+#endif /* CONFIG_MOSIX */
+
 struct zone_t;
 /* filemap.c */
 extern void remove_inode_page(struct page *);
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/mount.h linux-openmosix/include/linux/mount.h
--- linux/include/linux/mount.h	2001-10-05 22:05:55.000000000 +0200
+++ linux-openmosix/include/linux/mount.h	2004-02-05 10:51:27.000000000 +0100
@@ -29,6 +29,11 @@
 	int mnt_flags;
 	char *mnt_devname;		/* Name of device e.g. /dev/dsk/hda1 */
 	struct list_head mnt_list;
+#ifdef CONFIG_MOSIX_DFSA
+	short mnt_dfsa;		/* what should be */
+	short mnt_dfsano;	/* what is */
+	short mnt_dfsaprev;	/* what was */
+#endif /* CONFIG_MOSIX_DFSA */
 };
 
 static inline struct vfsmount *mntget(struct vfsmount *mnt)
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/net.h linux-openmosix/include/linux/net.h
--- linux/include/linux/net.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/linux/net.h	2004-02-05 10:51:27.000000000 +0100
@@ -62,6 +62,12 @@
 #define SOCK_ASYNC_WAITDATA	1
 #define SOCK_NOSPACE		2
 
+#ifdef CONFIG_MOSIX
+#define SOCK_INTER_MOSIX	3	/* used internally in kernel-mode */
+#define	SOCK_WAIT_MFSDATA	4	/* waiting for MFS data */
+#define	SOCK_OOB_IN		5	/* OOB received on MOSIX socket */
+#endif /* CONFIG_MOSIX */
+
 struct socket
 {
 	socket_state		state;
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/personality.h linux-openmosix/include/linux/personality.h
--- linux/include/linux/personality.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/linux/personality.h	2004-02-05 10:51:27.000000000 +0100
@@ -127,4 +127,8 @@
 		__MOD_DEC_USE_COUNT(ep->module);	\
 } while (0)
 
+#ifdef CONFIG_MOSIX
+extern struct exec_domain *lookup_exec_domain(unsigned long);
+#endif /* CONFIG_MOSIX */
+
 #endif /* _LINUX_PERSONALITY_H */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/pipe_fs_i.h linux-openmosix/include/linux/pipe_fs_i.h
--- linux/include/linux/pipe_fs_i.h	2001-04-25 23:18:23.000000000 +0200
+++ linux-openmosix/include/linux/pipe_fs_i.h	2004-02-05 10:51:27.000000000 +0100
@@ -9,6 +9,10 @@
 	unsigned int start;
 	unsigned int readers;
 	unsigned int writers;
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+	unsigned int exceptions;
+	unsigned long reading_bytes;
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
 	unsigned int waiting_readers;
 	unsigned int waiting_writers;
 	unsigned int r_counter;
@@ -38,6 +42,14 @@
 #define PIPE_MAX_RCHUNK(inode)	(PIPE_SIZE - PIPE_START(inode))
 #define PIPE_MAX_WCHUNK(inode)	(PIPE_SIZE - PIPE_END(inode))
 
+#ifdef CONFIG_MOSIX_PIPE_EXCEPTIONS
+#define	PIPE_EXCEPTIONS(inode)	((inode).i_pipe->exceptions)
+#define	PIPE_READING_BYTES(inode)	((inode).i_pipe->reading_bytes)
+
+#define	PIPE_EXCEPTION_INPUT	1
+#define	PIPE_EXCEPTION_NOINPUT	2
+#endif /* CONFIG_MOSIX_PIPE_EXCEPTIONS */
+
 /* Drop the inode semaphore and wait for a pipe event, atomically */
 void pipe_wait(struct inode * inode);
 
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/proc_fs.h linux-openmosix/include/linux/proc_fs.h
--- linux/include/linux/proc_fs.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/linux/proc_fs.h	2004-02-05 10:51:27.000000000 +0100
@@ -90,6 +90,9 @@
 void proc_pid_delete_inode(struct inode *inode);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 
+#ifdef CONFIG_MOSIX
+extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
+#endif /* CONFIG_MOSIX */
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 						struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/remote_fs_i.h linux-openmosix/include/linux/remote_fs_i.h
--- linux/include/linux/remote_fs_i.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/include/linux/remote_fs_i.h	2002-02-14 11:35:25.000000000 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2000, 2001, Amnon Barak (amnon@cs.huji.ac.il)
+ *
+ * Permission to use this software is hereby granted under the terms of the
+ * GNU General Public License, as published by the Free Software Foundation.
+ *
+ * THIS  SOFTWARE  IS  PROVIDED IN ITS  "AS IS"  CONDITION, WITH NO WARRANTY
+ * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
+ */
+/*
+ * Author(s): Amnon Shiloh.
+ */
+#ifndef _LINUX_REMOTE_FS_I_H
+#define _LINUX_REMOTE_FS_I_H
+#ifdef CONFIG_MOSIX
+
+struct vm_area_struct;
+typedef struct page * (*nopage_t)(struct vm_area_struct *, unsigned long, int);
+
+struct remote_inode_info
+{
+	int origin;			/* node of origin */
+	struct dentry *dp;		/* dentry pointer on origin */
+	uint64_t unique;		/* unique version on origin */
+	nopage_t nopage;		/* nopage routine */
+};
+
+#define	home_file(f)	(*((struct file **)(&(f)->f_pos)))
+
+#endif /* CONFIG_MOSIX */
+#endif
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/sched.h linux-openmosix/include/linux/sched.h
--- linux/include/linux/sched.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/linux/sched.h	2004-02-05 10:51:27.000000000 +0100
@@ -29,6 +29,12 @@
 
 struct exec_domain;
 
+#ifdef CONFIG_MOSIX
+#include <hpc/hpctask.h>
+#else
+#define MOSIX_INIT_TASK(tsk)
+#endif /* CONFIG_MOSIX */
+
 /*
  * cloning flags:
  */
@@ -91,6 +97,9 @@
 #define TASK_UNINTERRUPTIBLE	2
 #define TASK_ZOMBIE		4
 #define TASK_STOPPED		8
+#ifdef CONFIG_MOSIX
+#define	TASK_SAME		16
+#endif /* CONFIG_MOSIX */
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
@@ -181,6 +190,25 @@
 	fd_set close_on_exec_init;
 	fd_set open_fds_init;
 	struct file * fd_array[NR_OPEN_DEFAULT];
+#ifdef CONFIG_MOSIX_DFSA
+	atomic_t users;		/* the real count, excluding /proc grabs */
+	int count_dropped_to_one;
+	int maxclosed;
+	fd_set *closed;
+	fd_set closed_fds_init;
+	int maxopened;
+	fd_set *opened;
+	fd_set opened_fds_init;
+	int maxmod;
+	fd_set *modified;
+	fd_set modified_fds_init;
+#define	INIT_FILES_DFSA , users : ATOMIC_INIT(1), \
+			  closed: &init_files.closed_fds_init, \
+			  opened: &init_files.opened_fds_init, \
+			  modified: &init_files.modified_fds_init,
+#else
+#define	INIT_FILES_DFSA
+#endif /* CONFIG_MOSIX_DFSA */
 };
 
 #define INIT_FILES \
@@ -196,6 +224,7 @@
 	close_on_exec_init: { { 0, } }, 		\
 	open_fds_init:	{ { 0, } }, 			\
 	fd_array:	{ NULL, } 			\
+	INIT_FILES_DFSA					\
 }
 
 /* Maximum number of active map areas.. This is a random (large) number */
@@ -231,8 +260,23 @@
 
 	/* Architecture-specific MM context */
 	mm_context_t context;
+#ifdef CONFIG_MOSIX
+	atomic_t mm_kiocount;
+	atomic_t mm_realusers;
+	unsigned long last_memsort;
+	int used, unused, swapped;	/* break-down of memory pages */
+	int private_unused;		/* unused but not active/inactive */
+/*
+	int private_unused;
+*/
+	int mark;
 };
 
+#define	INIT_MM_MOSIX	mm_kiocount: ATOMIC_INIT(0), mm_realusers: ATOMIC_INIT(1),
+#else
+#define	INIT_MM_MOSIX
+#endif /* CONFIG_MOSIX */
+
 extern int mmlist_nr;
 
 #define INIT_MM(name) \
@@ -244,6 +288,7 @@
 	mmap_sem:	__RWSEM_INITIALIZER(name.mmap_sem), \
 	page_table_lock: SPIN_LOCK_UNLOCKED, 		\
 	mmlist:		LIST_HEAD_INIT(name.mmlist),	\
+	INIT_MM_MOSIX					\
 }
 
 struct signal_struct {
@@ -343,9 +388,9 @@
 	pid_t tgid;
 	/* boolean value for session group leader */
 	int leader;
-	/* 
+	/*
 	 * pointers to (original) parent process, youngest child, younger sibling,
-	 * older sibling, respectively.  (p->father can be replaced with 
+	 * older sibling, respectively.  (p->father can be replaced with
 	 * p->p_pptr->pid)
 	 */
 	struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
@@ -406,13 +451,15 @@
 	int (*notifier)(void *priv);
 	void *notifier_data;
 	sigset_t *notifier_mask;
-	
+
 /* Thread group tracking */
    	u32 parent_exec_id;
    	u32 self_exec_id;
 /* Protection of (de-)allocation: mm, files, fs, tty */
 	spinlock_t alloc_lock;
-
+#ifdef CONFIG_MOSIX
+	struct mosix_task mosix;
+#endif /* CONFIG_MOSIX */
 /* journalling filesystem info */
 	void *journal_info;
 };
@@ -508,6 +555,7 @@
     blocked:		{{0}},						\
     alloc_lock:		SPIN_LOCK_UNLOCKED,				\
     journal_info:	NULL,						\
+MOSIX_INIT_TASK(tsk)                            \
 }
 
 
@@ -554,9 +602,23 @@
 
 	for(p = *htable; p && p->pid != pid; p = p->pidhash_next)
 		;
+#ifdef CONFIG_MOSIX
+	if(p && (p->mosix.dflags & DREMOTE))
+		p = NULL;
+#endif /* CONFIG_MOSIX */
+	return p;
+}
 
+#ifdef CONFIG_MOSIX
+static inline struct task_struct *find_any_task_by_pid(int pid)
+{
+	struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];
+
+	for(p = *htable; p && p->pid != pid; p = p->pidhash_next)
+		;
 	return p;
 }
+#endif /* CONFIG_MOSIX */
 
 #define task_has_cpu(tsk) ((tsk)->cpus_runnable != ~0UL)
 
@@ -679,6 +741,14 @@
 
 static inline void recalc_sigpending(struct task_struct *t)
 {
+#ifdef CONFIG_MOSIX
+	t->mosix.ignoreoldsigs = 0;
+	if(t->mosix.dflags & DHEAVYSLEEP)
+		t->sigpending = 0;
+	else if(t->mosix.dflags & DFAKESIGNAL)
+		t->sigpending = 1;
+	else
+#endif /* CONFIG_MOSIX */
 	t->sigpending = has_pending_signals(&t->pending.signal, &t->blocked);
 }
 
@@ -711,12 +781,12 @@
  * fsuser(). This is done, along with moving fsuser() checks to be
  * last.
  *
- * These will be removed, but in the mean time, when the SECURE_NOROOT 
+ * These will be removed, but in the mean time, when the SECURE_NOROOT
  * flag is set, uids don't grant privilege.
  */
 static inline int suser(void)
 {
-	if (!issecure(SECURE_NOROOT) && current->euid == 0) { 
+	if (!issecure(SECURE_NOROOT) && current->euid == 0) {
 		current->flags |= PF_SUPERPRIV;
 		return 1;
 	}
@@ -733,7 +803,7 @@
 }
 
 /*
- * capable() checks for a particular capability.  
+ * capable() checks for a particular capability.
  * New privilege checks should use this interface, rather than suser() or
  * fsuser(). See include/linux/capability.h for defined capabilities.
  */
@@ -803,6 +873,9 @@
 extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 
 extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+#ifdef CONFIG_MOSIX
+extern long user_thread(int (*fn)(void *), void * arg, unsigned long flags);
+#endif /* CONFIG_MOSIX */
 
 #define __wait_event(wq, condition) 					\
 do {									\
@@ -847,7 +920,7 @@
 	current->state = TASK_RUNNING;					\
 	remove_wait_queue(&wq, &__wait);				\
 } while (0)
-	
+
 #define wait_event_interruptible(wq, condition)				\
 ({									\
 	int __ret = 0;							\
@@ -889,10 +962,41 @@
 
 #define thread_group_leader(p)	(p->pid == p->tgid)
 
+#ifdef CONFIG_MOSIX
+#define for_each_local_task(p) \
+	for (p = &init_task ; (p = p->next_task) != &init_task ; ) \
+	if(!(p->mosix.dflags & DREMOTE))
+
+static inline long
+LOGICAL_STATE(struct task_struct *p)
+{
+	int result;
+	unsigned long flags;
+
+	read_lock_irqsave(&p->mosix.state_lock, flags);
+	result = (p->mosix.bstate == TASK_SAME) ? p->state : p->mosix.bstate;
+	read_unlock_irqrestore(&p->mosix.state_lock, flags);
+	return(result);
+}
+
+extern void run_on(struct task_struct *);
+extern void run_off(struct task_struct *);
+
+#define	need_interim_while_asleep()	mosix_need_while_asleep()
+#define	run_interim_while_asleep()	mosix_run_while_asleep()
+#endif /* CONFIG_MOSIX */
+
+#ifndef CONFIG_MOSIX
+#define LOGICAL_STATE(p)	(p->state)
+#endif /* !CONFIG_MOSIX */
+
 static inline void del_from_runqueue(struct task_struct * p)
 {
 	nr_running--;
 	p->sleep_time = jiffies;
+#ifdef CONFIG_MOSIX
+	run_off(p);
+#endif /* CONFIG_MOSIX */
 	list_del(&p->run_list);
 	p->run_list.next = NULL;
 }
@@ -932,6 +1036,11 @@
 	char *res;
 	struct vfsmount *rootmnt;
 	struct dentry *root;
+#if defined(CONFIG_MOSIX_DFSA) || defined(CONFIG_MOSIX_FS)
+	if(dentry->d_inode && dentry->d_inode->i_op &&
+		dentry->d_inode->i_op->check_path)
+		dentry->d_inode->i_op->check_path(dentry);
+#endif /* CONFIG_MOSIX_DFSA || CONFIG_MOSIX_FS */
 	read_lock(&current->fs->lock);
 	rootmnt = mntget(current->fs->rootmnt);
 	root = dget(current->fs->root);
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/smp_lock.h linux-openmosix/include/linux/smp_lock.h
--- linux/include/linux/smp_lock.h	2001-11-22 20:46:27.000000000 +0100
+++ linux-openmosix/include/linux/smp_lock.h	2004-02-05 10:51:27.000000000 +0100
@@ -11,6 +11,11 @@
 #define reacquire_kernel_lock(task)		do { } while(0)
 #define kernel_locked() 1
 
+#ifdef CONFIG_MOSIX
+#define	lock_mosix()				do {} while(0)
+#define	unlock_mosix()				do {} while(0)
+#endif /* CONFIG_MOSIX */
+
 #else
 
 #include <asm/smplock.h>
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/spinlock.h linux-openmosix/include/linux/spinlock.h
--- linux/include/linux/spinlock.h	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/include/linux/spinlock.h	2004-02-05 10:51:27.000000000 +0100
@@ -149,6 +149,10 @@
 #define write_lock(lock)	(void)(lock) /* Not "unused variable". */
 #define write_unlock(lock)	do { } while(0)
 
+#ifdef CONFIG_MOSIX
+#define	can_read_lock(rw)	(1)
+#endif /* CONFIG_MOSIX */
+
 #endif /* !SMP */
 
 /* "lock on reference count zero" */
diff -Naur --exclude=CVS --exclude=configs linux/include/linux/wait.h linux-openmosix/include/linux/wait.h
--- linux/include/linux/wait.h	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/include/linux/wait.h	2004-02-05 10:51:27.000000000 +0100
@@ -190,6 +190,21 @@
 	return !list_empty(&q->task_list);
 }
 
+#ifdef CONFIG_MOSIX
+#if BITS_PER_LONG == 32
+#define	KERNEL_ADDRESS_BIT	0x80000000
+#else
+#error please fill in: use a bit that is always set in kernel addresses.
+#endif
+#define	IN_MOSIX_CONTEXT(p)	(!(((unsigned long) (p)) & KERNEL_ADDRESS_BIT))
+#define	MOSIX_CONTEXT(p)	((struct task_struct *)\
+				(((unsigned long) (p)) & ~KERNEL_ADDRESS_BIT))
+#define	NORMAL_CONTEXT(p)	((struct task_struct *)\
+				(((unsigned long) (p)) | KERNEL_ADDRESS_BIT))
+
+extern void adjust_task_mosix_context(struct task_struct **);
+#endif /* CONFIG_MOSIX */
+
 static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
 {
 #if WAITQUEUE_DEBUG
@@ -200,6 +215,9 @@
 	if (!head->task_list.next || !head->task_list.prev)
 		WQ_BUG();
 #endif
+#ifdef CONFIG_MOSIX
+	adjust_task_mosix_context(&new->task);
+#endif /* CONFIG_MOSIX */
 	list_add(&new->task_list, &head->task_list);
 }
 
@@ -217,6 +235,9 @@
 	if (!head->task_list.next || !head->task_list.prev)
 		WQ_BUG();
 #endif
+#ifdef CONFIG_MOSIX
+	adjust_task_mosix_context(&new->task);
+#endif /* CONFIG_MOSIX */
 	list_add_tail(&new->task_list, &head->task_list);
 }
 
diff -Naur --exclude=CVS --exclude=configs linux/include/net/bluetooth/rfcomm.h linux-openmosix/include/net/bluetooth/rfcomm.h
--- linux/include/net/bluetooth/rfcomm.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/net/bluetooth/rfcomm.h	2004-02-05 10:51:28.000000000 +0100
@@ -26,7 +26,7 @@
 */
 
 /*
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #ifndef __RFCOMM_H
diff -Naur --exclude=CVS --exclude=configs linux/include/net/sock.h linux-openmosix/include/net/sock.h
--- linux/include/net/sock.h	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/include/net/sock.h	2004-02-05 10:51:28.000000000 +0100
@@ -560,6 +560,9 @@
 	/* Hole of 3 bytes. Try to pack. */
 	int			route_caps;
 	int			proc;
+#ifdef CONFIG_MOSIX
+	struct task_struct	*owner;
+#endif /* CONFIG_MOSIX */
 	unsigned long	        lingertime;
 
 	int			hashent;
diff -Naur --exclude=CVS --exclude=configs linux/init/main.c linux-openmosix/init/main.c
--- linux/init/main.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/init/main.c	2004-02-05 10:51:28.000000000 +0100
@@ -74,6 +74,10 @@
 #include <asm/smp.h>
 #endif
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -567,6 +571,9 @@
 	 * initmem segments and start the user-mode stuff..
 	 */
 	free_initmem();
+#ifdef CONFIG_MOSIX
+	init_mosix();
+#endif /* CONFIG_MOSIX */
 	unlock_kernel();
 	
 	/*
diff -Naur --exclude=CVS --exclude=configs linux/ipc/shm.c linux-openmosix/ipc/shm.c
--- linux/ipc/shm.c	2002-08-03 02:39:46.000000000 +0200
+++ linux-openmosix/ipc/shm.c	2004-02-05 10:51:29.000000000 +0100
@@ -12,7 +12,8 @@
  * Make shmmax, shmall, shmmni sysctl'able, Christoph Rohland <cr@sap.com>
  * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com>
  * Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com>
- *
+ * 
+ * Some changes by Moshe Bar to eliminate fh leaking problem in openMosix
  */
 
 #include <linux/config.h>
@@ -23,7 +24,7 @@
 #include <linux/mman.h>
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
-
+#include <linux/hpc.h>
 #include "util.h"
 
 struct shmid_kernel /* private to the kernel */
@@ -495,6 +496,9 @@
 		 *	Instead we set a destroyed flag, and then blow
 		 *	the name away when the usage hits zero.
 		 */
+#ifdef CONFIG_MOSIX
+ 		/* mosix_rebuild_file_list();  fh leakage fixed - moshe */
+#endif
 		down(&shm_ids.sem);
 		shp = shm_lock(shmid);
 		err = -EINVAL;
@@ -627,6 +631,9 @@
 	shp->shm_nattch++;
 	shm_unlock(shmid);
 
+#ifdef CONFIG_MOSIX
+	user_addr = (void *) do_mmap_down (file, addr, size, prot, flags, 0);
+#else
 	down_write(&current->mm->mmap_sem);
 	if (addr && !(shmflg & SHM_REMAP)) {
 		user_addr = ERR_PTR(-EINVAL);
@@ -645,6 +652,7 @@
 
 invalid:
 	up_write(&current->mm->mmap_sem);
+#endif /* CONFIG_MOSIX */
 
 	down (&shm_ids.sem);
 	if(!(shp = shm_lock(shmid)))
@@ -675,6 +683,11 @@
 	struct vm_area_struct *shmd, *shmdnext;
 	int retval = -EINVAL;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		return(0);
+	mosix_rebuild_file_list();
+#endif /* CONFIG_MOSIX */
 	down_write(&mm->mmap_sem);
 	for (shmd = mm->mmap; shmd; shmd = shmdnext) {
 		shmdnext = shmd->vm_next;
diff -Naur --exclude=CVS --exclude=configs linux/kernel/acct.c linux-openmosix/kernel/acct.c
--- linux/kernel/acct.c	2002-08-03 02:39:46.000000000 +0200
+++ linux-openmosix/kernel/acct.c	2004-02-05 10:51:30.000000000 +0100
@@ -57,6 +57,9 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
 /*
  * These constants control the amount of freespace that suspend and
  * resume the process accounting system, and the time delay between
@@ -203,6 +206,10 @@
 	}
 	unlock_kernel();
 	if (old_acct) {
+#ifdef CONFIG_MOSIX
+		if(current->mosix.dflags & DDEPUTY)
+			mosix_deputy_rusage(2);
+#endif /* CONFIG_MOSIX */
 		do_acct_process(0,old_acct);
 		filp_close(old_acct, NULL);
 	}
@@ -279,6 +286,10 @@
 	unsigned long vsize;
 	unsigned long flim;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DREMOTE)
+		return;
+#endif /* CONFIG_MOSIX */
 	/*
 	 * First check to see if there is enough free_space to continue
 	 * the process accounting system.
@@ -324,6 +335,10 @@
 		}
 		up_read(&current->mm->mmap_sem);
 	}
+#ifdef CONFIG_MOSIX
+	else	/* were we a DEPUTY?  otherwise, "mosix.exit_mem" is 0 anyway */
+		vsize = current->mosix.exit_mem;
+#endif /* CONFIG_MOSIX */
 	vsize = vsize / 1024;
 	ac.ac_mem = encode_comp_t(vsize);
 	ac.ac_io = encode_comp_t(0 /* current->io_usage */);	/* %% */
diff -Naur --exclude=CVS --exclude=configs linux/kernel/capability.c linux-openmosix/kernel/capability.c
--- linux/kernel/capability.c	2000-06-24 06:06:37.000000000 +0200
+++ linux-openmosix/kernel/capability.c	2004-02-05 10:51:30.000000000 +0100
@@ -7,6 +7,9 @@
 
 #include <linux/mm.h>
 #include <asm/uaccess.h>
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
 
 kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
 
@@ -85,7 +88,11 @@
 
      /* FIXME: do we need to have a write lock here..? */
      read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+     for_each_local_task(target) {
+#else
      for_each_task(target) {
+#endif /* CONFIG_MOSIX */
              if (target->pgrp != pgrp)
                      continue;
              target->cap_effective   = *effective;
@@ -106,7 +113,11 @@
      /* FIXME: do we need to have a write lock here..? */
      read_lock(&tasklist_lock);
      /* ALL means everyone other than self or 'init' */
+#ifdef CONFIG_MOSIX
+     for_each_local_task(target) {
+#else
      for_each_task(target) {
+#endif /* CONFIG_MOSIX */
              if (target == current || target->pid == 1)
                      continue;
              target->cap_effective   = *effective;
@@ -212,5 +223,8 @@
      }
 spin_out:
      spin_unlock(&task_capability_lock);
+#ifdef CONFIG_MOSIX
+     mosix_sync_caps(effective);
+#endif /* CONFIG_MOSIX */
      return error;
 }
diff -Naur --exclude=CVS --exclude=configs linux/kernel/exec_domain.c linux-openmosix/kernel/exec_domain.c
--- linux/kernel/exec_domain.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/kernel/exec_domain.c	2004-02-05 10:51:30.000000000 +0100
@@ -16,6 +16,10 @@
 #include <linux/sched.h>
 #include <linux/sysctl.h>
 #include <linux/types.h>
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#include <asm/namei.h>
+#endif /* CONFIG_MOSIX */
 
 
 static void default_handler(int, struct pt_regs *);
@@ -73,7 +77,11 @@
 		send_sig(SIGSEGV, current, 1);
 }
 
+#ifdef CONFIG_MOSIX
+struct exec_domain *
+#else
 static struct exec_domain *
+#endif /* CONFIG_MOSIX */
 lookup_exec_domain(u_long personality)
 {
 	struct exec_domain *	ep;
@@ -167,7 +175,11 @@
 		return 0;
 	}
 
+#ifdef CONFIG_MOSIX_DFSA
+	if (atomic_read(&current->fs->users) != 1) {
+#else
 	if (atomic_read(&current->fs->count) != 1) {
+#endif /* CONFIG_MOSIX_DFSA */
 		struct fs_struct *fsp, *ofsp;
 
 		fsp = copy_fs_struct(current->fs);
@@ -181,7 +193,11 @@
 		current->fs = fsp;
 		task_unlock(current);
 
+#ifdef CONFIG_MOSIX_DFSA
+		put_used_fs_struct(ofsp);
+#else
 		put_fs_struct(ofsp);
+#endif /* CONFIG_MOSIX_DFSA */
 	}
 
 	/*
@@ -189,6 +205,37 @@
 	 * current->fs.
 	 */
 
+#ifdef CONFIG_MOSIX
+	if((current->mosix.dflags & DDEPUTY) &&
+		personality != current->personality &&
+		mosix_deputy_personality(personality))
+	{
+		if(!current->mosix.inexec)
+			mosix_go_home(1);
+		if(current->mosix.dflags & DDEPUTY)
+		{
+			put_exec_domain(ep);
+			printk("%d(%s)-killed because it could not go back home"
+				"and\nits new personality (%ld) is not"
+				" supported where it ran (%d)\n", current->pid,
+				current->comm, personality,
+				current->mosix.whereami);
+			send_sig(SIGKILL, current, 1);
+			return(-EINVAL);
+		}
+	}
+	else if(current->mosix.dflags & DREMOTE)
+	{
+		unsigned long prev = current->personality;
+
+		current->personality = personality;
+		if(__emul_prefix())
+		{
+			current->personality = prev;
+			return(-EINVAL);
+		}
+	}
+#endif /* CONFIG_MOSIX */
 	current->personality = personality;
 	oep = current->exec_domain;
 	current->exec_domain = ep;
diff -Naur --exclude=CVS --exclude=configs linux/kernel/exit.c linux-openmosix/kernel/exit.c
--- linux/kernel/exit.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/kernel/exit.c	2004-02-05 10:51:30.000000000 +0100
@@ -16,6 +16,9 @@
 #ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
 #endif
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -85,7 +88,11 @@
 
 	fallback = -1;
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
  		if (p->session <= 0)
  			continue;
 		if (p->pgrp == pgrp) {
@@ -112,9 +119,17 @@
 	struct task_struct *p;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if ((p == ignored_task) || (p->pgrp != pgrp) ||
+#ifdef CONFIG_MOSIX
+		    (LOGICAL_STATE(p) == TASK_ZOMBIE) ||
+#else
 		    (p->state == TASK_ZOMBIE) ||
+#endif /* CONFIG_MOSIX */
 		    (p->p_pptr->pid == 1))
 			continue;
 		if ((p->p_pptr->pgrp != pgrp) &&
@@ -138,10 +153,18 @@
 	struct task_struct * p;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if (p->pgrp != pgrp)
 			continue;
+#ifdef CONFIG_MOSIX
+		if (LOGICAL_STATE(p) != TASK_STOPPED)
+#else
 		if (p->state != TASK_STOPPED)
+#endif /* CONFIG_MOSIX */
 			continue;
 		retval = 1;
 		break;
@@ -177,7 +200,11 @@
 	read_unlock(&tasklist_lock);
 }
 
+#ifdef CONFIG_MOSIX_DFSA
+void close_files(struct files_struct * files)
+#else
 static inline void close_files(struct files_struct * files)
+#endif /* CONFIG_MOSIX_DFSA */
 {
 	int i, j;
 
@@ -212,6 +239,11 @@
 		if (files->max_fdset > __FD_SETSIZE) {
 			free_fdset(files->open_fds, files->max_fdset);
 			free_fdset(files->close_on_exec, files->max_fdset);
+#ifdef CONFIG_MOSIX_DFSA
+			free_fdset(files->closed, files->max_fdset);
+			free_fdset(files->opened, files->max_fdset);
+			free_fdset(files->modified, files->max_fdset);
+#endif /* CONFIG_MOSIX_DFSA */
 		}
 		kmem_cache_free(files_cachep, files);
 	}
@@ -225,6 +257,11 @@
 		task_lock(tsk);
 		tsk->files = NULL;
 		task_unlock(tsk);
+#ifdef CONFIG_MOSIX_DFSA
+		atomic_dec(&files->users);
+		if(atomic_read(&files->users) == 1)
+			files->count_dropped_to_one = 1;
+#endif /* CONFIG_MOSIX_DFSA */
 		put_files_struct(files);
 	}
 }
@@ -255,6 +292,17 @@
 	__put_fs_struct(fs);
 }
 
+#ifdef CONFIG_MOSIX_DFSA
+inline void
+put_used_fs_struct(struct fs_struct *fs)
+{
+	atomic_dec(&fs->users);
+	if(atomic_read(&fs->users) == 1)
+		fs->count_dropped_to_one = 1;
+	__put_fs_struct(fs);
+}
+#endif /* CONFIG_MOSIX_DFSA */
+
 static inline void __exit_fs(struct task_struct *tsk)
 {
 	struct fs_struct * fs = tsk->fs;
@@ -263,7 +311,11 @@
 		task_lock(tsk);
 		tsk->fs = NULL;
 		task_unlock(tsk);
+#ifdef CONFIG_MOSIX_DFSA
+		put_used_fs_struct(fs);
+#else
 		__put_fs_struct(fs);
+#endif /* CONFIG_MOSIX_DFSA */
 	}
 }
 
@@ -307,6 +359,9 @@
 	struct mm_struct * mm = tsk->mm;
 
 	mm_release();
+#ifdef CONFIG_MOSIX
+	mosix_exit_mm(tsk);
+#endif /* CONFIG_MOSIX */
 	if (mm) {
 		atomic_inc(&mm->mm_count);
 		BUG_ON(mm != tsk->active_mm);
@@ -333,6 +388,14 @@
 	struct task_struct * p, *t;
 
 	forget_original_parent(current);
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DREMOTE)
+	{
+		current->state = TASK_ZOMBIE;
+		notify_parent(current, SIGCHLD);
+		return;
+	}
+#endif /* CONFIG_MOSIX */
 	/*
 	 * Check to see if any process groups have become orphaned
 	 * as a result of our exiting, and if they have any stopped
@@ -386,10 +449,24 @@
 	 */
 
 	write_lock_irq(&tasklist_lock);
+#ifndef CONFIG_MOSIX
 	current->state = TASK_ZOMBIE;
 	do_notify_parent(current, current->exit_signal);
+#endif /* CONFIG_MOSIX */
 	while (current->p_cptr != NULL) {
 		p = current->p_cptr;
+#ifdef CONFIG_MOSIX
+		if(p->ptrace && (p->mosix.dflags & DDEPUTY))
+		{
+			get_task_struct(p);
+			write_unlock_irq(&tasklist_lock);
+			request_process(p, NULL, PR_PTRACE_NOT_TRACED, 0);
+			p->ptrace = 0;
+			free_task_struct(p);
+			write_lock_irq(&tasklist_lock);
+			continue;
+		}
+#endif /* CONFIG_MOSIX */
 		current->p_cptr = p->p_osptr;
 		p->p_ysptr = NULL;
 		p->ptrace = 0;
@@ -399,7 +476,11 @@
 		if (p->p_osptr)
 			p->p_osptr->p_ysptr = p;
 		p->p_pptr->p_cptr = p;
+#ifdef CONFIG_MOSIX
+		if (LOGICAL_STATE(p) == TASK_ZOMBIE)
+#else
 		if (p->state == TASK_ZOMBIE)
+#endif /* CONFIG_MOSIX */
 			do_notify_parent(p, p->exit_signal);
 		/*
 		 * process group orphan check
@@ -419,6 +500,10 @@
 			write_lock_irq(&tasklist_lock);
 		}
 	}
+#ifdef CONFIG_MOSIX
+	current->state = TASK_ZOMBIE;
+	do_notify_parent(current, current->exit_signal);
+#endif /* CONFIG_MOSIX */
 	write_unlock_irq(&tasklist_lock);
 }
 
@@ -436,6 +521,9 @@
 	del_timer_sync(&tsk->real_timer);
 
 fake_volatile:
+#ifdef CONFIG_MOSIX
+	mosix_exit();
+#endif /* CONFIG_MOSIX */
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
 #endif
@@ -447,6 +535,9 @@
 	__exit_fs(tsk);
 	exit_namespace(tsk);
 	exit_sighand(tsk);
+#ifdef CONFIG_MOSIX
+	mosix_very_exit();
+#endif /* CONFIG_MOSIX */
 	exit_thread();
 
 	if (current->leader)
@@ -526,7 +617,11 @@
 			    && !(options & __WALL))
 				continue;
 			flag = 1;
+#ifdef CONFIG_MOSIX
+			switch (LOGICAL_STATE(p)) {
+#else
 			switch (p->state) {
+#endif /* CONFIG_MOSIX */
 			case TASK_STOPPED:
 				if (!p->exit_code)
 					continue;
diff -Naur --exclude=CVS --exclude=configs linux/kernel/fork.c linux-openmosix/kernel/fork.c
--- linux/kernel/fork.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/kernel/fork.c	2004-05-19 00:32:34.000000000 +0200
@@ -10,6 +10,7 @@
  * Fork is rather simple, once you get the hang of it, but the memory
  * management can be a bitch. See 'mm/memory.c': 'copy_page_range()'
  */
+/* some openMosix fork changes introduce by Moshe Bar */
 
 #include <linux/config.h>
 #include <linux/slab.h>
@@ -29,6 +30,10 @@
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /* The idle threads do not count.. */
 int nr_threads;
 int nr_running;
@@ -77,8 +82,14 @@
 	 */
 	max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8;
 
+#ifdef CONFIG_MOSIX
+	/* 1/6th of "max_threads" goes for guest tasks */
+	init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/3;
+	init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/3;
+#else
 	init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
 	init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
+#endif
 }
 
 /* Protects next_safe and last_pid. */
@@ -140,6 +151,16 @@
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+/* NOTE: "dup_mmap" is called beyond the point of no migration:
+ * this means we are no longer allowed to sleep interruptibly here without
+ * taking special measures to prevent migration (such as raising a new flag
+ * in "current->mosix.stay"),
+ * Fortunately, vm_ops->open(tmp) is rarely non-NULL and even then, it never
+ * sleeps interruptibly.  BUT if it ever does, then we must take such measures
+ * to prevent migration here.
+ */
+#endif /* CONFIG_MOSIX */
 static inline int dup_mmap(struct mm_struct * mm)
 {
 	struct vm_area_struct * mpnt, *tmp, **pprev;
@@ -230,6 +251,13 @@
 static struct mm_struct * mm_init(struct mm_struct * mm)
 {
 	atomic_set(&mm->mm_users, 1);
+#ifdef CONFIG_MOSIX
+	atomic_set(&mm->mm_realusers, 1);
+	atomic_set(&mm->mm_kiocount, 0);
+	mm->last_memsort = 0;
+	mm->used = mm->unused = mm->swapped = mm->private_unused = 0;
+	mm->mark = 0;
+#endif /* CONFIG_MOSIX */
 	atomic_set(&mm->mm_count, 1);
 	init_rwsem(&mm->mmap_sem);
 	mm->page_table_lock = SPIN_LOCK_UNLOCKED;
@@ -336,6 +364,9 @@
 
 	if (clone_flags & CLONE_VM) {
 		atomic_inc(&oldmm->mm_users);
+#ifdef CONFIG_MOSIX
+		atomic_inc(&oldmm->mm_realusers);
+#endif /* CONFIG_MOSIX */
 		mm = oldmm;
 		goto good_mm;
 	}
@@ -359,6 +390,9 @@
 
 	if (retval)
 		goto free_pt;
+#ifdef CONFIG_MOSIX
+	tsk->mosix.stay &= ~DSTAY_FOR_CLONE;
+#endif /* CONFIG_MOSIX */
 
 	/*
 	 * child gets a private LDT (if there was an LDT in the parent)
@@ -382,13 +416,28 @@
 	/* We don't need to lock fs - think why ;-) */
 	if (fs) {
 		atomic_set(&fs->count, 1);
+#ifdef CONFIG_MOSIX_DFSA
+		atomic_set(&fs->users, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 		fs->lock = RW_LOCK_UNLOCKED;
 		fs->umask = old->umask;
 		read_lock(&old->lock);
 		fs->rootmnt = mntget(old->rootmnt);
 		fs->root = dget(old->root);
+#ifdef CONFIG_MOSIX
+		if(current->mosix.dflags & (DREMOTEDAEMON|DREMOTE))
+		{
+			fs->pwdmnt = NULL;
+			fs->pwd = NULL;
+		}
+		else
+		{
+#endif /* CONFIG_MOSIX */
 		fs->pwdmnt = mntget(old->pwdmnt);
 		fs->pwd = dget(old->pwd);
+#ifdef CONFIG_MOSIX
+		}
+#endif /* CONFIG_MOSIX */
 		if (old->altroot) {
 			fs->altrootmnt = mntget(old->altrootmnt);
 			fs->altroot = dget(old->altroot);
@@ -410,6 +459,9 @@
 {
 	if (clone_flags & CLONE_FS) {
 		atomic_inc(&current->fs->count);
+#ifdef CONFIG_MOSIX_DFSA
+		atomic_inc(&current->fs->users);
+#endif /* CONFIG_MOSIX_DFSA */
 		return 0;
 	}
 	tsk->fs = __copy_fs_struct(current->fs);
@@ -446,6 +498,9 @@
 
 	if (clone_flags & CLONE_FILES) {
 		atomic_inc(&oldf->count);
+#ifdef CONFIG_MOSIX_DFSA
+		atomic_inc(&oldf->users);
+#endif /* CONFIG_MOSIX_DFSA */
 		goto out;
 	}
 
@@ -461,6 +516,9 @@
 		goto out;
 
 	atomic_set(&newf->count, 1);
+#ifdef CONFIG_MOSIX_DFSA
+	atomic_set(&newf->users, 1);
+#endif /* CONFIG_MOSIX_DFSA */
 
 	newf->file_lock	    = RW_LOCK_UNLOCKED;
 	newf->next_fd	    = 0;
@@ -469,6 +527,15 @@
 	newf->close_on_exec = &newf->close_on_exec_init;
 	newf->open_fds	    = &newf->open_fds_init;
 	newf->fd	    = &newf->fd_array[0];
+#ifdef CONFIG_MOSIX_DFSA
+	newf->closed	    = &newf->closed_fds_init;
+	newf->opened        = &newf->opened_fds_init;
+	newf->modified	    = &newf->modified_fds_init;
+	newf->maxclosed	    = 0;
+	newf->maxopened     = 0;
+	newf->maxmod	    = 0;
+	newf->count_dropped_to_one = 0;
+#endif /* CONFIG_MOSIX_DFSA */
 
 	/* We don't yet have the oldf readlock, but even if the old
            fdset gets grown now, we'll only copy up to "size" fds */
@@ -508,6 +575,11 @@
 
 	memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8);
 	memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8);
+#ifdef CONFIG_MOSIX_DFSA
+	memcpy(newf->closed->fds_bits, oldf->closed->fds_bits, open_files/8);
+	memcpy(newf->opened->fds_bits, oldf->opened->fds_bits, open_files/8);
+	memcpy(newf->modified->fds_bits, oldf->modified->fds_bits, open_files/8);
+#endif /* CONFIG_MOSIX_DFSA */
 
 	for (i = open_files; i != 0; i--) {
 		struct file *f = *old_fds++;
@@ -529,6 +601,11 @@
 		
 		memset(&newf->open_fds->fds_bits[start], 0, left);
 		memset(&newf->close_on_exec->fds_bits[start], 0, left);
+#ifdef CONFIG_MOSIX_DFSA
+		memset(&newf->closed->fds_bits[start], 0, left);
+		memset(&newf->opened->fds_bits[start], 0, left);
+		memset(&newf->modified->fds_bits[start], 0, left);
+#endif /* CONFIG_MOSIX_DFSA */
 	}
 
 	tsk->files = newf;
@@ -539,6 +616,11 @@
 out_release:
 	free_fdset (newf->close_on_exec, newf->max_fdset);
 	free_fdset (newf->open_fds, newf->max_fdset);
+#ifdef CONFIG_MOSIX_DFSA
+	free_fdset (newf->closed, newf->max_fdset);
+	free_fdset (newf->opened, newf->max_fdset);
+	free_fdset (newf->modified, newf->max_fdset);
+#endif /* CONFIG_MOSIX_DFSA */
 	kmem_cache_free(files_cachep, newf);
 	goto out;
 }
@@ -624,6 +706,34 @@
 	return ret;
 }
 
+#ifdef CONFIG_MOSIX
+long user_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	struct task_struct *task = current;
+	unsigned old_task_dumpable;
+	long ret;
+
+	/* lock out any potential ptracer */
+	task_lock(task);
+	if (task->ptrace) {
+		task_unlock(task);
+		return -EPERM;
+	}
+	
+	old_task_dumpable = task->task_dumpable;
+	task->task_dumpable = 0;
+	task_unlock(task);
+	
+	ret = arch_user_thread(fn, arg, flags);
+
+	/* never reached in child process, only in parent */
+	current->task_dumpable = old_task_dumpable;
+
+	return ret;
+}
+#endif /* CONFIG_MOSIX */
+
+
 /*
  *  Ok, this is the main fork-routine. It copies the system process
  * information (task[nr]) and sets up the necessary registers. It also
@@ -639,6 +749,9 @@
 	int retval;
 	struct task_struct *p;
 	struct completion vfork;
+#ifdef CONFIG_MOSIX
+	int migrated = 0;
+#endif /* CONFIG_MOSIX */
 
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 		return -EINVAL;
@@ -653,6 +766,14 @@
 		if (current->pid)
 			goto fork_out;
 	}
+#ifdef CONFIG_MOSIX
+	if(!(current->mosix.stay ||
+		(current->mosix.dflags & (DDEPUTY|DREMOTE|DREMOTEDAEMON))))
+
+		migrated = mosix_forkmigrate();
+
+
+#endif /* CONFIG_MOSIX */
 
 	retval = -ENOMEM;
 	p = alloc_task_struct();
@@ -738,6 +859,10 @@
 	INIT_LIST_HEAD(&p->local_pages);
 
 	retval = -ENOMEM;
+#ifdef CONFIG_MOSIX
+	if(mosix_fork_init_fields(p))
+		goto bad_fork_cleanup;
+#endif /* CONFIG_MOSIX */
 	/* copy all the process information */
 	if (copy_files(clone_flags, p))
 		goto bad_fork_cleanup;
@@ -745,6 +870,17 @@
 		goto bad_fork_cleanup_files;
 	if (copy_sighand(clone_flags, p))
 		goto bad_fork_cleanup_fs;
+
+	/* we need to set the tgid here, so that it's available */
+	/* to mosix_deputy_fork  contributed by Muli and Gilad*/
+	p->tgid = ((clone_flags & CLONE_THREAD) ? current->tgid : p->pid);
+
+#ifdef CONFIG_MOSIX
+	if((current->mosix.dflags & DDEPUTY) &&
+		(retval = mosix_deputy_fork(p, migrated, stack_start)))
+		goto bad_fork_cleanup_sighand;
+	/* No migrations allowed beyond this point! */
+#endif /* CONFIG_MOSIX */
 	if (copy_mm(clone_flags, p))
 		goto bad_fork_cleanup_sighand;
 	retval = copy_namespace(clone_flags, p);
@@ -792,6 +928,14 @@
 	/* CLONE_PARENT re-uses the old parent */
 	p->p_opptr = current->p_opptr;
 	p->p_pptr = current->p_pptr;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & (DREMOTE|DREMOTEDAEMON))
+	{
+		extern struct task_struct *child_reaper;
+		p->p_pptr = p->p_opptr = child_reaper;
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	if (!(clone_flags & CLONE_PARENT)) {
 		p->p_opptr = current;
 		if (!(p->ptrace & PT_PTRACED))
@@ -809,12 +953,19 @@
 	write_unlock_irq(&tasklist_lock);
 
 	if (p->ptrace & PT_PTRACED)
+#ifdef CONFIG_MOSIX
+	if(!(p->mosix.dflags & DREMOTE))
+#endif /* CONFIG_MOSIX */
 		send_sig(SIGSTOP, p, 1);
 
 	wake_up_process(p);		/* do this last */
 	++total_forks;
 	if (clone_flags & CLONE_VFORK)
+#ifdef CONFIG_MOSIX
+		wait_for_completion_half_interruptible(&vfork);
+#else
 		wait_for_completion(&vfork);
+#endif /* CONFIG_MOSIX */
 
 fork_out:
 	return retval;
@@ -823,6 +974,8 @@
 	exit_namespace(p);
 bad_fork_cleanup_mm:
 	exit_mm(p);
+	if (p->active_mm)
+		mmdrop(p->active_mm);
 bad_fork_cleanup_sighand:
 	exit_sighand(p);
 bad_fork_cleanup_fs:
@@ -830,6 +983,9 @@
 bad_fork_cleanup_files:
 	exit_files(p); /* blocking */
 bad_fork_cleanup:
+#ifdef CONFIG_MOSIX
+	mosix_fork_free_fields(p);
+#endif /* CONFIG_MOSIX */
 	put_exec_domain(p->exec_domain);
 	if (p->binfmt && p->binfmt->module)
 		__MOD_DEC_USE_COUNT(p->binfmt->module);
diff -Naur --exclude=CVS --exclude=configs linux/kernel/panic.c linux-openmosix/kernel/panic.c
--- linux/kernel/panic.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/kernel/panic.c	2004-05-19 00:33:48.000000000 +0200
@@ -59,7 +59,7 @@
 	
 	bust_spinlocks(1);
 	va_start(args, fmt);
-	vsprintf(buf, fmt, args);
+	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
 	printk(KERN_EMERG "Kernel panic: %s\n",buf);
 	if (in_interrupt())
diff -Naur --exclude=CVS --exclude=configs linux/kernel/ptrace.c linux-openmosix/kernel/ptrace.c
--- linux/kernel/ptrace.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/kernel/ptrace.c	2004-03-10 02:27:25.000000000 +0100
@@ -21,6 +21,13 @@
  */
 int ptrace_check_attach(struct task_struct *child, int kill)
 {
+	mb();
+#ifdef CONFIG_MOSIX
+	if (!(child->mm ? is_dumpable(child) : (child->mosix.dflags & DDUMPABLE)))
+#else
+	if (!is_dumpable(child))
+#endif
+		return -EPERM;
 
 	if (!(child->ptrace & PT_PTRACED))
 		return -ESRCH;
@@ -29,7 +36,11 @@
 		return -ESRCH;
 
 	if (!kill) {
+#ifdef CONFIG_MOSIX
+		if (LOGICAL_STATE(child) != TASK_STOPPED)
+#else
 		if (child->state != TASK_STOPPED)
+#endif /* CONFIG_MOSIX */
 			return -ESRCH;
 #ifdef CONFIG_SMP
 		/* Make sure the child gets off its CPU.. */
@@ -39,20 +50,28 @@
 				break;
 			task_unlock(child);
 			do {
+#ifdef CONFIG_MOSIX
+				if (LOGICAL_STATE(child) != TASK_STOPPED)
+#else
 				if (child->state != TASK_STOPPED)
+#endif /* CONFIG_MOSIX */
 					return -ESRCH;
 				barrier();
 				cpu_relax();
 			} while (task_has_cpu(child));
 		}
 		task_unlock(child);
-#endif		
+#endif
 	}
 
 	/* All systems go.. */
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+#include <hpc/request.h>
+#endif /* CONFIG_MOSIX */
+
 int ptrace_attach(struct task_struct *task)
 {
 	task_lock(task);
@@ -60,6 +79,9 @@
 		goto bad;
 	if (task == current)
 		goto bad;
+#ifdef CONFIG_MOSIX
+	if(!(task->mosix.dflags & DDEPUTY))
+#endif /* CONFIG_MOSIX */
 	if (!task->mm)
 		goto bad;
 	if(((current->uid != task->euid) ||
@@ -71,7 +93,12 @@
  	    (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
 		goto bad;
 	rmb();
+#ifdef CONFIG_MOSIX
+	if (!(task->mm ? is_dumpable(task) : (task->mosix.dflags & DDUMPABLE))
+		&& !capable(CAP_SYS_PTRACE))
+#else
 	if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE))
+#endif /* CONFIG_MOSIX */
 		goto bad;
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
@@ -105,6 +132,14 @@
 		return	-EIO;
 
 	/* Architecture-specific hardware disable .. */
+#ifdef CONFIG_MOSIX
+	if(child->mosix.dflags & DDEPUTY)
+	{
+		if(request_process(child, NULL, PR_PTRACE_CONT, PTRACE_DETACH))
+			return(-ESRCH);
+	}
+	else
+#endif /* CONFIG_MOSIX */
 	ptrace_disable(child);
 
 	/* .. re-parent .. */
@@ -123,7 +158,7 @@
 
 /*
  * Access another process' address space.
- * Source/target buffer must be kernel space, 
+ * Source/target buffer must be kernel space,
  * Do not walk the page table directly, use get_user_pages
  */
 
@@ -134,14 +169,35 @@
 	struct page *page;
 	void *old_buf = buf;
 
+#ifdef CONFIG_MOSIX
+	if (tsk->mosix.dflags & DDEPUTY)
+	{
+		return(request_process_arg2(tsk, buf,
+			write ? PR_PROCFS_MEM_WRITE : PR_PROCFS_MEM_READ,
+			(long) addr, len));
+	}					
+#endif
+
 	/* Worry about races with exit() */
 	task_lock(tsk);
 	mm = tsk->mm;
+	if (!is_dumpable(tsk))
+	{
+#ifdef CONFIG_MOSIX
+		if (!(tsk->mosix.dflags & DREMOTE))
+#endif
+			mm = NULL;
+	}
+	if (&init_mm == mm)
+	  	mm = NULL;
 	if (mm)
 		atomic_inc(&mm->mm_users);
 	task_unlock(tsk);
 	if (!mm)
+	{
 		return 0;
+	}
+	
 
 	down_read(&mm->mmap_sem);
 	/* ignore errors, just check how much was sucessfully transfered */
@@ -179,7 +235,7 @@
 	}
 	up_read(&mm->mmap_sem);
 	mmput(mm);
-	
+
 	return buf - old_buf;
 }
 
@@ -203,7 +259,7 @@
 		copied += retval;
 		src += retval;
 		dst += retval;
-		len -= retval;			
+		len -= retval;
 	}
 	return copied;
 }
@@ -228,7 +284,7 @@
 		copied += retval;
 		src += retval;
 		dst += retval;
-		len -= retval;			
+		len -= retval;
 	}
 	return copied;
 }
diff -Naur --exclude=CVS --exclude=configs linux/kernel/sched.c linux-openmosix/kernel/sched.c
--- linux/kernel/sched.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/kernel/sched.c	2004-02-05 10:51:30.000000000 +0100
@@ -37,6 +37,10 @@
 extern void tqueue_bh(void);
 extern void immediate_bh(void);
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /*
  * scheduler variables
  */
@@ -92,7 +96,11 @@
 spinlock_t runqueue_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;  /* inner */
 rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED;	/* outer */
 
+#ifdef CONFIG_MOSIX
+LIST_HEAD(runqueue_head);
+#else
 static LIST_HEAD(runqueue_head);
+#endif /* CONFIG_MOSIX */
 
 /*
  * We align per-CPU scheduling data on cacheline boundaries,
@@ -166,6 +174,16 @@
 		 * over..
 		 */
 		weight = p->counter;
+#ifdef CONFIG_MOSIX
+		/* give a generous advantage to processes in MOSIX context: */
+		/* (they do not hog the CPU anyway) */
+		if (p->mosix.dflags & DINSCHED)
+			weight += MOSIX_ASLEEP_PRIORITY;
+		if (p->mosix.dflags & DDEPUTY)
+			weight += MOSIX_DEPUTY_PRIORITY;
+		if (p->mosix.commpri)
+			weight += MOSIX_RESPOND_PRIORITY;
+#endif /* CONFIG_MOSIX */
 		if (!weight)
 			goto out;
 			
@@ -330,6 +348,9 @@
 {
 	list_add_tail(&p->run_list, &runqueue_head);
 	nr_running++;
+#ifdef CONFIG_MOSIX
+	run_on(p);
+#endif /* CONFIG_MOSIX */
 }
 
 static inline void move_last_runqueue(struct task_struct * p)
@@ -350,12 +371,35 @@
 {
 	unsigned long flags;
 	int success = 0;
+#ifdef CONFIG_MOSIX
+	struct task_struct *origp = p;
+#endif /* CONFIG_MOSIX */
 
 	/*
 	 * We want the common case fall through straight, thus the goto.
 	 */
 	spin_lock_irqsave(&runqueue_lock, flags);
+#ifdef CONFIG_MOSIX
+	p = NORMAL_CONTEXT(p);
+	write_lock(&p->mosix.state_lock);
+	if(origp != p)
+	{
+		if(p->mosix.bstate != TASK_SAME)
+			p->state = TASK_RUNNING;
+	}
+	else if(p->mosix.bstate == TASK_SAME)
+		p->state = TASK_RUNNING;
+	else
+	{
+		p->mosix.bstate = TASK_RUNNING;
+		success = 1;
+		write_unlock(&p->mosix.state_lock);
+		goto out;
+	}
+	write_unlock(&p->mosix.state_lock);
+#else
 	p->state = TASK_RUNNING;
+#endif /* CONFIG_MOSIX */
 	if (task_on_runqueue(p))
 		goto out;
 	add_to_runqueue(p);
@@ -372,6 +416,30 @@
 	return try_to_wake_up(p, 0);
 }
 
+#ifdef CONFIG_MOSIX
+/* wake up a process only if it is interested in MOSIX events */
+void
+wake_up_mosix(struct task_struct *p)
+{
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&runqueue_lock, flags);
+	if(mosix_wakeable(p))
+	{
+		write_lock(&p->mosix.state_lock);	/* not irq! */
+		if(p->mosix.bstate != TASK_SAME)
+			p->state = TASK_RUNNING;
+		write_unlock(&p->mosix.state_lock);
+		if (!task_on_runqueue(p))
+		{
+			add_to_runqueue(p);
+			reschedule_idle(p);
+		}
+	}
+	spin_unlock_irqrestore(&runqueue_lock, flags);
+}
+#endif /* CONFIG_MOSIX */
+
 static void process_timeout(unsigned long __data)
 {
 	struct task_struct * p = (struct task_struct *) __data;
@@ -444,6 +512,11 @@
 
 	init_timer(&timer);
 	timer.expires = expire;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DINSCHED)
+		timer.data = (unsigned long)MOSIX_CONTEXT(current);
+	else
+#endif /* CONFIG_MOSIX */
 	timer.data = (unsigned long) current;
 	timer.function = process_timeout;
 
@@ -550,6 +623,13 @@
 	struct task_struct *prev, *next, *p;
 	struct list_head *tmp;
 	int this_cpu, c;
+#ifdef CONFIG_MOSIX
+	auto volatile int handle_interim =
+		(current->state & (TASK_INTERRUPTIBLE|TASK_STOPPED)) &&
+		!(current->mosix.dflags & DINSCHED);
+
+	restart:
+#endif /* CONFIG_MOSIX */
 
 
 	spin_lock_prefetch(&runqueue_lock);
@@ -581,8 +661,42 @@
 			move_last_runqueue(prev);
 		}
 
+#ifdef CONFIG_MOSIX
+	if(handle_interim && need_interim_while_asleep())
+	{
+		int prev_kernel_lock_depth, prev_mosix_lock_depth;
+
+		do_interim_first:
+		write_lock(&prev->mosix.state_lock);	/* not irq! */
+		prev->mosix.bstate = prev->state;
+		prev->state = TASK_RUNNING;
+		write_unlock(&prev->mosix.state_lock);
+		prev->mosix.dflags |= DINSCHED;
+		spin_unlock_irq(&runqueue_lock);
+		prev_kernel_lock_depth = prev->lock_depth;
+		prev_mosix_lock_depth = prev->mosix.lock_depth;
+		prev->lock_depth = -1;
+		prev->mosix.lock_depth = -1;
+		run_interim_while_asleep();
+		prev->lock_depth = prev_kernel_lock_depth;
+		prev->mosix.lock_depth = prev_mosix_lock_depth;
+		if(prev_kernel_lock_depth != -1 || prev_mosix_lock_depth != -1)
+			reacquire_kernel_lock(prev);
+		spin_lock_irq(&runqueue_lock);
+		write_lock(&prev->mosix.state_lock);
+		prev->state = prev->mosix.bstate;
+		prev->mosix.bstate = TASK_SAME;
+		write_unlock(&prev->mosix.state_lock);
+		prev->mosix.dflags &= ~DINSCHED;
+		spin_unlock_irq(&runqueue_lock);
+		goto restart;
+	}
+#endif /* CONFIG_MOSIX */
 	switch (prev->state) {
 		case TASK_INTERRUPTIBLE:
+#ifdef CONFIG_MOSIX
+			if (!(prev->mosix.dflags & (DREMOTE|DINSCHED)))
+#endif /* CONFIG_MOSIX */
 			if (signal_pending(prev)) {
 				prev->state = TASK_RUNNING;
 				break;
@@ -632,6 +746,14 @@
 	 */
 	sched_data->curr = next;
 	task_set_cpu(next, this_cpu);
+#ifdef CONFIG_MOSIX
+	if(prev != next)
+		active_cpus += (next->pid != 0) - (prev->pid != 0);
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DIAG
+	if(active_cpus < 0 || active_cpus > smp_num_cpus)
+		mosix_panic("active_cpus got out of range");
+#endif /* CONFIG_MOSIX_DIAG */
 	spin_unlock_irq(&runqueue_lock);
 
 	if (unlikely(prev == next)) {
@@ -694,8 +816,28 @@
 	 */
 	switch_to(prev, next, prev);
 	__schedule_tail(prev);
+#ifdef CONFIG_MOSIX
+	prev = current;	/* we still use it */
+#endif /* CONFIG_MOSIX */
 
 same_process:
+
+#ifdef CONFIG_MOSIX
+	if(handle_interim)
+	{
+		spin_lock_irq(&runqueue_lock);
+		if(need_interim_while_asleep())
+			goto do_interim_first;
+		spin_unlock_irq(&runqueue_lock);
+	}
+	if(prev->state != TASK_RUNNING)
+	{
+		reacquire_kernel_lock(prev);
+		mosix_panic("Sched-Race: MOSIX awakened too late.\n");
+		goto restart;
+	}
+#endif /* CONFIG_MOSIX */
+
 	reacquire_kernel_lock(current);
 	if (current->need_resched)
 		goto need_resched_back;
@@ -716,6 +858,9 @@
 {
 	struct list_head *tmp;
 	struct task_struct *p;
+#ifdef CONFIG_MOSIX
+	struct task_struct *realp;
+#endif /* CONFIG_MOSIX */
 
 	CHECK_MAGIC_WQHEAD(q);
 	WQ_CHECK_LIST_HEAD(&q->task_list);
@@ -726,7 +871,25 @@
 
 		CHECK_MAGIC(curr->__magic);
 		p = curr->task;
+#ifdef CONFIG_MOSIX
+		realp = NORMAL_CONTEXT(p);
+		if(realp != p)
+		{
+			read_lock(&realp->mosix.state_lock);
+			if(realp->mosix.bstate == TASK_SAME)
+			{
+				/* no longer in MOSIX */
+				read_unlock(&realp->mosix.state_lock);
+				continue;
+			}
+			state = realp->state;
+			read_unlock(&realp->mosix.state_lock);
+		}
+		else
+			state = LOGICAL_STATE(p);
+#else
 		state = p->state;
+#endif /* CONFIG_MOSIX */
 		if (state & mode) {
 			WQ_NOTE_WAKER(curr);
 			if (try_to_wake_up(p, sync) && (curr->flags&WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
@@ -785,6 +948,35 @@
 	spin_unlock_irq(&x->wait.lock);
 }
 
+#ifdef CONFIG_MOSIX
+void wait_for_completion_half_interruptible(struct completion *x)
+{
+	struct task_struct *p = current;
+
+	spin_lock_irq(&x->wait.lock);
+	if (!x->done) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		wait.flags |= WQ_FLAG_EXCLUSIVE;
+		__add_wait_queue_tail(&x->wait, &wait);
+		do {
+			__set_current_state(TASK_INTERRUPTIBLE);
+			spin_unlock_irq(&x->wait.lock);
+			spin_lock_irq(&p->sigmask_lock);
+			p->mosix.ignoreoldsigs = 1;
+			p->sigpending = 0;
+			spin_unlock_irq(&p->sigmask_lock);
+			schedule();
+			spin_lock_irq(&x->wait.lock);
+		} while (!x->done);
+		__remove_wait_queue(&x->wait, &wait);
+	}
+	x->done--;
+	spin_unlock_irq(&x->wait.lock);
+	recalc_sigpending(p);
+}
+#endif /* CONFIG_MOSIX */
+
 #define	SLEEP_ON_VAR				\
 	unsigned long flags;			\
 	wait_queue_t wait;			\
@@ -920,6 +1112,10 @@
 	if (newprio > 19)
 		newprio = 19;
 	current->nice = newprio;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		mosix_inform_remote_of_nice();
+#endif /* CONFIG_MOSIX */
 	return 0;
 }
 
@@ -988,6 +1184,31 @@
 	    !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
+#ifdef CONFIG_MOSIX
+	spin_unlock(&runqueue_lock);
+	if(policy != SCHED_OTHER)
+	{
+		while(p->mosix.dflags & DDEPUTY)
+		{
+			get_task_struct(p);
+			read_unlock_irq(&tasklist_lock);
+			if((retval = mosix_send_back_home(p)))
+				return(retval);
+			read_lock(&tasklist_lock);
+			free_task_struct(p);
+		}
+		task_lock(p);
+		p->mosix.stay |= DSTAY_FOR_RT;
+		task_unlock(p);
+	}
+	else
+	{
+		task_lock(p);
+		p->mosix.stay &= ~DSTAY_FOR_RT;
+		task_unlock(p);
+	}
+	spin_lock(&runqueue_lock);
+#endif /* CONFIG_MOSIX */
 	retval = 0;
 	p->policy = policy;
 	p->rt_priority = lp.sched_priority;
@@ -1348,6 +1569,10 @@
  	exit_files(current);
 	current->files = init_task.files;
 	atomic_inc(&current->files->count);
+#ifdef CONFIG_MOSIX_DFSA
+	atomic_inc(&current->files->users);
+	atomic_inc(&fs->users);
+#endif /* CONFIG_MOSIX_DFSA */
 }
 
 extern unsigned long wait_init_idle;
diff -Naur --exclude=CVS --exclude=configs linux/kernel/signal.c linux-openmosix/kernel/signal.c
--- linux/kernel/signal.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-openmosix/kernel/signal.c	2004-02-05 10:51:30.000000000 +0100
@@ -14,6 +14,11 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#include <linux/interrupt.h>
+#endif /* CONFIG_MOSIX */
+
 #include <asm/uaccess.h>
 
 /*
@@ -105,6 +110,9 @@
 void
 flush_signals(struct task_struct *t)
 {
+#ifdef CONFIG_MOSIX
+	if(!(t->mosix.dflags & DFAKESIGNAL))
+#endif /* CONFIG_MOSIX */
 	t->sigpending = 0;
 	flush_sigqueue(&t->pending);
 }
@@ -119,6 +127,9 @@
 		if (atomic_dec_and_test(&sig->count))
 			kmem_cache_free(sigact_cachep, sig);
 	}
+#ifdef CONFIG_MOSIX
+	if(!(tsk->mosix.dflags & DFAKESIGNAL))
+#endif /* CONFIG_MOSIX */
 	tsk->sigpending = 0;
 	flush_sigqueue(&tsk->pending);
 	spin_unlock_irq(&tsk->sigmask_lock);
@@ -275,6 +286,9 @@
 		if (current->notifier) {
 			if (sigismember(current->notifier_mask, sig)) {
 				if (!(current->notifier)(current->notifier_data)) {
+#ifdef CONFIG_MOSIX
+					if(!(current->mosix.dflags&DFAKESIGNAL))
+#endif /* CONFIG_MOSIX */
 					current->sigpending = 0;
 					return 0;
 				}
@@ -411,7 +425,11 @@
 	switch (sig) {
 	case SIGKILL: case SIGCONT:
 		/* Wake up the process if stopped.  */
+#ifdef CONFIG_MOSIX
+		if (LOGICAL_STATE(t) == TASK_STOPPED)
+#else
 		if (t->state == TASK_STOPPED)
+#endif /* CONFIG_MOSIX */
 			wake_up_process(t);
 		t->exit_code = 0;
 		rm_sig_from_queue(SIGSTOP, t);
@@ -494,6 +512,11 @@
  */
 static inline void signal_wake_up(struct task_struct *t)
 {
+#ifdef CONFIG_MOSIX
+	t->mosix.ignoreoldsigs = 0;
+	if(t->mosix.dflags & DHEAVYSLEEP)
+		return;
+#endif /* CONFIG_MOSIX */
 	t->sigpending = 1;
 
 #ifdef CONFIG_SMP
@@ -513,7 +536,11 @@
 	spin_unlock(&runqueue_lock);
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_MOSIX
+	if (LOGICAL_STATE(t) & TASK_INTERRUPTIBLE) {
+#else
 	if (t->state & TASK_INTERRUPTIBLE) {
+#endif /* CONFIG_MOSIX */
 		wake_up_process(t);
 		return;
 	}
@@ -591,6 +618,42 @@
 {
 	unsigned long int flags;
 
+#ifdef CONFIG_MOSIX
+	if(t->mosix.dflags & DREMOTE)
+	{
+		int n;
+		siginfo_t *x;
+
+		if(!info || ((long)info) == 1)
+			panic("remote force_sig_info");
+		info->si_signo = sig;
+		/* (should be anyway, but some callers are mindless about it) */
+		if(in_interrupt())
+			panic("remote force_sig_info in interrupt");
+		repeat:
+		n = t->mosix.nforced_sigs;
+		if(!(x = kmalloc((n + 1) * sizeof(siginfo_t), GFP_KERNEL)))
+		{
+			/* just do our best */
+			send_sig(sig, t, 0);
+			return(0);
+		}
+		spin_lock_irqsave(&t->sigmask_lock, flags);
+		if(t->mosix.nforced_sigs != n)
+		{
+			spin_unlock_irqrestore(&t->sigmask_lock, flags);
+			kfree(x);
+			goto repeat;
+		}
+		if(n)
+			memcpy(x, t->mosix.forced_sigs, sizeof(siginfo_t) * n);
+		x[n] = *info;
+		t->mosix.forced_sigs = x;
+		t->mosix.nforced_sigs++;
+		spin_unlock_irqrestore(&t->sigmask_lock, flags);
+		return(0);
+	}
+#endif /* CONFIG_MOSIX */
 	spin_lock_irqsave(&t->sigmask_lock, flags);
 	if (t->sig == NULL) {
 		spin_unlock_irqrestore(&t->sigmask_lock, flags);
@@ -620,7 +683,11 @@
 
 		retval = -ESRCH;
 		read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+		for_each_local_task(p) {
+#else
 		for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 			if (p->pgrp == pgrp && thread_group_leader(p)) {
 				int err = send_sig_info(sig, info, p);
 				if (retval)
@@ -647,7 +714,11 @@
 
 		retval = -ESRCH;
 		read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+		for_each_local_task(p) {
+#else
 		for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 			if (p->leader && p->session == sess) {
 				int err = send_sig_info(sig, info, p);
 				if (retval)
@@ -698,7 +769,11 @@
 		struct task_struct * p;
 
 		read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+		for_each_local_task(p) {
+#else
 		for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 			if (p->pid > 1 && p != current && thread_group_leader(p)) {
 				int err = send_sig_info(sig, info, p);
 				++count;
@@ -722,12 +797,34 @@
 int
 send_sig(int sig, struct task_struct *p, int priv)
 {
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DREMOTE)
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&p->sigmask_lock, flags);
+		p->mosix.asig |= (1 << (sig-1));
+		spin_unlock_irqrestore(&p->sigmask_lock, flags);
+		if(p == current)
+			current->need_resched = 1;
+		return(0);
+	}
+#endif /* CONFIG_MOSIX */
 	return send_sig_info(sig, (void*)(long)(priv != 0), p);
 }
 
 void
 force_sig(int sig, struct task_struct *p)
 {
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DREMOTE)
+	{
+		if(sig == SIGSEGV)
+			sig = FATAL_SIGSEGV;
+		send_sig(sig, p, 0);
+		return;
+	}
+#endif /* CONFIG_MOSIX */
 	force_sig_info(sig, (void*)1L, p);
 }
 
@@ -783,7 +880,11 @@
 
 	status = tsk->exit_code & 0x7f;
 	why = SI_KERNEL;	/* shouldn't happen */
+#ifdef CONFIG_MOSIX
+	switch (LOGICAL_STATE(tsk)) {
+#else
 	switch (tsk->state) {
+#endif /* CONFIG_MOSIX */
 	case TASK_STOPPED:
 		/* FIXME -- can we deduce CLD_TRAPPED or CLD_CONTINUED? */
 		if (tsk->ptrace & PT_PTRACED)
diff -Naur --exclude=CVS --exclude=configs linux/kernel/sys.c linux-openmosix/kernel/sys.c
--- linux/kernel/sys.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/kernel/sys.c	2004-02-05 10:51:30.000000000 +0100
@@ -37,6 +37,13 @@
 # define GET_FPEXC_CTL(a,b)	(-EINVAL)
 #endif
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * this is where the system-wide overflow UID and GID are defined, for
  * architectures that now have 32-bit UID/GID but didn't in the past
@@ -193,6 +200,10 @@
 
 static int proc_sel(struct task_struct *p, int which, int who)
 {
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DREMOTE)
+		return(0);
+#endif /* CONFIG_MOSIX */
 	if(p->pid)
 	{
 		switch (which) {
@@ -229,7 +240,11 @@
 		niceval = 19;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if (!proc_sel(p, which, who))
 			continue;
 		if (p->uid != current->euid &&
@@ -242,7 +257,18 @@
 		if (niceval < p->nice && !capable(CAP_SYS_NICE))
 			error = -EACCES;
 		else
+#ifdef CONFIG_MOSIX
+		{
+#endif /* CONFIG_MOSIX */
 			p->nice = niceval;
+#ifdef CONFIG_MOSIX
+			if(p->mosix.dflags & DDEPUTY)
+			{
+				tell_process(p, DREQ_NICECNG);
+				wake_up_mosix(p);
+			}
+		}
+#endif /* CONFIG_MOSIX */
 	}
 	read_unlock(&tasklist_lock);
 
@@ -419,7 +445,11 @@
 	}
 	if (new_egid != old_egid)
 	{
+#ifdef CONFIG_MOSIX
+		set_me_dumpable(0);
+#else
 		current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 		wmb();
 	}
 	if (rgid != (gid_t) -1 ||
@@ -428,6 +458,12 @@
 	current->fsgid = new_egid;
 	current->egid = new_egid;
 	current->gid = new_rgid;
+#ifdef CONFIG_MOSIX
+	tell_process(current, DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	return 0;
 }
 
@@ -440,11 +476,21 @@
 {
 	int old_egid = current->egid;
 
+#ifdef CONFIG_MOSIX
+	tell_process(current, DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	if (capable(CAP_SETGID))
 	{
 		if(old_egid != gid)
 		{
+#ifdef CONFIG_MOSIX
+			set_me_dumpable(0);
+#else
 			current->mm->dumpable=0;
+#endif /* CONFIG_MOSIX */
 			wmb();
 		}
 		current->gid = current->egid = current->sgid = current->fsgid = gid;
@@ -453,7 +499,11 @@
 	{
 		if(old_egid != gid)
 		{
+#ifdef CONFIG_MOSIX
+			set_me_dumpable(0);
+#else
 			current->mm->dumpable=0;
+#endif /* CONFIG_MOSIX */
 			wmb();
 		}
 		current->egid = current->fsgid = gid;
@@ -520,10 +570,17 @@
 
 	if(dumpclear)
 	{
+#ifdef CONFIG_MOSIX
+		set_me_dumpable(0);
+#else
 		current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 		wmb();
 	}
 	current->uid = new_ruid;
+#ifdef CONFIG_MOSIX
+	tell_process(current, DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
 	return 0;
 }
 
@@ -558,6 +615,9 @@
 			return -EPERM;
 	}
 
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	if (euid != (uid_t) -1) {
 		new_euid = euid;
 		if ((old_ruid != euid) &&
@@ -572,7 +632,11 @@
 
 	if (new_euid != old_euid)
 	{
+#ifdef CONFIG_MOSIX
+		set_me_dumpable(0);
+#else
 		current->mm->dumpable=0;
+#endif /* CONFIG_MOSIX */
 		wmb();
 	}
 	current->fsuid = current->euid = new_euid;
@@ -606,6 +670,9 @@
 	int old_euid = current->euid;
 	int old_ruid, old_suid, new_ruid, new_suid;
 
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	old_ruid = new_ruid = current->uid;
 	old_suid = current->suid;
 	new_suid = old_suid;
@@ -619,7 +686,11 @@
 
 	if (old_euid != uid)
 	{
+#ifdef CONFIG_MOSIX
+		set_me_dumpable(0);
+#else
 		current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 		wmb();
 	}
 	current->fsuid = current->euid = uid;
@@ -654,6 +725,9 @@
 		    (suid != current->euid) && (suid != current->suid))
 			return -EPERM;
 	}
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	if (ruid != (uid_t) -1) {
 		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
 			return -EAGAIN;
@@ -661,7 +735,11 @@
 	if (euid != (uid_t) -1) {
 		if (euid != current->euid)
 		{
+#ifdef CONFIG_MOSIX
+			set_me_dumpable(0);
+#else
 			current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 			wmb();
 		}
 		current->euid = euid;
@@ -704,10 +782,17 @@
 		    (sgid != current->egid) && (sgid != current->sgid))
 			return -EPERM;
 	}
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	if (egid != (gid_t) -1) {
 		if (egid != current->egid)
 		{
+#ifdef CONFIG_MOSIX
+			set_me_dumpable(0);
+#else
 			current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 			wmb();
 		}
 		current->egid = egid;
@@ -717,6 +802,9 @@
 		current->gid = rgid;
 	if (sgid != (gid_t) -1)
 		current->sgid = sgid;
+#ifdef CONFIG_MOSIX
+	tell_process(current, DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
 	return 0;
 }
 
@@ -742,6 +830,9 @@
 {
 	int old_fsuid;
 
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	old_fsuid = current->fsuid;
 	if (uid == current->uid || uid == current->euid ||
 	    uid == current->suid || uid == current->fsuid || 
@@ -749,7 +840,11 @@
 	{
 		if (uid != old_fsuid)
 		{
+#ifdef CONFIG_MOSIX
+			set_me_dumpable(0);
+#else
 			current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 			wmb();
 		}
 		current->fsuid = uid;
@@ -784,6 +879,9 @@
 {
 	int old_fsgid;
 
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	old_fsgid = current->fsgid;
 	if (gid == current->gid || gid == current->egid ||
 	    gid == current->sgid || gid == current->fsgid || 
@@ -791,7 +889,11 @@
 	{
 		if (gid != old_fsgid)
 		{
+#ifdef CONFIG_MOSIX
+			set_me_dumpable(0);
+#else
 			current->mm->dumpable = 0;
+#endif /* CONFIG_MOSIX */
 			wmb();
 		}
 		current->fsgid = gid;
@@ -807,6 +909,10 @@
 	 *	atomically safe type this is just fine. Conceptually its
 	 *	as if the syscall took an instant longer to occur.
 	 */
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		mosix_deputy_rusage(0);
+#endif /* CONFIG_MOSIX */
 	if (tbuf)
 		if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
 			return -EFAULT;
@@ -862,7 +968,11 @@
 		goto out;
 	if (pgid != pid) {
 		struct task_struct * tmp;
+#ifdef CONFIG_MOSIX
+		for_each_local_task (tmp) {
+#else
 		for_each_task (tmp) {
+#endif /* CONFIG_MOSIX */
 			if (tmp->pgrp == pgid &&
 			    tmp->session == current->session)
 				goto ok_pgid;
@@ -876,6 +986,13 @@
 out:
 	/* All paths lead to here, thus we are safe. -DaveM */
 	read_unlock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	if(!err)
+	{
+		tell_process(p, DREQ_INFOCNG);
+		wake_up_mosix(p);
+	}
+#endif /* CONFIG_MOSIX */
 	return err;
 }
 
@@ -929,7 +1046,11 @@
 	int err = -EPERM;
 
 	read_lock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	for_each_local_task(p) {
+#else
 	for_each_task(p) {
+#endif /* CONFIG_MOSIX */
 		if (p->pgrp == current->pid)
 			goto out;
 	}
@@ -941,6 +1062,10 @@
 	err = current->pgrp;
 out:
 	read_unlock(&tasklist_lock);
+#ifdef CONFIG_MOSIX
+	if(err == current->pid)
+		tell_process(current, DREQ_INFOCNG);
+#endif /* CONFIG_MOSIX */
 	return err;
 }
 
@@ -979,6 +1104,9 @@
 		return -EPERM;
 	if ((unsigned) gidsetsize > NGROUPS)
 		return -EINVAL;
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDCRED;
+#endif /* CONFIG_MOSIX_DFSA */
 	if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
 		return -EFAULT;
 	current->ngroups = gidsetsize;
@@ -1146,6 +1274,22 @@
 			return -EPERM;
 	}
 	*old_rlim = new_rlim;
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+	switch(resource)
+	{
+		case RLIMIT_CPU:
+		case RLIMIT_DATA:
+		case RLIMIT_STACK:
+		case RLIMIT_RSS:
+		case RLIMIT_AS:
+#ifdef CONFIG_MOSIX_DFSA
+		case RLIMIT_NOFILE:
+		case RLIMIT_FSIZE:
+#endif /* CONFIG_MOSIX_DFSA */
+			mosix_deputy_rlimit(resource, new_rlim);
+	}
+#endif /* CONFIG_MOSIX */
 	return 0;
 }
 
@@ -1207,12 +1351,19 @@
 {
 	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
 		return -EINVAL;
+#ifdef CONFIG_MOSIX
+	if(who == RUSAGE_SELF && (current->mosix.dflags & DDEPUTY))
+		mosix_deputy_rusage(0);
+#endif /* CONFIG_MOSIX */
 	return getrusage(current, who, ru);
 }
 
 asmlinkage long sys_umask(int mask)
 {
 	mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
+#ifdef CONFIG_MOSIX_DFSA
+	current->mosix.dupdates |= DFSA_UPDUMASK;
+#endif /* CONFIG_MOSIX_DFSA */
 	return mask;
 }
     
@@ -1235,7 +1386,11 @@
 			error = put_user(current->pdeath_signal, (int *)arg2);
 			break;
 		case PR_GET_DUMPABLE:
+#ifdef CONFIG_MOSIX
+			if (i_am_dumpable())
+#else
 			if (is_dumpable(current))
+#endif /* CONFIG_MOSIX */
 				error = 1;
 			break;
 		case PR_SET_DUMPABLE:
@@ -1243,7 +1398,13 @@
 				error = -EINVAL;
 				break;
 			}
-			current->mm->dumpable = arg2;
+#ifdef CONFIG_MOSIX
+			if (i_am_dumpable())
+				set_me_dumpable(arg2 != 0);
+#else
+			if (is_dumpable(current))
+				current->mm->dumpable = arg2;
+#endif /* CONFIG_MOSIX */
 			break;
 
 	        case PR_SET_UNALIGN:
diff -Naur --exclude=CVS --exclude=configs linux/kernel/sysctl.c linux-openmosix/kernel/sysctl.c
--- linux/kernel/sysctl.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/kernel/sysctl.c	2004-02-05 10:51:30.000000000 +0100
@@ -434,11 +434,23 @@
 		       ctl_table *table, void **context)
 {
 	int n;
+#ifdef CONFIG_MOSIX
+	/* single "get_user" calls are expensive: */
+	int udata[CTL_MAXNAME];
+	int *nextu = udata;
+
+	if(copy_from_user(udata, name, nlen * sizeof(int)))
+		return(-EFAULT);
+#endif /* CONFIG_MOSIX */
 repeat:
 	if (!nlen)
 		return -ENOTDIR;
+#ifdef CONFIG_MOSIX
+	n = *nextu++;
+#else
 	if (get_user(n, name))
 		return -EFAULT;
+#endif /* CONFIG_MOSIX */
 	for ( ; table->ctl_name; table++) {
 		if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
 			int error;
@@ -869,10 +881,27 @@
 	
 	for (; left && vleft--; i++, first=0) {
 		if (write) {
+#ifdef CONFIG_MOSIX
+			/* "get_user" is expensive - need better optimization */
+			int nex = TMPBUFLEN;
+#endif /* CONFIG_MOSIX */
 			while (left) {
 				char c;
-				if (get_user(c, (char *) buffer))
+#ifdef CONFIG_MOSIX
+				if(nex == TMPBUFLEN)
+				{
+					len = left;
+					if(len > TMPBUFLEN)
+						len = TMPBUFLEN;
+					if(copy_from_user(buf, buffer, len))
+						return(-EFAULT);
+					nex = 0;
+				}
+				c = buf[nex++];
+#else
+				if (get_user(c,(char *) buffer))
 					return -EFAULT;
+#endif /* CONFIG_MOSIX */
 				if (!isspace(c))
 					break;
 				left--;
@@ -934,11 +963,29 @@
 		left--, buffer++;
 	}
 	if (write) {
+#ifdef CONFIG_MOSIX
+		/* "get_user" is expensive - need higher optimization */
+		int nex = TMPBUFLEN;
+#endif /* CONFIG_MOSIX */
 		p = (char *) buffer;
 		while (left) {
 			char c;
+#ifdef CONFIG_MOSIX
+			if(nex == TMPBUFLEN)
+			{
+				len = left;
+				if(len > TMPBUFLEN)
+					len = TMPBUFLEN;
+				if(copy_from_user(buf, p, len))
+					return(-EFAULT);
+				nex = 0;
+			}
+			c = buf[nex++];
+			p++;
+#else
 			if (get_user(c, p++))
 				return -EFAULT;
+#endif /* CONFIG_MOSIX */
 			if (!isspace(c))
 				break;
 			left--;
@@ -1022,10 +1069,27 @@
 	
 	for (; left && vleft--; i++, min++, max++, first=0) {
 		if (write) {
+#ifdef CONFIG_MOSIX
+			/* "get_user" is expensive - need higher optimization */
+			int nex = TMPBUFLEN;
+#endif /* CONFIG_MOSIX */
 			while (left) {
 				char c;
+#ifdef CONFIG_MOSIX
+				if(nex == TMPBUFLEN)
+				{
+					len = left;
+					if(len > TMPBUFLEN)
+						len = TMPBUFLEN;
+					if(copy_from_user(buf, buffer, len))
+						return(-EFAULT);
+					nex = 0;
+				}
+				c = buf[nex++];
+#else
 				if (get_user(c, (char *) buffer))
 					return -EFAULT;
+#endif /* CONFIG_MOSIX */
 				if (!isspace(c))
 					break;
 				left--;
@@ -1123,10 +1187,27 @@
 	
 	for (; left && vleft--; i++, first=0) {
 		if (write) {
+#ifdef CONFIG_MOSIX
+			/* "get_user" is expensive - need higher optimization */
+			int nex = TMPBUFLEN;
+#endif /* CONFIG_MOSIX */
 			while (left) {
 				char c;
+#ifdef CONFIG_MOSIX
+				if(nex == TMPBUFLEN)
+				{
+					len = left;
+					if(len > TMPBUFLEN)
+						len = TMPBUFLEN;
+					if(copy_from_user(buf, buffer, len))
+						return(-EFAULT);
+					nex = 0;
+				}
+				c = buf[nex++];
+#else
 				if (get_user(c, (char *) buffer))
 					return -EFAULT;
+#endif /* CONFIG_MOSIX */
 				if (!isspace(c))
 					break;
 				left--;
@@ -1185,11 +1266,29 @@
 		left--, buffer++;
 	}
 	if (write) {
+#ifdef CONFIG_MOSIX
+		/* "get_user" is expensive - need higher optimization */
+		int nex = TMPBUFLEN;
+#endif /* CONFIG_MOSIX */
 		p = (char *) buffer;
 		while (left) {
 			char c;
+#ifdef CONFIG_MOSIX
+			if(nex == TMPBUFLEN)
+			{
+				len = left;
+				if(len > TMPBUFLEN)
+					len = TMPBUFLEN;
+				if(copy_from_user(buf, p, len))
+					return(-EFAULT);
+				nex = 0;
+			}
+			c = buf[nex++];
+			p++;
+#else
 			if (get_user(c, p++))
 				return -EFAULT;
+#endif /* CONFIG_MOSIX */
 			if (!isspace(c))
 				break;
 			left--;
diff -Naur --exclude=CVS --exclude=configs linux/kernel/timer.c linux-openmosix/kernel/timer.c
--- linux/kernel/timer.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/kernel/timer.c	2004-02-05 10:51:30.000000000 +0100
@@ -25,6 +25,10 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /*
  * Timekeeping variables
  */
@@ -538,12 +542,26 @@
 	unsigned long user, unsigned long system)
 {
 	unsigned long psecs;
+#ifdef CONFIG_MOSIX
+	int i;
+#endif /* CONFIG_MOSIX */
 
 	psecs = (p->times.tms_utime += user);
 	psecs += (p->times.tms_stime += system);
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DREMOTE)
+		psecs += p->mosix.passedtime;
+	if(!(p->mosix.dflags & DDEPUTY))
+#endif /* CONFIG_MOSIX */
 	if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur) {
 		/* Send SIGXCPU every second.. */
+#ifdef CONFIG_MOSIX
+		i = p->mosix.last_sigxcpu ? : p->rlim[RLIMIT_CPU].rlim_cur;
+		p->mosix.last_sigxcpu = psecs / HZ;
+		for(; i < p->mosix.last_sigxcpu ; i++)
+#else
 		if (!(psecs % HZ))
+#endif /* CONFIG_MOSIX */
 			send_sig(SIGXCPU, p, 1);
 		/* and SIGKILL when we go over max.. */
 		if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_max)
@@ -551,7 +569,11 @@
 	}
 }
 
+#ifdef CONFIG_MOSIX
+inline void do_it_virt(struct task_struct * p, unsigned long ticks)
+#else
 static inline void do_it_virt(struct task_struct * p, unsigned long ticks)
+#endif /* CONFIG_MOSIX */
 {
 	unsigned long it_virt = p->it_virt_value;
 
@@ -569,6 +591,11 @@
 {
 	unsigned long it_prof = p->it_prof_value;
 
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DDEPUTY)
+		p->mosix.deputytime++;
+	else
+#endif /* CONFIG_MOSIX */
 	if (it_prof) {
 		if (--it_prof == 0) {
 			it_prof = p->it_prof_incr;
@@ -650,6 +677,9 @@
 	unsigned long active_tasks; /* fixed-point */
 	static int count = LOAD_FREQ;
 
+#ifdef CONFIG_MOSIX
+	mosix_snap_load(ticks);
+#endif /* CONFIG_MOSIX */
 	count -= ticks;
 	if (count < 0) {
 		count += LOAD_FREQ;
diff -Naur --exclude=CVS --exclude=configs linux/kernel/user.c linux-openmosix/kernel/user.c
--- linux/kernel/user.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/kernel/user.c	2004-02-05 10:51:30.000000000 +0100
@@ -87,6 +87,10 @@
 	struct user_struct **hashent = uidhashentry(uid);
 	struct user_struct *up;
 
+#ifdef CONFIG_MOSIX_DIAG
+	if(current->mosix.dflags & DREMOTE)
+		panic("REMOTE allocating uid");
+#endif /* CONFIG_MOSIX_DIAG */
 	spin_lock(&uidhash_lock);
 	up = uid_hash_find(uid, hashent);
 	spin_unlock(&uidhash_lock);
@@ -151,4 +155,46 @@
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+
+extern int max_threads;
+
+struct user_struct remote_guests =
+{
+	__count:	ATOMIC_INIT(1),
+	processes:	ATOMIC_INIT(1),
+	files:		ATOMIC_INIT(0)
+};
+
+void
+init_guest_user_struct(void)
+{
+	struct task_struct *p = current;
+
+	free_uid(p->user);
+	p->user = &remote_guests;
+	p->rlim[RLIMIT_NPROC].rlim_cur = max_threads / 6;
+}
+
+int
+get_free_guest_slots(void)
+{
+	int a, b;
+
+	write_lock_irq(&tasklist_lock);
+	a = max_threads/6 - atomic_read(&remote_guests.__count);
+	b = max_threads - nr_threads;
+	write_unlock_irq(&tasklist_lock);
+	if(a < 0)	/* a little paranoidic */
+		a = 0;
+	return(a < b ? a : b);
+}
+
+int
+count_guests(void)
+{
+	return(atomic_read(&remote_guests.__count) - 1);
+}
+#endif /* CONFIG_MOSIX */
+
 module_init(uid_cache_init);
diff -Naur --exclude=CVS --exclude=configs linux/lib/rwsem.c linux-openmosix/lib/rwsem.c
--- linux/lib/rwsem.c	2001-07-11 05:08:51.000000000 +0200
+++ linux-openmosix/lib/rwsem.c	2004-02-05 10:51:31.000000000 +0100
@@ -122,6 +122,9 @@
 	/* set up my own style of waitqueue */
 	spin_lock(&sem->wait_lock);
 	waiter->task = tsk;
+#ifdef CONFIG_MOSIX
+	adjust_task_mosix_context(&waiter->task);
+#endif /* CONFIG_MOSIX */
 
 	list_add_tail(&waiter->list,&sem->wait_list);
 
diff -Naur --exclude=CVS --exclude=configs linux/lib/rwsem-spinlock.c linux-openmosix/lib/rwsem-spinlock.c
--- linux/lib/rwsem-spinlock.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-openmosix/lib/rwsem-spinlock.c	2004-02-05 10:51:30.000000000 +0100
@@ -129,6 +129,9 @@
 
 	/* set up my own style of waitqueue */
 	waiter.task = tsk;
+#ifdef CONFIG_MOSIX
+	adjust_task_mosix_context(&waiter.task);
+#endif /* CONFIG_MOSIX */
 	waiter.flags = RWSEM_WAITING_FOR_READ;
 
 	list_add_tail(&waiter.list,&sem->wait_list);
@@ -197,6 +200,9 @@
 
 	/* set up my own style of waitqueue */
 	waiter.task = tsk;
+#ifdef CONFIG_MOSIX
+	adjust_task_mosix_context(&waiter.task);
+#endif /* CONFIG_MOSIX */
 	waiter.flags = RWSEM_WAITING_FOR_WRITE;
 
 	list_add_tail(&waiter.list,&sem->wait_list);
diff -Naur --exclude=CVS --exclude=configs linux/Makefile linux-openmosix/Makefile
--- linux/Makefile	2004-01-05 14:53:56.000000000 +0100
+++ linux-openmosix/Makefile	2004-02-05 10:50:31.000000000 +0100
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 24
-EXTRAVERSION =
+EXTRAVERSION = -om
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -128,7 +128,12 @@
 NETWORKS	=net/network.o
 
 LIBS		=$(TOPDIR)/lib/lib.a
+ifdef CONFIG_MOSIX
+CORE_FILES	+= $(TOPDIR)/hpc/hpc.o
+SUBDIRS		=hpc kernel drivers mm fs net ipc lib crypto
+else
 SUBDIRS		=kernel drivers mm fs net ipc lib crypto
+endif
 
 DRIVERS-n :=
 DRIVERS-y :=
@@ -224,6 +229,11 @@
 	net/khttpd/make_times_h \
 	net/khttpd/times.h \
 	submenu*
+
+CLEAN_FILES += arch/i386/kernel/mosasm.H arch/i386/kernel/offset \
+	hpc/auto_syscalls.c hpc/mkdefcalls hpc/alternate.c \
+	vmlinux.symtab
+
 # directories removed with 'make clean'
 CLEAN_DIRS = \
 	modules
diff -Naur --exclude=CVS --exclude=configs linux/mm/filemap.c linux-openmosix/mm/filemap.c
--- linux/mm/filemap.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/filemap.c	2004-02-05 10:51:31.000000000 +0100
@@ -30,6 +30,13 @@
 
 #include <linux/highmem.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
  * though.
@@ -54,7 +61,7 @@
 
 spinlock_cacheline_t pagecache_lock_cacheline  = {SPIN_LOCK_UNLOCKED};
 /*
- * NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock 
+ * NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock
  *	with the pagecache_lock held.
  *
  * Ordering:
@@ -220,6 +227,9 @@
 
 	spin_unlock(&pagecache_lock);
 	spin_unlock(&pagemap_lru_lock);
+#ifdef CONFIG_MOSIX
+	OPENMOSIX_VMODIFIED(inode);
+#endif /* CONFIG_MOSIX */
 }
 
 static int do_flushpage(struct page *page, unsigned long offset)
@@ -249,7 +259,7 @@
 	 * destroyed all buffer-cache references to it. Otherwise some
 	 * other process might think this inode page is not in the
 	 * page cache and creates a buffer-cache alias to it causing
-	 * all sorts of fun problems ...  
+	 * all sorts of fun problems ...
 	 */
 	ClearPageDirty(page);
 	ClearPageUptodate(page);
@@ -294,7 +304,7 @@
 				if (*partial && (offset + 1) == start) {
 					truncate_partial_page(page, *partial);
 					*partial = 0;
-				} else 
+				} else
 					truncate_complete_page(page);
 
 				UnlockPage(page);
@@ -326,7 +336,7 @@
  * that are beyond that offset (and zeroing out partial pages).
  * If any page is locked we wait for it to become unlocked.
  */
-void truncate_inode_pages(struct address_space * mapping, loff_t lstart) 
+void truncate_inode_pages(struct address_space * mapping, loff_t lstart)
 {
 	unsigned long start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
@@ -550,7 +560,7 @@
 /**
  *      filemap_fdatasync - walk the list of dirty pages of the given address space
  *     	and writepage() all of them.
- * 
+ *
  *      @mapping: address space structure to write
  *
  */
@@ -594,7 +604,7 @@
 /**
  *      filemap_fdatawait - walk the list of locked pages of the given address space
  *     	and wait for all of them.
- * 
+ *
  *      @mapping: address space structure to wait for
  *
  */
@@ -630,7 +640,7 @@
 /*
  * Add a page to the inode page cache.
  *
- * The caller must have locked the page and 
+ * The caller must have locked the page and
  * set all the page flags correctly..
  */
 void add_to_page_cache_locked(struct page * page, struct address_space *mapping, unsigned long index)
@@ -714,7 +724,7 @@
 {
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	struct page **hash = page_hash(mapping, offset);
-	struct page *page; 
+	struct page *page;
 
 	spin_lock(&pagecache_lock);
 	page = __find_page_nolock(mapping, offset, *hash);
@@ -732,7 +742,7 @@
 		return error;
 	}
 	/*
-	 * We arrive here in the unlikely event that someone 
+	 * We arrive here in the unlikely event that someone
 	 * raced with us and added our page to the cache first.
 	 */
 	page_cache_release(page);
@@ -829,13 +839,14 @@
 void wakeup_page_waiters(struct page * page)
 {
 	wait_queue_head_t * head;
-
+	
 	head = page_waitqueue(page);
 	if (waitqueue_active(head))
 		wake_up(head);
 }
 
-/* 
+
+/*
  * Wait for a page to get unlocked.
  *
  * This must be called with the caller "holding" the page,
@@ -1048,11 +1059,11 @@
 			spin_unlock(&pagecache_lock);
 			if (newpage == NULL)
 				lru_cache_add(page);
-			else 
+			else
 				page_cache_release(newpage);
 		}
 	}
-	return page;	
+	return page;
 }
 
 /*
@@ -1108,11 +1119,11 @@
 /*
  * Read-ahead profiling information
  * --------------------------------
- * Every PROFILE_MAXREADCOUNT, the following information is written 
+ * Every PROFILE_MAXREADCOUNT, the following information is written
  * to the syslog:
  *   Percentage of asynchronous read-ahead.
  *   Average of read-ahead fields context value.
- * If DEBUG_READAHEAD is defined, a snapshot of these fields is written 
+ * If DEBUG_READAHEAD is defined, a snapshot of these fields is written
  * to the syslog.
  */
 
@@ -1188,7 +1199,7 @@
  *
  * Synchronous read-ahead benefits:
  * --------------------------------
- * Using reasonable IO xfer length from peripheral devices increase system 
+ * Using reasonable IO xfer length from peripheral devices increase system
  * performances.
  * Reasonable means, in this context, not too large but not too small.
  * The actual maximum value is:
@@ -1197,22 +1208,22 @@
  *
  * Asynchronous read-ahead benefits:
  * ---------------------------------
- * Overlapping next read request and user process execution increase system 
+ * Overlapping next read request and user process execution increase system
  * performance.
  *
  * Read-ahead risks:
  * -----------------
  * We have to guess which further data are needed by the user process.
- * If these data are often not really needed, it's bad for system 
+ * If these data are often not really needed, it's bad for system
  * performances.
- * However, we know that files are often accessed sequentially by 
- * application programs and it seems that it is possible to have some good 
+ * However, we know that files are often accessed sequentially by
+ * application programs and it seems that it is possible to have some good
  * strategy in that guessing.
  * We only try to read-ahead files that seems to be read sequentially.
  *
  * Asynchronous read-ahead risks:
  * ------------------------------
- * In order to maximize overlapping, we must start some asynchronous read 
+ * In order to maximize overlapping, we must start some asynchronous read
  * request from the device, as soon as possible.
  * We must be very careful about:
  * - The number of effective pending IO read requests.
@@ -1250,7 +1261,7 @@
  * If the current position is inside the previous read IO request, do not
  * try to reread previously read ahead pages.
  * Otherwise decide or not to read ahead some pages synchronously.
- * If we are not going to read ahead, set the read ahead context for this 
+ * If we are not going to read ahead, set the read ahead context for this
  * page only.
  */
 	if (PageLocked(page)) {
@@ -1279,7 +1290,7 @@
 /*
  * Add ONE page to max_ahead in order to try to have about the same IO max size
  * as synchronous read-ahead (MAX_READAHEAD + 1)*PAGE_CACHE_SIZE.
- * Compute the position of the last page we have tried to read in order to 
+ * Compute the position of the last page we have tried to read in order to
  * begin to read ahead just at the next page.
  */
 		raend -= 1;
@@ -1372,7 +1383,7 @@
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
 /*
- * If the current position is outside the previous read-ahead window, 
+ * If the current position is outside the previous read-ahead window,
  * we reset the current read-ahead context and set read ahead max to zero
  * (will be set to just needed value later),
  * otherwise, we assume that the file accesses are sequential enough to
@@ -1415,7 +1426,7 @@
 		unsigned long end_index, nr, ret;
 
 		end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-			
+
 		if (index > end_index)
 			break;
 		nr = PAGE_CACHE_SIZE;
@@ -1555,7 +1566,7 @@
 		page = cached_page;
 		__add_to_page_cache(page, mapping, index, hash);
 		spin_unlock(&pagecache_lock);
-		lru_cache_add(page);		
+		lru_cache_add(page);
 		cached_page = NULL;
 
 		goto readpage;
@@ -1651,7 +1662,7 @@
 
 		if (rw == READ && retval > 0)
 			mark_dirty_kiobuf(iobuf, retval);
-		
+
 		if (retval >= 0) {
 			count -= retval;
 			buf += retval;
@@ -1673,7 +1684,7 @@
 		clear_bit(0, &filp->f_iobuf_lock);
 	else
 		free_kiovec(1, &iobuf);
- out:	
+ out:
 	return retval;
 }
 
@@ -1688,7 +1699,7 @@
 	kaddr = kmap(page);
 	left = __copy_to_user(desc->buf, kaddr + offset, size);
 	kunmap(page);
-	
+
 	if (left) {
 		size -= left;
 		desc->error = -EFAULT;
@@ -1798,6 +1809,10 @@
 	struct file * in_file, * out_file;
 	struct inode * in_inode, * out_inode;
 
+#ifdef CONFIG_MOSIX_DFSA
+	dfsa_touch_file(in_fd);
+	dfsa_touch_file(out_fd);
+#endif /* CONFIG_MOSIX_DFSA */
 	/*
 	 * Get input file, and verify that it is ok..
 	 */
@@ -2060,7 +2075,7 @@
 
 no_cached_page:
 	/*
-	 * If the requested offset is within our file, try to read a whole 
+	 * If the requested offset is within our file, try to read a whole
 	 * cluster of pages at once.
 	 *
 	 * Otherwise, we're off the end of a privately mapped file,
@@ -2164,7 +2179,7 @@
 }
 
 static inline int filemap_sync_pte_range(pmd_t * pmd,
-	unsigned long address, unsigned long size, 
+	unsigned long address, unsigned long size,
 	struct vm_area_struct *vma, unsigned long offset, unsigned int flags)
 {
 	pte_t * pte;
@@ -2194,7 +2209,7 @@
 }
 
 static inline int filemap_sync_pmd_range(pgd_t * pgd,
-	unsigned long address, unsigned long size, 
+	unsigned long address, unsigned long size,
 	struct vm_area_struct *vma, unsigned int flags)
 {
 	pmd_t * pmd;
@@ -2327,6 +2342,10 @@
 	struct vm_area_struct * vma;
 	int unmapped_error, error = -EINVAL;
 
+#ifdef CONFIG_MOSIX_DIAG
+	if(current->mosix.dflags & DDEPUTY)
+		panic("sys_msync: DEPUTY");
+#endif /* CONFIG_MOSIX_DIAG */
 	down_read(&current->mm->mmap_sem);
 	if (start & ~PAGE_MASK)
 		goto out;
@@ -2634,7 +2653,7 @@
 		error = -EINVAL;
 		break;
 	}
-		
+
 	return error;
 }
 
@@ -3006,7 +3025,7 @@
 	ssize_t		err;
 	unsigned long	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
 	loff_t		pos = *ppos;
-	
+
 	err = -EINVAL;
 	if (pos < 0)
 		goto out;
@@ -3038,7 +3057,7 @@
 	}
 
 	/*
-	 *	LFS rule 
+	 *	LFS rule
 	 */
 	if ( pos + *count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
 		if (pos >= MAX_NON_LFS) {
@@ -3060,7 +3079,7 @@
 	 *
 	 *	Linus frestrict idea will clean these up nicely..
 	 */
-	 
+
 	if (!S_ISBLK(inode->i_mode)) {
 		if (pos >= inode->i_sb->s_maxbytes)
 		{
@@ -3177,6 +3196,9 @@
 		page_fault = __copy_from_user(kaddr+offset, buf, bytes);
 		flush_dcache_page(page);
 		status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
+#ifdef CONFIG_MOSIX
+		OPENMOSIX_VMODIFIED(inode);
+#endif /* CONFIG_MOSIX */
 		if (page_fault)
 			goto fail_write;
 		if (!status)
@@ -3210,10 +3232,10 @@
 		if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
 			status = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA);
 	}
-	
+
+out_status:
 	err = written ? written : status;
 out:
-
 	return err;
 fail_write:
 	status = -EFAULT;
diff -Naur --exclude=CVS --exclude=configs linux/mm/memory.c linux-openmosix/mm/memory.c
--- linux/mm/memory.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/memory.c	2004-02-05 10:51:31.000000000 +0100
@@ -50,6 +50,10 @@
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 unsigned long max_mapnr;
 unsigned long num_physpages;
 unsigned long num_mappedpages;
@@ -543,6 +547,10 @@
 	if (iobuf->nr_pages)
 		return -EINVAL;
 
+#ifdef CONFIG_MOSIX
+	if(stay_me_and_my_clones(DSTAY_FOR_KIOBUF))
+		return(-ENOMEM);
+#endif /* CONFIG_MOSIX */
 	mm = current->mm;
 	dprintk ("map_user_kiobuf: begin\n");
 	
@@ -559,6 +567,21 @@
 	
 	/* Try to fault in all of the necessary pages */
 	down_read(&mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	write_lock_irq(&tasklist_lock);
+	if(iobuf->mm)
+	{
+		printk("map_user_kiobuf: double use\n");
+		write_unlock_irq(&tasklist_lock);
+		up_read(&mm->mmap_sem);
+		unstay_mm(mm);
+		return(-EINVAL);
+	}
+	atomic_inc(&mm->mm_count);
+	atomic_inc(&mm->mm_kiocount);
+	iobuf->mm = mm;
+	write_unlock_irq(&tasklist_lock);
+#endif /* CONFIG_MOSIX */
 	/* rw==READ means read from disk, write into memory area */
 	err = get_user_pages(current, mm, va, pgcount,
 			(rw==READ), 0, iobuf->maplist, NULL);
@@ -566,6 +589,9 @@
 	if (err < 0) {
 		unmap_kiobuf(iobuf);
 		dprintk ("map_user_kiobuf: end %d\n", err);
+#ifdef CONFIG_MOSIX
+		unstay_mm(mm);
+#endif /* CONFIG_MOSIX */
 		return err;
 	}
 	iobuf->nr_pages = err;
@@ -622,6 +648,9 @@
 {
 	int i;
 	struct page *map;
+#ifdef CONFIG_MOSIX
+	struct mm_struct *mm;
+#endif /* CONFIG_MOSIX */
 	
 	for (i = 0; i < iobuf->nr_pages; i++) {
 		map = iobuf->maplist[i];
@@ -637,6 +666,20 @@
 	
 	iobuf->nr_pages = 0;
 	iobuf->locked = 0;
+#ifdef CONFIG_MOSIX
+	write_lock_irq(&tasklist_lock);
+	mm = iobuf->mm;
+	iobuf->mm = NULL;
+	write_unlock_irq(&tasklist_lock);
+	if(!mm)
+	{
+		printk("unmap_kiobuf: no mm!\n");
+		return;
+	}
+	if(atomic_dec_and_test(&mm->mm_kiocount))
+		unstay_mm(mm);
+	mmdrop(mm);
+#endif /* CONFIG_MOSIX */
 }
 
 
@@ -960,6 +1003,10 @@
 		if (reuse) {
 			flush_cache_page(vma, address);
 			establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
+#ifdef CONFIG_MOSIX
+                      old_page->young = 0;
+                      old_page->last_young = jiffies;
+#endif /* a.shiloh */
 			spin_unlock(&mm->page_table_lock);
 			return 1;	/* Minor fault */
 		}
@@ -1057,6 +1104,9 @@
 		vmtruncate_list(mapping->i_mmap, pgoff);
 	if (mapping->i_mmap_shared != NULL)
 		vmtruncate_list(mapping->i_mmap_shared, pgoff);
+#ifdef CONFIG_MOSIX
+	OPENMOSIX_VMODIFIED(inode);
+#endif /* CONFIG_MOSIX */
 
 out_unlock:
 	spin_unlock(&mapping->i_shared_lock);
@@ -1122,8 +1172,18 @@
 	swp_entry_t entry = pte_to_swp_entry(orig_pte);
 	pte_t pte;
 	int ret = 1;
+#ifdef CONFIG_MOSIX
+	/* patch conflict resolution
+	   no swap readahead conflict here  */
+	int dpagein = (current->mosix.dflags & DPAGEIN) ^ DPAGEIN;
+#endif /* CONFIG_MOSIX */
 
 	spin_unlock(&mm->page_table_lock);
+#ifdef CONFIG_MOSIX /* comment as before - Qlusters */
+	spin_lock_irq(&runqueue_lock);
+	current->mosix.dflags |= dpagein;
+	spin_unlock_irq(&runqueue_lock);
+#endif /* CONFIG_MOSIX */
 	page = lookup_swap_cache(entry);
 	if (!page) {
 		swapin_readahead(entry);
@@ -1134,6 +1194,12 @@
 			 * we released the page table lock.
 			 */
 			int retval;
+#ifdef CONFIG_MOSIX /* comment as before - Qlusters */
+			spin_lock_irq(&runqueue_lock);
+			current->mosix.dflags &= ~dpagein;
+			spin_unlock_irq(&runqueue_lock);
+#endif /* CONFIG_MOSIX */
+
 			spin_lock(&mm->page_table_lock);
 			retval = pte_same(*page_table, orig_pte) ? -1 : 1;
 			spin_unlock(&mm->page_table_lock);
@@ -1147,6 +1213,11 @@
 	mark_page_accessed(page);
 
 	lock_page(page);
+#ifdef CONFIG_MOSIX
+	spin_lock_irq(&runqueue_lock);
+	current->mosix.dflags &= ~dpagein;
+	spin_unlock_irq(&runqueue_lock);
+#endif /* CONFIG_MOSIX */
 
 	/*
 	 * Back out if somebody else faulted in this pte while we
@@ -1354,6 +1425,14 @@
 		entry = pte_mkdirty(entry);
 	}
 	entry = pte_mkyoung(entry);
+#ifdef CONFIG_MOSIX
+	{
+		struct page *page = pte_page(entry);
+
+		page->young = 0;
+		page->last_young = jiffies;
+	}
+#endif /* CONFIG_MOSIX */
 	establish_pte(vma, address, pte, entry);
 	spin_unlock(&mm->page_table_lock);
 	return 1;
diff -Naur --exclude=CVS --exclude=configs linux/mm/mlock.c linux-openmosix/mm/mlock.c
--- linux/mm/mlock.c	2001-09-18 00:30:23.000000000 +0200
+++ linux-openmosix/mm/mlock.c	2004-02-05 10:51:31.000000000 +0100
@@ -12,6 +12,10 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 static inline int mlock_fixup_all(struct vm_area_struct * vma, int newflags)
 {
 	spin_lock(&vma->vm_mm->page_table_lock);
@@ -218,8 +222,16 @@
 		goto out;
 
 	error = do_mlock(start, len, 1);
+#ifdef CONFIG_MOSIX
+	if (!error)
+		stay_me_and_my_clones(DSTAY_FOR_MLOCK);
+#endif /* CONFIG_MOSIX */
 out:
 	up_write(&current->mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	if (error)
+		unstay_mm(current->mm);
+#endif /* CONFIG_MOSIX */
 	return error;
 }
 
@@ -227,11 +239,18 @@
 {
 	int ret;
 
+#ifdef CONFIG_MOSIX_DIAG
+	if(current->mosix.dflags & DDEPUTY)
+		panic("sys_munlock -- DEPUTY");
+#endif /* CONFIG_MOSIX_DIAG */
 	down_write(&current->mm->mmap_sem);
 	len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
 	start &= PAGE_MASK;
 	ret = do_mlock(start, len, 0);
 	up_write(&current->mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	unstay_mm(current->mm);
+#endif /* CONFIG_MOSIX */
 	return ret;
 }
 
@@ -285,8 +304,16 @@
 		goto out;
 
 	ret = do_mlockall(flags);
+#ifdef CONFIG_MOSIX
+	if (!ret)
+		stay_me_and_my_clones(DSTAY_FOR_MLOCK);
+#endif /* CONFIG_MOSIX */
 out:
 	up_write(&current->mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	if (ret < 0)
+		unstay_mm(current->mm);
+#endif /* CONFIG_MOSIX */
 	return ret;
 }
 
@@ -294,8 +321,15 @@
 {
 	int ret;
 
+#ifdef CONFIG_MOSIX_DIAG
+	if(current->mosix.dflags & DDEPUTY)
+		panic("sys_munlock -- DEPUTY");
+#endif /* CONFIG_MOSIX_DIAG */
 	down_write(&current->mm->mmap_sem);
 	ret = do_mlockall(0);
 	up_write(&current->mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	unstay_mm(current->mm);
+#endif /* CONFIG_MOSIX */
 	return ret;
 }
diff -Naur --exclude=CVS --exclude=configs linux/mm/mmap.c linux-openmosix/mm/mmap.c
--- linux/mm/mmap.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/mmap.c	2004-02-05 10:51:31.000000000 +0100
@@ -24,6 +24,16 @@
  */
 #undef DEBUG_MM_RB
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+#ifdef CONFIG_MOSIX_FS
+#include <linux/mfs.h>
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
+
 /* description of effects of mapping type and prot in current implementation.
  * this is due to the limited x86 page protection hardware.  The expected
  * behavior is in parens:
@@ -100,12 +110,31 @@
 
 	if (file) {
 		struct inode *inode = file->f_dentry->d_inode;
+#ifdef CONFIG_MOSIX
+		int was_shared = (inode->i_mapping->i_mmap_shared != NULL);
+#endif /* CONFIG_MOSIX */
 		if (vma->vm_flags & VM_DENYWRITE)
 			atomic_inc(&inode->i_writecount);
 		if(vma->vm_next_share)
 			vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
 		*vma->vm_pprev_share = vma->vm_next_share;
+#ifdef CONFIG_MOSIX
+		if(was_shared && !inode->i_mapping->i_mmap_shared)
+			mosix_no_longer_monkey(inode);
+		if(current->mosix.dflags & DREMOTE)
+		{
+			spin_lock_irq(&current->sigmask_lock);
+			current->mosix.asig |= (1 << (REMOTE_FILE_RELEASED-1));
+			spin_unlock_irq(&current->sigmask_lock);
+		}
+		else
+			tell_process(current, DREQ_FILEUNMAP);
+#endif /* CONFIG_MOSIX */
 	}
+#ifdef CONFIG_MOSIX
+	if(current->mosix.stay & DSTAY_PER_MM)
+		unstay_mm(current->mm);
+#endif /* CONFIG_MOSIX */
 }
 
 static inline void remove_shared_vm_struct(struct vm_area_struct *vma)
@@ -163,6 +192,13 @@
 	if (brk <= mm->brk) {
 		if (!do_munmap(mm, newbrk, oldbrk-newbrk))
 			goto set_brk;
+#ifdef CONFIG_MOSIX
+		if(process_told(current, DREQ_FILEUNMAP))
+		{
+			process_ack(current, DREQ_FILEUNMAP);
+			mosix_rebuild_file_list();
+		}
+#endif /* CONFIG_MOSIX */
 		goto out;
 	}
 
@@ -390,18 +426,90 @@
 	return 0;
 }
 
-unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len,
+#ifdef CONFIG_MOSIX
+#define	MMAP_REMOTELY	((current->mosix.dflags&(DDEPUTY|DINCOMING)) == DDEPUTY)
+#endif /* CONFIG_MOSIX */
+
+#ifdef CONFIG_MOSIX_FS
+unsigned long
+mmap_read_instead(struct file *file, unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long pgoff)
 {
+	extern asmlinkage long sys_mprotect(unsigned long,size_t,unsigned long);
+	extern asmlinkage long sys_munmap(unsigned long, size_t);
+	int mm_downed = (current->mosix.dirty_bits & MMAP_MMDOWNED);
+	loff_t loff = pgoff << PAGE_SHIFT;
+	mm_segment_t oldfs;
+	int error;
+
+	if((flags & MAP_TYPE) != MAP_PRIVATE)
+		return(-EPERM);
+	if(!(file->f_mode & 1))
+		return(-EACCES);
+	len = PAGE_ALIGN(len);
+	addr = do_mmap_pgoff(NULL, addr, len, prot | PROT_WRITE,
+				flags & ~MAP_DENYWRITE, pgoff);
+	if(IS_ERR((const void *)addr))
+		return(addr);
+	oldfs = get_fs();
+	set_fs(USER_DS);
+	if(mm_downed)
+		up_write(&current->mm->mmap_sem);
+#ifdef CONFIG_MOSIX_DFSA
+	error = dfsa_optimized_read(file, loff, addr, len);
+#else
+	error = file->f_op->read(file, (char *)addr, len, &loff);
+#endif /* CONFIG_MOSIX_DFSA */
+	if(error < 0)
+	{
+		set_fs(oldfs);
+		sys_munmap(addr, len);
+		if(mm_downed)
+			down_write(&current->mm->mmap_sem);
+		return(error);
+	}
+	if(error < len)
+		clear_user((void *)addr + error, len - error);
+	set_fs(oldfs);
+	if(!(prot & PROT_WRITE))
+	{
+		prot &= (PROT_READ|PROT_EXEC);
+		if(MMAP_REMOTELY)
+			deputy_mprotect(addr, len, prot);
+		else
+			sys_mprotect(addr, len, prot);
+	}
+	if(mm_downed)
+		down_write(&current->mm->mmap_sem);
+	return(addr);
+}
+#endif /* CONFIG_MOSIX_FS */
+
+unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+			unsigned long len, unsigned long prot,
+			unsigned long flags, unsigned long pgoff)
+{
 	struct mm_struct * mm = current->mm;
 	struct vm_area_struct * vma, * prev;
 	unsigned int vm_flags;
 	int correct_wcount = 0;
 	int error;
 	rb_node_t ** rb_link, * rb_parent;
+	unsigned long charged = 0;
+#ifdef CONFIG_MOSIX
+	uint32_t reason_to_come_back = 0;
+	int registration_result = 0;
+#endif /* CONFIG_MOSIX */
 
 	if (file && (!file->f_op || !file->f_op->mmap))
 		return -ENODEV;
+#ifdef CONFIG_MOSIX_FS
+	if(file && file_is_mfs(file))
+		return(mmap_read_instead(file, addr, len, prot, flags, pgoff));
+#endif /* CONFIG_MOSIX_FS */
+#ifdef CONFIG_MOSIX
+ repeat_after_migrating_back:
+#endif /* CONFIG_MOSIX */
 
 	if (!len)
 		return addr;
@@ -416,7 +524,12 @@
 		return -EINVAL;
 
 	/* Too many mappings? */
+
+#ifdef CONFIG_MOSIX
+	if (!(current->mosix.dflags & DDEPUTY) && mm->map_count > max_map_count)
+#else
 	if (mm->map_count > max_map_count)
+#endif /* CONFIG_MOSIX */
 		return -ENOMEM;
 
 	/* Obtain the address to map to. we verify (or select) it and ensure
@@ -430,9 +543,17 @@
 	 * to. we assume access permissions have been handled by the open
 	 * of the memory object, so we don't do any here.
 	 */
+#ifdef CONFIG_MOSIX
+	vm_flags = calc_vm_flags(prot,flags) | (mm ? mm->def_flags : 0) |
+					VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+#else
 	vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+#endif /* CONFIG_MOSIX */
 
 	/* mlock MCL_FUTURE? */
+#ifdef CONFIG_MOSIX
+	if (mm)
+#endif /* CONFIG_MOSIX */
 	if (vm_flags & VM_LOCKED) {
 		unsigned long locked = mm->locked_vm << PAGE_SHIFT;
 		locked += len;
@@ -457,9 +578,20 @@
 			vm_flags |= VM_SHARED | VM_MAYSHARE;
 			if (!(file->f_mode & FMODE_WRITE))
 				vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
+#ifdef CONFIG_MOSIX
+			if(file->f_mode & FMODE_WRITE)
+				reason_to_come_back |= DSTAY_FOR_MONKEY;
+#endif /* CONFIG_MOSIX */
 
 			/* fall through */
 		case MAP_PRIVATE:
+#ifdef CONFIG_MOSIX
+			if(file->f_dentry->d_inode->i_mapping->i_mmap_shared)
+				reason_to_come_back |= DSTAY_FOR_MONKEY;
+			if(S_ISCHR(file->f_dentry->d_inode->i_mode))
+				reason_to_come_back |= DSTAY_FOR_DEV;
+			if (!(current->mosix.dflags & DINCOMING))
+#endif /* CONFIG_MOSIX */
 			if (!(file->f_mode & FMODE_READ))
 				return -EACCES;
 			break;
@@ -479,6 +611,20 @@
 			break;
 		}
 	}
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dirty_bits & MMAP_MAYSHARE)
+		vm_flags |= VM_MAYSHARE;
+	if(MMAP_REMOTELY)
+	{
+		if(reason_to_come_back)
+		{
+			if(!mosix_go_home(1))
+				return(-EAGAIN);
+			goto again_locally;
+		}
+		goto prepare_vma;
+	}
+#endif /* CONFIG_MOSIX */
 
 	/* Clear old maps */
 munmap_back:
@@ -486,6 +632,12 @@
 	if (vma && vma->vm_start < addr + len) {
 		if (do_munmap(mm, addr, len))
 			return -ENOMEM;
+#ifdef CONFIG_MOSIX
+		if(process_told(current, DREQ_FILEUNMAP)) {
+			process_ack(current, DREQ_FILEUNMAP);
+			mosix_rebuild_file_list();
+		}
+#endif /* CONFIG_MOSIX */
 		goto munmap_back;
 	}
 
@@ -495,6 +647,9 @@
 		return -ENOMEM;
 
 	/* Private writable mapping? Check memory availability.. */
+#ifdef CONFIG_MOSIX
+	if(!(current->mosix.dflags & DINCOMING))
+#endif /* CONFIG_MOSIX */
 	if ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE &&
 	    !(flags & MAP_NORESERVE)				 &&
 	    !vm_enough_memory(len >> PAGE_SHIFT))
@@ -509,6 +664,9 @@
 	 * specific mapper. the address has already been validated, but
 	 * not unmapped, but the maps are removed from the list.
 	 */
+#ifdef CONFIG_MOSIX
+prepare_vma:
+#endif /* CONFIG_MOSIX */
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!vma)
 		return -ENOMEM;
@@ -524,6 +682,53 @@
 	vma->vm_private_data = NULL;
 	vma->vm_raend = 0;
 
+#ifdef CONFIG_MOSIX
+	if(file && !(current->mosix.dflags & DREMOTE) && (registration_result =
+		mosix_register_a_file(file, (flags & MAP_DENYWRITE) != 0)) < 0)
+	{
+		error = registration_result;
+		goto free_vma;
+	}
+	/*
+	 * even if we don't end up mapping locally, perform a dummy mapping,
+	 * only to check for fs-specific errors, so we do not fail if and when
+	 * we ever come home:
+	 */
+	if(MMAP_REMOTELY)
+	{
+		vma->vm_file = file;
+		if(file && (error = file->f_op->mmap(file, vma)))
+			goto free_vma;
+		/* did the mapping itself cause us to arrive back home
+		 * (perhaps we were mapping /proc/nnnn/mem)? */
+		if(!MMAP_REMOTELY)
+			goto again_locally_with_vma;
+		addr = mosix_deputy_mmap(file, addr, (flags & MAP_FIXED) != 0,
+			len, vma->vm_flags, pgoff,
+			file ? file->f_dentry->d_inode->i_size : 0,
+			file ? vma->vm_ops->nopage : NULL);
+		if(IS_ERR((const void *)addr))
+		{
+			error = addr;
+			if(error == -EDOITATHOME)
+			/* remote resource shortage: don't despair, come back */
+			if(mosix_go_home(1))
+				goto again_locally_with_vma;
+			goto free_vma;
+		}
+		/* we did not really want that vma... only to check */
+		kmem_cache_free(vm_area_cachep, vma);
+		/* meanwhile someone else could map the same file shared, so: */
+		if(file && file->f_dentry->d_inode->i_mapping->i_mmap_shared)
+		{
+			if(!mosix_go_home(0))
+				return(-EAGAIN);
+			stay_me_and_my_clones(DSTAY_FOR_MONKEY);
+		}
+		return(addr);
+	}
+
+#endif /* CONFIG_MOSIX */
 	if (file) {
 		error = -EINVAL;
 		if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
@@ -585,6 +790,12 @@
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
 	}
+#ifdef CONFIG_MOSIX
+	if(reason_to_come_back)
+		stay_me_and_my_clones(reason_to_come_back);
+	if(file && (vm_flags & VM_SHARED))
+		mosix_bring_monkey_users_back(file->f_dentry->d_inode);
+#endif /* CONFIG_MOSIX */
 	return addr;
 
 unmap_and_free_vma:
@@ -597,7 +808,22 @@
 	zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start);
 free_vma:
 	kmem_cache_free(vm_area_cachep, vma);
+#ifdef CONFIG_MOSIX
+	if(registration_result > 0)
+		mosix_undo_last_file_registration(file, registration_result);
+#endif /* CONFIG_MOSIX */
 	return error;
+#ifdef CONFIG_MOSIX
+again_locally_with_vma:
+	kmem_cache_free(vm_area_cachep, vma);
+	if(registration_result > 0)
+		mosix_undo_last_file_registration(file, registration_result);
+	registration_result = 0;
+again_locally:
+	mm = current->mm;
+	reason_to_come_back = 0;
+	goto repeat_after_migrating_back;
+#endif /* CONFIG_MOSIX */
 }
 
 /* Get an address range which is currently unmapped.
@@ -643,6 +869,10 @@
 
 unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
+#ifdef CONFIG_MOSIX
+	if(MMAP_REMOTELY && !(flags & MAP_FIXED))
+		return(PAGE_ALIGN(addr));
+#endif /* CONFIG_MOSIX */
 	if (flags & MAP_FIXED) {
 		if (addr > TASK_SIZE - len)
 			return -ENOMEM;
@@ -1019,9 +1249,20 @@
 	int ret;
 	struct mm_struct *mm = current->mm;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		return(deputy_munmap(addr, len));
+#endif /* CONFIG_MOSIX */
 	down_write(&mm->mmap_sem);
 	ret = do_munmap(mm, addr, len);
 	up_write(&mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	if(process_told(current, DREQ_FILEUNMAP))
+	{
+		process_ack(current, DREQ_FILEUNMAP);
+		mosix_rebuild_file_list();
+	}
+#endif /* CONFIG_MOSIX */
 	return ret;
 }
 
@@ -1044,6 +1285,10 @@
 	if ((addr + len) > TASK_SIZE || (addr + len) < addr)
 		return -EINVAL;
 
+#ifdef CONFIG_MOSIX
+	if(current->mosix.dflags & DDEPUTY)
+		return(mosix_deputy_brk(addr, len));
+#endif /* CONFIG_MOSIX */
 	/*
 	 * mlock MCL_FUTURE?
 	 */
diff -Naur --exclude=CVS --exclude=configs linux/mm/mprotect.c linux-openmosix/mm/mprotect.c
--- linux/mm/mprotect.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/mprotect.c	2004-02-05 10:51:31.000000000 +0100
@@ -270,6 +270,10 @@
 	struct vm_area_struct * vma, * next, * prev;
 	int error = -EINVAL;
 
+#ifdef CONFIG_MOSIX_DIAG
+	if(current->mosix.dflags & DDEPUTY)
+		panic("sys_mprotect: DEPUTY");
+#endif /* CONFIG_MOSIX_DIAG */
 	if (start & ~PAGE_MASK)
 		return -EINVAL;
 	len = PAGE_ALIGN(len);
diff -Naur --exclude=CVS --exclude=configs linux/mm/mremap.c linux-openmosix/mm/mremap.c
--- linux/mm/mremap.c	2004-01-05 14:53:56.000000000 +0100
+++ linux-openmosix/mm/mremap.c	2004-06-11 13:01:55.000000000 +0200
@@ -14,6 +14,9 @@
 #include <asm/pgalloc.h>
 
 extern int vm_enough_memory(long pages);
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
 
 static inline pte_t *get_one_pte(struct mm_struct *mm, unsigned long addr)
 {
@@ -77,12 +80,16 @@
 static int move_one_page(struct mm_struct *mm, unsigned long old_addr, unsigned long new_addr)
 {
 	int error = 0;
-	pte_t * src;
+	pte_t * src, * dst;
 
 	spin_lock(&mm->page_table_lock);
 	src = get_one_pte(mm, old_addr);
-	if (src)
-		error = copy_one_pte(mm, src, alloc_one_pte(mm, new_addr));
+	if (src) {
+		dst = alloc_one_pte(mm, new_addr);
+		src = get_one_pte(mm, old_addr);
+		if (src) 
+			error = copy_one_pte(mm, src, dst);
+	}
 	spin_unlock(&mm->page_table_lock);
 	return error;
 }
@@ -223,6 +230,10 @@
 	struct vm_area_struct *vma;
 	unsigned long ret = -EINVAL;
 
+#ifdef CONFIG_MOSIX_DIAG
+	if(current->mosix.dflags & DDEPUTY)
+		panic("sys_mremap: DEPUTY");
+#endif /* CONFIG_MOSIX_DIAG */
 	if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
 		goto out;
 
@@ -258,16 +269,20 @@
 		if ((addr <= new_addr) && (addr+old_len) > new_addr)
 			goto out;
 
-		do_munmap(current->mm, new_addr, new_len);
+		ret = do_munmap(current->mm, new_addr, new_len);
+		if (ret && new_len)
+			goto out;
 	}
 
 	/*
 	 * Always allow a shrinking remap: that just unmaps
 	 * the unnecessary pages..
 	 */
-	ret = addr;
 	if (old_len >= new_len) {
-		do_munmap(current->mm, addr+new_len, old_len - new_len);
+		ret = do_munmap(current->mm, addr+new_len, old_len - new_len);
+		if (ret && old_len != new_len)
+			goto out;
+		ret = addr;
 		if (!(flags & MREMAP_FIXED) || (new_addr == addr))
 			goto out;
 	}
@@ -360,5 +375,12 @@
 	down_write(&current->mm->mmap_sem);
 	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
 	up_write(&current->mm->mmap_sem);
+#ifdef CONFIG_MOSIX
+	if(process_told(current, DREQ_FILEUNMAP))
+	{
+		process_ack(current, DREQ_FILEUNMAP);
+		mosix_rebuild_file_list();
+	}
+#endif /* CONFIG_MOSIX */
 	return ret;
 }
diff -Naur --exclude=CVS --exclude=configs linux/mm/oom_kill.c linux-openmosix/mm/oom_kill.c
--- linux/mm/oom_kill.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/oom_kill.c	2004-02-05 10:51:31.000000000 +0100
@@ -25,6 +25,7 @@
 
 /* #define DEBUG */
 
+
 /**
  * int_sqrt - oom_kill.c internal function, rough approximation to sqrt
  * @x: integer of which to calculate the sqrt
@@ -95,6 +96,11 @@
 	 * Superuser processes are usually more important, so we make it
 	 * less likely that we kill those.
 	 */
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DREMOTE)
+		points *= 2;
+	else
+#endif /* CONFIG_MOSIX */
 	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
 				p->uid == 0 || p->euid == 0)
 		points /= 4;
@@ -105,6 +111,9 @@
 	 * tend to only have this flag set on applications they think
 	 * of as important.
 	 */
+#ifdef CONFIG_MOSIX
+	if(!(p->mosix.dflags & DREMOTE))
+#endif /* CONFIG_MOSIX */
 	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
 		points /= 4;
 #ifdef DEBUG
@@ -155,6 +164,11 @@
 	p->counter = 5 * HZ;
 
 	/* This process has hardware access, be more careful. */
+#ifdef CONFIG_MOSIX
+	if(p->mosix.dflags & DREMOTE)
+		send_sig(SIGTERM, p, 1);
+	else
+#endif /* CONFIG_MOSIX */
 	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO)) {
 		force_sig(SIGTERM, p);
 	} else {
@@ -174,6 +188,17 @@
 {
 	struct task_struct *p, *q;
 
+#ifdef CONFIG_MOSIX_NO_OOM
+
+/* We don't need no stinking OOM in openMosix
+ * Rather, we just send a message to syslog that the system
+ * is out of memory and let fate take over the system  - Moshe Bar  */
+
+	printk("openMosix: this node is seriously out of memory due to VM overcommit. I think I will pass out now.\n");
+  
+	return;
+#endif 
+
 	read_lock(&tasklist_lock);
 	p = select_bad_process();
 
diff -Naur --exclude=CVS --exclude=configs linux/mm/page_alloc.c linux-openmosix/mm/page_alloc.c
--- linux/mm/page_alloc.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/page_alloc.c	2004-02-05 10:51:31.000000000 +0100
@@ -397,7 +397,20 @@
 		goto out;
 
  rebalance:
+#ifdef CONFIG_MOSIX
+	{
+		__typeof__(jiffies)before = jiffies;
+#endif /* CONFIG_MOSIX */
 	page = balance_classzone(classzone, gfp_mask, order, &freed);
+#ifdef CONFIG_MOSIX
+	if((before = jiffies - before))
+#if 1000000 % HZ == 0
+		current->mosix.pagetime += before * (1000000 / HZ);
+#else
+		current->mosix.pagetime += before * 1000000 / HZ;
+#endif
+}
+#endif /* CONFIG_MOSIX */
 	if (page)
 		return page;
 
diff -Naur --exclude=CVS --exclude=configs linux/mm/vmscan.c linux-openmosix/mm/vmscan.c
--- linux/mm/vmscan.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/mm/vmscan.c	2004-02-05 10:51:31.000000000 +0100
@@ -79,6 +79,15 @@
 	pte_t pte;
 	swp_entry_t entry;
 
+#ifdef CONFIG_MOSIX
+	/* no swap_out conflict here - Copyright by Qlusters, Inc. */
+	if(page->young)
+	{
+		page->young = 0;
+		return(0);
+	}
+#endif /* CONFIG_MOSIX */
+
 	/* Don't look at this pte if it's been accessed recently. */
 	if ((vma->vm_flags & VM_LOCKED) || ptep_test_and_clear_young(page_table)) {
 		mark_page_accessed(page);
@@ -817,6 +826,10 @@
 		 * the processes needing more memory will wake us
 		 * up on a more timely basis.
 		 */
+#ifdef CONFIG_MOSIX
+		refill_inactive(-(nr_active_pages + 63) >> 6,
+					NODE_DATA(0)->node_zones);
+#endif /* CONFIG_MOSIX */
 		kswapd_balance();
 		run_task_queue(&tq_disk);
 	}
diff -Naur --exclude=CVS --exclude=configs linux/net/802/cl2llc.c linux-openmosix/net/802/cl2llc.c
--- linux/net/802/cl2llc.c	2001-04-06 19:51:19.000000000 +0200
+++ linux-openmosix/net/802/cl2llc.c	2004-02-05 10:51:32.000000000 +0100
@@ -96,7 +96,7 @@
 				else
 					llc_interpret_pseudo_code(lp, REJECT1, skb, NO_FRAME);
 				break;
-			default:;
+			default:
 		}
 		if(lp->llc_callbacks)
 		{
@@ -497,7 +497,7 @@
 				else
 					lp->f_flag = fr->i_hdr.i_pflag;
 				break;
-			default:;
+			default:
 		}
 		pc++;	
 	}
diff -Naur --exclude=CVS --exclude=configs linux/net/bluetooth/rfcomm/core.c linux-openmosix/net/bluetooth/rfcomm/core.c
--- linux/net/bluetooth/rfcomm/core.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/bluetooth/rfcomm/core.c	2004-02-05 10:51:32.000000000 +0100
@@ -28,7 +28,7 @@
 /*
  * RFCOMM core.
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #define __KERNEL_SYSCALLS__
diff -Naur --exclude=CVS --exclude=configs linux/net/bluetooth/rfcomm/crc.c linux-openmosix/net/bluetooth/rfcomm/crc.c
--- linux/net/bluetooth/rfcomm/crc.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-openmosix/net/bluetooth/rfcomm/crc.c	2004-02-05 10:51:32.000000000 +0100
@@ -24,7 +24,7 @@
 /*
  * RFCOMM FCS calculation.
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 /* reversed, 8-bit, poly=0x07 */
diff -Naur --exclude=CVS --exclude=configs linux/net/bluetooth/rfcomm/sock.c linux-openmosix/net/bluetooth/rfcomm/sock.c
--- linux/net/bluetooth/rfcomm/sock.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/net/bluetooth/rfcomm/sock.c	2004-02-05 10:51:32.000000000 +0100
@@ -24,7 +24,7 @@
 /*
  * RFCOMM sockets.
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #include <linux/config.h>
diff -Naur --exclude=CVS --exclude=configs linux/net/bluetooth/rfcomm/tty.c linux-openmosix/net/bluetooth/rfcomm/tty.c
--- linux/net/bluetooth/rfcomm/tty.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/net/bluetooth/rfcomm/tty.c	2004-02-05 10:51:32.000000000 +0100
@@ -24,7 +24,7 @@
 /*
  * RFCOMM TTY.
  *
- * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  */
 
 #include <linux/config.h>
diff -Naur --exclude=CVS --exclude=configs linux/net/core/scm.c linux-openmosix/net/core/scm.c
--- linux/net/core/scm.c	2001-12-21 18:42:05.000000000 +0100
+++ linux-openmosix/net/core/scm.c	2004-02-05 10:51:32.000000000 +0100
@@ -31,6 +31,9 @@
 #include <net/sock.h>
 #include <net/scm.h>
 
+#ifdef CONFIG_MOSIX_DFSA
+#include <linux/dfsa_interface.h>
+#endif /* CONFIG_MOSIX_DFSA */
 
 /*
  *	Only allow a user to send credentials, that they could set with 
@@ -81,6 +84,12 @@
 	 *	Verify the descriptors and increment the usage count.
 	 */
 	 
+#ifdef CONFIG_MOSIX_DFSA
+	/* this is massive and rare, so rather than make special cases: */
+	if(current->mosix.dflags & DREMOTE)
+		return(-EDOITATHOME);
+	dfsa_is_not_up_to_date();
+#endif /* CONFIG_MOSIX_DFSA */
 	for (i=0; i< num; i++)
 	{
 		int fd = fdp[i];
@@ -206,6 +215,10 @@
 	int *cmfptr;
 	int err = 0, i;
 
+#ifdef CONFIG_MOSIX_DFSA
+	if(current->mosix.dflags & DREMOTE)
+		panic("scm_detach_fds: REMOTE");
+#endif /* CONFIG_MOSIX_DFSA */
 	if (msg->msg_controllen > sizeof(struct cmsghdr))
 		fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr))
 			 / sizeof(int));
diff -Naur --exclude=CVS --exclude=configs linux/net/core/skbuff.c linux-openmosix/net/core/skbuff.c
--- linux/net/core/skbuff.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/net/core/skbuff.c	2004-02-05 10:51:32.000000000 +0100
@@ -61,6 +61,10 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 int sysctl_hot_list_len = 128;
 
 static kmem_cache_t *skbuff_head_cache;
diff -Naur --exclude=CVS --exclude=configs linux/net/core/sock.c linux-openmosix/net/core/sock.c
--- linux/net/core/sock.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-openmosix/net/core/sock.c	2004-02-05 10:51:32.000000000 +0100
@@ -128,6 +128,10 @@
 #include <net/tcp.h>
 #endif
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 /* Run time adjustable parameters. */
 __u32 sysctl_wmem_max = SK_WMEM_MAX;
 __u32 sysctl_rmem_max = SK_RMEM_MAX;
@@ -1138,6 +1142,10 @@
 	if (sk->sleep && waitqueue_active(sk->sleep))
 		wake_up_interruptible(sk->sleep);
 	sk_wake_async(sk,1,POLL_IN);
+#ifdef CONFIG_MOSIX
+	if (sk->socket && test_bit(SOCK_INTER_MOSIX, &sk->socket->flags))
+		mosix_notify_receive(sk->socket);
+#endif /* CONFIG_MOSIX */
 	read_unlock(&sk->callback_lock);
 }
 
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/af_inet.c linux-openmosix/net/ipv4/af_inet.c
--- linux/net/ipv4/af_inet.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/af_inet.c	2004-02-05 10:51:33.000000000 +0100
@@ -117,6 +117,10 @@
 #include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */
 #endif	/* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
+
 struct linux_mib net_statistics[NR_CPUS*2];
 
 #ifdef INET_REFCNT_DEBUG
@@ -556,6 +560,10 @@
 
 	if (sk->num==0 && inet_autobind(sk) != 0)
 		return -EAGAIN;
+#ifdef CONFIG_MOSIX
+	if(reserved_mosix_address(uaddr))
+		return(-EACCES);
+#endif /* CONFIG_MOSIX */
 	return sk->prot->connect(sk, (struct sockaddr *)uaddr, addr_len);
 }
 
@@ -620,6 +628,11 @@
 		if (sk->state != TCP_CLOSE) 
 			goto out;
 
+#ifdef CONFIG_MOSIX
+		err = -EACCES;
+		if(reserved_mosix_address(uaddr))
+			goto out;
+#endif /* CONFIG_MOSIX */
 		err = sk->prot->connect(sk, uaddr, addr_len);
 		if (err < 0)
 			goto out;
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ip_sockglue.c linux-openmosix/net/ipv4/ip_sockglue.c
--- linux/net/ipv4/ip_sockglue.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/net/ipv4/ip_sockglue.c	2004-05-19 00:34:54.000000000 +0200
@@ -622,6 +622,17 @@
 				kfree(msf);
 				break;
 			}
+			/* numsrc >= (1G-4) overflow in 32 bits */
+			if (msf->imsf_numsrc >= 0x3ffffffcU) {
+				kfree(msf);
+				err = -ENOBUFS;
+				break;
+			}
+			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
+				kfree(msf);
+				err = -EINVAL;
+				break;
+			}
 			err = ip_mc_msfilter(sk, msf, 0);
 			kfree(msf);
 			break;
@@ -760,7 +771,12 @@
 			if (copy_from_user(gsf, optval, optlen)) {
 				goto mc_msf_out;
 			}
-			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < optlen) {
+			/* numsrc >= (4G-140)/128 overflow in 32 bits */
+			if (gsf->gf_numsrc >= 0x1ffffffU) {
+				err = -ENOBUFS;
+				goto mc_msf_out;
+			}
+			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
 				err = EINVAL;
 				goto mc_msf_out;
 			}
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_app.c linux-openmosix/net/ipv4/ipvs/ip_vs_app.c
--- linux/net/ipv4/ipvs/ip_vs_app.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_app.c	2004-02-05 10:51:33.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS         Application module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_conn.c linux-openmosix/net/ipv4/ipvs/ip_vs_conn.c
--- linux/net/ipv4/ipvs/ip_vs_conn.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_conn.c	2004-02-05 10:51:33.000000000 +0100
@@ -5,7 +5,7 @@
  *              high-performance and highly available server based on a
  *              cluster of servers.
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *              Peter Kese <peter.kese@ijs.si>
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_core.c linux-openmosix/net/ipv4/ipvs/ip_vs_core.c
--- linux/net/ipv4/ipvs/ip_vs_core.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_core.c	2004-02-05 10:51:33.000000000 +0100
@@ -5,7 +5,7 @@
  *              high-performance and highly available server based on a
  *              cluster of servers.
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *              Peter Kese <peter.kese@ijs.si>
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_ctl.c linux-openmosix/net/ipv4/ipvs/ip_vs_ctl.c
--- linux/net/ipv4/ipvs/ip_vs_ctl.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_ctl.c	2004-02-05 10:51:33.000000000 +0100
@@ -5,7 +5,7 @@
  *              high-performance and highly available server based on a
  *              cluster of servers.
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *              Peter Kese <peter.kese@ijs.si>
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_dh.c linux-openmosix/net/ipv4/ipvs/ip_vs_dh.c
--- linux/net/ipv4/ipvs/ip_vs_dh.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_dh.c	2004-02-05 10:51:33.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Destination Hashing scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@gnuchina.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_est.c linux-openmosix/net/ipv4/ipvs/ip_vs_est.c
--- linux/net/ipv4/ipvs/ip_vs_est.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_est.c	2004-02-05 10:51:33.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * ip_vs_est.c  Simple rate estimator for IPVS
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_ftp.c linux-openmosix/net/ipv4/ipvs/ip_vs_ftp.c
--- linux/net/ipv4/ipvs/ip_vs_ftp.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_ftp.c	2004-02-05 10:51:33.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IP_VS        ftp application module
  *
- * Version:	$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:	$Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:	Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_lblc.c linux-openmosix/net/ipv4/ipvs/ip_vs_lblc.c
--- linux/net/ipv4/ipvs/ip_vs_lblc.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_lblc.c	2004-02-05 10:51:33.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Locality-Based Least-Connection scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@gnuchina.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_lblcr.c linux-openmosix/net/ipv4/ipvs/ip_vs_lblcr.c
--- linux/net/ipv4/ipvs/ip_vs_lblcr.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_lblcr.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Locality-Based Least-Connection with Replication scheduler
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@gnuchina.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_lc.c linux-openmosix/net/ipv4/ipvs/ip_vs_lc.c
--- linux/net/ipv4/ipvs/ip_vs_lc.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_lc.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Least-Connection Scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_nq.c linux-openmosix/net/ipv4/ipvs/ip_vs_nq.c
--- linux/net/ipv4/ipvs/ip_vs_nq.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_nq.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Never Queue scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_rr.c linux-openmosix/net/ipv4/ipvs/ip_vs_rr.c
--- linux/net/ipv4/ipvs/ip_vs_rr.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_rr.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Round-Robin Scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *              Peter Kese <peter.kese@ijs.si>
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_sched.c linux-openmosix/net/ipv4/ipvs/ip_vs_sched.c
--- linux/net/ipv4/ipvs/ip_vs_sched.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_sched.c	2004-02-05 10:51:34.000000000 +0100
@@ -5,7 +5,7 @@
  *              high-performance and highly available server based on a
  *              cluster of servers.
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *              Peter Kese <peter.kese@ijs.si>
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_sed.c linux-openmosix/net/ipv4/ipvs/ip_vs_sed.c
--- linux/net/ipv4/ipvs/ip_vs_sed.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_sed.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Shortest Expected Delay scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_sh.c linux-openmosix/net/ipv4/ipvs/ip_vs_sh.c
--- linux/net/ipv4/ipvs/ip_vs_sh.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_sh.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Source Hashing scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@gnuchina.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_sync.c linux-openmosix/net/ipv4/ipvs/ip_vs_sync.c
--- linux/net/ipv4/ipvs/ip_vs_sync.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_sync.c	2004-02-05 10:51:34.000000000 +0100
@@ -5,7 +5,7 @@
  *              high-performance and highly available server based on a
  *              cluster of servers.
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_wlc.c linux-openmosix/net/ipv4/ipvs/ip_vs_wlc.c
--- linux/net/ipv4/ipvs/ip_vs_wlc.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_wlc.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Weighted Least-Connection Scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *              Peter Kese <peter.kese@ijs.si>
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/ipvs/ip_vs_wrr.c linux-openmosix/net/ipv4/ipvs/ip_vs_wrr.c
--- linux/net/ipv4/ipvs/ip_vs_wrr.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/ipvs/ip_vs_wrr.c	2004-02-05 10:51:34.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  * IPVS:        Weighted Round-Robin Scheduling module
  *
- * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
+ * Version:     $Id: openMosix-2.4.24-om1,v 1.1 2004/07/02 08:38:16 sithender Exp $
  *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv4/tcp_input.c linux-openmosix/net/ipv4/tcp_input.c
--- linux/net/ipv4/tcp_input.c	2003-11-28 19:26:21.000000000 +0100
+++ linux-openmosix/net/ipv4/tcp_input.c	2004-02-05 10:51:33.000000000 +0100
@@ -2112,6 +2112,9 @@
 	return 0;
 }
 
+#ifdef CONFIG_MOSIX
+#include <linux/hpc.h>
+#endif /* CONFIG_MOSIX */
 
 /* Look for tcp options. Normally only called on SYN and SYNACK packets.
  * But, this can also be called on packets in the established flow when
@@ -3177,7 +3180,13 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	u32 ptr = ntohs(th->urg_ptr);
 
+#ifdef CONFIG_MOSIX
+	/* MOSIX sockets always use BSD style regardless of sysctl_tcp_stdurg */
+	if (ptr && (!sysctl_tcp_stdurg ||
+		(sk->socket && test_bit(SOCK_INTER_MOSIX, &sk->socket->flags))))
+#else
 	if (ptr && !sysctl_tcp_stdurg)
+#endif /* CONFIG_MOSIX */
 		ptr--;
 	ptr += ntohl(th->seq);
 
@@ -3204,6 +3213,17 @@
 
 	/* Tell the world about our new urgent pointer. */
 	if (sk->proc != 0) {
+#ifdef CONFIG_MOSIX
+		if (!sk->socket)
+#ifdef CONFIG_MOSIX_DEBUG
+			printk("tcp_check_urg: funny, no socket, sk=0x%x",
+									(int)sk)
+#endif /* CONFIG_MOSIX_DEBUG */
+				;
+		else if (test_bit(SOCK_INTER_MOSIX, &sk->socket->flags))
+			/*mosix_notify_urgent(sk->socket)*/ ;
+		else
+#endif /* CONFIG_MOSIX */
 		if (sk->proc > 0)
 			kill_proc(sk->proc, SIGURG, 1);
 		else
@@ -3265,6 +3285,15 @@
 			tp->urg_data = TCP_URG_VALID | tmp;
 			if (!sk->dead)
 				sk->data_ready(sk,0);
+#ifdef CONFIG_MOSIX
+			if (sk->socket &&
+				test_bit(SOCK_INTER_MOSIX, &sk->socket->flags))
+			{
+				if(tmp != 0xdb)
+					printk("tcp_urg: not 0xdb (%x)\n", tmp);
+				mosix_notify_urgent(sk->socket);
+			}
+#endif /* CONFIG_MOSIX */
 		}
 	}
 }
diff -Naur --exclude=CVS --exclude=configs linux/net/ipv6/ipv6_sockglue.c linux-openmosix/net/ipv6/ipv6_sockglue.c
--- linux/net/ipv6/ipv6_sockglue.c	2003-08-25 13:44:44.000000000 +0200
+++ linux-openmosix/net/ipv6/ipv6_sockglue.c	2004-05-19 00:34:55.000000000 +0200
@@ -466,6 +466,17 @@
 			kfree(gsf);
 			break;
 		}
+		/* numsrc >= (4G-140)/128 overflow in 32 bits */
+		if (gsf->gf_numsrc >= 0x1ffffffU) {
+			kfree(gsf);
+			retv = -ENOBUFS;
+			break;
+		}
+		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
+			kfree(gsf);
+			retv = -EINVAL;
+			break;
+		}
 		retv = ip6_mc_msfilter(sk, gsf);
 		kfree(gsf);
 
diff -Naur --exclude=CVS --exclude=configs linux/net/sunrpc/sched.c linux-openmosix/net/sunrpc/sched.c
--- linux/net/sunrpc/sched.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-openmosix/net/sunrpc/sched.c	2004-02-05 10:51:34.000000000 +0100
@@ -1112,6 +1112,9 @@
 	 * Usually rpciod will exit very quickly, so we
 	 * wait briefly before checking the process id.
 	 */
+#ifdef CONFIG_MOSIX
+	current->mosix.ignoreoldsigs = 1;
+#endif /* CONFIG_MOSIX */
 	current->sigpending = 0;
 	yield();
 	/*
diff -Naur --exclude=CVS --exclude=configs linux/net/sunrpc/svc.c linux-openmosix/net/sunrpc/svc.c
--- linux/net/sunrpc/svc.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-openmosix/net/sunrpc/svc.c	2004-02-05 10:51:34.000000000 +0100
@@ -198,6 +198,9 @@
 		progp->pg_name, proto == IPPROTO_UDP? "udp" : "tcp", port);
 
 	if (!port)
+#ifdef CONFIG_MOSIX
+		current->mosix.ignoreoldsigs = 1,
+#endif /* CONFIG_MOSIX */
 		current->sigpending = 0;
 
 	for (i = 0; i < progp->pg_nvers; i++) {
diff -Naur --exclude=CVS --exclude=configs linux/openMosix_MAINTAINERS linux-openmosix/openMosix_MAINTAINERS
--- linux/openMosix_MAINTAINERS	1970-01-01 01:00:00.000000000 +0100
+++ linux-openmosix/openMosix_MAINTAINERS	2004-03-11 18:02:27.000000000 +0100
@@ -0,0 +1,12 @@
+Current maintainers with commit bit are (not by any significant ordering):
+
+Matthias Rechenburg (kernel, user-space)	matt@qlusters.com
+Vincent Hanquez (kernel)			tab@tuxfamily.org
+Moshe Bar (kernel, user-space)			moshe@qlusters.com
+Bruce Knox (PR and webmaster)			bknox@uaex.edu
+Ettore Simone (kernel)				esimone@suse.it
+Jason Ferrara(kernel)				jason@xxx.com
+Aaron Peterson(CVS, sysadmin, userland)		aaronp@qlusters.com
+
+
+
