--- /dev/null
+# Copyright (C) 2001 Cluster File Systems, Inc.
+#
+# This code is issued under the GNU General Public License.
+# See the file COPYING in this distribution
+
+%define arch i586-smp
+%define kernel_version 2.4.20
+%define patch_version
+%define lustre_version 22
+%define lustre_release PQ_TEST
+%define lustre_branch b_devel
+%define kernel_config kernel-2.4.20
+
+# disable build root strip policy
+%define __spec_install_post /usr/lib/rpm/brp-compress || :
+%ifarch ia64
+%define initrd_dir /boot/efi/redhat
+%else
+%define initrd_dir /boot
+%endif
+
+Name: lustre-kernel
+Summary: The Linux_lustre kernel
+Version: %{kernel_version}%{patch_version}_lustre%{lustre_version}
+Release: %{lustre_release}
+License: GPL
+Group: System Environment/Kernel
+URL: http://www.lustre.org/pub/lustre/
+BuildRoot: %{_tmppath}/%{kernel_version}-%{patch_version}-buildroot
+BuildConflicts: rhbuildsys(DiskFree) < 500Mb
+BuildRequires: gcc >= 2.96-98 modutils >= 2.4.10
+
+Source0: linux-%{kernel_version}-%{patch_version}.tar.gz
+Source1: lustre-%{lustre_branch}.tar.gz
+Patch0: lustre-patch-%{lustre_version}
+
+%description
+The Lustre Lite Cluster File System: kernel for lustre file system
+
+%package -n lustre-kernel-debug
+Summary: lustre-kernel-packages with debug info
+Group: System Environment/Kernel
+
+%description -n lustre-kernel-debug
+lustre-kernel-packages with debug info
+
+%package -n lustre-lite-utils
+Summary: Lustre utils for Linux %{kernel_version}
+Group: Development
+
+%description -n lustre-lite-utils
+The Lustre Lite Cluster File System utilities.
+
+%package -n lustre-doc
+Summary: Documentation and sample configuration files
+Group: Documentation
+
+%description -n lustre-doc
+Documentation and sample configuration files for Lustre
+
+%package -n lustre-ldap
+Summary: Configures openldap server for LDAP Lustre config database
+Group: Configuration
+Requires: openldap-servers, openldap-clients, python-ldap, 4Suite
+
+%description -n lustre-ldap
+Configures openldap server for LDAP Lustre config database
+
+#####################################################
+%prep
+%setup -q -n linux-%{kernel_version}-%{patch_version}
+
+#patch the lustre kernel
+%patch0 -p1
+#mkdir -p configs
+#cp -fv $RPM_SOURCE_DIR/kernel-%{kernel_version}-%{arch}.config configs
+sed -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{patch_version}_lustre%{lustre_version}/g" < Makefile > Makefile.new
+mv -f Makefile.new Makefile
+
+#get rid of -g flags
+sed -e "s/\([^$]\)*CFLAGS\([^$]\)*\+=\([^$]\)*\-g//g" < Makefile > Makefile.new
+mv -f Makefile.new Makefile
+# get rid of unwanted files
+find . -name "*.orig" -exec rm -fv {} \;
+find . -name "*~" -exec rm -fv {} \;
+
+#FIXME later, I do not know how to setup two build directory
+#For debug info kernel FIXME later
+rm -rf $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}-debug
+mkdir -p $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}-debug
+gzip -dc $RPM_SOURCE_DIR/linux-%{kernel_version}-%{patch_version}.tar.gz | tar -xf- -C $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}-debug
+
+#for release lustre
+rm -rf $RPM_BUILD_DIR/lustre-%{lustre_branch}
+gzip -dc $RPM_SOURCE_DIR/lustre-%{lustre_branch}.tar.gz | tar -xf- -C $RPM_BUILD_DIR/
+
+#for debug lustre
+rm -rf $RPM_BUILD_DIR/lustre-%{lustre_release}-debug
+mkdir -p $RPM_BUILD_DIR/lustre-%{lustre_release}-debug
+gzip -dc $RPM_SOURCE_DIR/lustre-%{lustre_branch}.tar.gz | tar -xf- -C $RPM_BUILD_DIR/lustre-%{lustre_release}-debug
+# end of prepare
+#####################################################
+
+#####################################################
+# build
+%build
+
+BuildKernel() {
+ cd $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}
+ make distclean
+ cp -fv $RPM_BUILD_DIR/lustre-%{lustre_branch}/kernel_patches/kernel_configs/%{kernel_config} .config
+ if [ %{arch} = "ia64" ]; then
+ make oldconfig dep vmlinux modules
+ else
+ make oldconfig dep bzImage modules
+ fi
+}
+BuildLustre() {
+ cd $RPM_BUILD_DIR/lustre-%{lustre_branch}
+ sh autogen.sh
+ ./configure --with-linux="$RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}"
+ make
+}
+
+BuildDebugKernel() {
+ cd $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}-debug/linux-%{kernel_version}-%{patch_version}
+ patch -p1 < $RPM_SOURCE_DIR/lustre-patch-%{lustre_version}
+ make distclean
+ cp -fv $RPM_BUILD_DIR/lustre-%{lustre_branch}/kernel_patches/kernel_configs/%{kernel_config} .config
+ sed -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{patch_version}_lustre%{lustre_version}-debug/g" < Makefile > Makefile.new
+ mv -f Makefile.new Makefile
+ if [ %{arch} = "ia64" ]; then
+ make oldconfig dep vmlinux modules
+ else
+ make oldconfig dep bzImage modules
+ fi
+}
+BuildDebugLustre() {
+ cd $RPM_BUILD_DIR/lustre-%{lustre_release}-debug/lustre-%{lustre_branch}
+ sh autogen.sh
+ ./configure --with-linux="$RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}-debug/linux-%{kernel_version}-%{patch_version}"
+ make
+}
+rm -rf $RPM_BUILD_ROOT
+
+BuildKernel
+BuildLustre
+BuildDebugKernel
+BuildDebugLustre
+# end of build
+#####################################################
+
+#####################################################
+# install kernel and lustre_modules
+%install
+
+#install kernel
+cd $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}
+mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules
+INSTALL_MOD_PATH=$RPM_BUILD_ROOT/ make modules_install
+if [ %{arch} = "ia64" ]; then
+ cp vmlinux $RPM_BUILD_ROOT/boot/vmlinuz-%{kernel_version}_lustre%{lustre_version}
+else
+ cp arch/i386/boot/bzImage $RPM_BUILD_ROOT/boot/vmlinuz-%{kernel_version}_lustre%{lustre_version}
+fi
+cp System.map $RPM_BUILD_ROOT/boot/System.map-%{kernel_version}-%{patch_version}_lustre%{lustre_version}
+cp .config $RPM_BUILD_ROOT/boot/config-%{kernel_version}_lustre%{lustre_version}
+
+#install debug kernel
+cd $RPM_BUILD_DIR/linux-%{kernel_version}-%{patch_version}-debug/linux-%{kernel_version}-%{patch_version}
+mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules
+INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install
+if [ %{arch} = "ia64" ]; then
+ cp vmlinux $RPM_BUILD_ROOT/boot/vmlinuz-%{kernel_version}_lustre%{lustre_version}-debug
+else
+ cp arch/i386/boot/bzImage $RPM_BUILD_ROOT/boot/vmlinuz-%{kernel_version}_lustre%{lustre_version}-debug
+fi
+cp System.map $RPM_BUILD_ROOT/boot/System.map-%{kernel_version}-%{patch_version}_lustre%{lustre_version}-debug
+cp vmlinux $RPM_BUILD_ROOT/boot/vmlinux-%{kernel_version}_lustre%{lustre_version}-debug
+cp .config $RPM_BUILD_ROOT/boot/config-%{kernel_version}_lustre%{lustre_version}-debug
+
+#install lustre
+cd $RPM_BUILD_DIR/lustre-%{lustre_branch}
+make install prefix="$RPM_BUILD_ROOT"
+
+#install debug lustre
+cd $RPM_BUILD_DIR/lustre-%{lustre_release}-debug/lustre-%{lustre_branch}
+make install prefix="$RPM_BUILD_ROOT/"
+
+#install Document of lustre
+mkdir -p $RPM_BUILD_ROOT/usr/share/doc/lustre
+cp -pr $RPM_BUILD_DIR/lustre-%{lustre_branch}/COPYING $RPM_BUILD_ROOT/usr/share/doc/lustre
+cp -pr $RPM_BUILD_DIR/lustre-%{lustre_branch}/doc/lustre.pdf $RPM_BUILD_ROOT/usr/share/doc/lustre
+cp -pr $RPM_BUILD_DIR/lustre-%{lustre_branch}/doc/lustre-HOWTO.txt $RPM_BUILD_ROOT/usr/share/doc/lustre
+
+%ifarch alpha
+# this hurts me
+ conf_flag=
+ linuxdir=$RPM_BUILD_ROOT/linux-%{kernel_version}-%{patch_version}
+ test -d $linuxdir && conf_flag=--with-linux=$linuxdir
+ make clean
+ ./configure --enable-rtscts-myrinet $conf_flag
+ make
+ cp linux/rtscts/rtscts.o $RPM_BUILD_ROOT/lib/modules/%{kernel_version}-%{patch_version}/kernel/net/lustre/rtscts_myrinet.o
+ cp user/myrinet_utils/mcpload $RPM_BUILD_ROOT/lustre/usr/sbin/mcpload
+%endif
+
+mkdir -p $RPM_BUILD_ROOT/var/lib/ldap/lustre
+# end of install
+#################################################
+
+#################################################
+# file lists
+%files
+%defattr (-, root, root)
+/boot/vmlinuz-%{kernel_version}_lustre%{lustre_version}
+/boot/System.map-%{kernel_version}-%{patch_version}_lustre%{lustre_version}
+/boot/config-%{kernel_version}_lustre%{lustre_version}
+%dir /lib/modules/%{kernel_version}-%{patch_version}_lustre%{lustre_version}
+/lib/modules/%{kernel_version}-%{patch_version}_lustre%{lustre_version}
+
+%files -n lustre-kernel-debug
+%defattr (-, root, root)
+/boot/vmlinuz-%{kernel_version}_lustre%{lustre_version}-debug
+/boot/vmlinux-%{kernel_version}_lustre%{lustre_version}-debug
+/boot/System.map-%{kernel_version}-%{patch_version}_lustre%{lustre_version}-debug
+/boot/config-%{kernel_version}_lustre%{lustre_version}-debug
+%dir /lib/modules/%{kernel_version}-%{patch_version}_lustre%{lustre_version}-debug
+/lib/modules/%{kernel_version}-%{patch_version}_lustre%{lustre_version}-debug
+
+%files -n lustre-lite-utils
+%attr(-, root, root) /usr/sbin/lmc
+%attr(-, root, root) /usr/sbin/lctl
+%attr(-, root, root) /usr/sbin/lconf
+%attr(-, root, root) /usr/sbin/lactive
+%attr(-, root, root) /usr/sbin/llanalyze
+%attr(755, root, root) /usr/sbin/lfind
+%attr(755, root, root) /usr/sbin/lstripe
+%attr(-, root, root) /usr/sbin/mcreate
+%attr(-, root, root) /usr/sbin/mkdirmany
+%attr(-, root, root) /usr/sbin/munlink
+%attr(-, root, root) /usr/sbin/llstat.pl
+%attr(-, root, root) /usr/sbin/llobdstat.pl
+%attr(-, root, root) /usr/sbin/load_ldap.sh
+%attr(755, root, root) /usr/lib/lustre/python/*
+%attr(755, root, root) /usr/lib/lustre/examples/llmount.sh
+%attr(755, root, root) /usr/lib/lustre/examples/llmountcleanup.sh
+%attr(755, root, root) /usr/lib/lustre/examples/llecho.sh
+%attr(755, root, root) /usr/lib/lustre/examples/local.sh
+%attr(755, root, root) /usr/lib/lustre/examples/uml.sh
+%attr(755, root, root) /usr/lib/lustre/examples/lov.sh
+%attr(755, root, root) /usr/lib/lustre/examples/echo.sh
+%attr(755, root, root) /usr/lib/lustre/examples/llechocleanup.sh
+
+%attr(-, root, root) /etc/init.d/lustre
+%attr(-, root, root) /usr/sbin/acceptor
+%attr(-, root, root) /usr/sbin/ptlctl
+%attr(-, root, root) /usr/sbin/debugctl
+%attr(-, root, root) /lib/libportals.a
+%attr(-, root, root) /lib/libptlctl.a
+%attr(-, root, root) /lib/libtcpnal.a
+%attr(-, root, root) /usr/include/lustre/*.h
+%attr(-, root, root) /usr/sbin/lload
+%attr(-, root, root) /usr/sbin/obdbarrier
+%attr(-, root, root) /usr/sbin/obdio
+%attr(-, root, root) /usr/sbin/routerstat
+%attr(-, root, root) /usr/sbin/wirecheck
+
+%ifarch alpha
+%attr(-, root, root) /usr/sbin/mcpload
+%endif
+
+%files -n lustre-doc
+%attr(-, root, root) /usr/share/doc/lustre/COPYING
+%attr(-, root, root) /usr/share/doc/lustre/lustre.pdf
+%attr(-, root, root) /usr/share/doc/lustre/lustre-HOWTO.txt
+
+%files -n lustre-ldap
+%attr(-, root, root) /etc/openldap/slapd-lustre.conf
+%attr(-, root, root) /etc/openldap/schema/lustre.schema
+%attr(-, root, root) /usr/lib/lustre/lustre2ldif.xsl
+%attr(-, root, root) /usr/lib/lustre/top.ldif
+#%dir /var/lib/ldap/lustre
+%attr(700, ldap, ldap) /var/lib/ldap/lustre
+
+################################################
+# clean
+%clean
+rm -rf $RPM_BUILD_ROOT
+# end of clean
+###############################################
+
+###############################################
+# post
+%post
+if [ ! -e /dev/obd ]; then
+ mknod /dev/obd c 10 241
+fi
+if [ ! -e /dev/portals ]; then
+ mknod /dev/portals c 10 240
+fi
+depmod -ae || exit 0
+
+#change the grub.conf
+#cd /boot
+#[ -x /usr/sbin/module_upgrade ] && /usr/sbin/module_upgrade
+#[ -x /sbin/mkkerneldoth ] && /sbin/mkkerneldoth
+#if [ -x /sbin/new-kernel-pkg ] ; then
+# /sbin/new-kernel-pkg --mkinitrd --depmod --install %{kernel_version}-%{patch_version}_lustre%{lustre_version}
+#fi
+
+%postun
+depmod -ae || exit 0
+
+%post -n lustre-kernel-debug
+if [ ! -e /dev/obd ]; then
+ mknod /dev/obd c 10 241
+fi
+if [ ! -e /dev/portals ]; then
+ mknod /dev/portals c 10 240
+fi
+depmod -ae || exit 0
+
+#change the grub.conf
+#cd /boot
+#[ -x /usr/sbin/module_upgrade ] && /usr/sbin/module_upgrade
+#[ -x /sbin/mkkerneldoth ] && /sbin/mkkerneldoth
+#if [ -x /sbin/new-kernel-pkg ] ; then
+# /sbin/new-kernel-pkg --mkinitrd --depmod --install %{kernel_version}-%{patch_version}_lustre%{lustre_version}-debug
+#fi
+
+%post -n lustre-ldap
+if ! grep -q slapd-lustre /etc/openldap/slapd.conf; then
+ echo "include /etc/openldap/slapd-lustre.conf" >> /etc/openldap/slapd.conf
+fi
+
+%postun -n lustre-ldap
+ slapd=/etc/openldap/slapd.conf
+ if grep -q slapd-lustre $slapd; then
+ tmp=/tmp/lustre-ldap.$$
+ sed "/slapd-lustre/d" $slapd >> $tmp
+ cp $tmp $slapd
+ rm $tmp
+ fi
+# end of post
+##############################################
+
--- /dev/null
+$Id: bproc-patch-2.4.20,v 1.1.8.1 2003/09/17 11:24:56 mfrey Exp $
+
+Index: linux/fs/exec.c
+===================================================================
+--- linux.orig/fs/exec.c 2003-09-03 17:52:00.000000000 -0400
++++ linux/fs/exec.c 2003-09-03 17:52:04.000000000 -0400
+@@ -38,6 +38,7 @@
+ #include <linux/utsname.h>
+ #define __NO_VERSION__
+ #include <linux/module.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+@@ -953,9 +954,11 @@
+ xa_call_actions (XA_EXEC, XA_KOE, NULL);
+
+ retval = search_binary_handler(&bprm,regs);
+- if (retval >= 0)
++ if (retval >= 0) {
+ /* execve success */
++ bproc_hook_im(do_execve,());
+ return retval;
++ }
+
+ out:
+ /* Something went wrong, return the inode and free the argument pages*/
+Index: linux/fs/binfmt_script.c
+===================================================================
+--- linux.orig/fs/binfmt_script.c 2002-08-02 20:39:45.000000000 -0400
++++ linux/fs/binfmt_script.c 2003-09-03 17:52:04.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/file.h>
+ #include <linux/smp_lock.h>
++#include <linux/bproc.h>
+
+ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+ {
+@@ -67,7 +68,7 @@
+ * user environment and arguments are stored.
+ */
+ remove_arg_zero(bprm);
+- retval = copy_strings_kernel(1, &bprm->filename, bprm);
++ retval = copy_strings_kernel(1,bproc_hook_v(&bprm->filename,load_script,(&bprm->filename)), bprm);
+ if (retval < 0) return retval;
+ bprm->argc++;
+ if (i_arg) {
+Index: linux/fs/binfmt_elf.c
+===================================================================
+--- linux.orig/fs/binfmt_elf.c 2002-08-02 20:39:45.000000000 -0400
++++ linux/fs/binfmt_elf.c 2003-09-03 17:52:04.000000000 -0400
+@@ -73,7 +73,7 @@
+ #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))
+ #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))
+
+-static struct linux_binfmt elf_format = {
++struct linux_binfmt elf_format = {
+ NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
+ };
+
+Index: linux/fs/proc/base.c
+===================================================================
+--- linux.orig/fs/proc/base.c 2003-09-03 17:52:00.000000000 -0400
++++ linux/fs/proc/base.c 2003-09-03 17:52:04.000000000 -0400
+@@ -25,6 +25,7 @@
+ #include <linux/string.h>
+ #include <linux/seq_file.h>
+ #include <linux/namespace.h>
++#include <linux/bproc.h>
+
+ /*
+ * For hysterical raisins we keep the same inumbers as in the old procfs.
+@@ -304,6 +305,7 @@
+ if (!(page = __get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+
++ if (bproc_isghost(task)) bproc_hook(refresh_status,(task));
+ length = inode->u.proc_i.op.proc_read(task, (char*)page);
+
+ if (length < 0) {
+@@ -976,14 +978,14 @@
+ static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
+ {
+ char tmp[30];
+- sprintf(tmp, "%d", current->pid);
++ sprintf(tmp, "%d", bproc_hook_imv(current->pid,proc3,()));
+ return vfs_readlink(dentry,buffer,buflen,tmp);
+ }
+
+ static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+ char tmp[30];
+- sprintf(tmp, "%d", current->pid);
++ sprintf(tmp, "%d", bproc_hook_imv(current->pid,proc3,()));
+ return vfs_follow_link(nd,tmp);
+ }
+
+@@ -1031,6 +1033,7 @@
+ goto out;
+ }
+
++ pid = bproc_hook_imv(pid,proc2,(pid));
+ read_lock(&tasklist_lock);
+ task = find_task_by_pid(pid);
+ if (task)
+@@ -1082,7 +1085,7 @@
+ index--;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+- int pid = p->pid;
++ int pid = bproc_hook_imv(p->pid,proc1,(p));
+ if (!pid)
+ continue;
+ if (--index >= 0)
+Index: linux/fs/proc/array.c
+===================================================================
+--- linux.orig/fs/proc/array.c 2002-08-02 20:39:45.000000000 -0400
++++ linux/fs/proc/array.c 2003-09-03 17:52:04.000000000 -0400
+@@ -70,6 +70,7 @@
+ #include <linux/smp.h>
+ #include <linux/signal.h>
+ #include <linux/highmem.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -130,7 +131,8 @@
+
+ static inline const char * get_task_state(struct task_struct *tsk)
+ {
+- unsigned int state = tsk->state & (TASK_RUNNING |
++ unsigned int state = (bproc_hook_v(tsk->state,get_task_state,(tsk)))
++ & (TASK_RUNNING |
+ TASK_INTERRUPTIBLE |
+ TASK_UNINTERRUPTIBLE |
+ TASK_ZOMBIE |
+@@ -158,7 +160,8 @@
+ "Uid:\t%d\t%d\t%d\t%d\n"
+ "Gid:\t%d\t%d\t%d\t%d\n",
+ get_task_state(p), p->tgid,
+- p->pid, p->pid ? p->p_opptr->pid : 0, 0,
++ bproc_hook_imv(p->pid, proc_pid, (p)),
++ bproc_hook_imv(p->p_opptr->pid, proc_ppid, (p)), 0,
+ p->uid, p->euid, p->suid, p->fsuid,
+ p->gid, p->egid, p->sgid, p->fsgid);
+ read_unlock(&tasklist_lock);
+@@ -305,7 +308,7 @@
+ sigset_t sigign, sigcatch;
+ char state;
+ int res;
+- pid_t ppid;
++ pid_t pid, ppid;
+ struct mm_struct *mm;
+
+ state = *get_task_state(task);
+@@ -343,12 +346,14 @@
+ nice = task->nice;
+
+ read_lock(&tasklist_lock);
+- ppid = task->pid ? task->p_opptr->pid : 0;
++ pid = bproc_hook_imv(task->pid, proc_pid, (task)),
++ ppid = bproc_hook_imv(task->pid ? task->p_opptr->pid : 0,
++ proc_ppid, (task));
+ read_unlock(&tasklist_lock);
+ res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
+ %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
+ %lu %lu %lu %lu %lu %lu %lu %lu %d %d\n",
+- task->pid,
++ pid,
+ task->comm,
+ state,
+ ppid,
+Index: linux/kernel/timer.c
+===================================================================
+--- linux.orig/kernel/timer.c 2003-09-03 17:51:01.000000000 -0400
++++ linux/kernel/timer.c 2003-09-03 17:52:04.000000000 -0400
+@@ -22,6 +22,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/kernel_stat.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+
+@@ -754,7 +755,7 @@
+ */
+ asmlinkage long sys_getpid(void)
+ {
+- return current->tgid;
++ return bproc_hook_imv(current->tgid, sys_getpid, ());
+ }
+
+ /*
+@@ -788,7 +789,7 @@
+
+ parent = me->p_opptr;
+ for (;;) {
+- pid = parent->pid;
++ pid = bproc_hook_imv(parent->pid,sys_getppid,(parent));
+ #if CONFIG_SMP
+ {
+ struct task_struct *old = parent;
+Index: linux/kernel/signal.c
+===================================================================
+--- linux.orig/kernel/signal.c 2003-09-03 17:51:01.000000000 -0400
++++ linux/kernel/signal.c 2003-09-03 17:52:04.000000000 -0400
+@@ -16,6 +16,8 @@
+
+ #include <asm/uaccess.h>
+
++#include <linux/bproc.h>
++
+ /*
+ * SLAB caches for signal bits.
+ */
+@@ -548,6 +550,9 @@
+ if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig))
+ goto out;
+
++ if (bproc_hook_v(0, send_sig_info, (sig, info, t)))
++ goto out;
++
+ ret = deliver_signal(sig, info, t);
+ out:
+ spin_unlock_irqrestore(&t->sigmask_lock, flags);
+@@ -590,6 +595,9 @@
+ kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
+ {
+ int retval = -EINVAL;
++
++ if (bproc_hook_imv(0,kill_pg_info, (sig, info, &pgrp, &retval)) == 1)
++ return retval;
+ if (pgrp > 0) {
+ struct task_struct *p;
+
+@@ -617,6 +625,7 @@
+ kill_sl_info(int sig, struct siginfo *info, pid_t sess)
+ {
+ int retval = -EINVAL;
++ /* XXX bproc: Need ways to deal with session leaders...*/
+ if (sess > 0) {
+ struct task_struct *p;
+
+@@ -640,6 +649,9 @@
+ int error;
+ struct task_struct *p;
+
++ if (bproc_hook_imv(0, kill_proc_info,(sig, info, &pid, &error)) == 1)
++ return error;
++
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ error = -ESRCH;
+@@ -684,6 +696,7 @@
+ read_unlock(&tasklist_lock);
+ return count ? retval : -ESRCH;
+ } else if (pid < 0) {
++ /* XXX pid masq - do PG stuff. */
+ return kill_pg_info(sig, info, -pid);
+ } else {
+ return kill_proc_info(sig, info, pid);
+@@ -815,6 +828,7 @@
+ EXPORT_SYMBOL(recalc_sigpending);
+ EXPORT_SYMBOL(send_sig);
+ EXPORT_SYMBOL(send_sig_info);
++EXPORT_SYMBOL(kill_something_info);
+ EXPORT_SYMBOL(block_all_signals);
+ EXPORT_SYMBOL(unblock_all_signals);
+
+Index: linux/kernel/sched.c
+===================================================================
+--- linux.orig/kernel/sched.c 2003-09-03 17:51:05.000000000 -0400
++++ linux/kernel/sched.c 2003-09-03 17:52:04.000000000 -0400
+@@ -30,6 +30,7 @@
+ #include <linux/dump.h>
+ #include <linux/prefetch.h>
+ #include <linux/compiler.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/mmu_context.h>
+@@ -370,6 +371,8 @@
+
+ inline int wake_up_process(struct task_struct * p)
+ {
++ if (p->state == TASK_STOPPED && bproc_ismasq(p))
++ bproc_hook(wake_up_process, (p));
+ return try_to_wake_up(p, 0);
+ }
+
+Index: linux/kernel/ksyms.c
+===================================================================
+--- linux.orig/kernel/ksyms.c 2003-09-03 17:52:02.000000000 -0400
++++ linux/kernel/ksyms.c 2003-09-03 17:52:04.000000000 -0400
+@@ -68,6 +68,10 @@
+ extern void set_device_ro(kdev_t dev,int flag);
+
+ extern void *sys_call_table;
++extern struct task_struct *child_reaper;
++#if defined(CONFIG_BINFMT_ELF)
++extern struct linux_binfmt elf_format;
++#endif
+
+ extern struct timezone sys_tz;
+ extern int request_dma(unsigned int dmanr, char * deviceID);
+@@ -104,9 +108,17 @@
+ EXPORT_SYMBOL(do_munmap);
+ EXPORT_SYMBOL(do_brk);
+ EXPORT_SYMBOL(exit_mm);
++EXPORT_SYMBOL(do_exit);
+ EXPORT_SYMBOL(exit_files);
+ EXPORT_SYMBOL(exit_fs);
+ EXPORT_SYMBOL(exit_sighand);
++EXPORT_SYMBOL(is_orphaned_pgrp);
++EXPORT_SYMBOL(child_reaper);
++#if defined(CONFIG_BINFMT_ELF)
++EXPORT_SYMBOL(elf_format);
++#endif
++EXPORT_SYMBOL(alloc_uid);
++EXPORT_SYMBOL(free_uid);
+ EXPORT_SYMBOL(copy_fs_struct);
+ EXPORT_SYMBOL_GPL(make_pages_present);
+
+@@ -584,6 +596,7 @@
+ EXPORT_SYMBOL(read_ahead);
+ EXPORT_SYMBOL(get_hash_table);
+ EXPORT_SYMBOL(new_inode);
++EXPORT_SYMBOL(get_empty_inode);
+ EXPORT_SYMBOL(insert_inode_hash);
+ EXPORT_SYMBOL(remove_inode_hash);
+ EXPORT_SYMBOL(buffer_insert_inode_queue);
+Index: linux/kernel/fork.c
+===================================================================
+--- linux.orig/kernel/fork.c 2003-09-03 17:52:00.000000000 -0400
++++ linux/kernel/fork.c 2003-09-03 17:52:04.000000000 -0400
+@@ -23,6 +23,8 @@
+ #include <linux/personality.h>
+ #include <linux/compiler.h>
+
++#include <linux/bproc.h>
++
+ #include <asm/pgtable.h>
+ #include <asm/pgalloc.h>
+ #include <asm/uaccess.h>
+@@ -413,6 +415,7 @@
+
+ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
+ {
++ if (!current->fs) return 0;
+ if (clone_flags & CLONE_FS) {
+ atomic_inc(¤t->fs->count);
+ return 0;
+@@ -781,7 +784,8 @@
+ *
+ * Let it rip!
+ */
+- retval = p->pid;
++ if ((retval = bproc_hook_v(p->pid, do_fork, (p, clone_flags))) < 0)
++ goto bad_fork_cleanup_mm;
+ p->tgid = retval;
+ INIT_LIST_HEAD(&p->thread_group);
+
+@@ -805,6 +809,7 @@
+ SET_LINKS(p);
+ hash_pid(p);
+ nr_threads++;
++ bproc_hook(do_fork_2, (p));
+ write_unlock_irq(&tasklist_lock);
+
+ if (p->ptrace & PT_PTRACED)
+@@ -816,6 +821,7 @@
+ wait_for_completion(&vfork);
+
+ fork_out:
++ bproc_clear_kcall();
+ return retval;
+
+ bad_fork_cleanup_namespace:
+Index: linux/kernel/exit.c
+===================================================================
+--- linux.orig/kernel/exit.c 2003-09-03 17:52:00.000000000 -0400
++++ linux/kernel/exit.c 2003-09-03 17:52:04.000000000 -0400
+@@ -22,6 +22,8 @@
+ #include <asm/pgtable.h>
+ #include <asm/mmu_context.h>
+
++#include <linux/bproc.h>
++
+ extern void sem_exit (void);
+ extern struct task_struct *child_reaper;
+
+@@ -47,6 +49,7 @@
+ }
+ task_unlock(p);
+ #endif
++ bproc_hook(release,(p));
+ atomic_dec(&p->user->processes);
+ free_uid(p->user);
+ unhash_process(p);
+@@ -130,7 +133,8 @@
+
+ int is_orphaned_pgrp(int pgrp)
+ {
+- return will_become_orphaned_pgrp(pgrp, 0);
++ return bproc_hook_imv(will_become_orphaned_pgrp(pgrp, 0),
++ is_orphaned_pgrp,(pgrp));
+ }
+
+ static inline int has_stopped_jobs(int pgrp)
+@@ -170,7 +174,7 @@
+ p->self_exec_id++;
+
+ /* Make sure we're not reparenting to ourselves */
+- p->p_opptr = child_reaper;
++ p->p_opptr = bproc_hook_v(child_reaper, child_reaper, (p));
+
+ if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
+ }
+@@ -450,6 +454,7 @@
+ #endif
+ __exit_mm(tsk);
+
++ bproc_hook(do_exit, (tsk,code));
+ lock_kernel();
+ sem_exit();
+ __exit_files(tsk);
+@@ -501,6 +506,7 @@
+ asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)
+ {
+ int flag, retval;
++ pid_t orig_pid = pid;
+ DECLARE_WAITQUEUE(wait, current);
+ struct task_struct *tsk;
+
+@@ -512,6 +518,9 @@
+ flag = 0;
+ current->state = TASK_INTERRUPTIBLE;
+ read_lock(&tasklist_lock);
++ pid = orig_pid;
++ if (bproc_hook_imv(0, sys_wait4_1, (&pid, stat_addr, options, ru, &retval)))
++ goto end_wait4; /* handler will unlock tasklist_lock */
+ tsk = current;
+ do {
+ struct task_struct *p;
+@@ -535,7 +544,7 @@
+ && !(options & __WALL))
+ continue;
+ flag = 1;
+- switch (p->state) {
++ switch (bproc_hook_v(p->state,sys_wait4_2,(p))) {
+ case TASK_STOPPED:
+ if (!p->exit_code)
+ continue;
+@@ -547,7 +556,7 @@
+ retval = put_user((p->exit_code << 8) | 0x7f, stat_addr);
+ if (!retval) {
+ p->exit_code = 0;
+- retval = p->pid;
++ retval = bproc_hook_imv(p->pid, sys_wait4_3, (p));
+ }
+ goto end_wait4;
+ case TASK_ZOMBIE:
+@@ -559,7 +568,7 @@
+ retval = put_user(p->exit_code, stat_addr);
+ if (retval)
+ goto end_wait4;
+- retval = p->pid;
++ retval = bproc_hook_imv(p->pid, sys_wait4_3, (p));
+ if (p->p_opptr != p->p_pptr) {
+ write_lock_irq(&tasklist_lock);
+ REMOVE_LINKS(p);
+@@ -569,6 +578,7 @@
+ write_unlock_irq(&tasklist_lock);
+ } else
+ release_task(p);
++ bproc_hook_im(sys_wait4_4,(retval, options));
+ goto end_wait4;
+ default:
+ continue;
+@@ -593,6 +603,7 @@
+ end_wait4:
+ current->state = TASK_RUNNING;
+ remove_wait_queue(¤t->wait_chldexit,&wait);
++ bproc_clear_kcall();
+ return retval;
+ }
+
+Index: linux/kernel/sys.c
+===================================================================
+--- linux.orig/kernel/sys.c 2003-09-03 17:51:05.000000000 -0400
++++ linux/kernel/sys.c 2003-09-03 17:52:04.000000000 -0400
+@@ -21,6 +21,8 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+
++#include <linux/bproc.h>
++
+ /*
+ * 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
+@@ -448,6 +450,7 @@
+ current->fsgid = new_egid;
+ current->egid = new_egid;
+ current->gid = new_rgid;
++ bproc_hook_im(set_creds, ());
+ return 0;
+ }
+
+@@ -480,6 +483,7 @@
+ }
+ else
+ return -EPERM;
++ bproc_hook_im(set_creds, ());
+ return 0;
+ }
+
+@@ -614,6 +618,7 @@
+ cap_emulate_setxuid(old_ruid, old_euid, old_suid);
+ }
+
++ bproc_hook_im(set_creds, ());
+ return 0;
+ }
+
+@@ -658,6 +663,8 @@
+ cap_emulate_setxuid(old_ruid, old_euid, old_suid);
+ }
+
++ bproc_hook_im(set_creds, ());
++ bproc_hook_im(set_creds, ());
+ return 0;
+ }
+
+@@ -746,6 +753,7 @@
+ current->gid = rgid;
+ if (sgid != (gid_t) -1)
+ current->sgid = sgid;
++ bproc_hook_im(set_creds, ());
+ return 0;
+ }
+
+@@ -803,6 +811,7 @@
+ }
+ }
+
++ if (current->fsuid != old_fsuid) bproc_hook_im(set_creds, ());
+ return old_fsuid;
+ }
+
+@@ -825,6 +834,8 @@
+ }
+ current->fsgid = gid;
+ }
++
++ if (current->fsgid != old_fsgid) bproc_hook_im(set_creds, ());
+ return old_fsgid;
+ }
+
+@@ -860,6 +871,8 @@
+ struct task_struct * p;
+ int err = -EINVAL;
+
++ bproc_hook_imr(sys_setpgid1, (pid, pgid));
++
+ if (!pid)
+ pid = current->pid;
+ if (!pgid)
+@@ -901,6 +914,7 @@
+
+ ok_pgid:
+ p->pgrp = pgid;
++ if (bproc_isghost(p)) bproc_hook(sys_setpgid2, (p));
+ err = 0;
+ out:
+ /* All paths lead to here, thus we are safe. -DaveM */
+@@ -910,6 +924,7 @@
+
+ asmlinkage long sys_getpgid(pid_t pid)
+ {
++ bproc_hook_imr(sys_getpgid,(pid));
+ if (!pid) {
+ return current->pgrp;
+ } else {
+@@ -930,23 +945,25 @@
+ asmlinkage long sys_getpgrp(void)
+ {
+ /* SMP - assuming writes are word atomic this is fine */
+- return current->pgrp;
++ return bproc_hook_imv(current->pgrp,sys_getpgrp,());
+ }
+
+ asmlinkage long sys_getsid(pid_t pid)
+ {
+ if (!pid) {
+- return current->session;
++ return bproc_hook_imv(current->session,sys_getsid1,());
+ } else {
+ int retval;
+ struct task_struct *p;
++ if (bproc_hook_imv(0,sys_getsid2, (&pid, &retval))==1)
++ return retval;
+
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+
+ retval = -ESRCH;
+ if(p)
+- retval = p->session;
++ retval = bproc_hook_imv(p->session,sys_getsid3,(p));
+ read_unlock(&tasklist_lock);
+ return retval;
+ }
+@@ -957,6 +974,8 @@
+ struct task_struct * p;
+ int err = -EPERM;
+
++ bproc_hook_imr(sys_setsid,());
++
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pgrp == current->pid)
+@@ -1011,6 +1030,7 @@
+ if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
+ return -EFAULT;
+ current->ngroups = gidsetsize;
++ bproc_hook_im(set_creds, ());
+ return 0;
+ }
+
+Index: linux/kernel/ptrace.c
+===================================================================
+--- linux.orig/kernel/ptrace.c 2003-09-03 17:51:04.000000000 -0400
++++ linux/kernel/ptrace.c 2003-09-03 17:52:04.000000000 -0400
+@@ -12,6 +12,7 @@
+ #include <linux/mm.h>
+ #include <linux/highmem.h>
+ #include <linux/smp_lock.h>
++#include <linux/bproc.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/uaccess.h>
+@@ -25,8 +26,13 @@
+ if (!(child->ptrace & PT_PTRACED))
+ return -ESRCH;
+
+- if (child->p_pptr != current)
+- return -ESRCH;
++ if (child->p_pptr != current &&
++ !bproc_hook_v(0,ptrace_slave_call,
++ (PTRACE_DETACH, child, current->bproc.arg)))
++ return -ESRCH;
++
++ if (bproc_isghost(child))
++ return 0;
+
+ if (!kill) {
+ if (child->state != TASK_STOPPED)
+@@ -55,6 +61,7 @@
+
+ int ptrace_attach(struct task_struct *task)
+ {
++ long ret;
+ task_lock(task);
+ if (task->pid <= 1)
+ goto bad;
+@@ -83,16 +90,22 @@
+ task->ptrace |= PT_PTRACE_CAP;
+ task_unlock(task);
+
++ ret = 0;
+ write_lock_irq(&tasklist_lock);
+ if (task->p_pptr != current) {
++ if (bproc_isghost(current) && !bproc_isghost(task)) ret = 1;
+ REMOVE_LINKS(task);
+ task->p_pptr = current;
+ SET_LINKS(task);
+ }
++ if (bproc_ismasq(task))
++ bproc_hook(ptrace_attach, (task, current->bproc.arg, &ret));
+ write_unlock_irq(&tasklist_lock);
+-
+- send_sig(SIGSTOP, task, 1);
+- return 0;
++ if (bproc_isghost(task))
++ bproc_hook(ptraceg,(PTRACE_ATTACH, task, 0, 0, &ret, 0));
++ else
++ send_sig(SIGSTOP, task, 1);
++ return ret;
+
+ bad:
+ task_unlock(task);
+@@ -101,6 +114,7 @@
+
+ int ptrace_detach(struct task_struct *child, unsigned int data)
+ {
++ long ret = 0;
+ if ((unsigned long) data > _NSIG)
+ return -EIO;
+
+@@ -111,14 +125,19 @@
+ child->ptrace = 0;
+ child->exit_code = data;
+ write_lock_irq(&tasklist_lock);
++ if (bproc_isghost(current) && !bproc_isghost(child) &&
++ child->p_pptr != child->p_opptr)
++ ret = 1;
+ REMOVE_LINKS(child);
++ if (bproc_ismasq(child))
++ bproc_hook(ptrace_detach,(child,(long*)&ret));
+ child->p_pptr = child->p_opptr;
+ SET_LINKS(child);
+ write_unlock_irq(&tasklist_lock);
+
+ /* .. and wake it up. */
+ wake_up_process(child);
+- return 0;
++ return ret;
+ }
+
+ /*
+Index: linux/kernel/Makefile
+===================================================================
+--- linux.orig/kernel/Makefile 2003-09-03 17:51:06.000000000 -0400
++++ linux/kernel/Makefile 2003-09-03 17:52:04.000000000 -0400
+@@ -9,7 +9,7 @@
+
+ O_TARGET := kernel.o
+
+-export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
++export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o bproc_hook.o
+
+ obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
+ module.o exit.o itimer.o info.o time.o softirq.o resource.o \
+@@ -24,6 +24,7 @@
+ obj-$(CONFIG_MODULES) += ksyms.o
+ obj-$(CONFIG_PM) += pm.o
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
++obj-$(CONFIG_BPROC) += bproc_hook.o
+
+ ifneq ($(CONFIG_IA64),y)
+ # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
+Index: linux/kernel/bproc_hook.c
+===================================================================
+--- linux.orig/kernel/bproc_hook.c 2003-09-03 17:52:04.000000000 -0400
++++ linux/kernel/bproc_hook.c 2003-09-03 17:52:04.000000000 -0400
+@@ -0,0 +1,36 @@
++/*-------------------------------------------------------------------------
++ * bproc_hook.c: Beowulf distributed PID space (bproc) definitions
++ *
++ * Copyright (C) 2000 by Erik Hendriks <hendriks@scyld.com>
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * $Id: bproc-patch-2.4.20,v 1.1.8.1 2003/09/17 11:24:56 mfrey Exp $
++ *-----------------------------------------------------------------------*/
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/module.h>
++
++#define bprocdeclhook(ret,func,args) \
++ ret (* bproc_hook_ ## func ## _hook) args = 0;\
++ EXPORT_SYMBOL( bproc_hook_ ## func ## _hook )
++
++#include <linux/bproc.h>
++
++/*
++ * Local variables:
++ * c-basic-offset: 4
++ * End:
++ */
+Index: linux/include/linux/sched.h
+===================================================================
+--- linux.orig/include/linux/sched.h 2003-09-03 17:51:06.000000000 -0400
++++ linux/include/linux/sched.h 2003-09-03 17:52:04.000000000 -0400
+@@ -430,6 +430,14 @@
+
+ /* journalling filesystem info */
+ void *journal_info;
++
++/* bproc */
++ struct {
++ long flag;
++ long arg;
++ struct bproc_masq_proc_t *masq;
++ struct bproc_ghost_proc_t *ghost;
++ } bproc;
+ };
+
+ /*
+@@ -526,6 +534,7 @@
+ alloc_lock: SPIN_LOCK_UNLOCKED, \
+ exit_actions: NULL, \
+ journal_info: NULL, \
++ bproc: {0, 0, 0, 0} \
+ }
+
+
+Index: linux/include/linux/bproc.h
+===================================================================
+--- linux.orig/include/linux/bproc.h 2003-09-03 17:52:04.000000000 -0400
++++ linux/include/linux/bproc.h 2003-09-03 17:52:04.000000000 -0400
+@@ -0,0 +1,155 @@
++/*-------------------------------------------------------------------------
++ * bproc.h: Beowulf distributed PID space (bproc) definitions
++ *
++ * Copyright (C) 1999-2001 by Erik Hendriks <erik@hendriks.cx>
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * $Id: bproc-patch-2.4.20,v 1.1.8.1 2003/09/17 11:24:56 mfrey Exp $
++ *-----------------------------------------------------------------------*/
++#ifndef _LINUX_BPROC_H
++#define _LINUX_BPROC_H
++
++#include <linux/config.h>
++#include <linux/types.h>
++
++#ifdef CONFIG_BPROC
++
++#ifndef bprocdeclhook
++/* Function pointers for bproc hooks. */
++#define bprocdeclhook(ret,func,args) extern ret (* bproc_hook_ ## func ## _hook) args
++#endif
++
++struct bproc_ghost_proc_t;
++struct task_struct;
++struct rusage;
++struct siginfo;
++
++/*----- fs/exec.c -------------------------------------------------------*/
++bprocdeclhook(void, do_execve, (void));
++/*----- fs/binfmt_script.c ----------------------------------------------*/
++bprocdeclhook(char**,load_script, (char **));
++/*----- fs/proc/array.c ----------------------------------------------------*/
++bprocdeclhook(void, refresh_status, (struct task_struct *));
++bprocdeclhook(int, get_task_state, (struct task_struct *));
++bprocdeclhook(int, proc_pid, (struct task_struct *));
++bprocdeclhook(int, proc_ppid, (struct task_struct *));
++bprocdeclhook(int, proc1, (struct task_struct *));
++bprocdeclhook(int, proc2, (int));
++bprocdeclhook(int, proc3, (void));
++/*----- kernel/timer.c --------------------------------------------------*/
++bprocdeclhook(int, sys_getpid, (void));
++bprocdeclhook(int, sys_getppid, (struct task_struct *));
++/*----- kernel/sched.c --------------------------------------------------*/
++bprocdeclhook(void, wake_up_process, (struct task_struct *));
++/*----- kernel/exit.c ---------------------------------------------------*/
++bprocdeclhook(void, release, (struct task_struct *));
++bprocdeclhook(int, is_orphaned_pgrp,(int));
++bprocdeclhook(struct task_struct *,child_reaper,(struct task_struct *));
++bprocdeclhook(void, do_exit, (struct task_struct *, long code));
++bprocdeclhook(int, sys_wait4_1, (pid_t *, unsigned int *, int,
++ struct rusage *, int *));
++bprocdeclhook(long, sys_wait4_2, (struct task_struct *));
++bprocdeclhook(int, sys_wait4_3, (struct task_struct *));
++bprocdeclhook(void, sys_wait4_4, (pid_t, int options));
++/*----- kernel/fork.c ---------------------------------------------------*/
++bprocdeclhook(int, do_fork, (struct task_struct *, unsigned long));
++bprocdeclhook(void, do_fork_2, (struct task_struct *));
++/*----- kernel/signal.c -------------------------------------------------*/
++bprocdeclhook(int, send_sig_info, (int, struct siginfo *,
++ struct task_struct *));
++bprocdeclhook(int, kill_pg_info, (int, struct siginfo *, pid_t *, int *));
++bprocdeclhook(int, kill_proc_info, (int, struct siginfo *, pid_t *, int *));
++/*----- kernel/sys.c ----------------------------------------------------*/
++bprocdeclhook(int, sys_setpgid1, (pid_t, pid_t));
++bprocdeclhook(void, sys_setpgid2, (struct task_struct *p));
++bprocdeclhook(int, sys_getpgid, (pid_t pid));
++bprocdeclhook(int, sys_getpgrp, (void));
++bprocdeclhook(int, sys_getsid1, (void));
++bprocdeclhook(int, sys_getsid2, (pid_t *pid, int *error));
++bprocdeclhook(int, sys_getsid3, (struct task_struct *p));
++bprocdeclhook(int, sys_setsid, (void));
++bprocdeclhook(void, set_creds, (void));
++/*----- arch/???/kernel/ptrace.c,signal.c -------------------------------*/
++bprocdeclhook(void, stop_notify, (int));
++bprocdeclhook(int, ptracem, (long, long *, long, long,
++ long *, long *));
++bprocdeclhook(void, ptrace_attach, (struct task_struct *, long, long *));
++bprocdeclhook(void, ptraceg, (long, struct task_struct *, long,
++ long, long *, long *));
++bprocdeclhook(int, ptrace_slave_call,(long, struct task_struct *, long));
++bprocdeclhook(void, ptrace_detach, (struct task_struct *, long *));
++bprocdeclhook(int, sys_execve, (struct pt_regs *, char *,
++ char **, char **));
++
++/* Macro suffixes:
++ * (none) = execute this hook if it's present.
++ * im = if masq'ed
++ * nkc = no kernel call (kcall must be 0 to call hook)
++ * r = return the value of this hook
++ * v = hook returns a value.
++ */
++#define hookname(func) bproc_hook_ ## func ## _hook
++#define bproc_hook(func,args) do{if(hookname(func))hookname(func)args;}while(0)
++#define bproc_hook_im(func,args) do{if(hookname(func)&¤t->bproc.masq)hookname(func)args;}while(0)
++#define bproc_hook_imr(func,args) do{if(hookname(func)&¤t->bproc.masq)return hookname(func)args;}while(0)
++#define bproc_hook_v(defl,func,args) ( hookname(func) ?hookname(func)args:defl)
++#define bproc_hook_imv(defl,func,args) ((hookname(func)&¤t->bproc.masq)?hookname(func)args:defl)
++
++#define bproc_isghost(tsk) ((tsk)->bproc.ghost != 0)
++#define bproc_ismasq(tsk) ((tsk)->bproc.masq != 0)
++#define bproc_set_arg(x) do{current->bproc.arg=(x);}while(0)
++
++/* Kernel call weirdness... a kernel call is a call made from the
++ * kernel which we do not want to be subject to the usual rules for
++ * PID masquerading. This is mostly used for drivers which create and
++ * possibly wait for kernel threads which they create. These
++ * functions are called from the relevant places within the kernel
++ * (like within kernel_thread) to set a flag so that things will be
++ * handled correctly later on. */
++static inline void bproc_no_kcall(void) {
++ current->bproc.flag = (current->bproc.flag & ~3) | 2;
++}
++static inline void bproc_clear_kcall(void) {
++ current->bproc.flag &= ~3;
++}
++static inline void bproc_kcall(void) {
++ if (current->bproc.flag & 2)
++ bproc_clear_kcall();
++ else
++ current->bproc.flag |= 1; /* set kernel call flag */
++}
++
++#else
++/* Stubs for when hooks are not compiled in */
++#define bproc_hook(func,args) do{}while(0)
++#define bproc_hook_im(func,args) do{}while(0)
++#define bproc_hook_imr(func,args) do{}while(0)
++#define bproc_hook_v(defl,func,args) (defl)
++#define bproc_hook_imv(defl,func,args) (defl)
++#define bproc_isghost(tsk) (0)
++#define bproc_ismasq(tsk) (0)
++#define bproc_set_arg(x) do{}while(0)
++#define bproc_no_kcall() do{}while(0)
++#define bproc_clear_kcall() do{}while(0)
++#define bproc_kcall() do{}while(0)
++#endif
++#endif
++
++/*
++ * Local variables:
++ * c-basic-offset: 4
++ * End:
++ */
+Index: linux/include/asm-i386/unistd.h
+===================================================================
+--- linux.orig/include/asm-i386/unistd.h 2002-11-28 18:53:15.000000000 -0500
++++ linux/include/asm-i386/unistd.h 2003-09-03 17:52:04.000000000 -0400
+@@ -349,6 +349,7 @@
+
+ #ifdef __KERNEL_SYSCALLS__
+
++#include <linux/bproc.h>
+ /*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+@@ -373,7 +374,16 @@
+ static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+ static inline _syscall1(int,close,int,fd)
+ static inline _syscall1(int,_exit,int,exitcode)
+-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
++static inline pid_t waitpid(pid_t pid, int *wait_stat, int options) {
++ long __res;
++ bproc_kcall();
++ __asm__ volatile ("int $0x80"
++ : "=a" (__res)
++ : "0" (__NR_waitpid),"b" ((long)(pid)),"c" ((long)(wait_stat)),
++ "d" ((long)(options)));
++ __syscall_return(pid_t,__res);
++}
++
+ static inline _syscall1(int,delete_module,const char *,name)
+
+ static inline pid_t wait(int * wait_stat)
+Index: linux/include/asm-alpha/unistd.h
+===================================================================
+--- linux.orig/include/asm-alpha/unistd.h 2002-08-02 20:39:45.000000000 -0400
++++ linux/include/asm-alpha/unistd.h 2003-09-03 17:52:04.000000000 -0400
+@@ -519,6 +519,7 @@
+
+ #include <linux/string.h>
+ #include <linux/signal.h>
++#include <linux/bproc.h>
+
+ extern void sys_idle(void);
+ static inline void idle(void)
+@@ -591,11 +592,13 @@
+
+ static inline pid_t waitpid(int pid, int * wait_stat, int flags)
+ {
++ bproc_kcall();
+ return sys_wait4(pid, wait_stat, flags, NULL);
+ }
+
+ static inline pid_t wait(int * wait_stat)
+ {
++ bproc_kcall();
+ return waitpid(-1,wait_stat,0);
+ }
+
+Index: linux/net/socket.c
+===================================================================
+--- linux.orig/net/socket.c 2003-09-03 17:51:05.000000000 -0400
++++ linux/net/socket.c 2003-09-03 17:52:04.000000000 -0400
+@@ -111,7 +111,7 @@
+ * in the operation structures but are done directly via the socketcall() multiplexor.
+ */
+
+-static struct file_operations socket_file_ops = {
++struct file_operations socket_file_ops = {
+ llseek: no_llseek,
+ read: sock_read,
+ write: sock_write,
+@@ -298,13 +298,13 @@
+ return sb;
+ }
+
+-static struct vfsmount *sock_mnt;
++struct vfsmount *sock_mnt;
+ static DECLARE_FSTYPE(sock_fs_type, "sockfs", sockfs_read_super, FS_NOMOUNT);
+ static int sockfs_delete_dentry(struct dentry *dentry)
+ {
+ return 1;
+ }
+-static struct dentry_operations sockfs_dentry_operations = {
++struct dentry_operations sockfs_dentry_operations = {
+ d_delete: sockfs_delete_dentry,
+ };
+
+Index: linux/net/netsyms.c
+===================================================================
+--- linux.orig/net/netsyms.c 2003-09-03 17:52:04.000000000 -0400
++++ linux/net/netsyms.c 2003-09-03 17:52:04.000000000 -0400
+@@ -599,4 +599,11 @@
+ EXPORT_SYMBOL(wireless_send_event);
+ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
+
++extern struct vfsmount *sock_mnt;
++extern struct dentry_operations sockfs_dentry_operations;
++extern struct file_operations socket_file_ops;
++EXPORT_SYMBOL(sock_mnt);
++EXPORT_SYMBOL(sockfs_dentry_operations);
++EXPORT_SYMBOL(socket_file_ops);
++
+ #endif /* CONFIG_NET */
+Index: linux/arch/i386/config.in
+===================================================================
+--- linux.orig/arch/i386/config.in 2003-09-03 17:51:06.000000000 -0400
++++ linux/arch/i386/config.in 2003-09-03 17:52:04.000000000 -0400
+@@ -285,6 +285,7 @@
+
+ bool 'System V IPC' CONFIG_SYSVIPC
+ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
++bool 'Beowulf Distributed Process Space' CONFIG_BPROC
+ bool 'Sysctl support' CONFIG_SYSCTL
+ if [ "$CONFIG_PROC_FS" = "y" ]; then
+ choice 'Kernel core (/proc/kcore) format' \
+Index: linux/arch/i386/kernel/signal.c
+===================================================================
+--- linux.orig/arch/i386/kernel/signal.c 2002-08-02 20:39:42.000000000 -0400
++++ linux/arch/i386/kernel/signal.c 2003-09-03 17:52:04.000000000 -0400
+@@ -20,6 +20,7 @@
+ #include <linux/stddef.h>
+ #include <linux/tty.h>
+ #include <linux/personality.h>
++#include <linux/bproc.h>
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/i387.h>
+@@ -612,6 +613,7 @@
+ /* Let the debugger run. */
+ current->exit_code = signr;
+ current->state = TASK_STOPPED;
++ bproc_hook_im(stop_notify,(signr));
+ notify_parent(current, SIGCHLD);
+ schedule();
+
+@@ -670,6 +672,7 @@
+ struct signal_struct *sig;
+ current->state = TASK_STOPPED;
+ current->exit_code = signr;
++ bproc_hook_im(stop_notify,(signr));
+ sig = current->p_pptr->sig;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ notify_parent(current, SIGCHLD);
+Index: linux/arch/i386/kernel/ptrace.c
+===================================================================
+--- linux.orig/arch/i386/kernel/ptrace.c 2002-08-02 20:39:42.000000000 -0400
++++ linux/arch/i386/kernel/ptrace.c 2003-09-03 17:52:04.000000000 -0400
+@@ -21,6 +21,8 @@
+ #include <asm/i387.h>
+ #include <asm/debugreg.h>
+
++#include <linux/bproc.h>
++
+ /*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+@@ -152,6 +154,15 @@
+ struct task_struct *child;
+ struct user * dummy = NULL;
+ int i, ret;
++ long orig_pid;
++
++ orig_pid = pid;
++ retry_ptrace:
++ pid = orig_pid;
++ if (bproc_hook_imv(0, ptracem, (request,&pid,addr,data,(long*)&ret,0))) {
++ if (ret == -ELOOP) goto retry_ptrace;
++ return ret;
++ }
+
+ lock_kernel();
+ ret = -EPERM;
+@@ -178,14 +189,21 @@
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
++ bproc_set_arg(addr);
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
++ bproc_set_arg(request == PTRACE_DETACH ? addr : 0);
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
++ if (bproc_isghost(child)) {
++ bproc_hook(ptraceg, (request,child,addr,data,(long*)&ret,0));
++ goto out_tsk;
++ }
++
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+@@ -427,6 +445,7 @@
+ free_task_struct(child);
+ out:
+ unlock_kernel();
++ if (ret == -ELOOP) goto retry_ptrace;
+ return ret;
+ }
+
+@@ -440,6 +459,7 @@
+ current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0);
+ current->state = TASK_STOPPED;
++ bproc_hook_im(stop_notify,(SIGTRAP));
+ notify_parent(current, SIGCHLD);
+ schedule();
+ /*
+Index: linux/arch/i386/kernel/process.c
+===================================================================
+--- linux.orig/arch/i386/kernel/process.c 2003-09-03 17:51:02.000000000 -0400
++++ linux/arch/i386/kernel/process.c 2003-09-03 17:52:04.000000000 -0400
+@@ -33,6 +33,7 @@
+ #include <linux/reboot.h>
+ #include <linux/init.h>
+ #include <linux/mc146818rtc.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -489,6 +490,7 @@
+ {
+ long retval, d0;
+
++ bproc_kcall();
+ __asm__ __volatile__(
+ "movl %%esp,%%esi\n\t"
+ "int $0x80\n\t" /* Linux/i386 system call */
+@@ -789,6 +791,11 @@
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+ out:
++ if (error == -ENOENT)
++ error = bproc_hook_imv(error, sys_execve,
++ (®s,(char *)regs.ebx,
++ (char **)regs.ecx, (char **)regs.edx));
++
+ return error;
+ }
+
+Index: linux/arch/i386/kernel/i386_ksyms.c
+===================================================================
+--- linux.orig/arch/i386/kernel/i386_ksyms.c 2003-09-03 17:51:04.000000000 -0400
++++ linux/arch/i386/kernel/i386_ksyms.c 2003-09-03 17:52:04.000000000 -0400
+@@ -107,6 +107,11 @@
+ EXPORT_SYMBOL(__generic_copy_to_user);
+ EXPORT_SYMBOL(strnlen_user);
+
++asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
++EXPORT_SYMBOL_NOVERS(ret_from_sys_call);
++asmlinkage void syscall_trace(void);
++EXPORT_SYMBOL(syscall_trace);
++
+ EXPORT_SYMBOL(pci_alloc_consistent);
+ EXPORT_SYMBOL(pci_free_consistent);
+
+Index: linux/arch/alpha/config.in
+===================================================================
+--- linux.orig/arch/alpha/config.in 2003-09-03 17:51:04.000000000 -0400
++++ linux/arch/alpha/config.in 2003-09-03 17:52:04.000000000 -0400
+@@ -271,6 +271,7 @@
+
+ bool 'Networking support' CONFIG_NET
+ bool 'System V IPC' CONFIG_SYSVIPC
++bool 'Beowulf Distributed Process Space' CONFIG_BPROC
+ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+ bool 'Sysctl support' CONFIG_SYSCTL
+ if [ "$CONFIG_PROC_FS" = "y" ]; then
+Index: linux/arch/alpha/kernel/signal.c
+===================================================================
+--- linux.orig/arch/alpha/kernel/signal.c 2002-08-02 20:39:42.000000000 -0400
++++ linux/arch/alpha/kernel/signal.c 2003-09-03 17:52:04.000000000 -0400
+@@ -23,6 +23,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/sigcontext.h>
+ #include <asm/ucontext.h>
++#include <linux/bproc.h>
+
+ #include "proto.h"
+
+@@ -643,6 +644,7 @@
+ /* Let the debugger run. */
+ current->exit_code = signr;
+ current->state = TASK_STOPPED;
++ bproc_hook_im(stop_notify,(signr));
+ notify_parent(current, SIGCHLD);
+ schedule();
+ single_stepping |= ptrace_cancel_bpt(current);
+@@ -701,6 +703,7 @@
+ case SIGSTOP:
+ current->state = TASK_STOPPED;
+ current->exit_code = signr;
++ bproc_hook_im(stop_notify,(signr));
+ if (!(current->p_pptr->sig->action[SIGCHLD-1]
+ .sa.sa_flags & SA_NOCLDSTOP))
+ notify_parent(current, SIGCHLD);
+Index: linux/arch/alpha/kernel/osf_sys.c
+===================================================================
+--- linux.orig/arch/alpha/kernel/osf_sys.c 2002-08-02 20:39:42.000000000 -0400
++++ linux/arch/alpha/kernel/osf_sys.c 2003-09-03 17:52:04.000000000 -0400
+@@ -33,6 +33,7 @@
+ #include <linux/file.h>
+ #include <linux/types.h>
+ #include <linux/ipc.h>
++#include <linux/bproc.h>
+
+ #include <asm/fpu.h>
+ #include <asm/io.h>
+@@ -219,8 +220,8 @@
+ * isn't actually going to matter, as if the parent happens
+ * to change we can happily return either of the pids.
+ */
+- (®s)->r20 = tsk->p_opptr->tgid;
+- return tsk->tgid;
++ (®s)->r20 = bproc_hook_imv(tsk->p_opptr->tgid,sys_getppid,(tsk->p_opptr));
++ return bproc_hook_imv(tsk->tgid,sys_getpid,());
+ }
+
+ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
+Index: linux/arch/alpha/kernel/entry.S
+===================================================================
+--- linux.orig/arch/alpha/kernel/entry.S 2003-09-03 17:52:01.000000000 -0400
++++ linux/arch/alpha/kernel/entry.S 2003-09-03 17:52:04.000000000 -0400
+@@ -212,8 +212,10 @@
+ * stack buildup, as we can't do system calls from kernel space.
+ */
+ .align 3
++.globl kernel_clone
+ .ent kernel_clone
+ kernel_clone:
++ ldgp $29,0($27) /* we can be called from a module */
+ .frame $30, 0, $26
+ .prologue 0
+ subq $30,6*8,$30
+@@ -230,6 +232,23 @@
+ br ret_from_sys_call
+ .end kernel_clone
+
++.align 3
++.globl ret_to_user_space
++.ent ret_to_user_space
++ret_to_user_space:
++ ldgp $29, 0($27) /* We can jump here from a module */
++ bsr $1, undo_switch_stack
++ lda $1, 8($31) /* Set ps = 8 */
++ stq $1, 0xB8($30)
++
++ /* This tidbit ripped from entSys. Is this appropriate here ? */
++ blt $0,syscall_error /* the call failed */
++ stq $0,0($30)
++ stq $31,72($30) /* a3=0 => no error */
++
++ br ret_from_sys_call
++.end ret_to_user_space
++
+ /*
+ * arch_kernel_thread(fn, arg, clone_flags)
+ */
+@@ -240,19 +259,24 @@
+ ldgp $29,0($27) /* we can be called from a module */
+ .frame $30, 4*8, $26
+ subq $30,4*8,$30
++ stq $11,24($30)
+ stq $10,16($30)
+ stq $9,8($30)
+- lda $0,CLONE_VM
+ stq $26,0($30)
+ .prologue 1
+ mov $16,$9 /* save fn */
+ mov $17,$10 /* save arg */
+- or $18,$0,$16 /* shuffle flags to front; add CLONE_VM. */
+- bsr $26,kernel_clone
++ mov $18,$11 /* save flags */
++ bsr $26,bproc_kcall_
++ lda $0,CLONE_VM
++ or $11,$0,$16 /* shuffle flags to front; add CLONE_VM. */
++ jsr $26,kernel_clone
++ ldgp $29,0($26)
+ bne $20,1f /* $20 is non-zero in child */
+ ldq $26,0($30)
+ ldq $9,8($30)
+ ldq $10,16($30)
++ ldq $11,24($30)
+ addq $30,4*8,$30
+ ret $31,($26),1
+ /* this is in child: look out as we don't have any stack here.. */
+@@ -290,6 +314,7 @@
+ .end __kernel_execve
+
+ .align 3
++.globl do_switch_stack
+ .ent do_switch_stack
+ do_switch_stack:
+ lda $30,-SWITCH_STACK_SIZE($30)
+@@ -339,6 +364,7 @@
+ .end do_switch_stack
+
+ .align 3
++.globl undo_switch_stack
+ .ent undo_switch_stack
+ undo_switch_stack:
+ ldq $9,0($30)
+@@ -1062,7 +1088,7 @@
+ .quad alpha_ni_syscall
+ .quad alpha_ni_syscall
+ .quad alpha_ni_syscall /* 290 */
+- .quad alpha_ni_syscall
++ .quad sys_ni_syscall /* bproc: please shut up... */
+ .quad alpha_ni_syscall
+ .quad alpha_ni_syscall
+ .quad alpha_ni_syscall
+Index: linux/arch/alpha/kernel/alpha_ksyms.c
+===================================================================
+--- linux.orig/arch/alpha/kernel/alpha_ksyms.c 2002-08-02 20:39:42.000000000 -0400
++++ linux/arch/alpha/kernel/alpha_ksyms.c 2003-09-03 17:52:04.000000000 -0400
+@@ -164,6 +164,17 @@
+ EXPORT_SYMBOL(sys_sync);
+ EXPORT_SYMBOL(sys_wait4);
+
++extern void kernel_clone(void);
++extern void ret_to_user_space(void);
++extern void do_switch_stack(void);
++extern void undo_switch_stack(void);
++asmlinkage void syscall_trace(void);
++EXPORT_SYMBOL_NOVERS(kernel_clone);
++EXPORT_SYMBOL_NOVERS(ret_to_user_space);
++EXPORT_SYMBOL_NOVERS(do_switch_stack);
++EXPORT_SYMBOL_NOVERS(undo_switch_stack);
++EXPORT_SYMBOL(syscall_trace);
++
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_tcpudp_magic);
+ EXPORT_SYMBOL(ip_compute_csum);
+Index: linux/arch/alpha/kernel/process.c
+===================================================================
+--- linux.orig/arch/alpha/kernel/process.c 2001-09-30 15:26:08.000000000 -0400
++++ linux/arch/alpha/kernel/process.c 2003-09-03 17:52:04.000000000 -0400
+@@ -30,6 +30,7 @@
+ #include <linux/reboot.h>
+ #include <linux/tty.h>
+ #include <linux/console.h>
++#include <linux/bproc.h>
+
+ #include <asm/reg.h>
+ #include <asm/uaccess.h>
+@@ -430,6 +431,9 @@
+ error = do_execve(filename, argv, envp, ®s);
+ putname(filename);
+ out:
++ if (error == -ENOENT)
++ error = bproc_hook_imv(error, sys_execve,
++ (®s,ufilename,argv,envp));
+ return error;
+ }
+
+@@ -465,3 +469,10 @@
+ }
+ return pc;
+ }
++
++/* This is usually inlined. It's packaged in a function here so that
++ * we can call it from ASM code on this architecture. */
++void bproc_kcall_(void)
++{
++ bproc_kcall();
++}
+Index: linux/arch/alpha/kernel/ptrace.c
+===================================================================
+--- linux.orig/arch/alpha/kernel/ptrace.c 2001-09-18 20:03:51.000000000 -0400
++++ linux/arch/alpha/kernel/ptrace.c 2003-09-03 17:52:04.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/user.h>
+ #include <linux/slab.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -248,7 +249,15 @@
+ int a4, int a5, struct pt_regs regs)
+ {
+ struct task_struct *child;
+- long ret;
++ long ret, orig_pid;
++
++ orig_pid = pid;
++ retry_ptrace:
++ pid = orig_pid;
++ if (bproc_hook_imv(0, ptracem, (request,&pid,addr,data,&ret,®s.r0))) {
++ if (ret == -ELOOP && regs.r0) goto retry_ptrace;
++ return ret;
++ }
+
+ lock_kernel();
+ DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
+@@ -274,6 +283,7 @@
+ if (!child)
+ goto out_notsk;
+ if (request == PTRACE_ATTACH) {
++ bproc_set_arg(addr);
+ ret = ptrace_attach(child);
+ goto out;
+ }
+@@ -282,15 +292,20 @@
+ DBG(DBG_MEM, ("child not traced\n"));
+ goto out;
+ }
++ if (child->p_pptr != current &&
++ !bproc_hook_v(0,ptrace_slave_call,(request,child,addr))) {
++ DBG(DBG_MEM, ("child not parent of this process\n"));
++ goto out;
++ }
++ if (bproc_isghost(child)) {
++ bproc_hook(ptraceg,(request,child,addr,data,&ret,®s.r0));
++ goto out;
++ }
+ if (child->state != TASK_STOPPED) {
+ DBG(DBG_MEM, ("child process not stopped\n"));
+ if (request != PTRACE_KILL)
+ goto out;
+ }
+- if (child->p_pptr != current) {
+- DBG(DBG_MEM, ("child not parent of this process\n"));
+- goto out;
+- }
+
+ switch (request) {
+ /* When I and D space are separate, these will need to be fixed. */
+@@ -384,6 +399,7 @@
+ free_task_struct(child);
+ out_notsk:
+ unlock_kernel();
++ if (ret == -ELOOP && regs.r0) goto retry_ptrace;
+ return ret;
+ }
+
+@@ -395,6 +411,7 @@
+ return;
+ current->exit_code = SIGTRAP;
+ current->state = TASK_STOPPED;
++ bproc_hook_im(stop_notify,(SIGTRAP));
+ notify_parent(current, SIGCHLD);
+ schedule();
+ /*
+Index: linux/arch/ppc/config.in
+===================================================================
+--- linux.orig/arch/ppc/config.in 2002-11-28 18:53:11.000000000 -0500
++++ linux/arch/ppc/config.in 2003-09-03 17:52:04.000000000 -0400
+@@ -162,6 +162,7 @@
+ bool 'Networking support' CONFIG_NET
+ bool 'Sysctl support' CONFIG_SYSCTL
+ bool 'System V IPC' CONFIG_SYSVIPC
++bool 'Beowulf Distributed Process Space' CONFIG_BPROC
+ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+
+ # only elf supported, a.out is not -- Cort
+Index: linux/arch/ppc/kernel/signal.c
+===================================================================
+--- linux.orig/arch/ppc/kernel/signal.c 2002-11-28 18:53:11.000000000 -0500
++++ linux/arch/ppc/kernel/signal.c 2003-09-03 17:52:04.000000000 -0400
+@@ -29,6 +29,7 @@
+ #include <linux/unistd.h>
+ #include <linux/stddef.h>
+ #include <linux/elf.h>
++#include <linux/bproc.h>
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -579,6 +580,7 @@
+ /* Let the debugger run. */
+ current->exit_code = signr;
+ current->state = TASK_STOPPED;
++ bproc_hook_im(stop_notify,(signr));
+ notify_parent(current, SIGCHLD);
+ schedule();
+
+@@ -636,6 +638,7 @@
+ case SIGSTOP:
+ current->state = TASK_STOPPED;
+ current->exit_code = signr;
++ bproc_hook_im(stop_notify,(signr));
+ if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ notify_parent(current, SIGCHLD);
+ schedule();
+Index: linux/arch/ppc/kernel/ptrace.c
+===================================================================
+--- linux.orig/arch/ppc/kernel/ptrace.c 2002-11-28 18:53:11.000000000 -0500
++++ linux/arch/ppc/kernel/ptrace.c 2003-09-03 17:52:04.000000000 -0400
+@@ -27,6 +27,7 @@
+ #include <linux/errno.h>
+ #include <linux/ptrace.h>
+ #include <linux/user.h>
++#include <linux/bproc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/page.h>
+@@ -161,6 +162,15 @@
+ {
+ struct task_struct *child;
+ int ret = -EPERM;
++ long orig_pid;
++
++ orig_pid = pid;
++ retry_ptrace:
++ pid = orig_pid;
++ if (bproc_hook_imv(0, ptracem,(request,&pid,addr,data,(long*)&ret,0))){
++ if (ret == -ELOOP) goto retry_ptrace;
++ return ret;
++ }
+
+ lock_kernel();
+ if (request == PTRACE_TRACEME) {
+@@ -186,14 +196,21 @@
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
++ bproc_set_arg(addr);
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
++ bproc_set_arg(request == PTRACE_DETACH ? addr : 0);
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
++ if (bproc_isghost(child)) {
++ bproc_hook(ptraceg, (request,child,addr,data,(long*)&ret,0));
++ goto out_tsk;
++ }
++
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+@@ -342,6 +359,7 @@
+ free_task_struct(child);
+ out:
+ unlock_kernel();
++ if (ret == -ELOOP) goto retry_ptrace;
+ return ret;
+ }
+
+@@ -352,6 +370,7 @@
+ return;
+ current->exit_code = SIGTRAP;
+ current->state = TASK_STOPPED;
++ bproc_hook_im(stop_notify,(SIGTRAP));
+ notify_parent(current, SIGCHLD);
+ schedule();
+ /*
+Index: linux/arch/ppc/kernel/ppc_ksyms.c
+===================================================================
+--- linux.orig/arch/ppc/kernel/ppc_ksyms.c 2002-11-28 18:53:11.000000000 -0500
++++ linux/arch/ppc/kernel/ppc_ksyms.c 2003-09-03 17:52:04.000000000 -0400
+@@ -366,3 +366,5 @@
+ EXPORT_SYMBOL_NOVERS(agp_special_page);
+ #endif /* defined(CONFIG_ALL_PPC) */
+
++asmlinkage void ret_from_syscall_1(void) __asm__("ret_from_syscall_1");
++EXPORT_SYMBOL_NOVERS(ret_from_syscall_1);
+Index: linux/arch/ppc/kernel/misc.S
+===================================================================
+--- linux.orig/arch/ppc/kernel/misc.S 2003-09-03 17:51:02.000000000 -0400
++++ linux/arch/ppc/kernel/misc.S 2003-09-03 17:52:04.000000000 -0400
+@@ -901,6 +901,20 @@
+ * arch_kernel_thread(fn, arg, flags)
+ */
+ _GLOBAL(arch_kernel_thread)
++ stwu r1,-28(r1) /* Setup stack frame to save args */
++ mflr r0
++ stw r3, 16(r1)
++ stw r4, 20(r1)
++ stw r5, 24(r1)
++ stw r0, 32(r1)
++ bl bproc_kcall_ /* Call bproc_kcall_ hook */
++ lwz r0, 32(r1) /* Restore stack + arguments */
++ lwz r5, 24(r1)
++ lwz r4, 20(r1)
++ lwz r3, 16(r1)
++ mtlr r0
++ addi r1,r1,28
++
+ mr r6,r3 /* function */
+ ori r3,r5,CLONE_VM /* flags */
+ li r0,__NR_clone
+@@ -941,7 +955,29 @@
+ SYSCALL(execve)
+ SYSCALL(open)
+ SYSCALL(close)
+-SYSCALL(waitpid)
++_GLOBAL(waitpid)
++ stwu r1,-28(r1) /* Setup stack frame to save args */
++ mflr r0
++ stw r3, 16(r1)
++ stw r4, 20(r1)
++ stw r5, 24(r1)
++ stw r0, 32(r1)
++ bl bproc_kcall_ /* Call bproc_kcall_ hook */
++ lwz r0, 32(r1) /* Restore stack + arguments */
++ lwz r5, 24(r1)
++ lwz r4, 20(r1)
++ lwz r3, 16(r1)
++ mtlr r0
++ addi r1,r1,28
++
++ li r0,__NR_waitpid
++ sc
++ bnslr
++ lis r4,errno@ha
++ stw r3,errno@l(r4)
++ li r3,-1
++ blr
++
+ SYSCALL(fork)
+ SYSCALL(delete_module)
+ SYSCALL(_exit)
+Index: linux/arch/ppc/kernel/process.c
+===================================================================
+--- linux.orig/arch/ppc/kernel/process.c 2001-11-26 08:29:17.000000000 -0500
++++ linux/arch/ppc/kernel/process.c 2003-09-03 17:52:04.000000000 -0400
+@@ -34,6 +34,7 @@
+ #include <linux/user.h>
+ #include <linux/elf.h>
+ #include <linux/init.h>
++#include <linux/bproc.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/uaccess.h>
+@@ -443,6 +444,10 @@
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+ out:
++ if (error == -ENOENT)
++ error = bproc_hook_imv(error, sys_execve,
++ (regs,(char*)a0,(char**)a1,(char**)a2));
++
+ return error;
+ }
+
+@@ -605,3 +610,10 @@
+ } while (count++ < 16);
+ return 0;
+ }
++
++/* This is usually inlined. It's packaged in a function here so that
++ * we can call it from ASM code on this architecture. */
++void bproc_kcall_(void)
++{
++ bproc_kcall();
++}
+Index: linux/fs/inode.c
+===================================================================
+--- linux.orig/fs/inode.c 2003-09-03 17:52:00.000000000 -0400
++++ linux/fs/inode.c 2003-09-03 17:52:04.000000000 -0400
+@@ -816,6 +816,76 @@
+ return inode;
+ }
+
++/*
++ * This just initializes the inode fields
++ * to known values before returning the inode..
++ *
++ * i_sb, i_ino, i_count, i_state and the lists have
++ * been initialized elsewhere..
++ */
++static void clean_inode(struct inode *inode)
++{
++ static struct address_space_operations empty_aops;
++ static struct inode_operations empty_iops;
++ static struct file_operations empty_fops;
++ memset(&inode->u, 0, sizeof(inode->u));
++ inode->i_sock = 0;
++ inode->i_op = &empty_iops;
++ inode->i_fop = &empty_fops;
++ inode->i_nlink = 1;
++ atomic_set(&inode->i_writecount, 0);
++ inode->i_size = 0;
++ inode->i_blocks = 0;
++ inode->i_generation = 0;
++ memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
++ inode->i_pipe = NULL;
++ inode->i_bdev = NULL;
++ inode->i_cdev = NULL;
++ inode->i_data.a_ops = &empty_aops;
++ inode->i_data.host = inode;
++ inode->i_data.gfp_mask = GFP_HIGHUSER;
++ inode->i_mapping = &inode->i_data;
++}
++
++/**
++ * get_empty_inode - obtain an inode
++ *
++ * This is called by things like the networking layer
++ * etc that want to get an inode without any inode
++ * number, or filesystems that allocate new inodes with
++ * no pre-existing information.
++ *
++ * On a successful return the inode pointer is returned. On a failure
++ * a %NULL pointer is returned. The returned inode is not on any superblock
++ * lists.
++ */
++
++struct inode * get_empty_inode(void)
++{
++ static unsigned long last_ino;
++ struct inode * inode;
++
++ spin_lock_prefetch(&inode_lock);
++
++ inode = (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
++ if (inode)
++ {
++ spin_lock(&inode_lock);
++ inodes_stat.nr_inodes++;
++ list_add(&inode->i_list, &inode_in_use);
++ inode->i_sb = NULL;
++ inode->i_dev = 0;
++ inode->i_blkbits = 0;
++ inode->i_ino = ++last_ino;
++ inode->i_flags = 0;
++ atomic_set(&inode->i_count, 1);
++ inode->i_state = 0;
++ spin_unlock(&inode_lock);
++ clean_inode(inode);
++ }
++ return inode;
++}
++
+ /**
+ * new_inode - obtain an inode
+ * @sb: superblock
+Index: linux/include/linux/fs.h
+===================================================================
+--- linux.orig/include/linux/fs.h 2003-09-03 17:52:02.000000000 -0400
++++ linux/include/linux/fs.h 2003-09-03 17:52:04.000000000 -0400
+@@ -1440,6 +1440,7 @@
+
+ extern void clear_inode(struct inode *);
+ extern struct inode *new_inode(struct super_block *sb);
++extern struct inode * get_empty_inode(void);
+ extern void remove_suid(struct inode *inode);
+
+ extern void insert_inode_hash(struct inode *);
+Index: linux/arch/i386/kernel/setup.c
+===================================================================
+--- linux.orig/arch/i386/kernel/setup.c 2003-09-03 17:51:01.000000000 -0400
++++ linux/arch/i386/kernel/setup.c 2003-09-03 17:53:05.000000000 -0400
+@@ -172,6 +172,8 @@
+ static u32 disabled_x86_caps[NCAPINTS] __initdata = { 0 };
+ extern int blk_nohighio;
+
++int enable_acpi_smp_table;
++
+ /*
+ * This is set up by the setup-routine at boot-time
+ */
--- /dev/null
+ fs/ext3/ialloc.c | 6
+ fs/ext3/inode.c | 8
+ fs/ext3/xattr.c | 600 +++++++++++++++++++++++++++++++++++++++++++++-
+ include/linux/ext3_fs.h | 2
+ include/linux/ext3_fs_i.h | 3
+ 5 files changed, 608 insertions(+), 11 deletions(-)
+
+--- linux-2.4.18-chaos-uml/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.18-chaos 2003-09-10 23:43:07.000000000 +0400
++++ linux-2.4.18-chaos-uml-alexey/fs/ext3/ialloc.c 2003-09-10 23:43:23.000000000 +0400
+@@ -586,6 +586,12 @@ repeat:
+ insert_inode_hash(inode);
+ inode->i_generation = sbi->s_next_generation++;
+
++ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
++ ei->i_extra_isize = sizeof(__u16) /* i_extra_isize */
++ + sizeof(__u16); /* i_pad1 */
++ } else
++ ei->i_extra_isize = 0;
++
+ ei->i_state = EXT3_STATE_NEW;
+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
+ if (err) goto fail;
+--- linux-2.4.18-chaos-uml/fs/ext3/inode.c~ext3-ea-in-inode-2.4.18-chaos 2003-09-10 23:43:07.000000000 +0400
++++ linux-2.4.18-chaos-uml-alexey/fs/ext3/inode.c 2003-09-10 23:43:23.000000000 +0400
+@@ -2459,6 +2459,11 @@ void ext3_read_inode(struct inode * inod
+ ei->i_data[block] = iloc.raw_inode->i_block[block];
+ INIT_LIST_HEAD(&ei->i_orphan);
+
++ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
++ ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
++ else
++ ei->i_extra_isize = 0;
++
+ brelse (iloc.bh);
+
+ if (S_ISREG(inode->i_mode)) {
+@@ -2606,6 +2611,9 @@ static int ext3_do_update_inode(handle_t
+ else for (block = 0; block < EXT3_N_BLOCKS; block++)
+ raw_inode->i_block[block] = ei->i_data[block];
+
++ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
++ raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
++
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ rc = ext3_journal_dirty_metadata(handle, bh);
+ if (!err)
+--- linux-2.4.18-chaos-uml/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.18-chaos 2003-09-10 23:42:57.000000000 +0400
++++ linux-2.4.18-chaos-uml-alexey/fs/ext3/xattr.c 2003-09-10 23:43:23.000000000 +0400
+@@ -102,6 +102,9 @@
+ static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
+ struct ext3_xattr_header *);
+
++int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
++ void *, size_t, int);
++
+ #ifdef CONFIG_EXT3_FS_XATTR_SHARING
+
+ static int ext3_xattr_cache_insert(struct buffer_head *);
+@@ -362,17 +365,12 @@ ext3_removexattr(struct dentry *dentry,
+ }
+
+ /*
+- * ext3_xattr_get()
+- *
+- * Copy an extended attribute into the buffer
+- * provided, or compute the buffer size required.
+- * Buffer is NULL to compute the size of the buffer required.
++ * ext3_xattr_block_get()
+ *
+- * Returns a negative error number on failure, or the number of bytes
+- * used / required on success.
++ * routine looks for attribute in EA block and returns it's value and size
+ */
+ int
+-ext3_xattr_get(struct inode *inode, int name_index, const char *name,
++ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ void *buffer, size_t buffer_size)
+ {
+ struct buffer_head *bh = NULL;
+@@ -461,6 +459,94 @@ cleanup:
+ }
+
+ /*
++ * ext3_xattr_ibode_get()
++ *
++ * routine looks for attribute in inode body and returns it's value and size
++ */
++int
++ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size)
++{
++ int size, name_len = strlen(name), storage_size;
++ struct ext3_xattr_entry *last;
++ struct ext3_inode *raw_inode;
++ struct ext3_iloc iloc;
++ char *start, *end;
++ int ret = -ENOENT;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return -ENOENT;
++
++ ret = ext3_get_inode_loc(inode, &iloc);
++ if (ret)
++ return ret;
++ raw_inode = iloc.raw_inode;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
++ brelse(iloc.bh);
++ return -ENOENT;
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
++ "inode %ld", inode->i_ino);
++ brelse(iloc.bh);
++ return -EIO;
++ }
++ if (name_index == last->e_name_index &&
++ name_len == last->e_name_len &&
++ !memcmp(name, last->e_name, name_len))
++ goto found;
++ last = next;
++ }
++
++ /* can't find EA */
++ brelse(iloc.bh);
++ return -ENOENT;
++
++found:
++ size = le32_to_cpu(last->e_value_size);
++ if (buffer) {
++ ret = -ERANGE;
++ if (buffer_size >= size) {
++ memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
++ size);
++ ret = size;
++ }
++ } else
++ ret = size;
++ brelse(iloc.bh);
++ return ret;
++}
++
++int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size)
++{
++ int err;
++
++ /* try to find attribute in inode body */
++ err = ext3_xattr_ibody_get(inode, name_index, name,
++ buffer, buffer_size);
++ if (err < 0)
++ /* search was unsuccessful, try to find EA in dedicated block */
++ err = ext3_xattr_block_get(inode, name_index, name,
++ buffer, buffer_size);
++ return err;
++}
++
++/*
+ * ext3_xattr_list()
+ *
+ * Copy a list of attribute names into the buffer
+@@ -471,7 +557,7 @@ cleanup:
+ * used / required on success.
+ */
+ int
+-ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
++ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ {
+ struct buffer_head *bh = NULL;
+ struct ext3_xattr_entry *entry;
+@@ -547,6 +633,131 @@ cleanup:
+ return error;
+ }
+
++/* ext3_xattr_ibody_list()
++ *
++ * generate list of attributes stored in inode body
++ */
++int
++ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
++{
++ struct ext3_xattr_entry *last;
++ struct ext3_inode *raw_inode;
++ char *start, *end, *buf;
++ struct ext3_iloc iloc;
++ int storage_size;
++ int ret;
++ int size = 0;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return 0;
++
++ ret = ext3_get_inode_loc(inode, &iloc);
++ if (ret)
++ return ret;
++ raw_inode = iloc.raw_inode;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
++ brelse(iloc.bh);
++ return 0;
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ struct ext3_xattr_handler *handler;
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
++ "inode %ld", inode->i_ino);
++ brelse(iloc.bh);
++ return -EIO;
++ }
++ handler = ext3_xattr_handler(last->e_name_index);
++ if (handler)
++ size += handler->list(NULL, inode, last->e_name,
++ last->e_name_len);
++ last = next;
++ }
++
++ if (!buffer) {
++ ret = size;
++ goto cleanup;
++ } else {
++ ret = -ERANGE;
++ if (size > buffer_size)
++ goto cleanup;
++ }
++
++ last = (struct ext3_xattr_entry *) start;
++ buf = buffer;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ struct ext3_xattr_handler *handler;
++ handler = ext3_xattr_handler(last->e_name_index);
++ if (handler)
++ buf += handler->list(buf, inode, last->e_name,
++ last->e_name_len);
++ last = next;
++ }
++ ret = size;
++cleanup:
++ brelse(iloc.bh);
++ return ret;
++}
++
++/*
++ * ext3_xattr_list()
++ *
++ * Copy a list of attribute names into the buffer
++ * provided, or compute the buffer size required.
++ * Buffer is NULL to compute the size of the buffer required.
++ *
++ * Returns a negative error number on failure, or the number of bytes
++ * used / required on success.
++ */
++int
++ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
++{
++ int error;
++ int size = buffer_size;
++
++ /* get list of attributes stored in inode body */
++ error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
++ if (error < 0) {
++ /* some error occured while collecting
++ * attributes in inode body */
++ size = 0;
++ goto cleanup;
++ }
++ size = error;
++
++ /* get list of attributes stored in dedicated block */
++ if (buffer) {
++ buffer_size -= error;
++ if (buffer_size <= 0) {
++ buffer = NULL;
++ buffer_size = 0;
++ } else
++ buffer += error;
++ }
++
++ error = ext3_xattr_block_list(inode, buffer, buffer_size);
++ if (error < 0)
++ /* listing was successful, so we return len */
++ size = 0;
++
++cleanup:
++ return error + size;
++}
++
+ /*
+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
+ * not set, set it.
+@@ -570,6 +781,279 @@ static void ext3_xattr_update_super_bloc
+ }
+
+ /*
++ * ext3_xattr_ibody_find()
++ *
++ * search attribute and calculate free space in inode body
++ * NOTE: free space includes space our attribute hold
++ */
++int
++ext3_xattr_ibody_find(struct inode *inode, int name_index,
++ const char *name, struct ext3_xattr_entry *rentry, int *free)
++{
++ struct ext3_xattr_entry *last;
++ struct ext3_inode *raw_inode;
++ int name_len = strlen(name);
++ int err, storage_size;
++ struct ext3_iloc iloc;
++ char *start, *end;
++ int ret = -ENOENT;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return ret;
++
++ err = ext3_get_inode_loc(inode, &iloc);
++ if (err)
++ return -EIO;
++ raw_inode = iloc.raw_inode;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ *free = storage_size - sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
++ brelse(iloc.bh);
++ return -ENOENT;
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
++ "inode %ld", inode->i_ino);
++ brelse(iloc.bh);
++ return -EIO;
++ }
++
++ if (name_index == last->e_name_index &&
++ name_len == last->e_name_len &&
++ !memcmp(name, last->e_name, name_len)) {
++ memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
++ ret = 0;
++ } else {
++ *free -= EXT3_XATTR_LEN(last->e_name_len);
++ *free -= le32_to_cpu(last->e_value_size);
++ }
++ last = next;
++ }
++
++ brelse(iloc.bh);
++ return ret;
++}
++
++/*
++ * ext3_xattr_block_find()
++ *
++ * search attribute and calculate free space in EA block (if it allocated)
++ * NOTE: free space includes space our attribute hold
++ */
++int
++ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
++ struct ext3_xattr_entry *rentry, int *free)
++{
++ struct buffer_head *bh = NULL;
++ struct ext3_xattr_entry *entry;
++ char *end;
++ int name_len, error = -ENOENT;
++
++ if (!EXT3_I(inode)->i_file_acl) {
++ *free = inode->i_sb->s_blocksize -
++ sizeof(struct ext3_xattr_header) -
++ sizeof(__u32);
++ return -ENOENT;
++ }
++ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
++ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
++ if (!bh)
++ return -EIO;
++ ea_bdebug(bh, "b_count=%d, refcount=%d",
++ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
++ end = bh->b_data + bh->b_size;
++ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
++ HDR(bh)->h_blocks != cpu_to_le32(1)) {
++bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
++ "inode %ld: bad block %d", inode->i_ino,
++ EXT3_I(inode)->i_file_acl);
++ brelse(bh);
++ return -EIO;
++ }
++ /* find named attribute */
++ name_len = strlen(name);
++ *free = bh->b_size - sizeof(__u32);
++
++ entry = FIRST_ENTRY(bh);
++ while (!IS_LAST_ENTRY(entry)) {
++ struct ext3_xattr_entry *next =
++ EXT3_XATTR_NEXT(entry);
++ if ((char *)next >= end)
++ goto bad_block;
++ if (name_index == entry->e_name_index &&
++ name_len == entry->e_name_len &&
++ memcmp(name, entry->e_name, name_len) == 0) {
++ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
++ error = 0;
++ } else {
++ *free -= EXT3_XATTR_LEN(entry->e_name_len);
++ *free -= le32_to_cpu(entry->e_value_size);
++ }
++ entry = next;
++ }
++ brelse(bh);
++
++ return error;
++}
++
++/*
++ * ext3_xattr_inode_set()
++ *
++ * this routine add/remove/replace attribute in inode body
++ */
++int
++ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
++ const char *name, const void *value, size_t value_len,
++ int flags)
++{
++ struct ext3_xattr_entry *last, *next, *here = NULL;
++ struct ext3_inode *raw_inode;
++ int name_len = strlen(name);
++ int esize = EXT3_XATTR_LEN(name_len);
++ struct buffer_head *bh;
++ int err, storage_size;
++ struct ext3_iloc iloc;
++ int free, min_offs;
++ char *start, *end;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return -ENOSPC;
++
++ err = ext3_get_inode_loc(inode, &iloc);
++ if (err)
++ return err;
++ raw_inode = iloc.raw_inode;
++ bh = iloc.bh;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
++ /* inode had no attributes before */
++ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++ min_offs = storage_size;
++ free = storage_size - sizeof(__u32);
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ next = EXT3_XATTR_NEXT(last);
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
++ "inode %ld", inode->i_ino);
++ brelse(bh);
++ return -EIO;
++ }
++
++ if (last->e_value_size) {
++ int offs = le16_to_cpu(last->e_value_offs);
++ if (offs < min_offs)
++ min_offs = offs;
++ }
++ if (name_index == last->e_name_index &&
++ name_len == last->e_name_len &&
++ !memcmp(name, last->e_name, name_len))
++ here = last;
++ else {
++ /* we calculate all but our attribute
++ * because it will be removed before changing */
++ free -= EXT3_XATTR_LEN(last->e_name_len);
++ free -= le32_to_cpu(last->e_value_size);
++ }
++ last = next;
++ }
++
++ if (value && (esize + value_len > free)) {
++ brelse(bh);
++ return -ENOSPC;
++ }
++
++ err = ext3_reserve_inode_write(handle, inode, &iloc);
++ if (err) {
++ brelse(bh);
++ return err;
++ }
++
++ if (here) {
++ /* time to remove old value */
++ struct ext3_xattr_entry *e;
++ int size = le32_to_cpu(here->e_value_size);
++ int border = le16_to_cpu(here->e_value_offs);
++ char *src;
++
++ /* move tail */
++ memmove(start + min_offs + size, start + min_offs,
++ border - min_offs);
++
++ /* recalculate offsets */
++ e = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(e)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
++ int offs = le16_to_cpu(e->e_value_offs);
++ if (offs < border)
++ e->e_value_offs =
++ cpu_to_le16(offs + size);
++ e = next;
++ }
++ min_offs += size;
++
++ /* remove entry */
++ border = EXT3_XATTR_LEN(here->e_name_len);
++ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
++ size = (char *) last - src;
++ if ((char *) here + size > end)
++ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
++ __FILE__, __LINE__, here, size, end);
++ memmove(here, src, size);
++ last = (struct ext3_xattr_entry *) ((char *) last - border);
++ *((__u32 *) last) = 0;
++ }
++
++ if (value) {
++ int offs = min_offs - value_len;
++ /* use last to create new entry */
++ last->e_name_len = strlen(name);
++ last->e_name_index = name_index;
++ last->e_value_offs = cpu_to_le16(offs);
++ last->e_value_size = cpu_to_le32(value_len);
++ last->e_hash = last->e_value_block = 0;
++ memset(last->e_name, 0, esize);
++ memcpy(last->e_name, name, last->e_name_len);
++ if (start + offs + value_len > end)
++ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
++ __FILE__, __LINE__, start, offs,
++ value_len, end);
++ memcpy(start + offs, value, value_len);
++ last = EXT3_XATTR_NEXT(last);
++ *((__u32 *) last) = 0;
++ }
++
++ ext3_mark_iloc_dirty(handle, inode, &iloc);
++ brelse(bh);
++
++ return 0;
++}
++
++/*
+ * ext3_xattr_set()
+ *
+ * Create, replace or remove an extended attribute for this inode. Buffer
+@@ -583,6 +1067,102 @@ static void ext3_xattr_update_super_bloc
+ */
+ int
+ ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
++ const char *name, void *value, size_t value_len, int flags)
++{
++ struct ext3_xattr_entry entry;
++ int err, where = 0, found = 0, total;
++ int free1 = -1, free2 = -1;
++ int name_len;
++
++ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
++ name_index, name, value, (long)value_len);
++
++ if (IS_RDONLY(inode))
++ return -EROFS;
++ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
++ return -EPERM;
++ if (value == NULL)
++ value_len = 0;
++ if (name == NULL)
++ return -EINVAL;
++ name_len = strlen(name);
++ if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
++ return -ERANGE;
++ ext3_xattr_lock();
++
++ /* try to find attribute in inode body */
++ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
++ if (err == 0) {
++ /* found EA in inode */
++ found = 1;
++ where = 0;
++ } else if (err == -ENOENT) {
++ /* there is no such attribute in inode body */
++ /* try to find attribute in dedicated block */
++ err = ext3_xattr_block_find(inode, name_index, name,
++ &entry, &free2);
++ if (err != 0 && err != -ENOENT) {
++ /* not found EA in block */
++ goto finish;
++ }
++ /* found EA in block */
++ where = 1;
++ found = 1;
++ } else
++ goto finish;
++
++ /* check flags: may replace? may create ? */
++ if (found && (flags & XATTR_CREATE)) {
++ err = -EEXIST;
++ goto finish;
++ } else if (!found && (flags & XATTR_REPLACE)) {
++ err = -ENODATA;
++ goto finish;
++ }
++
++ /* check if we have enough space to store attribute */
++ total = EXT3_XATTR_LEN(strlen(name)) + value_len;
++ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
++ /* have no enough space */
++ err = -ENOSPC;
++ goto finish;
++ }
++
++ /* time to remove attribute */
++ if (found) {
++ if (where == 0) {
++ /* EA is stored in inode body */
++ ext3_xattr_ibody_set(handle, inode, name_index, name,
++ NULL, 0, flags);
++ } else {
++ /* EA is stored in separated block */
++ ext3_xattr_block_set(handle, inode, name_index, name,
++ NULL, 0, flags);
++ }
++ }
++
++ /* try to store EA in inode body */
++ err = ext3_xattr_ibody_set(handle, inode, name_index, name,
++ value, value_len, flags);
++ if (err) {
++ /* can't store EA in inode body */
++ /* try to store in block */
++ err = ext3_xattr_block_set(handle, inode, name_index,
++ name, value, value_len, flags);
++ }
++
++finish:
++ ext3_xattr_unlock();
++ return err;
++}
++
++/*
++ * ext3_xattr_block_set()
++ *
++ * this routine add/remove/replace attribute in EA block
++ */
++int
++ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
+ const char *name, void *value, size_t value_len, int flags)
+ {
+ struct super_block *sb = inode->i_sb;
+@@ -619,7 +1199,6 @@ ext3_xattr_set(handle_t *handle, struct
+ name_len = strlen(name);
+ if (name_len > 255 || value_len > sb->s_blocksize)
+ return -ERANGE;
+- ext3_xattr_lock();
+
+ if (EXT3_I(inode)->i_file_acl) {
+ /* The inode already has an extended attribute block. */
+@@ -819,7 +1398,6 @@ cleanup:
+ brelse(bh);
+ if (!(bh && header == HDR(bh)))
+ kfree(header);
+- ext3_xattr_unlock();
+
+ return error;
+ }
+--- linux-2.4.18-chaos-uml/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.18-chaos 2003-09-10 23:43:07.000000000 +0400
++++ linux-2.4.18-chaos-uml-alexey/include/linux/ext3_fs.h 2003-09-10 23:43:23.000000000 +0400
+@@ -264,6 +264,8 @@ struct ext3_inode {
+ __u32 m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
++ __u16 i_extra_isize;
++ __u16 i_pad1;
+ };
+
+ #define i_size_high i_dir_acl
+--- linux-2.4.18-chaos-uml/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.18-chaos 2003-09-10 23:43:06.000000000 +0400
++++ linux-2.4.18-chaos-uml-alexey/include/linux/ext3_fs_i.h 2003-09-10 23:43:23.000000000 +0400
+@@ -62,6 +62,9 @@ struct ext3_inode_info {
+ */
+ loff_t i_disksize;
+
++ /* on-disk additional lenght */
++ __u16 i_extra_isize;
++
+ /*
+ * truncate_sem is for serialising ext3_truncate() against
+ * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's
+
+_