+++ /dev/null
-diff -Naur a/arch/um/Kconfig b/arch/um/Kconfig
---- a/arch/um/Kconfig Fri Aug 15 15:05:57 2003
-+++ b/arch/um/Kconfig Fri Aug 15 15:11:53 2003
-@@ -61,6 +61,20 @@
-
- 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"
-
-@@ -85,6 +99,19 @@
- If you'd like to be able to work with files stored on the host,
- say Y or M here; otherwise say N.
-
-+config HPPFS
-+ tristate "HoneyPot ProcFS"
-+ help
-+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
-+ entries to be overridden, removed, or fabricated from the host.
-+ Its purpose is to allow a UML to appear to be a physical machine
-+ by removing or changing anything in /proc which gives away the
-+ identity of a UML.
-+
-+ See http://user-mode-linux.sf.net/hppfs.html for more information.
-+
-+ You only need this if you are setting up a UML honeypot. Otherwise,
-+ it is safe to say 'N' here.
-
- config MCONSOLE
- bool "Management console"
-@@ -105,6 +132,16 @@
- 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"
-@@ -159,6 +196,9 @@
- config HIGHMEM
- bool "Highmem support"
-
-+config PROC_MM
-+ bool "/proc/mm support"
-+
- config KERNEL_STACK_ORDER
- int "Kernel stack size order"
- default 2
-@@ -239,6 +279,10 @@
- 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 -Naur a/arch/um/Kconfig_block b/arch/um/Kconfig_block
---- a/arch/um/Kconfig_block Fri Aug 15 15:07:32 2003
-+++ b/arch/um/Kconfig_block Fri Aug 15 15:12:56 2003
-@@ -29,6 +29,20 @@
- 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 -Naur a/arch/um/Kconfig_net b/arch/um/Kconfig_net
---- a/arch/um/Kconfig_net Fri Aug 15 15:06:52 2003
-+++ b/arch/um/Kconfig_net Fri Aug 15 15:12:43 2003
-@@ -1,5 +1,5 @@
-
--menu "Network Devices"
-+menu "UML Network Devices"
- depends on NET
-
- # UML virtual driver
-@@ -176,73 +176,5 @@
-
- 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 -Naur a/arch/um/Makefile b/arch/um/Makefile
---- a/arch/um/Makefile Fri Aug 15 15:07:18 2003
-+++ b/arch/um/Makefile Fri Aug 15 15:12:45 2003
-@@ -24,15 +24,17 @@
- # 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 @@
- 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 @@
-
- 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
-@@ -116,6 +121,7 @@
-
- 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 += -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)/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 -Naur a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
---- a/arch/um/Makefile-i386 Fri Aug 15 15:07:46 2003
-+++ b/arch/um/Makefile-i386 Fri Aug 15 15:13:14 2003
-@@ -16,22 +16,28 @@
-
- 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 -Naur a/arch/um/Makefile-skas b/arch/um/Makefile-skas
---- a/arch/um/Makefile-skas Fri Aug 15 15:05:43 2003
-+++ b/arch/um/Makefile-skas Fri Aug 15 15:11:52 2003
-@@ -14,7 +14,7 @@
- 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 -Naur a/arch/um/config.release b/arch/um/config.release
---- a/arch/um/config.release Fri Aug 15 15:09:05 2003
-+++ b/arch/um/config.release Fri Aug 15 15:13:48 2003
-@@ -228,7 +228,6 @@
- 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 -Naur a/arch/um/defconfig b/arch/um/defconfig
---- a/arch/um/defconfig Fri Aug 15 15:07:30 2003
-+++ b/arch/um/defconfig Fri Aug 15 15:12:54 2003
-@@ -6,7 +6,6 @@
- CONFIG_SWAP=y
- CONFIG_UID16=y
- CONFIG_RWSEM_GENERIC_SPINLOCK=y
--CONFIG_CONFIG_LOG_BUF_SHIFT=14
-
- #
- # Code maturity level options
-@@ -116,7 +115,6 @@
- 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
-@@ -385,7 +383,6 @@
- #
- # Disk-On-Chip Device Drivers
- #
--# CONFIG_MTD_DOC1000 is not set
- # CONFIG_MTD_DOC2000 is not set
- # CONFIG_MTD_DOC2001 is not set
-
-diff -Naur a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
---- a/arch/um/drivers/Makefile Fri Aug 15 15:06:42 2003
-+++ b/arch/um/drivers/Makefile Fri Aug 15 15:12:40 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_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_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 -Naur a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
---- a/arch/um/drivers/chan_kern.c Fri Aug 15 15:09:13 2003
-+++ b/arch/um/drivers/chan_kern.c Fri Aug 15 15:13:51 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 -Naur a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
---- a/arch/um/drivers/chan_user.c Fri Aug 15 15:03:46 2003
-+++ b/arch/um/drivers/chan_user.c Fri Aug 15 15:10:09 2003
-@@ -188,8 +188,8 @@
- 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 -Naur a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
---- a/arch/um/drivers/cow.h Wed Dec 31 19:00:00 1969
-+++ b/arch/um/drivers/cow.h Fri Aug 15 15:10:34 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 -Naur a/arch/um/drivers/cow_kern.c b/arch/um/drivers/cow_kern.c
---- a/arch/um/drivers/cow_kern.c Wed Dec 31 19:00:00 1969
-+++ b/arch/um/drivers/cow_kern.c Fri Aug 15 15:13:51 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(¤t->sigmask_lock);
-+ sigfillset(¤t->blocked);
-+ flush_signals(current);
-+ spin_unlock_irq(¤t->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 -Naur a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
---- a/arch/um/drivers/cow_sys.h Wed Dec 31 19:00:00 1969
-+++ b/arch/um/drivers/cow_sys.h Fri Aug 15 15:12:37 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 -Naur a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
---- a/arch/um/drivers/cow_user.c Wed Dec 31 19:00:00 1969
-+++ b/arch/um/drivers/cow_user.c Fri Aug 15 15:12:34 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 -Naur a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
---- a/arch/um/drivers/hostaudio_kern.c Fri Aug 15 15:09:05 2003
-+++ b/arch/um/drivers/hostaudio_kern.c Fri Aug 15 15:13:48 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 @@
- #ifndef MODULE
- static int set_dsp(char *name, int *add)
- {
-- dsp = uml_strdup(name);
-+ dsp = name;
- return(0);
- }
-
-@@ -34,7 +35,7 @@
-
- static int set_mixer(char *name, int *add)
- {
-- mixer = uml_strdup(name);
-+ mixer = name;
- return(0);
- }
-
-@@ -51,23 +52,55 @@
- 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 @@
- 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 @@
-
- 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 -Naur a/arch/um/drivers/line.c b/arch/um/drivers/line.c
---- a/arch/um/drivers/line.c Fri Aug 15 15:08:24 2003
-+++ b/arch/um/drivers/line.c Fri Aug 15 15:13:28 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 @@
- 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 @@
- * 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 @@
-
- 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 @@
- }
-
- 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 @@
- 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 @@
-
- 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 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 @@
- 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 @@
-
- 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 -Naur a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
---- a/arch/um/drivers/mconsole_kern.c Fri Aug 15 15:03:47 2003
-+++ b/arch/um/drivers/mconsole_kern.c Fri Aug 15 15:10:11 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 @@
-
- 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 @@
- }
- 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 @@
- 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 @@
- 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 -Naur a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
---- a/arch/um/drivers/mconsole_user.c Fri Aug 15 15:04:47 2003
-+++ b/arch/um/drivers/mconsole_user.c Fri Aug 15 15:10:35 2003
-@@ -28,6 +28,7 @@
- { "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 @@
- 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 -Naur a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
---- a/arch/um/drivers/mmapper_kern.c Fri Aug 15 15:04:33 2003
-+++ b/arch/um/drivers/mmapper_kern.c Fri Aug 15 15:10:32 2003
-@@ -120,7 +120,10 @@
- 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 -Naur a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
---- a/arch/um/drivers/net_kern.c Fri Aug 15 15:05:49 2003
-+++ b/arch/um/drivers/net_kern.c Fri Aug 15 15:11:52 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 @@
- 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 @@
-
- out:
- spin_unlock(&lp->lock);
-+ return(IRQ_HANDLED);
- }
-
- static int uml_net_open(struct net_device *dev)
-@@ -292,7 +294,7 @@
- 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);
-@@ -362,21 +364,29 @@
- 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;
-diff -Naur a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
---- a/arch/um/drivers/port_kern.c Fri Aug 15 15:04:01 2003
-+++ b/arch/um/drivers/port_kern.c Fri Aug 15 15:10:18 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 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 @@
- 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 @@
- 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 @@
-
- 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 -Naur a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
---- a/arch/um/drivers/ssl.c Fri Aug 15 15:06:09 2003
-+++ b/arch/um/drivers/ssl.c Fri Aug 15 15:12:30 2003
-@@ -53,8 +53,9 @@
-
- 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 -Naur a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
---- a/arch/um/drivers/stdio_console.c Fri Aug 15 15:04:51 2003
-+++ b/arch/um/drivers/stdio_console.c Fri Aug 15 15:10:56 2003
-@@ -83,7 +83,8 @@
-
- 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 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 @@
- 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 @@
- 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 @@
- 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 -Naur a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
---- a/arch/um/drivers/ubd_kern.c Fri Aug 15 15:05:56 2003
-+++ b/arch/um/drivers/ubd_kern.c Fri Aug 15 15:11:53 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"
-@@ -70,7 +78,7 @@
- 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];
-@@ -99,12 +107,12 @@
-
- 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;
- };
-
-@@ -118,12 +126,12 @@
-
- #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, \
- }
-
-@@ -131,8 +139,10 @@
-
- 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);
- }
-
-@@ -199,19 +209,39 @@
- " 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);
-@@ -223,20 +253,14 @@
- 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);
-@@ -246,25 +270,23 @@
- 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;
- }
-@@ -279,6 +301,11 @@
- flags.s = 1;
- str++;
- }
-+ if (*str == 'd'){
-+ dev->no_cow = 1;
-+ str++;
-+ }
-+
- if(*str++ != '='){
- printk(KERN_ERR "ubd_setup : Expected '='\n");
- goto out2;
-@@ -287,14 +314,17 @@
- 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);
-@@ -324,8 +354,7 @@
- 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;
- }
-@@ -394,9 +423,10 @@
- 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. */
-@@ -432,16 +462,18 @@
- 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,
-@@ -458,7 +490,10 @@
- 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,
-@@ -484,17 +519,31 @@
-
- {
- 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;
-@@ -509,10 +558,7 @@
- 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))
-@@ -526,7 +572,7 @@
- if(err)
- return(err);
-
-- if(fake_major)
-+ if(fake_major != MAJOR_NR)
- ubd_new_disk(fake_major, dev->size, n,
- &fake_gendisk[n]);
-
-@@ -564,42 +610,42 @@
- 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)
-@@ -607,11 +653,9 @@
- 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];
-@@ -672,7 +716,7 @@
-
- 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);
-@@ -717,15 +761,9 @@
- {
- 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",
-@@ -799,15 +837,6 @@
-
- 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 -Naur a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
---- a/arch/um/drivers/ubd_user.c Fri Aug 15 15:04:51 2003
-+++ b/arch/um/drivers/ubd_user.c Fri Aug 15 15:10:54 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);
- }
-@@ -178,6 +60,7 @@
- long long actual;
- int err;
-
-+ printk("%ld", htonll(size));
- if(stat64(file, &buf) < 0){
- printk("Failed to stat backing file \"%s\", errno = %d\n",
- file, errno);
-@@ -215,118 +98,6 @@
- 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 +117,17 @@
- 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,
-- §orsize, bitmap_offset_out);
-+ err = read_cow_header(file_reader, &fd, &magic, &backing_file, &mtime,
-+ &size, §orsize, 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 +154,12 @@
- 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 +167,7 @@
- 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 +178,12 @@
- 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 +206,6 @@
- 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 -Naur a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
---- a/arch/um/drivers/xterm.c Fri Aug 15 15:04:00 2003
-+++ b/arch/um/drivers/xterm.c Fri Aug 15 15:10:18 2003
-@@ -108,7 +108,7 @@
- }
- 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 -Naur a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
---- a/arch/um/drivers/xterm_kern.c Fri Aug 15 15:07:37 2003
-+++ b/arch/um/drivers/xterm_kern.c Fri Aug 15 15:13:03 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 @@
- 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 -Naur a/arch/um/dyn.lds.S b/arch/um/dyn.lds.S
---- a/arch/um/dyn.lds.S Fri Aug 15 15:06:20 2003
-+++ b/arch/um/dyn.lds.S Fri Aug 15 15:12:31 2003
-@@ -15,7 +15,11 @@
- . = 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 @@
-
- #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 -Naur a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h
---- a/arch/um/include/irq_kern.h Wed Dec 31 19:00:00 1969
-+++ b/arch/um/include/irq_kern.h Fri Aug 15 15:11:53 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 -Naur a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
---- a/arch/um/include/kern_util.h Fri Aug 15 15:05:04 2003
-+++ b/arch/um/include/kern_util.h Fri Aug 15 15:11:18 2003
-@@ -63,10 +63,9 @@
- 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 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 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 -Naur a/arch/um/include/line.h b/arch/um/include/line.h
---- a/arch/um/include/line.h Fri Aug 15 15:07:40 2003
-+++ b/arch/um/include/line.h Fri Aug 15 15:13:11 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 @@
-
- #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 -Naur a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
---- a/arch/um/include/mconsole.h Fri Aug 15 15:05:26 2003
-+++ b/arch/um/include/mconsole.h Fri Aug 15 15:11:43 2003
-@@ -77,6 +77,7 @@
- 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 -Naur a/arch/um/include/mem.h b/arch/um/include/mem.h
---- a/arch/um/include/mem.h Fri Aug 15 15:09:22 2003
-+++ b/arch/um/include/mem.h Fri Aug 15 15:14:01 2003
-@@ -13,7 +13,6 @@
- };
-
- extern void set_usable_vm(unsigned long start, unsigned long end);
--extern void set_kmem_end(unsigned long new);
-
- #endif
-
-diff -Naur a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
---- a/arch/um/include/mem_user.h Fri Aug 15 15:07:31 2003
-+++ b/arch/um/include/mem_user.h Fri Aug 15 15:12:54 2003
-@@ -51,9 +51,6 @@
-
- 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 -Naur a/arch/um/include/os.h b/arch/um/include/os.h
---- a/arch/um/include/os.h Fri Aug 15 15:04:50 2003
-+++ b/arch/um/include/os.h Fri Aug 15 15:10:48 2003
-@@ -103,10 +103,11 @@
- 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_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 -Naur a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
---- a/arch/um/include/sysdep-i386/sigcontext.h Fri Aug 15 15:07:37 2003
-+++ b/arch/um/include/sysdep-i386/sigcontext.h Fri Aug 15 15:13:03 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 -Naur a/arch/um/include/ubd_user.h b/arch/um/include/ubd_user.h
---- a/arch/um/include/ubd_user.h Fri Aug 15 15:06:34 2003
-+++ b/arch/um/include/ubd_user.h Fri Aug 15 15:12:37 2003
-@@ -39,7 +39,6 @@
- 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 -Naur a/arch/um/include/user.h b/arch/um/include/user.h
---- a/arch/um/include/user.h Fri Aug 15 15:03:58 2003
-+++ b/arch/um/include/user.h Fri Aug 15 15:10:14 2003
-@@ -14,7 +14,7 @@
- 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 -Naur a/arch/um/include/user_util.h b/arch/um/include/user_util.h
---- a/arch/um/include/user_util.h Fri Aug 15 15:04:33 2003
-+++ b/arch/um/include/user_util.h Fri Aug 15 15:10:32 2003
-@@ -59,7 +59,6 @@
- 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_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 -Naur a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
---- a/arch/um/kernel/Makefile Fri Aug 15 15:07:32 2003
-+++ b/arch/um/kernel/Makefile Fri Aug 15 15:12:57 2003
-@@ -19,6 +19,8 @@
- 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 \
-@@ -43,17 +45,13 @@
- $(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 -Naur a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in
---- a/arch/um/kernel/config.c.in Fri Aug 15 15:07:37 2003
-+++ b/arch/um/kernel/config.c.in Fri Aug 15 15:13:03 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 -Naur a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
---- a/arch/um/kernel/exec_kern.c Fri Aug 15 15:04:54 2003
-+++ b/arch/um/kernel/exec_kern.c Fri Aug 15 15:11:03 2003
-@@ -32,10 +32,15 @@
- CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
- }
-
-+extern void log_exec(char **argv, void *tty);
-+
- static int execve1(char *file, char **argv, char **env)
- {
- int error;
-
-+#ifdef CONFIG_TTY_LOG
-+ log_exec(argv, current->tty);
-+#endif
- error = do_execve(file, argv, env, ¤t->thread.regs);
- if (error == 0){
- current->ptrace &= ~PT_DTRACE;
-diff -Naur a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
---- a/arch/um/kernel/init_task.c Fri Aug 15 15:09:24 2003
-+++ b/arch/um/kernel/init_task.c Fri Aug 15 15:14:04 2003
-@@ -17,6 +17,7 @@
- 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 @@
- __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 -Naur a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
---- a/arch/um/kernel/irq.c Fri Aug 15 15:07:53 2003
-+++ b/arch/um/kernel/irq.c Fri Aug 15 15:13:18 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 @@
- 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 @@
- * 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 @@
- */
-
- 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 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 */
-diff -Naur a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
---- a/arch/um/kernel/mem.c Fri Aug 15 15:05:20 2003
-+++ b/arch/um/kernel/mem.c Fri Aug 15 15:11:21 2003
-@@ -119,11 +119,6 @@
- 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 @@
- 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 @@
- 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 @@
- 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 -Naur a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
---- a/arch/um/kernel/mem_user.c Fri Aug 15 15:06:25 2003
-+++ b/arch/um/kernel/mem_user.c Fri Aug 15 15:12:36 2003
-@@ -111,6 +111,11 @@
- offset = 0;
- }
-
-+ if(offset >= region->len){
-+ printf("%d 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 @@
-
- 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 -Naur a/arch/um/kernel/process.c b/arch/um/kernel/process.c
---- a/arch/um/kernel/process.c Fri Aug 15 15:08:15 2003
-+++ b/arch/um/kernel/process.c Fri Aug 15 15:13:26 2003
-@@ -72,7 +72,6 @@
- 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 @@
- 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 -Naur a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
---- a/arch/um/kernel/process_kern.c Fri Aug 15 15:06:24 2003
-+++ b/arch/um/kernel/process_kern.c Fri Aug 15 15:12:35 2003
-@@ -52,17 +52,12 @@
-
- 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 @@
-
- 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,
-@@ -157,6 +153,10 @@
- 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 @@
-
- void default_idle(void)
- {
-- idle_timer();
-+ uml_idle_timer();
-
- atomic_inc(&init_mm.mm_count);
- current->mm = &init_mm;
-@@ -363,6 +363,11 @@
- return(clear_user(buf, size));
- }
-
-+int strlen_user_proc(char *str)
-+{
-+ return(strlen_user(str));
-+}
-+
- int smp_sigio_handler(void)
- {
- #ifdef CONFIG_SMP
-diff -Naur a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
---- a/arch/um/kernel/ptrace.c Fri Aug 15 15:04:36 2003
-+++ b/arch/um/kernel/ptrace.c Fri Aug 15 15:10:33 2003
-@@ -311,11 +311,8 @@
-
- /* 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 -Naur a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c
---- a/arch/um/kernel/sigio_kern.c Fri Aug 15 15:04:52 2003
-+++ b/arch/um/kernel/sigio_kern.c Fri Aug 15 15:10:59 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 -Naur a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
---- a/arch/um/kernel/signal_kern.c Fri Aug 15 15:06:38 2003
-+++ b/arch/um/kernel/signal_kern.c Fri Aug 15 15:12:40 2003
-@@ -36,7 +36,7 @@
- if(sig == SIGSEGV){
- struct k_sigaction *ka;
-
-- ka = ¤t->sig->action[SIGSEGV - 1];
-+ ka = ¤t->sighand->action[SIGSEGV - 1];
- ka->sa.sa_handler = SIG_DFL;
- }
- force_sig(SIGSEGV, current);
-@@ -142,7 +142,7 @@
- return(0);
-
- /* Whee! Actually deliver the signal. */
-- ka = ¤t->sig->action[sig -1 ];
-+ ka = ¤t->sighand->action[sig -1 ];
- err = handle_signal(regs, sig, ka, &info, oldset, error);
- if(!err) return(1);
-
-@@ -201,7 +201,7 @@
- }
- }
-
--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_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(¤t->thread.regs)));
-+}
-+
- static int copy_sc_from_user(struct pt_regs *to, void *from,
- struct arch_frame_data *arch)
- {
-@@ -239,8 +275,8 @@
-
- int sys_sigreturn(struct pt_regs regs)
- {
-- void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
-- void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
-+ void __user *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
-+ void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
- int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
-
- spin_lock_irq(¤t->sighand->siglock);
-@@ -257,7 +293,8 @@
-
- int sys_rt_sigreturn(struct pt_regs regs)
- {
-- struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs));
-+ unsigned long sp = PT_REGS_SP(¤t->thread.regs);
-+ struct ucontext __user *uc = sp_to_uc(sp);
- void *fp;
- int sig_size = _NSIG_WORDS * sizeof(unsigned long);
-
-diff -Naur a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
---- a/arch/um/kernel/skas/Makefile Fri Aug 15 15:05:00 2003
-+++ b/arch/um/kernel/skas/Makefile Fri Aug 15 15:11:08 2003
-@@ -7,18 +7,22 @@
- 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 -Naur a/arch/um/kernel/skas/include/mode.h b/arch/um/kernel/skas/include/mode.h
---- a/arch/um/kernel/skas/include/mode.h Fri Aug 15 15:06:34 2003
-+++ b/arch/um/kernel/skas/include/mode.h Fri Aug 15 15:12:37 2003
-@@ -20,6 +20,7 @@
- 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 -Naur a/arch/um/kernel/skas/include/uaccess.h b/arch/um/kernel/skas/include/uaccess.h
---- a/arch/um/kernel/skas/include/uaccess.h Fri Aug 15 15:05:28 2003
-+++ b/arch/um/kernel/skas/include/uaccess.h Fri Aug 15 15:11:44 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 -Naur a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
---- a/arch/um/kernel/skas/process.c Fri Aug 15 15:08:54 2003
-+++ b/arch/um/kernel/skas/process.c Fri Aug 15 15:13:46 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];
-@@ -72,8 +83,6 @@
- handle_syscall(regs);
- }
-
--int userspace_pid;
--
- static int userspace_tramp(void *arg)
- {
- init_new_thread_signals(0);
-@@ -83,6 +92,8 @@
- return(0);
- }
-
-+int userspace_pid;
-+
- void start_userspace(void)
- {
- void *stack;
-@@ -149,6 +160,7 @@
- case SIGILL:
- case SIGBUS:
- case SIGFPE:
-+ case SIGWINCH:
- user_signal(WSTOPSIG(status), regs);
- break;
- default:
-@@ -328,7 +340,8 @@
- 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 @@
- printk("new_mm : /proc/mm copy_segments failed, "
- "errno = %d\n", errno);
- }
-+
- return(fd);
- }
-
-diff -Naur a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
---- a/arch/um/kernel/skas/process_kern.c Fri Aug 15 15:04:51 2003
-+++ b/arch/um/kernel/skas/process_kern.c Fri Aug 15 15:10:56 2003
-@@ -61,9 +61,8 @@
- thread_wait(¤t->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, ¤t->thread.exec_buf);
-@@ -93,9 +92,8 @@
- 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();
-
-@@ -164,7 +162,7 @@
- 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 -Naur a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c
---- a/arch/um/kernel/skas/util/mk_ptregs.c Fri Aug 15 15:05:20 2003
-+++ b/arch/um/kernel/skas/util/mk_ptregs.c Fri Aug 15 15:11:21 2003
-@@ -1,3 +1,4 @@
-+#include <stdio.h>
- #include <asm/ptrace.h>
- #include <asm/user.h>
-
-diff -Naur a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
---- a/arch/um/kernel/smp.c Fri Aug 15 15:04:50 2003
-+++ b/arch/um/kernel/smp.c Fri Aug 15 15:10:52 2003
-@@ -140,8 +140,10 @@
-
- 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");
-
- cpu_tasks[cpu] = ((struct cpu_task)
- { .pid = new_task->thread.mode.tt.extern_pid,
-@@ -150,6 +152,7 @@
- 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);
- }
-
-@@ -254,15 +257,19 @@
- atomic_inc(&scf_finished);
- }
-
--int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
-- int wait)
-+int smp_call_function_on_cpu(void (*_func)(void *info), void *_info, int wait,
-+ unsigned long mask)
- {
-- int cpus = num_online_cpus() - 1;
-- int i;
--
-- if (!cpus)
-- return 0;
-+ int i, cpu, num_cpus;
-
-+ cpu = get_cpu();
-+ mask &= ~(1UL << cpu);
-+ num_cpus = hweight32(mask);
-+ if(num_cpus == 0){
-+ put_cpu_no_resched();
-+ return(0);
-+ }
-+
- spin_lock_bh(&call_lock);
- atomic_set(&scf_started, 0);
- atomic_set(&scf_finished, 0);
-@@ -270,19 +277,25 @@
- info = _info;
-
- for (i=0;i<NR_CPUS;i++)
-- if((i != current->thread_info->cpu) &&
-- test_bit(i, &cpu_online_map))
-+ if(cpu_online(i) && ((1UL << i) & mask))
- write(cpu_data[i].ipi_pipe[1], "C", 1);
-
-- while (atomic_read(&scf_started) != cpus)
-+ while(atomic_read(&scf_started) != num_cpus)
- barrier();
-
-- if (wait)
-- while (atomic_read(&scf_finished) != cpus)
-+ if(wait)
-+ while(atomic_read(&scf_finished) != num_cpus)
- barrier();
-
- spin_unlock_bh(&call_lock);
-- return 0;
-+ put_cpu_no_resched();
-+ return(0);
-+}
-+
-+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
-+ int wait)
-+{
-+ return(smp_call_function_on_cpu(_func, _info, wait, cpu_online_map));
- }
-
- #endif
-diff -Naur a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
---- a/arch/um/kernel/sys_call_table.c Fri Aug 15 15:07:57 2003
-+++ b/arch/um/kernel/sys_call_table.c Fri Aug 15 15:13:24 2003
-@@ -219,6 +219,18 @@
- 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;
-@@ -235,6 +247,19 @@
- 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;
-
- #ifdef CONFIG_NFSD
- #define NFSSERVCTL sys_nfsservctl
-@@ -459,18 +484,18 @@
- [ __NR_getdents64 ] = sys_getdents64,
- [ __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,
-@@ -488,6 +513,19 @@
- [ __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,
-
- ARCH_SYSCALLS
- [ LAST_SYSCALL + 1 ... NR_syscalls ] =
-diff -Naur a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
---- a/arch/um/kernel/syscall_kern.c Fri Aug 15 15:07:37 2003
-+++ b/arch/um/kernel/syscall_kern.c Fri Aug 15 15:13:03 2003
-@@ -35,39 +35,40 @@
-
- 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;
-@@ -79,9 +80,9 @@
- goto out;
- }
-
-- down_write(¤t->mm->mmap_sem);
-- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-- up_write(¤t->mm->mmap_sem);
-+ down_write(&mm->mmap_sem);
-+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
-+ up_write(&mm->mmap_sem);
-
- if (file)
- fput(file);
-@@ -93,7 +94,7 @@
- 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 @@
- 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 @@
- 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 @@
- return sys_shmctl (first, second,
- (struct shmid_ds *) ptr);
- default:
-- return -EINVAL;
-+ return -ENOSYS;
- }
- }
-
-@@ -302,11 +273,6 @@
- return error;
- }
-
--int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
--{
-- return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
--}
--
- long execute_syscall(void *r)
- {
- return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
-diff -Naur a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
---- a/arch/um/kernel/sysrq.c Fri Aug 15 15:05:01 2003
-+++ b/arch/um/kernel/sysrq.c Fri Aug 15 15:11:13 2003
-@@ -11,6 +11,14 @@
- #include "sysrq.h"
- #include "user_util.h"
-
-+void show_stack(struct task_struct *task, unsigned long *sp)
-+{
-+ if(task)
-+ show_trace_task(task);
-+ else
-+ show_trace(sp);
-+}
-+
- void show_trace(unsigned long * stack)
- {
- int i;
-diff -Naur a/arch/um/kernel/time.c b/arch/um/kernel/time.c
---- a/arch/um/kernel/time.c Fri Aug 15 15:04:49 2003
-+++ b/arch/um/kernel/time.c Fri Aug 15 15:10:46 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 @@
- 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 @@
- set_interval(ITIMER_VIRTUAL);
- }
-
--struct timeval local_offset = { 0, 0 };
--
- void do_gettimeofday(struct timeval *tv)
- {
- unsigned long flags;
-@@ -100,7 +102,7 @@
- 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 @@
- gettimeofday(&now, NULL);
- timersub(&tv_in, &now, &local_offset);
- time_unlock(flags);
-+
-+ return(0);
- }
-
- void idle_sleep(int secs)
-diff -Naur a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
---- a/arch/um/kernel/time_kern.c Fri Aug 15 15:07:19 2003
-+++ b/arch/um/kernel/time_kern.c Fri Aug 15 15:12:46 2003
-@@ -55,12 +55,13 @@
- do_timer(®s);
- }
-
--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_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,7 +123,9 @@
- 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)
- timer_irq(regs);
-diff -Naur a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
---- a/arch/um/kernel/trap_kern.c Fri Aug 15 15:04:01 2003
-+++ b/arch/um/kernel/trap_kern.c Fri Aug 15 15:10:18 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"
-@@ -180,6 +181,11 @@
- else relay_signal(sig, regs);
- }
-
-+void winch(int sig, union uml_pt_regs *regs)
-+{
-+ do_IRQ(WINCH_IRQ, regs);
-+}
-+
- void trap_init(void)
- {
- }
-diff -Naur a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
---- a/arch/um/kernel/trap_user.c Fri Aug 15 15:05:45 2003
-+++ b/arch/um/kernel/trap_user.c Fri Aug 15 15:11:52 2003
-@@ -82,6 +82,8 @@
- .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 -Naur a/arch/um/kernel/tt/include/uaccess.h b/arch/um/kernel/tt/include/uaccess.h
---- a/arch/um/kernel/tt/include/uaccess.h Fri Aug 15 15:07:25 2003
-+++ b/arch/um/kernel/tt/include/uaccess.h Fri Aug 15 15:12:52 2003
-@@ -46,18 +46,20 @@
-
- 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,
-- ¤t->thread.fault_addr,
-- ¤t->thread.fault_catcher) : n);
-+ if(!access_ok_tt(VERIFY_READ, from, n))
-+ return(n);
-+
-+ return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr,
-+ ¤t->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,
-- ¤t->thread.fault_addr,
-- ¤t->thread.fault_catcher) : n);
-+ if(!access_ok_tt(VERIFY_WRITE, to, n))
-+ return(n);
-+
-+ return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
- }
-
- extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
-@@ -67,7 +69,9 @@
- {
- 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,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher);
-@@ -87,10 +91,11 @@
-
- static inline int clear_user_tt(void *mem, int len)
- {
-- return(access_ok_tt(VERIFY_WRITE, mem, len) ?
-- __do_clear_user(mem, len,
-- ¤t->thread.fault_addr,
-- ¤t->thread.fault_catcher) : len);
-+ if(!access_ok_tt(VERIFY_WRITE, mem, len))
-+ return(len);
-+
-+ return(__do_clear_user(mem, len, ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
- }
-
- extern int __do_strnlen_user(const char *str, unsigned long n,
-diff -Naur a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
---- a/arch/um/kernel/tt/process_kern.c Fri Aug 15 15:07:55 2003
-+++ b/arch/um/kernel/tt/process_kern.c Fri Aug 15 15:13:23 2003
-@@ -104,7 +104,10 @@
-
- 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 @@
- UPT_SC(¤t->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, ¤t->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 @@
- UPT_SC(¤t->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;
--
- 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);
- }
-
-diff -Naur a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
---- a/arch/um/kernel/tt/ptproxy/proxy.c Fri Aug 15 15:07:01 2003
-+++ b/arch/um/kernel/tt/ptproxy/proxy.c Fri Aug 15 15:12:44 2003
-@@ -293,10 +293,10 @@
- }
-
- 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 -Naur a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
---- a/arch/um/kernel/tt/tracer.c Fri Aug 15 15:03:51 2003
-+++ b/arch/um/kernel/tt/tracer.c Fri Aug 15 15:10:12 2003
-@@ -39,7 +39,7 @@
- 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 @@
-
- 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 -Naur a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
---- a/arch/um/kernel/tt/uaccess_user.c Fri Aug 15 15:05:00 2003
-+++ b/arch/um/kernel/tt/uaccess_user.c Fri Aug 15 15:11:10 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 @@
- 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 @@
- 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_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 @@
- }
- *fault_addr = NULL;
- *fault_catcher = NULL;
-+
-+ TASK_REGS(get_current())->tt = save;
- return ret;
- }
-
-diff -Naur a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c
---- a/arch/um/kernel/tty_log.c Fri Aug 15 15:07:04 2003
-+++ b/arch/um/kernel/tty_log.c Fri Aug 15 15:12:44 2003
-@@ -13,6 +13,7 @@
- #include <sys/time.h>
- #include "init.h"
- #include "user.h"
-+#include "kern_util.h"
- #include "os.h"
-
- #define TTY_LOG_DIR "./"
-@@ -24,29 +25,40 @@
- #define TTY_LOG_OPEN 1
- #define TTY_LOG_CLOSE 2
- #define TTY_LOG_WRITE 3
-+#define TTY_LOG_EXEC 4
-+
-+#define TTY_READ 1
-+#define TTY_WRITE 2
-
- struct tty_log_buf {
- int what;
- unsigned long tty;
- int len;
-+ int direction;
-+ unsigned long sec;
-+ unsigned long usec;
- };
-
--int open_tty_log(void *tty)
-+int open_tty_log(void *tty, void *current_tty)
- {
- struct timeval tv;
- struct tty_log_buf data;
- char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
- int fd;
-
-+ gettimeofday(&tv, NULL);
- if(tty_log_fd != -1){
-- data = ((struct tty_log_buf) { what : TTY_LOG_OPEN,
-- tty : (unsigned long) tty,
-- len : 0 });
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN,
-+ .tty = (unsigned long) tty,
-+ .len = sizeof(current_tty),
-+ .direction = 0,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
- write(tty_log_fd, &data, sizeof(data));
-+ write(tty_log_fd, ¤t_tty, data.len);
- return(tty_log_fd);
- }
-
-- gettimeofday(&tv, NULL);
- sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
- (unsigned int) tv.tv_usec);
-
-@@ -62,30 +74,114 @@
- void close_tty_log(int fd, void *tty)
- {
- struct tty_log_buf data;
-+ struct timeval tv;
-
- if(tty_log_fd != -1){
-- data = ((struct tty_log_buf) { what : TTY_LOG_CLOSE,
-- tty : (unsigned long) tty,
-- len : 0 });
-+ gettimeofday(&tv, NULL);
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE,
-+ .tty = (unsigned long) tty,
-+ .len = 0,
-+ .direction = 0,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
- write(tty_log_fd, &data, sizeof(data));
- return;
- }
- close(fd);
- }
-
--int write_tty_log(int fd, char *buf, int len, void *tty)
-+static int log_chunk(int fd, const char *buf, int len)
- {
-+ int total = 0, try, missed, n;
-+ char chunk[64];
-+
-+ while(len > 0){
-+ try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
-+ missed = copy_from_user_proc(chunk, (char *) buf, try);
-+ try -= missed;
-+ n = write(fd, chunk, try);
-+ if(n != try)
-+ return(-errno);
-+ if(missed != 0)
-+ return(-EFAULT);
-+
-+ len -= try;
-+ total += try;
-+ buf += try;
-+ }
-+
-+ return(total);
-+}
-+
-+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
-+{
-+ struct timeval tv;
- struct tty_log_buf data;
-+ int direction;
-
- if(fd == tty_log_fd){
-- data = ((struct tty_log_buf) { what : TTY_LOG_WRITE,
-- tty : (unsigned long) tty,
-- len : len });
-+ gettimeofday(&tv, NULL);
-+ direction = is_read ? TTY_READ : TTY_WRITE;
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE,
-+ .tty = (unsigned long) tty,
-+ .len = len,
-+ .direction = direction,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
- write(tty_log_fd, &data, sizeof(data));
- }
-- return(write(fd, buf, len));
-+
-+ return(log_chunk(fd, buf, len));
- }
-
-+void log_exec(char **argv, void *tty)
-+{
-+ struct timeval tv;
-+ struct tty_log_buf data;
-+ char **ptr,*arg;
-+ int len;
-+
-+ if(tty_log_fd == -1) return;
-+
-+ gettimeofday(&tv, NULL);
-+
-+ len = 0;
-+ for(ptr = argv; ; ptr++){
-+ if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
-+ return;
-+ if(arg == NULL) break;
-+ len += strlen_user_proc(arg);
-+ }
-+
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC,
-+ .tty = (unsigned long) tty,
-+ .len = len,
-+ .direction = 0,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
-+ write(tty_log_fd, &data, sizeof(data));
-+
-+ for(ptr = argv; ; ptr++){
-+ if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
-+ return;
-+ if(arg == NULL) break;
-+ log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
-+ }
-+}
-+
-+extern void register_tty_logger(int (*opener)(void *, void *),
-+ int (*writer)(int, const char *, int,
-+ void *, int),
-+ void (*closer)(int, void *));
-+
-+static int register_logger(void)
-+{
-+ register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
-+ return(0);
-+}
-+
-+__uml_initcall(register_logger);
-+
- static int __init set_tty_log_dir(char *name, int *add)
- {
- tty_log_dir = name;
-@@ -104,7 +200,7 @@
-
- tty_log_fd = strtoul(name, &end, 0);
- if((*end != '\0') || (end == name)){
-- printk("set_tty_log_fd - strtoul failed on '%s'\n", name);
-+ printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
- tty_log_fd = -1;
- }
- return 0;
-diff -Naur a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
---- a/arch/um/kernel/um_arch.c Fri Aug 15 15:07:48 2003
-+++ b/arch/um/kernel/um_arch.c Fri Aug 15 15:13:14 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 @@
- 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 @@
- 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 @@
- 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 *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 *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 @@
- 2 * PAGE_SIZE;
-
- task_protections((unsigned long) &init_thread_info);
-+ os_flush_stdout();
-
- return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
- }
-diff -Naur a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
---- a/arch/um/kernel/umid.c Fri Aug 15 15:08:44 2003
-+++ b/arch/um/kernel/umid.c Fri Aug 15 15:13:39 2003
-@@ -33,18 +33,19 @@
- 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_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 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 @@
- 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 @@
- 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 @@
- 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 @@
- 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 @@
- * 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 @@
- 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_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 -Naur a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
---- a/arch/um/kernel/user_util.c Fri Aug 15 15:04:48 2003
-+++ b/arch/um/kernel/user_util.c Fri Aug 15 15:10:41 2003
-@@ -119,17 +119,6 @@
- }
- }
-
--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 -Naur a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
---- a/arch/um/os-Linux/drivers/tuntap_user.c Fri Aug 15 15:09:23 2003
-+++ b/arch/um/os-Linux/drivers/tuntap_user.c Fri Aug 15 15:14:02 2003
-@@ -142,7 +142,7 @@
- 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 -Naur a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
---- a/arch/um/os-Linux/file.c Fri Aug 15 15:09:15 2003
-+++ b/arch/um/os-Linux/file.c Fri Aug 15 15:13:54 2003
-@@ -315,7 +315,7 @@
- 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 @@
- 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 @@
- 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 -Naur a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
---- a/arch/um/sys-i386/Makefile Fri Aug 15 15:04:47 2003
-+++ b/arch/um/sys-i386/Makefile Fri Aug 15 15:10:35 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 @@
- 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 @@
- $(SYMLINKS):
- $(call make_link,$@)
-
--clean:
-- $(MAKE) -C util clean
-+subdir- := util
-
- fastdep:
-
-diff -Naur a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
---- a/arch/um/sys-i386/bugs.c Fri Aug 15 15:07:41 2003
-+++ b/arch/um/sys-i386/bugs.c Fri Aug 15 15:13:14 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 @@
- 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 @@
- "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 @@
- 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 -Naur a/arch/um/uml.lds.S b/arch/um/uml.lds.S
---- a/arch/um/uml.lds.S Fri Aug 15 15:05:37 2003
-+++ b/arch/um/uml.lds.S Fri Aug 15 15:11:48 2003
-@@ -26,7 +26,11 @@
- . = 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 @@
-
- #include "asm/common.lds.S"
-
-- .data.init : { *(.data.init) }
-+ init.data : { *(init.data) }
- .data :
- {
- . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
-diff -Naur a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c
---- a/arch/um/util/mk_constants_kern.c Fri Aug 15 15:04:15 2003
-+++ b/arch/um/util/mk_constants_kern.c Fri Aug 15 15:10:27 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 @@
- {
- 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 @@
- 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 -Naur a/fs/Makefile b/fs/Makefile
---- a/fs/Makefile Fri Aug 15 15:06:45 2003
-+++ b/fs/Makefile Fri Aug 15 15:12:41 2003
-@@ -91,3 +91,5 @@
- obj-$(CONFIG_XFS_FS) += xfs/
- obj-$(CONFIG_AFS_FS) += afs/
- obj-$(CONFIG_BEFS_FS) += befs/
-+obj-$(CONFIG_HOSTFS) += hostfs/
-+obj-$(CONFIG_HPPFS) += hppfs/
-diff -Naur a/fs/hostfs/Makefile b/fs/hostfs/Makefile
---- a/fs/hostfs/Makefile Wed Dec 31 19:00:00 1969
-+++ b/fs/hostfs/Makefile Fri Aug 15 15:10:07 2003
-@@ -0,0 +1,36 @@
-+#
-+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino
-+# to __st_ino. It stayed in the same place, so as long as the correct name
-+# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa.
-+
-+STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
-+ echo __)st_ino
-+
-+hostfs-objs := hostfs_kern.o hostfs_user.o
-+
-+obj-y =
-+obj-$(CONFIG_HOSTFS) += hostfs.o
-+
-+SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
-+
-+USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS))
-+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-+
-+USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD)
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean:
-+
-+modules:
-+
-+fastdep:
-+
-+dep:
-+
-+archmrproper: clean
-diff -Naur a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
---- a/fs/hostfs/hostfs.h Wed Dec 31 19:00:00 1969
-+++ b/fs/hostfs/hostfs.h Fri Aug 15 15:10:06 2003
-@@ -0,0 +1,79 @@
-+#ifndef __UM_FS_HOSTFS
-+#define __UM_FS_HOSTFS
-+
-+#include "os.h"
-+
-+/* These are exactly the same definitions as in fs.h, but the names are
-+ * changed so that this file can be included in both kernel and user files.
-+ */
-+
-+#define HOSTFS_ATTR_MODE 1
-+#define HOSTFS_ATTR_UID 2
-+#define HOSTFS_ATTR_GID 4
-+#define HOSTFS_ATTR_SIZE 8
-+#define HOSTFS_ATTR_ATIME 16
-+#define HOSTFS_ATTR_MTIME 32
-+#define HOSTFS_ATTR_CTIME 64
-+#define HOSTFS_ATTR_ATIME_SET 128
-+#define HOSTFS_ATTR_MTIME_SET 256
-+#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */
-+#define HOSTFS_ATTR_ATTR_FLAG 1024
-+
-+struct hostfs_iattr {
-+ unsigned int ia_valid;
-+ mode_t ia_mode;
-+ uid_t ia_uid;
-+ gid_t ia_gid;
-+ loff_t ia_size;
-+ struct timespec ia_atime;
-+ struct timespec ia_mtime;
-+ struct timespec ia_ctime;
-+ unsigned int ia_attr_flags;
-+};
-+
-+extern int stat_file(const char *path, unsigned long long *inode_out,
-+ int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
-+ unsigned long long *size_out, struct timespec *atime_out,
-+ struct timespec *mtime_out, struct timespec *ctime_out,
-+ int *blksize_out, unsigned long long *blocks_out);
-+extern int access_file(char *path, int r, int w, int x);
-+extern int open_file(char *path, int r, int w, int append);
-+extern int file_type(const char *path, int *rdev);
-+extern void *open_dir(char *path, int *err_out);
-+extern char *read_dir(void *stream, unsigned long long *pos,
-+ unsigned long long *ino_out, int *len_out);
-+extern void close_file(void *stream);
-+extern void close_dir(void *stream);
-+extern int read_file(int fd, unsigned long long *offset, char *buf, int len);
-+extern int write_file(int fd, unsigned long long *offset, const char *buf,
-+ int len);
-+extern int lseek_file(int fd, long long offset, int whence);
-+extern int file_create(char *name, int ur, int uw, int ux, int gr,
-+ int gw, int gx, int or, int ow, int ox);
-+extern int set_attr(const char *file, struct hostfs_iattr *attrs);
-+extern int make_symlink(const char *from, const char *to);
-+extern int unlink_file(const char *file);
-+extern int do_mkdir(const char *file, int mode);
-+extern int do_rmdir(const char *file);
-+extern int do_mknod(const char *file, int mode, int dev);
-+extern int link_file(const char *from, const char *to);
-+extern int do_readlink(char *file, char *buf, int size);
-+extern int rename_file(char *from, char *to);
-+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
-+ long long *bfree_out, long long *bavail_out,
-+ long long *files_out, long long *ffree_out,
-+ void *fsid_out, int fsid_size, long *namelen_out,
-+ long *spare_out);
-+
-+#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 -Naur a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
---- a/fs/hostfs/hostfs_kern.c Wed Dec 31 19:00:00 1969
-+++ b/fs/hostfs/hostfs_kern.c Fri Aug 15 15:10:12 2003
-@@ -0,0 +1,1010 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ *
-+ * Ported the filesystem routines to 2.5.
-+ * 2003-02-10 Petr Baudis <pasky@ucw.cz>
-+ */
-+
-+#include <linux/stddef.h>
-+#include <linux/fs.h>
-+#include <linux/version.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/pagemap.h>
-+#include <linux/blkdev.h>
-+#include <linux/list.h>
-+#include <linux/buffer_head.h>
-+#include <linux/root_dev.h>
-+#include <linux/statfs.h>
-+#include <asm/uaccess.h>
-+#include "hostfs.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "user_util.h"
-+#include "2_5compat.h"
-+#include "init.h"
-+
-+struct hostfs_inode_info {
-+ char *host_filename;
-+ int fd;
-+ int mode;
-+ struct inode vfs_inode;
-+};
-+
-+static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
-+{
-+ return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
-+}
-+
-+#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode)
-+
-+int hostfs_d_delete(struct dentry *dentry)
-+{
-+ return(1);
-+}
-+
-+struct dentry_operations hostfs_dentry_ops = {
-+ .d_delete = hostfs_d_delete,
-+};
-+
-+/* Changed in hostfs_args before the kernel starts running */
-+static char *root_ino = "/";
-+static int append = 0;
-+
-+#define HOSTFS_SUPER_MAGIC 0x00c0ffee
-+
-+static struct inode_operations hostfs_iops;
-+static struct inode_operations hostfs_dir_iops;
-+static struct address_space_operations hostfs_link_aops;
-+
-+static int __init hostfs_args(char *options, int *add)
-+{
-+ char *ptr;
-+
-+ ptr = strchr(options, ',');
-+ if(ptr != NULL)
-+ *ptr++ = '\0';
-+ if(*options != '\0')
-+ root_ino = options;
-+
-+ options = ptr;
-+ while(options){
-+ ptr = strchr(options, ',');
-+ if(ptr != NULL)
-+ *ptr++ = '\0';
-+ if(*options != '\0'){
-+ if(!strcmp(options, "append"))
-+ append = 1;
-+ else printf("hostfs_args - unsupported option - %s\n",
-+ options);
-+ }
-+ options = ptr;
-+ }
-+ return(0);
-+}
-+
-+__uml_setup("hostfs=", hostfs_args,
-+"hostfs=<root dir>,<flags>,...\n"
-+" This is used to set hostfs parameters. The root directory argument\n"
-+" is used to confine all hostfs mounts to within the specified directory\n"
-+" tree on the host. If this isn't specified, then a user inside UML can\n"
-+" mount anything on the host that's accessible to the user that's running\n"
-+" it.\n"
-+" The only flag currently supported is 'append', which specifies that all\n"
-+" files opened by hostfs will be opened in append mode.\n\n"
-+);
-+
-+static char *dentry_name(struct dentry *dentry, int extra)
-+{
-+ struct dentry *parent;
-+ char *root, *name;
-+ int len;
-+
-+ len = 0;
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ len += parent->d_name.len + 1;
-+ parent = parent->d_parent;
-+ }
-+
-+ root = HOSTFS_I(parent->d_inode)->host_filename;
-+ len += strlen(root);
-+ name = kmalloc(len + extra + 1, GFP_KERNEL);
-+ if(name == NULL) return(NULL);
-+
-+ name[len] = '\0';
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ len -= parent->d_name.len + 1;
-+ name[len] = '/';
-+ strncpy(&name[len + 1], parent->d_name.name,
-+ parent->d_name.len);
-+ parent = parent->d_parent;
-+ }
-+ strncpy(name, root, strlen(root));
-+ return(name);
-+}
-+
-+static char *inode_name(struct inode *ino, int extra)
-+{
-+ struct dentry *dentry;
-+
-+ dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
-+ return(dentry_name(dentry, extra));
-+}
-+
-+static int read_name(struct inode *ino, char *name)
-+{
-+ /* The non-int inode fields are copied into ints by stat_file and
-+ * then copied into the inode because passing the actual pointers
-+ * in and having them treated as int * breaks on big-endian machines
-+ */
-+ int err;
-+ int i_mode, i_nlink, i_blksize;
-+ unsigned long long i_size;
-+ unsigned long long i_ino;
-+ unsigned long long i_blocks;
-+
-+ err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
-+ &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
-+ &ino->i_ctime, &i_blksize, &i_blocks);
-+ if(err)
-+ return(err);
-+
-+ ino->i_ino = i_ino;
-+ ino->i_mode = i_mode;
-+ ino->i_nlink = i_nlink;
-+ ino->i_size = i_size;
-+ ino->i_blksize = i_blksize;
-+ ino->i_blocks = i_blocks;
-+ if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid()))
-+ ino->i_uid = 0;
-+ return(0);
-+}
-+
-+static char *follow_link(char *link)
-+{
-+ int len, n;
-+ char *name, *resolved, *end;
-+
-+ len = 64;
-+ while(1){
-+ n = -ENOMEM;
-+ name = kmalloc(len, GFP_KERNEL);
-+ if(name == NULL)
-+ goto out;
-+
-+ n = do_readlink(link, name, len);
-+ if(n < len)
-+ break;
-+ len *= 2;
-+ kfree(name);
-+ }
-+ if(n < 0)
-+ goto out_free;
-+
-+ if(*name == '/')
-+ return(name);
-+
-+ end = strrchr(link, '/');
-+ if(end == NULL)
-+ return(name);
-+
-+ *(end + 1) = '\0';
-+ len = strlen(link) + strlen(name) + 1;
-+
-+ resolved = kmalloc(len, GFP_KERNEL);
-+ if(resolved == NULL){
-+ n = -ENOMEM;
-+ goto out_free;
-+ }
-+
-+ sprintf(resolved, "%s%s", link, name);
-+ kfree(name);
-+ kfree(link);
-+ return(resolved);
-+
-+ out_free:
-+ kfree(name);
-+ out:
-+ return(ERR_PTR(n));
-+}
-+
-+static int read_inode(struct inode *ino)
-+{
-+ char *name;
-+ int err = 0;
-+
-+ /* Unfortunately, we are called from iget() when we don't have a dentry
-+ * allocated yet.
-+ */
-+ if(list_empty(&ino->i_dentry))
-+ goto out;
-+
-+ err = -ENOMEM;
-+ name = inode_name(ino, 0);
-+ if(name == NULL)
-+ goto out;
-+
-+ if(file_type(name, NULL) == OS_TYPE_SYMLINK){
-+ name = follow_link(name);
-+ if(IS_ERR(name)){
-+ err = PTR_ERR(name);
-+ goto out;
-+ }
-+ }
-+
-+ err = read_name(ino, name);
-+ kfree(name);
-+ out:
-+ return(err);
-+}
-+
-+int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
-+{
-+ /* do_statfs uses struct statfs64 internally, but the linux kernel
-+ * struct statfs still has 32-bit versions for most of these fields,
-+ * so we convert them here
-+ */
-+ int err;
-+ long long f_blocks;
-+ long long f_bfree;
-+ long long f_bavail;
-+ long long f_files;
-+ long long f_ffree;
-+
-+ err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename,
-+ &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
-+ &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
-+ &sf->f_namelen, sf->f_spare);
-+ if(err) return(err);
-+ sf->f_blocks = f_blocks;
-+ sf->f_bfree = f_bfree;
-+ sf->f_bavail = f_bavail;
-+ sf->f_files = f_files;
-+ sf->f_ffree = f_ffree;
-+ sf->f_type = HOSTFS_SUPER_MAGIC;
-+ return(0);
-+}
-+
-+static struct inode *hostfs_alloc_inode(struct super_block *sb)
-+{
-+ struct hostfs_inode_info *hi;
-+
-+ hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-+ if(hi == NULL)
-+ return(NULL);
-+
-+ *hi = ((struct hostfs_inode_info) { .host_filename = NULL,
-+ .fd = -1,
-+ .mode = 0 });
-+ inode_init_once(&hi->vfs_inode);
-+ return(&hi->vfs_inode);
-+}
-+
-+static void hostfs_destroy_inode(struct inode *inode)
-+{
-+ if(HOSTFS_I(inode)->host_filename)
-+ kfree(HOSTFS_I(inode)->host_filename);
-+
-+ if(HOSTFS_I(inode)->fd != -1)
-+ close_file(&HOSTFS_I(inode)->fd);
-+
-+ kfree(HOSTFS_I(inode));
-+}
-+
-+static void hostfs_read_inode(struct inode *inode)
-+{
-+ read_inode(inode);
-+}
-+
-+static struct super_operations hostfs_sbops = {
-+ .alloc_inode = hostfs_alloc_inode,
-+ .destroy_inode = hostfs_destroy_inode,
-+ .read_inode = hostfs_read_inode,
-+ .statfs = hostfs_statfs,
-+};
-+
-+int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
-+{
-+ void *dir;
-+ char *name;
-+ unsigned long long next, ino;
-+ int error, len;
-+
-+ name = dentry_name(file->f_dentry, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ dir = open_dir(name, &error);
-+ kfree(name);
-+ if(dir == NULL) return(-error);
-+ next = file->f_pos;
-+ while((name = read_dir(dir, &next, &ino, &len)) != NULL){
-+ error = (*filldir)(ent, name, len, file->f_pos,
-+ ino, DT_UNKNOWN);
-+ if(error) break;
-+ file->f_pos = next;
-+ }
-+ close_dir(dir);
-+ return(0);
-+}
-+
-+int hostfs_file_open(struct inode *ino, struct file *file)
-+{
-+ char *name;
-+ int mode = 0, r = 0, w = 0, fd;
-+
-+ mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
-+ if((mode & HOSTFS_I(ino)->mode) == mode)
-+ return(0);
-+
-+ /* The file may already have been opened, but with the wrong access,
-+ * so this resets things and reopens the file with the new access.
-+ */
-+ if(HOSTFS_I(ino)->fd != -1){
-+ close_file(&HOSTFS_I(ino)->fd);
-+ HOSTFS_I(ino)->fd = -1;
-+ }
-+
-+ HOSTFS_I(ino)->mode |= mode;
-+ if(HOSTFS_I(ino)->mode & FMODE_READ)
-+ r = 1;
-+ if(HOSTFS_I(ino)->mode & FMODE_WRITE)
-+ w = 1;
-+ if(w)
-+ r = 1;
-+
-+ name = dentry_name(file->f_dentry, 0);
-+ if(name == NULL)
-+ return(-ENOMEM);
-+
-+ fd = open_file(name, r, w, append);
-+ kfree(name);
-+ if(fd < 0) return(fd);
-+ FILE_HOSTFS_I(file)->fd = fd;
-+
-+ return(0);
-+}
-+
-+int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-+{
-+ return(0);
-+}
-+
-+static struct file_operations hostfs_file_fops = {
-+ .llseek = generic_file_llseek,
-+ .read = generic_file_read,
-+ .write = generic_file_write,
-+ .mmap = generic_file_mmap,
-+ .open = hostfs_file_open,
-+ .release = NULL,
-+ .fsync = hostfs_fsync,
-+};
-+
-+static struct file_operations hostfs_dir_fops = {
-+ .readdir = hostfs_readdir,
-+ .read = generic_read_dir,
-+};
-+
-+int hostfs_writepage(struct page *page, struct writeback_control *wbc)
-+{
-+ struct address_space *mapping = page->mapping;
-+ struct inode *inode = mapping->host;
-+ char *buffer;
-+ unsigned long long base;
-+ int count = PAGE_CACHE_SIZE;
-+ int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-+ int err;
-+
-+ if (page->index >= end_index)
-+ count = inode->i_size & (PAGE_CACHE_SIZE-1);
-+
-+ buffer = kmap(page);
-+ base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
-+
-+ err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
-+ if(err != count){
-+ ClearPageUptodate(page);
-+ goto out;
-+ }
-+
-+ if (base > inode->i_size)
-+ inode->i_size = base;
-+
-+ if (PageError(page))
-+ ClearPageError(page);
-+ err = 0;
-+
-+ out:
-+ kunmap(page);
-+
-+ unlock_page(page);
-+ return err;
-+}
-+
-+int hostfs_readpage(struct file *file, struct page *page)
-+{
-+ char *buffer;
-+ long long start;
-+ int err = 0;
-+
-+ start = (long long) page->index << PAGE_CACHE_SHIFT;
-+ buffer = kmap(page);
-+ err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
-+ PAGE_CACHE_SIZE);
-+ if(err < 0) goto out;
-+
-+ memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
-+
-+ flush_dcache_page(page);
-+ SetPageUptodate(page);
-+ if (PageError(page)) ClearPageError(page);
-+ err = 0;
-+ out:
-+ kunmap(page);
-+ unlock_page(page);
-+ return(err);
-+}
-+
-+int hostfs_prepare_write(struct file *file, struct page *page,
-+ unsigned int from, unsigned int to)
-+{
-+ char *buffer;
-+ long long start, tmp;
-+ int err;
-+
-+ start = (long long) page->index << PAGE_CACHE_SHIFT;
-+ buffer = kmap(page);
-+ if(from != 0){
-+ tmp = start;
-+ err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
-+ from);
-+ if(err < 0) goto out;
-+ }
-+ if(to != PAGE_CACHE_SIZE){
-+ start += to;
-+ err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
-+ PAGE_CACHE_SIZE - to);
-+ if(err < 0) goto out;
-+ }
-+ err = 0;
-+ out:
-+ kunmap(page);
-+ return(err);
-+}
-+
-+int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
-+ unsigned to)
-+{
-+ struct address_space *mapping = page->mapping;
-+ struct inode *inode = mapping->host;
-+ char *buffer;
-+ long long start;
-+ int err = 0;
-+
-+ start = (long long) (page->index << PAGE_CACHE_SHIFT) + from;
-+ buffer = kmap(page);
-+ err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
-+ to - from);
-+ if(err > 0) err = 0;
-+ if(!err && (start > inode->i_size))
-+ inode->i_size = start;
-+
-+ kunmap(page);
-+ return(err);
-+}
-+
-+static struct address_space_operations hostfs_aops = {
-+ .writepage = hostfs_writepage,
-+ .readpage = hostfs_readpage,
-+/* .set_page_dirty = __set_page_dirty_nobuffers, */
-+ .prepare_write = hostfs_prepare_write,
-+ .commit_write = hostfs_commit_write
-+};
-+
-+static int init_inode(struct inode *inode, struct dentry *dentry)
-+{
-+ char *name;
-+ int type, err = -ENOMEM, rdev;
-+
-+ if(dentry){
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL)
-+ goto out;
-+ type = file_type(name, &rdev);
-+ kfree(name);
-+ }
-+ else type = OS_TYPE_DIR;
-+
-+ err = 0;
-+ if(type == OS_TYPE_SYMLINK)
-+ inode->i_op = &page_symlink_inode_operations;
-+ else if(type == OS_TYPE_DIR)
-+ inode->i_op = &hostfs_dir_iops;
-+ else inode->i_op = &hostfs_iops;
-+
-+ if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
-+ else inode->i_fop = &hostfs_file_fops;
-+
-+ if(type == OS_TYPE_SYMLINK)
-+ inode->i_mapping->a_ops = &hostfs_link_aops;
-+ else inode->i_mapping->a_ops = &hostfs_aops;
-+
-+ switch (type) {
-+ case OS_TYPE_CHARDEV:
-+ init_special_inode(inode, S_IFCHR, rdev);
-+ break;
-+ case OS_TYPE_BLOCKDEV:
-+ init_special_inode(inode, S_IFBLK, rdev);
-+ break;
-+ case OS_TYPE_FIFO:
-+ init_special_inode(inode, S_IFIFO, 0);
-+ break;
-+ case OS_TYPE_SOCK:
-+ init_special_inode(inode, S_IFSOCK, 0);
-+ break;
-+ }
-+ out:
-+ return(err);
-+}
-+
-+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
-+ struct nameidata *nd)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int error, fd;
-+
-+ error = -ENOMEM;
-+ inode = iget(dir->i_sb, 0);
-+ if(inode == NULL) goto out;
-+
-+ error = init_inode(inode, dentry);
-+ if(error)
-+ goto out_put;
-+
-+ error = -ENOMEM;
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL)
-+ goto out_put;
-+
-+ fd = file_create(name,
-+ mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
-+ mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
-+ mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
-+ if(fd < 0)
-+ error = fd;
-+ else error = read_name(inode, name);
-+
-+ kfree(name);
-+ if(error)
-+ goto out_put;
-+
-+ HOSTFS_I(inode)->fd = fd;
-+ HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
-+ d_instantiate(dentry, inode);
-+ return(0);
-+
-+ out_free:
-+ kfree(name);
-+ out_put:
-+ iput(inode);
-+ out:
-+ return(error);
-+}
-+
-+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
-+ struct nameidata *nd)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int err;
-+
-+ err = -ENOMEM;
-+ inode = iget(ino->i_sb, 0);
-+ if(inode == NULL)
-+ goto out;
-+
-+ err = init_inode(inode, dentry);
-+ if(err)
-+ goto out_put;
-+
-+ err = -ENOMEM;
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL)
-+ goto out_put;
-+
-+ err = read_name(inode, name);
-+ kfree(name);
-+ if(err == -ENOENT){
-+ iput(inode);
-+ inode = NULL;
-+ }
-+ else if(err)
-+ goto out_put;
-+
-+ d_add(dentry, inode);
-+ dentry->d_op = &hostfs_dentry_ops;
-+ return(NULL);
-+
-+ out_put:
-+ iput(inode);
-+ out:
-+ return(ERR_PTR(err));
-+}
-+
-+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
-+{
-+ char *file;
-+ int len;
-+
-+ file = inode_name(ino, dentry->d_name.len + 1);
-+ if(file == NULL) return(NULL);
-+ strcat(file, "/");
-+ len = strlen(file);
-+ strncat(file, dentry->d_name.name, dentry->d_name.len);
-+ file[len + dentry->d_name.len] = '\0';
-+ return(file);
-+}
-+
-+int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
-+{
-+ char *from_name, *to_name;
-+ int err;
-+
-+ if((from_name = inode_dentry_name(ino, from)) == NULL)
-+ return(-ENOMEM);
-+ to_name = dentry_name(to, 0);
-+ if(to_name == NULL){
-+ kfree(from_name);
-+ return(-ENOMEM);
-+ }
-+ err = link_file(to_name, from_name);
-+ kfree(from_name);
-+ kfree(to_name);
-+ return(err);
-+}
-+
-+int hostfs_unlink(struct inode *ino, struct dentry *dentry)
-+{
-+ char *file;
-+ int err;
-+
-+ if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
-+ if(append)
-+ return(-EPERM);
-+
-+ err = unlink_file(file);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
-+{
-+ char *file;
-+ int err;
-+
-+ if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
-+ err = make_symlink(file, to);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
-+{
-+ char *file;
-+ int err;
-+
-+ if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
-+ err = do_mkdir(file, mode);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
-+{
-+ char *file;
-+ int err;
-+
-+ if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
-+ err = do_rmdir(file);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int err = -ENOMEM;
-+
-+ inode = iget(dir->i_sb, 0);
-+ if(inode == NULL)
-+ goto out;
-+
-+ err = init_inode(inode, dentry);
-+ if(err)
-+ goto out_put;
-+
-+ err = -ENOMEM;
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL)
-+ goto out_put;
-+
-+ init_special_inode(inode, mode, dev);
-+ err = do_mknod(name, mode, dev);
-+ if(err)
-+ goto out_free;
-+
-+ err = read_name(inode, name);
-+ kfree(name);
-+ if(err)
-+ goto out_put;
-+
-+ d_instantiate(dentry, inode);
-+ return(0);
-+
-+ out_free:
-+ kfree(name);
-+ out_put:
-+ iput(inode);
-+ out:
-+ return(err);
-+}
-+
-+int hostfs_rename(struct inode *from_ino, struct dentry *from,
-+ struct inode *to_ino, struct dentry *to)
-+{
-+ char *from_name, *to_name;
-+ int err;
-+
-+ if((from_name = inode_dentry_name(from_ino, from)) == NULL)
-+ return(-ENOMEM);
-+ if((to_name = inode_dentry_name(to_ino, to)) == NULL){
-+ kfree(from_name);
-+ return(-ENOMEM);
-+ }
-+ err = rename_file(from_name, to_name);
-+ kfree(from_name);
-+ kfree(to_name);
-+ return(err);
-+}
-+
-+void hostfs_truncate(struct inode *ino)
-+{
-+ not_implemented();
-+}
-+
-+int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
-+{
-+ char *name;
-+ int r = 0, w = 0, x = 0, err;
-+
-+ if(desired & MAY_READ) r = 1;
-+ if(desired & MAY_WRITE) w = 1;
-+ if(desired & MAY_EXEC) x = 1;
-+ name = inode_name(ino, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ err = access_file(name, r, w, x);
-+ kfree(name);
-+ if(!err) err = vfs_permission(ino, desired);
-+ return(err);
-+}
-+
-+int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+ struct hostfs_iattr attrs;
-+ char *name;
-+ int err;
-+
-+ if(append)
-+ attr->ia_valid &= ~ATTR_SIZE;
-+
-+ attrs.ia_valid = 0;
-+ if(attr->ia_valid & ATTR_MODE){
-+ attrs.ia_valid |= HOSTFS_ATTR_MODE;
-+ attrs.ia_mode = attr->ia_mode;
-+ }
-+ if(attr->ia_valid & ATTR_UID){
-+ if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
-+ (attr->ia_uid == 0))
-+ attr->ia_uid = getuid();
-+ attrs.ia_valid |= HOSTFS_ATTR_UID;
-+ attrs.ia_uid = attr->ia_uid;
-+ }
-+ if(attr->ia_valid & ATTR_GID){
-+ if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
-+ (attr->ia_gid == 0))
-+ attr->ia_gid = getuid();
-+ attrs.ia_valid |= HOSTFS_ATTR_GID;
-+ attrs.ia_gid = attr->ia_gid;
-+ }
-+ if(attr->ia_valid & ATTR_SIZE){
-+ attrs.ia_valid |= HOSTFS_ATTR_SIZE;
-+ attrs.ia_size = attr->ia_size;
-+ }
-+ if(attr->ia_valid & ATTR_ATIME){
-+ attrs.ia_valid |= HOSTFS_ATTR_ATIME;
-+ attrs.ia_atime = attr->ia_atime;
-+ }
-+ if(attr->ia_valid & ATTR_MTIME){
-+ attrs.ia_valid |= HOSTFS_ATTR_MTIME;
-+ attrs.ia_mtime = attr->ia_mtime;
-+ }
-+ if(attr->ia_valid & ATTR_CTIME){
-+ attrs.ia_valid |= HOSTFS_ATTR_CTIME;
-+ attrs.ia_ctime = attr->ia_ctime;
-+ }
-+ if(attr->ia_valid & ATTR_ATIME_SET){
-+ attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
-+ }
-+ if(attr->ia_valid & ATTR_MTIME_SET){
-+ attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
-+ }
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ err = set_attr(name, &attrs);
-+ kfree(name);
-+ if(err)
-+ return(err);
-+
-+ return(inode_setattr(dentry->d_inode, attr));
-+}
-+
-+int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-+ struct kstat *stat)
-+{
-+ generic_fillattr(dentry->d_inode, stat);
-+ return(0);
-+}
-+
-+static struct inode_operations hostfs_iops = {
-+ .create = hostfs_create,
-+ .link = hostfs_link,
-+ .unlink = hostfs_unlink,
-+ .symlink = hostfs_symlink,
-+ .mkdir = hostfs_mkdir,
-+ .rmdir = hostfs_rmdir,
-+ .mknod = hostfs_mknod,
-+ .rename = hostfs_rename,
-+ .truncate = hostfs_truncate,
-+ .permission = hostfs_permission,
-+ .setattr = hostfs_setattr,
-+ .getattr = hostfs_getattr,
-+};
-+
-+static struct inode_operations hostfs_dir_iops = {
-+ .create = hostfs_create,
-+ .lookup = hostfs_lookup,
-+ .link = hostfs_link,
-+ .unlink = hostfs_unlink,
-+ .symlink = hostfs_symlink,
-+ .mkdir = hostfs_mkdir,
-+ .rmdir = hostfs_rmdir,
-+ .mknod = hostfs_mknod,
-+ .rename = hostfs_rename,
-+ .truncate = hostfs_truncate,
-+ .permission = hostfs_permission,
-+ .setattr = hostfs_setattr,
-+ .getattr = hostfs_getattr,
-+};
-+
-+int hostfs_link_readpage(struct file *file, struct page *page)
-+{
-+ char *buffer, *name;
-+ long long start;
-+ int err;
-+
-+ start = page->index << PAGE_CACHE_SHIFT;
-+ buffer = kmap(page);
-+ name = inode_name(page->mapping->host, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
-+ kfree(name);
-+ if(err == PAGE_CACHE_SIZE)
-+ err = -E2BIG;
-+ else if(err > 0){
-+ flush_dcache_page(page);
-+ SetPageUptodate(page);
-+ if (PageError(page)) ClearPageError(page);
-+ err = 0;
-+ }
-+ kunmap(page);
-+ unlock_page(page);
-+ return(err);
-+}
-+
-+static struct address_space_operations hostfs_link_aops = {
-+ .readpage = hostfs_link_readpage,
-+};
-+
-+static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
-+{
-+ struct inode *root_inode;
-+ char *name, *data = d;
-+ int err;
-+
-+ sb->s_blocksize = 1024;
-+ sb->s_blocksize_bits = 10;
-+ sb->s_magic = HOSTFS_SUPER_MAGIC;
-+ sb->s_op = &hostfs_sbops;
-+
-+ if((data == NULL) || (*data == '\0'))
-+ data = root_ino;
-+
-+ err = -ENOMEM;
-+ name = kmalloc(strlen(data) + 1, GFP_KERNEL);
-+ if(name == NULL)
-+ goto out;
-+
-+ strcpy(name, data);
-+
-+ root_inode = iget(sb, 0);
-+ if(root_inode == NULL)
-+ goto out_free;
-+
-+ err = init_inode(root_inode, NULL);
-+ if(err)
-+ goto out_put;
-+
-+ HOSTFS_I(root_inode)->host_filename = name;
-+
-+ err = -ENOMEM;
-+ sb->s_root = d_alloc_root(root_inode);
-+ if(sb->s_root == NULL)
-+ goto out_put;
-+
-+ err = read_inode(root_inode);
-+ if(err)
-+ goto out_put;
-+
-+ return(0);
-+
-+ out_put:
-+ iput(root_inode);
-+ out_free:
-+ kfree(name);
-+ out:
-+ return(err);
-+}
-+
-+static struct super_block *hostfs_read_sb(struct file_system_type *type,
-+ int flags, const char *dev_name,
-+ void *data)
-+{
-+ return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common));
-+}
-+
-+static struct file_system_type hostfs_type = {
-+ .owner = THIS_MODULE,
-+ .name = "hostfs",
-+ .get_sb = hostfs_read_sb,
-+ .kill_sb = kill_anon_super,
-+ .fs_flags = 0,
-+};
-+
-+static int __init init_hostfs(void)
-+{
-+ return(register_filesystem(&hostfs_type));
-+}
-+
-+static void __exit exit_hostfs(void)
-+{
-+ unregister_filesystem(&hostfs_type);
-+}
-+
-+module_init(init_hostfs)
-+module_exit(exit_hostfs)
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * 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 -Naur a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
---- a/fs/hostfs/hostfs_user.c Wed Dec 31 19:00:00 1969
-+++ b/fs/hostfs/hostfs_user.c Fri Aug 15 15:10:43 2003
-@@ -0,0 +1,361 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <fcntl.h>
-+#include <dirent.h>
-+#include <errno.h>
-+#include <utime.h>
-+#include <string.h>
-+#include <sys/stat.h>
-+#include <sys/time.h>
-+#include <sys/vfs.h>
-+#include "hostfs.h"
-+#include "kern_util.h"
-+#include "user.h"
-+
-+int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
-+ int *nlink_out, int *uid_out, int *gid_out,
-+ unsigned long long *size_out, struct timespec *atime_out,
-+ struct timespec *mtime_out, struct timespec *ctime_out,
-+ int *blksize_out, unsigned long long *blocks_out)
-+{
-+ struct stat64 buf;
-+
-+ if(lstat64(path, &buf) < 0)
-+ return(-errno);
-+
-+ /* See the Makefile for why STAT64_INO_FIELD is passed in
-+ * by the build
-+ */
-+ if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD;
-+ if(mode_out != NULL) *mode_out = buf.st_mode;
-+ if(nlink_out != NULL) *nlink_out = buf.st_nlink;
-+ if(uid_out != NULL) *uid_out = buf.st_uid;
-+ if(gid_out != NULL) *gid_out = buf.st_gid;
-+ if(size_out != NULL) *size_out = buf.st_size;
-+ if(atime_out != NULL) {
-+ atime_out->tv_sec = buf.st_atime;
-+ atime_out->tv_nsec = 0;
-+ }
-+ if(mtime_out != NULL) {
-+ mtime_out->tv_sec = buf.st_mtime;
-+ mtime_out->tv_nsec = 0;
-+ }
-+ if(ctime_out != NULL) {
-+ ctime_out->tv_sec = buf.st_ctime;
-+ ctime_out->tv_nsec = 0;
-+ }
-+ if(blksize_out != NULL) *blksize_out = buf.st_blksize;
-+ if(blocks_out != NULL) *blocks_out = buf.st_blocks;
-+ return(0);
-+}
-+
-+int file_type(const char *path, int *rdev)
-+{
-+ struct stat64 buf;
-+
-+ if(lstat64(path, &buf) < 0)
-+ return(-errno);
-+ if(rdev != NULL)
-+ *rdev = buf.st_rdev;
-+
-+ if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
-+ else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
-+ else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
-+ else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
-+ else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO);
-+ else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK);
-+ else return(OS_TYPE_FILE);
-+}
-+
-+int access_file(char *path, int r, int w, int x)
-+{
-+ int mode = 0;
-+
-+ if(r) mode = R_OK;
-+ if(w) mode |= W_OK;
-+ if(x) mode |= X_OK;
-+ if(access(path, mode) != 0) return(-errno);
-+ else return(0);
-+}
-+
-+int open_file(char *path, int r, int w, int append)
-+{
-+ int mode = 0, fd;
-+
-+ if(r && !w)
-+ mode = O_RDONLY;
-+ else if(!r && w)
-+ mode = O_WRONLY;
-+ else if(r && w)
-+ mode = O_RDWR;
-+ else panic("Impossible mode in open_file");
-+
-+ if(append)
-+ mode |= O_APPEND;
-+ fd = open64(path, mode);
-+ if(fd < 0) return(-errno);
-+ else return(fd);
-+}
-+
-+void *open_dir(char *path, int *err_out)
-+{
-+ DIR *dir;
-+
-+ dir = opendir(path);
-+ *err_out = errno;
-+ if(dir == NULL) return(NULL);
-+ return(dir);
-+}
-+
-+char *read_dir(void *stream, unsigned long long *pos,
-+ unsigned long long *ino_out, int *len_out)
-+{
-+ DIR *dir = stream;
-+ struct dirent *ent;
-+
-+ seekdir(dir, *pos);
-+ ent = readdir(dir);
-+ if(ent == NULL) return(NULL);
-+ *len_out = strlen(ent->d_name);
-+ *ino_out = ent->d_ino;
-+ *pos = telldir(dir);
-+ return(ent->d_name);
-+}
-+
-+int read_file(int fd, unsigned long long *offset, char *buf, int len)
-+{
-+ int n;
-+
-+ n = pread64(fd, buf, len, *offset);
-+ if(n < 0) return(-errno);
-+ *offset += n;
-+ return(n);
-+}
-+
-+int write_file(int fd, unsigned long long *offset, const char *buf, int len)
-+{
-+ int n;
-+
-+ n = pwrite64(fd, buf, len, *offset);
-+ if(n < 0) return(-errno);
-+ *offset += n;
-+ return(n);
-+}
-+
-+int lseek_file(int fd, long long offset, int whence)
-+{
-+ int ret;
-+
-+ ret = lseek64(fd, offset, whence);
-+ if(ret < 0) return(-errno);
-+ return(0);
-+}
-+
-+void close_file(void *stream)
-+{
-+ close(*((int *) stream));
-+}
-+
-+void close_dir(void *stream)
-+{
-+ closedir(stream);
-+}
-+
-+int file_create(char *name, int ur, int uw, int ux, int gr,
-+ int gw, int gx, int or, int ow, int ox)
-+{
-+ int mode, fd;
-+
-+ mode = 0;
-+ mode |= ur ? S_IRUSR : 0;
-+ mode |= uw ? S_IWUSR : 0;
-+ mode |= ux ? S_IXUSR : 0;
-+ mode |= gr ? S_IRGRP : 0;
-+ mode |= gw ? S_IWGRP : 0;
-+ mode |= gx ? S_IXGRP : 0;
-+ mode |= or ? S_IROTH : 0;
-+ mode |= ow ? S_IWOTH : 0;
-+ mode |= ox ? S_IXOTH : 0;
-+ fd = open64(name, O_CREAT | O_RDWR, mode);
-+ if(fd < 0)
-+ return(-errno);
-+ return(fd);
-+}
-+
-+int set_attr(const char *file, struct hostfs_iattr *attrs)
-+{
-+ struct utimbuf buf;
-+ int err, ma;
-+
-+ if(attrs->ia_valid & HOSTFS_ATTR_MODE){
-+ if(chmod(file, attrs->ia_mode) != 0) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_UID){
-+ if(chown(file, attrs->ia_uid, -1)) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_GID){
-+ if(chown(file, -1, attrs->ia_gid)) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_SIZE){
-+ if(truncate(file, attrs->ia_size)) return(-errno);
-+ }
-+ ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET;
-+ if((attrs->ia_valid & ma) == ma){
-+ buf.actime = attrs->ia_atime.tv_sec;
-+ buf.modtime = attrs->ia_mtime.tv_sec;
-+ if(utime(file, &buf) != 0) return(-errno);
-+ }
-+ else {
-+ struct timespec ts;
-+
-+ if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){
-+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, &ts, NULL, NULL, NULL);
-+ if(err != 0)
-+ return(err);
-+ buf.actime = attrs->ia_atime.tv_sec;
-+ buf.modtime = ts.tv_sec;
-+ if(utime(file, &buf) != 0)
-+ return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){
-+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-+ NULL, &ts, NULL, NULL, NULL, NULL);
-+ if(err != 0)
-+ return(err);
-+ buf.actime = ts.tv_sec;
-+ buf.modtime = attrs->ia_mtime.tv_sec;
-+ if(utime(file, &buf) != 0)
-+ return(-errno);
-+ }
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
-+ if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
-+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
-+ &attrs->ia_atime, &attrs->ia_mtime, NULL,
-+ NULL, NULL);
-+ if(err != 0) return(err);
-+ }
-+ return(0);
-+}
-+
-+int make_symlink(const char *from, const char *to)
-+{
-+ int err;
-+
-+ err = symlink(to, from);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int unlink_file(const char *file)
-+{
-+ int err;
-+
-+ err = unlink(file);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_mkdir(const char *file, int mode)
-+{
-+ int err;
-+
-+ err = mkdir(file, mode);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_rmdir(const char *file)
-+{
-+ int err;
-+
-+ err = rmdir(file);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_mknod(const char *file, int mode, int dev)
-+{
-+ int err;
-+
-+ err = mknod(file, mode, dev);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int link_file(const char *to, const char *from)
-+{
-+ int err;
-+
-+ err = link(to, from);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_readlink(char *file, char *buf, int size)
-+{
-+ int n;
-+
-+ n = readlink(file, buf, size);
-+ if(n < 0)
-+ return(-errno);
-+ if(n < size)
-+ buf[n] = '\0';
-+ return(n);
-+}
-+
-+int rename_file(char *from, char *to)
-+{
-+ int err;
-+
-+ err = rename(from, to);
-+ if(err < 0) return(-errno);
-+ return(0);
-+}
-+
-+int do_statfs(char *root, long *bsize_out, long long *blocks_out,
-+ long long *bfree_out, long long *bavail_out,
-+ long long *files_out, long long *ffree_out,
-+ void *fsid_out, int fsid_size, long *namelen_out,
-+ long *spare_out)
-+{
-+ struct statfs64 buf;
-+ int err;
-+
-+ err = statfs64(root, &buf);
-+ if(err < 0) return(-errno);
-+ *bsize_out = buf.f_bsize;
-+ *blocks_out = buf.f_blocks;
-+ *bfree_out = buf.f_bfree;
-+ *bavail_out = buf.f_bavail;
-+ *files_out = buf.f_files;
-+ *ffree_out = buf.f_ffree;
-+ memcpy(fsid_out, &buf.f_fsid,
-+ sizeof(buf.f_fsid) > fsid_size ? fsid_size :
-+ sizeof(buf.f_fsid));
-+ *namelen_out = buf.f_namelen;
-+ spare_out[0] = buf.f_spare[0];
-+ spare_out[1] = buf.f_spare[1];
-+ spare_out[2] = buf.f_spare[2];
-+ spare_out[3] = buf.f_spare[3];
-+ spare_out[4] = buf.f_spare[4];
-+ spare_out[5] = buf.f_spare[5];
-+ return(0);
-+}
-+
-+/*
-+ * 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 -Naur a/fs/hppfs/Makefile b/fs/hppfs/Makefile
---- a/fs/hppfs/Makefile Wed Dec 31 19:00:00 1969
-+++ b/fs/hppfs/Makefile Fri Aug 15 15:12:31 2003
-@@ -0,0 +1,19 @@
-+#
-+# Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+hppfs-objs := hppfs_kern.o
-+
-+obj-y =
-+obj-$(CONFIG_HPPFS) += hppfs.o
-+
-+clean:
-+
-+modules:
-+
-+fastdep:
-+
-+dep:
-+
-+archmrproper: clean
-diff -Naur a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
---- a/fs/hppfs/hppfs_kern.c Wed Dec 31 19:00:00 1969
-+++ b/fs/hppfs/hppfs_kern.c Fri Aug 15 15:11:52 2003
-@@ -0,0 +1,811 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/list.h>
-+#include <linux/kernel.h>
-+#include <linux/ctype.h>
-+#include <linux/dcache.h>
-+#include <linux/statfs.h>
-+#include <asm/uaccess.h>
-+#include <asm/fcntl.h>
-+#include "os.h"
-+
-+static int init_inode(struct inode *inode, struct dentry *dentry);
-+
-+struct hppfs_data {
-+ struct list_head list;
-+ char contents[PAGE_SIZE - sizeof(struct list_head)];
-+};
-+
-+struct hppfs_private {
-+ struct file proc_file;
-+ int host_fd;
-+ loff_t len;
-+ struct hppfs_data *contents;
-+};
-+
-+struct hppfs_inode_info {
-+ struct dentry *proc_dentry;
-+ struct inode vfs_inode;
-+};
-+
-+static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
-+{
-+ return(list_entry(inode, struct hppfs_inode_info, vfs_inode));
-+}
-+
-+#define HPPFS_SUPER_MAGIC 0xb00000ee
-+
-+static struct super_operations hppfs_sbops;
-+
-+static int is_pid(struct dentry *dentry)
-+{
-+ struct super_block *sb;
-+ int i;
-+
-+ sb = dentry->d_sb;
-+ if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root))
-+ return(0);
-+
-+ for(i = 0; i < dentry->d_name.len; i++){
-+ if(!isdigit(dentry->d_name.name[i]))
-+ return(0);
-+ }
-+ return(1);
-+}
-+
-+static char *dentry_name(struct dentry *dentry, int extra)
-+{
-+ struct dentry *parent;
-+ char *root, *name;
-+ const char *seg_name;
-+ int len, seg_len;
-+
-+ len = 0;
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ if(is_pid(parent))
-+ len += strlen("pid") + 1;
-+ else len += parent->d_name.len + 1;
-+ parent = parent->d_parent;
-+ }
-+
-+ root = "proc";
-+ len += strlen(root);
-+ name = kmalloc(len + extra + 1, GFP_KERNEL);
-+ if(name == NULL) return(NULL);
-+
-+ name[len] = '\0';
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ if(is_pid(parent)){
-+ seg_name = "pid";
-+ seg_len = strlen("pid");
-+ }
-+ else {
-+ seg_name = parent->d_name.name;
-+ seg_len = parent->d_name.len;
-+ }
-+
-+ len -= seg_len + 1;
-+ name[len] = '/';
-+ strncpy(&name[len + 1], seg_name, seg_len);
-+ parent = parent->d_parent;
-+ }
-+ strncpy(name, root, strlen(root));
-+ return(name);
-+}
-+
-+struct dentry_operations hppfs_dentry_ops = {
-+};
-+
-+static int file_removed(struct dentry *dentry, const char *file)
-+{
-+ char *host_file;
-+ int extra, fd;
-+
-+ extra = 0;
-+ if(file != NULL) extra += strlen(file) + 1;
-+
-+ host_file = dentry_name(dentry, extra + strlen("/remove"));
-+ if(host_file == NULL){
-+ printk("file_removed : allocation failed\n");
-+ return(-ENOMEM);
-+ }
-+
-+ if(file != NULL){
-+ strcat(host_file, "/");
-+ strcat(host_file, file);
-+ }
-+ strcat(host_file, "/remove");
-+
-+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
-+ kfree(host_file);
-+ if(fd > 0){
-+ os_close_file(fd);
-+ return(1);
-+ }
-+ return(0);
-+}
-+
-+static void hppfs_read_inode(struct inode *ino)
-+{
-+ struct inode *proc_ino;
-+
-+ if(HPPFS_I(ino)->proc_dentry == NULL)
-+ return;
-+
-+ proc_ino = HPPFS_I(ino)->proc_dentry->d_inode;
-+ ino->i_uid = proc_ino->i_uid;
-+ ino->i_gid = proc_ino->i_gid;
-+ ino->i_atime = proc_ino->i_atime;
-+ ino->i_mtime = proc_ino->i_mtime;
-+ ino->i_ctime = proc_ino->i_ctime;
-+ ino->i_ino = proc_ino->i_ino;
-+ ino->i_mode = proc_ino->i_mode;
-+ ino->i_nlink = proc_ino->i_nlink;
-+ ino->i_size = proc_ino->i_size;
-+ ino->i_blksize = proc_ino->i_blksize;
-+ ino->i_blocks = proc_ino->i_blocks;
-+}
-+
-+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
-+ struct nameidata *nd)
-+{
-+ struct dentry *proc_dentry, *new, *parent;
-+ struct inode *inode;
-+ int err, deleted;
-+
-+ deleted = file_removed(dentry, NULL);
-+ if(deleted < 0)
-+ return(ERR_PTR(deleted));
-+ else if(deleted)
-+ return(ERR_PTR(-ENOENT));
-+
-+ err = -ENOMEM;
-+ parent = HPPFS_I(ino)->proc_dentry;
-+ down(&parent->d_inode->i_sem);
-+ proc_dentry = d_lookup(parent, &dentry->d_name);
-+ if(proc_dentry == NULL){
-+ proc_dentry = d_alloc(parent, &dentry->d_name);
-+ if(proc_dentry == NULL){
-+ up(&parent->d_inode->i_sem);
-+ goto out;
-+ }
-+ new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
-+ proc_dentry, NULL);
-+ if(new){
-+ dput(proc_dentry);
-+ proc_dentry = new;
-+ }
-+ }
-+ up(&parent->d_inode->i_sem);
-+
-+ if(IS_ERR(proc_dentry))
-+ return(proc_dentry);
-+
-+ inode = iget(ino->i_sb, 0);
-+ if(inode == NULL)
-+ goto out_dput;
-+
-+ err = init_inode(inode, proc_dentry);
-+ if(err)
-+ goto out_put;
-+
-+ hppfs_read_inode(inode);
-+
-+ d_add(dentry, inode);
-+ dentry->d_op = &hppfs_dentry_ops;
-+ return(NULL);
-+
-+ out_put:
-+ iput(inode);
-+ out_dput:
-+ dput(proc_dentry);
-+ out:
-+ return(ERR_PTR(err));
-+}
-+
-+static struct inode_operations hppfs_file_iops = {
-+};
-+
-+static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
-+ loff_t *ppos, int is_user)
-+{
-+ ssize_t (*read)(struct file *, char *, size_t, loff_t *);
-+ ssize_t n;
-+
-+ read = file->f_dentry->d_inode->i_fop->read;
-+
-+ if(!is_user)
-+ set_fs(KERNEL_DS);
-+
-+ n = (*read)(file, buf, count, &file->f_pos);
-+
-+ if(!is_user)
-+ set_fs(USER_DS);
-+
-+ if(ppos) *ppos = file->f_pos;
-+ return(n);
-+}
-+
-+static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
-+{
-+ ssize_t n;
-+ int cur, err;
-+ char *new_buf;
-+
-+ n = -ENOMEM;
-+ new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+ if(new_buf == NULL){
-+ printk("hppfs_read_file : kmalloc failed\n");
-+ goto out;
-+ }
-+ n = 0;
-+ while(count > 0){
-+ cur = min_t(ssize_t, count, PAGE_SIZE);
-+ err = os_read_file(fd, new_buf, cur);
-+ if(err < 0){
-+ printk("hppfs_read : read failed, errno = %d\n",
-+ count);
-+ n = err;
-+ goto out_free;
-+ }
-+ else if(err == 0)
-+ break;
-+
-+ if(copy_to_user(buf, new_buf, err)){
-+ n = -EFAULT;
-+ goto out_free;
-+ }
-+ n += err;
-+ count -= err;
-+ }
-+ out_free:
-+ kfree(new_buf);
-+ out:
-+ return(n);
-+}
-+
-+static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
-+ loff_t *ppos)
-+{
-+ struct hppfs_private *hppfs = file->private_data;
-+ struct hppfs_data *data;
-+ loff_t off;
-+ int err;
-+
-+ if(hppfs->contents != NULL){
-+ if(*ppos >= hppfs->len) return(0);
-+
-+ data = hppfs->contents;
-+ off = *ppos;
-+ while(off >= sizeof(data->contents)){
-+ data = list_entry(data->list.next, struct hppfs_data,
-+ list);
-+ off -= sizeof(data->contents);
-+ }
-+
-+ if(off + count > hppfs->len)
-+ count = hppfs->len - off;
-+ copy_to_user(buf, &data->contents[off], count);
-+ *ppos += count;
-+ }
-+ else if(hppfs->host_fd != -1){
-+ err = os_seek_file(hppfs->host_fd, *ppos);
-+ if(err){
-+ printk("hppfs_read : seek failed, errno = %d\n", err);
-+ return(err);
-+ }
-+ count = hppfs_read_file(hppfs->host_fd, buf, count);
-+ if(count > 0)
-+ *ppos += count;
-+ }
-+ else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1);
-+
-+ return(count);
-+}
-+
-+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
-+ loff_t *ppos)
-+{
-+ struct hppfs_private *data = file->private_data;
-+ struct file *proc_file = &data->proc_file;
-+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
-+ int err;
-+
-+ write = proc_file->f_dentry->d_inode->i_fop->write;
-+
-+ proc_file->f_pos = file->f_pos;
-+ err = (*write)(proc_file, buf, len, &proc_file->f_pos);
-+ file->f_pos = proc_file->f_pos;
-+
-+ return(err);
-+}
-+
-+static int open_host_sock(char *host_file, int *filter_out)
-+{
-+ char *end;
-+ int fd;
-+
-+ end = &host_file[strlen(host_file)];
-+ strcpy(end, "/rw");
-+ *filter_out = 1;
-+ fd = os_connect_socket(host_file);
-+ if(fd > 0)
-+ return(fd);
-+
-+ strcpy(end, "/r");
-+ *filter_out = 0;
-+ fd = os_connect_socket(host_file);
-+ return(fd);
-+}
-+
-+static void free_contents(struct hppfs_data *head)
-+{
-+ struct hppfs_data *data;
-+ struct list_head *ele, *next;
-+
-+ if(head == NULL) return;
-+
-+ list_for_each_safe(ele, next, &head->list){
-+ data = list_entry(ele, struct hppfs_data, list);
-+ kfree(data);
-+ }
-+ kfree(head);
-+}
-+
-+static struct hppfs_data *hppfs_get_data(int fd, int filter,
-+ struct file *proc_file,
-+ struct file *hppfs_file,
-+ loff_t *size_out)
-+{
-+ struct hppfs_data *data, *new, *head;
-+ int n, err;
-+
-+ err = -ENOMEM;
-+ data = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(data == NULL){
-+ printk("hppfs_get_data : head allocation failed\n");
-+ goto failed;
-+ }
-+
-+ INIT_LIST_HEAD(&data->list);
-+
-+ head = data;
-+ *size_out = 0;
-+
-+ if(filter){
-+ while((n = read_proc(proc_file, data->contents,
-+ sizeof(data->contents), NULL, 0)) > 0)
-+ os_write_file(fd, data->contents, n);
-+ err = os_shutdown_socket(fd, 0, 1);
-+ if(err){
-+ printk("hppfs_get_data : failed to shut down "
-+ "socket\n");
-+ goto failed_free;
-+ }
-+ }
-+ while(1){
-+ n = os_read_file(fd, data->contents, sizeof(data->contents));
-+ if(n < 0){
-+ err = n;
-+ printk("hppfs_get_data : read failed, errno = %d\n",
-+ err);
-+ goto failed_free;
-+ }
-+ else if(n == 0)
-+ break;
-+
-+ *size_out += n;
-+
-+ if(n < sizeof(data->contents))
-+ break;
-+
-+ new = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(new == 0){
-+ printk("hppfs_get_data : data allocation failed\n");
-+ err = -ENOMEM;
-+ goto failed_free;
-+ }
-+
-+ INIT_LIST_HEAD(&new->list);
-+ list_add(&new->list, &data->list);
-+ data = new;
-+ }
-+ return(head);
-+
-+ failed_free:
-+ free_contents(head);
-+ failed:
-+ return(ERR_PTR(err));
-+}
-+
-+static struct hppfs_private *hppfs_data(void)
-+{
-+ struct hppfs_private *data;
-+
-+ data = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(data == NULL)
-+ return(data);
-+
-+ *data = ((struct hppfs_private ) { .host_fd = -1,
-+ .len = -1,
-+ .contents = NULL } );
-+ return(data);
-+}
-+
-+static int file_mode(int fmode)
-+{
-+ if(fmode == (FMODE_READ | FMODE_WRITE))
-+ return(O_RDWR);
-+ if(fmode == FMODE_READ)
-+ return(O_RDONLY);
-+ if(fmode == FMODE_WRITE)
-+ return(O_WRONLY);
-+ return(0);
-+}
-+
-+static int hppfs_open(struct inode *inode, struct file *file)
-+{
-+ struct hppfs_private *data;
-+ struct dentry *proc_dentry;
-+ char *host_file;
-+ int err, fd, type, filter;
-+
-+ err = -ENOMEM;
-+ data = hppfs_data();
-+ if(data == NULL)
-+ goto out;
-+
-+ host_file = dentry_name(file->f_dentry, strlen("/rw"));
-+ if(host_file == NULL)
-+ goto out_free2;
-+
-+ proc_dentry = HPPFS_I(inode)->proc_dentry;
-+
-+ /* XXX This isn't closed anywhere */
-+ err = open_private_file(&data->proc_file, proc_dentry,
-+ file_mode(file->f_mode));
-+ if(err)
-+ goto out_free1;
-+
-+ type = os_file_type(host_file);
-+ if(type == OS_TYPE_FILE){
-+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
-+ if(fd >= 0)
-+ data->host_fd = fd;
-+ else printk("hppfs_open : failed to open '%s', errno = %d\n",
-+ host_file, -fd);
-+
-+ data->contents = NULL;
-+ }
-+ else if(type == OS_TYPE_DIR){
-+ fd = open_host_sock(host_file, &filter);
-+ if(fd > 0){
-+ data->contents = hppfs_get_data(fd, filter,
-+ &data->proc_file,
-+ file, &data->len);
-+ if(!IS_ERR(data->contents))
-+ data->host_fd = fd;
-+ }
-+ else printk("hppfs_open : failed to open a socket in "
-+ "'%s', errno = %d\n", host_file, -fd);
-+ }
-+ kfree(host_file);
-+
-+ file->private_data = data;
-+ return(0);
-+
-+ out_free1:
-+ kfree(host_file);
-+ out_free2:
-+ free_contents(data->contents);
-+ kfree(data);
-+ out:
-+ return(err);
-+}
-+
-+static int hppfs_dir_open(struct inode *inode, struct file *file)
-+{
-+ struct hppfs_private *data;
-+ struct dentry *proc_dentry;
-+ int err;
-+
-+ err = -ENOMEM;
-+ data = hppfs_data();
-+ if(data == NULL)
-+ goto out;
-+
-+ proc_dentry = HPPFS_I(inode)->proc_dentry;
-+ err = open_private_file(&data->proc_file, proc_dentry,
-+ file_mode(file->f_mode));
-+ if(err)
-+ goto out_free;
-+
-+ file->private_data = data;
-+ return(0);
-+
-+ out_free:
-+ kfree(data);
-+ out:
-+ return(err);
-+}
-+
-+static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
-+{
-+ struct hppfs_private *data = file->private_data;
-+ struct file *proc_file = &data->proc_file;
-+ loff_t (*llseek)(struct file *, loff_t, int);
-+ loff_t ret;
-+
-+ llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
-+ if(llseek != NULL){
-+ ret = (*llseek)(proc_file, off, where);
-+ if(ret < 0)
-+ return(ret);
-+ }
-+
-+ return(default_llseek(file, off, where));
-+}
-+
-+static struct file_operations hppfs_file_fops = {
-+ .owner = NULL,
-+ .llseek = hppfs_llseek,
-+ .read = hppfs_read,
-+ .write = hppfs_write,
-+ .open = hppfs_open,
-+};
-+
-+struct hppfs_dirent {
-+ void *vfs_dirent;
-+ filldir_t filldir;
-+ struct dentry *dentry;
-+};
-+
-+static int hppfs_filldir(void *d, const char *name, int size,
-+ loff_t offset, ino_t inode, unsigned int type)
-+{
-+ struct hppfs_dirent *dirent = d;
-+
-+ if(file_removed(dirent->dentry, name))
-+ return(0);
-+
-+ return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
-+ inode, type));
-+}
-+
-+static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
-+{
-+ struct hppfs_private *data = file->private_data;
-+ struct file *proc_file = &data->proc_file;
-+ int (*readdir)(struct file *, void *, filldir_t);
-+ struct hppfs_dirent dirent = ((struct hppfs_dirent)
-+ { .vfs_dirent = ent,
-+ .filldir = filldir,
-+ .dentry = file->f_dentry } );
-+ int err;
-+
-+ readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
-+
-+ proc_file->f_pos = file->f_pos;
-+ err = (*readdir)(proc_file, &dirent, hppfs_filldir);
-+ file->f_pos = proc_file->f_pos;
-+
-+ return(err);
-+}
-+
-+static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-+{
-+ return(0);
-+}
-+
-+static struct file_operations hppfs_dir_fops = {
-+ .owner = NULL,
-+ .readdir = hppfs_readdir,
-+ .open = hppfs_dir_open,
-+ .fsync = hppfs_fsync,
-+};
-+
-+static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf)
-+{
-+ sf->f_blocks = 0;
-+ sf->f_bfree = 0;
-+ sf->f_bavail = 0;
-+ sf->f_files = 0;
-+ sf->f_ffree = 0;
-+ sf->f_type = HPPFS_SUPER_MAGIC;
-+ return(0);
-+}
-+
-+static struct inode *hppfs_alloc_inode(struct super_block *sb)
-+{
-+ struct hppfs_inode_info *hi;
-+
-+ hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-+ if(hi == NULL)
-+ return(NULL);
-+
-+ *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL });
-+ inode_init_once(&hi->vfs_inode);
-+ return(&hi->vfs_inode);
-+}
-+
-+void hppfs_delete_inode(struct inode *ino)
-+{
-+ clear_inode(ino);
-+}
-+
-+static void hppfs_destroy_inode(struct inode *inode)
-+{
-+ kfree(HPPFS_I(inode));
-+}
-+
-+static struct super_operations hppfs_sbops = {
-+ .alloc_inode = hppfs_alloc_inode,
-+ .destroy_inode = hppfs_destroy_inode,
-+ .read_inode = hppfs_read_inode,
-+ .delete_inode = hppfs_delete_inode,
-+ .statfs = hppfs_statfs,
-+};
-+
-+static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
-+{
-+ struct file proc_file;
-+ struct dentry *proc_dentry;
-+ int (*readlink)(struct dentry *, char *, int);
-+ int err, n;
-+
-+ proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-+ err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
-+ if(err)
-+ return(err);
-+
-+ readlink = proc_dentry->d_inode->i_op->readlink;
-+ n = (*readlink)(proc_dentry, buffer, buflen);
-+
-+ close_private_file(&proc_file);
-+
-+ return(n);
-+}
-+
-+static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+ struct file proc_file;
-+ struct dentry *proc_dentry;
-+ int (*follow_link)(struct dentry *, struct nameidata *);
-+ int err, n;
-+
-+ proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-+ err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
-+ if(err)
-+ return(err);
-+
-+ follow_link = proc_dentry->d_inode->i_op->follow_link;
-+ n = (*follow_link)(proc_dentry, nd);
-+
-+ close_private_file(&proc_file);
-+
-+ return(n);
-+}
-+
-+static struct inode_operations hppfs_dir_iops = {
-+ .lookup = hppfs_lookup,
-+};
-+
-+static struct inode_operations hppfs_link_iops = {
-+ .readlink = hppfs_readlink,
-+ .follow_link = hppfs_follow_link,
-+};
-+
-+static int init_inode(struct inode *inode, struct dentry *dentry)
-+{
-+ if(S_ISDIR(dentry->d_inode->i_mode)){
-+ inode->i_op = &hppfs_dir_iops;
-+ inode->i_fop = &hppfs_dir_fops;
-+ }
-+ else if(S_ISLNK(dentry->d_inode->i_mode)){
-+ inode->i_op = &hppfs_link_iops;
-+ inode->i_fop = &hppfs_file_fops;
-+ }
-+ else {
-+ inode->i_op = &hppfs_file_iops;
-+ inode->i_fop = &hppfs_file_fops;
-+ }
-+
-+ HPPFS_I(inode)->proc_dentry = dentry;
-+
-+ return(0);
-+}
-+
-+static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
-+{
-+ struct inode *root_inode;
-+ struct file_system_type *procfs;
-+ struct super_block *proc_sb;
-+ int err;
-+
-+ err = -ENOENT;
-+ procfs = get_fs_type("proc");
-+ if(procfs == NULL)
-+ goto out;
-+
-+ if(list_empty(&procfs->fs_supers))
-+ goto out;
-+
-+ proc_sb = list_entry(procfs->fs_supers.next, struct super_block,
-+ s_instances);
-+
-+ sb->s_blocksize = 1024;
-+ sb->s_blocksize_bits = 10;
-+ sb->s_magic = HPPFS_SUPER_MAGIC;
-+ sb->s_op = &hppfs_sbops;
-+
-+ root_inode = iget(sb, 0);
-+ if(root_inode == NULL)
-+ goto out;
-+
-+ err = init_inode(root_inode, proc_sb->s_root);
-+ if(err)
-+ goto out_put;
-+
-+ err = -ENOMEM;
-+ sb->s_root = d_alloc_root(root_inode);
-+ if(sb->s_root == NULL)
-+ goto out_put;
-+
-+ hppfs_read_inode(root_inode);
-+
-+ return(0);
-+
-+ out_put:
-+ iput(root_inode);
-+ out:
-+ return(err);
-+}
-+
-+static struct super_block *hppfs_read_super(struct file_system_type *type,
-+ int flags, const char *dev_name,
-+ void *data)
-+{
-+ return(get_sb_nodev(type, flags, data, hppfs_fill_super));
-+}
-+
-+static struct file_system_type hppfs_type = {
-+ .owner = THIS_MODULE,
-+ .name = "hppfs",
-+ .get_sb = hppfs_read_super,
-+ .kill_sb = kill_anon_super,
-+ .fs_flags = 0,
-+};
-+
-+static int __init init_hppfs(void)
-+{
-+ return(register_filesystem(&hppfs_type));
-+}
-+
-+static void __exit exit_hppfs(void)
-+{
-+ unregister_filesystem(&hppfs_type);
-+}
-+
-+module_init(init_hppfs)
-+module_exit(exit_hppfs)
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * 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 -Naur a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h
---- a/include/asm-um/archparam-i386.h Fri Aug 15 15:07:52 2003
-+++ b/include/asm-um/archparam-i386.h Fri Aug 15 15:13:17 2003
-@@ -56,6 +56,65 @@
- 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 -Naur a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S
---- a/include/asm-um/common.lds.S Fri Aug 15 15:04:49 2003
-+++ b/include/asm-um/common.lds.S Fri Aug 15 15:10:46 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 -Naur a/include/asm-um/cpufeature.h b/include/asm-um/cpufeature.h
---- a/include/asm-um/cpufeature.h Wed Dec 31 19:00:00 1969
-+++ b/include/asm-um/cpufeature.h Fri Aug 15 15:10:07 2003
-@@ -0,0 +1,6 @@
-+#ifndef __UM_CPUFEATURE_H
-+#define __UM_CPUFEATURE_H
-+
-+#include "asm/arch/cpufeature.h"
-+
-+#endif
-diff -Naur a/include/asm-um/current.h b/include/asm-um/current.h
---- a/include/asm-um/current.h Fri Aug 15 15:04:11 2003
-+++ b/include/asm-um/current.h Fri Aug 15 15:10:19 2003
-@@ -16,8 +16,10 @@
- #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 -Naur a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
---- a/include/asm-um/fixmap.h Fri Aug 15 15:08:40 2003
-+++ b/include/asm-um/fixmap.h Fri Aug 15 15:13:36 2003
-@@ -34,6 +34,7 @@
- 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 @@
- #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 -Naur a/include/asm-um/irq.h b/include/asm-um/irq.h
---- a/include/asm-um/irq.h Fri Aug 15 15:09:15 2003
-+++ b/include/asm-um/irq.h Fri Aug 15 15:13:51 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 @@
- #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 -Naur a/include/asm-um/local.h b/include/asm-um/local.h
---- a/include/asm-um/local.h Wed Dec 31 19:00:00 1969
-+++ b/include/asm-um/local.h Fri Aug 15 15:12:46 2003
-@@ -0,0 +1,6 @@
-+#ifndef __UM_LOCAL_H
-+#define __UM_LOCAL_H
-+
-+#include "asm/arch/local.h"
-+
-+#endif
-diff -Naur a/include/asm-um/module-generic.h b/include/asm-um/module-generic.h
---- a/include/asm-um/module-generic.h Wed Dec 31 19:00:00 1969
-+++ b/include/asm-um/module-generic.h Fri Aug 15 15:12:38 2003
-@@ -0,0 +1,6 @@
-+#ifndef __UM_MODULE_GENERIC_H
-+#define __UM_MODULE_GENERIC_H
-+
-+#include "asm/arch/module.h"
-+
-+#endif
-diff -Naur a/include/asm-um/module-i386.h b/include/asm-um/module-i386.h
---- a/include/asm-um/module-i386.h Wed Dec 31 19:00:00 1969
-+++ b/include/asm-um/module-i386.h Fri Aug 15 15:12:37 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 -Naur a/include/asm-um/page.h b/include/asm-um/page.h
---- a/include/asm-um/page.h Fri Aug 15 15:06:42 2003
-+++ b/include/asm-um/page.h Fri Aug 15 15:12:40 2003
-@@ -4,7 +4,6 @@
- struct page;
-
- #include "asm/arch/page.h"
--#include "asm/bug.h"
-
- #undef __pa
- #undef __va
-diff -Naur a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
---- a/include/asm-um/pgtable.h Fri Aug 15 15:09:25 2003
-+++ b/include/asm-um/pgtable.h Fri Aug 15 15:14:09 2003
-@@ -79,12 +79,13 @@
-
- #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 @@
- #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 @@
- * 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 @@
- !(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 @@
- #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 @@
- 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 @@
- #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 -Naur a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
---- a/include/asm-um/processor-generic.h Fri Aug 15 15:04:48 2003
-+++ b/include/asm-um/processor-generic.h Fri Aug 15 15:10:42 2003
-@@ -11,9 +11,7 @@
- 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 @@
- } 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 -Naur a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
---- a/include/asm-um/processor-i386.h Fri Aug 15 15:04:00 2003
-+++ b/include/asm-um/processor-i386.h Fri Aug 15 15:10:18 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 -Naur a/include/asm-um/sections.h b/include/asm-um/sections.h
---- a/include/asm-um/sections.h Wed Dec 31 19:00:00 1969
-+++ b/include/asm-um/sections.h Fri Aug 15 15:12:54 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 -Naur a/include/asm-um/smp.h b/include/asm-um/smp.h
---- a/include/asm-um/smp.h Fri Aug 15 15:03:35 2003
-+++ b/include/asm-um/smp.h Fri Aug 15 15:10:04 2003
-@@ -7,9 +7,10 @@
-
- #include "linux/config.h"
- #include "linux/bitops.h"
-+#include "linux/threads.h"
- #include "asm/current.h"
-
--#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 */
-@@ -30,6 +31,13 @@
- {
- }
-
-+extern inline int any_online_cpu(unsigned int mask)
-+{
-+ if (mask & cpu_online_map)
-+ return __ffs(mask & cpu_online_map);
-+
-+ return -1;
-+}
- #endif
-
- #endif
-diff -Naur a/include/asm-um/system-generic.h b/include/asm-um/system-generic.h
---- a/include/asm-um/system-generic.h Fri Aug 15 15:09:22 2003
-+++ b/include/asm-um/system-generic.h Fri Aug 15 15:14:01 2003
-@@ -23,8 +23,10 @@
- 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)
-diff -Naur a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
---- a/include/asm-um/thread_info.h Fri Aug 15 15:05:00 2003
-+++ b/include/asm-um/thread_info.h Fri Aug 15 15:11:11 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 @@
- 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 @@
- #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 -Naur a/include/asm-um/timex.h b/include/asm-um/timex.h
---- a/include/asm-um/timex.h Fri Aug 15 15:07:22 2003
-+++ b/include/asm-um/timex.h Fri Aug 15 15:12:48 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)
-diff -Naur a/include/linux/mm.h b/include/linux/mm.h
---- a/include/linux/mm.h Fri Aug 15 15:03:56 2003
-+++ b/include/linux/mm.h Fri Aug 15 15:10:14 2003
-@@ -483,6 +483,9 @@
- return __set_page_dirty_buffers(page);
- }
-
-+extern long do_mprotect(struct mm_struct *mm, unsigned long start,
-+ size_t len, unsigned long prot);
-+
- /*
- * On a two-level page table, this ends up being trivial. Thus the
- * inlining and the symmetry break with pte_alloc_map() that does all
-@@ -513,9 +516,10 @@
-
- extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
-
--extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
-- unsigned long len, unsigned long prot,
-- unsigned long flag, unsigned long pgoff);
-+extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file,
-+ unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flag,
-+ unsigned long pgoff);
-
- static inline unsigned long do_mmap(struct file *file, unsigned long addr,
- unsigned long len, unsigned long prot,
-@@ -525,7 +529,8 @@
- if ((offset + PAGE_ALIGN(len)) < offset)
- goto out;
- if (!(offset & ~PAGE_MASK))
-- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
-+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag,
-+ offset >> PAGE_SHIFT);
- out:
- return ret;
- }
-diff -Naur a/include/linux/proc_mm.h b/include/linux/proc_mm.h
---- a/include/linux/proc_mm.h Wed Dec 31 19:00:00 1969
-+++ b/include/linux/proc_mm.h Fri Aug 15 15:10:02 2003
-@@ -0,0 +1,48 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PROC_MM_H
-+#define __PROC_MM_H
-+
-+#include "linux/sched.h"
-+
-+#define MM_MMAP 54
-+#define MM_MUNMAP 55
-+#define MM_MPROTECT 56
-+#define MM_COPY_SEGMENTS 57
-+
-+struct mm_mmap {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned long prot;
-+ unsigned long flags;
-+ unsigned long fd;
-+ unsigned long offset;
-+};
-+
-+struct mm_munmap {
-+ unsigned long addr;
-+ unsigned long len;
-+};
-+
-+struct mm_mprotect {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned int prot;
-+};
-+
-+struct proc_mm_op {
-+ int op;
-+ union {
-+ struct mm_mmap mmap;
-+ struct mm_munmap munmap;
-+ struct mm_mprotect mprotect;
-+ int copy_segments;
-+ } u;
-+};
-+
-+extern struct mm_struct *proc_mm_get_mm(int fd);
-+
-+#endif
-diff -Naur a/mm/Makefile b/mm/Makefile
---- a/mm/Makefile Fri Aug 15 15:07:22 2003
-+++ b/mm/Makefile Fri Aug 15 15:12:48 2003
-@@ -12,3 +12,5 @@
- slab.o swap.o truncate.o vcache.o vmscan.o $(mmu-y)
-
- obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o
-+obj-$(CONFIG_PROC_MM) += proc_mm.o
-+
-diff -Naur a/mm/memory.c b/mm/memory.c
---- a/mm/memory.c Fri Aug 15 15:05:37 2003
-+++ b/mm/memory.c Fri Aug 15 15:11:48 2003
-@@ -45,6 +45,7 @@
- #include <linux/pagemap.h>
- #include <linux/vcache.h>
- #include <linux/rmap-locking.h>
-+#include <linux/init.h>
-
- #include <asm/pgalloc.h>
- #include <asm/rmap.h>
-@@ -669,6 +670,24 @@
- }
-
-
-+static struct vm_area_struct fixmap_vma = {
-+ /* Catch users - if there are any valid
-+ ones, we can make this be "&init_mm" or
-+ something. */
-+ .vm_mm = NULL,
-+ .vm_page_prot = PAGE_READONLY,
-+ .vm_flags = VM_READ | VM_EXEC,
-+};
-+
-+static int init_fixmap_vma(void)
-+{
-+ fixmap_vma.vm_start = FIXADDR_START;
-+ fixmap_vma.vm_end = FIXADDR_TOP;
-+ return(0);
-+}
-+
-+__initcall(init_fixmap_vma);
-+
- int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, int len, int write, int force,
- struct page **pages, struct vm_area_struct **vmas)
-@@ -689,19 +708,8 @@
-
- vma = find_extend_vma(mm, start);
-
--#ifdef FIXADDR_USER_START
-- if (!vma &&
-- start >= FIXADDR_USER_START && start < FIXADDR_USER_END) {
-- static struct vm_area_struct fixmap_vma = {
-- /* Catch users - if there are any valid
-- ones, we can make this be "&init_mm" or
-- something. */
-- .vm_mm = NULL,
-- .vm_start = FIXADDR_USER_START,
-- .vm_end = FIXADDR_USER_END,
-- .vm_page_prot = PAGE_READONLY,
-- .vm_flags = VM_READ | VM_EXEC,
-- };
-+#ifdef FIXADDR_START
-+ if (!vma && start >= FIXADDR_START && start < FIXADDR_TOP) {
- unsigned long pg = start & PAGE_MASK;
- pgd_t *pgd;
- pmd_t *pmd;
-diff -Naur a/mm/mmap.c b/mm/mmap.c
---- a/mm/mmap.c Fri Aug 15 15:07:18 2003
-+++ b/mm/mmap.c Fri Aug 15 15:12:45 2003
-@@ -457,11 +457,11 @@
- * The caller must hold down_write(current->mm->mmap_sem).
- */
-
--unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
-- unsigned long len, unsigned long prot,
-- unsigned long flags, unsigned long pgoff)
-+unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file,
-+ unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags,
-+ unsigned long pgoff)
- {
-- struct mm_struct * mm = current->mm;
- struct vm_area_struct * vma, * prev;
- struct inode *inode;
- unsigned int vm_flags;
-diff -Naur a/mm/mprotect.c b/mm/mprotect.c
---- a/mm/mprotect.c Fri Aug 15 15:05:20 2003
-+++ b/mm/mprotect.c Fri Aug 15 15:11:21 2003
-@@ -222,7 +222,8 @@
- }
-
- asmlinkage long
--sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-+do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
-+ unsigned long prot)
- {
- unsigned long nstart, end, tmp;
- struct vm_area_struct * vma, * next, * prev;
-@@ -239,9 +240,9 @@
- if (end == start)
- return 0;
-
-- down_write(¤t->mm->mmap_sem);
-+ down_write(&mm->mmap_sem);
-
-- vma = find_vma_prev(current->mm, start, &prev);
-+ vma = find_vma_prev(mm, start, &prev);
- error = -ENOMEM;
- if (!vma || vma->vm_start > start)
- goto out;
-@@ -301,6 +302,11 @@
- prev->vm_mm->map_count--;
- }
- out:
-- up_write(¤t->mm->mmap_sem);
-+ up_write(&mm->mmap_sem);
- return error;
- }
-+
-+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-+{
-+ return(do_mprotect(current->mm, start, len, prot));
-+}
-diff -Naur a/mm/proc_mm.c b/mm/proc_mm.c
---- a/mm/proc_mm.c Wed Dec 31 19:00:00 1969
-+++ b/mm/proc_mm.c Fri Aug 15 15:11:44 2003
-@@ -0,0 +1,174 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/mm.h"
-+#include "linux/init.h"
-+#include "linux/proc_fs.h"
-+#include "linux/proc_mm.h"
-+#include "linux/file.h"
-+#include "asm/uaccess.h"
-+#include "asm/mmu_context.h"
-+
-+static struct file_operations proc_mm_fops;
-+
-+struct mm_struct *proc_mm_get_mm(int fd)
-+{
-+ struct mm_struct *ret = ERR_PTR(-EBADF);
-+ struct file *file;
-+
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+
-+ ret = ERR_PTR(-EINVAL);
-+ if(file->f_op != &proc_mm_fops)
-+ goto out_fput;
-+
-+ ret = file->private_data;
-+ out_fput:
-+ fput(file);
-+ out:
-+ return(ret);
-+}
-+
-+extern 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);
-+
-+static ssize_t write_proc_mm(struct file *file, const char *buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ struct mm_struct *mm = file->private_data;
-+ struct proc_mm_op req;
-+ int n, ret;
-+
-+ if(count > sizeof(req))
-+ return(-EINVAL);
-+
-+ n = copy_from_user(&req, buffer, count);
-+ if(n != 0)
-+ return(-EFAULT);
-+
-+ ret = count;
-+ switch(req.op){
-+ case MM_MMAP: {
-+ struct mm_mmap *map = &req.u.mmap;
-+
-+ ret = do_mmap2(mm, map->addr, map->len, map->prot,
-+ map->flags, map->fd, map->offset >> PAGE_SHIFT);
-+ if((ret & ~PAGE_MASK) == 0)
-+ ret = count;
-+
-+ break;
-+ }
-+ case MM_MUNMAP: {
-+ struct mm_munmap *unmap = &req.u.munmap;
-+
-+ down_write(&mm->mmap_sem);
-+ ret = do_munmap(mm, unmap->addr, unmap->len);
-+ up_write(&mm->mmap_sem);
-+
-+ if(ret == 0)
-+ ret = count;
-+ break;
-+ }
-+ case MM_MPROTECT: {
-+ struct mm_mprotect *protect = &req.u.mprotect;
-+
-+ ret = do_mprotect(mm, protect->addr, protect->len,
-+ protect->prot);
-+ if(ret == 0)
-+ ret = count;
-+ break;
-+ }
-+
-+ case MM_COPY_SEGMENTS: {
-+ struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments);
-+
-+ if(IS_ERR(from)){
-+ ret = PTR_ERR(from);
-+ break;
-+ }
-+
-+ mm_copy_segments(from, mm);
-+ break;
-+ }
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return(ret);
-+}
-+
-+static int open_proc_mm(struct inode *inode, struct file *file)
-+{
-+ struct mm_struct *mm = mm_alloc();
-+ int ret;
-+
-+ ret = -ENOMEM;
-+ if(mm == NULL)
-+ goto out_mem;
-+
-+ ret = init_new_context(current, mm);
-+ if(ret)
-+ goto out_free;
-+
-+ spin_lock(&mmlist_lock);
-+ list_add(&mm->mmlist, ¤t->mm->mmlist);
-+ mmlist_nr++;
-+ spin_unlock(&mmlist_lock);
-+
-+ file->private_data = mm;
-+
-+ return(0);
-+
-+ out_free:
-+ mmput(mm);
-+ out_mem:
-+ return(ret);
-+}
-+
-+static int release_proc_mm(struct inode *inode, struct file *file)
-+{
-+ struct mm_struct *mm = file->private_data;
-+
-+ mmput(mm);
-+ return(0);
-+}
-+
-+static struct file_operations proc_mm_fops = {
-+ .open = open_proc_mm,
-+ .release = release_proc_mm,
-+ .write = write_proc_mm,
-+};
-+
-+static int make_proc_mm(void)
-+{
-+ struct proc_dir_entry *ent;
-+
-+ ent = create_proc_entry("mm", 0222, &proc_root);
-+ if(ent == NULL){
-+ printk("make_proc_mm : Failed to register /proc/mm\n");
-+ return(0);
-+ }
-+ ent->proc_fops = &proc_mm_fops;
-+
-+ return(0);
-+}
-+
-+__initcall(make_proc_mm);
-+
-+/*
-+ * 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:
-+ */