From: Jeff Dike <jdike@addtoit.com>

Below is a patch which updates UML to 2.6.0-test5.



 25-akpm/arch/um/Kconfig                          |   28 +
 25-akpm/arch/um/Kconfig_block                    |   14 
 25-akpm/arch/um/Kconfig_net                      |   70 --
 25-akpm/arch/um/Makefile                         |   49 +
 25-akpm/arch/um/Makefile-i386                    |   20 
 25-akpm/arch/um/Makefile-skas                    |    6 
 25-akpm/arch/um/config.release                   |    1 
 25-akpm/arch/um/defconfig                        |  203 ++++---
 25-akpm/arch/um/drivers/Makefile                 |    6 
 25-akpm/arch/um/drivers/chan_kern.c              |    1 
 25-akpm/arch/um/drivers/chan_user.c              |    4 
 25-akpm/arch/um/drivers/cow.h                    |   40 +
 25-akpm/arch/um/drivers/cow_kern.c               |  628 +++++++++++++++++++++++
 25-akpm/arch/um/drivers/cow_sys.h                |   48 +
 25-akpm/arch/um/drivers/cow_user.c               |  296 ++++++++++
 25-akpm/arch/um/drivers/hostaudio_kern.c         |   77 ++
 25-akpm/arch/um/drivers/line.c                   |   61 +-
 25-akpm/arch/um/drivers/mconsole_kern.c          |   46 +
 25-akpm/arch/um/drivers/mconsole_user.c          |    2 
 25-akpm/arch/um/drivers/mmapper_kern.c           |    5 
 25-akpm/arch/um/drivers/net_kern.c               |   86 +--
 25-akpm/arch/um/drivers/port_kern.c              |   10 
 25-akpm/arch/um/drivers/ssl.c                    |    5 
 25-akpm/arch/um/drivers/stdio_console.c          |   28 -
 25-akpm/arch/um/drivers/ubd_kern.c               |  199 ++++---
 25-akpm/arch/um/drivers/ubd_user.c               |  297 ----------
 25-akpm/arch/um/drivers/xterm.c                  |    2 
 25-akpm/arch/um/drivers/xterm_kern.c             |    8 
 25-akpm/arch/um/dyn.lds.S                        |    8 
 25-akpm/arch/um/include/irq_kern.h               |   28 +
 25-akpm/arch/um/include/kern_util.h              |    7 
 25-akpm/arch/um/include/line.h                   |    7 
 25-akpm/arch/um/include/mconsole.h               |    1 
 25-akpm/arch/um/include/mem.h                    |    1 
 25-akpm/arch/um/include/mem_user.h               |    3 
 25-akpm/arch/um/include/os.h                     |    4 
 25-akpm/arch/um/include/sysdep-i386/sigcontext.h |    4 
 25-akpm/arch/um/include/ubd_user.h               |    1 
 25-akpm/arch/um/include/user.h                   |    2 
 25-akpm/arch/um/include/user_util.h              |    4 
 25-akpm/arch/um/kernel/Makefile                  |    8 
 25-akpm/arch/um/kernel/config.c.in               |    4 
 25-akpm/arch/um/kernel/init_task.c               |   15 
 25-akpm/arch/um/kernel/irq.c                     |   85 +--
 25-akpm/arch/um/kernel/mem.c                     |   17 
 25-akpm/arch/um/kernel/mem_user.c                |   15 
 25-akpm/arch/um/kernel/process.c                 |    4 
 25-akpm/arch/um/kernel/process_kern.c            |   39 -
 25-akpm/arch/um/kernel/ptrace.c                  |    7 
 25-akpm/arch/um/kernel/sigio_kern.c              |    7 
 25-akpm/arch/um/kernel/signal_kern.c             |   49 +
 25-akpm/arch/um/kernel/skas/Makefile             |   22 
 25-akpm/arch/um/kernel/skas/include/mode.h       |    1 
 25-akpm/arch/um/kernel/skas/include/uaccess.h    |    2 
 25-akpm/arch/um/kernel/skas/process.c            |   22 
 25-akpm/arch/um/kernel/skas/process_kern.c       |   14 
 25-akpm/arch/um/kernel/skas/util/mk_ptregs.c     |    1 
 25-akpm/arch/um/kernel/smp.c                     |   37 -
 25-akpm/arch/um/kernel/sys_call_table.c          |   76 ++
 25-akpm/arch/um/kernel/syscall_kern.c            |   72 --
 25-akpm/arch/um/kernel/sysrq.c                   |    8 
 25-akpm/arch/um/kernel/time.c                    |   12 
 25-akpm/arch/um/kernel/time_kern.c               |   17 
 25-akpm/arch/um/kernel/trap_kern.c               |    8 
 25-akpm/arch/um/kernel/trap_user.c               |    2 
 25-akpm/arch/um/kernel/tt/exec_kern.c            |    6 
 25-akpm/arch/um/kernel/tt/include/uaccess.h      |   31 -
 25-akpm/arch/um/kernel/tt/process_kern.c         |   44 -
 25-akpm/arch/um/kernel/tt/ptproxy/proxy.c        |    8 
 25-akpm/arch/um/kernel/tt/tracer.c               |    4 
 25-akpm/arch/um/kernel/tt/uaccess_user.c         |   14 
 25-akpm/arch/um/kernel/um_arch.c                 |   26 
 25-akpm/arch/um/kernel/umid.c                    |   47 -
 25-akpm/arch/um/kernel/user_util.c               |   11 
 25-akpm/arch/um/os-Linux/drivers/tuntap_user.c   |    2 
 25-akpm/arch/um/os-Linux/file.c                  |   37 +
 25-akpm/arch/um/sys-i386/Makefile                |   10 
 25-akpm/arch/um/sys-i386/bugs.c                  |   36 +
 25-akpm/arch/um/uml.lds.S                        |    8 
 25-akpm/arch/um/util/mk_constants_kern.c         |    4 
 25-akpm/include/asm-um/archparam-i386.h          |   59 ++
 25-akpm/include/asm-um/common.lds.S              |   34 +
 25-akpm/include/asm-um/cpufeature.h              |    6 
 25-akpm/include/asm-um/current.h                 |    6 
 25-akpm/include/asm-um/fixmap.h                  |    8 
 25-akpm/include/asm-um/irq.h                     |   13 
 25-akpm/include/asm-um/local.h                   |    6 
 25-akpm/include/asm-um/module-generic.h          |    6 
 25-akpm/include/asm-um/module-i386.h             |   13 
 25-akpm/include/asm-um/page.h                    |    1 
 25-akpm/include/asm-um/pgtable.h                 |   68 ++
 25-akpm/include/asm-um/processor-generic.h       |    9 
 25-akpm/include/asm-um/processor-i386.h          |    4 
 25-akpm/include/asm-um/sections.h                |    7 
 25-akpm/include/asm-um/smp.h                     |    2 
 25-akpm/include/asm-um/system-generic.h          |    9 
 25-akpm/include/asm-um/thread_info.h             |   16 
 25-akpm/include/asm-um/timex.h                   |    2 
 98 files changed, 2338 insertions(+), 1073 deletions(-)

diff -puN arch/um/config.release~uml-update arch/um/config.release
--- 25/arch/um/config.release~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/config.release	Fri Sep 12 11:39:06 2003
@@ -228,7 +228,6 @@ CONFIG_ROMFS_FS=m
 CONFIG_EXT2_FS=y
 CONFIG_SYSV_FS=m
 CONFIG_UDF_FS=m
-# CONFIG_UDF_RW is not set
 CONFIG_UFS_FS=m
 # CONFIG_UFS_FS_WRITE is not set
 
diff -puN arch/um/defconfig~uml-update arch/um/defconfig
--- 25/arch/um/defconfig~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/defconfig	Fri Sep 12 11:39:06 2003
@@ -3,29 +3,19 @@
 #
 CONFIG_USERMODE=y
 CONFIG_MMU=y
-CONFIG_SWAP=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_LOG_BUF_SHIFT=14
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
 
 #
-# General Setup
+# UML-specific options
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
 CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_HOSTFS=y
+CONFIG_HPPFS=y
 CONFIG_MCONSOLE=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HOST_2G_2G is not set
@@ -38,10 +28,38 @@ CONFIG_PROC_MM=y
 CONFIG_KERNEL_STACK_ORDER=2
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_KMOD is not set
+# CONFIG_MODULES is not set
+
+#
+# Generic Driver Options
+#
 
 #
 # Character Devices
@@ -69,6 +87,7 @@ CONFIG_HOSTAUDIO=y
 #
 CONFIG_BLK_DEV_UBD=y
 # CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
@@ -78,7 +97,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_NETDEVICES=y
 
 #
-# Network Devices
+# UML Network Devices
 #
 CONFIG_UML_NET=y
 CONFIG_UML_NET_ETHERTAP=y
@@ -88,22 +107,6 @@ CONFIG_UML_NET_DAEMON=y
 CONFIG_UML_NET_MCAST=y
 # CONFIG_UML_NET_PCAP is not set
 CONFIG_UML_NET_SLIRP=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Networking support
@@ -115,8 +118,6 @@ CONFIG_SLIP=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -130,8 +131,11 @@ CONFIG_INET=y
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_INET_IPCOMP is not set
 # CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -141,8 +145,6 @@ CONFIG_IPV6_SCTP__=y
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -160,6 +162,10 @@ CONFIG_IPV6_SCTP__=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
 
 #
 # Ethernet (10 or 100Mbit)
@@ -171,6 +177,22 @@ CONFIG_IPV6_SCTP__=y
 #
 
 #
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=y
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
@@ -188,66 +210,82 @@ CONFIG_IPV6_SCTP__=y
 #
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
 CONFIG_QUOTACTL=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 CONFIG_JFFS_FS=y
 CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_MINIX_FS=m
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
 
 #
 # Network File Systems
 #
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
 # CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -317,28 +355,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # SCSI support
 #
-CONFIG_SCSI=y
-CONFIG_GENERIC_ISA_DMA=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_DEBUG_QUEUES=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_DEBUG=y
+# CONFIG_SCSI is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -360,6 +377,7 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -374,20 +392,21 @@ CONFIG_MTD_BLOCK=y
 #
 # Mapping drivers for chip access
 #
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
 
 #
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLKMTD=m
+CONFIG_MTD_BLKMTD=y
 
 #
 # Disk-On-Chip Device Drivers
 #
-# CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
 
 #
 # NAND Flash Device Drivers
diff -puN arch/um/drivers/chan_kern.c~uml-update arch/um/drivers/chan_kern.c
--- 25/arch/um/drivers/chan_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/chan_kern.c	Fri Sep 12 11:39:06 2003
@@ -8,6 +8,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
+#include <linux/string.h>
 #include <linux/tty_flip.h>
 #include <asm/irq.h>
 #include "chan_kern.h"
diff -puN arch/um/drivers/chan_user.c~uml-update arch/um/drivers/chan_user.c
--- 25/arch/um/drivers/chan_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/chan_user.c	Fri Sep 12 11:39:06 2003
@@ -188,8 +188,8 @@ void register_winch(int fd, void *device
 	if(!isatty(fd)) return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) && 
-	   (pid == -1)){
+	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, 
+			     device_data) && (pid == -1)){
 		thread = winch_tramp(fd, device_data, &thread_fd);
 		if(fd != -1){
 			register_winch_irq(thread_fd, fd, thread, device_data);
diff -puN /dev/null arch/um/drivers/cow.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/um/drivers/cow.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,40 @@
+#ifndef __COW_H__
+#define __COW_H__
+
+#include <asm/types.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define ntohll(x) (x)
+# define htonll(x) (x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define ntohll(x)  bswap_64(x)
+# define htonll(x)  bswap_64(x)
+#else
+#error "__BYTE_ORDER not defined"
+#endif
+
+extern int init_cow_file(int fd, char *cow_file, char *backing_file, 
+			 int sectorsize, int *bitmap_offset_out, 
+			 unsigned long *bitmap_len_out, int *data_offset_out);
+
+extern int file_reader(__u64 offset, char *buf, int len, void *arg);
+extern int read_cow_header(int (*reader)(__u64, char *, int, void *), 
+			   void *arg, __u32 *magic_out, 
+			   char **backing_file_out, time_t *mtime_out, 
+			   __u64 *size_out, int *sectorsize_out, 
+			   int *bitmap_offset_out);
+
+extern int write_cow_header(char *cow_file, int fd, char *backing_file, 
+			    int sectorsize, long long *size);
+
+extern void cow_sizes(__u64 size, int sectorsize, int bitmap_offset, 
+		      unsigned long *bitmap_len_out, int *data_offset_out);
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN /dev/null arch/um/drivers/cow_kern.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/um/drivers/cow_kern.c	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,628 @@
+#define COW_MAJOR 60
+#define MAJOR_NR COW_MAJOR
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/stat.h>
+#include <linux/vmalloc.h>
+#include <linux/blkdev.h>
+#include <linux/blk.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/devfs_fs.h>
+#include <asm/uaccess.h>
+#include "2_5compat.h"
+#include "cow.h"
+#include "ubd_user.h"
+
+#define COW_SHIFT 4
+
+struct cow {
+	int count;
+	char *cow_path;
+	dev_t cow_dev;
+	struct block_device *cow_bdev;
+	char *backing_path;
+	dev_t backing_dev;
+	struct block_device *backing_bdev;
+	int sectorsize;
+	unsigned long *bitmap;
+	unsigned long bitmap_len;
+	int bitmap_offset;
+	int data_offset;
+	devfs_handle_t devfs;
+	struct semaphore sem;
+	struct semaphore io_sem;
+	atomic_t working;
+	spinlock_t io_lock;
+	struct buffer_head *bh;
+	struct buffer_head *bhtail;
+	void *end_io;
+};
+
+#define DEFAULT_COW { \
+	.count			= 0, \
+	.cow_path		= NULL, \
+	.cow_dev		= 0, \
+	.backing_path		= NULL, \
+	.backing_dev		= 0, \
+        .bitmap			= NULL, \
+	.bitmap_len		= 0, \
+	.bitmap_offset		= 0, \
+        .data_offset		= 0, \
+	.devfs			= NULL, \
+	.working		= ATOMIC_INIT(0), \
+	.io_lock		= SPIN_LOCK_UNLOCKED, \
+}
+
+#define MAX_DEV (8)
+#define MAX_MINOR (MAX_DEV << COW_SHIFT)
+
+struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW };
+
+/* Not modified by this driver */
+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
+
+/* Protected by cow_lock */
+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
+
+static struct hd_struct	cow_part[MAX_MINOR] =
+	{ [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
+
+/* Protected by io_request_lock */
+static request_queue_t *cow_queue;
+
+static int cow_open(struct inode *inode, struct file *filp);
+static int cow_release(struct inode * inode, struct file * file);
+static int cow_ioctl(struct inode * inode, struct file * file,
+		     unsigned int cmd, unsigned long arg);
+static int cow_revalidate(kdev_t rdev);
+
+static struct block_device_operations cow_blops = {
+       .open		= cow_open,
+       .release	= cow_release,
+       .ioctl		= cow_ioctl,
+       .revalidate	= cow_revalidate,
+};
+
+/* Initialized in an initcall, and unchanged thereafter */
+devfs_handle_t cow_dir_handle;
+
+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
+{ \
+	.major 		= maj, \
+	.major_name  	= name, \
+	.minor_shift 	= shift, \
+	.max_p  	= 1 << shift, \
+	.part  		= parts, \
+	.sizes  	= bsizes, \
+	.nr_real  	= max, \
+	.real_devices  	= NULL, \
+	.next  		= NULL, \
+	.fops  		= blops, \
+	.de_arr  	= NULL, \
+	.flags  	= 0 \
+}
+
+static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED;
+
+static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part,
+						 COW_SHIFT, sizes, MAX_DEV, 
+						 &cow_blops);
+
+static int cow_add(int n)
+{
+	struct cow *dev = &cow_dev[n];
+	char name[sizeof("nnnnnn\0")];
+	int err = -ENODEV;
+
+	if(dev->cow_path == NULL)
+		goto out;
+
+	sprintf(name, "%d", n);
+	dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE,
+				    MAJOR_NR, n << COW_SHIFT, S_IFBLK | 
+				    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+				    &cow_blops, NULL);
+
+	init_MUTEX_LOCKED(&dev->sem);
+	init_MUTEX(&dev->io_sem);
+
+	return(0);
+
+out:
+	return(err);
+}
+
+/*
+* Add buffer_head to back of pending list
+*/
+static void cow_add_bh(struct cow *cow, struct buffer_head *bh)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cow->io_lock, flags);
+	if(cow->bhtail != NULL){
+		cow->bhtail->b_reqnext = bh;
+		cow->bhtail = bh;
+	}
+	else {
+		cow->bh = bh;
+		cow->bhtail = bh;
+	}
+	spin_unlock_irqrestore(&cow->io_lock, flags);
+}
+
+/*
+* Grab first pending buffer
+*/
+static struct buffer_head *cow_get_bh(struct cow *cow)
+{
+	struct buffer_head *bh;
+
+	spin_lock_irq(&cow->io_lock);
+	bh = cow->bh;
+	if(bh != NULL){
+		if(bh == cow->bhtail)
+			cow->bhtail = NULL;
+		cow->bh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+	}
+	spin_unlock_irq(&cow->io_lock);
+
+	return(bh);
+}
+
+static void cow_handle_bh(struct cow *cow, struct buffer_head *bh, 
+			  struct buffer_head **cow_bh, int ncow_bh)
+{
+	int i;
+
+	if(ncow_bh > 0)
+		ll_rw_block(WRITE, ncow_bh, cow_bh);
+
+	for(i = 0; i < ncow_bh ; i++){
+		wait_on_buffer(cow_bh[i]);
+		brelse(cow_bh[i]);
+	}
+
+	ll_rw_block(WRITE, 1, &bh);
+	brelse(bh);
+}
+
+static struct buffer_head *cow_new_bh(struct cow *dev, int sector)
+{
+	struct buffer_head *bh;
+
+	sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize;
+	bh = getblk(dev->cow_dev, sector, dev->sectorsize);
+	memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])),
+	       dev->sectorsize);
+	return(bh);
+}
+
+/* Copied from loop.c, needed to avoid deadlocking in make_request. */
+
+static int cow_thread(void *data)
+{
+	struct cow *dev = data;
+	struct buffer_head *bh;
+
+	daemonize();
+	exit_files(current);
+
+	sprintf(current->comm, "cow%d", dev - cow_dev);
+
+	spin_lock_irq(&current->sigmask_lock);
+	sigfillset(&current->blocked);
+	flush_signals(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	atomic_inc(&dev->working);
+
+	current->policy = SCHED_OTHER;
+	current->nice = -20;
+
+	current->flags |= PF_NOIO;
+
+	/*
+	 * up sem, we are running
+	 */
+	up(&dev->sem);
+
+	for(;;){
+		int start, len, nbh, i, update_bitmap = 0;
+		struct buffer_head *cow_bh[2];
+
+		down_interruptible(&dev->io_sem);
+		/*
+		 * could be upped because of tear-down, not because of
+		 * pending work
+		 */
+		if(!atomic_read(&dev->working))
+			break;
+
+		bh = cow_get_bh(dev);
+		if(bh == NULL){
+			printk(KERN_ERR "cow: missing bh\n");
+			continue;
+		}
+
+		start = bh->b_blocknr * bh->b_size / dev->sectorsize;
+		len = bh->b_size / dev->sectorsize;
+		for(i = 0; i < len ; i++){
+			if(ubd_test_bit(start +ni, 
+					(unsigned char *) dev->bitmap))
+				continue;
+
+			update_bitmap = 1;
+			ubd_set_bit(start + i, (unsigned char *) dev->bitmap);
+		}
+
+		cow_bh[0] = NULL;
+		cow_bh[1] = NULL;
+		nbh = 0;
+		if(update_bitmap){
+			cow_bh[0] = cow_new_bh(dev, start);
+			nbh++;
+			if(start / dev->sectorsize != 
+			   (start + len) / dev->sectorsize){
+				cow_bh[1] = cow_new_bh(dev, start + len);
+				nbh++;
+			}
+		}
+		
+		bh->b_dev = dev->cow_dev;
+		bh->b_blocknr += dev->data_offset / dev->sectorsize;
+
+		cow_handle_bh(dev, bh, cow_bh, nbh);
+
+		/*
+		 * upped both for pending work and tear-down, lo_pending
+		 * will hit zero then
+		 */
+		if(atomic_dec_and_test(&dev->working))
+			break;
+	}
+
+	up(&dev->sem);
+	return(0);
+}
+
+static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
+{
+	struct cow *dev;
+	int n, minor;
+
+	minor = MINOR(bh->b_rdev);
+	n = minor >> COW_SHIFT;
+	dev = &cow_dev[n];
+
+	dev->end_io = NULL;
+	if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){
+		bh->b_rdev = dev->cow_dev;
+		bh->b_rsector += dev->data_offset / dev->sectorsize;
+	}
+	else if(rw == WRITE){
+		bh->b_dev = dev->cow_dev;
+		bh->b_blocknr += dev->data_offset / dev->sectorsize;
+
+		cow_add_bh(dev, bh);
+		up(&dev->io_sem);
+		return(0);
+	}
+	else {
+		bh->b_rdev = dev->backing_dev;
+	}
+
+	return(1);
+}
+
+int cow_init(void)
+{
+	int i;
+
+	cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL);
+	if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) {
+		printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR);
+		return -1;
+	}
+	read_ahead[MAJOR_NR] = 8;		/* 8 sector (4kB) read-ahead */
+	blksize_size[MAJOR_NR] = blk_sizes;
+	blk_size[MAJOR_NR] = sizes;
+	INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
+
+	cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
+	blk_init_queue(cow_queue, NULL);
+	INIT_ELV(cow_queue, &cow_queue->elevator);
+	blk_queue_make_request(cow_queue, cow_make_request);
+
+       add_gendisk(&cow_gendisk);
+
+	for(i=0;i<MAX_DEV;i++) 
+		cow_add(i);
+
+	return(0);
+}
+
+__initcall(cow_init);
+
+static int reader(__u64 start, char *buf, int count, void *arg)
+{
+	dev_t dev = *((dev_t *) arg);
+	struct buffer_head *bh;
+	__u64 block;
+	int cur, offset, left, n, blocksize = get_hardsect_size(dev);
+
+	if(blocksize == 0)
+		panic("Zero blocksize");
+
+	block = start / blocksize;
+	offset = start % blocksize;
+	left = count;
+	cur = 0;
+	while(left > 0){
+		n = (left > blocksize) ? blocksize : left;
+
+		bh = bread(dev, block, (n < 512) ? 512 : n);
+		if(bh == NULL)
+			return(-EIO);
+
+		n -= offset;
+		memcpy(&buf[cur], bh->b_data + offset, n);
+		block++;
+		left -= n;
+		cur += n;
+		offset = 0;
+		brelse(bh);
+	}
+
+	return(count);
+}
+
+static int cow_open(struct inode *inode, struct file *filp)
+{
+	int (*dev_ioctl)(struct inode *, struct file *, unsigned int, 
+			 unsigned long);
+	mm_segment_t fs;
+	struct cow *dev;
+	__u64 size;
+	__u32 magic;
+	time_t mtime;
+	char *backing_file;
+	int n, offset, err = 0;
+
+	n = DEVICE_NR(inode->i_rdev);
+	if(n >= MAX_DEV)
+		return(-ENODEV);
+	dev = &cow_dev[n];
+	offset = n << COW_SHIFT;
+
+	spin_lock(&cow_lock);
+
+	if(dev->count == 0){
+		dev->cow_dev = name_to_kdev_t(dev->cow_path);
+		if(dev->cow_dev == 0){
+			printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
+			       "failed\n", dev->cow_path);
+			err = -ENODEV;
+		}
+
+		dev->backing_dev = name_to_kdev_t(dev->backing_path);
+		if(dev->backing_dev == 0){
+			printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
+			       "failed\n", dev->backing_path);
+			err = -ENODEV;
+		}
+
+		if(err) 
+			goto out;
+
+		dev->cow_bdev = bdget(dev->cow_dev);
+		if(dev->cow_bdev == NULL){
+			printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", 
+			       dev->cow_path);
+			err = -ENOMEM;
+		}
+		dev->backing_bdev = bdget(dev->backing_dev);
+		if(dev->backing_bdev == NULL){
+			printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", 
+			       dev->backing_path);
+			err = -ENOMEM;
+		}
+
+		if(err) 
+			goto out;
+
+		err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0, 
+				 BDEV_RAW);
+		if(err){
+			printk("cow_open - blkdev_get of COW device failed, "
+			       "error = %d\n", err);
+			goto out;
+		}
+		
+		err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW);
+		if(err){
+			printk("cow_open - blkdev_get of backing device "
+			       "failed, error = %d\n", err);
+			goto out;
+		}
+		
+		err = read_cow_header(reader, &dev->cow_dev, &magic, 
+				      &backing_file, &mtime, &size,
+				      &dev->sectorsize, &dev->bitmap_offset);
+		if(err){
+			printk(KERN_ERR "cow_open - read_cow_header failed, "
+			       "err = %d\n", err);
+			goto out;
+		}
+
+		cow_sizes(size, dev->sectorsize, dev->bitmap_offset, 
+			  &dev->bitmap_len, &dev->data_offset);
+		dev->bitmap = (void *) vmalloc(dev->bitmap_len);
+		if(dev->bitmap == NULL){
+			err = -ENOMEM;
+			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+			goto out;
+		}
+		flush_tlb_kernel_vm();
+		
+		err = reader(dev->bitmap_offset, (char *) dev->bitmap, 
+			     dev->bitmap_len, &dev->cow_dev);
+		if(err < 0){
+			printk(KERN_ERR "Failed to read COW bitmap\n");
+			vfree(dev->bitmap);
+			goto out;
+		}
+
+		dev_ioctl = dev->backing_bdev->bd_op->ioctl;
+		fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = (*dev_ioctl)(inode, filp, BLKGETSIZE, 
+				   (unsigned long) &sizes[offset]);
+		set_fs(fs);
+		if(err){
+			printk(KERN_ERR "cow_open - BLKGETSIZE failed, "
+			       "error = %d\n", err);
+			goto out;
+		}
+
+		kernel_thread(cow_thread, dev, 
+			      CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+		down(&dev->sem);
+	}
+	dev->count++;
+out:
+	spin_unlock(&cow_lock);
+	return(err);
+}
+
+static int cow_release(struct inode * inode, struct file * file)
+{
+	struct cow *dev;
+	int n, err;
+
+	n = DEVICE_NR(inode->i_rdev);
+	if(n >= MAX_DEV)
+		return(-ENODEV);
+	dev = &cow_dev[n];
+
+	spin_lock(&cow_lock);
+
+	if(--dev->count > 0)
+		goto out;
+
+	err = blkdev_put(dev->cow_bdev, BDEV_RAW);
+	if(err)
+		printk("cow_release - blkdev_put of cow device failed, "
+		       "error = %d\n", err);
+	bdput(dev->cow_bdev);
+	dev->cow_bdev = 0;
+
+	err = blkdev_put(dev->backing_bdev, BDEV_RAW);
+	if(err)
+		printk("cow_release - blkdev_put of backing device failed, "
+		       "error = %d\n", err);
+	bdput(dev->backing_bdev);
+	dev->backing_bdev = 0;
+
+out:
+	spin_unlock(&cow_lock);
+	return(0);
+}
+
+static int cow_ioctl(struct inode * inode, struct file * file,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct cow *dev;
+	int (*dev_ioctl)(struct inode *, struct file *, unsigned int, 
+			 unsigned long);
+	int n;
+
+	n = DEVICE_NR(inode->i_rdev);
+	if(n >= MAX_DEV)
+		return(-ENODEV);
+	dev = &cow_dev[n];
+
+	dev_ioctl = dev->backing_bdev->bd_op->ioctl;
+	return((*dev_ioctl)(inode, file, cmd, arg));
+}
+
+static int cow_revalidate(kdev_t rdev)
+{
+	printk(KERN_ERR "Need to implement cow_revalidate\n");
+	return(0);
+}
+
+static int parse_unit(char **ptr)
+{
+	char *str = *ptr, *end;
+	int n = -1;
+
+	if(isdigit(*str)) {
+		n = simple_strtoul(str, &end, 0);
+		if(end == str)
+			return(-1);
+		*ptr = end;
+	}
+	else if (('a' <= *str) && (*str <= 'h')) {
+		n = *str - 'a';
+		str++;
+		*ptr = str;
+	}
+	return(n);
+}
+
+static int cow_setup(char *str)
+{
+	struct cow *dev;
+	char *cow_name, *backing_name;
+	int unit;
+
+	unit = parse_unit(&str);
+	if(unit < 0){
+		printk(KERN_ERR "cow_setup - Couldn't parse unit number\n");
+		return(1);
+	}
+
+	if(*str != '='){
+		printk(KERN_ERR "cow_setup - Missing '=' after unit "
+		       "number\n");
+		return(1);
+	}
+	str++;
+
+	cow_name = str;
+	backing_name = strchr(str, ',');
+	if(backing_name == NULL){
+		printk(KERN_ERR "cow_setup - missing backing device name\n");
+		return(0);
+	}
+	*backing_name = '\0';
+	backing_name++;
+
+	spin_lock(&cow_lock);
+
+	dev = &cow_dev[unit];
+	dev->cow_path = cow_name;
+	dev->backing_path = backing_name;
+	
+	spin_unlock(&cow_lock);
+	return(0);
+}
+
+__setup("cow", cow_setup);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN /dev/null arch/um/drivers/cow_sys.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/um/drivers/cow_sys.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,48 @@
+#ifndef __COW_SYS_H__
+#define __COW_SYS_H__
+
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "user.h"
+
+static inline void *cow_malloc(int size)
+{
+	return(um_kmalloc(size));
+}
+
+static inline void cow_free(void *ptr)
+{
+	kfree(ptr);
+}
+
+#define cow_printf printk
+
+static inline char *cow_strdup(char *str)
+{
+	return(uml_strdup(str));
+}
+
+static inline int cow_seek_file(int fd, __u64 offset)
+{
+	return(os_seek_file(fd, offset));
+}
+
+static inline int cow_file_size(char *file, __u64 *size_out)
+{
+	return(os_file_size(file, size_out));
+}
+
+static inline int cow_write_file(int fd, char *buf, int size)
+{
+	return(os_write_file(fd, buf, size));
+}
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN /dev/null arch/um/drivers/cow_user.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/um/drivers/cow_user.c	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,296 @@
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+
+#include "cow.h"
+#include "cow_sys.h"
+
+#define PATH_LEN_V1 256
+
+struct cow_header_v1 {
+	int magic;
+	int version;
+	char backing_file[PATH_LEN_V1];
+	time_t mtime;
+	__u64 size;
+	int sectorsize;
+};
+
+#define PATH_LEN_V2 MAXPATHLEN
+
+struct cow_header_v2 {
+	unsigned long magic;
+	unsigned long version;
+	char backing_file[PATH_LEN_V2];
+	time_t mtime;
+	__u64 size;
+	int sectorsize;
+};
+
+union cow_header {
+	struct cow_header_v1 v1;
+	struct cow_header_v2 v2;
+};
+
+#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
+#define COW_VERSION 2
+
+void cow_sizes(__u64 size, int sectorsize, int bitmap_offset, 
+	       unsigned long *bitmap_len_out, int *data_offset_out)
+{
+	*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
+
+	*data_offset_out = bitmap_offset + *bitmap_len_out;
+	*data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
+	*data_offset_out *= sectorsize;
+}
+
+static int absolutize(char *to, int size, char *from)
+{
+	char save_cwd[256], *slash;
+	int remaining;
+
+	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
+		cow_printf("absolutize : unable to get cwd - errno = %d\n", 
+			   errno);
+		return(-1);
+	}
+	slash = strrchr(from, '/');
+	if(slash != NULL){
+		*slash = '\0';
+		if(chdir(from)){
+			*slash = '/';
+			cow_printf("absolutize : Can't cd to '%s' - " 
+				   "errno = %d\n", from, errno);
+			return(-1);
+		}
+		*slash = '/';
+		if(getcwd(to, size) == NULL){
+			cow_printf("absolutize : unable to get cwd of '%s' - "
+			       "errno = %d\n", from, errno);
+			return(-1);
+		}
+		remaining = size - strlen(to);
+		if(strlen(slash) + 1 > remaining){
+			cow_printf("absolutize : unable to fit '%s' into %d "
+			       "chars\n", from, size);
+			return(-1);
+		}
+		strcat(to, slash);
+	}
+	else {
+		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
+			cow_printf("absolutize : unable to fit '%s' into %d "
+			       "chars\n", from, size);
+			return(-1);
+		}
+		strcpy(to, save_cwd);
+		strcat(to, "/");
+		strcat(to, from);
+	}
+	chdir(save_cwd);
+	return(0);
+}
+
+int write_cow_header(char *cow_file, int fd, char *backing_file, 
+		     int sectorsize, long long *size)
+{
+	struct cow_header_v2 *header;
+	struct stat64 buf;
+	int err;
+
+	err = cow_seek_file(fd, 0);
+	if(err != 0){
+		cow_printf("write_cow_header - lseek failed, errno = %d\n", 
+			   errno);
+		return(-errno);
+	}
+
+	err = -ENOMEM;
+	header = cow_malloc(sizeof(*header));
+	if(header == NULL){
+		cow_printf("Failed to allocate COW V2 header\n");
+		goto out;
+	}
+	header->magic = htonl(COW_MAGIC);
+	header->version = htonl(COW_VERSION);
+
+	err = -EINVAL;
+	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+		cow_printf("Backing file name \"%s\" is too long - names are "
+			   "limited to %d characters\n", backing_file, 
+			   sizeof(header->backing_file) - 1);
+		goto out_free;
+	}
+
+	if(absolutize(header->backing_file, sizeof(header->backing_file), 
+		      backing_file))
+		goto out_free;
+
+	err = stat64(header->backing_file, &buf);
+	if(err < 0){
+		cow_printf("Stat of backing file '%s' failed, errno = %d\n",
+			   header->backing_file, errno);
+		err = -errno;
+		goto out_free;
+	}
+
+	err = cow_file_size(header->backing_file, size);
+	if(err){
+		cow_printf("Couldn't get size of backing file '%s', "
+			   "errno = %d\n", header->backing_file, -*size);
+		goto out_free;
+	}
+
+	header->mtime = htonl(buf.st_mtime);
+	header->size = htonll(*size);
+	header->sectorsize = htonl(sectorsize);
+
+	err = write(fd, header, sizeof(*header));
+	if(err != sizeof(*header)){
+		cow_printf("Write of header to new COW file '%s' failed, "
+			   "errno = %d\n", cow_file, errno);
+		goto out_free;
+	}
+	err = 0;
+ out_free:
+	cow_free(header);
+ out:
+	return(err);
+}
+
+int file_reader(__u64 offset, char *buf, int len, void *arg)
+{
+	int fd = *((int *) arg);
+
+	return(pread(fd, buf, len, offset));
+}
+
+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, 
+		    __u32 *magic_out, char **backing_file_out, 
+		    time_t *mtime_out, __u64 *size_out, 
+		    int *sectorsize_out, int *bitmap_offset_out)
+{
+	union cow_header *header;
+	char *file;
+	int err, n;
+	unsigned long version, magic;
+
+	header = cow_malloc(sizeof(*header));
+	if(header == NULL){
+	        cow_printf("read_cow_header - Failed to allocate header\n");
+		return(-ENOMEM);
+	}
+	err = -EINVAL;
+	n = (*reader)(0, (char *) header, sizeof(*header), arg);
+	if(n < offsetof(typeof(header->v1), backing_file)){
+		cow_printf("read_cow_header - short header\n");
+		goto out;
+	}
+
+	magic = header->v1.magic;
+	if(magic == COW_MAGIC) {
+		version = header->v1.version;
+	}
+	else if(magic == ntohl(COW_MAGIC)){
+		version = ntohl(header->v1.version);
+	}
+	/* No error printed because the non-COW case comes through here */
+	else goto out;
+
+	*magic_out = COW_MAGIC;
+
+	if(version == 1){
+		if(n < sizeof(header->v1)){
+			cow_printf("read_cow_header - failed to read V1 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = header->v1.mtime;
+		*size_out = header->v1.size;
+		*sectorsize_out = header->v1.sectorsize;
+		*bitmap_offset_out = sizeof(header->v1);
+		file = header->v1.backing_file;
+	}
+	else if(version == 2){
+		if(n < sizeof(header->v2)){
+			cow_printf("read_cow_header - failed to read V2 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = ntohl(header->v2.mtime);
+		*size_out = ntohll(header->v2.size);
+		*sectorsize_out = ntohl(header->v2.sectorsize);
+		*bitmap_offset_out = sizeof(header->v2);
+		file = header->v2.backing_file;
+	}
+	else {
+		cow_printf("read_cow_header - invalid COW version\n");
+		goto out;
+	}
+	err = -ENOMEM;
+	*backing_file_out = cow_strdup(file);
+	if(*backing_file_out == NULL){
+		cow_printf("read_cow_header - failed to allocate backing "
+			   "file\n");
+		goto out;
+	}
+	err = 0;
+ out:
+	cow_free(header);
+	return(err);
+}
+
+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
+		  int *bitmap_offset_out, unsigned long *bitmap_len_out, 
+		  int *data_offset_out)
+{
+	__u64 size, offset;
+	char zero = 0;
+	int err;
+
+	err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
+	if(err) 
+		goto out;
+	
+	cow_sizes(size, sectorsize, sizeof(struct cow_header_v2), 
+		  bitmap_len_out, data_offset_out);
+	*bitmap_offset_out = sizeof(struct cow_header_v2);
+
+	offset = *data_offset_out + size - sizeof(zero);
+	err = cow_seek_file(fd, offset);
+	if(err != 0){
+		cow_printf("cow bitmap lseek failed : errno = %d\n", errno);
+		goto out;
+	}
+
+	/* does not really matter how much we write it is just to set EOF 
+	 * this also sets the entire COW bitmap
+	 * to zero without having to allocate it 
+	 */
+	err = cow_write_file(fd, &zero, sizeof(zero));
+	if(err != sizeof(zero)){
+		err = -EINVAL;
+		cow_printf("Write of bitmap to new COW file '%s' failed, "
+			   "errno = %d\n", cow_file, errno);
+		goto out;
+	}
+
+	return(0);
+
+ out:
+	return(err);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN arch/um/drivers/hostaudio_kern.c~uml-update arch/um/drivers/hostaudio_kern.c
--- 25/arch/um/drivers/hostaudio_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/hostaudio_kern.c	Fri Sep 12 11:39:06 2003
@@ -11,6 +11,7 @@
 #include "linux/fs.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
+#include "asm/uaccess.h"
 #include "kern_util.h"
 #include "init.h"
 #include "hostaudio.h"
@@ -22,7 +23,7 @@ char *mixer = HOSTAUDIO_DEV_MIXER;
 #ifndef MODULE
 static int set_dsp(char *name, int *add)
 {
-	dsp = uml_strdup(name);
+	dsp = name;
 	return(0);
 }
 
@@ -34,7 +35,7 @@ __uml_setup("dsp=", set_dsp,
 
 static int set_mixer(char *name, int *add)
 {
-	mixer = uml_strdup(name);
+	mixer = name;
 	return(0);
 }
 
@@ -51,23 +52,55 @@ static ssize_t hostaudio_read(struct fil
 			      loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: read called, count = %d\n", count);
 #endif
 
-        return(hostaudio_read_user(state, buffer, count, ppos));
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+        err = hostaudio_read_user(state, kbuf, count, ppos);
+	if(err < 0)
+		goto out;
+
+	if(copy_to_user(buffer, kbuf, err))
+		err = -EFAULT;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static ssize_t hostaudio_write(struct file *file, const char *buffer, 
 			       size_t count, loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: write called, count = %d\n", count);
 #endif
-        return(hostaudio_write_user(state, buffer, count, ppos));
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+	err = -EFAULT;
+	if(copy_from_user(kbuf, buffer, count))
+		goto out;
+
+        err = hostaudio_write_user(state, kbuf, count, ppos);
+	if(err < 0)
+		goto out;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static unsigned int hostaudio_poll(struct file *file, 
@@ -86,12 +119,43 @@ static int hostaudio_ioctl(struct inode 
 			   unsigned int cmd, unsigned long arg)
 {
         struct hostaudio_state *state = file->private_data;
+	unsigned long data = 0;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: ioctl called, cmd = %u\n", cmd);
 #endif
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(get_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
+
+        err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
+
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(put_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
 
-        return(hostaudio_ioctl_user(state, cmd, arg));
+	return(err);
 }
 
 static int hostaudio_open(struct inode *inode, struct file *file)
@@ -225,7 +289,8 @@ MODULE_LICENSE("GPL");
 
 static int __init hostaudio_init_module(void)
 {
-        printk(KERN_INFO "UML Audio Relay\n");
+        printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
+	       dsp, mixer);
 
 	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
         if(module_data.dev_audio < 0){
diff -puN arch/um/drivers/line.c~uml-update arch/um/drivers/line.c
--- 25/arch/um/drivers/line.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/line.c	Fri Sep 12 11:39:06 2003
@@ -6,8 +6,8 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/list.h"
+#include "linux/interrupt.h"
 #include "linux/devfs_fs_kernel.h"
-#include "asm/irq.h"
 #include "asm/uaccess.h"
 #include "chan_kern.h"
 #include "irq_user.h"
@@ -16,16 +16,18 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
+#include "irq_kern.h"
 
 #define LINE_BUFSIZE 4096
 
-void line_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct line *dev = data;
 
 	if(dev->count > 0) 
 		chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, 
 			       dev);
+	return IRQ_HANDLED;
 }
 
 void line_timer_cb(void *arg)
@@ -136,20 +138,22 @@ int line_write(struct line *lines, struc
 	return(len);
 }
 
-void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t line_write_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct line *dev = data;
 	struct tty_struct *tty = dev->tty;
 	int err;
 
 	err = flush_buffer(dev);
-	if(err == 0) return;
+	if(err == 0) 
+		return(IRQ_NONE);
 	else if(err < 0){
 		dev->head = dev->buffer;
 		dev->tail = dev->buffer;
 	}
 
-	if(tty == NULL) return;
+	if(tty == NULL) 
+		return(IRQ_NONE);
 
 	if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
 	   (tty->ldisc.write_wakeup != NULL))
@@ -161,9 +165,9 @@ void line_write_interrupt(int irq, void 
 	 * writes.
 	 */
 
-	if (waitqueue_active(&tty->write_wait))
+	if(waitqueue_active(&tty->write_wait))
 		wake_up_interruptible(&tty->write_wait);
-
+	return(IRQ_HANDLED);
 }
 
 int line_write_room(struct tty_struct *tty)
@@ -369,7 +373,7 @@ int line_get_config(char *name, struct l
 
 	dev = simple_strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		*error_out = "line_setup failed to parse device number";
+		*error_out = "line_get_config failed to parse device number";
 		return(0);
 	}
 
@@ -379,15 +383,15 @@ int line_get_config(char *name, struct l
 	}
 
 	line = &lines[dev];
+
 	down(&line->sem);
-	
 	if(!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if(line->count == 0)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-
 	up(&line->sem);
+
 	return(n);
 }
 
@@ -412,7 +416,8 @@ struct tty_driver *line_register_devfs(s
 		return NULL;
 
 	driver->driver_name = line_driver->name;
-	driver->name = line_driver->devfs_name;
+	driver->name = line_driver->device_name;
+	driver->devfs_name = line_driver->devfs_name;
 	driver->major = line_driver->major;
 	driver->minor_start = line_driver->minor_start;
 	driver->type = line_driver->type;
@@ -432,7 +437,7 @@ struct tty_driver *line_register_devfs(s
 
 	for(i = 0; i < nlines; i++){
 		if(!lines[i].valid) 
-			tty_unregister_devfs(driver, i);
+			tty_unregister_device(driver, i);
 	}
 
 	mconsole_register_dev(&line_driver->mc);
@@ -465,24 +470,25 @@ struct winch {
 	struct line *line;
 };
 
-void winch_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct winch *winch = data;
 	struct tty_struct *tty;
 	int err;
 	char c;
 
-	err = generic_read(winch->fd, &c, NULL);
-	if(err < 0){
-		if(err != -EAGAIN){
-			printk("winch_interrupt : read failed, errno = %d\n", 
-			       -err);
-			printk("fd %d is losing SIGWINCH support\n", 
-			       winch->tty_fd);
-			free_irq(irq, data);
-			return;
+	if(winch->fd != -1){
+		err = generic_read(winch->fd, &c, NULL);
+		if(err < 0){
+			if(err != -EAGAIN){
+				printk("winch_interrupt : read failed, "
+				       "errno = %d\n", -err);
+				printk("fd %d is losing SIGWINCH support\n", 
+				       winch->tty_fd);
+				return(IRQ_HANDLED);
+			}
+			goto out;
 		}
-		goto out;
 	}
 	tty = winch->line->tty;
 	if(tty != NULL){
@@ -492,7 +498,9 @@ void winch_interrupt(int irq, void *data
 		kill_pg(tty->pgrp, SIGWINCH, 1);
 	}
  out:
-	reactivate_fd(winch->fd, WINCH_IRQ);
+	if(winch->fd != -1)
+		reactivate_fd(winch->fd, WINCH_IRQ);
+	return(IRQ_HANDLED);
 }
 
 DECLARE_MUTEX(winch_handler_sem);
@@ -529,7 +537,10 @@ static void winch_cleanup(void)
 
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		close(winch->fd);
+		if(winch->fd != -1){
+			deactivate_fd(winch->fd, WINCH_IRQ);
+			close(winch->fd);
+		}
 		if(winch->pid != -1) 
 			os_kill_process(winch->pid, 1);
 	}
diff -puN arch/um/drivers/Makefile~uml-update arch/um/drivers/Makefile
--- 25/arch/um/drivers/Makefile~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/Makefile	Fri Sep 12 11:39:06 2003
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
 
@@ -39,6 +39,8 @@ obj-$(CONFIG_PTY_CHAN) += pty.o
 obj-$(CONFIG_TTY_CHAN) += tty.o 
 obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
+obj-$(CONFIG_BLK_DEV_COW) += cow_kern.o
+obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 
 obj-y += stdio_console.o $(CHAN_OBJS)
 
@@ -46,7 +48,7 @@ USER_SINGLE_OBJS = $(foreach f,$(patsubs
 
 USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
 	null.o pty.o tty.o xterm.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff -puN arch/um/drivers/mconsole_kern.c~uml-update arch/um/drivers/mconsole_kern.c
--- 25/arch/um/drivers/mconsole_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/mconsole_kern.c	Fri Sep 12 11:39:06 2003
@@ -27,6 +27,7 @@
 #include "init.h"
 #include "os.h"
 #include "umid.h"
+#include "irq_kern.h"
 
 static int do_unlink_socket(struct notifier_block *notifier, 
 			    unsigned long what, void *data)
@@ -67,7 +68,7 @@ void mc_work_proc(void *unused)
 
 DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
 
-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int fd;
 	struct mconsole_entry *new;
@@ -88,6 +89,7 @@ void mconsole_interrupt(int irq, void *d
 	}
 	if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
 	reactivate_fd(fd, MCONSOLE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 void mconsole_version(struct mc_request *req)
@@ -100,20 +102,34 @@ void mconsole_version(struct mc_request 
 	mconsole_reply(req, version, 0, 0);
 }
 
+void mconsole_log(struct mc_request *req)
+{
+	int len;
+	char *ptr = req->request.data;
+	
+	ptr += strlen("log");
+	while(isspace(*ptr)) ptr++;
+
+	len = ptr - req->request.data;
+	printk("%.*s", len, ptr);
+	mconsole_reply(req, "", 0, 0);
+}
+
 #define UML_MCONSOLE_HELPTEXT \
-"Commands:
-    version - Get kernel version
-    help - Print this message
-    halt - Halt UML
-    reboot - Reboot UML
-    config <dev>=<config> - Add a new device to UML; 
-	same syntax as command line
-    config <dev> - Query the configuration of a device
-    remove <dev> - Remove a device from UML
-    sysrq <letter> - Performs the SysRq action controlled by the letter
-    cad - invoke the Ctl-Alt-Del handler
-    stop - pause the UML; it will do nothing until it receives a 'go'
-    go - continue the UML after a 'stop'
+"Commands: \n\
+    version - Get kernel version \n\
+    help - Print this message \n\
+    halt - Halt UML \n\
+    reboot - Reboot UML \n\
+    config <dev>=<config> - Add a new device to UML;  \n\
+	same syntax as command line \n\
+    config <dev> - Query the configuration of a device \n\
+    remove <dev> - Remove a device from UML \n\
+    sysrq <letter> - Performs the SysRq action controlled by the letter \n\
+    cad - invoke the Ctl-Alt-Del handler \n\
+    stop - pause the UML; it will do nothing until it receives a 'go' \n\
+    go - continue the UML after a 'stop' \n\
+    log <string> - make UML enter <string> into the kernel log\n\
 "
 
 void mconsole_help(struct mc_request *req)
@@ -302,7 +318,7 @@ int mconsole_init(void)
 	if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
 	snprintf(mconsole_socket_name, sizeof(file), "%s", file);
 
-	sock = create_unix_socket(file, sizeof(file));
+	sock = create_unix_socket(file, sizeof(file), 1);
 	if (sock < 0){
 		printk("Failed to initialize management console\n");
 		return(1);
diff -puN arch/um/drivers/mconsole_user.c~uml-update arch/um/drivers/mconsole_user.c
--- 25/arch/um/drivers/mconsole_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/mconsole_user.c	Fri Sep 12 11:39:06 2003
@@ -28,6 +28,7 @@ static struct mconsole_command commands[
 	{ "cad", mconsole_cad, 1 },
 	{ "stop", mconsole_stop, 0 },
 	{ "go", mconsole_go, 1 },
+	{ "log", mconsole_log, 1 },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -139,6 +140,7 @@ int mconsole_reply(struct mc_request *re
 		memcpy(reply.data, str, len);
 		reply.data[len] = '\0';
 		total -= len;
+ 		str += len;
 		reply.len = len + 1;
 
 		len = sizeof(reply) + reply.len - sizeof(reply.data);
diff -puN arch/um/drivers/mmapper_kern.c~uml-update arch/um/drivers/mmapper_kern.c
--- 25/arch/um/drivers/mmapper_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/mmapper_kern.c	Fri Sep 12 11:39:06 2003
@@ -120,7 +120,10 @@ static int __init mmapper_init(void)
 	printk(KERN_INFO "Mapper v0.1\n");
 
 	v_buf = (char *) find_iomem("mmapper", &mmapper_size);
-	if(mmapper_size == 0) return(0);
+	if(mmapper_size == 0){
+		printk(KERN_ERR "mmapper_init - find_iomem failed\n");
+		return(0);
+	}
 
 	p_buf = __pa(v_buf);
 
diff -puN arch/um/drivers/net_kern.c~uml-update arch/um/drivers/net_kern.c
--- 25/arch/um/drivers/net_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/net_kern.c	Fri Sep 12 11:39:06 2003
@@ -26,6 +26,7 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(opened);
@@ -61,14 +62,14 @@ static int uml_net_rx(struct net_device 
 	return pkt_len;
 }
 
-void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct uml_net_private *lp = dev->priv;
 	int err;
 
 	if(!netif_running(dev))
-		return;
+		return(IRQ_NONE);
 
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
@@ -83,6 +84,7 @@ void uml_net_interrupt(int irq, void *de
 
  out:
 	spin_unlock(&lp->lock);
+	return(IRQ_HANDLED);
 }
 
 static int uml_net_open(struct net_device *dev)
@@ -252,37 +254,6 @@ void uml_net_user_timer_expire(unsigned 
 #endif
 }
 
-/*
- * default do nothing hard header packet routines for struct net_device init.
- * real ethernet transports will overwrite with real routines.
- */
-static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
-                 unsigned short type, void *daddr, void *saddr, unsigned len)
-{
-	return(0); /* no change */
-}
-
-static int uml_net_rebuild_header(struct sk_buff *skb)
-{
-	return(0); /* ignore */ 
-}
-
-static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-{
-	return(-1); /* fail */
-}
-
-static void uml_net_header_cache_update(struct hh_cache *hh,
-                 struct net_device *dev, unsigned char * haddr)
-{
-	/* ignore */
-}
-
-static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
-{
-	return(0); /* nothing */
-}
-
 static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head devices = LIST_HEAD_INIT(devices);
 
@@ -292,7 +263,7 @@ static int eth_configure(int n, void *in
 	struct uml_net *device;
 	struct net_device *dev;
 	struct uml_net_private *lp;
-	int err, size;
+	int save, err, size;
 
 	size = transport->private_size + sizeof(struct uml_net_private) + 
 		sizeof(((struct uml_net_private *) 0)->user);
@@ -334,12 +305,6 @@ static int eth_configure(int n, void *in
 	snprintf(dev->name, sizeof(dev->name), "eth%d", n);
 	device->dev = dev;
 
-        dev->hard_header = uml_net_hard_header;
-        dev->rebuild_header = uml_net_rebuild_header;
-        dev->hard_header_cache = uml_net_header_cache;
-        dev->header_cache_update= uml_net_header_cache_update;
-        dev->hard_header_parse = uml_net_header_parse;
-
 	(*transport->kern->init)(dev, init);
 
 	dev->mtu = transport->user->max_packet;
@@ -362,21 +327,29 @@ static int eth_configure(int n, void *in
 		return 1;
 	lp = dev->priv;
 
-	INIT_LIST_HEAD(&lp->list);
-	spin_lock_init(&lp->lock);
-	lp->dev = dev;
-	lp->fd = -1;
-	lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
-	lp->have_mac = device->have_mac;
-	lp->protocol = transport->kern->protocol;
-	lp->open = transport->user->open;
-	lp->close = transport->user->close;
-	lp->remove = transport->user->remove;
-	lp->read = transport->kern->read;
-	lp->write = transport->kern->write;
-	lp->add_address = transport->user->add_address;
-	lp->delete_address = transport->user->delete_address;
-	lp->set_mtu = transport->user->set_mtu;
+	/* lp.user is the first four bytes of the transport data, which
+	 * has already been initialized.  This structure assignment will
+	 * overwrite that, so we make sure that .user gets overwritten with
+	 * what it already has.
+	 */
+	save = lp->user[0];
+	*lp = ((struct uml_net_private) 
+		{ .list  		= LIST_HEAD_INIT(lp->list),
+		  .lock 		= SPIN_LOCK_UNLOCKED,
+		  .dev 			= dev,
+		  .fd 			= -1,
+		  .mac 			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
+		  .have_mac 		= device->have_mac,
+		  .protocol 		= transport->kern->protocol,
+		  .open 		= transport->user->open,
+		  .close 		= transport->user->close,
+		  .remove 		= transport->user->remove,
+		  .read 		= transport->kern->read,
+		  .write 		= transport->kern->write,
+		  .add_address 		= transport->user->add_address,
+		  .delete_address  	= transport->user->delete_address,
+		  .set_mtu 		= transport->user->set_mtu,
+		  .user  		= { save } });
 
 	init_timer(&lp->tl);
 	lp->tl.function = uml_net_user_timer_expire;
@@ -609,7 +582,8 @@ static int net_remove(char *str)
 	unregister_netdev(dev);
 
 	list_del(&device->list);
-	free_netdev(device);
+	kfree(device);
+	free_netdev(dev);
 	return(0);
 }
 
diff -puN arch/um/drivers/port_kern.c~uml-update arch/um/drivers/port_kern.c
--- 25/arch/um/drivers/port_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/port_kern.c	Fri Sep 12 11:39:06 2003
@@ -6,6 +6,7 @@
 #include "linux/list.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
+#include "linux/interrupt.h"
 #include "linux/irq.h"
 #include "linux/spinlock.h"
 #include "linux/errno.h"
@@ -14,6 +15,7 @@
 #include "kern_util.h"
 #include "kern.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "port.h"
 #include "init.h"
 #include "os.h"
@@ -44,7 +46,7 @@ struct connection {
 	struct port_list *port;
 };
 
-static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct connection *conn = data;
 	int fd;
@@ -52,7 +54,7 @@ static void pipe_interrupt(int irq, void
  	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
 	if(fd < 0){
 		if(fd == -EAGAIN)
-			return;
+			return(IRQ_NONE);
 
 		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 
 		       -fd);
@@ -65,6 +67,7 @@ static void pipe_interrupt(int irq, void
 	list_add(&conn->list, &conn->port->connections);
 
 	up(&conn->port->sem);
+	return(IRQ_HANDLED);
 }
 
 static int port_accept(struct port_list *port)
@@ -138,12 +141,13 @@ void port_work_proc(void *unused)
 
 DECLARE_WORK(port_work, port_work_proc, NULL);
 
-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct port_list *port = data;
 
 	port->has_connection = 1;
 	schedule_work(&port_work);
+	return(IRQ_HANDLED);
 } 
 
 void *port_data(int port_num)
diff -puN arch/um/drivers/ssl.c~uml-update arch/um/drivers/ssl.c
--- 25/arch/um/drivers/ssl.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/ssl.c	Fri Sep 12 11:39:06 2003
@@ -53,8 +53,9 @@ static int ssl_remove(char *str);
 
 static struct line_driver driver = {
 	.name 			= "UML serial line",
-	.devfs_name 		= "tts/%d",
-	.major 			= TTYAUX_MAJOR,
+	.device_name 		= "ttS",
+	.devfs_name 		= "tts/",
+	.major 			= TTY_MAJOR,
 	.minor_start 		= 64,
 	.type 		 	= TTY_DRIVER_TYPE_SERIAL,
 	.subtype 	 	= 0,
diff -puN arch/um/drivers/stdio_console.c~uml-update arch/um/drivers/stdio_console.c
--- 25/arch/um/drivers/stdio_console.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/stdio_console.c	Fri Sep 12 11:39:06 2003
@@ -83,7 +83,8 @@ static int con_remove(char *str);
 
 static struct line_driver driver = {
 	.name 			= "UML console",
-	.devfs_name 		= "vc/%d",
+	.device_name 		= "tty",
+	.devfs_name 		= "vc/",
 	.major 			= TTY_MAJOR,
 	.minor_start 		= 0,
 	.type 		 	= TTY_DRIVER_TYPE_CONSOLE,
@@ -159,6 +160,15 @@ static int chars_in_buffer(struct tty_st
 
 static int con_init_done = 0;
 
+static struct tty_operations console_ops = {
+	.open 	 		= con_open,
+	.close 	 		= con_close,
+	.write 	 		= con_write,
+	.chars_in_buffer 	= chars_in_buffer,
+	.set_termios 		= set_termios,
+	.write_room		= line_write_room,
+};
+
 int stdio_init(void)
 {
 	char *new_title;
@@ -166,7 +176,8 @@ int stdio_init(void)
 	printk(KERN_INFO "Initializing stdio console driver\n");
 
 	console_driver = line_register_devfs(&console_lines, &driver,
-				&console_ops, vts, sizeof(vts)/sizeof(vts[0]));
+					     &console_ops, vts,
+					     sizeof(vts)/sizeof(vts[0]));
 
 	lines_init(vts, sizeof(vts)/sizeof(vts[0]));
 
@@ -188,15 +199,6 @@ static void console_write(struct console
 	if(con_init_done) up(&vts[console->index].sem);
 }
 
-static struct tty_operations console_ops = {
-	.open 	 		= con_open,
-	.close 	 		= con_close,
-	.write 	 		= con_write,
-	.chars_in_buffer 	= chars_in_buffer,
-	.set_termios 		= set_termios,
-	.write_room		= line_write_room,
-};
-
 static struct tty_driver *console_device(struct console *c, int *index)
 {
 	*index = c->index;
@@ -212,12 +214,14 @@ static struct console stdiocons = INIT_C
 					       console_device, console_setup,
 					       CON_PRINTBUFFER);
 
-static void __init stdio_console_init(void)
+static int __init stdio_console_init(void)
 {
 	INIT_LIST_HEAD(&vts[0].chan_list);
 	list_add(&init_console_chan.list, &vts[0].chan_list);
 	register_console(&stdiocons);
+	return(0);
 }
+
 console_initcall(stdio_console_init);
 
 static int console_chan_setup(char *str)
diff -puN arch/um/drivers/ubd_kern.c~uml-update arch/um/drivers/ubd_kern.c
--- 25/arch/um/drivers/ubd_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/ubd_kern.c	Fri Sep 12 11:39:06 2003
@@ -8,6 +8,13 @@
  * old style ubd by setting UBD_SHIFT to 0
  * 2002-09-27...2002-10-18 massive tinkering for 2.5
  * partitions have changed in 2.5
+ * 2003-01-29 more tinkering for 2.5.59-1
+ * This should now address the sysfs problems and has
+ * the symlink for devfs to allow for booting with
+ * the common /dev/ubd/discX/... names rather than
+ * only /dev/ubdN/discN this version also has lots of
+ * clean ups preparing for ubd-many.
+ * James McMechan
  */
 
 #define MAJOR_NR UBD_MAJOR
@@ -40,6 +47,7 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "ubd_user.h"
 #include "2_5compat.h"
 #include "os.h"
@@ -67,7 +75,7 @@ static struct block_device_operations ub
 static request_queue_t *ubd_queue;
 
 /* Protected by ubd_lock */
-static int fake_major = 0;
+static int fake_major = MAJOR_NR;
 
 static struct gendisk *ubd_gendisk[MAX_DEV];
 static struct gendisk *fake_gendisk[MAX_DEV];
@@ -96,12 +104,12 @@ struct cow {
 
 struct ubd {
 	char *file;
-	int is_dir;
 	int count;
 	int fd;
 	__u64 size;
 	struct openflags boot_openflags;
 	struct openflags openflags;
+	int no_cow;
 	struct cow cow;
 };
 
@@ -115,12 +123,12 @@ struct ubd {
 
 #define DEFAULT_UBD { \
 	.file = 		NULL, \
-	.is_dir =		0, \
 	.count =		0, \
 	.fd =			-1, \
 	.size =			-1, \
 	.boot_openflags =	OPEN_FLAGS, \
 	.openflags =		OPEN_FLAGS, \
+        .no_cow =               0, \
         .cow =			DEFAULT_COW, \
 }
 
@@ -128,8 +136,10 @@ struct ubd ubd_dev[MAX_DEV] = { [ 0 ... 
 
 static int ubd0_init(void)
 {
-	if(ubd_dev[0].file == NULL)
-		ubd_dev[0].file = "root_fs";
+	struct ubd *dev = &ubd_dev[0];
+
+	if(dev->file == NULL)
+		dev->file = "root_fs";
 	return(0);
 }
 
@@ -196,19 +206,39 @@ __uml_help(fake_ide_setup,
 "    Create ide0 entries that map onto ubd devices.\n\n"
 );
 
+static int parse_unit(char **ptr)
+{
+	char *str = *ptr, *end;
+	int n = -1;
+
+	if(isdigit(*str)) {
+		n = simple_strtoul(str, &end, 0);
+		if(end == str)
+			return(-1);
+		*ptr = end;
+	}
+	else if (('a' <= *str) && (*str <= 'h')) {
+		n = *str - 'a';
+		str++;
+		*ptr = str;
+	}
+	return(n);
+}
+
 static int ubd_setup_common(char *str, int *index_out)
 {
+	struct ubd *dev;
 	struct openflags flags = global_openflags;
 	char *backing_file;
 	int n, err;
 
 	if(index_out) *index_out = -1;
-	n = *str++;
+	n = *str;
 	if(n == '='){
-		static int fake_major_allowed = 1;
 		char *end;
 		int major;
 
+		str++;
 		if(!strcmp(str, "sync")){
 			global_openflags.s = 1;
 			return(0);
@@ -220,20 +250,14 @@ static int ubd_setup_common(char *str, i
 			return(1);
 		}
 
-		if(!fake_major_allowed){
-			printk(KERN_ERR "Can't assign a fake major twice\n");
-			return(1);
-		}
-
 		err = 1;
  		spin_lock(&ubd_lock);
- 		if(!fake_major_allowed){
+ 		if(fake_major != MAJOR_NR){
  			printk(KERN_ERR "Can't assign a fake major twice\n");
  			goto out1;
  		}
  
  		fake_major = major;
-		fake_major_allowed = 0;
 
 		printk(KERN_INFO "Setting extra ubd major number to %d\n",
 		       major);
@@ -243,25 +267,23 @@ static int ubd_setup_common(char *str, i
 		return(err);
 	}
 
-	if(n < '0'){
-		printk(KERN_ERR "ubd_setup : index out of range\n"); }
-
-	if((n >= '0') && (n <= '9')) n -= '0';
-	else if((n >= 'a') && (n <= 'z')) n -= 'a';
-	else {
-		printk(KERN_ERR "ubd_setup : device syntax invalid\n");
+	n = parse_unit(&str);
+	if(n < 0){
+		printk(KERN_ERR "ubd_setup : couldn't parse unit number "
+		       "'%s'\n", str);
 		return(1);
 	}
 	if(n >= MAX_DEV){
-		printk(KERN_ERR "ubd_setup : index out of range "
-		       "(%d devices)\n", MAX_DEV);	
+		printk(KERN_ERR "ubd_setup : index %d out of range "
+		       "(%d devices)\n", n, MAX_DEV);
 		return(1);
 	}
 
 	err = 1;
 	spin_lock(&ubd_lock);
 
-	if(ubd_dev[n].file != NULL){
+	dev = &ubd_dev[n];
+	if(dev->file != NULL){
 		printk(KERN_ERR "ubd_setup : device already configured\n");
 		goto out2;
 	}
@@ -276,6 +298,11 @@ static int ubd_setup_common(char *str, i
 		flags.s = 1;
 		str++;
 	}
+	if (*str == 'd'){
+		dev->no_cow = 1;
+		str++;
+	}
+
 	if(*str++ != '='){
 		printk(KERN_ERR "ubd_setup : Expected '='\n");
 		goto out2;
@@ -284,14 +311,17 @@ static int ubd_setup_common(char *str, i
 	err = 0;
 	backing_file = strchr(str, ',');
 	if(backing_file){
-		*backing_file = '\0';
-		backing_file++;
+		if(dev->no_cow)
+			printk(KERN_ERR "Can't specify both 'd' and a "
+			       "cow file\n");
+		else {
+			*backing_file = '\0';
+			backing_file++;
+		}
 	}
-	ubd_dev[n].file = str;
-	if(ubd_is_dir(ubd_dev[n].file))
-		ubd_dev[n].is_dir = 1;
-	ubd_dev[n].cow.file = backing_file;
-	ubd_dev[n].boot_openflags = flags;
+	dev->file = str;
+	dev->cow.file = backing_file;
+	dev->boot_openflags = flags;
  out2:
 	spin_unlock(&ubd_lock);
 	return(err);
@@ -321,8 +351,7 @@ __uml_help(ubd_setup,
 static int fakehd_set = 0;
 static int fakehd(char *str)
 {
-	printk(KERN_INFO 
-	       "fakehd : Changing ubd name to \"hd\".\n");
+	printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
 	fakehd_set = 1;
 	return 1;
 }
@@ -391,9 +420,10 @@ static void ubd_handler(void)
 	do_ubd_request(ubd_queue);
 }
 
-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
+static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
 {
 	ubd_handler();
+	return(IRQ_HANDLED);
 }
 
 /* Only changed by ubd_init, which is an initcall. */
@@ -429,16 +459,18 @@ static void ubd_close(struct ubd *dev)
 static int ubd_open_dev(struct ubd *dev)
 {
 	struct openflags flags;
-	int err, n, create_cow, *create_ptr;
+	char **back_ptr;
+	int err, create_cow, *create_ptr;
 
+	dev->openflags = dev->boot_openflags;
 	create_cow = 0;
 	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
-	dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
+	back_ptr = dev->no_cow ? NULL : &dev->cow.file;
+	dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
 				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 
 				&dev->cow.data_offset, create_ptr);
 
 	if((dev->fd == -ENOENT) && create_cow){
-		n = dev - ubd_dev;
 		dev->fd = create_cow_file(dev->file, dev->cow.file, 
 					  dev->openflags, 1 << 9,
 					  &dev->cow.bitmap_offset, 
@@ -455,7 +487,10 @@ static int ubd_open_dev(struct ubd *dev)
 	if(dev->cow.file != NULL){
 		err = -ENOMEM;
 		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
-		if(dev->cow.bitmap == NULL) goto error;
+		if(dev->cow.bitmap == NULL){
+			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+			goto error;
+		}
 		flush_tlb_kernel_vm();
 
 		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 
@@ -481,17 +516,31 @@ static int ubd_new_disk(int major, u64 s
 			
 {
 	struct gendisk *disk;
+	char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
+	int err;
 
 	disk = alloc_disk(1 << UBD_SHIFT);
-	if (!disk)
-		return -ENOMEM;
+	if(disk == NULL)
+		return(-ENOMEM);
 
 	disk->major = major;
 	disk->first_minor = unit << UBD_SHIFT;
 	disk->fops = &ubd_blops;
 	set_capacity(disk, size / 512);
-	sprintf(disk->disk_name, "ubd");
-	sprintf(disk->devfs_name, "ubd/disc%d", unit);
+	if(major == MAJOR_NR){
+		sprintf(disk->disk_name, "ubd%d", unit);
+		sprintf(disk->devfs_name, "ubd/disc%d", unit);
+		sprintf(from, "ubd/%d", unit);
+		sprintf(to, "disc%d/disc", unit);
+		err = devfs_mk_symlink(from, to);
+		if(err)
+			printk("ubd_new_disk failed to make link from %s to "
+			       "%s, error = %d\n", from, to, err);
+	}
+	else {
+		sprintf(disk->disk_name, "ubd_fake%d", unit);
+		sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
+	}
 
 	disk->private_data = &ubd_dev[unit];
 	disk->queue = ubd_queue;
@@ -506,10 +555,7 @@ static int ubd_add(int n)
 	struct ubd *dev = &ubd_dev[n];
 	int err;
 
-	if(dev->is_dir)
-		return(-EISDIR);
-
-	if (!dev->file)
+	if(dev->file == NULL)
 		return(-ENODEV);
 
 	if (ubd_open_dev(dev))
@@ -523,7 +569,7 @@ static int ubd_add(int n)
 	if(err) 
 		return(err);
  
-	if(fake_major)
+	if(fake_major != MAJOR_NR)
 		ubd_new_disk(fake_major, dev->size, n, 
 			     &fake_gendisk[n]);
 
@@ -561,42 +607,42 @@ static int ubd_config(char *str)
 	return(err);
 }
 
-static int ubd_get_config(char *dev, char *str, int size, char **error_out)
+static int ubd_get_config(char *name, char *str, int size, char **error_out)
 {
-	struct ubd *ubd;
+	struct ubd *dev;
 	char *end;
-	int major, n = 0;
+	int n, len = 0;
 
-	major = simple_strtoul(dev, &end, 0);
-	if((*end != '\0') || (end == dev)){
-		*error_out = "ubd_get_config : didn't parse major number";
+	n = simple_strtoul(name, &end, 0);
+	if((*end != '\0') || (end == name)){
+		*error_out = "ubd_get_config : didn't parse device number";
 		return(-1);
 	}
 
-	if((major >= MAX_DEV) || (major < 0)){
-		*error_out = "ubd_get_config : major number out of range";
+	if((n >= MAX_DEV) || (n < 0)){
+		*error_out = "ubd_get_config : device number out of range";
 		return(-1);
 	}
 
-	ubd = &ubd_dev[major];
+	dev = &ubd_dev[n];
 	spin_lock(&ubd_lock);
 
-	if(ubd->file == NULL){
-		CONFIG_CHUNK(str, size, n, "", 1);
+	if(dev->file == NULL){
+		CONFIG_CHUNK(str, size, len, "", 1);
 		goto out;
 	}
 
-	CONFIG_CHUNK(str, size, n, ubd->file, 0);
+	CONFIG_CHUNK(str, size, len, dev->file, 0);
 
-	if(ubd->cow.file != NULL){
-		CONFIG_CHUNK(str, size, n, ",", 0);
-		CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
+	if(dev->cow.file != NULL){
+		CONFIG_CHUNK(str, size, len, ",", 0);
+		CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
 	}
-	else CONFIG_CHUNK(str, size, n, "", 1);
+	else CONFIG_CHUNK(str, size, len, "", 1);
 
  out:
 	spin_unlock(&ubd_lock);
-	return(n);
+	return(len);
 }
 
 static int ubd_remove(char *str)
@@ -604,11 +650,9 @@ static int ubd_remove(char *str)
 	struct ubd *dev;
 	int n, err = -ENODEV;
 
-	if(!isdigit(*str))
-		return(err);	/* it should be a number 0-7/a-h */
+	n = parse_unit(&str);
 
-	n = *str - '0';
-	if(n >= MAX_DEV) 
+	if((n < 0) || (n >= MAX_DEV))
 		return(err);
 
 	dev = &ubd_dev[n];
@@ -669,7 +713,7 @@ int ubd_init(void)
 		
 	elevator_init(ubd_queue, &elevator_noop);
 
-	if (fake_major != 0) {
+	if (fake_major != MAJOR_NR) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
@@ -714,15 +758,9 @@ static int ubd_open(struct inode *inode,
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ubd *dev = disk->private_data;
-	int err = -EISDIR;
-
-	if(dev->is_dir == 1)
-		goto out;
+	int err = 0;
 
-	err = 0;
 	if(dev->count == 0){
-		dev->openflags = dev->boot_openflags;
-
 		err = ubd_open_dev(dev);
 		if(err){
 			printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
@@ -796,15 +834,6 @@ static int prepare_request(struct reques
 
 	if(req->rq_status == RQ_INACTIVE) return(1);
 
-	if(dev->is_dir){
-		strcpy(req->buffer, "HOSTFS:");
-		strcat(req->buffer, dev->file);
- 		spin_lock(&ubd_io_lock);
-		end_request(req, 1);
- 		spin_unlock(&ubd_io_lock);
-		return(1);
-	}
-
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
 		printk("Write attempted on readonly ubd device %s\n", 
 		       disk->disk_name);
diff -puN arch/um/drivers/ubd_user.c~uml-update arch/um/drivers/ubd_user.c
--- 25/arch/um/drivers/ubd_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/ubd_user.c	Fri Sep 12 11:39:06 2003
@@ -24,142 +24,24 @@
 #include "user.h"
 #include "ubd_user.h"
 #include "os.h"
+#include "cow.h"
 
 #include <endian.h>
 #include <byteswap.h>
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x)  bswap_64(x)
-# define htonll(x)  bswap_64(x)
-#else
-#error "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
-	int magic;
-	int version;
-	char backing_file[PATH_LEN_V1];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
-	unsigned long magic;
-	unsigned long version;
-	char backing_file[PATH_LEN_V2];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-union cow_header {
-	struct cow_header_v1 v1;
-	struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset, 
-		  unsigned long *bitmap_len_out, int *data_offset_out)
-{
-	*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
-	*data_offset_out = bitmap_offset + *bitmap_len_out;
-	*data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
-	*data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out, 
-			   time_t *mtime_out, __u64 *size_out, 
-			   int *sectorsize_out, int *bitmap_offset_out)
-{
-	union cow_header *header;
-	char *file;
-	int err, n;
-	unsigned long version, magic;
-
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("read_cow_header - Failed to allocate header\n");
-		return(-ENOMEM);
-	}
-	err = -EINVAL;
-	n = read(fd, header, sizeof(*header));
-	if(n < offsetof(typeof(header->v1), backing_file)){
-		printk("read_cow_header - short header\n");
-		goto out;
-	}
-
-	magic = header->v1.magic;
-	if(magic == COW_MAGIC) {
-		version = header->v1.version;
-	}
-	else if(magic == ntohl(COW_MAGIC)){
-		version = ntohl(header->v1.version);
-	}
-	else goto out;
-
-	*magic_out = COW_MAGIC;
-
-	if(version == 1){
-		if(n < sizeof(header->v1)){
-			printk("read_cow_header - failed to read V1 header\n");
-			goto out;
-		}
-		*mtime_out = header->v1.mtime;
-		*size_out = header->v1.size;
-		*sectorsize_out = header->v1.sectorsize;
-		*bitmap_offset_out = sizeof(header->v1);
-		file = header->v1.backing_file;
-	}
-	else if(version == 2){
-		if(n < sizeof(header->v2)){
-			printk("read_cow_header - failed to read V2 header\n");
-			goto out;
-		}
-		*mtime_out = ntohl(header->v2.mtime);
-		*size_out = ntohll(header->v2.size);
-		*sectorsize_out = ntohl(header->v2.sectorsize);
-		*bitmap_offset_out = sizeof(header->v2);
-		file = header->v2.backing_file;
-	}
-	else {
-		printk("read_cow_header - invalid COW version\n");
-		goto out;
-	}
-	err = -ENOMEM;
-	*backing_file_out = uml_strdup(file);
-	if(*backing_file_out == NULL){
-		printk("read_cow_header - failed to allocate backing file\n");
-		goto out;
-	}
-	err = 0;
- out:
-	kfree(header);
-	return(err);
-}
 
 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 {
-	struct stat buf1, buf2;
+	struct stat64 buf1, buf2;
 
 	if(from_cmdline == NULL) return(1);
 	if(!strcmp(from_cmdline, from_cow)) return(1);
 
-	if(stat(from_cmdline, &buf1) < 0){
+	if(stat64(from_cmdline, &buf1) < 0){
 		printk("Couldn't stat '%s', errno = %d\n", from_cmdline, 
 		       errno);
 		return(1);
 	}
-	if(stat(from_cow, &buf2) < 0){
+	if(stat64(from_cow, &buf2) < 0){
 		printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
 		return(1);
 	}
@@ -215,118 +97,6 @@ int read_cow_bitmap(int fd, void *buf, i
 	return(0);
 }
 
-static int absolutize(char *to, int size, char *from)
-{
-	char save_cwd[256], *slash;
-	int remaining;
-
-	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-		printk("absolutize : unable to get cwd - errno = %d\n", errno);
-		return(-1);
-	}
-	slash = strrchr(from, '/');
-	if(slash != NULL){
-		*slash = '\0';
-		if(chdir(from)){
-			*slash = '/';
-			printk("absolutize : Can't cd to '%s' - errno = %d\n",
-			       from, errno);
-			return(-1);
-		}
-		*slash = '/';
-		if(getcwd(to, size) == NULL){
-			printk("absolutize : unable to get cwd of '%s' - "
-			       "errno = %d\n", from, errno);
-			return(-1);
-		}
-		remaining = size - strlen(to);
-		if(strlen(slash) + 1 > remaining){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcat(to, slash);
-	}
-	else {
-		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcpy(to, save_cwd);
-		strcat(to, "/");
-		strcat(to, from);
-	}
-	chdir(save_cwd);
-	return(0);
-}
-
-static int write_cow_header(char *cow_file, int fd, char *backing_file, 
-			    int sectorsize, long long *size)
-{
-        struct cow_header_v2 *header;
-	struct stat64 buf;
-	int err;
-
-	err = os_seek_file(fd, 0);
-	if(err != 0){
-		printk("write_cow_header - lseek failed, errno = %d\n", errno);
-		return(-errno);
-	}
-
-	err = -ENOMEM;
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("Failed to allocate COW V2 header\n");
-		goto out;
-	}
-	header->magic = htonl(COW_MAGIC);
-	header->version = htonl(COW_VERSION);
-
-	err = -EINVAL;
-	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
-		printk("Backing file name \"%s\" is too long - names are "
-		       "limited to %d characters\n", backing_file, 
-		       sizeof(header->backing_file) - 1);
-		goto out_free;
-	}
-
-	if(absolutize(header->backing_file, sizeof(header->backing_file), 
-		      backing_file))
-		goto out_free;
-
-	err = stat64(header->backing_file, &buf);
-	if(err < 0){
-		printk("Stat of backing file '%s' failed, errno = %d\n",
-		       header->backing_file, errno);
-		err = -errno;
-		goto out_free;
-	}
-
-	err = os_file_size(header->backing_file, size);
-	if(err){
-		printk("Couldn't get size of backing file '%s', errno = %d\n",
-		       header->backing_file, -*size);
-		goto out_free;
-	}
-
-	header->mtime = htonl(buf.st_mtime);
-	header->size = htonll(*size);
-	header->sectorsize = htonl(sectorsize);
-
-	err = write(fd, header, sizeof(*header));
-	if(err != sizeof(*header)){
-		printk("Write of header to new COW file '%s' failed, "
-		       "errno = %d\n", cow_file, errno);
-		goto out_free;
-	}
-	err = 0;
- out_free:
-	kfree(header);
- out:
-	return(err);
-}
-
 int open_ubd_file(char *file, struct openflags *openflags, 
 		  char **backing_file_out, int *bitmap_offset_out, 
 		  unsigned long *bitmap_len_out, int *data_offset_out, 
@@ -346,10 +116,17 @@ int open_ubd_file(char *file, struct ope
                 if((fd = os_open_file(file, *openflags, mode)) < 0) 
 			return(fd);
         }
+
+	err = os_lock_file(fd, openflags->w);
+	if(err){
+		printk("Failed to lock '%s', errno = %d\n", file, -err);
+		goto error;
+	}
+	
 	if(backing_file_out == NULL) return(fd);
 
-	err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, 
-			      &sectorsize, bitmap_offset_out);
+	err = read_cow_header(file_reader, &fd, &magic, &backing_file, &mtime, 
+			      &size, &sectorsize, bitmap_offset_out);
 	if(err && (*backing_file_out != NULL)){
 		printk("Failed to read COW header from COW file \"%s\", "
 		       "errno = %d\n", file, err);
@@ -376,12 +153,12 @@ int open_ubd_file(char *file, struct ope
 		if(err) goto error;
 	}
 
-	sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, 
-	      data_offset_out);
+	cow_sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, 
+		  data_offset_out);
 
         return(fd);
  error:
-	close(fd);
+	os_close_file(fd);
 	return(err);
 }
 
@@ -389,10 +166,7 @@ int create_cow_file(char *cow_file, char
 		    int sectorsize, int *bitmap_offset_out, 
 		    unsigned long *bitmap_len_out, int *data_offset_out)
 {
-	__u64 blocks;
-	long zero;
-	int err, fd, i;
-	long long size;
+	int err, fd;
 
 	flags.c = 1;
 	fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
@@ -403,29 +177,12 @@ int create_cow_file(char *cow_file, char
 		goto out;
 	}
 
-	err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
-	if(err) goto out_close;
-
-	blocks = (size + sectorsize - 1) / sectorsize;
-	blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
-	zero = 0;
-	for(i = 0; i < blocks; i++){
-		err = write(fd, &zero, sizeof(zero));
-		if(err != sizeof(zero)){
-			printk("Write of bitmap to new COW file '%s' failed, "
-			       "errno = %d\n", cow_file, errno);
-			goto out_close;
-		}
-	}
-
-	sizes(size, sectorsize, sizeof(struct cow_header_v2), 
-	      bitmap_len_out, data_offset_out);
-	*bitmap_offset_out = sizeof(struct cow_header_v2);
-
-	return(fd);
-
- out_close:
-	close(fd);
+	err = init_cow_file(fd, cow_file, backing_file, sectorsize, 
+			    bitmap_offset_out, bitmap_len_out, 
+			    data_offset_out);
+	if(!err)
+		return(fd);
+	os_close_file(fd);
  out:
 	return(err);
 }
@@ -448,14 +205,6 @@ int write_ubd_fs(int fd, char *buffer, i
 	else return(n);
 }
 
-int ubd_is_dir(char *file)
-{
-	struct stat64 buf;
-
-	if(stat64(file, &buf) < 0) return(0);
-	return(S_ISDIR(buf.st_mode));
-}
-
 void do_io(struct io_thread_req *req)
 {
 	char *buf;
diff -puN arch/um/drivers/xterm.c~uml-update arch/um/drivers/xterm.c
--- 25/arch/um/drivers/xterm.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/xterm.c	Fri Sep 12 11:39:06 2003
@@ -108,7 +108,7 @@ int xterm_open(int input, int output, in
 	}
 	close(fd);
 
-	fd = create_unix_socket(file, sizeof(file));
+	fd = create_unix_socket(file, sizeof(file), 1);
 	if(fd < 0){
 		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
 		       -fd);
diff -puN arch/um/drivers/xterm_kern.c~uml-update arch/um/drivers/xterm_kern.c
--- 25/arch/um/drivers/xterm_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/drivers/xterm_kern.c	Fri Sep 12 11:39:06 2003
@@ -5,9 +5,12 @@
 
 #include "linux/errno.h"
 #include "linux/slab.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "asm/irq.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "kern_util.h"
 #include "os.h"
 #include "xterm.h"
@@ -19,17 +22,18 @@ struct xterm_wait {
 	int new_fd;
 };
 
-static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct xterm_wait *xterm = data;
 	int fd;
 
 	fd = os_rcv_fd(xterm->fd, &xterm->pid);
 	if(fd == -EAGAIN)
-		return;
+		return(IRQ_NONE);
 
 	xterm->new_fd = fd;
 	up(&xterm->sem);
+	return(IRQ_HANDLED);
 }
 
 int xterm_fd(int socket, int *pid_out)
diff -puN arch/um/dyn.lds.S~uml-update arch/um/dyn.lds.S
--- 25/arch/um/dyn.lds.S~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/dyn.lds.S	Fri Sep 12 11:39:06 2003
@@ -15,7 +15,11 @@ SECTIONS
   . = ALIGN(4096);		/* Init code and data */
   _stext = .;
   __init_begin = .;
-  .text.init : { *(.text.init) }
+  .init.text : { 
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
 
   . = ALIGN(4096);
 
@@ -67,7 +71,7 @@ SECTIONS
 
   #include "asm/common.lds.S"
 
-  .data.init : { *(.data.init) }
+  init.data : { *(.init.data) }
 
   /* Ensure the __preinit_array_start label is properly aligned.  We
      could instead move the label definition inside the section, but
diff -puN /dev/null arch/um/include/irq_kern.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/um/include/irq_kern.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,28 @@
+/* 
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __IRQ_KERN_H__
+#define __IRQ_KERN_H__
+
+#include "linux/interrupt.h"
+
+extern int um_request_irq(unsigned int irq, int fd, int type,
+			  irqreturn_t (*handler)(int, void *, 
+						 struct pt_regs *),
+			  unsigned long irqflags,  const char * devname,
+			  void *dev_id);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN arch/um/include/kern_util.h~uml-update arch/um/include/kern_util.h
--- 25/arch/um/include/kern_util.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/kern_util.h	Fri Sep 12 11:39:06 2003
@@ -63,10 +63,9 @@ extern void init_flush_vm(void);
 extern void *syscall_sp(void *t);
 extern void syscall_trace(void);
 extern int hz(void);
-extern void idle_timer(void);
+extern void uml_idle_timer(void);
 extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
 extern int external_pid(void *t);
-extern int pid_to_processor_id(int pid);
 extern void boot_timer_handler(int sig);
 extern void interrupt_end(void);
 extern void initial_thread_cb(void (*proc)(void *), void *arg);
@@ -90,9 +89,7 @@ extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
 extern void unprotect_kernel_mem(void);
 extern void protect_kernel_mem(void);
-extern void set_kmem_end(unsigned long);
 extern void uml_cleanup(void);
-extern int pid_to_processor_id(int pid);
 extern void set_current(void *t);
 extern void lock_signalled_task(void *t);
 extern void IPI_handler(int cpu);
@@ -101,7 +98,9 @@ extern void *get_init_task(void);
 extern int clear_user_proc(void *buf, int size);
 extern int copy_to_user_proc(void *to, void *from, int size);
 extern int copy_from_user_proc(void *to, void *from, int size);
+extern int strlen_user_proc(char *str);
 extern void bus_handler(int sig, union uml_pt_regs *regs);
+extern void winch(int sig, union uml_pt_regs *regs);
 extern long execute_syscall(void *r);
 extern int smp_sigio_handler(void);
 extern void *get_current(void);
diff -puN arch/um/include/line.h~uml-update arch/um/include/line.h
--- 25/arch/um/include/line.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/line.h	Fri Sep 12 11:39:06 2003
@@ -9,12 +9,14 @@
 #include "linux/list.h"
 #include "linux/workqueue.h"
 #include "linux/tty.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
 struct line_driver {
 	char *name;
+	char *device_name;
 	char *devfs_name;
 	short major;
 	short minor_start;
@@ -67,8 +69,9 @@ struct lines {
 
 #define LINES_INIT(n) {  num :		n }
 
-extern void line_interrupt(int irq, void *data, struct pt_regs *unused);
-extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
+extern irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused);
+extern irqreturn_t line_write_interrupt(int irq, void *data, 
+					struct pt_regs *unused);
 extern void line_close(struct line *lines, struct tty_struct *tty);
 extern int line_open(struct line *lines, struct tty_struct *tty, 
 		     struct chan_opts *opts);
diff -puN arch/um/include/mconsole.h~uml-update arch/um/include/mconsole.h
--- 25/arch/um/include/mconsole.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/mconsole.h	Fri Sep 12 11:39:06 2003
@@ -77,6 +77,7 @@ extern void mconsole_sysrq(struct mc_req
 extern void mconsole_cad(struct mc_request *req);
 extern void mconsole_stop(struct mc_request *req);
 extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
 
 extern int mconsole_get_request(int fd, struct mc_request *req);
 extern int mconsole_notify(char *sock_name, int type, const void *data, 
diff -puN arch/um/include/mem.h~uml-update arch/um/include/mem.h
--- 25/arch/um/include/mem.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/mem.h	Fri Sep 12 11:39:06 2003
@@ -13,7 +13,6 @@ struct vm_reserved {
 };
 
 extern void set_usable_vm(unsigned long start, unsigned long end);
-extern void set_kmem_end(unsigned long new);
 
 #endif
 
diff -puN arch/um/include/mem_user.h~uml-update arch/um/include/mem_user.h
--- 25/arch/um/include/mem_user.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/mem_user.h	Fri Sep 12 11:39:06 2003
@@ -51,9 +51,6 @@ extern unsigned long task_size;
 
 extern int init_mem_user(void);
 extern int create_mem_file(unsigned long len);
-extern void setup_range(int fd, char *driver, unsigned long start,
-			unsigned long pfn, unsigned long total, int need_vm, 
-			struct mem_region *region, void *reserved);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
 extern int init_maps(struct mem_region *region);
diff -puN arch/um/include/os.h~uml-update arch/um/include/os.h
--- 25/arch/um/include/os.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/os.h	Fri Sep 12 11:39:06 2003
@@ -103,10 +103,11 @@ extern int os_accept_connection(int fd);
 extern int os_shutdown_socket(int fd, int r, int w);
 extern void os_close_file(int fd);
 extern int os_rcv_fd(int fd, int *helper_pid_out);
-extern int create_unix_socket(char *file, int len);
+extern int create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_connect_socket(char *name);
 extern int os_file_type(char *file);
 extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_lock_file(int fd, int excl);
 
 extern unsigned long os_process_pc(int pid);
 extern int os_process_parent(int pid);
@@ -120,6 +121,7 @@ extern int os_map_memory(void *virt, int
 extern int os_protect_memory(void *addr, unsigned long len, 
 			     int r, int w, int x);
 extern int os_unmap_memory(void *addr, int len);
+extern void os_flush_stdout(void);
 
 #endif
 
diff -puN arch/um/include/sysdep-i386/sigcontext.h~uml-update arch/um/include/sysdep-i386/sigcontext.h
--- 25/arch/um/include/sysdep-i386/sigcontext.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/sysdep-i386/sigcontext.h	Fri Sep 12 11:39:06 2003
@@ -28,8 +28,8 @@
  */
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
-/* These are General Protection and Page Fault */
-#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(trap) (trap == 14)
 
 #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
 
diff -puN arch/um/include/ubd_user.h~uml-update arch/um/include/ubd_user.h
--- 25/arch/um/include/ubd_user.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/ubd_user.h	Fri Sep 12 11:39:06 2003
@@ -39,7 +39,6 @@ extern int read_ubd_fs(int fd, void *buf
 extern int write_ubd_fs(int fd, char *buffer, int len);
 extern int start_io_thread(unsigned long sp, int *fds_out);
 extern void do_io(struct io_thread_req *req);
-extern int ubd_is_dir(char *file);
 
 static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
diff -puN arch/um/include/user.h~uml-update arch/um/include/user.h
--- 25/arch/um/include/user.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/user.h	Fri Sep 12 11:39:06 2003
@@ -14,7 +14,7 @@ extern void *um_kmalloc_atomic(int size)
 extern void kfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
-
+extern int strlcpy(char *, const char *, int);
 #endif
 
 /*
diff -puN arch/um/include/user_util.h~uml-update arch/um/include/user_util.h
--- 25/arch/um/include/user_util.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/include/user_util.h	Fri Sep 12 11:39:06 2003
@@ -59,7 +59,6 @@ extern int wait_for_stop(int pid, int si
 extern void *add_signal_handler(int sig, void (*handler)(int));
 extern int start_fork_tramp(void *arg, unsigned long temp_stack, 
 			    int clone_flags, int (*tramp)(void *));
-extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
 extern int linux_main(int argc, char **argv);
 extern void set_cmdline(char *cmd);
 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
@@ -90,7 +89,8 @@ extern int arch_handle_signal(int sig, u
 extern int arch_fixup(unsigned long address, void *sc_ptr);
 extern void forward_pending_sigio(int target);
 extern int can_do_skas(void);
- 
+extern void arch_init_thread(void);
+
 #endif
 
 /*
diff -puN arch/um/Kconfig~uml-update arch/um/Kconfig
--- 25/arch/um/Kconfig~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/Kconfig	Fri Sep 12 11:39:06 2003
@@ -61,6 +61,20 @@ config MODE_SKAS
 
 config NET
 	bool "Networking support"
+	help
+	Unless you really know what you are doing, you should say Y here.
+	The reason is that some programs need kernel networking support even
+	when running on a stand-alone machine that isn't connected to any
+	other computer. If you are upgrading from an older kernel, you
+	should consider updating your networking tools too because changes
+	in the kernel and the tools often go hand in hand. The tools are
+	contained in the package net-tools, the location and version number
+	of which are given in Documentation/Changes.
+
+	For a general introduction to Linux networking, it is highly
+	recommended to read the NET-HOWTO, available from
+	<http://www.tldp.org/docs.html#howto>.
+
 
 source "fs/Kconfig.binfmt"
 
@@ -105,6 +119,16 @@ config MCONSOLE
 config MAGIC_SYSRQ
 	bool "Magic SysRq key"
 	depends on MCONSOLE
+	help
+	If you say Y here, you will have some control over the system even
+	if the system crashes for example during kernel debugging (e.g., you
+	will be able to flush the buffer cache to disk, reboot the system
+	immediately or dump some status information). This is accomplished
+	by pressing various keys while holding SysRq (Alt+PrintScreen). It
+	also works on a serial console (on PC hardware at least), if you
+	send a BREAK and then within 5 seconds a command keypress. The
+	keys are documented in Documentation/sysrq.txt. Don't say Y
+	unless you really know what this hack does.
 
 config HOST_2G_2G
 	bool "2G/2G host address space split"
@@ -239,6 +263,10 @@ config FRAME_POINTER
 config PT_PROXY
 	bool "Enable ptrace proxy"
 	depends on XTERM_CHAN && DEBUG_INFO
+	help
+	This option enables a debugging interface which allows gdb to debug
+	the kernel without needing to actually attach to kernel threads.
+	If you want to do kernel debugging, say Y here; otherwise say N.
 
 config GPROF
 	bool "Enable gprof support"
diff -puN arch/um/Kconfig_block~uml-update arch/um/Kconfig_block
--- 25/arch/um/Kconfig_block~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/Kconfig_block	Fri Sep 12 11:39:06 2003
@@ -29,6 +29,20 @@ config BLK_DEV_UBD_SYNC
         wise choice too.  In all other cases (for example, if you're just
         playing around with User-Mode Linux) you can choose N.
 
+# Turn this back on when the driver actually works
+#
+#config BLK_DEV_COW
+#	tristate "COW block device"
+#	help
+#	This is a layered driver which sits above two other block devices.
+#	One is read-only, and the other is a read-write layer which stores
+#	all changes.  This provides the illusion that the read-only layer
+#	can be mounted read-write and changed.
+
+config BLK_DEV_COW_COMMON
+	bool
+	default BLK_DEV_COW || BLK_DEV_UBD
+
 config BLK_DEV_LOOP
 	tristate "Loopback device support"
 
diff -puN arch/um/Kconfig_net~uml-update arch/um/Kconfig_net
--- 25/arch/um/Kconfig_net~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/Kconfig_net	Fri Sep 12 11:39:06 2003
@@ -1,5 +1,5 @@
 
-menu "Network Devices"
+menu "UML Network Devices"
 	depends on NET
 
 # UML virtual driver
@@ -176,73 +176,5 @@ config UML_NET_SLIRP
 	
         Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
 
-
-# Below are hardware-independent drivers mirrored from
-# drivers/net/Config.in. It would be nice if Linux
-# had HW independent drivers separated from the other
-# but it does not. Until then each non-ISA/PCI arch
-# needs to provide it's own menu of network drivers
-config DUMMY
-	tristate "Dummy net driver support"
-
-config BONDING
-	tristate "Bonding driver support"
-
-config EQUALIZER
-	tristate "EQL (serial line load balancing) support"
-
-config TUN
-	tristate "Universal TUN/TAP device driver support"
-
-config ETHERTAP
-	tristate "Ethertap network tap (OBSOLETE)"
-	depends on EXPERIMENTAL && NETLINK
-
-config PPP
-	tristate "PPP (point-to-point protocol) support"
-
-config PPP_MULTILINK
-	bool "PPP multilink support (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config PPP_FILTER
-	bool "PPP filtering"
-	depends on PPP && FILTER
-
-config PPP_ASYNC
-	tristate "PPP support for async serial ports"
-	depends on PPP
-
-config PPP_SYNC_TTY
-	tristate "PPP support for sync tty ports"
-	depends on PPP
-
-config PPP_DEFLATE
-	tristate "PPP Deflate compression"
-	depends on PPP
-
-config PPP_BSDCOMP
-	tristate "PPP BSD-Compress compression"
-	depends on PPP
-
-config PPPOE
-	tristate "PPP over Ethernet (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config SLIP
-	tristate "SLIP (serial line) support"
-
-config SLIP_COMPRESSED
-	bool "CSLIP compressed headers"
-	depends on SLIP=y
-
-config SLIP_SMART
-	bool "Keepalive and linefill"
-	depends on SLIP=y
-
-config SLIP_MODE_SLIP6
-	bool "Six bit SLIP encapsulation"
-	depends on SLIP=y
-
 endmenu
 
diff -puN arch/um/kernel/config.c.in~uml-update arch/um/kernel/config.c.in
--- 25/arch/um/kernel/config.c.in~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/config.c.in	Fri Sep 12 11:39:06 2003
@@ -7,9 +7,7 @@
 #include <stdlib.h>
 #include "init.h"
 
-static __initdata char *config = "
-CONFIG
-";
+static __initdata char *config = "CONFIG";
 
 static int __init print_config(char *line, int *add)
 {
diff -puN arch/um/kernel/init_task.c~uml-update arch/um/kernel/init_task.c
--- 25/arch/um/kernel/init_task.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/init_task.c	Fri Sep 12 11:39:06 2003
@@ -17,6 +17,7 @@ static struct fs_struct init_fs = INIT_F
 struct mm_struct init_mm = INIT_MM(init_mm);
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 
 /*
  * Initial task structure.
@@ -38,26 +39,12 @@ union thread_union init_thread_union 
 __attribute__((__section__(".data.init_task"))) = 
 { INIT_THREAD_INFO(init_task) };
 
-struct task_struct *alloc_task_struct(void)
-{
-	return((struct task_struct *) 
-	       __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
-}
-
 void unprotect_stack(unsigned long stack)
 {
 	protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 
 		       1, 1, 0, 1);
 }
 
-void free_task_struct(struct task_struct *task)
-{
-	/* free_pages decrements the page counter and only actually frees
-	 * the pages if they are now not accessed by anything.
-	 */
-	free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
-}
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/kernel/irq.c~uml-update arch/um/kernel/irq.c
--- 25/arch/um/kernel/irq.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/irq.c	Fri Sep 12 11:39:06 2003
@@ -28,6 +28,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static void register_irq_proc (unsigned int irq);
 
@@ -82,65 +83,52 @@ struct hw_interrupt_type no_irq_type = {
 	end_none
 };
 
-/* Not changed */
-volatile unsigned long irq_err_count;
-
 /*
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
-	unsigned long flags;
 	struct irqaction * action;
-	char *p = buf;
+	unsigned long flags;
 
-	p += sprintf(p, "           ");
-	for (j=0; j<num_online_cpus(); j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+	seq_printf(p, "           ");
+	for (j=0; j<NR_CPUS; j++)
+		if (cpu_online(j))
+			seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			goto end;
-		p += sprintf(p, "%3d: ",i);
+			goto skip;
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < num_online_cpus(); j++)
-			p += sprintf(p, "%10u ",
-				kstat_cpu(cpu_logical_map(j)).irqs[i]);
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
-	end:
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
-	p += sprintf(p, "\n");
-#ifdef notdef
-#ifdef CONFIG_SMP
-	p += sprintf(p, "LOC: ");
-	for (j = 0; j < num_online_cpus(); j++)
-		p += sprintf(p, "%10u ",
-			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
-#endif
-#endif
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
-	return p - buf;
-}
+	seq_printf(p, "NMI: ");
+	for (j = 0; j < NR_CPUS; j++)
+		if (cpu_online(j))
+			seq_printf(p, "%10u ", nmi_count(j));
+	seq_putc(p, '\n');
 
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	return(0);
+	return 0;
 }
 
 /*
@@ -281,13 +269,12 @@ unsigned int do_IRQ(int irq, union uml_p
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
 
 	irq_enter();
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_this_cpu.irqs[irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
@@ -384,7 +371,7 @@ out:
  */
  
 int request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags, 
 		const char * devname,
 		void *dev_id)
@@ -430,15 +417,19 @@ int request_irq(unsigned int irq,
 }
 
 int um_request_irq(unsigned int irq, int fd, int type,
-		   void (*handler)(int, void *, struct pt_regs *),
+		   irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		   unsigned long irqflags, const char * devname,
 		   void *dev_id)
 {
-	int retval;
+	int err;
 
-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
-	if(retval) return(retval);
-	return(activate_fd(irq, fd, type, dev_id));
+	err = request_irq(irq, handler, irqflags, devname, dev_id);
+	if(err) 
+		return(err);
+
+	if(fd != -1)
+		err = activate_fd(irq, fd, type, dev_id);
+	return(err);
 }
 
 /* this was setup_x86_irq but it seems pretty generic */
@@ -654,7 +645,7 @@ static int prof_cpu_mask_read_proc (char
 		return -EINVAL;
 	tmp = *mask;
 	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", cpus_coerce(tmp));
+		int j = sprintf(page, "%04hx", (short) cpus_coerce(tmp));
 		len += j;
 		page += j;
 		cpus_shift_right(tmp, tmp, 16);
diff -puN arch/um/kernel/Makefile~uml-update arch/um/kernel/Makefile
--- 25/arch/um/kernel/Makefile~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/Makefile	Fri Sep 12 11:39:06 2003
@@ -21,6 +21,8 @@ obj-$(CONFIG_TTY_LOG)	+= tty_log.o
 obj-$(CONFIG_MODE_TT) += tt/
 obj-$(CONFIG_MODE_SKAS) += skas/
 
+clean-files	:= config.c
+
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(filter %_user.o,$(obj-y))  $(user-objs-y) config.o helper.o \
@@ -45,17 +47,13 @@ $(USER_OBJS) : %.o: %.c
 $(obj)/frame.o: $(src)/frame.c
 	$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
 
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
 
 $(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
 	$(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
 
 $(obj)/config.o : $(obj)/config.c
 
-clean:
-	rm -f config.c
-	for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-
 modules:
 
 fastdep:
diff -puN arch/um/kernel/mem.c~uml-update arch/um/kernel/mem.c
--- 25/arch/um/kernel/mem.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/mem.c	Fri Sep 12 11:39:06 2003
@@ -119,11 +119,6 @@ unsigned long get_kmem_end(void)
 	return(kmem_top);
 }
 
-void set_kmem_end(unsigned long new)
-{
-	kmem_top = new;
-}
-
 #ifdef CONFIG_HIGHMEM
 /* Changed during early boot */
 pte_t *kmap_pte;
@@ -218,7 +213,7 @@ static int setup_one_range(int fd, char 
 		if(regions[i] == NULL) break;		
 	}
 	if(i == NREGIONS){
-		printk("setup_range : no free regions\n");
+		printk("setup_one_range : no free regions\n");
 		i = -1;
 		goto out;
 	}
@@ -227,7 +222,9 @@ static int setup_one_range(int fd, char 
 		fd = create_mem_file(len);
 
 	if(region == NULL){
-		region = alloc_bootmem_low_pages(sizeof(*region));
+		if(kmalloc_ok)
+			region = kmalloc(sizeof(*region), GFP_KERNEL);
+		else region = alloc_bootmem_low_pages(sizeof(*region));
 		if(region == NULL)
 			panic("Failed to allocating mem_region");
 	}
@@ -528,9 +525,9 @@ int nregions(void)
 	return(NREGIONS);
 }
 
-void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
-		 unsigned long len, int need_vm, struct mem_region *region, 
-		 void *reserved)
+static void setup_range(int fd, char *driver, unsigned long start, 
+			unsigned long pfn, unsigned long len, int need_vm, 
+			struct mem_region *region, void *reserved)
 {
 	int i, cur;
 
diff -puN arch/um/kernel/mem_user.c~uml-update arch/um/kernel/mem_user.c
--- 25/arch/um/kernel/mem_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/mem_user.c	Fri Sep 12 11:39:06 2003
@@ -111,6 +111,11 @@ int setup_region(struct mem_region *regi
 		offset = 0;
 	}
 
+	if(offset >= region->len){
+		printf("%ld bytes of physical memory is insufficient\n",
+		       region->len);
+		exit(1);
+	}
 	loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE, 
 		   MAP_SHARED | MAP_FIXED, region->fd, offset);
 	if(loc != start){
@@ -122,26 +127,26 @@ int setup_region(struct mem_region *regi
 
 static int __init parse_iomem(char *str, int *add)
 {
-	struct stat buf;
+	struct stat64 buf;
 	char *file, *driver;
 	int fd;
 
 	driver = str;
 	file = strchr(str,',');
 	if(file == NULL){
-		printk("parse_iomem : failed to parse iomem\n");
+		printf("parse_iomem : failed to parse iomem\n");
 		return(1);
 	}
 	*file = '\0';
 	file++;
 	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("parse_iomem - Couldn't open io file, errno = %d\n", 
+		printf("parse_iomem - Couldn't open io file, errno = %d\n", 
 		       errno);
 		return(1);
 	}
-	if(fstat(fd, &buf) < 0) {
-		printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
+	if(fstat64(fd, &buf) < 0) {
+		printf("parse_iomem - cannot fstat file, errno = %d\n", errno);
 		return(1);
 	}
 	add_iomem(driver, fd, buf.st_size);
diff -puN arch/um/kernel/process.c~uml-update arch/um/kernel/process.c
--- 25/arch/um/kernel/process.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/process.c	Fri Sep 12 11:39:06 2003
@@ -72,7 +72,6 @@ void init_new_thread_signals(int altstac
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
 		    SA_NOMASK | flags, -1);
-	(void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
 	signal(SIGHUP, SIG_IGN);
 
 	init_irq_signals(altstack);
@@ -127,7 +126,8 @@ int start_fork_tramp(void *thread_arg, u
 	if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", 
 			  errno);
 	if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
-		panic("outer trampoline didn't exit with SIGKILL");
+		panic("outer trampoline didn't exit with SIGKILL, "
+		      "status = %d", status);
 
 	return(arg.pid);
 }
diff -puN arch/um/kernel/process_kern.c~uml-update arch/um/kernel/process_kern.c
--- 25/arch/um/kernel/process_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/process_kern.c	Fri Sep 12 11:39:06 2003
@@ -52,17 +52,12 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [
 
 struct task_struct *get_task(int pid, int require)
 {
-        struct task_struct *task, *ret;
+        struct task_struct *ret;
 
-        ret = NULL;
         read_lock(&tasklist_lock);
-        for_each_process(task){
-                if(task->pid == pid){
-                        ret = task;
-                        break;
-                }
-        }
+	ret = find_task_by_pid(pid);
         read_unlock(&tasklist_lock);
+
         if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
         return(ret);
 }
@@ -103,13 +98,14 @@ unsigned long alloc_stack(int order, int
 
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	struct task_struct *p;
+	int pid;
 
 	current->thread.request.u.thread.proc = fn;
 	current->thread.request.u.thread.arg = arg;
-	p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
-	return(p->pid);
+	pid = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
+	if(pid < 0)
+		panic("do_fork failed in kernel_thread, errno = %d", pid);
+	return(pid);
 }
 
 void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
@@ -129,7 +125,7 @@ void set_current(void *t)
 		{ external_pid(task), task });
 }
 
-void *switch_to(void *prev, void *next, void *last)
+void *_switch_to(void *prev, void *next, void *last)
 {
 	return(CHOOSE_MODE(switch_to_tt(prev, next), 
 			   switch_to_skas(prev, next)));
@@ -149,7 +145,7 @@ void release_thread(struct task_struct *
 void exit_thread(void)
 {
 	CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 }
  
 void *get_current(void)
@@ -157,6 +153,10 @@ void *get_current(void)
 	return(current);
 }
 
+void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		unsigned long stack_top, struct task_struct * p, 
 		struct pt_regs *regs)
@@ -190,7 +190,7 @@ int current_pid(void)
 
 void default_idle(void)
 {
-	idle_timer();
+	uml_idle_timer();
 
 	atomic_inc(&init_mm.mm_count);
 	current->mm = &init_mm;
@@ -363,10 +363,15 @@ int clear_user_proc(void *buf, int size)
 	return(clear_user(buf, size));
 }
 
+int strlen_user_proc(char *str)
+{
+	return(strlen_user(str));
+}
+
 int smp_sigio_handler(void)
 {
 #ifdef CONFIG_SMP
-	int cpu = current->thread_info->cpu;
+	int cpu = current_thread->cpu;
 	IPI_handler(cpu);
 	if(cpu != 0)
 		return(1);
@@ -381,7 +386,7 @@ int um_in_interrupt(void)
 
 int cpu(void)
 {
-	return(current->thread_info->cpu);
+	return(current_thread->cpu);
 }
 
 /*
diff -puN arch/um/kernel/ptrace.c~uml-update arch/um/kernel/ptrace.c
--- 25/arch/um/kernel/ptrace.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/ptrace.c	Fri Sep 12 11:39:06 2003
@@ -311,11 +311,8 @@ void syscall_trace(void)
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
- 	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- 					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff -puN arch/um/kernel/sigio_kern.c~uml-update arch/um/kernel/sigio_kern.c
--- 25/arch/um/kernel/sigio_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/sigio_kern.c	Fri Sep 12 11:39:06 2003
@@ -6,18 +6,21 @@
 #include "linux/kernel.h"
 #include "linux/list.h"
 #include "linux/slab.h"
-#include "asm/irq.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "init.h"
 #include "sigio.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 /* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
 
-void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	read_sigio_fd(sigio_irq_fd);
 	reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 int write_sigio_irq(int fd)
diff -puN arch/um/kernel/signal_kern.c~uml-update arch/um/kernel/signal_kern.c
--- 25/arch/um/kernel/signal_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/signal_kern.c	Fri Sep 12 11:39:06 2003
@@ -36,7 +36,7 @@ static void force_segv(int sig)
 	if(sig == SIGSEGV){
 		struct k_sigaction *ka;
 
-		ka = &current->sig->action[SIGSEGV - 1];
+		ka = &current->sighand->action[SIGSEGV - 1];
 		ka->sa.sa_handler = SIG_DFL;
 	}
 	force_sig(SIGSEGV, current);
@@ -142,7 +142,7 @@ static int kern_do_signal(struct pt_regs
 		return(0);
 
 	/* Whee!  Actually deliver the signal.  */
-	ka = &current->sig->action[sig -1 ];
+	ka = &current->sighand->action[sig -1 ];
 	err = handle_signal(regs, sig, ka, &info, oldset, error);
 	if(!err) return(1);
 
@@ -201,7 +201,7 @@ int sys_sigsuspend(int history0, int his
 	}
 }
 
-int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 {
 	sigset_t saveset, newset;
 
@@ -227,6 +227,42 @@ int sys_rt_sigsuspend(sigset_t *unewset,
 	}
 }
 
+int sys_sigaction(int sig, const struct old_sigaction __user *act,
+			 struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
+}
+
 static int copy_sc_from_user(struct pt_regs *to, void *from, 
 			     struct arch_frame_data *arch)
 {
@@ -239,8 +275,8 @@ static int copy_sc_from_user(struct pt_r
 
 int sys_sigreturn(struct pt_regs regs)
 {
-	void *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
-	void *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
+	void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
+	void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
 	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -257,7 +293,8 @@ int sys_sigreturn(struct pt_regs regs)
 
 int sys_rt_sigreturn(struct pt_regs regs)
 {
-	struct ucontext *uc = sp_to_uc(PT_REGS_SP(&current->thread.regs));
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct ucontext __user *uc = sp_to_uc(sp);
 	void *fp;
 	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
 
diff -puN arch/um/kernel/skas/include/mode.h~uml-update arch/um/kernel/skas/include/mode.h
--- 25/arch/um/kernel/skas/include/mode.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/skas/include/mode.h	Fri Sep 12 11:39:06 2003
@@ -20,6 +20,7 @@ extern void sig_handler_common_skas(int 
 extern void halt_skas(void);
 extern void reboot_skas(void);
 extern void kill_off_processes_skas(void);
+extern int is_skas_winch(int pid, int fd, void *data);
 
 #endif
 
diff -puN arch/um/kernel/skas/include/uaccess.h~uml-update arch/um/kernel/skas/include/uaccess.h
--- 25/arch/um/kernel/skas/include/uaccess.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/skas/include/uaccess.h	Fri Sep 12 11:39:06 2003
@@ -19,7 +19,7 @@
 #define access_ok_skas(type, addr, size) \
 	((segment_eq(get_fs(), KERNEL_DS)) || \
 	 (((unsigned long) (addr) < TASK_SIZE) && \
-	  ((unsigned long) (addr) + (size) < TASK_SIZE)))
+	  ((unsigned long) (addr) + (size) <= TASK_SIZE)))
 
 static inline int verify_area_skas(int type, const void * addr, 
 				   unsigned long size)
diff -puN arch/um/kernel/skas/Makefile~uml-update arch/um/kernel/skas/Makefile
--- 25/arch/um/kernel/skas/Makefile~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/skas/Makefile	Fri Sep 12 11:39:06 2003
@@ -7,18 +7,22 @@ obj-y = exec_kern.o exec_user.o mem.o me
 	process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
 	sys-$(SUBARCH)/
 
+host-progs	:= util/mk_ptregs
+clean-files	:= include/skas_ptregs.h
+
 USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-include/skas_ptregs.h : util/mk_ptregs
-	util/mk_ptregs > $@
-
-util/mk_ptregs :
-	$(MAKE) -C util
+$(TOPDIR)/arch/um/include/skas_ptregs.h : $(src)/util/mk_ptregs
+	@echo -n '  Generating $@'
+	@$< > $@.tmp
+	@if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+		echo ' (unchanged)'; \
+		rm -f $@.tmp; \
+	else \
+		echo ' (updated)'; \
+		mv -f $@.tmp $@; \
+	fi
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-	$(MAKE) -C util clean
-	$(RM) -f include/skas_ptregs.h
diff -puN arch/um/kernel/skas/process.c~uml-update arch/um/kernel/skas/process.c
--- 25/arch/um/kernel/skas/process.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/skas/process.c	Fri Sep 12 11:39:06 2003
@@ -4,6 +4,7 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <signal.h>
 #include <setjmp.h>
@@ -24,6 +25,16 @@
 #include "os.h"
 #include "proc_mm.h"
 #include "skas_ptrace.h"
+#include "chan_user.h"
+
+int is_skas_winch(int pid, int fd, void *data)
+{
+	if(pid != getpid())
+		return(0);
+
+	register_winch_irq(-1, fd, -1, data);
+	return(1);
+}
 
 unsigned long exec_regs[FRAME_SIZE];
 unsigned long exec_fp_regs[HOST_FP_SIZE];
@@ -48,11 +59,11 @@ static void handle_trap(int pid, union u
 	int err, syscall_nr, status;
 
 	syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+	UPT_SYSCALL_NR(regs) = syscall_nr;
 	if(syscall_nr < 1){
 		relay_signal(SIGTRAP, regs);
 		return;
 	}
-	UPT_SYSCALL_NR(regs) = syscall_nr;
 
 	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
 	if(err < 0)
@@ -72,8 +83,6 @@ static void handle_trap(int pid, union u
 	handle_syscall(regs);
 }
 
-int userspace_pid;
-
 static int userspace_tramp(void *arg)
 {
 	init_new_thread_signals(0);
@@ -83,6 +92,8 @@ static int userspace_tramp(void *arg)
 	return(0);
 }
 
+int userspace_pid;
+
 void start_userspace(void)
 {
 	void *stack;
@@ -149,6 +160,7 @@ void userspace(union uml_pt_regs *regs)
 			case SIGILL:
 			case SIGBUS:
 			case SIGFPE:
+			case SIGWINCH:
 				user_signal(WSTOPSIG(status), regs);
 				break;
 			default:
@@ -328,7 +340,8 @@ void reboot_skas(void)
 int new_mm(int from)
 {
 	struct proc_mm_op copy;
-	int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
+	int n, fd = os_open_file("/proc/mm", 
+				 of_cloexec(of_write(OPENFLAGS())), 0);
 
 	if(fd < 0)
 		return(-errno);
@@ -342,6 +355,7 @@ int new_mm(int from)
 			printk("new_mm : /proc/mm copy_segments failed, "
 			       "errno = %d\n", errno);
 	}
+
 	return(fd);
 }
 
diff -puN arch/um/kernel/skas/process_kern.c~uml-update arch/um/kernel/skas/process_kern.c
--- 25/arch/um/kernel/skas/process_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/skas/process_kern.c	Fri Sep 12 11:39:06 2003
@@ -61,9 +61,8 @@ void new_thread_handler(int sig)
 	thread_wait(&current->thread.mode.skas.switch_buf, 
 		    current->thread.mode.skas.fork_buf);
 
-#ifdef CONFIG_SMP
-	schedule_tail(NULL);
-#endif
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 
 	n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
@@ -93,9 +92,8 @@ void fork_handler(int sig)
 		    current->thread.mode.skas.fork_buf);
   	
 	force_flush_all();
-#ifdef CONFIG_SMP
-	schedule_tail(current->thread.prev_sched);
-#endif
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 	unblock_signals();
 
@@ -136,7 +134,7 @@ int copy_thread_skas(int nr, unsigned lo
 
 void init_idle_skas(void)
 {
-	cpu_tasks[current->thread_info->cpu].pid = os_getpid();
+	cpu_tasks[current_thread->cpu].pid = os_getpid();
 	default_idle();
 }
 
@@ -164,7 +162,7 @@ int start_uml_skas(void)
 	capture_signal_stack();
 
 	init_new_thread_signals(1);
-	idle_timer();
+	uml_idle_timer();
 
 	init_task.thread.request.u.thread.proc = start_kernel_proc;
 	init_task.thread.request.u.thread.arg = NULL;
diff -puN arch/um/kernel/skas/util/mk_ptregs.c~uml-update arch/um/kernel/skas/util/mk_ptregs.c
--- 25/arch/um/kernel/skas/util/mk_ptregs.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/skas/util/mk_ptregs.c	Fri Sep 12 11:39:06 2003
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff -puN arch/um/kernel/smp.c~uml-update arch/um/kernel/smp.c
--- 25/arch/um/kernel/smp.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/smp.c	Fri Sep 12 11:39:06 2003
@@ -22,7 +22,7 @@
 #include "os.h"
 
 /* CPU online map, set by smp_boot_cpus */
-unsigned long cpu_online_map = cpumask_of_cpu(0);
+unsigned long cpu_online_map = CPU_MASK_NONE;
 
 /* Per CPU bogomips and other parameters
  * The only piece used here is the ipi pipe, which is set before SMP is
@@ -97,15 +97,15 @@ void smp_send_stop(void)
 
 	printk(KERN_INFO "Stopping all CPUs...");
 	for(i = 0; i < num_online_cpus(); i++){
-		if(i == current->thread_info->cpu)
+		if(i == current_thread->cpu)
 			continue;
 		write(cpu_data[i].ipi_pipe[1], "S", 1);
 	}
 	printk("done\n");
 }
 
-static cpumask_t smp_commenced_mask;
-static cpumask_t smp_callin_map = CPU_MASK_NONE;
+static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+static cpumask_t cpu_callin_map = CPU_MASK_NONE;
 
 static int idle_proc(void *cpup)
 {
@@ -120,12 +120,12 @@ static int idle_proc(void *cpup)
 		     current->thread.mode.tt.extern_pid);
  
 	wmb();
-	if (cpu_test_and_set(cpu, &smp_callin_map)) {
+	if (cpu_test_and_set(cpu, cpu_callin_map)) {
 		printk("huh, CPU#%d already present??\n", cpu);
 		BUG();
 	}
 
-	while (!cpu_isset(cpu, &smp_commenced_mask))
+	while (!cpu_isset(cpu, smp_commenced_mask))
 		cpu_relax();
 
 	cpu_set(cpu, cpu_online_map);
@@ -140,8 +140,11 @@ static struct task_struct *idle_thread(i
 
         current->thread.request.u.thread.proc = idle_proc;
         current->thread.request.u.thread.arg = (void *) cpu;
-	new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
+	new_task = copy_process(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, 
+				NULL);
+	if(IS_ERR(new_task)) 
+		panic("copy_process failed in idle_thread, error = %ld",
+		      PTR_ERR(new_task));
 
 	cpu_tasks[cpu] = ((struct cpu_task) 
 		          { .pid = 	new_task->thread.mode.tt.extern_pid,
@@ -150,6 +153,7 @@ static struct task_struct *idle_thread(i
 	CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, 
 			  sizeof(c)),
 		    ({ panic("skas mode doesn't support SMP"); }));
+	wake_up_forked_process(new_task);
 	return(new_task);
 }
 
@@ -157,15 +161,16 @@ void smp_prepare_cpus(unsigned int maxcp
 {
 	struct task_struct *idle;
 	unsigned long waittime;
-	int err, cpu;
+	int err, cpu, me = smp_processor_id();
 
-	cpu_set(0, cpu_online_map);
-	cpu_set(0, smp_callin_map);
+	cpu_clear(me, cpu_online_map);
+	cpu_set(me, cpu_online_map);
+	cpu_set(me, cpu_callin_map);
 
-	err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
+	err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
 	if(err)	panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
 
-	activate_ipi(cpu_data[0].ipi_pipe[0], 
+	activate_ipi(cpu_data[me].ipi_pipe[0], 
 		     current->thread.mode.tt.extern_pid);
 
 	for(cpu = 1; cpu < ncpus; cpu++){
@@ -177,10 +182,10 @@ void smp_prepare_cpus(unsigned int maxcp
 		unhash_process(idle);
 
 		waittime = 200000000;
-		while (waittime-- && !cpu_isset(cpu, smp_callin_map))
+		while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
 			cpu_relax();
 
-		if (cpu_isset(cpu, smp_callin_map))
+		if (cpu_isset(cpu, cpu_callin_map))
 			printk("done\n");
 		else printk("failed\n");
 	}
@@ -270,7 +275,7 @@ int smp_call_function(void (*_func)(void
 	info = _info;
 
 	for (i=0;i<NR_CPUS;i++)
-		if((i != current->thread_info->cpu) && 
+		if((i != current_thread->cpu) && 
 		   cpu_isset(i, cpu_online_map))
 			write(cpu_data[i].ipi_pipe[1], "C", 1);
 
diff -puN arch/um/kernel/syscall_kern.c~uml-update arch/um/kernel/syscall_kern.c
--- 25/arch/um/kernel/syscall_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/syscall_kern.c	Fri Sep 12 11:39:06 2003
@@ -35,39 +35,40 @@ long um_mount(char * dev_name, char * di
 
 long sys_fork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-        p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+        ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
-long sys_clone(unsigned long clone_flags, unsigned long newsp)
+long sys_clone(unsigned long clone_flags, unsigned long newsp, 
+	       int *parent_tid, int *child_tid)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
+	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 long sys_vfork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
+	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, 
+		      NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 /* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
+long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len,
+	      unsigned long prot, unsigned long flags, unsigned long fd,
+	      unsigned long pgoff)
 {
 	int error = -EBADF;
 	struct file * file = NULL;
@@ -93,7 +94,7 @@ long sys_mmap2(unsigned long addr, unsig
 	       unsigned long prot, unsigned long flags,
 	       unsigned long fd, unsigned long pgoff)
 {
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+	return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
 }
 
 /*
@@ -120,7 +121,8 @@ int old_mmap(unsigned long addr, unsigne
 	if (offset & ~PAGE_MASK)
 		goto out;
 
-	err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+	err = do_mmap2(current->mm, addr, len, prot, flags, fd, 
+		       offset >> PAGE_SHIFT);
  out:
 	return err;
 }
@@ -141,37 +143,6 @@ int sys_pipe(unsigned long * fildes)
         return error;
 }
 
-int sys_sigaction(int sig, const struct old_sigaction *act,
-			 struct old_sigaction *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
-
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
@@ -253,7 +224,7 @@ int sys_ipc (uint call, int first, int s
 		return sys_shmctl (first, second,
 				   (struct shmid_ds *) ptr);
 	default:
-		return -EINVAL;
+		return -ENOSYS;
 	}
 }
 
@@ -302,11 +273,6 @@ int sys_olduname(struct oldold_utsname *
 	return error;
 }
 
-int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-{
-	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
-}
-
 long execute_syscall(void *r)
 {
 	return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
diff -puN arch/um/kernel/sys_call_table.c~uml-update arch/um/kernel/sys_call_table.c
--- 25/arch/um/kernel/sys_call_table.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/sys_call_table.c	Fri Sep 12 11:39:06 2003
@@ -219,15 +219,30 @@ extern syscall_handler_t sys_getdents64;
 extern syscall_handler_t sys_gettid;
 extern syscall_handler_t sys_readahead;
 extern syscall_handler_t sys_tkill;
+extern syscall_handler_t sys_setxattr;
+extern syscall_handler_t sys_lsetxattr;
+extern syscall_handler_t sys_fsetxattr;
+extern syscall_handler_t sys_getxattr;
+extern syscall_handler_t sys_lgetxattr;
+extern syscall_handler_t sys_fgetxattr;
+extern syscall_handler_t sys_listxattr;
+extern syscall_handler_t sys_llistxattr;
+extern syscall_handler_t sys_flistxattr;
+extern syscall_handler_t sys_removexattr;
+extern syscall_handler_t sys_lremovexattr;
+extern syscall_handler_t sys_fremovexattr;
 extern syscall_handler_t sys_sendfile64;
 extern syscall_handler_t sys_futex;
 extern syscall_handler_t sys_sched_setaffinity;
 extern syscall_handler_t sys_sched_getaffinity;
+extern syscall_handler_t sys_set_thread_area;
+extern syscall_handler_t sys_get_thread_area;
 extern syscall_handler_t sys_io_setup;
 extern syscall_handler_t sys_io_destroy;
 extern syscall_handler_t sys_io_getevents;
 extern syscall_handler_t sys_io_submit;
 extern syscall_handler_t sys_io_cancel;
+extern syscall_handler_t sys_fadvise64;
 extern syscall_handler_t sys_exit_group;
 extern syscall_handler_t sys_lookup_dcookie;
 extern syscall_handler_t sys_epoll_create;
@@ -235,6 +250,20 @@ extern syscall_handler_t sys_epoll_ctl;
 extern syscall_handler_t sys_epoll_wait;
 extern syscall_handler_t sys_remap_file_pages;
 extern syscall_handler_t sys_set_tid_address;
+extern syscall_handler_t sys_timer_create;
+extern syscall_handler_t sys_timer_settime;
+extern syscall_handler_t sys_timer_gettime;
+extern syscall_handler_t sys_timer_getoverrun;
+extern syscall_handler_t sys_timer_delete;
+extern syscall_handler_t sys_clock_settime;
+extern syscall_handler_t sys_clock_gettime;
+extern syscall_handler_t sys_clock_getres;
+extern syscall_handler_t sys_clock_nanosleep;
+extern syscall_handler_t sys_statfs64;
+extern syscall_handler_t sys_fstatfs64;
+extern syscall_handler_t sys_tgkill;
+extern syscall_handler_t sys_utimes;
+extern syscall_handler_t sys_fadvise64_64;
 
 #ifdef CONFIG_NFSD
 #define NFSSERVCTL sys_nfsservctl
@@ -246,7 +275,7 @@ extern syscall_handler_t um_mount;
 extern syscall_handler_t um_time;
 extern syscall_handler_t um_stime;
 
-#define LAST_GENERIC_SYSCALL __NR_set_tid_address
+#define LAST_GENERIC_SYSCALL __NR_fadvise64_64
 
 #if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
 #define LAST_SYSCALL LAST_GENERIC_SYSCALL
@@ -455,32 +484,37 @@ syscall_handler_t *sys_call_table[] = {
 	[ __NR_stat64 ] = sys_stat64,
 	[ __NR_lstat64 ] = sys_lstat64,
 	[ __NR_fstat64 ] = sys_fstat64,
-	[ __NR_fcntl64 ] = sys_fcntl64,
 	[ __NR_getdents64 ] = sys_getdents64,
+	[ __NR_fcntl64 ] = sys_fcntl64,
+	[ 223 ] = sys_ni_syscall,
 	[ __NR_gettid ] = sys_gettid,
 	[ __NR_readahead ] = sys_readahead,
-	[ __NR_setxattr ] = sys_ni_syscall,
-	[ __NR_lsetxattr ] = sys_ni_syscall,
-	[ __NR_fsetxattr ] = sys_ni_syscall,
-	[ __NR_getxattr ] = sys_ni_syscall,
-	[ __NR_lgetxattr ] = sys_ni_syscall,
-	[ __NR_fgetxattr ] = sys_ni_syscall,
-	[ __NR_listxattr ] = sys_ni_syscall,
-	[ __NR_llistxattr ] = sys_ni_syscall,
-	[ __NR_flistxattr ] = sys_ni_syscall,
-	[ __NR_removexattr ] = sys_ni_syscall,
-	[ __NR_lremovexattr ] = sys_ni_syscall,
-	[ __NR_fremovexattr ] = sys_ni_syscall,
+	[ __NR_setxattr ] = sys_setxattr,
+	[ __NR_lsetxattr ] = sys_lsetxattr,
+	[ __NR_fsetxattr ] = sys_fsetxattr,
+	[ __NR_getxattr ] = sys_getxattr,
+	[ __NR_lgetxattr ] = sys_lgetxattr,
+	[ __NR_fgetxattr ] = sys_fgetxattr,
+	[ __NR_listxattr ] = sys_listxattr,
+	[ __NR_llistxattr ] = sys_llistxattr,
+	[ __NR_flistxattr ] = sys_flistxattr,
+	[ __NR_removexattr ] = sys_removexattr,
+	[ __NR_lremovexattr ] = sys_lremovexattr,
+	[ __NR_fremovexattr ] = sys_fremovexattr,
 	[ __NR_tkill ] = sys_tkill,
 	[ __NR_sendfile64 ] = sys_sendfile64,
 	[ __NR_futex ] = sys_futex,
 	[ __NR_sched_setaffinity ] = sys_sched_setaffinity,
 	[ __NR_sched_getaffinity ] = sys_sched_getaffinity,
+	[ __NR_set_thread_area ] = sys_ni_syscall,
+	[ __NR_get_thread_area ] = sys_ni_syscall,
 	[ __NR_io_setup ] = sys_io_setup,
 	[ __NR_io_destroy ] = sys_io_destroy,
 	[ __NR_io_getevents ] = sys_io_getevents,
 	[ __NR_io_submit ] = sys_io_submit,
 	[ __NR_io_cancel ] = sys_io_cancel,
+	[ __NR_fadvise64 ] = sys_fadvise64,
+	[ 251 ] = sys_ni_syscall,
 	[ __NR_exit_group ] = sys_exit_group,
 	[ __NR_lookup_dcookie ] = sys_lookup_dcookie,
 	[ __NR_epoll_create ] = sys_epoll_create,
@@ -488,6 +522,20 @@ syscall_handler_t *sys_call_table[] = {
 	[ __NR_epoll_wait ] = sys_epoll_wait,
         [ __NR_remap_file_pages ] = sys_remap_file_pages,
         [ __NR_set_tid_address ] = sys_set_tid_address,
+	[ __NR_timer_create ] = sys_timer_create,
+	[ __NR_timer_settime ] = sys_timer_settime,
+	[ __NR_timer_gettime ] = sys_timer_gettime,
+	[ __NR_timer_getoverrun ] = sys_timer_getoverrun,
+	[ __NR_timer_delete ] = sys_timer_delete,
+	[ __NR_clock_settime ] = sys_clock_settime,
+	[ __NR_clock_gettime ] = sys_clock_gettime,
+	[ __NR_clock_getres ] = sys_clock_getres,
+	[ __NR_clock_nanosleep ] = sys_clock_nanosleep,
+	[ __NR_statfs64 ] = sys_statfs64,
+	[ __NR_fstatfs64 ] = sys_fstatfs64,
+	[ __NR_tgkill ] = sys_tgkill,
+	[ __NR_utimes ] = sys_utimes,
+	[ __NR_fadvise64_64 ] = sys_fadvise64_64,
 
 	ARCH_SYSCALLS
 	[ LAST_SYSCALL + 1 ... NR_syscalls ] = 
diff -puN arch/um/kernel/sysrq.c~uml-update arch/um/kernel/sysrq.c
--- 25/arch/um/kernel/sysrq.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/sysrq.c	Fri Sep 12 11:39:06 2003
@@ -53,6 +53,14 @@ void show_trace_task(struct task_struct 
 	show_trace((unsigned long *)esp);
 }
 
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	if(task)
+		show_trace_task(task);
+	else
+		show_trace(sp);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/kernel/time.c~uml-update arch/um/kernel/time.c
--- 25/arch/um/kernel/time.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/time.c	Fri Sep 12 11:39:06 2003
@@ -15,12 +15,16 @@
 #include "process.h"
 #include "signal_user.h"
 #include "time_user.h"
+#include "kern_constants.h"
 
 extern struct timeval xtime;
 
+struct timeval local_offset = { 0, 0 };
+
 void timer(void)
 {
 	gettimeofday(&xtime, NULL);
+	timeradd(&xtime, &local_offset, &xtime);
 }
 
 void set_interval(int timer_type)
@@ -65,7 +69,7 @@ void switch_timers(int to_real)
 		       errno);
 }
 
-void idle_timer(void)
+void uml_idle_timer(void)
 {
 	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 		panic("Couldn't unset SIGVTALRM handler");
@@ -82,8 +86,6 @@ void time_init(void)
 	set_interval(ITIMER_VIRTUAL);
 }
 
-struct timeval local_offset = { 0, 0 };
-
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long flags;
@@ -100,7 +102,7 @@ int do_settimeofday(struct timespec *tv)
 	unsigned long flags;
 	struct timeval tv_in;
 
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+	if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
 		return -EINVAL;
 
 	tv_in.tv_sec = tv->tv_sec;
@@ -110,6 +112,8 @@ int do_settimeofday(struct timespec *tv)
 	gettimeofday(&now, NULL);
 	timersub(&tv_in, &now, &local_offset);
 	time_unlock(flags);
+
+	return(0);
 }
 
 void idle_sleep(int secs)
diff -puN arch/um/kernel/time_kern.c~uml-update arch/um/kernel/time_kern.c
--- 25/arch/um/kernel/time_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/time_kern.c	Fri Sep 12 11:39:06 2003
@@ -38,7 +38,7 @@ int __attribute__ ((__section__ (".unpro
 
 void timer_irq(union uml_pt_regs *regs)
 {
-	int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
+	int cpu = current_thread->cpu, ticks = missed_ticks[cpu];
 
         if(!timer_irq_inited) return;
 	missed_ticks[cpu] = 0;
@@ -55,12 +55,13 @@ void boot_timer_handler(int sig)
 	do_timer(&regs);
 }
 
-void um_timer(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 {
 	do_timer(regs);
-	write_seqlock(&xtime_lock);
+	write_seqlock_irq(&xtime_lock);
 	timer();
-	write_sequnlock(&xtime_lock);
+	write_sequnlock_irq(&xtime_lock);
+	return(IRQ_HANDLED);
 }
 
 long um_time(int * tloc)
@@ -78,12 +79,12 @@ long um_time(int * tloc)
 long um_stime(int * tptr)
 {
 	int value;
-	struct timeval new;
+	struct timespec new;
 
 	if (get_user(value, tptr))
                 return -EFAULT;
 	new.tv_sec = value;
-	new.tv_usec = 0;
+	new.tv_nsec = 0;
 	do_settimeofday(&new);
 	return 0;
 }
@@ -122,9 +123,11 @@ void __const_udelay(um_udelay_t usecs)
 void timer_handler(int sig, union uml_pt_regs *regs)
 {
 #ifdef CONFIG_SMP
+	local_irq_disable();
 	update_process_times(user_context(UPT_SP(regs)));
+	local_irq_enable();
 #endif
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		timer_irq(regs);
 }
 
diff -puN arch/um/kernel/trap_kern.c~uml-update arch/um/kernel/trap_kern.c
--- 25/arch/um/kernel/trap_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/trap_kern.c	Fri Sep 12 11:39:06 2003
@@ -16,6 +16,7 @@
 #include "asm/tlbflush.h"
 #include "asm/a.out.h"
 #include "asm/current.h"
+#include "asm/irq.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
@@ -51,7 +52,7 @@ int handle_page_fault(unsigned long addr
 	if(is_write && !(vma->vm_flags & VM_WRITE)) 
 		goto out;
 	page = address & PAGE_MASK;
-	if(page == (unsigned long) current->thread_info + PAGE_SIZE)
+	if(page == (unsigned long) current_thread + PAGE_SIZE)
 		panic("Kernel stack overflow");
 	pgd = pgd_offset(mm, page);
 	pmd = pmd_offset(pgd, page);
@@ -180,6 +181,11 @@ void bus_handler(int sig, union uml_pt_r
 	else relay_signal(sig, regs);
 }
 
+void winch(int sig, union uml_pt_regs *regs)
+{
+	do_IRQ(WINCH_IRQ, regs);
+}
+
 void trap_init(void)
 {
 }
diff -puN arch/um/kernel/trap_user.c~uml-update arch/um/kernel/trap_user.c
--- 25/arch/um/kernel/trap_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/trap_user.c	Fri Sep 12 11:39:06 2003
@@ -82,6 +82,8 @@ struct signal_info sig_info[] = {
 		     .is_irq 		= 0 },
 	[ SIGILL ] { .handler 		= relay_signal,
 		     .is_irq 		= 0 },
+	[ SIGWINCH ] { .handler		= winch,
+		       .is_irq		= 1 },
 	[ SIGBUS ] { .handler 		= bus_handler,
 		     .is_irq 		= 0 },
 	[ SIGSEGV] { .handler 		= segv_handler,
diff -puN arch/um/kernel/tt/exec_kern.c~uml-update arch/um/kernel/tt/exec_kern.c
--- 25/arch/um/kernel/tt/exec_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/tt/exec_kern.c	Fri Sep 12 11:39:06 2003
@@ -47,17 +47,17 @@ void flush_thread_tt(void)
 		do_exit(SIGKILL);
 	}
 
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		forward_interrupts(new_pid);
 	current->thread.request.op = OP_EXEC;
 	current->thread.request.u.exec.pid = new_pid;
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 	os_usr1_process(os_getpid());
 
 	enable_timer();
 	free_page(stack);
 	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
+	task_protections((unsigned long) current_thread);
 	force_flush_all();
 	unblock_signals();
 }
diff -puN arch/um/kernel/tt/include/uaccess.h~uml-update arch/um/kernel/tt/include/uaccess.h
--- 25/arch/um/kernel/tt/include/uaccess.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/tt/include/uaccess.h	Fri Sep 12 11:39:06 2003
@@ -46,18 +46,20 @@ extern int __do_copy_from_user(void *to,
 
 static inline int copy_from_user_tt(void *to, const void *from, int n)
 {
-	return(access_ok_tt(VERIFY_READ, from, n) ?
-	       __do_copy_from_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
+	if(!access_ok_tt(VERIFY_READ, from, n)) 
+		return(n);
+
+	return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
+				   &current->thread.fault_catcher));
 }
 
 static inline int copy_to_user_tt(void *to, const void *from, int n)
 {
-	return(access_ok_tt(VERIFY_WRITE, to, n) ?
-	       __do_copy_to_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
+	if(!access_ok_tt(VERIFY_WRITE, to, n))
+		return(n);
+		
+	return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
+				 &current->thread.fault_catcher));
 }
 
 extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
@@ -67,7 +69,9 @@ static inline int strncpy_from_user_tt(c
 {
 	int n;
 
-	if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
+	if(!access_ok_tt(VERIFY_READ, src, 1)) 
+		return(-EFAULT);
+
 	n = __do_strncpy_from_user(dst, src, count, 
 				   &current->thread.fault_addr,
 				   &current->thread.fault_catcher);
@@ -87,10 +91,11 @@ static inline int __clear_user_tt(void *
 
 static inline int clear_user_tt(void *mem, int len)
 {
-	return(access_ok_tt(VERIFY_WRITE, mem, len) ? 
-	       __do_clear_user(mem, len, 
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher) : len);
+	if(!access_ok_tt(VERIFY_WRITE, mem, len))
+		return(len);
+
+	return(__do_clear_user(mem, len, &current->thread.fault_addr,
+			       &current->thread.fault_catcher));
 }
 
 extern int __do_strnlen_user(const char *str, unsigned long n,
diff -puN arch/um/kernel/tt/process_kern.c~uml-update arch/um/kernel/tt/process_kern.c
--- 25/arch/um/kernel/tt/process_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/tt/process_kern.c	Fri Sep 12 11:39:06 2003
@@ -104,7 +104,10 @@ void *switch_to_tt(void *prev, void *nex
 
 void release_thread_tt(struct task_struct *task)
 {
-	os_kill_process(task->thread.mode.tt.extern_pid, 0);
+	int pid = task->thread.mode.tt.extern_pid;
+
+	if(os_getpid() != pid)
+		os_kill_process(pid, 0);
 }
 
 void exit_thread_tt(void)
@@ -125,27 +128,27 @@ static void new_thread_handler(int sig)
 	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-	block_signals();
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	init_new_thread_signals(1);
-#ifdef CONFIG_SMP
-	schedule_tail(current->thread.prev_sched);
-#endif
 	enable_timer();
 	free_page(current->thread.temp_stack);
 	set_cmdline("(kernel thread)");
-	force_flush_all();
 
-	current->thread.prev_sched = NULL;
 	change_sig(SIGUSR1, 1);
 	change_sig(SIGVTALRM, 1);
 	change_sig(SIGPROF, 1);
-	unblock_signals();
+	local_irq_enable();
 	if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
 		do_exit(0);
 }
 
 static int new_thread_proc(void *stack)
 {
+	local_irq_disable();
 	init_new_thread_stack(stack, new_thread_handler);
 	os_usr1_process(os_getpid());
 	return(0);
@@ -165,35 +168,32 @@ void finish_fork_handler(int sig)
  	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-#ifdef CONFIG_SMP	
-	schedule_tail(NULL);
-#endif
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	enable_timer();
 	change_sig(SIGVTALRM, 1);
 	local_irq_enable();
-	force_flush_all();
 	if(current->mm != current->parent->mm)
 		protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 
 			       1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
-
-	current->thread.prev_sched = NULL;
+	task_protections((unsigned long) current_thread);
 
 	free_page(current->thread.temp_stack);
+	local_irq_disable();
 	change_sig(SIGUSR1, 0);
 	set_user_mode(current);
 }
 
-static int sigusr1 = SIGUSR1;
-
 int fork_tramp(void *stack)
 {
-	int sig = sigusr1;
-
 	local_irq_disable();
+	arch_init_thread();
 	init_new_thread_stack(stack, finish_fork_handler);
 
-	kill(os_getpid(), sig);
+	os_usr1_process(os_getpid());
 	return(0);
 }
 
@@ -377,8 +377,8 @@ static void mprotect_kernel_mem(int w)
 
 	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
 
-	start = (unsigned long) current->thread_info + PAGE_SIZE;
-	end = (unsigned long) current + PAGE_SIZE * pages;
+	start = (unsigned long) current_thread + PAGE_SIZE;
+	end = (unsigned long) current_thread + PAGE_SIZE * pages;
 	protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
 	protect_memory(end, high_physmem - end, 1, w, 1, 1);
 
diff -puN arch/um/kernel/tt/ptproxy/proxy.c~uml-update arch/um/kernel/tt/ptproxy/proxy.c
--- 25/arch/um/kernel/tt/ptproxy/proxy.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/tt/ptproxy/proxy.c	Fri Sep 12 11:39:06 2003
@@ -293,10 +293,10 @@ void fake_child_exit(void)
 }
 
 char gdb_init_string[] = 
-"att 1
-b panic
-b stop
-handle SIGWINCH nostop noprint pass
+"att 1 \n\
+b panic \n\
+b stop \n\
+handle SIGWINCH nostop noprint pass \n\
 ";
 
 int start_debugger(char *prog, int startup, int stop, int *fd_out)
diff -puN arch/um/kernel/tt/tracer.c~uml-update arch/um/kernel/tt/tracer.c
--- 25/arch/um/kernel/tt/tracer.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/tt/tracer.c	Fri Sep 12 11:39:06 2003
@@ -39,7 +39,7 @@ int is_tracer_winch(int pid, int fd, voi
 		return(0);
 
 	register_winch_irq(tracer_winch[0], fd, -1, data);
-	return(0);
+	return(1);
 }
 
 static void tracer_winch_handler(int sig)
@@ -401,7 +401,7 @@ static int __init uml_debug_setup(char *
 		
 		if(!strcmp(line, "go"))	debug_stop = 0;
 		else if(!strcmp(line, "parent")) debug_parent = 1;
-		else printk("Unknown debug option : '%s'\n", line);
+		else printf("Unknown debug option : '%s'\n", line);
 
 		line = next;
 	}
diff -puN arch/um/kernel/tt/uaccess_user.c~uml-update arch/um/kernel/tt/uaccess_user.c
--- 25/arch/um/kernel/tt/uaccess_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/tt/uaccess_user.c	Fri Sep 12 11:39:06 2003
@@ -8,15 +8,20 @@
 #include <string.h>
 #include "user_util.h"
 #include "uml_uaccess.h"
+#include "task.h"
+#include "kern_util.h"
 
 int __do_copy_from_user(void *to, const void *from, int n,
 			void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
 			       __do_copy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(n - (fault - (unsigned long) from));
 }
@@ -29,11 +34,14 @@ static void __do_strncpy(void *dst, cons
 int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
 			   void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
 			       __do_strncpy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(strlen(dst));
 	else return(-1);
 }
@@ -46,11 +54,14 @@ static void __do_clear(void *to, const v
 int __do_clear_user(void *mem, unsigned long len,
 		    void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
 			       __do_clear, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(len - (fault - (unsigned long) mem));
 }
@@ -58,6 +69,7 @@ int __do_clear_user(void *mem, unsigned 
 int __do_strnlen_user(const char *str, unsigned long n,
 		      void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	int ret;
 	unsigned long *faddrp = (unsigned long *)fault_addr;
 	jmp_buf jbuf;
@@ -71,6 +83,8 @@ int __do_strnlen_user(const char *str, u
 	}
 	*fault_addr = NULL;
 	*fault_catcher = NULL;
+
+	TASK_REGS(get_current())->tt = save;
 	return ret;
 }
 
diff -puN arch/um/kernel/um_arch.c~uml-update arch/um/kernel/um_arch.c
--- 25/arch/um/kernel/um_arch.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/um_arch.c	Fri Sep 12 11:39:06 2003
@@ -38,13 +38,18 @@
 #include "mode_kern.h"
 #include "mode.h"
 
-#define DEFAULT_COMMAND_LINE "root=6200"
+#define DEFAULT_COMMAND_LINE "root=ubd0"
 
 struct cpuinfo_um boot_cpu_data = { 
 	.loops_per_jiffy	= 0,
 	.ipi_pipe		= { -1, -1 }
 };
 
+/* Placeholder to make UML link until the vsyscall stuff is actually 
+ * implemented
+ */
+void *__kernel_vsyscall;
+
 unsigned long thread_saved_pc(struct task_struct *task)
 {
 	return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
@@ -61,10 +66,14 @@ static int show_cpuinfo(struct seq_file 
 		return 0;
 #endif
 
-	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+	seq_printf(m, "processor\t: %d\n", index);
+	seq_printf(m, "vendor_id\t: User Mode Linux\n");
+	seq_printf(m, "model name\t: UML\n");
+	seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+	seq_printf(m, "host\t\t: %s\n", host_info);
+	seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
 		   loops_per_jiffy/(500000/HZ),
 		   (loops_per_jiffy/(5000/HZ)) % 100);
-	seq_printf(m, "host\t\t: %s\n", host_info);
 
 	return(0);
 }
@@ -134,12 +143,12 @@ void set_cmdline(char *cmd)
 	if(umid != NULL){
 		snprintf(argv1_begin, 
 			 (argv1_end - argv1_begin) * sizeof(*ptr), 
-			 "(%s)", umid);
+			 "(%s) ", umid);
 		ptr = &argv1_begin[strlen(argv1_begin)];
 	}
 	else ptr = argv1_begin;
 
-	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd);
+	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
 	memset(argv1_begin + strlen(argv1_begin), '\0', 
 	       argv1_end - argv1_begin - strlen(argv1_begin));
 #endif
@@ -179,7 +188,7 @@ __uml_setup("root=", uml_root_setup,
 static int __init uml_ncpus_setup(char *line, int *add)
 {
        if (!sscanf(line, "%d", &ncpus)) {
-               printk("Couldn't parse [%s]\n", line);
+               printf("Couldn't parse [%s]\n", line);
                return -1;
        }
 
@@ -210,7 +219,7 @@ static int __init mode_tt_setup(char *li
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
+	printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
 	return(0);
 }
 
@@ -221,7 +230,7 @@ static int __init mode_tt_setup(char *li
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
+	printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
 	return(0);
 }
 
@@ -369,6 +378,7 @@ int linux_main(int argc, char **argv)
 		2 * PAGE_SIZE;
 
 	task_protections((unsigned long) &init_thread_info);
+	os_flush_stdout();
 
 	return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
 }
diff -puN arch/um/kernel/umid.c~uml-update arch/um/kernel/umid.c
--- 25/arch/um/kernel/umid.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/umid.c	Fri Sep 12 11:39:06 2003
@@ -33,18 +33,19 @@ static char *uml_dir = UML_DIR;
 static int umid_is_random = 1;
 static int umid_inited = 0;
 
-static int make_umid(void);
+static int make_umid(int (*printer)(const char *fmt, ...));
 
-static int __init set_umid(char *name, int is_random)
+static int __init set_umid(char *name, int is_random, 
+			   int (*printer)(const char *fmt, ...))
 {
 	if(umid_inited){
-		printk("Unique machine name can't be set twice\n");
+		(*printer)("Unique machine name can't be set twice\n");
 		return(-1);
 	}
 
 	if(strlen(name) > UMID_LEN - 1)
-		printk("Unique machine name is being truncated to %s "
-		       "characters\n", UMID_LEN);
+		(*printer)("Unique machine name is being truncated to %s "
+			   "characters\n", UMID_LEN);
 	strlcpy(umid, name, sizeof(umid));
 
 	umid_is_random = is_random;
@@ -54,7 +55,7 @@ static int __init set_umid(char *name, i
 
 static int __init set_umid_arg(char *name, int *add)
 {
-	return(set_umid(name, 0));
+	return(set_umid(name, 0, printf));
 }
 
 __uml_setup("umid=", set_umid_arg,
@@ -67,7 +68,7 @@ int __init umid_file_name(char *name, ch
 {
 	int n;
 
-	if(!umid_inited && make_umid()) return(-1);
+	if(!umid_inited && make_umid(printk)) return(-1);
 
 	n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
 	if(n > len){
@@ -92,14 +93,14 @@ static int __init create_pid_file(void)
 	fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 
 			  0644);
 	if(fd < 0){
-		printk("Open of machine pid file \"%s\" failed - "
+		printf("Open of machine pid file \"%s\" failed - "
 		       "errno = %d\n", file, -fd);
 		return 0;
 	}
 
 	sprintf(pid, "%d\n", os_getpid());
 	if(write(fd, pid, strlen(pid)) != strlen(pid))
-		printk("Write of pid file failed - errno = %d\n", errno);
+		printf("Write of pid file failed - errno = %d\n", errno);
 	close(fd);
 	return 0;
 }
@@ -197,7 +198,7 @@ static int __init set_uml_dir(char *name
 	if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
 		uml_dir = malloc(strlen(name) + 1);
 		if(uml_dir == NULL){
-			printk("Failed to malloc uml_dir - error = %d\n",
+			printf("Failed to malloc uml_dir - error = %d\n",
 			       errno);
 			uml_dir = name;
 			return(0);
@@ -217,7 +218,7 @@ static int __init make_uml_dir(void)
 		char *home = getenv("HOME");
 
 		if(home == NULL){
-			printk("make_uml_dir : no value in environment for "
+			printf("make_uml_dir : no value in environment for "
 			       "$HOME\n");
 			exit(1);
 		}
@@ -239,25 +240,25 @@ static int __init make_uml_dir(void)
 	strcpy(uml_dir, dir);
 	
 	if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
-	        printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
+	        printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
 		return(-1);
 	}
 	return 0;
 }
 
-static int __init make_umid(void)
+static int __init make_umid(int (*printer)(const char *fmt, ...))
 {
 	int fd, err;
 	char tmp[strlen(uml_dir) + UMID_LEN + 1];
 
 	strlcpy(tmp, uml_dir, sizeof(tmp));
 
-	if(*umid == 0){
+	if(!umid_inited){
 		strcat(tmp, "XXXXXX");
 		fd = mkstemp(tmp);
 		if(fd < 0){
-			printk("make_umid - mkstemp failed, errno = %d\n",
-			       errno);
+			(*printer)("make_umid - mkstemp failed, errno = %d\n",
+				   errno);
 			return(1);
 		}
 
@@ -267,7 +268,7 @@ static int __init make_umid(void)
 		 * for directories.
 		 */
 		unlink(tmp);
-		set_umid(&tmp[strlen(uml_dir)], 1);
+		set_umid(&tmp[strlen(uml_dir)], 1, printer);
 	}
 	
 	sprintf(tmp, "%s%s", uml_dir, umid);
@@ -275,14 +276,14 @@ static int __init make_umid(void)
 	if((err = mkdir(tmp, 0777)) < 0){
 		if(errno == EEXIST){
 			if(not_dead_yet(tmp)){
-				printk("umid '%s' is in use\n", umid);
+				(*printer)("umid '%s' is in use\n", umid);
 				return(-1);
 			}
 			err = mkdir(tmp, 0777);
 		}
 	}
 	if(err < 0){
-		printk("Failed to create %s - errno = %d\n", umid, errno);
+		(*printer)("Failed to create %s - errno = %d\n", umid, errno);
 		return(-1);
 	}
 
@@ -295,7 +296,13 @@ __uml_setup("uml_dir=", set_uml_dir,
 );
 
 __uml_postsetup(make_uml_dir);
-__uml_postsetup(make_umid);
+
+static int __init make_umid_setup(void)
+{
+	return(make_umid(printf));
+}
+
+__uml_postsetup(make_umid_setup);
 __uml_postsetup(create_pid_file);
 
 /*
diff -puN arch/um/kernel/user_util.c~uml-update arch/um/kernel/user_util.c
--- 25/arch/um/kernel/user_util.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/kernel/user_util.c	Fri Sep 12 11:39:06 2003
@@ -119,17 +119,6 @@ int wait_for_stop(int pid, int sig, int 
 	}
 }
 
-int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags)
-{
-	int pid;
-
-	pid = clone(fn, sp, flags, arg);
- 	if(pid < 0) return(-1);
-	wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
-	ptrace(PTRACE_CONT, pid, 0, 0);
-	return(pid);
-}
-
 int raw(int fd, int complain)
 {
 	struct termios tt;
diff -puN arch/um/Makefile~uml-update arch/um/Makefile
--- 25/arch/um/Makefile~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/Makefile	Fri Sep 12 11:39:06 2003
@@ -24,15 +24,17 @@ core-y			+= $(ARCH_DIR)/kernel/		 \
 # Have to precede the include because the included Makefiles reference them.
 SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
 	include/asm-um/sigcontext.h include/asm-um/processor.h \
-	include/asm-um/ptrace.h include/asm-um/arch-signal.h
+	include/asm-um/ptrace.h include/asm-um/arch-signal.h \
+	include/asm-um/module.h
 
 ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
 	$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 
 GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
 
-include $(ARCH_DIR)/Makefile-$(SUBARCH)
-include $(ARCH_DIR)/Makefile-os-$(OS)
+.PHONY: sys_prepare
+sys_prepare:
+	@:
 
 MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
 MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
@@ -41,6 +43,9 @@ ifneq ($(MAKEFILE-y),)
   include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
 endif
 
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
+
 EXTRAVERSION := $(EXTRAVERSION)-1um
 
 ARCH_INCLUDE = -I$(ARCH_DIR)/include
@@ -52,14 +57,14 @@ ARCH_INCLUDE = -I$(ARCH_DIR)/include
 
 CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
 	-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
-	$(MODE_INCLUDE)
+	-Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
 
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
 SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
 
 ifeq ($(CONFIG_MODE_SKAS), y)
-$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
 endif
 
 include/linux/version.h: arch/$(ARCH)/Makefile
@@ -98,17 +103,17 @@ CPP_MODE_TT := $(shell [ "$(CONFIG_MODE_
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 
-AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \
+AFLAGS_vmlinux.lds.o = $(shell echo -U$(SUBARCH) \
 	-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
 	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
-	-DKERNEL_STACK_SIZE=$(STACK_SIZE)
+	-DKERNEL_STACK_SIZE=$(STACK_SIZE))
 
-AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
+export AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
 
 LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
 
-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
-	$(call if_changed_dep,as_s_S)
+#$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
+#	$(call if_changed_dep,as_s_S)
 
 linux: vmlinux $(LD_SCRIPT-y)
 	$(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
@@ -116,6 +121,7 @@ linux: vmlinux $(LD_SCRIPT-y)
 
 USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
 USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
+USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
 USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
 	$(MODE_INCLUDE)
 
@@ -123,9 +129,10 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,
 USER_CFLAGS += -D_GNU_SOURCE
 
 CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds.s \
-	$(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
+	$(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \
+	$(GEN_HEADERS)
 
-$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
+$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c sys_prepare
 	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
 
 archmrproper:
@@ -161,19 +168,23 @@ $(ARCH_DIR)/include/sysdep:
 $(ARCH_DIR)/os:
 	cd $(ARCH_DIR) && ln -sf os-$(OS) os
 
-$(ARCH_DIR)/include/uml-config.h :
+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
 	sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
 
+filechk_$(ARCH_DIR)/include/task.h := $(ARCH_DIR)/util/mk_task
+
 $(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
-	$< > $@
+	$(call filechk,$@)
+
+filechk_$(ARCH_DIR)/include/kern_constants.h := $(ARCH_DIR)/util/mk_constants
 
 $(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
-	$< > $@
+	$(call filechk,$@)
 
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
-	$(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \
+	sys_prepare FORCE ;
 
 $(ARCH_DIR)/util: FORCE
-	@$(call descend,$@,)
+	$(MAKE) -f scripts/Makefile.build obj=$@
 
-export SUBARCH USER_CFLAGS OS
+export SUBARCH USER_CFLAGS OS 
diff -puN arch/um/Makefile-i386~uml-update arch/um/Makefile-i386
--- 25/arch/um/Makefile-i386~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/Makefile-i386	Fri Sep 12 11:39:06 2003
@@ -16,22 +16,28 @@ SYS_UTIL_DIR	:= $(ARCH_DIR)/sys-i386/uti
 
 SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
 
+sys_prepare: $(SYS_DIR)/sc.h
+
 prepare: $(SYS_HEADERS)
 
+filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
+
 $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-	$< > $@
+	$(call filechk,$@)
+
+filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread 
 
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
-	$< > $@
+	$(call filechk,$@)
 
-$(SYS_UTIL_DIR)/mk_sc: FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_sc: scripts/fixdep include/config/MARKER FORCE ; 
+	+@$(call descend,$(SYS_UTIL_DIR),$@)
 
-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ; 
+	+@$(call descend,$(SYS_UTIL_DIR),$@)
 
 $(SYS_UTIL_DIR): include/asm FORCE
-	@$(call descend,$@,)
+	+@$(call descend,$@,)
 
 sysclean :
 	rm -f $(SYS_HEADERS)
diff -puN arch/um/Makefile-skas~uml-update arch/um/Makefile-skas
--- 25/arch/um/Makefile-skas~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/Makefile-skas	Fri Sep 12 11:39:06 2003
@@ -14,7 +14,7 @@ MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/
 LINK_SKAS = -Wl,-rpath,/lib 
 LD_SCRIPT_SKAS = dyn.lds.s
 
-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
 
-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
-	$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h :
+	$(call descend,$(ARCH_DIR)/kernel/skas,$@)
diff -puN arch/um/os-Linux/drivers/tuntap_user.c~uml-update arch/um/os-Linux/drivers/tuntap_user.c
--- 25/arch/um/os-Linux/drivers/tuntap_user.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/os-Linux/drivers/tuntap_user.c	Fri Sep 12 11:39:06 2003
@@ -142,7 +142,7 @@ static int tuntap_open(void *data)
 			return(-errno);
 		}
 		memset(&ifr, 0, sizeof(ifr));
-		ifr.ifr_flags = IFF_TAP;
+		ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
 		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
 			printk("TUNSETIFF failed, errno = %d", errno);
diff -puN arch/um/os-Linux/file.c~uml-update arch/um/os-Linux/file.c
--- 25/arch/um/os-Linux/file.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/os-Linux/file.c	Fri Sep 12 11:39:06 2003
@@ -315,7 +315,7 @@ int os_rcv_fd(int fd, int *helper_pid_ou
 	return(new);
 }
 
-int create_unix_socket(char *file, int len)
+int create_unix_socket(char *file, int len, int close_on_exec)
 {
 	struct sockaddr_un addr;
 	int sock, err;
@@ -327,6 +327,10 @@ int create_unix_socket(char *file, int l
 		return(-errno);
 	}
 
+	if(close_on_exec && fcntl(sock, F_SETFD, 1) < 0)
+		printk("create_unix_socket : Setting FD_CLOEXEC failed, "
+		       "errno = %d", errno);
+
 	addr.sun_family = AF_UNIX;
 
 	/* XXX Be more careful about overflow */
@@ -342,6 +346,37 @@ int create_unix_socket(char *file, int l
 	return(sock);
 }
 
+void os_flush_stdout(void)
+{
+	fflush(stdout);
+}
+
+int os_lock_file(int fd, int excl)
+{
+	int type = excl ? F_WRLCK : F_RDLCK;
+	struct flock lock = ((struct flock) { .l_type	= type,
+					      .l_whence	= SEEK_SET,
+					      .l_start	= 0,
+					      .l_len	= 0 } );
+	int err, save;
+
+	err = fcntl(fd, F_SETLK, &lock);
+	if(!err)
+		goto out;
+
+	save = -errno;
+	err = fcntl(fd, F_GETLK, &lock);
+	if(err){
+		err = -errno;
+		goto out;
+	}
+	
+	printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+	err = save;
+ out:
+	return(err);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/sys-i386/bugs.c~uml-update arch/um/sys-i386/bugs.c
--- 25/arch/um/sys-i386/bugs.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/sys-i386/bugs.c	Fri Sep 12 11:39:06 2003
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/signal.h>
+#include <asm/ldt.h>
 #include "kern_util.h"
 #include "user.h"
 #include "sysdep/ptrace.h"
@@ -16,8 +17,8 @@
 #define MAXTOKEN 64
 
 /* Set during early boot */
-int cpu_has_cmov = 1;
-int cpu_has_xmm = 0;
+int host_has_cmov = 1;
+int host_has_xmm = 0;
 
 static char token(int fd, char *buf, int len, char stop)
 {
@@ -104,6 +105,25 @@ static int check_cpu_feature(char *featu
 	return(1);
 }
 
+static void disable_lcall(void)
+{
+	struct modify_ldt_ldt_s ldt;
+	int err;
+
+	bzero(&ldt, sizeof(ldt));
+	ldt.entry_number = 7;
+	ldt.base_addr = 0;
+	ldt.limit = 0;
+	err = modify_ldt(1, &ldt, sizeof(ldt));
+	if(err)
+		printk("Failed to disable lcall7 - errno = %d\n", errno);
+}
+
+void arch_init_thread(void)
+{
+	disable_lcall();
+}
+
 void arch_check_bugs(void)
 {
 	int have_it;
@@ -113,8 +133,8 @@ void arch_check_bugs(void)
 		       "checks\n");
 		return;
 	}
-	if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it;
-	if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
+	if(check_cpu_feature("cmov", &have_it)) host_has_cmov = have_it;
+	if(check_cpu_feature("xmm", &have_it)) host_has_xmm = have_it;
 }
 
 int arch_handle_signal(int sig, union uml_pt_regs *regs)
@@ -130,18 +150,18 @@ int arch_handle_signal(int sig, union um
 	if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
 		return(0);
 
-	if(cpu_has_cmov == 0)
+	if(host_has_cmov == 0)
 		panic("SIGILL caused by cmov, which this processor doesn't "
 		      "implement, boot a filesystem compiled for older "
 		      "processors");
-	else if(cpu_has_cmov == 1)
+	else if(host_has_cmov == 1)
 		panic("SIGILL caused by cmov, which this processor claims to "
 		      "implement");
-	else if(cpu_has_cmov == -1)
+	else if(host_has_cmov == -1)
 		panic("SIGILL caused by cmov, couldn't tell if this processor "
 		      "implements it, boot a filesystem compiled for older "
 		      "processors");
-	else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov);
+	else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
 	return(0);
 }
 
diff -puN arch/um/sys-i386/Makefile~uml-update arch/um/sys-i386/Makefile
--- 25/arch/um/sys-i386/Makefile~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/sys-i386/Makefile	Fri Sep 12 11:39:06 2003
@@ -1,7 +1,8 @@
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
-	ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o ptrace.o \
+	ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_MODULES) += module.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
@@ -9,6 +10,8 @@ USER_OBJS := $(foreach file,$(USER_OBJS)
 SYMLINKS = semaphore.c highmem.c module.c
 SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
 
+clean-files := $(SYMLINKS)
+
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
@@ -24,8 +27,7 @@ $(USER_OBJS) : %.o: %.c
 $(SYMLINKS): 
 	$(call make_link,$@)
 
-clean:
-	$(MAKE) -C util clean
+subdir- := util
 
 fastdep:
 
diff -puN arch/um/uml.lds.S~uml-update arch/um/uml.lds.S
--- 25/arch/um/uml.lds.S~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/uml.lds.S	Fri Sep 12 11:39:06 2003
@@ -26,7 +26,11 @@ SECTIONS
   . = ALIGN(4096);		/* Init code and data */
   _stext = .;
   __init_begin = .;
-  .text.init : { *(.text.init) }
+  .init.text : { 
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
   . = ALIGN(4096);
   .text      :
   {
@@ -38,7 +42,7 @@ SECTIONS
 
   #include "asm/common.lds.S"
 
-  .data.init : { *(.data.init) }
+  init.data : { *(init.data) }
   .data    :
   {
     . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
diff -puN arch/um/util/mk_constants_kern.c~uml-update arch/um/util/mk_constants_kern.c
--- 25/arch/um/util/mk_constants_kern.c~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/arch/um/util/mk_constants_kern.c	Fri Sep 12 11:39:06 2003
@@ -1,5 +1,6 @@
 #include "linux/kernel.h"
 #include "linux/stringify.h"
+#include "linux/time.h"
 #include "asm/page.h"
 
 extern void print_head(void);
@@ -11,6 +12,7 @@ int main(int argc, char **argv)
 {
   print_head();
   print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
+
   print_constant_str("UM_KERN_EMERG", KERN_EMERG);
   print_constant_str("UM_KERN_ALERT", KERN_ALERT);
   print_constant_str("UM_KERN_CRIT", KERN_CRIT);
@@ -19,6 +21,8 @@ int main(int argc, char **argv)
   print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
   print_constant_str("UM_KERN_INFO", KERN_INFO);
   print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
+
+  print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
   print_tail();
   return(0);
 }
diff -puN include/asm-um/archparam-i386.h~uml-update include/asm-um/archparam-i386.h
--- 25/include/asm-um/archparam-i386.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/archparam-i386.h	Fri Sep 12 11:39:06 2003
@@ -56,6 +56,65 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
 	pr_reg[16] = PT_REGS_SS(regs);		\
 } while(0);
 
+#define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
+#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
+#define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
+extern void *__kernel_vsyscall;
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);	\
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	Elf32_Off ofs = 0;						      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
+		if (phdr.p_type == PT_LOAD) {				      \
+			ofs = phdr.p_offset = offset;			      \
+			offset += phdr.p_filesz;			      \
+		}							      \
+		else							      \
+			phdr.p_offset += ofs;				      \
+		phdr.p_paddr = 0; /* match other core phdrs */		      \
+		DUMP_WRITE(&phdr, sizeof(phdr));			      \
+	}								      \
+} while (0)
+#define ELF_CORE_WRITE_EXTRA_DATA					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
+			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
+				   vsyscall_phdrs[i].p_filesz);		      \
+	}								      \
+} while (0)
+
 /********* Bits for asm-um/delay.h **********/
 
 typedef unsigned long um_udelay_t;
diff -puN include/asm-um/common.lds.S~uml-update include/asm-um/common.lds.S
--- 25/include/asm-um/common.lds.S~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/common.lds.S	Fri Sep 12 11:39:06 2003
@@ -1,3 +1,5 @@
+#include <asm-generic/vmlinux.lds.h>
+
   .fini      : { *(.fini)    } =0x9090
   _etext = .;
   PROVIDE (etext = .);
@@ -67,6 +69,10 @@
   }
   __initcall_end = .;
 
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
   __uml_initcall_start = .;
   .uml.initcall.init : { *(.uml.initcall.init) }
   __uml_initcall_end = .;
@@ -80,7 +86,33 @@
   .uml.exitcall : { *(.uml.exitcall.exit) }
   __uml_exitcall_end = .;
 
-  . = ALIGN(4096);
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) } 
+  __alt_instructions_end = .; 
+  .altinstr_replacement : { *(.altinstr_replacement) } 
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
+ 
+  __preinit_array_start = .;
+  .preinit_array : { *(.preinit_array) }
+  __preinit_array_end = .;
+  __init_array_start = .;
+  .init_array : { *(.init_array) }
+  __init_array_end = .;
+  __fini_array_start = .;
+  .fini_array : { *(.fini_array) }
+  __fini_array_end = .;
+
+   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+ 	*(.exitcall.exit)
+  }
+ 
diff -puN /dev/null include/asm-um/cpufeature.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/asm-um/cpufeature.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,6 @@
+#ifndef __UM_CPUFEATURE_H
+#define __UM_CPUFEATURE_H
+
+#include "asm/arch/cpufeature.h"
+
+#endif
diff -puN include/asm-um/current.h~uml-update include/asm-um/current.h
--- 25/include/asm-um/current.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/current.h	Fri Sep 12 11:39:06 2003
@@ -16,8 +16,10 @@ struct thread_info;
 #define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \
 			        (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
 
-#define current ({ int dummy; \
-                   ((struct thread_info *) CURRENT_THREAD(dummy))->task; })
+#define current_thread \
+	({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); })
+
+#define current (current_thread->task)
 
 #endif /* __ASSEMBLY__ */
 
diff -puN include/asm-um/fixmap.h~uml-update include/asm-um/fixmap.h
--- 25/include/asm-um/fixmap.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/fixmap.h	Fri Sep 12 11:39:06 2003
@@ -34,6 +34,7 @@ enum fixed_addresses {
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+	FIX_VSYSCALL,
 	__end_of_fixed_addresses
 };
 
@@ -63,6 +64,13 @@ extern unsigned long get_kmem_end(void);
 #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)      ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
 
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START	(__fix_to_virt(FIX_VSYSCALL))
+#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+
 extern void __this_fixmap_does_not_exist(void);
 
 /*
diff -puN include/asm-um/irq.h~uml-update include/asm-um/irq.h
--- 25/include/asm-um/irq.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/irq.h	Fri Sep 12 11:39:06 2003
@@ -1,15 +1,6 @@
 #ifndef __UM_IRQ_H
 #define __UM_IRQ_H
 
-/* The i386 irq.h has a struct task_struct in a prototype without including
- * sched.h.  This forward declaration kills the resulting warning.
- */
-struct task_struct;
-
-#include "asm/ptrace.h"
-
-#undef NR_IRQS
-
 #define TIMER_IRQ		0
 #define UMN_IRQ			1
 #define CONSOLE_IRQ		2
@@ -28,8 +19,4 @@ struct task_struct;
 #define LAST_IRQ XTERM_IRQ
 #define NR_IRQS (LAST_IRQ + 1)
 
-extern int um_request_irq(unsigned int irq, int fd, int type,
-			  void (*handler)(int, void *, struct pt_regs *),
-			  unsigned long irqflags,  const char * devname,
-			  void *dev_id);
 #endif
diff -puN /dev/null include/asm-um/local.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/asm-um/local.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,6 @@
+#ifndef __UM_LOCAL_H
+#define __UM_LOCAL_H
+
+#include "asm/arch/local.h"
+
+#endif
diff -puN /dev/null include/asm-um/module-generic.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/asm-um/module-generic.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,6 @@
+#ifndef __UM_MODULE_GENERIC_H
+#define __UM_MODULE_GENERIC_H
+
+#include "asm/arch/module.h"
+
+#endif
diff -puN /dev/null include/asm-um/module-i386.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/asm-um/module-i386.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,13 @@
+#ifndef __UM_MODULE_I386_H
+#define __UM_MODULE_I386_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif
diff -puN include/asm-um/page.h~uml-update include/asm-um/page.h
--- 25/include/asm-um/page.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/page.h	Fri Sep 12 11:39:06 2003
@@ -4,7 +4,6 @@
 struct page;
 
 #include "asm/arch/page.h"
-#include "asm/bug.h"
 
 #undef __pa
 #undef __va
diff -puN include/asm-um/pgtable.h~uml-update include/asm-um/pgtable.h
--- 25/include/asm-um/pgtable.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/pgtable.h	Fri Sep 12 11:39:06 2003
@@ -79,12 +79,13 @@ extern unsigned long high_physmem;
 
 #define _PAGE_PRESENT	0x001
 #define _PAGE_NEWPAGE	0x002
-#define _PAGE_PROTNONE	0x004	/* If not present */
-#define _PAGE_RW	0x008
-#define _PAGE_USER	0x010
-#define _PAGE_ACCESSED	0x020
-#define _PAGE_DIRTY	0x040
-#define _PAGE_NEWPROT   0x080
+#define _PAGE_NEWPROT   0x004
+#define _PAGE_FILE	0x008   /* set:pagecache unset:swap */
+#define _PAGE_PROTNONE	0x010	/* If not present */
+#define _PAGE_RW	0x020
+#define _PAGE_USER	0x040
+#define _PAGE_ACCESSED	0x080
+#define _PAGE_DIRTY	0x100
 
 #define REGION_MASK	0xf0000000
 #define REGION_SHIFT	28
@@ -203,6 +204,16 @@ extern unsigned long pfn_to_phys(unsigne
 #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
 #define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
 
+/*
+ * Bits 0 through 3 are taken
+ */
+#define PTE_FILE_MAX_BITS	28
+
+#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((off) << 4) + _PAGE_FILE })
+
 static inline pte_t pte_mknewprot(pte_t pte)
 {
  	pte_val(pte) |= _PAGE_NEWPROT;
@@ -236,6 +247,12 @@ static inline void set_pte(pte_t *pteptr
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+static inline int pte_user(pte_t pte)
+{ 
+	return((pte_val(pte) & _PAGE_USER) && 
+	       !(pte_val(pte) & _PAGE_PROTNONE));
+}
+
 static inline int pte_read(pte_t pte)
 { 
 	return((pte_val(pte) & _PAGE_USER) && 
@@ -253,6 +270,14 @@ static inline int pte_write(pte_t pte)
 	       !(pte_val(pte) & _PAGE_PROTNONE));
 }
 
+/*
+ * The following only works if pte_present() is not true.
+ */
+static inline int pte_file(pte_t pte)
+{ 
+	return (pte).pte_low & _PAGE_FILE; 
+}
+
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
@@ -355,14 +380,26 @@ static inline pte_t pte_modify(pte_t pte
 #define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \
 		       ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT)))
 
-/* to find an entry in a page-table-directory. */
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-/* to find an entry in a page-table-directory */
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
 #define pgd_offset(mm, address) \
 ((mm)->pgd + ((address) >> PGDIR_SHIFT))
 
-/* to find an entry in a kernel page-table-directory */
+
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 #define pmd_index(address) \
@@ -374,7 +411,12 @@ static inline pmd_t * pmd_offset(pgd_t *
 	return (pmd_t *) dir;
 }
 
-/* Find an entry in the third-level page table.. */ 
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
 #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
@@ -400,11 +442,11 @@ typedef pte_t *pte_addr_t;
 #define update_mmu_cache(vma,address,pte) do ; while (0)
 
 /* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 3) & 0x7f)
-#define __swp_offset(x)			((x).val >> 10)
+#define __swp_type(x)			(((x).val >> 4) & 0x3f)
+#define __swp_offset(x)			((x).val >> 11)
 
 #define __swp_entry(type, offset) \
-	((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
+	((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
 #define __pte_to_swp_entry(pte) \
 	((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
diff -puN include/asm-um/processor-generic.h~uml-update include/asm-um/processor-generic.h
--- 25/include/asm-um/processor-generic.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/processor-generic.h	Fri Sep 12 11:39:06 2003
@@ -11,9 +11,7 @@ struct pt_regs;
 struct task_struct;
 
 #include "linux/config.h"
-#include "linux/signal.h"
 #include "asm/ptrace.h"
-#include "asm/siginfo.h"
 #include "choose-mode.h"
 
 struct mm_struct;
@@ -101,14 +99,19 @@ typedef struct {
 } mm_segment_t;
 
 extern struct task_struct *alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *task);
 
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern void dump_thread(struct pt_regs *regs, struct user *u);
+extern void prepare_to_copy(struct task_struct *tsk);
 
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
+static inline void mm_copy_segments(struct mm_struct *from_mm, 
+				    struct mm_struct *new_mm)
+{
+}
+
 #define init_stack	(init_thread_union.stack)
 
 /*
diff -puN include/asm-um/processor-i386.h~uml-update include/asm-um/processor-i386.h
--- 25/include/asm-um/processor-i386.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/processor-i386.h	Fri Sep 12 11:39:06 2003
@@ -6,8 +6,8 @@
 #ifndef __UM_PROCESSOR_I386_H
 #define __UM_PROCESSOR_I386_H
 
-extern int cpu_has_xmm;
-extern int cpu_has_cmov;
+extern int host_has_xmm;
+extern int host_has_cmov;
 
 struct arch_thread {
 	unsigned long debugregs[8];
diff -puN /dev/null include/asm-um/sections.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/asm-um/sections.h	Fri Sep 12 11:39:06 2003
@@ -0,0 +1,7 @@
+#ifndef _UM_SECTIONS_H
+#define _UM_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff -puN include/asm-um/smp.h~uml-update include/asm-um/smp.h
--- 25/include/asm-um/smp.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/smp.h	Fri Sep 12 11:39:06 2003
@@ -10,7 +10,7 @@
 
 extern cpumask_t cpu_online_map;
 
-#define smp_processor_id() (current->thread_info->cpu)
+#define smp_processor_id() (current_thread->cpu)
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY	15 /* Pick a number, any number */
diff -puN include/asm-um/system-generic.h~uml-update include/asm-um/system-generic.h
--- 25/include/asm-um/system-generic.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/system-generic.h	Fri Sep 12 11:39:06 2003
@@ -23,8 +23,10 @@ extern int get_signals(void);
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { set_signals(flags); } while(0)
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
+				     (flags) = get_signals(); } while(0)
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+				      set_signals(flags); } while(0)
 
 #define local_irq_save(flags) do { local_save_flags(flags); \
                                    local_irq_disable(); } while(0)
@@ -39,4 +41,7 @@ extern void unblock_signals(void);
         (flags == 0);                   \
 })
 
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
 #endif
diff -puN include/asm-um/thread_info.h~uml-update include/asm-um/thread_info.h
--- 25/include/asm-um/thread_info.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/thread_info.h	Fri Sep 12 11:39:06 2003
@@ -9,6 +9,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/processor.h>
+#include <asm/types.h>
 
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
@@ -43,15 +44,18 @@ struct thread_info {
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL));
+	unsigned long mask = PAGE_SIZE * 
+		(1 << CONFIG_KERNEL_STACK_ORDER) - 1;
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
 	return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (4*PAGE_SIZE)
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-	__get_free_pages(GFP_KERNEL,2))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
+#define alloc_thread_info(tsk) \
+	((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
+#define free_thread_info(ti) kfree(ti)
+	
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
@@ -65,11 +69,13 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling 
 					 * TIF_NEED_RESCHED 
 					 */
+#define TIF_RESTART_BLOCK 	4
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+#define _TIF_RESTART_BLOCK	(1 << TIF_RESTART_BLOCK)
 
 #endif
 
diff -puN include/asm-um/timex.h~uml-update include/asm-um/timex.h
--- 25/include/asm-um/timex.h~uml-update	Fri Sep 12 11:39:06 2003
+++ 25-akpm/include/asm-um/timex.h	Fri Sep 12 11:39:06 2003
@@ -1,8 +1,6 @@
 #ifndef __UM_TIMEX_H
 #define __UM_TIMEX_H
 
-#include "linux/time.h"
-
 typedef unsigned long cycles_t;
 
 #define cacheflush_time (0)

_