From: alex Date: Sun, 5 Oct 2003 11:27:46 +0000 (+0000) Subject: - unused patches removed X-Git-Tag: v1_7_0_51~2^9~264 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=1af93cc099046119942b01c528f67f147cdad314;p=fs%2Flustre-release.git - unused patches removed --- diff --git a/lustre/kernel_patches/patches/uml-patch-2.6.0-test3-1.patch b/lustre/kernel_patches/patches/uml-patch-2.6.0-test3-1.patch deleted file mode 100644 index 8ea5a43..0000000 --- a/lustre/kernel_patches/patches/uml-patch-2.6.0-test3-1.patch +++ /dev/null @@ -1,8716 +0,0 @@ -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 -+ . -+ - - 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 - #include - #include -+#include - #include - #include - #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 -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 = - Add a new device to UML; -- same syntax as command line -- config - Query the configuration of a device -- remove - Remove a device from UML -- sysrq - 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 = - Add a new device to UML; \n\ -+ same syntax as command line \n\ -+ config - Query the configuration of a device \n\ -+ remove - Remove a device from UML \n\ -+ sysrq - 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 - make UML enter 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 - #include --#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() { $$_ =~ s/CONFIG/$$config/; print $$_ }' -+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while() { $$_ =~ 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 - #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; jtypename); -- 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 -+#include - #include - #include - #include -@@ -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 - #include - #include - -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;ithread_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 - #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 - #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 - #include - #include -+#include - #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 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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=,,...\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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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 -+ - .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 -+ -+#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 -+#include - - 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 - #include - #include -+#include - - #include - #include -@@ -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: -+ */ diff --git a/lustre/kernel_patches/pc/uml-patch-2.6.0-test3-1.pc b/lustre/kernel_patches/pc/uml-patch-2.6.0-test3-1.pc deleted file mode 100644 index 9a32c9a..0000000 --- a/lustre/kernel_patches/pc/uml-patch-2.6.0-test3-1.pc +++ /dev/null @@ -1,113 +0,0 @@ -arch/um/config.release -arch/um/defconfig -arch/um/drivers/chan_kern.c -arch/um/drivers/chan_user.c -arch/um/drivers/cow.h -arch/um/drivers/cow_kern.c -arch/um/drivers/cow_sys.h -arch/um/drivers/cow_user.c -arch/um/drivers/hostaudio_kern.c -arch/um/drivers/line.c -arch/um/drivers/Makefile -arch/um/drivers/mconsole_kern.c -arch/um/drivers/mconsole_user.c -arch/um/drivers/mmapper_kern.c -arch/um/drivers/net_kern.c -arch/um/drivers/port_kern.c -arch/um/drivers/ssl.c -arch/um/drivers/stdio_console.c -arch/um/drivers/ubd_kern.c -arch/um/drivers/ubd_user.c -arch/um/drivers/xterm.c -arch/um/drivers/xterm_kern.c -arch/um/dyn.lds.S -arch/um/include/irq_kern.h -arch/um/include/kern_util.h -arch/um/include/line.h -arch/um/include/mconsole.h -arch/um/include/mem.h -arch/um/include/mem_user.h -arch/um/include/os.h -arch/um/include/sysdep-i386/sigcontext.h -arch/um/include/ubd_user.h -arch/um/include/user.h -arch/um/include/user_util.h -arch/um/Kconfig -arch/um/Kconfig_block -arch/um/Kconfig_net -arch/um/kernel/config.c.in -arch/um/kernel/exec_kern.c -arch/um/kernel/init_task.c -arch/um/kernel/irq.c -arch/um/kernel/Makefile -arch/um/kernel/mem.c -arch/um/kernel/mem_user.c -arch/um/kernel/process.c -arch/um/kernel/process_kern.c -arch/um/kernel/ptrace.c -arch/um/kernel/sigio_kern.c -arch/um/kernel/signal_kern.c -arch/um/kernel/skas/include/mode.h -arch/um/kernel/skas/include/uaccess.h -arch/um/kernel/skas/Makefile -arch/um/kernel/skas/process.c -arch/um/kernel/skas/process_kern.c -arch/um/kernel/skas/util/mk_ptregs.c -arch/um/kernel/smp.c -arch/um/kernel/syscall_kern.c -arch/um/kernel/sys_call_table.c -arch/um/kernel/sysrq.c -arch/um/kernel/time.c -arch/um/kernel/time_kern.c -arch/um/kernel/trap_kern.c -arch/um/kernel/trap_user.c -arch/um/kernel/tt/include/uaccess.h -arch/um/kernel/tt/process_kern.c -arch/um/kernel/tt/ptproxy/proxy.c -arch/um/kernel/tt/tracer.c -arch/um/kernel/tt/uaccess_user.c -arch/um/kernel/tty_log.c -arch/um/kernel/um_arch.c -arch/um/kernel/umid.c -arch/um/kernel/user_util.c -arch/um/Makefile -arch/um/Makefile-i386 -arch/um/Makefile-skas -arch/um/os-Linux/drivers/tuntap_user.c -arch/um/os-Linux/file.c -arch/um/sys-i386/bugs.c -arch/um/sys-i386/Makefile -arch/um/uml.lds.S -arch/um/util/mk_constants_kern.c -fs/hostfs/hostfs.h -fs/hostfs/hostfs_kern.c -fs/hostfs/hostfs_user.c -fs/hostfs/Makefile -fs/hppfs/hppfs_kern.c -fs/hppfs/Makefile -fs/Makefile -include/asm-um/archparam-i386.h -include/asm-um/common.lds.S -include/asm-um/cpufeature.h -include/asm-um/current.h -include/asm-um/fixmap.h -include/asm-um/irq.h -include/asm-um/local.h -include/asm-um/module-generic.h -include/asm-um/module-i386.h -include/asm-um/page.h -include/asm-um/pgtable.h -include/asm-um/processor-generic.h -include/asm-um/processor-i386.h -include/asm-um/sections.h -include/asm-um/smp.h -include/asm-um/system-generic.h -include/asm-um/thread_info.h -include/asm-um/timex.h -include/linux/mm.h -include/linux/proc_mm.h -mm/Makefile -mm/memory.c -mm/mmap.c -mm/mprotect.c -mm/proc_mm.c