diff -u --recursive --new-file v2.1.20/linux/CREDITS linux/CREDITS
--- v2.1.20/linux/CREDITS	Mon Dec 30 15:39:02 1996
+++ linux/CREDITS	Tue Jan 14 12:59:10 1997
@@ -194,7 +194,7 @@
 N: Remy Card
 E: Remy.Card@masi.ibp.fr
 E: Remy.Card@linux.org
-D: Extended file system designer and developer
+D: Extended file system [defunct] designer and developer
 D: Second extended file system designer and developer
 S: Institut Blaise Pascal
 S: 4 Place Jussieu
@@ -394,6 +394,14 @@
 D: Debugging: SCSI code; Cyclades serial driver; APM driver
 D: Debugging: XFree86 Mach 32 server, accelerated server code
 
+N: János Farkas
+E: chexum@shadow.banki.hu
+D: romfs, various (mostly networking) fixes
+P: 1024/F81FB2E1 41 B7 E4 E6 3E D4 A6 71  6D 9C F3 9F F2 BF DF 6E
+S: Madarász Viktor utca 25
+S: 1131 Budapest
+S: Hungary
+
 N: Jürgen Fischer
 E: fischer@et-inf.fho-emden.de (=?iso-8859-1?q?J=FCrgen?= Fischer)
 D: Author of Adaptec AHA-152x scsi driver
@@ -1562,7 +1570,7 @@
 
 N: Frank Xia
 E: qx@math.columbia.edu
-D: Xiafs filesystem
+D: Xiafs filesystem [defunct]
 S: 542 West 112th Street, 5N
 S: New York, New York 10025
 S: USA
diff -u --recursive --new-file v2.1.20/linux/Documentation/Changes linux/Documentation/Changes
--- v2.1.20/linux/Documentation/Changes	Sun Dec 22 16:37:16 1996
+++ linux/Documentation/Changes	Tue Jan 14 12:51:53 1997
@@ -19,7 +19,7 @@
 generated by texinfo so a diff is useless anyway (though I can
 incorporate one by hand if you insist upon sending it that way ;-).
 
-Last updated: December 13, 1996.
+Last updated: January 9, 1997.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Minimal Requirements
@@ -28,7 +28,7 @@
    Upgrade to at *least* these software revisions before thinking you've
 encountered a bug!
 
-- Kernel modules	 2.1.13
+- Kernel modules	 modutils-970104
 - Gnu C 		 2.7.2.1
 - Binutils		 2.7.0.3
 - Linux C Library	 5.4.17
@@ -36,7 +36,6 @@
 - Linux C++ Library	 2.7.2.1
 - Procps		 1.01
 - SysVinit		 2.69
-- Sysklogd               1.3-3
 - Mount                  2.5p
 - Net-tools              1.32-alpha
 - Kbd                    0.91
@@ -75,7 +74,7 @@
 Modules
 =======
 
-   You need to upgrade to modules-2.1.13 for kernels 2.1.8 and later.
+   You need to upgrade to modutils-970104 for kernels 2.1.8 and later.
 
 Gnu C
 =====
@@ -89,9 +88,20 @@
 Networking Changes
 ==================
 
-    Please read Documentation/networking/routing.txt. People wanting to use
-all the new routing table features such as OSPF classes should also read
-Documentation/networking/policy-routing.txt.
+   Please read Documentation/networking/routing.txt and
+Documentation/networking/policy-routing.txt for more information about
+changes in routing code.  OSPF classes have been added, and interface
+routes are generated automatically.
+
+   If for some reason you need to override this automatic default
+routing, you have to specify the complete route specification (netmask,
+device, etc.) for the kernel to accept it. Consequently, you need to
+either remove interface routes from your init scripts or add missing
+information to them if you need to replace the automatic routes.
+
+   Also note that some routes, such as loopback routes, do not show up
+in some standard tools.  Check in /proc/net/rt_local to verify their
+presence.
 
 SysVinit
 ========
@@ -99,6 +109,18 @@
    To avoid an oops while shutting down or rebooting the computer,
 upgrade to SysVinit 2.69.
 
+RPM
+===
+
+   If you run RedHat Linux or any other distribution that uses RPM, you
+need to upgrade RPM to version 2.2.7 or later.
+
+DOSEMU
+======
+
+   A new "stable" version of DOSEMU is available for 2.1.x kernels.
+Upgrade to 0.64.2 or later.
+
 How to know the version of the installed programs
 *************************************************
 
@@ -109,11 +131,13 @@
 Gnu C: gcc -v or gcc --version
 Libc: ls -l /lib/libc.so.*
 Libc++: ls -l /usr/lib/libg++.so.*
+Ld.so:  ldd-v
 Binutils: ld -v
 modules: insmod -V
 procps: ps --version
-SysVinit: cat /proc/`cat /var/run/syslog.pid`/environ|strings|awk '$1 ~
+SysVinit: cat /proc/`cat /var/run/klogd.pid`/environ|strings|awk '$1 ~
 /INIT_VERSION/ {print}'
+RPM:  rpm --version
 
 Where to get the files
 **********************
@@ -168,9 +192,8 @@
 Modules utilities
 =================
 
-The 2.1.13 release:
-ftp://tsx-11.mit.edu/pub/linux/sources/system/v2.1/modules-2.1.13.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/kernel/v2.1/modules-2.1.13.tar.gz
+The 970104 release:
+ftp://ftp.redhat.com/pub/alphabits/modutils-970104.tar.gz
 
 Procps utilities
 ================
@@ -185,6 +208,26 @@
 The 2.69 release (when it gets there):
 ftp://tsx-11.mit.edu/pub/linux/sources/sbin/sysvinit-2.69.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.69.tar.gz
+
+RPM utilities
+=============
+
+The 2.2.7 release for Intel:
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-2.2.7-1.i386.rpm
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.i386.rpm
+The 2.2.7 release for Alpha:
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/axp/rpm-2.2.7-1.axp.rpm
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/axp/rpm-devel-2.2.7-1.axp.rpm
+The 2.2.7 release for SPARC:
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-2.2.7-1.sparc.rpm
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.sparc.rpm
+
+DOSEMU
+======
+
+The 0.64.2 release:
+ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu0.64.2.tgz
+ftp://sunsite.unc.edu/pub/Linux/system/Emulators/dosemu0.64.2.tgz
 
 Other Info
 ==========
diff -u --recursive --new-file v2.1.20/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.20/linux/Documentation/Configure.help	Thu Jan  2 15:55:13 1997
+++ linux/Documentation/Configure.help	Tue Jan 14 12:59:10 1997
@@ -3108,13 +3108,6 @@
   Documentation/modules.txt. Note that the filesystem of your root
   partition cannot be compiled as a module.
 
-Extended fs support
-CONFIG_EXT_FS
-  This is the old Linux filesystem (= method to organize files on a
-  harddisk partition or a floppy disk) and not in use anymore. It
-  enlarges your kernel by about 25 kB. Let's all kill this beast. Say
-  N.
-
 Second extended fs support
 CONFIG_EXT2_FS
   This is the de facto standard Linux filesystem (= method to organize
@@ -3138,16 +3131,6 @@
   sunsite.unc.edu:/pub/Linux/docs/faqs. This option will enlarge your
   kernel by about 41 kB. Default is Y.
 
-xiafs filesystem support
-CONFIG_XIA_FS
-  This is an old filesystem (= method to organize files on a harddisk
-  partition or a floppy disk) and not in use anymore. This option
-  would enlarge your kernel by about 28 kB. Let's all kill this beast:
-  say N.  If you want to compile this as a module ( = code which can
-  be inserted in and removed from the running kernel whenever you
-  want), say M here and read Documentation/modules.txt. Note that the
-  filesystem of your root partition cannot be compiled as a module.
-
 fat fs support
 CONFIG_FAT_FS
   If you want to use one of the FAT-based filesystems (the MS-DOS,
@@ -3450,6 +3433,14 @@
   module, say M here and read Documentation/modules.txt.
   If unsure, say N.
 
+ROMFS filesystem support (EXPERIMENTAL)
+CONFIG_ROMFS_FS
+  This is a special file system intended for installation disks or
+  otherwise prebuilt medias.  It has very low overhead and low memory
+  requirements.  However, it's read-only (one particular reason of the
+  smallness), so you need extra programs to prepare disks in this
+  format.  If you are not sure, just say N, you don't need it.
+
 Standard/generic serial support
 CONFIG_SERIAL
   This selects whether you want to include the driver for the standard
@@ -4587,7 +4578,7 @@
 # LocalWords:  TR Sony CDU caddyless cdu Mitsumi MCD cd mcd XA MultiSession CDA
 # LocalWords:  Matsushita Panasonic SBPCD Soundblaster Longshine sbpcd Aztech
 # LocalWords:  Okano Wearnes AZTCD CDD SE aztcd sonycd Goldstar GSCD Philips fs
-# LocalWords:  LMS OPTCD Sanyo SJCD minix faqs xiafs XIA msdos harddrive mtools
+# LocalWords:  LMS OPTCD Sanyo SJCD minix faqs msdos harddrive mtools
 # LocalWords:  std softlinks umssync NetworkFileSharing nfsd mountd CDs HPFS TI
 # LocalWords:  hpfs SYSV SCO intel iBCS Wyse WordPerfect tsx mit unixes sysv NR
 # LocalWords:  SMB WfW Cyclades async mux Logitech busmouse MouseSystem aka AST
diff -u --recursive --new-file v2.1.20/linux/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX
--- v2.1.20/linux/Documentation/filesystems/00-INDEX	Thu Jun  6 14:57:43 1996
+++ linux/Documentation/filesystems/00-INDEX	Fri Jan  3 13:03:41 1997
@@ -6,6 +6,8 @@
 	- info and mount options for the OS/2 HPFS.
 ncpfs.txt
 	- info on Novell Netware(tm) filesystem using NCP protocol.
+romfs.txt
+	- Description of the ROMFS filesystem.
 smbfs.txt
 	- info on using filesystems with the SMB protocol (Win 3.11, Win NT)
 sysv-fs.txt
diff -u --recursive --new-file v2.1.20/linux/Documentation/filesystems/romfs.txt linux/Documentation/filesystems/romfs.txt
--- v2.1.20/linux/Documentation/filesystems/romfs.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/filesystems/romfs.txt	Fri Jan  3 13:03:41 1997
@@ -0,0 +1,152 @@
+
+ROMFS - ROM FILE SYSTEM
+
+This is a quite dumb, read only filesystem, mainly for initial ram
+disks of installation disks.  It has grown up by the need of having
+modules linked at boot time.  Using this filesystem, you get a very
+similar feature, and even the possibility of a small kernel, with a
+file system which doesn't take up useful memory from the router
+functions in the basement of your office.
+
+For comparison, both the older minix and xiafs filesystems (compiled
+as module) need more than 20000 bytes, while romfs is less than a
+page, about 4000 bytes (assuming ix86 code).  Under the same
+conditions, the msdos filesystem would need about 30K (and does not
+support device nodes or symlinks), while the nfs module with nfsroot
+is about 57K.  Furthermore, as a bit unfair comparison, an actual
+rescue disk used up 3202 blocks with ext2, while with romfs, it needed
+3079 blocks.
+
+To create such a file system, you'll need a user program named
+genromfs.  It is (or will be shortly) available via ftp on
+sunsite.unc.edu and its mirrors, in the /pub/Linux/system/Filesystems/
+directory.
+
+As the name suggests, romfs could be also used (space-efficiently) on
+various read-only medias, like (E)EPROM disks if someone will have the
+motivation.. :)
+
+However, the main purpose of romfs is to have a very small kernel,
+which has only this filesystem linked in, and then can load any module
+later, with the current module utilities.  It can also be used to run
+some program to decide if you need SCSI devices, and even IDE or
+floppy drives can be loaded later if you use the "initrd" -- initial
+ram disk -- feature of the kernel.  This would not be really news
+flash, but with romfs, you can even spare off your ext2 or minix or
+maybe even affs filesystem until you really know that you need it.
+
+For example, a distribution boot disk can contain only the cd disk
+drivers (and possibly the SCSI drivers), and the ISO filesystem
+module.  The kernel can be small enough, since it doesn't have other
+filesystems, like the quite large ext2fs module, which can then be
+loaded off the CD at a later stage of the installation.  Another use
+would be for a recovery disk, when you are reinstalling a workstation
+from the network, and you will have all the tools/modules available
+from a nearby server, so you don't want to carry two disks for this
+purpose, just because it won't fit into ext2.
+
+romfs operates on block devices as you can expect, and the underlying
+structure is very simple.  Every accessible structure begins on 16
+byte boundaries for fast access.  The minimum space a file will take
+is 32 bytes (this is an empty file, with a less than 16 character
+name).  The maximum overhead for any non-empty file is the header, and
+the 16 byte padding for the name and the contents, also 16+14+15 = 45
+bytes.  This is quite rare however, since most file names are longer
+than 3 bytes, and shorter than 15 bytes.
+
+The layout of the filesystem is the following:
+
+offset	    content
+
+	+---+---+---+---+
+  0	| - | r | o | m |  \
+	+---+---+---+---+	The ASCII representation of those bytes
+  4	| 1 | f | s | - |  /	(i.e. "-rom1fs-"
+	+---+---+---+---+
+  8	|   full size	|	The number of accessible bytes in this fs.
+	+---+---+---+---+
+ 12	|    checksum	|	The checksum of the FIRST 512 BYTES.
+	+---+---+---+---+
+ 16	| volume name	|	The zero terminated name of the volume,
+	:               :	padded to 16 byte boundary.
+	+---+---+---+---+
+ xx	|     file	|
+	:    headers	:
+
+Every multi byte value (32 bit words, I'll use the longwords term from
+now on) must be in big endian order.
+
+The first eight bytes identify the filesystem, even for the casual
+reader.  After that in the 3rd longword, it contains the number of
+bytes accessible from the start of this filesystem.  The 4th longword
+is the checksum of the first 512 bytes (or the number of bytes
+accessible, whichever is smallest).  The applied algorithm is the same
+as in the AFFS filesystem, namely a simple sum of the longwords
+(assuming bigendian quantities again).  For details, please consult
+the source.  This algorithm was chosen because although it's not quite
+reliable, it does not require any tables, and it is very simple.
+
+The following bytes are now part of the file system; each file header
+must begin on a 16 byte boundary.
+
+offset	    content
+
+     	+---+---+---+---+
+  0	| next filehdr|X|	The offset of the next file header
+	+---+---+---+---+	  (zero if no more files)
+  4	|   spec.info	|	Info for directories/hard links/devices
+	+---+---+---+---+
+  8	|     size      |	The size of this file in bytes
+	+---+---+---+---+
+ 12	|   checksum	|	Covering the meta data, including the file
+	+---+---+---+---+	  name, and padding
+ 16	| file name     |	The zero terminated name of the file,
+	:               :	padded to 16 byte boundary.
+	+---+---+---+---+
+ xx	| file data	|
+	:		:
+
+Since the file headers begin always at a 16 byte boundary, the lowest
+4 bits would be always zero in the next filehdr pointer.  These four
+bits are used for the mode information.  Bits 0..2 specify the type of
+the file; while bit 4 shows if the file is executable or not.  The
+permissions are assumed to be world readable, if this bit is not set,
+and world executable if it is; except the character and block devices,
+they are readable only for the owner.  The owner of every file is user
+and group 0, this should never be a problem for the intended use.  The
+mapping of the 8 possible values to file types is the following:
+
+	  mapping		spec.info means
+ 0	hard link	link destination [file header]
+ 1	directory	first file's header
+ 2	regular file	unused, must be zero [MBZ]
+ 3	symbolic link	unused, MBZ (file data is the link content)
+ 4	block device	16/16 bits major/minor number
+ 5	char device		    - " -
+ 6	socket		unused, MBZ
+ 7	fifo		unused, MBZ
+
+Note that hard links are specifically marked in this filesystem, but
+they will behave as you can expect (i.e. share the inode number).
+Note also that your responsibility to not create hard link loops, and
+creating all the . and .. links for directories.  This is normally
+done correctly by the genromfs program.  Please refrain from using the
+executable bits on the socket and fifo special files, they may have
+other uses in the future.  Additionally, please remember that only
+regular files, and symlinks are supposed to have a nonzero size field;
+they contain the number of bytes available directly after the (padded)
+file name.
+
+Another thing to note is that romfs works on file headers and data
+aligned to 16 byte boundaries, but most hardware devices and the block
+device drivers are unable to cope with smaller than block-sized data.
+To overcome this limitation, the whole size of the file system must be
+padded to an 1024 byte boundary.
+
+If you have any problems or suggestions concerning this file system,
+please contact me.  However, think twice before wanting me to add
+features and code, because the primary advantage of this file system
+is the small code.
+
+Have fun,
+Janos Farkas <chexum@shadow.banki.hu>
diff -u --recursive --new-file v2.1.20/linux/Documentation/modules.txt linux/Documentation/modules.txt
--- v2.1.20/linux/Documentation/modules.txt	Sun Dec 22 16:37:20 1996
+++ linux/Documentation/modules.txt	Tue Jan 14 12:59:10 1997
@@ -49,7 +49,7 @@
 
 Here is a sample of the available modules included in the kernel sources:
 
-	Most filesystems: minix, xiafs, msdos, umsdos, sysv, isofs, hpfs,
+	Most filesystems: minix, msdos, umsdos, sysv, isofs, hpfs,
 			  smbfs, nfs
 
 	Mid-level SCSI support (required by top and low level scsi drivers).
diff -u --recursive --new-file v2.1.20/linux/Makefile linux/Makefile
--- v2.1.20/linux/Makefile	Thu Jan  2 15:55:14 1997
+++ linux/Makefile	Fri Jan  3 11:33:25 1997
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 20
+SUBLEVEL = 21
 
 ARCH = i386
 
@@ -39,6 +39,7 @@
 NM	=$(CROSS_COMPILE)nm
 STRIP	=$(CROSS_COMPILE)strip
 MAKE	=make
+GENKSYMS=/sbin/genksyms
 
 all:	do-it-all
 
@@ -87,7 +88,7 @@
 # standard CFLAGS
 #
 
-CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce
+CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
 
 ifdef CONFIG_CPP
 CFLAGS := $(CFLAGS) -x c++
diff -u --recursive --new-file v2.1.20/linux/Rules.make linux/Rules.make
--- v2.1.20/linux/Rules.make	Thu Dec 12 17:02:39 1996
+++ linux/Rules.make	Tue Jan 14 08:47:10 1997
@@ -67,7 +67,7 @@
 else
 	$(AR) rcs $@
 endif
-endif
+endif # O_TARGET
 
 #
 # Rule to compile a set of .o files into one .a file
@@ -140,56 +140,58 @@
 # Separate the object into "normal" objects and "exporting" objects
 # Exporting objects are: all objects that define symbol tables
 #
-ifdef CONFIG_MODVERSIONS
+ifdef CONFIG_MODULES
+
 SYMTAB_OBJS = $(LX_OBJS) $(OX_OBJS) $(MX_OBJS)
+
+ifdef CONFIG_MODVERSIONS
 ifneq "$(strip $(SYMTAB_OBJS))" ""
 
 MODINCL = $(TOPDIR)/include/linux/modules
 
-# The -w option (enable warnings) for /bin/genksyms will return here in 2.1
+# The -w option (enable warnings) for genksyms will return here in 2.1
 $(MODINCL)/%.ver: %.c
-	@if [ ! -x /sbin/genksyms ]; then echo "Please read: Documentation/modules.txt"; fi
-	$(CC) $(CFLAGS) -E -D__GENKSYMS__ $< | /sbin/genksyms $(MODINCL)
-
+	$(CC) $(CFLAGS) -E -D__GENKSYMS__ $<\
+	| $(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp
+	mv $@.tmp $@
+	
 $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h
 
 $(TOPDIR)/include/linux/modversions.h: $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver))
 	@echo updating $(TOPDIR)/include/linux/modversions.h
-	@(echo "#ifdef MODVERSIONS";\
-	echo "#undef  CONFIG_MODVERSIONS";\
-	echo "#define CONFIG_MODVERSIONS";\
-	echo "#ifndef _set_ver";\
-	echo "#define _set_ver(sym,vers) sym ## _R ## vers";\
-	echo "#endif";\
-	cd $(TOPDIR)/include/linux/modules; for f in *.ver;\
-	do echo "#include <linux/modules/$${f}>"; done; \
-	echo "#undef  CONFIG_MODVERSIONS";\
-	echo "#endif") \
-	> $(TOPDIR)/include/linux/modversions.h
-
-$(MX_OBJS): $(TOPDIR)/include/linux/modversions.h
-	$(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c)
-
-$(LX_OBJS) $(OX_OBJS): $(TOPDIR)/include/linux/modversions.h
-	$(CC) $(CFLAGS) -DMODVERSIONS -DEXPORT_SYMTAB -c $(@:.o=.c)
+	@(echo "#ifndef _LINUX_MODVERSIONS_H";\
+	  echo "#define _LINUX_MODVERSIONS_H"; \
+	  echo "#include <linux/modsetver.h>"; \
+	  cd $(TOPDIR)/include/linux/modules; \
+	  for f in *.ver; do \
+	    if [ -f $$f ]; then echo "#include <linux/modules/$${f}>"; fi; \
+	  done; \
+	  echo "#endif"; \
+	) > $@
 
 dep fastdep: $(TOPDIR)/include/linux/modversions.h
 
-endif
+endif # SYMTAB_OBJS 
+
 $(M_OBJS): $(TOPDIR)/include/linux/modversions.h
 ifdef MAKING_MODULES
 $(O_OBJS) $(L_OBJS): $(TOPDIR)/include/linux/modversions.h
 endif
-# This is needed to ensure proper dependency for multipart modules such as
-# fs/ext.o.  (Otherwise, not all subobjects will be recompiled when
-# version information changes.)
 
 else
 
 $(TOPDIR)/include/linux/modversions.h:
-	@touch $(TOPDIR)/include/linux/modversions.h
+	@echo "#include <linux/modsetver.h>" > $@
+
+endif # CONFIG_MODVERSIONS
 
+ifneq "$(strip $(SYMTAB_OBJS))" ""
+$(SYMTAB_OBJS): $(TOPDIR)/include/linux/modversions.h
+	$(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c)
 endif
+
+endif # CONFIG_MODULES
+
 
 #
 # include dependency files they exist
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.1.20/linux/arch/alpha/defconfig	Mon Dec 30 15:39:02 1996
+++ linux/arch/alpha/defconfig	Tue Jan 14 12:59:10 1997
@@ -183,9 +183,7 @@
 #
 # CONFIG_QUOTA is not set
 # CONFIG_MINIX_FS is not set
-# CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 # CONFIG_VFAT_FS is not set
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.1.20/linux/arch/alpha/kernel/Makefile	Tue Jun  4 06:06:37 1996
+++ linux/arch/alpha/kernel/Makefile	Fri Jan  3 11:33:25 1997
@@ -16,7 +16,8 @@
 
 O_TARGET := kernel.o
 O_OBJS   := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
-	    bios32.o ptrace.o time.o apecs.o lca.o cia.o ksyms.o
+	    bios32.o ptrace.o time.o apecs.o lca.o cia.o
+OX_OBJS  := alpha_ksyms.o
 
 all: kernel.o head.o
 
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.1.20/linux/arch/alpha/kernel/alpha_ksyms.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Fri Jan  3 11:33:25 1997
@@ -0,0 +1,103 @@
+/*
+ * linux/arch/alpha/kernel/ksyms.c
+ *
+ * Export the alpha-specific functions that are needed for loadable
+ * modules.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <asm/io.h>
+#include <asm/hwrpb.h>
+#include <asm/uaccess.h>
+
+
+extern void bcopy (const char *src, char *dst, int len);
+extern struct hwrpb_struct *hwrpb;
+extern long __kernel_thread(unsigned long, int (*)(void *), void *);
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+
+/* these are C runtime functions with special calling conventions: */
+extern void __divl (void);
+extern void __reml (void);
+extern void __divq (void);
+extern void __remq (void);
+extern void __divlu (void);
+extern void __remlu (void);
+extern void __divqu (void);
+extern void __remqu (void);
+
+
+/* platform dependent support */
+EXPORT_SYMBOL(_inb);
+EXPORT_SYMBOL(_inw);
+EXPORT_SYMBOL(_inl);
+EXPORT_SYMBOL(_outb);
+EXPORT_SYMBOL(_outw);
+EXPORT_SYMBOL(_outl);
+EXPORT_SYMBOL(_readb);
+EXPORT_SYMBOL(_readw);
+EXPORT_SYMBOL(_readl);
+EXPORT_SYMBOL(_writeb);
+EXPORT_SYMBOL(_writew);
+EXPORT_SYMBOL(_writel);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strtok);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(__constant_c_memset);
+
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(hwrpb);
+EXPORT_SYMBOL(wrusp);
+EXPORT_SYMBOL(__kernel_thread);
+
+/*
+ * The following are specially called from the uaccess assembly stubs.
+ */
+EXPORT_SYMBOL_NOVERS(__copy_user);
+EXPORT_SYMBOL_NOVERS(__clear_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(__strlen_user);
+
+/*
+ * The following are special because they're not called
+ * explicitly (the C compiler or assembler generates them in
+ * response to division operations).  Fortunately, their
+ * interface isn't gonna change any time soon now, so it's OK
+ * to leave it out of version control.
+ */
+# undef bcopy
+# undef memcpy
+# undef memset
+EXPORT_SYMBOL_NOVERS(__divl);
+EXPORT_SYMBOL_NOVERS(__divlu);
+EXPORT_SYMBOL_NOVERS(__divq);
+EXPORT_SYMBOL_NOVERS(__divqu);
+EXPORT_SYMBOL_NOVERS(__reml);
+EXPORT_SYMBOL_NOVERS(__remlu);
+EXPORT_SYMBOL_NOVERS(__remq);
+EXPORT_SYMBOL_NOVERS(__remqu);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/kernel/ksyms.c linux/arch/alpha/kernel/ksyms.c
--- v2.1.20/linux/arch/alpha/kernel/ksyms.c	Mon Dec 30 15:39:02 1996
+++ linux/arch/alpha/kernel/ksyms.c	Thu Jan  1 02:00:00 1970
@@ -1,101 +0,0 @@
-/*
- * linux/arch/alpha/kernel/ksyms.c
- *
- * Export the alpha-specific functions that are needed for loadable
- * modules.
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/uaccess.h>
-
-extern void bcopy (const char *src, char *dst, int len);
-extern struct hwrpb_struct *hwrpb;
-
-/* these are C runtime functions with special calling conventions: */
-extern void __divl (void);
-extern void __reml (void);
-extern void __divq (void);
-extern void __remq (void);
-extern void __divlu (void);
-extern void __remlu (void);
-extern void __divqu (void);
-extern void __remqu (void);
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
-
-
-/* platform dependent support */
-EXPORT_SYMBOL(_inb);
-EXPORT_SYMBOL(_inw);
-EXPORT_SYMBOL(_inl);
-EXPORT_SYMBOL(_outb);
-EXPORT_SYMBOL(_outw);
-EXPORT_SYMBOL(_outl);
-EXPORT_SYMBOL(_readb);
-EXPORT_SYMBOL(_readw);
-EXPORT_SYMBOL(_readl);
-EXPORT_SYMBOL(_writeb);
-EXPORT_SYMBOL(_writew);
-EXPORT_SYMBOL(_writel);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(__memcpy);
-EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(__constant_c_memset);
-
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(hwrpb);
-EXPORT_SYMBOL(wrusp);
-
-/*
- * The following are specially called from the uaccess assembly stubs.
- */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__clear_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(__strlen_user);
-
-/*
- * The following are special because they're not called
- * explicitly (the C compiler or assembler generates them in
- * response to division operations).  Fortunately, their
- * interface isn't gonna change any time soon now, so it's OK
- * to leave it out of version control.
- */
-# undef bcopy
-# undef memcpy
-# undef memset
-EXPORT_SYMBOL_NOVERS(__divl);
-EXPORT_SYMBOL_NOVERS(__divlu);
-EXPORT_SYMBOL_NOVERS(__divq);
-EXPORT_SYMBOL_NOVERS(__divqu);
-EXPORT_SYMBOL_NOVERS(__reml);
-EXPORT_SYMBOL_NOVERS(__remlu);
-EXPORT_SYMBOL_NOVERS(__remq);
-EXPORT_SYMBOL_NOVERS(__remqu);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.1.20/linux/arch/alpha/kernel/traps.c	Mon Dec 30 15:39:02 1996
+++ linux/arch/alpha/kernel/traps.c	Fri Jan  3 18:48:37 1997
@@ -236,7 +236,7 @@
 		"	lda %1,3b-1b(%0)\n"
 		"	.gprel32 2b\n"
 		"	lda %2,3b-2b(%0)\n"
-		".text"
+		".previous"
 			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
 			: "r"(va), "0"(0));
 		if (error)
@@ -257,7 +257,7 @@
 		"	lda %1,3b-1b(%0)\n"
 		"	.gprel32 2b\n"
 		"	lda %2,3b-2b(%0)\n"
-		".text"
+		".previous"
 			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
 			: "r"(va), "0"(0));
 		if (error)
@@ -277,7 +277,7 @@
 		"	lda %1,3b-1b(%0)\n"
 		"	.gprel32 2b\n"
 		"	lda %2,3b-2b(%0)\n"
-		".text"
+		".previous"
 			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
 			: "r"(va), "0"(0));
 		if (error)
@@ -311,7 +311,7 @@
 		"	lda $31,5b-3b(%0)\n"
 		"	.gprel32 4b\n"
 		"	lda $31,5b-4b(%0)\n"
-		".text"
+		".previous"
 			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
 			  "=&r"(tmp3), "=&r"(tmp4)
 			: "r"(va), "r"(una_reg(reg)), "0"(0));
@@ -342,7 +342,7 @@
 		"	lda $31,5b-3b(%0)\n"
 		"	.gprel32 4b\n"
 		"	lda $31,5b-4b(%0)\n"
-		".text"
+		".previous"
 			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
 			  "=&r"(tmp3), "=&r"(tmp4)
 			: "r"(va), "r"(una_reg(reg)), "0"(0));
@@ -372,7 +372,7 @@
 		"	lda $31,5b-3b(%0)\n"
 		"	.gprel32 4b\n"
 		"	lda $31,5b-4b(%0)\n"
-		".text"
+		".previous"
 			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
 			  "=&r"(tmp3), "=&r"(tmp4)
 			: "r"(va), "r"(una_reg(reg)), "0"(0));
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/lib/clear_user.S linux/arch/alpha/lib/clear_user.S
--- v2.1.20/linux/arch/alpha/lib/clear_user.S	Fri Nov  1 17:13:14 1996
+++ linux/arch/alpha/lib/clear_user.S	Fri Jan  3 18:48:37 1997
@@ -31,7 +31,7 @@
 	.section __ex_table,"a";	\
 	.gprel32 99b;			\
 	lda $31, $exception-99b($31); 	\
-	.text
+	.previous
 
 	.set noat
 	.set noreorder
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/lib/copy_user.S linux/arch/alpha/lib/copy_user.S
--- v2.1.20/linux/arch/alpha/lib/copy_user.S	Fri Nov  1 17:13:14 1996
+++ linux/arch/alpha/lib/copy_user.S	Fri Jan  3 18:48:37 1997
@@ -33,7 +33,7 @@
 	.section __ex_table,"a";	\
 	.gprel32 99b;			\
 	lda $31, $exit-99b($31);	\
-	.text
+	.previous
 
 	.set noat
 	.align 3
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/lib/strlen_user.S linux/arch/alpha/lib/strlen_user.S
--- v2.1.20/linux/arch/alpha/lib/strlen_user.S	Tue Nov 19 15:53:53 1996
+++ linux/arch/alpha/lib/strlen_user.S	Fri Jan  3 18:48:37 1997
@@ -14,7 +14,7 @@
 	.section __ex_table,"a";	\
 	.gprel32 99b;			\
 	lda v0, $exception-99b(zero);	\
-	.text
+	.previous
 
 
 	.set noreorder
diff -u --recursive --new-file v2.1.20/linux/arch/alpha/lib/strncpy_from_user.S linux/arch/alpha/lib/strncpy_from_user.S
--- v2.1.20/linux/arch/alpha/lib/strncpy_from_user.S	Mon Dec 30 15:39:02 1996
+++ linux/arch/alpha/lib/strncpy_from_user.S	Fri Jan  3 18:48:37 1997
@@ -21,7 +21,7 @@
 	.section __ex_table,"a";	\
 	.gprel32 99b;			\
 	lda $31, $exception-99b($0); 	\
-	.text
+	.previous
 
 
 	.set noat
diff -u --recursive --new-file v2.1.20/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.1.20/linux/arch/i386/Makefile	Thu Sep 26 07:39:10 1996
+++ linux/arch/i386/Makefile	Fri Jan  3 11:33:25 1997
@@ -45,7 +45,7 @@
 BZLINKFLAGS =-Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
 LINKFLAGS =-Ttext $(IMAGE_OFFSET) $(LDFLAGS)
 
-CFLAGS := $(CFLAGS) -pipe
+CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
 
 ifdef CONFIG_M386
 CFLAGS := $(CFLAGS) -m386 -DCPU=386
diff -u --recursive --new-file v2.1.20/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.20/linux/arch/i386/defconfig	Thu Jan  2 15:55:14 1997
+++ linux/arch/i386/defconfig	Tue Jan 14 12:59:10 1997
@@ -136,9 +136,7 @@
 #
 # CONFIG_QUOTA is not set
 CONFIG_MINIX_FS=y
-# CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 # CONFIG_VFAT_FS is not set
@@ -151,6 +149,7 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
diff -u --recursive --new-file v2.1.20/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.1.20/linux/arch/i386/kernel/Makefile	Wed Dec 18 15:58:34 1996
+++ linux/arch/i386/kernel/Makefile	Fri Jan  3 11:33:25 1997
@@ -22,7 +22,8 @@
 
 O_TARGET := kernel.o
 O_OBJS   := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \
-            ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o
+            ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o
+OX_OBJS  := i386_ksyms.o
 
 ifdef CONFIG_MCA
 O_OBJS += mca.o
diff -u --recursive --new-file v2.1.20/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.1.20/linux/arch/i386/kernel/i386_ksyms.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/kernel/i386_ksyms.c	Fri Jan  3 11:33:25 1997
@@ -0,0 +1,48 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/mca.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
+/* platform dependent support */
+EXPORT_SYMBOL(EISA_bus);
+EXPORT_SYMBOL(MCA_bus);
+EXPORT_SYMBOL(wp_works_ok);
+EXPORT_SYMBOL(__verify_write);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
+#ifdef __SMP__
+EXPORT_SYMBOL(apic_reg);	/* Needed internally for the I386 inlines */
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(syscall_count);
+EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_counter);
+EXPORT_SYMBOL(active_kernel_processor);
+EXPORT_SYMBOL(smp_invalidate_needed);
+#endif
+
+#ifdef CONFIG_MCA
+/* Adapter probing and info methods. */
+EXPORT_SYMBOL(mca_write_pos);
+EXPORT_SYMBOL(mca_read_pos);
+EXPORT_SYMBOL(mca_read_stored_pos);
+EXPORT_SYMBOL(mca_set_adapter_name);
+EXPORT_SYMBOL(mca_get_adapter_name);
+EXPORT_SYMBOL(mca_set_adapter_procfn);
+EXPORT_SYMBOL(mca_isenabled);
+EXPORT_SYMBOL(mca_isadapter);
+#endif
diff -u --recursive --new-file v2.1.20/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c
--- v2.1.20/linux/arch/i386/kernel/ksyms.c	Mon Dec 30 15:39:03 1996
+++ linux/arch/i386/kernel/ksyms.c	Thu Jan  1 02:00:00 1970
@@ -1,48 +0,0 @@
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/mca.h>
-
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
-
-/* platform dependent support */
-EXPORT_SYMBOL(EISA_bus);
-EXPORT_SYMBOL(MCA_bus);
-EXPORT_SYMBOL(wp_works_ok);
-EXPORT_SYMBOL(__verify_write);
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(ioremap);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
-#ifdef __SMP__
-EXPORT_SYMBOL(apic_reg);	/* Needed internally for the I386 inlines */
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(syscall_count);
-EXPORT_SYMBOL(kernel_flag);
-EXPORT_SYMBOL(kernel_counter);
-EXPORT_SYMBOL(active_kernel_processor);
-EXPORT_SYMBOL(smp_invalidate_needed);
-#endif
-
-#ifdef CONFIG_MCA
-/* Adapter probing and info methods. */
-EXPORT_SYMBOL(mca_write_pos);
-EXPORT_SYMBOL(mca_read_pos);
-EXPORT_SYMBOL(mca_read_stored_pos);
-EXPORT_SYMBOL(mca_set_adapter_name);
-EXPORT_SYMBOL(mca_get_adapter_name);
-EXPORT_SYMBOL(mca_set_adapter_procfn);
-EXPORT_SYMBOL(mca_isenabled);
-EXPORT_SYMBOL(mca_isadapter);
-#endif
diff -u --recursive --new-file v2.1.20/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.20/linux/arch/i386/kernel/process.c	Thu Jan  2 15:55:14 1997
+++ linux/arch/i386/kernel/process.c	Fri Jan  3 11:54:16 1997
@@ -284,8 +284,7 @@
 	if(!reboot_thru_bios) {
 		sti();
 		/* rebooting needs to touch the page at absolute addr 0 */
-		pg0[0] = 7;
-		*((unsigned short *)0x472) = reboot_mode;
+		*((unsigned short *)__va(0x472)) = reboot_mode;
 		for (;;) {
 			int i;
 			for (i=0; i<100; i++) {
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/amiga/Makefile linux/arch/m68k/amiga/Makefile
--- v2.1.20/linux/arch/m68k/amiga/Makefile	Wed Sep 25 10:47:37 1996
+++ linux/arch/m68k/amiga/Makefile	Fri Jan  3 11:33:25 1997
@@ -9,7 +9,8 @@
 
 O_TARGET := amiga.o
 O_OBJS   := config.o amikeyb.o amiints.o cia.o \
-            chipram.o amisound.o amifb.o zorro.o ksyms.o
+            chipram.o amisound.o amifb.o zorro.o
+OX_OBJS  := amiga_ksyms.o
 
 ifdef CONFIG_FB_CYBER
 O_OBJS := $(O_OBJS) cyberfb.o
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/amiga/amiga_ksyms.c linux/arch/m68k/amiga/amiga_ksyms.c
--- v2.1.20/linux/arch/m68k/amiga/amiga_ksyms.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/m68k/amiga/amiga_ksyms.c	Fri Jan  3 11:33:25 1997
@@ -0,0 +1,26 @@
+#include <linux/types.h>
+#include <linux/module.h>
+#include <asm/zorro.h>
+#include <asm/amigahw.h>
+
+extern volatile u_short amiga_audio_min_period;
+extern u_short amiga_audio_period;
+
+/*
+ * Add things here when you find the need for it.
+ */
+EXPORT_SYMBOL(amiga_model);
+EXPORT_SYMBOL(amiga_hw_present);
+EXPORT_SYMBOL(amiga_eclock);
+EXPORT_SYMBOL(amiga_colorclock);
+EXPORT_SYMBOL(amiga_chip_alloc);
+EXPORT_SYMBOL(amiga_chip_free);
+EXPORT_SYMBOL(amiga_chip_avail);
+EXPORT_SYMBOL(amiga_audio_period);
+EXPORT_SYMBOL(amiga_audio_min_period);
+
+EXPORT_SYMBOL(zorro_find);
+EXPORT_SYMBOL(zorro_get_board);
+EXPORT_SYMBOL(zorro_config_board);
+EXPORT_SYMBOL(zorro_unconfig_board);
+EXPORT_SYMBOL(zorro_unused_z2ram);
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/amiga/ksyms.c linux/arch/m68k/amiga/ksyms.c
--- v2.1.20/linux/arch/m68k/amiga/ksyms.c	Mon Dec 30 15:39:03 1996
+++ linux/arch/m68k/amiga/ksyms.c	Thu Jan  1 02:00:00 1970
@@ -1,26 +0,0 @@
-#include <linux/types.h>
-#include <linux/module.h>
-#include <asm/zorro.h>
-#include <asm/amigahw.h>
-
-extern volatile u_short amiga_audio_min_period;
-extern u_short amiga_audio_period;
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(amiga_model);
-EXPORT_SYMBOL(amiga_hw_present);
-EXPORT_SYMBOL(amiga_eclock);
-EXPORT_SYMBOL(amiga_colorclock);
-EXPORT_SYMBOL(amiga_chip_alloc);
-EXPORT_SYMBOL(amiga_chip_free);
-EXPORT_SYMBOL(amiga_chip_avail);
-EXPORT_SYMBOL(amiga_audio_period);
-EXPORT_SYMBOL(amiga_audio_min_period);
-
-EXPORT_SYMBOL(zorro_find);
-EXPORT_SYMBOL(zorro_get_board);
-EXPORT_SYMBOL(zorro_config_board);
-EXPORT_SYMBOL(zorro_unconfig_board);
-EXPORT_SYMBOL(zorro_unused_z2ram);
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/atari/Makefile linux/arch/m68k/atari/Makefile
--- v2.1.20/linux/arch/m68k/atari/Makefile	Sun Dec 22 16:37:21 1996
+++ linux/arch/m68k/atari/Makefile	Fri Jan  3 11:33:25 1997
@@ -9,6 +9,7 @@
 
 O_TARGET := atari.o
 O_OBJS	 := config.o atakeyb.o ataints.o \
-            stdma.o atasound.o joystick.o stram.o atafb.o ksyms.o
+            stdma.o atasound.o joystick.o stram.o atafb.o
+OX_OBJS  := atari_ksyms.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/atari/atari_ksyms.c linux/arch/m68k/atari/atari_ksyms.c
--- v2.1.20/linux/arch/m68k/atari/atari_ksyms.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/m68k/atari/atari_ksyms.c	Fri Jan  3 11:33:25 1997
@@ -0,0 +1,33 @@
+#include <linux/module.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atarikb.h>
+#include <asm/atari_joystick.h>
+#include <asm/atari_stdma.h>
+
+extern void atari_microwire_cmd( int cmd );
+
+
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(atari_hw_present);
+EXPORT_SYMBOL(is_medusa);
+EXPORT_SYMBOL(atari_register_vme_int);
+EXPORT_SYMBOL(atari_unregister_vme_int);
+EXPORT_SYMBOL(stdma_lock);
+EXPORT_SYMBOL(stdma_release);
+EXPORT_SYMBOL(stdma_others_waiting);
+EXPORT_SYMBOL(stdma_islocked);
+
+EXPORT_SYMBOL(atari_mouse_buttons);
+EXPORT_SYMBOL(atari_mouse_interrupt_hook);
+EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(ikbd_write);
+EXPORT_SYMBOL(ikbd_mouse_y0_top);
+EXPORT_SYMBOL(ikbd_mouse_thresh);
+EXPORT_SYMBOL(ikbd_mouse_rel_pos);
+EXPORT_SYMBOL(ikbd_mouse_disable);
+
+EXPORT_SYMBOL(atari_microwire_cmd);
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/atari/ksyms.c linux/arch/m68k/atari/ksyms.c
--- v2.1.20/linux/arch/m68k/atari/ksyms.c	Mon Dec 30 15:39:03 1996
+++ linux/arch/m68k/atari/ksyms.c	Thu Jan  1 02:00:00 1970
@@ -1,33 +0,0 @@
-#include <linux/module.h>
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-
-extern void atari_microwire_cmd( int cmd );
-
-
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(atari_hw_present);
-EXPORT_SYMBOL(is_medusa);
-EXPORT_SYMBOL(atari_register_vme_int);
-EXPORT_SYMBOL(atari_unregister_vme_int);
-EXPORT_SYMBOL(stdma_lock);
-EXPORT_SYMBOL(stdma_release);
-EXPORT_SYMBOL(stdma_others_waiting);
-EXPORT_SYMBOL(stdma_islocked);
-
-EXPORT_SYMBOL(atari_mouse_buttons);
-EXPORT_SYMBOL(atari_mouse_interrupt_hook);
-EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(ikbd_write);
-EXPORT_SYMBOL(ikbd_mouse_y0_top);
-EXPORT_SYMBOL(ikbd_mouse_thresh);
-EXPORT_SYMBOL(ikbd_mouse_rel_pos);
-EXPORT_SYMBOL(ikbd_mouse_disable);
-
-EXPORT_SYMBOL(atari_microwire_cmd);
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/defconfig linux/arch/m68k/defconfig
--- v2.1.20/linux/arch/m68k/defconfig	Sun Dec 22 16:37:22 1996
+++ linux/arch/m68k/defconfig	Tue Jan 14 12:59:10 1997
@@ -149,9 +149,7 @@
 #
 # CONFIG_QUOTA is not set
 CONFIG_MINIX_FS=y
-# CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 # CONFIG_VFAT_FS is not set
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/kernel/Makefile linux/arch/m68k/kernel/Makefile
--- v2.1.20/linux/arch/m68k/kernel/Makefile	Wed Sep 25 10:47:39 1996
+++ linux/arch/m68k/kernel/Makefile	Fri Jan  3 11:33:25 1997
@@ -13,7 +13,8 @@
 all: kernel.o head.o
 O_TARGET := kernel.o
 O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
-	  setup.o bios32.o sys_m68k.o console.o time.o ksyms.o
+	  setup.o bios32.o sys_m68k.o console.o time.o
+OX_OBJS := m68k_ksyms.o
 
 head.o: head.S
 
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/kernel/ksyms.c linux/arch/m68k/kernel/ksyms.c
--- v2.1.20/linux/arch/m68k/kernel/ksyms.c	Mon Dec 30 15:39:03 1996
+++ linux/arch/m68k/kernel/ksyms.c	Thu Jan  1 02:00:00 1970
@@ -1,51 +0,0 @@
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-
-#include <asm/setup.h>
-#include <asm/machdep.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/semaphore.h>
-
-asmlinkage long long __ashrdi3 (long long, int);
-extern char m68k_debug_device[];
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
-
-/* platform dependent support */
-
-EXPORT_SYMBOLS(memcmp);
-EXPORT_SYMBOLS(m68k_machtype);
-EXPORT_SYMBOLS(m68k_cputype);
-EXPORT_SYMBOLS(m68k_is040or060);
-EXPORT_SYMBOLS(cache_push);
-EXPORT_SYMBOLS(cache_push_v);
-EXPORT_SYMBOLS(cache_clear);
-EXPORT_SYMBOLS(mm_vtop);
-EXPORT_SYMBOLS(mm_ptov);
-EXPORT_SYMBOLS(mm_end_of_chunk);
-EXPORT_SYMBOLS(m68k_debug_device);
-EXPORT_SYMBOLS(request_irq);
-EXPORT_SYMBOLS(free_irq);
-EXPORT_SYMBOLS(dump_fpu);
-EXPORT_SYMBOLS(dump_thread);
-EXPORT_SYMBOLS(strnlen);
-EXPORT_SYMBOLS(strrchr);
-EXPORT_SYMBOLS(strstr);
-
-/* The following are special because they're not called
-   explicitly (the C compiler generates them).  Fortunately,
-   their interface isn't gonna change any time soon now, so
-   it's OK to leave it out of version control.  */
-EXPORT_SYMBOLS_NOVERS(__ashrdi3);
-EXPORT_SYMBOLS_NOVERS(memcpy);
-EXPORT_SYMBOLS_NOVERS(memset);
-
-EXPORT_SYMBOLS_NOVERS(__down_failed);
-EXPORT_SYMBOLS_NOVERS(__up_wakeup);
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.1.20/linux/arch/m68k/kernel/m68k_ksyms.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/m68k/kernel/m68k_ksyms.c	Fri Jan  3 11:33:25 1997
@@ -0,0 +1,51 @@
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+
+#include <asm/setup.h>
+#include <asm/machdep.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/semaphore.h>
+
+asmlinkage long long __ashrdi3 (long long, int);
+extern char m68k_debug_device[];
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOLS(memcmp);
+EXPORT_SYMBOLS(m68k_machtype);
+EXPORT_SYMBOLS(m68k_cputype);
+EXPORT_SYMBOLS(m68k_is040or060);
+EXPORT_SYMBOLS(cache_push);
+EXPORT_SYMBOLS(cache_push_v);
+EXPORT_SYMBOLS(cache_clear);
+EXPORT_SYMBOLS(mm_vtop);
+EXPORT_SYMBOLS(mm_ptov);
+EXPORT_SYMBOLS(mm_end_of_chunk);
+EXPORT_SYMBOLS(m68k_debug_device);
+EXPORT_SYMBOLS(request_irq);
+EXPORT_SYMBOLS(free_irq);
+EXPORT_SYMBOLS(dump_fpu);
+EXPORT_SYMBOLS(dump_thread);
+EXPORT_SYMBOLS(strnlen);
+EXPORT_SYMBOLS(strrchr);
+EXPORT_SYMBOLS(strstr);
+
+/* The following are special because they're not called
+   explicitly (the C compiler generates them).  Fortunately,
+   their interface isn't gonna change any time soon now, so
+   it's OK to leave it out of version control.  */
+EXPORT_SYMBOLS_NOVERS(__ashrdi3);
+EXPORT_SYMBOLS_NOVERS(memcpy);
+EXPORT_SYMBOLS_NOVERS(memset);
+
+EXPORT_SYMBOLS_NOVERS(__down_failed);
+EXPORT_SYMBOLS_NOVERS(__up_wakeup);
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c
--- v2.1.20/linux/arch/m68k/kernel/signal.c	Sun Dec 22 16:37:22 1996
+++ linux/arch/m68k/kernel/signal.c	Fri Jan  3 18:48:37 1997
@@ -174,7 +174,7 @@
 
 	if (context.sc_usp != fp+fsize)
 		current->flags &= ~PF_ONSIGSTK;
-	
+
 	/* OK.	Make room on the supervisor stack for the extra junk,
 	 * if necessary.
 	 */
@@ -200,7 +200,7 @@
 			 "   .align 4\n"
 			 "   .long 2b,4b\n"
 			 "   .long 3b,4b\n"
-			 ".text"
+			 ".previous"
 			 : /* no outputs, it doesn't ever return */
 			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
 			   "n" (frame_offset), "a" (fp)
@@ -360,7 +360,7 @@
 
 /*
  * OK, we're invoking a handler
- */	
+ */
 static inline void handle_signal(unsigned long signr, struct sigaction *sa,
 				 unsigned long oldmask, struct pt_regs *regs)
 {
@@ -482,7 +482,7 @@
 					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
 				      SA_NOCLDSTOP))
 					notify_parent(current);
 				schedule();
diff -u --recursive --new-file v2.1.20/linux/arch/m68k/lib/checksum.c linux/arch/m68k/lib/checksum.c
--- v2.1.20/linux/arch/m68k/lib/checksum.c	Fri Nov 22 18:28:17 1996
+++ linux/arch/m68k/lib/checksum.c	Fri Jan  3 18:48:37 1997
@@ -241,7 +241,7 @@
 		".long 19b,7b\n"
 		".long 20b,7b\n"
 		".long 21b,7b\n"
-		".text"
+		".previous"
 		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
 		  "=&d" (tmp1), "=&d" (tmp2)
 		: "0" (sum), "1" (len), "2" (src), "3" (dst)
diff -u --recursive --new-file v2.1.20/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.1.20/linux/arch/mips/defconfig	Thu Feb  8 05:41:50 1996
+++ linux/arch/mips/defconfig	Tue Jan 14 12:59:10 1997
@@ -53,9 +53,7 @@
 # Filesystems
 #
 # CONFIG_MINIX_FS is not set
-# CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
 # CONFIG_MSDOS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_ISO9660_FS is not set
diff -u --recursive --new-file v2.1.20/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.1.20/linux/arch/sparc/defconfig	Tue Dec 31 21:40:59 1996
+++ linux/arch/sparc/defconfig	Tue Jan 14 12:59:10 1997
@@ -167,9 +167,7 @@
 #
 CONFIG_QUOTA=y
 CONFIG_MINIX_FS=m
-CONFIG_EXT_FS=m
 CONFIG_EXT2_FS=y
-CONFIG_XIA_FS=m
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
diff -u --recursive --new-file v2.1.20/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.1.20/linux/arch/sparc/kernel/sparc_ksyms.c	Tue Dec 31 21:40:59 1996
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Tue Jan 14 08:58:19 1997
@@ -67,10 +67,8 @@
  */
 
 #define EXPORT_SYMBOL_DOT(sym)					\
-extern int __sparc_dot_ ## sym (int) __asm__("." ## #sym);	\
-const struct module_symbol __export_dot_##sym			\
-__attribute__((section("__ksymtab"))) =				\
-{ (unsigned long) &__sparc_dot_ ## sym, "." ## #sym }
+extern int __sparc_dot_ ## sym (int) __asm__("." #sym);		\
+__EXPORT_SYMBOL(__sparc_dot_ ## sym, "." #sym)
 
 
 /* used by various drivers */
diff -u --recursive --new-file v2.1.20/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.1.20/linux/arch/sparc/kernel/sys_sunos.c	Tue Dec 31 21:41:00 1996
+++ linux/arch/sparc/kernel/sys_sunos.c	Tue Jan 14 12:59:10 1997
@@ -779,10 +779,6 @@
 		dev_fname = (char *) data;
 	} else if(strcmp(type, "minix") == 0) {
 		dev_fname = (char *) data;
-	} else if(strcmp(type, "ext") == 0) {
-		dev_fname = (char *) data;
-	} else if(strcmp(type, "xiafs") == 0) {
-		dev_fname = (char *) data;
 	} else if(strcmp(type, "nfs") == 0) {
 		return sunos_nfs_mount (dir, flags, data);
         } else if(strcmp(type, "ufs") == 0) {
diff -u --recursive --new-file v2.1.20/linux/arch/sparc/kernel/unaligned.c linux/arch/sparc/kernel/unaligned.c
--- v2.1.20/linux/arch/sparc/kernel/unaligned.c	Wed Dec 18 15:58:46 1996
+++ linux/arch/sparc/kernel/unaligned.c	Fri Jan  3 18:48:37 1997
@@ -202,11 +202,11 @@
 	".word	14b, " #errh "\n\t"						\
 	".word	15b, " #errh "\n\t"						\
 	".word	16b, " #errh "\n\n\t"						\
-	".text\n\t"								\
+	".previous\n\t"								\
 	: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed)		\
 	: "l1", "l2", "g7", "g1");						\
 })
-	
+
 #define store_common(dst_addr, size, src_val, errh) ({				\
 __asm__ __volatile__ (								\
 	"ld	[%2], %%l1\n"							\
@@ -256,7 +256,7 @@
 	".word	15b, " #errh "\n\t"						\
 	".word	16b, " #errh "\n\t"						\
 	".word	17b, " #errh "\n\n\t"						\
-	".text\n\t"								\
+	".previous\n\t"								\
 	: : "r" (dst_addr), "r" (size), "r" (src_val)				\
 	: "l1", "l2", "g7", "g1");						\
 })
@@ -307,7 +307,7 @@
 {
 	unsigned long g2 = regs->u_regs [UREG_G2];
 	unsigned long fixup = search_exception_table (regs->pc, &g2);
-	
+
 	if (!fixup) {
 		unsigned long address = compute_effective_address(regs, insn);
         	if(address < PAGE_SIZE) {
@@ -336,7 +336,7 @@
 		printk("Unsupported unaligned load/store trap for kernel at <%08lx>.\n",
 		       regs->pc);
 		unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store.");
-		
+
 		__asm__ __volatile__ ("\n"
 "kernel_unaligned_trap_fault:\n\t"
 		"mov	%0, %%o0\n\t"
@@ -344,7 +344,7 @@
 		" mov	%1, %%o1\n\t"
 		: : "r" (regs), "r" (insn)
 		: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
-		
+
 		return;
 	} else {
 		unsigned long addr = compute_effective_address(regs, insn);
@@ -369,7 +369,7 @@
 #if 0 /* unsupported */
 		case both:
 			do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
-				  (unsigned long *) addr, 
+				  (unsigned long *) addr,
 				  kernel_unaligned_trap_fault);
 			break;
 #endif
@@ -477,7 +477,7 @@
 			" mov	%1, %%o1\n\t"
 			: : "r" (regs), "r" (insn)
 			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
-		
+
 			return;
 		}
 		advance(regs);
diff -u --recursive --new-file v2.1.20/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.20/linux/arch/sparc64/defconfig	Tue Dec 31 21:41:00 1996
+++ linux/arch/sparc64/defconfig	Tue Jan 14 12:59:10 1997
@@ -165,9 +165,7 @@
 #
 CONFIG_QUOTA=y
 CONFIG_MINIX_FS=y
-CONFIG_EXT_FS=y
 CONFIG_EXT2_FS=y
-CONFIG_XIA_FS=y
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
diff -u --recursive --new-file v2.1.20/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.20/linux/drivers/block/rd.c	Mon Dec 30 15:39:04 1996
+++ linux/drivers/block/rd.c	Fri Jan  3 13:03:42 1997
@@ -41,6 +41,7 @@
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/ext2_fs.h>
+#include <linux/romfs_fs.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -328,6 +329,7 @@
  * We currently check for the following magic numbers:
  * 	minix
  * 	ext2
+ *	romfs
  * 	gzip
  */
 int
@@ -336,6 +338,7 @@
 	const int size = 512;
 	struct minix_super_block *minixsb;
 	struct ext2_super_block *ext2sb;
+	struct romfs_super_block *romfsb;
 	int nblocks = -1;
 	int max_blocks;
 	unsigned char *buf;
@@ -346,6 +349,7 @@
 
 	minixsb = (struct minix_super_block *) buf;
 	ext2sb = (struct ext2_super_block *) buf;
+	romfsb = (struct romfs_super_block *) buf;
 	memset(buf, 0xe5, size);
 
 	/*
@@ -368,6 +372,16 @@
 		goto done;
 	}
 
+	/* romfs is at block zero too */
+	if (romfsb->word0 == ROMSB_WORD0 &&
+	    romfsb->word1 == ROMSB_WORD1) {
+		printk(KERN_NOTICE
+		       "RAMDISK: Romfs filesystem found at block %d\n",
+		       start_block);
+		nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+		goto done;
+	}
+
 	/*
 	 * Read block 1 to test for minix and ext2 superblock
 	 */
@@ -396,6 +410,7 @@
 		nblocks = ext2sb->s_blocks_count;
 		goto done;
 	}
+
 	printk(KERN_NOTICE
 	       "RAMDISK: Couldn't find valid ramdisk image starting at %d.\n",
 	       start_block);
diff -u --recursive --new-file v2.1.20/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.20/linux/drivers/char/serial.c	Mon Dec 30 15:39:08 1996
+++ linux/drivers/char/serial.c	Tue Jan 14 12:52:46 1997
@@ -25,6 +25,7 @@
  * 	int rs_open(struct tty_struct * tty, struct file * filp)
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
@@ -35,7 +36,6 @@
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
-#include <linux/config.h>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
@@ -2931,6 +2931,11 @@
 	}
 	state->xmit_fifo_size =	uart_config[state->type].dfl_xmit_fifo_size;
 
+	if (state->type == PORT_UNKNOWN) {
+		restore_flags(flags);
+		return;
+	}
+
 	request_region(info->port,8,"serial(auto)");
 
 	/*
@@ -3099,11 +3104,6 @@
 	state->port = req->port;
 	state->flags = req->flags;
 
-	if (check_region(state->port,8)) {
-		restore_flags(flags);
-		printk("register_serial(): I/O region in use\n");
-		return -1;		/* Area in use */
-	}
 	autoconfig(state);
 	if (state->type == PORT_UNKNOWN) {
 		restore_flags(flags);
diff -u --recursive --new-file v2.1.20/linux/drivers/net/hdlcdrv.c linux/drivers/net/hdlcdrv.c
--- v2.1.20/linux/drivers/net/hdlcdrv.c	Thu Jan  2 15:55:18 1997
+++ linux/drivers/net/hdlcdrv.c	Fri Jan  3 11:33:26 1997
@@ -35,9 +35,8 @@
 
 /*****************************************************************************/
 
-#include <linux/module.h>
-
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/net.h>
 #include <linux/in.h>
diff -u --recursive --new-file v2.1.20/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.20/linux/drivers/net/ppp.c	Thu Jan  2 15:55:19 1997
+++ linux/drivers/net/ppp.c	Fri Jan  3 11:33:26 1997
@@ -59,6 +59,7 @@
  *   released under the GNU General Public License Version 2.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.20/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.1.20/linux/drivers/net/smc-ultra.c	Tue Dec 31 21:41:06 1996
+++ linux/drivers/net/smc-ultra.c	Tue Jan 14 08:58:19 1997
@@ -434,8 +434,8 @@
 static int io[MAX_ULTRA_CARDS] = { 0, };
 static int irq[MAX_ULTRA_CARDS]  = { 0, };
 
-MODULE_PARM(io, "1-" __MODULE_PARM(MAX_ULTRA_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_PARM(MAX_ULTRA_CARDS) "i");
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.1.20/linux/drivers/scsi/ChangeLog.ncr53c8xx	Thu Jan  2 15:55:21 1997
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Tue Jan 14 08:21:41 1997
@@ -1,3 +1,32 @@
+Sun Jan 12 12:00 1997 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c - revision 1.16e
+	- Add support of PCI burst length control from boot setup command.
+	  burst:0     disable burst
+	  burst:255   get burst from initial settings (BIOS settings?)
+	  burst:#x    set burst transfers to 1<<#x
+	- Only check xfer direction for common op-codes.
+	  For all device specific / vendor specific opcodes the driver 
+	  now uses the xfer direction decided by the target.
+
+Sun Jan 05 12:00 1997 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c - revision 1.16d
+	- The driver is now able to process scsi commands without 
+	  knowledge of xfer data direction.
+	  Stefan agreed with this change for Linux. This change is 
+	  not needed under FreeBSD since low-level drivers receive 
+	  the expected data direction for each scsi request.
+	- Save ctest5 features bits at start-up and restore them at 
+	  module release step.
+	  Avoid side effects when a ncr driver which trusts bios 
+	  settings is reloaded (could be the ncr53c8xx itself).
+
+
+Wed Jan 01 23:30 1997 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c - revision 1.16c
+	- Bad decision about 20MHz for 13 ns period factor.
+	  Was wrong, so I restore the previous algorithm.
+	- Burst length 128 not correctly set in dmode.
+
 Thu Dec 26 22:00 1996 Gerard Roudier (groudier@club-internet.fr)
 	* ncr53c8xx.c ncr53c8xx.h README.ncr53c8xx - revision 1.16b
 	- Remove useless code.
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.1.20/linux/drivers/scsi/Config.in	Thu Jan  2 15:55:21 1997
+++ linux/drivers/scsi/Config.in	Tue Jan 14 12:48:50 1997
@@ -32,6 +32,8 @@
 dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
   if [ "$CONFIG_SCSI_EATA" != "n" ]; then
     bool '  enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE
+    bool '  enable linked commands' CONFIG_SCSI_EATA_LINKED_COMMANDS
+    int  '  maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
   fi
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
 dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
@@ -74,6 +76,10 @@
 dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
 dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
 dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
+  if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then
+    bool '  enable linked commands' CONFIG_SCSI_U14_34F_LINKED_COMMANDS
+    int  '  maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8
+  fi
 dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
 #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
 endmenu
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.1.20/linux/drivers/scsi/Makefile	Wed Dec 18 15:58:50 1996
+++ linux/drivers/scsi/Makefile	Tue Jan 14 08:58:19 1997
@@ -30,11 +30,19 @@
 endif
 
 ifeq ($(CONFIG_SCSI),y)
-L_OBJS += hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o
+  # We must attach scsi_syms.o to scsi.o, as otherwise there is nothing to
+  # pull the object file from the archive.
+  SCSI=scsi.o
+  ifeq ($(CONFIG_MODULES),y)
+    O_TARGET := scsi_n_syms.o
+    O_OBJS   := scsi.o
+    OX_OBJS  := scsi_syms.o
+    SCSI     := $(O_TARGET)
+  endif
+  L_OBJS += $(SCSI) hosts.o scsi_ioctl.o constants.o scsicam.o
   ifeq ($(CONFIG_PROC_FS),y)
     L_OBJS += scsi_proc.o
   endif
-LX_OBJS += scsi_syms.o
 else
   ifeq ($(CONFIG_SCSI),m)
     MX_OBJS += scsi_syms.o
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx
--- v2.1.20/linux/drivers/scsi/README.ncr53c8xx	Thu Jan  2 15:55:21 1997
+++ linux/drivers/scsi/README.ncr53c8xx	Tue Jan 14 08:21:41 1997
@@ -4,7 +4,7 @@
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-29 December 1996
+12 January 1997
 ===============================================================================
 
 1.  Introduction
@@ -62,6 +62,10 @@
 
 This driver has been tested OK with linux/i386 and Linux/Alpha.
 
+Latest driver version and patches are available at:
+
+          ftp://linux.wauug.org/pub/roudier
+
 I am not a native speaker of English and there are probably lots of
 mistakes in this README file. Any help will be welcome.
 
@@ -491,8 +495,20 @@
   DEBUG_FREEZE    0x800
   DEBUG_RESTART  0x1000
 
-You can play safely with DEBUG_NEGO. However, some of these flags may 
-generate bunches of syslog messages. 
+  You can play safely with DEBUG_NEGO. However, some of these flags may 
+  generate bunches of syslog messages. 
+
+Burst max
+      burst:0    burst disabled
+      burst:255  get burst length from initial IO register settings.
+      burst:#x   burst enabled (1<<#x burst transfers max)
+  #x is an integer value which is log base 2 of the burst transfers max.
+  The NCR53C875 and NCR53C825A support up to 128 burst transfers (#x = 7).
+  Other chips only support up to 16 (#x = 4).
+  This is a maximum value. The driver set the burst length according to chip 
+  and revision ids. By default the driver uses the maximum value supported 
+  by the chip.
+
 
 10.3 Advised boot setup commands
 
@@ -508,7 +524,8 @@
 
 The driver prints its actual setup when verbosity level is 2. You can try 
 "ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2" 
-to your boot setup command in order to check the actual setup the drive use.
+to your boot setup command in order to check the actual setup the driver is 
+using.
 
 
 11. Some constants and flags of the ncr53c8xx.h header file
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.1.20/linux/drivers/scsi/eata.c	Thu Dec 12 19:37:07 1996
+++ linux/drivers/scsi/eata.c	Tue Jan 14 12:48:50 1997
@@ -1,6 +1,10 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *       8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27
+ *          Added linked command support.
+ *          Improved detection of PCI boards using ISA base addresses.
+ *
  *       3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27
  *          Added support for tagged commands and queue depth adjustment.
  *
@@ -88,7 +92,7 @@
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *  Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -124,6 +128,15 @@
  *  PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS 
  *  v003.D0, firmware v07G.0).
  *
+ *  DPT SmartRAID boards support "Hardware Array" - a group of disk drives
+ *  which are all members of the same RAID-1 or RAID-5 array implemented
+ *  in host adapter hardware. Hardware Arrays are fully compatible with this
+ *  driver, since they look to it as a single disk drive.
+ *  By contrast RAID-0 are implemented as "Array Group", which does not
+ *  seem to be supported correctly by the actual SCSI subsystem.
+ *  To get RAID-0 functionality, the linux MD driver must be used instead of
+ *  the DPT "Array Group" feature.
+ *
  *  Multiple ISA, EISA and PCI boards can be configured in the same system.
  *  It is suggested to put all the EISA boards on the same IRQ level, all
  *  the PCI  boards on another IRQ level, while ISA boards cannot share 
@@ -202,6 +215,7 @@
 
 #undef FORCE_CONFIG
 
+#undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
@@ -231,6 +245,8 @@
 #define LOCKED   2
 #define IN_RESET 3
 #define IGNORE   4
+#define READY    5
+#define ABORTING 6
 #define NO_DMA  0xff
 #define MAXLOOP 200000
 
@@ -245,8 +261,9 @@
 #define REG_MID         4
 #define REG_MSB         5
 #define REGION_SIZE     9
-#define ISA_RANGE       0x0fff
-#define EISA_RANGE      0xfc88
+#define MAX_ISA_ADDR    0x03ff
+#define MIN_EISA_ADDR   0x1c88
+#define MAX_EISA_ADDR   0xfc88
 #define BSY_ASSERTED      0x80
 #define DRQ_ASSERTED      0x08
 #define ABSY_ASSERTED     0x01
@@ -373,6 +390,7 @@
    ulong  sp_addr;       /* Address where sp is DMA'ed when cp completes */
    ulong  sense_addr;    /* Address where Sense Data is DMA'ed on error */
    unsigned int index;   /* cp index */
+   unsigned int link_id; /* reference cp for linked commands */
    struct sg_list *sglist;
    };
 
@@ -437,6 +455,18 @@
 static int tagged_commands = FALSE;
 #endif
 
+#if defined (CONFIG_SCSI_EATA_LINKED_COMMANDS)
+static int linked_commands = TRUE;
+#else
+static int linked_commands = FALSE;
+#endif
+
+#if defined CONFIG_SCSI_EATA_MAX_TAGS
+static int max_queue_depth = CONFIG_SCSI_EATA_MAX_TAGS;
+#else
+static int max_queue_depth = MAX_CMD_PER_LUN;
+#endif
+
 static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    Scsi_Device *dev;
    int j, ntag = 0, nuntag = 0, tqd, utqd; 
@@ -459,7 +489,7 @@
 
    tqd = (host->can_queue - utqd * nuntag) / (ntag + 1);
 
-   if (tqd > MAX_TAGGED_CMD_PER_LUN) tqd = MAX_TAGGED_CMD_PER_LUN;
+   if (tqd > max_queue_depth) tqd = max_queue_depth;
 
    if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN;
 
@@ -568,34 +598,59 @@
    else
       protocol_rev = 'C';
 
-   irq = info.irq;
-
-   if (port_base > ISA_RANGE) {
-
-      if (!info.haaval || info.ata || info.drqvld) {
-	 printk("%s: unusable EISA/PCI board found (%d%d%d), detaching.\n", 
-		name, info.haaval, info.ata, info.drqvld);
-	 return FALSE;
-	 }
-
+   if (!setup_done && j > 0 && j <= MAX_PCI) {
+      bus_type = "PCI";
+      subversion = ESA;
+      }
+   else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) {
+      bus_type = "PCI";
+      subversion = ESA;
+      }
+   else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) {
+      bus_type = "EISA";
+      subversion = ESA;
+      }
+   else if (protocol_rev == 'C' && !info.eisa && !info.pci) {
+      bus_type = "ISA";
+      subversion = ISA;
+      }
+   else if (port_base > MAX_ISA_ADDR) {
+      bus_type = "PCI";
       subversion = ESA;
-      dma_channel = NO_DMA;
       }
    else {
+      bus_type = "ISA";
+      subversion = ISA;
+      }
 
-      if (!info.haaval || info.ata || !info.drqvld) {
-	 printk("%s: unusable ISA board found (%d%d%d), detaching.\n",
-		name, info.haaval, info.ata, info.drqvld);
-	 return FALSE;
-	 }
+   if (!info.haaval || info.ata) {
+      printk("%s: address 0x%03x, unusable %s board (%d%d), detaching.\n",
+             name, port_base, bus_type, info.haaval, info.ata);
+      return FALSE;
+      }
+
+   if (info.drqvld) {
+
+      if (subversion ==  ESA)
+	 printk("%s: warning, weird %s board using DMA.\n", name, bus_type);
 
       subversion = ISA;
       dma_channel = dma_channel_table[3 - info.drqx];
       }
+   else {
+
+      if (subversion ==  ISA)
+	 printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);
+
+      subversion = ESA;
+      dma_channel = NO_DMA;
+      }
 
    if (!info.dmasup)
       printk("%s: warning, DMA protocol support not asserted.\n", name);
 
+   irq = info.irq;
+
    if (subversion == ESA && !info.irq_tr)
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
 	     name, irq);
@@ -707,11 +762,6 @@
          sh[j]->max_lun = info.max_lun + 1;
       }
 
-   if (subversion == ESA && protocol_rev == 'C' && info.pci) bus_type = "PCI";
-   else if (sh[j]->io_port > EISA_RANGE) bus_type = "PCI";
-   else if (subversion == ESA) bus_type = "EISA";
-   else bus_type = "ISA";
-
    if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "NO DMA");
    else                       sprintf(dma_name, "DMA %u", dma_channel);
 
@@ -724,10 +774,15 @@
          return FALSE;
          }
       
-   printk("%s: rev. 2.0%c, %s, PORT 0x%03x, IRQ %u, %s, SG %d, "\
-	  "Mbox %d, TC %d.\n", BN(j), HD(j)->protocol_rev, bus_type,
-          sh[j]->io_port, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
-          sh[j]->can_queue, tagged_commands);
+   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) 
+       max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
+
+   if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
+
+   printk("%s: 2.0%c, %s 0x%03x, IRQ %u, %s, SG %d, MB %d, TC %d, LC %d, "\
+          "MQ %d.\n", BN(j), HD(j)->protocol_rev, bus_type, sh[j]->io_port,
+          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
+          tagged_commands, linked_commands, max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -831,7 +886,7 @@
       }
 
    if (j > 0) 
-      printk("EATA/DMA 2.0x: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994-1997 Dario Ballabio.\n");
 
    restore_flags(flags);
    return j;
@@ -962,6 +1017,28 @@
 
    memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
+   if (linked_commands && SCpnt->device->tagged_supported
+            && !HD(j)->target_to[SCpnt->target][SCpnt->channel]
+	    && !HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+   
+      for (k = 0; k < sh[j]->can_queue; k++) {
+ 
+         if (HD(j)->cp_stat[k] != IN_USE) continue;
+
+         if ((&HD(j)->cp[k])->SCpnt->device != SCpnt->device) continue;
+
+         cpp->link_id = k;
+         HD(j)->cp_stat[i] = READY;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+         printk("%s: qcomm, target %d.%d:%d, pid %ld, Mbox %d ready.\n", 
+                BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+                SCpnt->pid, i);
+#endif
+         restore_flags(flags);
+         return 0;
+         }
+
    /* Send control packet to the board */
    if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
       SCpnt->result = DID_ERROR << 16; 
@@ -1038,6 +1115,18 @@
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
+
+   if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+      SCarg->result = DID_ABORT << 16;
+      SCarg->host_scribble = NULL;
+      HD(j)->cp_stat[i] = FREE;
+      printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
+	     BN(j), i, SCarg->pid);
+      SCarg->scsi_done(SCarg);
+      restore_flags(flags);
+      return SCSI_ABORT_SUCCESS;
+      }
+
    restore_flags(flags);
    panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
@@ -1088,14 +1177,21 @@
 	 continue;
 	 }
 
-      SCpnt = HD(j)->cp[i].SCpnt;
-      HD(j)->cp_stat[i] = IN_RESET;
-      printk("%s: reset, mbox %d in reset, pid %ld.\n",
-	     BN(j), i, SCpnt->pid);
-
-      if (SCpnt == NULL)
+      if (!(SCpnt = HD(j)->cp[i].SCpnt))
 	 panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
+      if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+         HD(j)->cp_stat[i] = ABORTING;
+         printk("%s: reset, mbox %d aborting, pid %ld.\n",
+                BN(j), i, SCpnt->pid);
+         }
+
+      else {
+         HD(j)->cp_stat[i] = IN_RESET;
+         printk("%s: reset, mbox %d in reset, pid %ld.\n",
+                BN(j), i, SCpnt->pid);
+         }
+
       if (SCpnt->host_scribble == NULL)
 	 panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
@@ -1129,18 +1225,35 @@
 
    for (i = 0; i < sh[j]->can_queue; i++) {
 
-      /* Skip mailboxes already set free by interrupt */
-      if (HD(j)->cp_stat[i] != IN_RESET) continue;
+      if (HD(j)->cp_stat[i] == IN_RESET) {
+         SCpnt = HD(j)->cp[i].SCpnt;
+         SCpnt->result = DID_RESET << 16;
+         SCpnt->host_scribble = NULL;
 
-      SCpnt = HD(j)->cp[i].SCpnt;
-      SCpnt->result = DID_RESET << 16;
-      SCpnt->host_scribble = NULL;
+         /* This mailbox is still waiting for its interrupt */
+         HD(j)->cp_stat[i] = LOCKED;
 
-      /* This mailbox is still waiting for its interrupt */
-      HD(j)->cp_stat[i] = LOCKED;
+         printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
+	        BN(j), i, SCpnt->pid);
+         }
+
+      else if (HD(j)->cp_stat[i] == ABORTING) {
+         SCpnt = HD(j)->cp[i].SCpnt;
+         SCpnt->result = DID_RESET << 16;
+         SCpnt->host_scribble = NULL;
+
+         /* This mailbox was never queued to the adapter */
+         HD(j)->cp_stat[i] = FREE;
+
+         printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
+	        BN(j), i, SCpnt->pid);
+         }
+
+      else
+
+         /* Any other mailbox has already been set free by interrupt */
+         continue;
 
-      printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-	     BN(j), i, SCpnt->pid);
       restore_flags(flags);
       SCpnt->scsi_done(SCpnt);
       cli();
@@ -1160,6 +1273,42 @@
       }
 }
 
+static inline void process_ready_list(unsigned int i, unsigned int j) {
+   Scsi_Cmnd *SCpnt;
+   unsigned int k, n_ready = 0;
+   struct mscp *cpp;
+
+   for (k = 0; k < sh[j]->can_queue; k++) {
+
+      if (HD(j)->cp_stat[k] != READY) continue;
+
+      cpp = &HD(j)->cp[k];
+
+      if (cpp->link_id != i) continue;
+
+      SCpnt = cpp->SCpnt;
+      n_ready++;
+
+      if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
+         printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d, link_id %d, "\
+                "n_ready %d, adapter busy, will abort.\n", BN(j),
+                SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+                k, i, n_ready);
+         HD(j)->cp_stat[k] = ABORTING;
+         continue;
+         }
+
+      HD(j)->cp_stat[k] = IN_USE;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+      printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d in use, link_id %d,"
+             " n_ready %d.\n", BN(j), SCpnt->channel, SCpnt->target, 
+             SCpnt->lun, SCpnt->pid, k, i, n_ready);
+#endif
+      }
+
+}
+
 static void eata2x_interrupt_handler(int irq, void *dev_id,
                                      struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
@@ -1207,6 +1356,8 @@
    
 	    spp->eoc = FALSE;
    
+            if (linked_commands) process_ready_list(i, j);
+
 	    if (HD(j)->cp_stat[i] == IGNORE) {
 	       HD(j)->cp_stat[i] = FREE;
 	       continue;
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v2.1.20/linux/drivers/scsi/eata.h	Thu Dec 12 19:37:07 1996
+++ linux/drivers/scsi/eata.h	Tue Jan 14 12:48:50 1997
@@ -12,7 +12,7 @@
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "2.40.00"
+#define EATA_VERSION "2.50.00"
 
 
 #define EATA {                                                 \
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.20/linux/drivers/scsi/ncr53c8xx.c	Thu Jan  2 15:55:21 1997
+++ linux/drivers/scsi/ncr53c8xx.c	Tue Jan 14 08:21:41 1997
@@ -40,7 +40,7 @@
 */
 
 /*
-**	26 December 1996, version 1.16b
+**	12 January 1997, version 1.16e
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -368,15 +368,17 @@
 /*
 **	Transfer direction
 **
-**	The middle scsi driver of Linux does not provide the transfer
-**	direction in the command structure.
-**	FreeBsd ncr driver requires this information.
-**
-**	I spent some hours to read the scsi2 documentation to see if
-**	it was possible to deduce the direction of transfer from the opcode
-**	of the command. It seems that it's OK.
-**	guess_xfer_direction() seems to work. If it's wrong we will
-**	get a phase mismatch on some opcode.
+**	Low-level scsi drivers under Linux do not receive the expected 
+**	data transfer direction from upper scsi drivers.
+**	The driver will only check actual data direction for common 
+**	scsi opcodes. Other ones may cause problem, since they may 
+**	depend on device type or be vendor specific.
+**	I would prefer to never trust the device for data direction, 
+**	but that is not possible.
+**
+**	The original driver requires the expected direction to be known.
+**	The Linux version of the driver has been enhanced in order to 
+**	be able to transfer data in the direction choosen by the target. 
 */
 
 #define XferNone	0
@@ -440,6 +442,7 @@
 	unsigned default_tags;
 	unsigned default_sync;
 	unsigned debug;
+	unsigned burst_max;
 } driver_setup = SCSI_NCR_DRIVER_SETUP;
 
 /*
@@ -656,7 +659,8 @@
 #define	SIR_REJECT_SENT		(10)
 #define	SIR_IGN_RESIDUE		(11)
 #define	SIR_MISSING_SAVE	(12)
-#define	SIR_MAX			(12)
+#define	SIR_DATA_IO_IS_OUT	(13)
+#define	SIR_MAX			(13)
 
 /*==========================================================
 **
@@ -1254,6 +1258,14 @@
 	*/
 
 	u_char			tag;
+
+	/*
+	**	Number of segments of the scatter list.
+	**	Used for recalculation of savep/goalp/lastp on 
+	**	SIR_DATA_IO_IS_OUT interrupt.
+	*/
+	
+	u_char			segments;
 };
 
 #define CCB_PHYS(cp,lbl)	(cp->p_ccb + offsetof(struct ccb, lbl))
@@ -1297,6 +1309,7 @@
 	u_char	sv_dcntl;
 	u_char	sv_ctest3;
 	u_char	sv_ctest4;
+	u_char	sv_ctest5;
 
 	u_char	rv_dmode;
 	u_char	rv_dcntl;
@@ -1544,6 +1557,7 @@
 	ncrcmd	resel_tmp	[  5];
 	ncrcmd  resel_lun	[ 18];
 	ncrcmd	resel_tag	[ 24];
+	ncrcmd  data_io		[  2];	/* MUST be just before data_in */
 	ncrcmd  data_in		[MAX_SCATTER * 4 + 7];
 	ncrcmd  data_out	[MAX_SCATTER * 4 + 7];
 	ncrcmd	aborttag	[  4];
@@ -3088,6 +3102,17 @@
 	SCR_RETURN,
 		0,
 
+}/*-------------------------< DATA_IO >--------------------*/,{
+/*
+**	Because Linux does not provide xfer data direction 
+**	to low-level scsi drivers, we must trust the target 
+**	for actual data direction when we cannot guess it.
+**	The programmed interrupt patches savep, lastp, goalp,
+**	etc.., and restarts the scsi script at data_out.
+*/
+	SCR_INT ^ IFTRUE (WHEN (SCR_DATA_OUT)),
+		SIR_DATA_IO_IS_OUT,
+
 }/*-------------------------< DATA_IN >--------------------*/,{
 /*
 **	Because the size depends on the
@@ -4149,8 +4174,14 @@
 	**----------------------------------------------------
 	*/
 
+	cp->segments = segments;
+
 	switch (xfer_direction) {
 	default:
+	case XferBoth:
+	     cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_io);
+	     cp->phys.header.goalp = cp->phys.header.savep +8 +20 +segments*16;
+	     break;
 	case XferIn:
 	     cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_in);
 	     cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16;
@@ -4470,6 +4501,7 @@
 	OUTB(nc_dcntl,	np->sv_dcntl);
 	OUTB(nc_ctest3,	np->sv_ctest3);
 	OUTB(nc_ctest4,	np->sv_ctest4);
+	OUTB(nc_ctest5,	np->sv_ctest5);
 
 	if (np->uf_doubler) {
 		OUTB(nc_stest1, DBLEN);		/* Enable clock doubler	*/
@@ -4883,6 +4915,46 @@
 	};
 }
 
+/*===============================================================
+**
+**	NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128 
+**	transfers. 32,64,128 are only supported by 875 chips.
+**	We use log base 2 (burst length) as internal code, with 
+**	value 0 meaning "burst disabled".
+**
+**===============================================================
+*/
+
+/*
+ *	Burst length from burst code.
+ */
+#define burst_length(bc) (!(bc))? 0 : 1 << (bc)
+
+/*
+ *	Burst code from io register bits.
+ */
+#define burst_code(dmode, ctest4, ctest5) \
+	(ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1
+
+/*
+ *	Set initial io register bits from burst code.
+ */
+static void ncr_init_burst(ncb_p np, u_char bc)
+{
+	np->rv_ctest4	&= ~0x80;
+	np->rv_dmode	&= ~(0x3 << 6);
+	np->rv_ctest5	&= ~0x4;
+
+	if (!bc) {
+		np->rv_ctest4	|= 0x80;
+	}
+	else {
+		--bc;
+		np->rv_dmode	|= ((bc & 0x3) << 6);
+		np->rv_ctest5	|= (bc & 0x4);
+	}
+}
+
 /*==========================================================
 **
 **
@@ -4897,6 +4969,7 @@
 	int	i;
 	u_long	usrsync;
 	u_char	usrwide;
+	u_char	burst_max;
 
 	/*
 	**	Reset chip.
@@ -4938,40 +5011,48 @@
 	np->rv_dcntl	= np->sv_dcntl;
 	np->rv_ctest3	= np->sv_ctest3;
 	np->rv_ctest4	= np->sv_ctest4;
+	np->rv_ctest5	= np->sv_ctest5;
+	burst_max	= burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
 #else
 	np->rv_dmode	= 0;
 	np->rv_dcntl	= 0;
 	np->rv_ctest3	= 0;
 	np->rv_ctest4	= 0;
+	burst_max	= driver_setup.burst_max;
+	if (burst_max == 255)
+		burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
+	if (burst_max > 7)
+		burst_max = 7;
 
 /**	NCR53C810			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C810 && ChipVersion == 0) {
-		np->rv_dmode	= 0x80;	/* burst length 8 */
+		burst_max	= burst_max < 4 ? burst_max : 4;
 	}
 	else
 /**	NCR53C815			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) {
-		np->rv_dmode	= 0x80;	/* burst length 8 */
+		burst_max	= burst_max < 4 ? burst_max : 4;
 	}
 	else
 /**	NCR53C825			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion == 0) {
-		np->rv_dmode	= 0x8a;	/* burst length 8, burst opcode fetch */
+		burst_max	= burst_max < 4 ? burst_max : 4;
+		np->rv_dmode	= 0x0a;	/* burst opcode fetch */
 	}
 	else
 /**	NCR53C810A or NCR53C860		**/
 	if ((ChipDevice == PCI_DEVICE_ID_NCR_53C810 && ChipVersion >= 0x10) ||
 	    ChipDevice == PCI_DEVICE_ID_NCR_53C860) {
 		if (!driver_setup.special_features)
-			np->rv_dmode	= 0xc0;	/* burst length 16 */
+			burst_max	= burst_max < 4 ? burst_max : 4;
 		else {
-			np->rv_dmode	= 0xc0 | BOF | ERMP | ERL;
+			burst_max	= burst_max < 4 ? burst_max : 4;
+			np->rv_dmode	= BOF | ERMP | ERL;
 						/* burst op-code fetch, read multiple */
-						/* read line, burst 16 */
+						/* read line */
 			np->rv_dcntl	= PFEN | CLSE;
 						/* prefetch, cache line size */
 			np->rv_ctest3	= WRIE;	/* write and invalidate */
-			np->rv_ctest4	= 0x0;	/* burst not disabled */
 		}
 	}
 	else
@@ -4979,30 +5060,43 @@
 	if ((ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion >= 0x10) ||
 	    ChipDevice == PCI_DEVICE_ID_NCR_53C875) {
 		if (!driver_setup.special_features)
-			np->rv_dmode	= 0xc0;	/* burst length 16 */
+			burst_max	= burst_max < 4 ? burst_max : 4;
 		else {
-			np->rv_dmode	= 0xc0 | BOF | ERMP | ERL;
+			burst_max	= burst_max < 7 ? burst_max : 7;
+			np->rv_dmode	= BOF | ERMP | ERL;
 						/* burst op-code fetch, read multiple */
 						/* read line, burst 128 (ctest5&4) */
 			np->rv_dcntl	= PFEN | CLSE;
 						/* prefetch, cache line size */
 			np->rv_ctest3	= WRIE;	/* write and invalidate */
-			np->rv_ctest4	= 0x0;	/* burst not disabled */
-			np->rv_ctest5	= 0x24;	/* burst 128	(0x04) */
-						/* dma fifo 536	(0x20) */
+			np->rv_ctest5	= 0x20;	/* dma fifo 536 (0x20) */
 		}
 	}
 /**	OTHERS				**/
 	else {
-		np->rv_dmode	= 0xc0;	/* burst length 16 */
+		burst_max	= burst_max < 4 ? burst_max : 4;
 	}
 #endif /* SCSI_NCR_TRUST_BIOS_SETTING */
 
+	/*
+	 *	Prepare initial io register bits for burst length
+	 */
+	ncr_init_burst(np, burst_max);
+
+	if (bootverbose > 1) {
+		printf ("%s: initial value of dmode/ctest4/ctest5 = 0x%02x/0x%02x/0x%02x\n",
+			ncr_name(np), np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
+	}
+	if (bootverbose) {
+		printf ("%s: final value of dmode/ctest4/ctest5 = 0x%02x/0x%02x/0x%02x\n",
+			ncr_name(np), np->rv_dmode, np->rv_ctest4, np->rv_ctest5);
+	}
+
 #if 0
-	printf("%s: bios: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x\n",
-		ncr_name(np), np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4);
-	printf("%s: used: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x\n",
-		ncr_name(np), np->rv_dmode, np->rv_dcntl, np->rv_ctest3, np->rv_ctest4);
+	printf("%s: bios: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x, ctest5=0x%02x\n",
+		ncr_name(np), np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4, np->sv_ctest5);
+	printf("%s: used: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x, ctest5=0x%02x\n",
+		ncr_name(np), np->rv_dmode, np->rv_dcntl, np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
 #endif
 
 	OUTB (nc_istat,  0x00   );      /*  Remove Reset, abort ...	     */
@@ -6268,6 +6362,23 @@
 	}
 
 	switch (num) {
+	case SIR_DATA_IO_IS_OUT:
+/*
+**	We did not guess the direction of transfer. We assumed DATA IN,
+**	but the the target drove DATA OUT.
+**	We have to patch the script context with DATA OUT context and 
+**	restart processing at data out script address.
+*/
+		cp->phys.header.savep	= NCB_SCRIPT_PHYS (np, data_out);
+		cp->phys.header.goalp	= cp->phys.header.savep +20 +cp->segments*16;
+		cp->phys.header.lastp	= cp->phys.header.savep;
+		np->header.savep	= cp->phys.header.savep;
+		np->header.goalp	= cp->phys.header.goalp;
+		np->header.lastp	= cp->phys.header.lastp;
+		OUTL (nc_temp,	np->header.savep);
+		OUTL (nc_dsp,	np->header.savep);
+		return;
+		/* break; */
 
 /*--------------------------------------------------------------------
 **
@@ -6492,14 +6603,14 @@
 		/*
 		**	Check against controller limits.
 		**	--------------------------------
-		**	per <= 13  special case, allow fast 20 MHz transfer.
-		**	per <  25  fast 20
+		**	per <  25  fast20
 		**	per <  50  fast
 		**	per < 100  slow
 		**	Use a value p2 twice the controller limit in order to 
 		**	not do wrong integer calculation for 80 MHz clock.
 		**	(12.5x2 = 25ns).
-		**	Compute scntl3&0xf0 sync clock divisor for 50 ns period.
+		**	Compute scntl3&0xf0 sync clock divisor for 50 ns period 
+		**	from the async pre-scaler.
 		**	Ajust it according to actual controller sync period.
 		**	- 0x40 divides it by 4  -> 50/4 = 12.5ns
 		**	- 0x20 divides it by 2  -> 50/2 = 25 ns
@@ -6513,25 +6624,19 @@
 			p2	= 100;
 			scntl3	= (np->rv_scntl3 & 0x07) << 4;
 
-			if (per <= 13) {
-				fak	= 0;
+			if (per < 25) {
+				p2	= 25;
 				scntl3	= (scntl3 - 0x40) | 0x80;
 			}
-			else {
-				if (per < 25) {
-					p2	= 25;
-					scntl3	= (scntl3 - 0x40) | 0x80;
-				}
-				else if (per < 50) {
-					p2	= 50;
-					scntl3	= scntl3 - 0x20;
-				}
+			else if (per < 50) {
+				p2	= 50;
+				scntl3	= scntl3 - 0x20;
+			}
 
-				fak = (8 * per - 1) / p2 - 3;
-				if (fak > 7) {
-					chg = 1;
-					ofs = 0;
-				}
+			fak = (8 * per - 1) / p2 - 3;
+			if (fak > 7) {
+				chg = 1;
+				ofs = 0;
 			}
 		}
 		if (ofs == 0) {
@@ -7654,22 +7759,27 @@
 **		0x04	enable read multiple
 **		0x08	enable read line
 **		0xc0	burst length 16/8/2
-**	DCNTL   0xa0
+**	DCNTL   0xa8
+**		0x08	totem pole irq
 **		0x20	enable pre-fetch
 **		0x80	enable cache line size
 **	CTEST3  0x01
 **		0x01	set write and invalidate
 **	CTEST4  0x80
 **		0x80	burst disabled
+**	CTEST5  0x24
+**		0x20	dma fifo 536		(875 only)
+**		0x04	burst len 32/64/128	(875 only)
 */
 
 static void ncr_save_bios_setting(ncb_p np)
 {
 	np->sv_scntl3	= INB(nc_scntl3) & 0x07;
 	np->sv_dmode	= INB(nc_dmode)  & 0xce;
-	np->sv_dcntl	= INB(nc_dcntl)  & 0xa0;
+	np->sv_dcntl	= INB(nc_dcntl)  & 0xa8;
 	np->sv_ctest3	= INB(nc_ctest3) & 0x01;
 	np->sv_ctest4	= INB(nc_ctest4) & 0x80;
+	np->sv_ctest5	= INB(nc_ctest5) & 0x24;
 }
 
 /*===================== LINUX ENTRY POINTS SECTION ==========================*/
@@ -7750,6 +7860,8 @@
 			driver_setup.verbose	= val;
 		else if	(!strncmp(cur, "debug:", 6))
 			driver_setup.debug	= val;
+		else if	(!strncmp(cur, "burst:", 6))
+			driver_setup.burst_max	= val;
 
 		if ((cur = strchr(cur, ',')) != NULL)
 			++cur;
@@ -7804,12 +7916,13 @@
 
 #define YesNo(y)	y ? 'y' : 'n'
     if (bootverbose >= 2) {
-         printk("ncr53c8xx: setup=disc:%c,specf:%c,ultra:%c,tags:%d,sync:%d\n",
+         printk("ncr53c8xx: setup=disc:%c,specf:%c,ultra:%c,tags:%d,sync:%d,burst:%d\n",
 			 YesNo(driver_setup.disconnection),
 			 YesNo(driver_setup.special_features),
 			 YesNo(driver_setup.ultra_scsi),
 			 driver_setup.default_tags,
-			 driver_setup.default_sync/1000);
+			 driver_setup.default_sync/1000,
+			 driver_setup.burst_max);
          printk("ncr53c8xx: setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x\n",
 			 YesNo(driver_setup.master_parity),
 			 YesNo(driver_setup.scsi_parity),
@@ -8173,13 +8286,7 @@
 #undef next_wcmd
 
 /*
-**	In order to patch the SCSI script for SAVE/RESTORE DATA POINTER,
-**	we need the direction of transfer.
-**	Linux middle-level scsi driver does not provide this information.
-**	So we have to guess it.
-**	My documentation about SCSI-II standard is old. Probably some opcode
-**	are missing.
-**	If I do'nt know the command code, I assume input transfer direction.
+**	Returns data transfer direction for common op-codes.
 */
 
 static int guess_xfer_direction(int opcode)
@@ -8187,111 +8294,31 @@
 	int d;
 
 	switch(opcode) {
-	case 0x00:  /*	TEST UNIT READY			00 */
-	case 0x08:  /*	READ(6)				08 */
 	case 0x12:  /*	INQUIRY				12 */
 	case 0x4D:  /*	LOG SENSE			4D */
 	case 0x5A:  /*	MODE SENSE(10)			5A */
 	case 0x1A:  /*	MODE SENSE(6)			1A */
-	case 0x28:  /*	READ(10)			28 */
-	case 0xA8:  /*	READ(12)			A8 */
 	case 0x3C:  /*	READ BUFFER			3C */
 	case 0x1C:  /*	RECEIVE DIAGNOSTIC RESULTS	1C */
-	case 0xB7:  /*	READ DEFECT DATA(12)		B7 */
-	case 0xB8:  /*	READ ELEMENT STATUS		B8 */
-	            /*	GET WINDOW			25 */
-	case 0x25:  /*	READ CAPACITY			25 */
-	case 0x29:  /*	READ GENERATION			29 */
-	case 0x3E:  /*	READ LONG			3E */
-	            /*	GET DATA BUFFER STATUS		34 */
-	            /*	PRE-FETCH			34 */
-	case 0x34:  /*	READ POSITION			34 */
 	case 0x03:  /*	REQUEST SENSE			03 */
-	case 0x05:  /*	READ BLOCK LIMITS		05 */
-	case 0x0F:  /*	READ REVERSE			0F */
-	case 0x14:  /*	RECOVER BUFFERED DATA		14 */
-	case 0x2D:  /*	READ UPDATED BLOCK		2D */
-	case 0x37:  /*	READ DEFECT DATA(10)		37 */
-	case 0x42:  /*	READ SUB-CHANNEL		42 */
-	case 0x43:  /*	READ TOC			43 */
-	case 0x44:  /*	READ HEADER			44 */
-	case 0xC7:  /*  ???                  ???        C7 */
 		d = XferIn;
 		break;
 	case 0x39:  /*	COMPARE				39 */
 	case 0x3A:  /*	COPY AND VERIFY			3A */
-	            /*	PRINT				0A */
-	            /*	SEND MESSAGE(6)			0A */
-	case 0x0A:  /*	WRITE(6)			0A */
 	case 0x18:  /*	COPY				18 */
 	case 0x4C:  /*	LOG SELECT			4C */
 	case 0x55:  /*	MODE SELECT(10)			55 */
 	case 0x3B:  /*	WRITE BUFFER			3B */
 	case 0x1D:  /*	SEND DIAGNOSTIC			1D */
 	case 0x40:  /*	CHANGE DEFINITION		40 */
-	            /*	SEND MESSAGE(12)		AA */
-	case 0xAA:  /*	WRITE(12)			AA */
-	case 0xB6:  /*	SEND VOLUME TAG			B6 */
-	case 0x3F:  /*	WRITE LONG			3F */
-	case 0x04:  /*	FORMAT UNIT			04 */
-		    /*	INITIALIZE ELEMENT STATUS	07 */
-	case 0x07:  /*	REASSIGN BLOCKS			07 */
 	case 0x15:  /*	MODE SELECT(6)			15 */
-	case 0x24:  /*	SET WINDOW			24 */
-	case 0x2A:  /*	WRITE(10)			2A */
-	case 0x2E:  /*	WRITE AND VERIFY(10)		2E */
-	case 0xAE:  /*	WRITE AND VERIFY(12)		AE */
-	case 0xB0:  /*	SEARCH DATA HIGH(12)		B0 */
-	case 0xB1:  /*	SEARCH DATA EQUAL(12)		B1 */
-	case 0xB2:  /*	SEARCH DATA LOW(12)		B2 */
-	            /*	OBJECT POSITION			31 */
-	case 0x30:  /*	SEARCH DATA HIGH(10)		30 */
-	case 0x31:  /*	SEARCH DATA EQUAL(10)		31 */
-	case 0x32:  /*	SEARCH DATA LOW(10)		32 */
-	case 0x38:  /*	MEDIUM SCAN			38 */
-	case 0x3D:  /*	UPDATE BLOCK			3D */
-	case 0x41:  /*	WRITE SAME			41 */
-	            /*	LOAD UNLOAD			1B */
-	            /*	SCAN				1B */
-	case 0x1B:  /*	START STOP UNIT			1B */
 		d = XferOut;
 		break;
-	case 0x01:  /*	REZERO UNIT			01 */
-	            /*	SEEK(6)				0B */
-	case 0x0B:  /*	SLEW AND PRINT			0B */
-	            /*	SYNCHRONIZE BUFFER		10 */
-	case 0x10:  /*	WRITE FILEMARKS			10 */
-	case 0x11:  /*	SPACE				11 */
-	case 0x13:  /*	VERIFY				13 */
-	case 0x16:  /*	RESERVE UNIT			16 */
-	case 0x17:  /*	RELEASE UNIT			17 */
-	case 0x19:  /*	ERASE				19 */
-	            /*	LOCATE				2B */
-	            /*	POSITION TO ELEMENT		2B */
-	case 0x2B:  /*	SEEK(10)			2B */
-	case 0x1E:  /*	PREVENT ALLOW MEDIUM REMOVAL	1E */
-	case 0x2C:  /*	ERASE(10)			2C */
-	case 0xAC:  /*	ERASE(12)			AC */
-	case 0x2F:  /*	VERIFY(10)			2F */
-	case 0xAF:  /*	VERIFY(12)			AF */
-	case 0x33:  /*	SET LIMITS(10)			33 */
-	case 0xB3:  /*	SET LIMITS(12)			B3 */
-	case 0x35:  /*	SYNCHRONIZE CACHE		35 */
-	case 0x36:  /*	LOCK UNLOCK CACHE		36 */
-	case 0x45:  /*	PLAY AUDIO(10)			45 */
-	case 0x47:  /*	PLAY AUDIO MSF			47 */
-	case 0x48:  /*	PLAY AUDIO TRACK/INDEX		48 */
-	case 0x49:  /*	PLAY TRACK RELATIVE(10)		49 */
-	case 0xA9:  /*	PLAY TRACK RELATIVE(12)		A9 */
-	case 0x4B:  /*	PAUSE/RESUME			4B */
-	            /*	MOVE MEDIUM			A5 */
-	case 0xA5:  /*	PLAY AUDIO(12)			A5 */
-	case 0xA6:  /*	EXCHANGE MEDIUM			A6 */
-	case 0xB5:  /*	REQUEST VOLUME ELEMENT ADDRESS	B5 */
+	case 0x00:  /*	TEST UNIT READY			00 */
 		d = XferNone;
 		break;
 	default:
-		d = XferIn;
+		d = XferBoth;
 		break;
 	}
 
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.1.20/linux/drivers/scsi/ncr53c8xx.h	Thu Jan  2 15:55:21 1997
+++ linux/drivers/scsi/ncr53c8xx.h	Tue Jan 14 08:21:41 1997
@@ -45,7 +45,7 @@
 /*
 **	Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 1.16b"
+#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 1.16e"
  
 /*
 **	If SCSI_NCR_SETUP_SPECIAL_FEATURES is defined,
@@ -292,7 +292,8 @@
 	1,					\
 	SCSI_NCR_SETUP_DEFAULT_TAGS,		\
 	SCSI_NCR_SETUP_DEFAULT_SYNC,		\
-	0x00					\
+	0x00,					\
+	7					\
 }
 
 
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.1.20/linux/drivers/scsi/scsi_syms.c	Mon Dec 30 15:39:11 1996
+++ linux/drivers/scsi/scsi_syms.c	Fri Jan  3 11:33:26 1997
@@ -3,8 +3,8 @@
  * a module.
  */
 #define __NO_VERSION__
-#include <linux/module.h>
 #include <linux/config.h>
+#include <linux/module.h>
 
 #ifdef CONFIG_MODULES
 
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/st_options.h linux/drivers/scsi/st_options.h
--- v2.1.20/linux/drivers/scsi/st_options.h	Sun Dec 17 10:59:24 1995
+++ linux/drivers/scsi/st_options.h	Thu Jan  2 20:27:46 1997
@@ -88,4 +88,8 @@
    files and the file number status is retained. */
 #define ST_FAST_MTEOM 0
 
+/* If ST_SYSV is non-zero, the tape behaves according to the SYS V semantics.
+   The default is BSD semantics. */
+#define ST_SYSV 0
+
 #endif
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.1.20/linux/drivers/scsi/u14-34f.c	Thu Dec 12 19:37:17 1996
+++ linux/drivers/scsi/u14-34f.c	Tue Jan 14 12:48:50 1997
@@ -1,6 +1,9 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *       8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27
+ *          Added linked command support.
+ *
  *       3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27
  *          Added queue depth adjustment.
  *
@@ -81,7 +84,7 @@
  * 
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -115,8 +118,8 @@
  *
  *  Here a sample configuration using two U14F boards:
  *
- U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, Mbox 16, UC 1.
- U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, Mbox 16, UC 1.
+ U14F0: ISA 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, MB 16, UC 1, LC 1, MQ 8.
+ U14F1: ISA 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, MB 16, UC 1, LC 1, MQ 8.
  *
  *  The boot controller must have its BIOS enabled, while other boards can
  *  have their BIOS disabled, or enabled to an higher address.
@@ -197,6 +200,7 @@
 #include <asm/irq.h>
 #include "u14-34f.h"
 #include<linux/stat.h>
+#include<linux/config.h>
 
 struct proc_dir_entry proc_scsi_u14_34f = {
     PROC_SCSI_U14_34F, 6, "u14_34f",
@@ -223,6 +227,7 @@
 #define HA_CMD_READ_BUFF  0x3
 #define HA_CMD_WRITE_BUFF 0x4
 
+#undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
@@ -251,6 +256,8 @@
 #define LOCKED   2
 #define IN_RESET 3
 #define IGNORE   4
+#define READY    5
+#define ABORTING 6
 #define NO_DMA  0xff
 #define MAXLOOP 200000
 
@@ -296,7 +303,7 @@
    unsigned int data_address PACKED;    /* transfer data pointer */
    unsigned int data_len PACKED;        /* length in bytes */
    unsigned int link_address PACKED;    /* for linking command chains */
-   unsigned char link_id;               /* identifies command in chain */
+   unsigned char clink_id;              /* identifies command in chain */
    unsigned char use_sg;                /* (if sg is set) 8 bytes per list */
    unsigned char sense_len;
    unsigned char scsi_cdbs_len;         /* 6, 10, or 12 */
@@ -306,6 +313,7 @@
    unsigned int sense_addr PACKED;
    Scsi_Cmnd *SCpnt;
    unsigned int index;                  /* cp index */
+   unsigned int link_id;                /* reference cp for linked commands */
    struct sg_list *sglist;
    };
 
@@ -365,6 +373,18 @@
 static int do_trace = FALSE;
 static int setup_done = FALSE;
 
+#if defined (CONFIG_SCSI_U14_34F_LINKED_COMMANDS)
+static int linked_commands = TRUE;
+#else
+static int linked_commands = FALSE;
+#endif
+
+#if defined CONFIG_SCSI_U14_34F_MAX_TAGS
+static int max_queue_depth = CONFIG_SCSI_U14_34F_MAX_TAGS;
+#else
+static int max_queue_depth = MAX_CMD_PER_LUN;
+#endif
+
 static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    Scsi_Device *dev;
    int j, ntag = 0, nuntag = 0, tqd, utqd; 
@@ -387,7 +407,7 @@
 
    tqd = (host->can_queue - utqd * nuntag) / (ntag + 1);
 
-   if (tqd > MAX_TAGGED_CMD_PER_LUN) tqd = MAX_TAGGED_CMD_PER_LUN;
+   if (tqd > max_queue_depth) tqd = max_queue_depth;
 
    if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN;
 
@@ -467,7 +487,7 @@
                               Scsi_Host_Template *tpnt) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char in_byte;
-   char dma_name[16];
+   char *bus_type, dma_name[16];
 
    /* Allowed BIOS base addresses (NULL indicates reserved) */
    void *bios_segment_table[8] = { 
@@ -595,6 +615,7 @@
       sh[j]->dma_channel = NO_DMA;
       sh[j]->unchecked_isa_dma = FALSE;
       sprintf(BN(j), "U34F%d", j);
+      bus_type = "VESA";
       }
    else {
       sh[j]->wish_block = TRUE;
@@ -611,6 +632,7 @@
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
+      bus_type = "ISA";
       }
 
    sh[j]->max_channel = MAX_CHANNEL - 1;
@@ -641,10 +663,15 @@
          return FALSE;
          }
       
-   printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, "\
-	  "Mbox %d, UC %d.\n", BN(j), sh[j]->io_port,
-          (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
-          sh[j]->can_queue, sh[j]->hostt->use_clustering);
+   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) 
+       max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
+
+   if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
+
+   printk("%s: %s 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, UC %d, "\
+          "LC %d, MQ %d.\n", BN(j), bus_type, sh[j]->io_port, (int)sh[j]->base,
+          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
+          sh[j]->hostt->use_clustering, linked_commands, max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -691,7 +718,7 @@
       if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
 
    if (j > 0) 
-      printk("UltraStor 14F/34F: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-1997 Dario Ballabio.\n");
 
    restore_flags(flags);
    return j;
@@ -803,6 +830,28 @@
    cpp->scsi_cdbs_len = SCpnt->cmd_len;
    memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len);
 
+   if (linked_commands && SCpnt->device->tagged_supported
+            && !HD(j)->target_to[SCpnt->target][SCpnt->channel]
+	    && !HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+   
+      for (k = 0; k < sh[j]->can_queue; k++) {
+ 
+         if (HD(j)->cp_stat[k] != IN_USE) continue;
+
+         if ((&HD(j)->cp[k])->SCpnt->device != SCpnt->device) continue;
+
+         cpp->link_id = k;
+         HD(j)->cp_stat[i] = READY;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+         printk("%s: qcomm, target %d.%d:%d, pid %ld, Mbox %d ready.\n", 
+                BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+                SCpnt->pid, i);
+#endif
+         restore_flags(flags);
+         return 0;
+         }
+
    if (wait_on_busy(sh[j]->io_port)) {
       SCpnt->result = DID_ERROR << 16;
       SCpnt->host_scribble = NULL;
@@ -884,6 +933,18 @@
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
+
+   if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+      SCarg->result = DID_ABORT << 16;
+      SCarg->host_scribble = NULL;
+      HD(j)->cp_stat[i] = FREE;
+      printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
+	     BN(j), i, SCarg->pid);
+      SCarg->scsi_done(SCarg);
+      restore_flags(flags);
+      return SCSI_ABORT_SUCCESS;
+      }
+
    restore_flags(flags);
    panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
@@ -934,14 +995,21 @@
 	 continue;
 	 }
 
-      SCpnt = HD(j)->cp[i].SCpnt;
-      HD(j)->cp_stat[i] = IN_RESET;
-      printk("%s: reset, mbox %d in reset, pid %ld.\n",
-	     BN(j), i, SCpnt->pid);
-
-      if (SCpnt == NULL)
+      if (!(SCpnt = HD(j)->cp[i].SCpnt))
 	 panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
+      if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+         HD(j)->cp_stat[i] = ABORTING;
+         printk("%s: reset, mbox %d aborting, pid %ld.\n",
+                BN(j), i, SCpnt->pid);
+         }
+
+      else {
+         HD(j)->cp_stat[i] = IN_RESET;
+         printk("%s: reset, mbox %d in reset, pid %ld.\n",
+                BN(j), i, SCpnt->pid);
+         }
+
       if (SCpnt->host_scribble == NULL)
 	 panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
@@ -976,18 +1044,35 @@
 
    for (i = 0; i < sh[j]->can_queue; i++) {
 
-      /* Skip mailboxes already set free by interrupt */
-      if (HD(j)->cp_stat[i] != IN_RESET) continue;
+      if (HD(j)->cp_stat[i] == IN_RESET) {
+         SCpnt = HD(j)->cp[i].SCpnt;
+         SCpnt->result = DID_RESET << 16;
+         SCpnt->host_scribble = NULL;
 
-      SCpnt = HD(j)->cp[i].SCpnt;
-      SCpnt->result = DID_RESET << 16;
-      SCpnt->host_scribble = NULL;
+         /* This mailbox is still waiting for its interrupt */
+         HD(j)->cp_stat[i] = LOCKED;
 
-      /* This mailbox is still waiting for its interrupt */
-      HD(j)->cp_stat[i] = LOCKED;
+         printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
+	        BN(j), i, SCpnt->pid);
+         }
+
+      else if (HD(j)->cp_stat[i] == ABORTING) {
+         SCpnt = HD(j)->cp[i].SCpnt;
+         SCpnt->result = DID_RESET << 16;
+         SCpnt->host_scribble = NULL;
+
+         /* This mailbox was never queued to the adapter */
+         HD(j)->cp_stat[i] = FREE;
+
+         printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
+	        BN(j), i, SCpnt->pid);
+         }
+
+      else
+
+         /* Any other mailbox has already been set free by interrupt */
+         continue;
 
-      printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-	     BN(j), i, SCpnt->pid);
       restore_flags(flags);
       SCpnt->scsi_done(SCpnt);
       cli();
@@ -1017,11 +1102,49 @@
    return FALSE;
 }
 
+static inline void process_ready_list(unsigned int i, unsigned int j) {
+   Scsi_Cmnd *SCpnt;
+   unsigned int k, n_ready = 0;
+   struct mscp *cpp;
+
+   for (k = 0; k < sh[j]->can_queue; k++) {
+
+      if (HD(j)->cp_stat[k] != READY) continue;
+
+      cpp = &HD(j)->cp[k];
+
+      if (cpp->link_id != i) continue;
+
+      SCpnt = cpp->SCpnt;
+      n_ready++;
+
+      if (wait_on_busy(sh[j]->io_port)) {
+         printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d, link_id %d, "\
+                "n_ready %d, adapter busy, will abort.\n", BN(j),
+                SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+                k, i, n_ready);
+         HD(j)->cp_stat[k] = ABORTING;
+         continue;
+         }
+
+      outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+      outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
+      HD(j)->cp_stat[k] = IN_USE;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+      printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d in use, link_id %d,"
+             " n_ready %d.\n", BN(j), SCpnt->channel, SCpnt->target, 
+             SCpnt->lun, SCpnt->pid, k, i, n_ready);
+#endif
+      }
+
+}
+
 static void u14_34f_interrupt_handler(int irq, void *dev_id,
                                       struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
    unsigned long flags;
-   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0;
+   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, ret;
    struct mscp *spp;
 
    save_flags(flags);
@@ -1051,15 +1174,19 @@
 	 if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
 			      BN(j), HD(j)->iocount);
 
-	 spp = (struct mscp *)DEV2V(inl(sh[j]->io_port + REG_ICM));
+	 spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
 
 	 /* Clear interrupt pending flag */
 	 outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
 	 i = spp - HD(j)->cp;
 
-	 if (i >= sh[j]->can_queue)
-	    panic("%s: ihdlr, invalid mscp address.\n", BN(j));
+	 if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+                                            || i >= sh[j]->can_queue)
+	    panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n",
+                  BN(j), (void *)ret, HD(j)->cp);
+
+         if (linked_commands) process_ready_list(i, j);
 
 	 if (HD(j)->cp_stat[i] == IGNORE) {
 	    HD(j)->cp_stat[i] = FREE;
diff -u --recursive --new-file v2.1.20/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v2.1.20/linux/drivers/scsi/u14-34f.h	Thu Dec 12 19:37:17 1996
+++ linux/drivers/scsi/u14-34f.h	Tue Jan 14 12:48:50 1997
@@ -11,7 +11,7 @@
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "2.40.00"
+#define U14_34F_VERSION "2.50.00"
 
 #define ULTRASTOR_14_34F {                                            \
 		NULL, /* Ptr for modules */                           \
diff -u --recursive --new-file v2.1.20/linux/fs/Config.in linux/fs/Config.in
--- v2.1.20/linux/fs/Config.in	Thu Dec 12 17:02:45 1996
+++ linux/fs/Config.in	Tue Jan 14 12:59:10 1997
@@ -6,9 +6,7 @@
 
 bool	 'Quota support' CONFIG_QUOTA
 tristate 'Minix fs support' CONFIG_MINIX_FS
-tristate 'Extended fs support' CONFIG_EXT_FS
 tristate 'Second extended fs support' CONFIG_EXT2_FS
-tristate 'xiafs filesystem support' CONFIG_XIA_FS
 
 # msdos filesystems
 tristate 'DOS FAT fs support' CONFIG_FAT_FS
@@ -38,6 +36,7 @@
 tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
 tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS
+tristate 'ROM filesystem support' CONFIG_ROMFS_FS
 if [ "$CONFIG_AFFS_FS" != "n" ]; then
   define_bool CONFIG_AMIGA_PARTITION y
 fi
@@ -47,3 +46,4 @@
   bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
 fi
 endmenu
+
diff -u --recursive --new-file v2.1.20/linux/fs/Makefile linux/fs/Makefile
--- v2.1.20/linux/fs/Makefile	Sun Dec 22 16:37:38 1996
+++ linux/fs/Makefile	Tue Jan 14 13:00:18 1997
@@ -16,8 +16,8 @@
 		dcache.o $(BINFMTS) 
 
 MOD_LIST_NAME := FS_MODULES
-ALL_SUB_DIRS = minix ext ext2 fat msdos vfat proc isofs nfs xiafs umsdos \
-		hpfs sysv smbfs ncpfs ufs affs
+ALL_SUB_DIRS = minix ext2 fat msdos vfat proc isofs nfs umsdos \
+		hpfs sysv smbfs ncpfs ufs affs romfs
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
@@ -33,14 +33,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_EXT_FS),y)
-SUB_DIRS += ext
-else
-  ifeq ($(CONFIG_EXT_FS),m)
-  MOD_SUB_DIRS += ext
-  endif
-endif
-
 ifeq ($(CONFIG_EXT2_FS),y)
 SUB_DIRS += ext2
 else
@@ -97,14 +89,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_XIA_FS),y)
-SUB_DIRS += xiafs
-else
-  ifeq ($(CONFIG_XIA_FS),m)
-  MOD_SUB_DIRS += xiafs
-  endif
-endif
-
 ifeq ($(CONFIG_UMSDOS_FS),y)
 SUB_DIRS += umsdos
 else
@@ -158,6 +142,14 @@
 else
   ifeq ($(CONFIG_AFFS_FS),m)
   MOD_SUB_DIRS += affs
+  endif
+endif
+
+ifeq ($(CONFIG_ROMFS_FS),y)
+SUB_DIRS += romfs
+else
+  ifeq ($(CONFIG_ROMFS_FS),m)
+  MOD_SUB_DIRS += romfs
   endif
 endif
 
diff -u --recursive --new-file v2.1.20/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.20/linux/fs/binfmt_elf.c	Mon Dec 30 15:39:13 1996
+++ linux/fs/binfmt_elf.c	Thu Jan  2 20:29:00 1997
@@ -1238,9 +1238,9 @@
 		unsigned long addr = vma->vm_start;
 		unsigned long len = vma->vm_end - vma->vm_start;
 		
+		i++;
 		if (!maydump(vma))
 			continue;
-		i++;
 #ifdef DEBUG
 		printk("elf_core_dump: writing %08lx %lx\n", addr, len);
 #endif
diff -u --recursive --new-file v2.1.20/linux/fs/devices.c linux/fs/devices.c
--- v2.1.20/linux/fs/devices.c	Mon May 13 07:36:19 1996
+++ linux/fs/devices.c	Tue Jan 14 12:59:10 1997
@@ -13,7 +13,6 @@
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/sched.h>
-#include <linux/ext_fs.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.20/linux/fs/ext/Makefile linux/fs/ext/Makefile
--- v2.1.20/linux/fs/ext/Makefile	Tue Aug 15 15:07:02 1995
+++ linux/fs/ext/Makefile	Thu Jan  1 02:00:00 1970
@@ -1,15 +0,0 @@
-#
-# Makefile for the linux ext-filesystem routines.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-O_TARGET := ext.o
-O_OBJS   := freelists.o truncate.o namei.o inode.o file.o dir.o \
-		symlink.o fsync.o
-M_OBJS   := $(O_TARGET)
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.20/linux/fs/ext/dir.c linux/fs/ext/dir.c
--- v2.1.20/linux/fs/ext/dir.c	Tue Oct 29 19:58:20 1996
+++ linux/fs/ext/dir.c	Thu Jan  1 02:00:00 1970
@@ -1,122 +0,0 @@
-/*
- *  linux/fs/ext/dir.c
- *
- *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/dir.c
- *
- *  Copyright (C) 1991, 1992 Linus Torvalds
- *
- *  ext directory handling functions
- */
-
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-
-static long ext_dir_read(struct inode * inode, struct file * filp,
-	char * buf, unsigned long count)
-{
-	return -EISDIR;
-}
-
-static int ext_readdir(struct inode *, struct file *, void *, filldir_t);
-
-static struct file_operations ext_dir_operations = {
-	NULL,			/* lseek - default */
-	ext_dir_read,		/* read */
-	NULL,			/* write - bad */
-	ext_readdir,		/* readdir */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* no special release code */
-	file_fsync		/* fsync */
-};
-
-/*
- * directories can handle most operations...
- */
-struct inode_operations ext_dir_inode_operations = {
-	&ext_dir_operations,	/* default directory file-ops */
-	ext_create,		/* create */
-	ext_lookup,		/* lookup */
-	ext_link,		/* link */
-	ext_unlink,		/* unlink */
-	ext_symlink,		/* symlink */
-	ext_mkdir,		/* mkdir */
-	ext_rmdir,		/* rmdir */
-	ext_mknod,		/* mknod */
-	ext_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	ext_truncate,		/* truncate */
-	NULL			/* permission */
-};
-
-static int ext_readdir(struct inode * inode, struct file * filp,
-	void * dirent, filldir_t filldir)
-{
-	int error;
-	unsigned int i;
-	off_t offset;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de;
-
-	if (!inode || !S_ISDIR(inode->i_mode))
-		return -EBADF;
-	if ((filp->f_pos & 7) != 0)
-		return -EBADF;
-	error = 0;
-	while (!error && filp->f_pos < inode->i_size) {
-		offset = filp->f_pos & 1023;
-		bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
-		if (!bh) {
-			filp->f_pos += 1024-offset;
-			continue;
-		}
-		for (i = 0; i < 1024 && i < offset; ) {
-			de = (struct ext_dir_entry *) (bh->b_data + i);
-			if (!de->rec_len)
-				break;
-			i += de->rec_len;
-		}
-		offset = i;
-		de = (struct ext_dir_entry *) (offset + bh->b_data);
-		while (offset < 1024 && filp->f_pos < inode->i_size) {
-			if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
-			    de->rec_len < de->name_len + 8 ||
-			    (de->rec_len + (off_t) filp->f_pos - 1) / 1024 > ((off_t) filp->f_pos / 1024)) {
-				printk ("ext_readdir: bad dir entry, skipping\n");
-				printk ("dev=%s, dir=%ld, "
-				    "offset=%ld, rec_len=%d, name_len=%d\n",
-				    kdevname(inode->i_dev), inode->i_ino,
-				    offset, de->rec_len, de->name_len);
-				filp->f_pos += 1024-offset;
-				if (filp->f_pos > inode->i_size)
-					filp->f_pos = inode->i_size;
-				continue;
-			}
-			if (de->inode) {
-				error = filldir(dirent, de->name, de->name_len, filp->f_pos, de->inode);
-				if (error)
-					break;
-			}
-			offset += de->rec_len;
-			filp->f_pos += de->rec_len;
-			((char *) de) += de->rec_len;
-		}
-		brelse(bh);
-	}
-	return 0;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/ext/file.c linux/fs/ext/file.c
--- v2.1.20/linux/fs/ext/file.c	Tue Oct 29 19:58:20 1996
+++ linux/fs/ext/file.c	Thu Jan  1 02:00:00 1970
@@ -1,264 +0,0 @@
-/*
- *  linux/fs/ext/file.c
- *
- *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/file.c
- *
- *  Copyright (C) 1991, 1992 Linus Torvalds
- *
- *  ext regular file handling primitives
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/pagemap.h>
-
-#define	NBUF	32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-
-static long ext_file_read(struct inode *, struct file *, char *, unsigned long);
-static long ext_file_write(struct inode *, struct file *, const char *, unsigned long);
-
-/*
- * We have mostly NULL's here: the current defaults are ok for
- * the ext filesystem.
- */
-static struct file_operations ext_file_operations = {
-	NULL,			/* lseek - default */
-	ext_file_read,	/* read */
-	ext_file_write,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-	NULL,			/* release */
-	ext_sync_file			/* fsync */
-};
-
-struct inode_operations ext_file_inode_operations = {
-	&ext_file_operations,	/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	generic_readpage,	/* readpage */
-	NULL,			/* writepage */
-	ext_bmap,		/* bmap */
-	ext_truncate,		/* truncate */
-	NULL			/* permission */
-};
-
-static long ext_file_read(struct inode * inode, struct file * filp,
-	char * buf, unsigned long count)
-{
-	int read,left,chars;
-	int block, blocks, offset;
-	int bhrequest, uptodate;
-	struct buffer_head ** bhb, ** bhe;
-	struct buffer_head * bhreq[NBUF];
-	struct buffer_head * buflist[NBUF];
-	unsigned int size;
-
-	if (!inode) {
-		printk("ext_file_read: inode = NULL\n");
-		return -EINVAL;
-	}
-	if (!S_ISREG(inode->i_mode)) {
-		printk("ext_file_read: mode = %07o\n",inode->i_mode);
-		return -EINVAL;
-	}
-	offset = filp->f_pos;
-	size = inode->i_size;
-	if (offset > size)
-		left = 0;
-	else
-		left = size - offset;
-	if (left > count)
-		left = count;
-	if (left <= 0)
-		return 0;
-	read = 0;
-	block = offset >> BLOCK_SIZE_BITS;
-	offset &= BLOCK_SIZE-1;
-	size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
-	blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
-	bhb = bhe = buflist;
-	if (filp->f_reada) {
-	        if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
-		  blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
-		if (block + blocks > size)
-			blocks = size - block;
-	}
-
-	/* We do this in a two stage process.  We first try to request
-	   as many blocks as we can, then we wait for the first one to
-	   complete, and then we try to wrap up as many as are actually
-	   done.  This routine is rather generic, in that it can be used
-	   in a filesystem by substituting the appropriate function in
-	   for getblk.
-
-	   This routine is optimized to make maximum use of the various
-	   buffers and caches. */
-
-	do {
-		bhrequest = 0;
-		uptodate = 1;
-		while (blocks) {
-			--blocks;
-			*bhb = ext_getblk(inode, block++, 0);
-			if (*bhb && !buffer_uptodate(*bhb)) {
-				uptodate = 0;
-				bhreq[bhrequest++] = *bhb;
-			}
-
-			if (++bhb == &buflist[NBUF])
-				bhb = buflist;
-
-			/* If the block we have on hand is uptodate, go ahead
-			   and complete processing. */
-			if (uptodate)
-				break;
-			if (bhb == bhe)
-				break;
-		}
-
-		/* Now request them all */
-		if (bhrequest)
-			ll_rw_block(READ, bhrequest, bhreq);
-
-		do { /* Finish off all I/O that has actually completed */
-			if (*bhe) {
-				wait_on_buffer(*bhe);
-				if (!buffer_uptodate(*bhe)) {	/* read error? */
-				        brelse(*bhe);
-					if (++bhe == &buflist[NBUF])
-					  bhe = buflist;
-					left = 0;
-					break;
-				}
-			}
-			if (left < BLOCK_SIZE - offset)
-				chars = left;
-			else
-				chars = BLOCK_SIZE - offset;
-			filp->f_pos += chars;
-			left -= chars;
-			read += chars;
-			if (*bhe) {
-				copy_to_user(buf,offset+(*bhe)->b_data,chars);
-				brelse(*bhe);
-				buf += chars;
-			} else {
-				while (chars-->0)
-					put_user(0,buf++);
-			}
-			offset = 0;
-			if (++bhe == &buflist[NBUF])
-				bhe = buflist;
-		} while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
-	} while (left > 0);
-
-/* Release the read-ahead blocks */
-	while (bhe != bhb) {
-		brelse(*bhe);
-		if (++bhe == &buflist[NBUF])
-			bhe = buflist;
-	};
-	if (!read)
-		return -EIO;
-	filp->f_reada = 1;
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-		inode->i_dirt = 1;
-	}
-	return read;
-}
-
-static long ext_file_write(struct inode * inode, struct file * filp,
-	const char * buf, unsigned long count)
-{
-	off_t pos;
-	int written,c;
-	struct buffer_head * bh;
-	char * p;
-
-	if (!inode) {
-		printk("ext_file_write: inode = NULL\n");
-		return -EINVAL;
-	}
-	if (!S_ISREG(inode->i_mode)) {
-		printk("ext_file_write: mode = %07o\n",inode->i_mode);
-		return -EINVAL;
-	}
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
-	if (filp->f_flags & O_APPEND)
-		pos = inode->i_size;
-	else
-		pos = filp->f_pos;
-	written = 0;
-	while (written<count) {
-		bh = ext_getblk(inode,pos/BLOCK_SIZE,1);
-		if (!bh) {
-			if (!written)
-				written = -ENOSPC;
-			break;
-		}
-		c = BLOCK_SIZE - (pos % BLOCK_SIZE);
-		if (c > count-written)
-			c = count-written;
-		if (c != BLOCK_SIZE && !buffer_uptodate(bh)) {
-			ll_rw_block(READ, 1, &bh);
-			wait_on_buffer(bh);
-			if (!buffer_uptodate(bh)) {
-				brelse(bh);
-				if (!written)
-					written = -EIO;
-				break;
-			}
-		}
-		p = (pos % BLOCK_SIZE) + bh->b_data;
-		copy_from_user(p,buf,c);
-		update_vm_cache(inode, pos, p, c);
-		pos += c;
-		if (pos > inode->i_size) {
-			inode->i_size = pos;
-			inode->i_dirt = 1;
-		}
-		written += c;
-		buf += c;
-		mark_buffer_uptodate(bh, 1);
-		mark_buffer_dirty(bh, 0);
-		brelse(bh);
-	}
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	filp->f_pos = pos;
-	inode->i_dirt = 1;
-	return written;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/ext/freelists.c linux/fs/ext/freelists.c
--- v2.1.20/linux/fs/ext/freelists.c	Sun Nov 26 19:23:10 1995
+++ linux/fs/ext/freelists.c	Thu Jan  1 02:00:00 1970
@@ -1,341 +0,0 @@
-/*
- *  linux/fs/ext/freelists.c
- *
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *
- */
-
-/* freelists.c contains the code that handles the inode and block free lists */
-
-
-/*
-
-   The free blocks are managed by a linked list. The super block contains the
-   number of the first free block. This block contains 254 numbers of other
-   free blocks and the number of the next block in the list.
-
-   When an ext fs is mounted, the number of the first free block is stored
-   in s->u.ext_sb.s_firstfreeblocknumber and the block header is stored in
-   s->u.ext_sb.s_firstfreeblock. u.ext_sb.s_freeblockscount contains the count
-   of free blocks.
-
-   The free inodes are also managed by a linked list in a similar way. The
-   super block contains the number of the first free inode. This inode contains
-   14 numbers of other free inodes and the number of the next inode in the list.
-   
-   The number of the first free inode is stored in
-   s->u.ext_sb.s_firstfreeinodenumber and the header of the block containing
-   the inode is stored in s->u.ext_sb.s_firstfreeinodeblock.
-   u.ext_sb.s_freeinodescount contains the count of free inodes.
-
-*/
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-
-void ext_free_block(struct super_block * sb, int block)
-{
-	struct buffer_head * bh;
-	struct ext_free_block * efb;
-
-	if (!sb) {
-		printk("trying to free block on non-existent device\n");
-		return;
-	}
-	lock_super (sb);
-	if (block < sb->u.ext_sb.s_firstdatazone ||
-	    block >= sb->u.ext_sb.s_nzones) {
-		printk("trying to free block not in datazone\n");
-		return;
-	}
-	bh = get_hash_table(sb->s_dev, block, sb->s_blocksize);
-	if (bh)
-		mark_buffer_clean(bh);
-	brelse(bh);
-	if (sb->u.ext_sb.s_firstfreeblock)
-		efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
-	if (!sb->u.ext_sb.s_firstfreeblock || efb->count == 254) {
-#ifdef EXTFS_DEBUG
-printk("ext_free_block: block full, skipping to %d\n", block);
-#endif
-		if (sb->u.ext_sb.s_firstfreeblock)
-			brelse (sb->u.ext_sb.s_firstfreeblock);
-		if (!(sb->u.ext_sb.s_firstfreeblock = bread (sb->s_dev,
-			block, sb->s_blocksize)))
-			panic ("ext_free_block: unable to read block to free\n");
-		efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
-		efb->next = sb->u.ext_sb.s_firstfreeblocknumber;
-		efb->count = 0;
-		sb->u.ext_sb.s_firstfreeblocknumber = block;
-	} else {
-		efb->free[efb->count++] = block;
-	}
-	sb->u.ext_sb.s_freeblockscount ++;
-	sb->s_dirt = 1;
-	mark_buffer_dirty(sb->u.ext_sb.s_firstfreeblock, 1);
-	unlock_super (sb);
-	return;
-}
-
-int ext_new_block(struct super_block * sb)
-{
-	struct buffer_head * bh;
-	struct ext_free_block * efb;
-	int j;
-
-	if (!sb) {
-		printk("trying to get new block from non-existent device\n");
-		return 0;
-	}
-	if (!sb->u.ext_sb.s_firstfreeblock)
-		return 0;
-	lock_super (sb);
-	efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
-	if (efb->count) {
-		j = efb->free[--efb->count];
-		mark_buffer_dirty(sb->u.ext_sb.s_firstfreeblock, 1);
-	} else {
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: block empty, skipping to %d\n", efb->next);
-#endif
-		j = sb->u.ext_sb.s_firstfreeblocknumber;
-		sb->u.ext_sb.s_firstfreeblocknumber = efb->next;
-		brelse (sb->u.ext_sb.s_firstfreeblock);
-		if (!sb->u.ext_sb.s_firstfreeblocknumber) {
-			sb->u.ext_sb.s_firstfreeblock = NULL;
-		} else {
-			if (!(sb->u.ext_sb.s_firstfreeblock = bread (sb->s_dev,
-				sb->u.ext_sb.s_firstfreeblocknumber,
-				sb->s_blocksize)))
-				panic ("ext_new_block: unable to read next free block\n");
-		}
-	}
-	if (j < sb->u.ext_sb.s_firstdatazone || j > sb->u.ext_sb.s_nzones) {
-		printk ("ext_new_block: blk = %d\n", j);
-		printk("allocating block not in data zone\n");
-		return 0;
-	}
-	sb->u.ext_sb.s_freeblockscount --;
-	sb->s_dirt = 1;
-
-	if (!(bh=getblk(sb->s_dev, j, sb->s_blocksize))) {
-		printk("new_block: cannot get block");
-		return 0;
-	}
-	memset(bh->b_data, 0, BLOCK_SIZE);
-	mark_buffer_uptodate(bh, 1);
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: allocating block %d\n", j);
-#endif
-	unlock_super (sb);
-	return j;
-}
-
-unsigned long ext_count_free_blocks(struct super_block *sb)
-{
-#ifdef EXTFS_DEBUG
-	struct buffer_head * bh;
-	struct ext_free_block * efb;
-	unsigned long count, block;
-
-	lock_super (sb);
-	if (!sb->u.ext_sb.s_firstfreeblock)
-		count = 0;
-	else {
-		efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
-		count = efb->count + 1;
-		block = efb->next;
-		while (block) {
-			if (!(bh = bread (sb->s_dev, block, sb->s_blocksize))) {
-				printk ("ext_count_free: error while reading free blocks list\n");
-				block = 0;
-			} else {
-				efb = (struct ext_free_block *) bh->b_data;
-				count += efb->count + 1;
-				block = efb->next;
-				brelse (bh);
-			}
-		}
-	}
-printk("ext_count_free_blocks: stored = %d, computed = %d\n",
-	sb->u.ext_sb.s_freeblockscount, count);
-	unlock_super (sb);
-	return count;
-#else
-	return sb->u.ext_sb.s_freeblockscount;
-#endif
-}
-
-void ext_free_inode(struct inode * inode)
-{
-	struct buffer_head * bh;
-	struct ext_free_inode * efi;
-	struct super_block * sb;
-	unsigned long block;
-	unsigned long ino;
-	kdev_t dev;
-
-	if (!inode)
-		return;
-	if (!inode->i_dev) {
-		printk("free_inode: inode has no device\n");
-		return;
-	}
-	if (inode->i_count != 1) {
-		printk("free_inode: inode has count=%d\n",inode->i_count);
-		return;
-	}
-	if (inode->i_nlink) {
-		printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
-		return;
-	}
-	if (!inode->i_sb) {
-		printk("free_inode: inode on non-existent device\n");
-		return;
-	}
-	sb = inode->i_sb;
-	ino = inode->i_ino;
-	dev = inode->i_dev;
-	clear_inode(inode);
-	lock_super (sb);
-	if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
-		printk("free_inode: inode 0 or non-existent inode\n");
-		unlock_super (sb);
-		return;
-	}
-	if (sb->u.ext_sb.s_firstfreeinodeblock)
-		efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
-			(sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
-	if (!sb->u.ext_sb.s_firstfreeinodeblock || efi->count == 14) {
-#ifdef EXTFS_DEBUG
-printk("ext_free_inode: inode full, skipping to %d\n", ino);
-#endif
-		if (sb->u.ext_sb.s_firstfreeinodeblock)
-			brelse (sb->u.ext_sb.s_firstfreeinodeblock);
-		block = 2 + (ino - 1) / EXT_INODES_PER_BLOCK;
-		if (!(bh = bread(dev, block, sb->s_blocksize)))
-			panic("ext_free_inode: unable to read inode block\n");
-		efi = ((struct ext_free_inode *) bh->b_data) +
-			(ino - 1) % EXT_INODES_PER_BLOCK;
-		efi->next = sb->u.ext_sb.s_firstfreeinodenumber;
-		efi->count = 0;
-		sb->u.ext_sb.s_firstfreeinodenumber = ino;
-		sb->u.ext_sb.s_firstfreeinodeblock = bh;
-	} else {
-		efi->free[efi->count++] = ino;
-	}
-	sb->u.ext_sb.s_freeinodescount ++;
-	sb->s_dirt = 1;
-	mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
-	unlock_super (sb);
-}
-
-struct inode * ext_new_inode(const struct inode * dir)
-{
-	struct super_block * sb;
-	struct inode * inode;
-	struct ext_free_inode * efi;
-	unsigned long block;
-	int j;
-
-	if (!dir || !(inode=get_empty_inode()))
-		return NULL;
-	sb = dir->i_sb;
-	inode->i_sb = sb;
-	inode->i_flags = sb->s_flags;
-	if (!sb->u.ext_sb.s_firstfreeinodeblock)
-		return 0;
-	lock_super (sb);
-	efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
-		(sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
-	if (efi->count) {
-		j = efi->free[--efi->count];
-		mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
-	} else {
-#ifdef EXTFS_DEBUG
-printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
-#endif
-		j = sb->u.ext_sb.s_firstfreeinodenumber;
-		if (efi->next > sb->u.ext_sb.s_ninodes) {
-			printk ("efi->next = %ld\n", efi->next);
-			panic ("ext_new_inode: bad inode number in free list\n");
-		}
-		sb->u.ext_sb.s_firstfreeinodenumber = efi->next;
-		block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
-		brelse (sb->u.ext_sb.s_firstfreeinodeblock);
-		if (!sb->u.ext_sb.s_firstfreeinodenumber) {
-			sb->u.ext_sb.s_firstfreeinodeblock = NULL;
-		} else {
-			if (!(sb->u.ext_sb.s_firstfreeinodeblock =
-			    bread(sb->s_dev, block, sb->s_blocksize)))
-				panic ("ext_new_inode: unable to read next free inode block\n");
-		}
-	}
-	sb->u.ext_sb.s_freeinodescount --;
-	sb->s_dirt = 1;
-	inode->i_count = 1;
-	inode->i_nlink = 1;
-	inode->i_dev = sb->s_dev;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	inode->i_dirt = 1;
-	inode->i_ino = j;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	inode->i_op = NULL;
-	inode->i_blocks = inode->i_blksize = 0;
-	insert_inode_hash(inode);
-#ifdef EXTFS_DEBUG
-printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
-#endif
-	unlock_super (sb);
-	return inode;
-}
-
-unsigned long ext_count_free_inodes(struct super_block *sb)
-{
-#ifdef EXTFS_DEBUG
-	struct buffer_head * bh;
-	struct ext_free_inode * efi;
-	unsigned long count, block, ino;
-
-	lock_super (sb);
-	if (!sb->u.ext_sb.s_firstfreeinodeblock)
-		count = 0;
-	else {
-		efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
-			((sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK);
-		count = efi->count + 1;
-		ino = efi->next;
-		while (ino) {
-			if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
-				printk ("u.ext_sb.s_firstfreeinodenumber = %d, ino = %d\n", 
-					(int) sb->u.ext_sb.s_firstfreeinodenumber,ino);
-				panic ("ext_count_fre_inodes: bad inode number in free list\n");
-			}
-			block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
-			if (!(bh = bread (sb->s_dev, block, sb->s_blocksize))) {
-				printk ("ext_count_free_inodes: error while reading free inodes list\n");
-				block = 0;
-			} else {
-				efi = ((struct ext_free_inode *) bh->b_data) +
-					((ino - 1) % EXT_INODES_PER_BLOCK);
-				count += efi->count + 1;
-				ino = efi->next;
-				brelse (bh);
-			}
-		}
-	}
-printk("ext_count_free_inodes: stored = %d, computed = %d\n",
-	sb->u.ext_sb.s_freeinodescount, count);
-	unlock_super (sb);
-	return count;
-#else
-	return sb->u.ext_sb.s_freeinodescount;
-#endif
-}
diff -u --recursive --new-file v2.1.20/linux/fs/ext/fsync.c linux/fs/ext/fsync.c
--- v2.1.20/linux/fs/ext/fsync.c	Tue Oct 29 19:58:20 1996
+++ linux/fs/ext/fsync.c	Thu Jan  1 02:00:00 1970
@@ -1,185 +0,0 @@
-
-/*
- *  linux/fs/ext/fsync.c
- *
- *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
- *  from
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *  from
- *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
- * 
- *  extfs fsync primitive
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/locks.h>
-
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-
-
-#define blocksize BLOCK_SIZE
-#define addr_per_block 256
-
-static int sync_block (struct inode * inode, unsigned long * block, int wait)
-{
-	struct buffer_head * bh;
-	int tmp;
-	
-	if (!*block)
-		return 0;
-	tmp = *block;
-	bh = get_hash_table(inode->i_dev, *block, blocksize);
-	if (!bh)
-		return 0;
-	if (*block != tmp) {
-		brelse (bh);
-		return 1;
-	}
-	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
-		brelse(bh);
-		return -1;
-	}
-	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
-	{
-		brelse(bh);
-		return 0;
-	}
-	ll_rw_block(WRITE, 1, &bh);
-	bh->b_count--;
-	return 0;
-}
-
-static int sync_iblock (struct inode * inode, unsigned long * iblock, 
-			struct buffer_head **bh, int wait) 
-{
-	int rc, tmp;
-	
-	*bh = NULL;
-	tmp = *iblock;
-	if (!tmp)
-		return 0;
-	rc = sync_block (inode, iblock, wait);
-	if (rc)
-		return rc;
-	*bh = bread(inode->i_dev, tmp, blocksize);
-	if (tmp != *iblock) {
-		brelse(*bh);
-		*bh = NULL;
-		return 1;
-	}
-	if (!*bh)
-		return -1;
-	return 0;
-}
-
-
-static int sync_direct(struct inode *inode, int wait)
-{
-	int i;
-	int rc, err = 0;
-
-	for (i = 0; i < 9; i++) {
-		rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	return err;
-}
-
-static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
-{
-	int i;
-	struct buffer_head * ind_bh;
-	int rc, err = 0;
-
-	rc = sync_iblock (inode, iblock, &ind_bh, wait);
-	if (rc || !ind_bh)
-		return rc;
-	
-	for (i = 0; i < addr_per_block; i++) {
-		rc = sync_block (inode, 
-				 ((unsigned long *) ind_bh->b_data) + i,
-				 wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(ind_bh);
-	return err;
-}
-
-static int sync_dindirect(struct inode *inode, unsigned long *diblock,
-			  int wait)
-{
-	int i;
-	struct buffer_head * dind_bh;
-	int rc, err = 0;
-
-	rc = sync_iblock (inode, diblock, &dind_bh, wait);
-	if (rc || !dind_bh)
-		return rc;
-	
-	for (i = 0; i < addr_per_block; i++) {
-		rc = sync_indirect (inode,
-				    ((unsigned long *) dind_bh->b_data) + i,
-				    wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(dind_bh);
-	return err;
-}
-
-static int sync_tindirect(struct inode *inode, unsigned long *tiblock, 
-			  int wait)
-{
-	int i;
-	struct buffer_head * tind_bh;
-	int rc, err = 0;
-
-	rc = sync_iblock (inode, tiblock, &tind_bh, wait);
-	if (rc || !tind_bh)
-		return rc;
-	
-	for (i = 0; i < addr_per_block; i++) {
-		rc = sync_dindirect (inode,
-				     ((unsigned long *) tind_bh->b_data) + i,
-				     wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(tind_bh);
-	return err;
-}
-
-int ext_sync_file(struct inode * inode, struct file *file)
-{
-	int wait, err = 0;
-
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	     S_ISLNK(inode->i_mode)))
-		return -EINVAL;
-	for (wait=0; wait<=1; wait++)
-	{
-		err |= sync_direct(inode, wait);
-		err |= sync_indirect(inode, inode->u.ext_i.i_data+9, wait);
-		err |= sync_dindirect(inode, inode->u.ext_i.i_data+10, wait);
-		err |= sync_tindirect(inode, inode->u.ext_i.i_data+11, wait);
-	}
-	err |= ext_sync_inode (inode);
-	return (err < 0) ? -EIO : 0;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/ext/inode.c linux/fs/ext/inode.c
--- v2.1.20/linux/fs/ext/inode.c	Mon Dec 30 15:39:13 1996
+++ linux/fs/ext/inode.c	Thu Jan  1 02:00:00 1970
@@ -1,477 +0,0 @@
-/*
- *  linux/fs/ext/inode.c
- *
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/inode.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-void ext_put_inode(struct inode *inode)
-{
-	if (inode->i_nlink)
-		return;
-	inode->i_size = 0;
-	ext_truncate(inode);
-	ext_free_inode(inode);
-}
-
-void ext_put_super(struct super_block *sb)
-{
-
-	lock_super(sb);
-	sb->s_dev = 0;
-	if (sb->u.ext_sb.s_firstfreeinodeblock)
-		brelse (sb->u.ext_sb.s_firstfreeinodeblock);
-	if (sb->u.ext_sb.s_firstfreeblock)
-		brelse (sb->u.ext_sb.s_firstfreeblock);
-	unlock_super(sb);
-	MOD_DEC_USE_COUNT;
-	return;
-}
-
-static struct super_operations ext_sops = {
-	ext_read_inode,
-	NULL,
-	ext_write_inode,
-	ext_put_inode,
-	ext_put_super,
-	ext_write_super,
-	ext_statfs,
-	NULL
-};
-
-struct super_block *ext_read_super(struct super_block *s,void *data,
-				   int silent)
-{
-	struct buffer_head *bh;
-	struct ext_super_block *es;
-	kdev_t dev = s->s_dev;
-	int block;
-
-	MOD_INC_USE_COUNT;
-	lock_super(s);
-	set_blocksize(dev, BLOCK_SIZE);
-	if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
-		s->s_dev = 0;
-		unlock_super(s);
-		printk("EXT-fs: unable to read superblock\n");
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
-	es = (struct ext_super_block *) bh->b_data;
-	s->s_blocksize = 1024;
-	s->s_blocksize_bits = 10;
-	s->u.ext_sb.s_ninodes = es->s_ninodes;
-	s->u.ext_sb.s_nzones = es->s_nzones;
-	s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
-	s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
-	s->u.ext_sb.s_max_size = es->s_max_size;
-	s->s_magic = es->s_magic;
-	s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
-	s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
-	s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
-	s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
-	brelse(bh);
-	if (s->s_magic != EXT_SUPER_MAGIC) {
-		s->s_dev = 0;
-		unlock_super(s);
-		if (!silent)
-			printk("VFS: Can't find an extfs filesystem on dev "
-			       "%s.\n", kdevname(dev));
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
-	if (!s->u.ext_sb.s_firstfreeblocknumber)
-		s->u.ext_sb.s_firstfreeblock = NULL;
-	else
-		if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
-			s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
-			printk("ext_read_super: unable to read first free block\n");
-			s->s_dev = 0;
-			unlock_super(s);
-			MOD_DEC_USE_COUNT;
-			return NULL;
-		}
-	if (!s->u.ext_sb.s_firstfreeinodenumber)
-		s->u.ext_sb.s_firstfreeinodeblock = NULL;
-	else {
-		block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
-		if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
-			printk("ext_read_super: unable to read first free inode block\n");
-			brelse(s->u.ext_sb.s_firstfreeblock);
-			s->s_dev = 0;
-			unlock_super (s);
-			MOD_DEC_USE_COUNT;
-			return NULL;
-		}
-	}
-	unlock_super(s);
-	/* set up enough so that it can read an inode */
-	s->s_dev = dev;
-	s->s_op = &ext_sops;
-	if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {
-		s->s_dev = 0;
-		printk("EXT-fs: get root inode failed\n");
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
-	return s;
-}
-
-void ext_write_super (struct super_block *sb)
-{
-	struct buffer_head * bh;
-	struct ext_super_block * es;
-
-	if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
-		printk ("ext_write_super: bread failed\n");
-		return;
-	}
-	es = (struct ext_super_block *) bh->b_data;
-	es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
-	es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
-	es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
-	es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
-	mark_buffer_dirty(bh, 1);
-	brelse (bh);
-	sb->s_dirt = 0;
-}
-
-void ext_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
-{
-	struct statfs tmp;
-
-	tmp.f_type = EXT_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
-	tmp.f_blocks = sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size;
-	tmp.f_bfree = ext_count_free_blocks(sb);
-	tmp.f_bavail = tmp.f_bfree;
-	tmp.f_files = sb->u.ext_sb.s_ninodes;
-	tmp.f_ffree = ext_count_free_inodes(sb);
-	tmp.f_namelen = EXT_NAME_LEN;
-	copy_to_user(buf, &tmp, bufsiz);
-}
-
-#define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
-
-static inline int block_bmap(struct buffer_head * bh, int nr)
-{
-	int tmp;
-
-	if (!bh)
-		return 0;
-	tmp = ((unsigned long *) bh->b_data)[nr];
-	brelse(bh);
-	return tmp;
-}
-
-int ext_bmap(struct inode * inode,int block)
-{
-	int i;
-
-	if (block<0) {
-		printk("ext_bmap: block<0");
-		return 0;
-	}
-	if (block >= 9+256+256*256+256*256*256) {
-		printk("ext_bmap: block>big");
-		return 0;
-	}
-	if (block<9)
-		return inode_bmap(inode,block);
-	block -= 9;
-	if (block<256) {
-		i = inode_bmap(inode,9);
-		if (!i)
-			return 0;
-		return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
-	}
-	block -= 256;
-	if (block<256*256) {
-		i = inode_bmap(inode,10);
-		if (!i)
-			return 0;
-		i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8);
-		if (!i)
-			return 0;
-		return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
-	}
-	block -= 256*256;
-	i = inode_bmap(inode,11);
-	if (!i)
-		return 0;
-	i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16);
-	if (!i)
-		return 0;
-	i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255);
-	if (!i)
-		return 0;
-	return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
-}
-
-static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
-{
-	int tmp;
-	unsigned long * p;
-	struct buffer_head * result;
-
-	p = inode->u.ext_i.i_data + nr;
-repeat:
-	tmp = *p;
-	if (tmp) {
-		result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
-		if (tmp == *p)
-			return result;
-		brelse(result);
-		goto repeat;
-	}
-	if (!create)
-		return NULL;
-	tmp = ext_new_block(inode->i_sb);
-	if (!tmp)
-		return NULL;
-	result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
-	if (*p) {
-		ext_free_block(inode->i_sb,tmp);
-		brelse(result);
-		goto repeat;
-	}
-	*p = tmp;
-	inode->i_ctime = CURRENT_TIME;
-	inode->i_dirt = 1;
-	return result;
-}
-
-static struct buffer_head * block_getblk(struct inode * inode,
-	struct buffer_head * bh, int nr, int create)
-{
-	int tmp;
-	unsigned long * p;
-	struct buffer_head * result;
-
-	if (!bh)
-		return NULL;
-	if (!buffer_uptodate(bh)) {
-		ll_rw_block(READ, 1, &bh);
-		wait_on_buffer(bh);
-		if (!buffer_uptodate(bh)) {
-			brelse(bh);
-			return NULL;
-		}
-	}
-	p = nr + (unsigned long *) bh->b_data;
-repeat:
-	tmp = *p;
-	if (tmp) {
-		result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
-		if (tmp == *p) {
-			brelse(bh);
-			return result;
-		}
-		brelse(result);
-		goto repeat;
-	}
-	if (!create) {
-		brelse(bh);
-		return NULL;
-	}
-	tmp = ext_new_block(inode->i_sb);
-	if (!tmp) {
-		brelse(bh);
-		return NULL;
-	}
-	result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
-	if (*p) {
-		ext_free_block(inode->i_sb,tmp);
-		brelse(result);
-		goto repeat;
-	}
-	*p = tmp;
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
-	return result;
-}
-
-struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
-{
-	struct buffer_head * bh;
-
-	if (block<0) {
-		printk("ext_getblk: block<0\n");
-		return NULL;
-	}
-	if (block >= 9+256+256*256+256*256*256) {
-		printk("ext_getblk: block>big\n");
-		return NULL;
-	}
-	if (block<9)
-		return inode_getblk(inode,block,create);
-	block -= 9;
-	if (block<256) {
-		bh = inode_getblk(inode,9,create);
-		return block_getblk(inode,bh,block,create);
-	}
-	block -= 256;
-	if (block<256*256) {
-		bh = inode_getblk(inode,10,create);
-		bh = block_getblk(inode,bh,block>>8,create);
-		return block_getblk(inode,bh,block & 255,create);
-	}
-	block -= 256*256;
-	bh = inode_getblk(inode,11,create);
-	bh = block_getblk(inode,bh,block>>16,create);
-	bh = block_getblk(inode,bh,(block>>8) & 255,create);
-	return block_getblk(inode,bh,block & 255,create);
-}
-
-struct buffer_head * ext_bread(struct inode * inode, int block, int create)
-{
-	struct buffer_head * bh;
-
-	bh = ext_getblk(inode,block,create);
-	if (!bh || buffer_uptodate(bh))
-		return bh;
-	ll_rw_block(READ, 1, &bh);
-	wait_on_buffer(bh);
-	if (buffer_uptodate(bh))
-		return bh;
-	brelse(bh);
-	return NULL;
-}
-
-void ext_read_inode(struct inode * inode)
-{
-	struct buffer_head * bh;
-	struct ext_inode * raw_inode;
-	int block;
-
-	block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
-	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
-		panic("unable to read i-node block");
-	raw_inode = ((struct ext_inode *) bh->b_data) +
-		(inode->i_ino-1)%EXT_INODES_PER_BLOCK;
-	inode->i_mode = raw_inode->i_mode;
-	inode->i_uid = raw_inode->i_uid;
-	inode->i_gid = raw_inode->i_gid;
-	inode->i_nlink = raw_inode->i_nlinks;
-	inode->i_size = raw_inode->i_size;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
-	inode->i_blocks = inode->i_blksize = 0;
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
-	else for (block = 0; block < 12; block++)
-		inode->u.ext_i.i_data[block] = raw_inode->i_zone[block];
-	brelse(bh);
-	inode->i_op = NULL;
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &ext_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
-		inode->i_op = &ext_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &ext_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
-}
-
-static struct buffer_head * ext_update_inode(struct inode * inode)
-{
-	struct buffer_head * bh;
-	struct ext_inode * raw_inode;
-	int block;
-
-	block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
-	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
-		panic("unable to read i-node block");
-	raw_inode = ((struct ext_inode *)bh->b_data) +
-		(inode->i_ino-1)%EXT_INODES_PER_BLOCK;
-	raw_inode->i_mode = inode->i_mode;
-	raw_inode->i_uid = inode->i_uid;
-	raw_inode->i_gid = inode->i_gid;
-	raw_inode->i_nlinks = inode->i_nlink;
-	raw_inode->i_size = inode->i_size;
-	raw_inode->i_time = inode->i_mtime;
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
-	else for (block = 0; block < 12; block++)
-		raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
-	mark_buffer_dirty(bh, 1);
-	inode->i_dirt=0;
-	return bh;
-}
-
-void ext_write_inode(struct inode * inode)
-{
-	struct buffer_head *bh;
-	bh = ext_update_inode (inode);
-	brelse(bh);
-}
-
-int ext_sync_inode (struct inode *inode)
-{
-	int err = 0;
-	struct buffer_head *bh;
-
-	bh = ext_update_inode(inode);
-	if (bh && buffer_dirty(bh))
-	{
-		ll_rw_block(WRITE, 1, &bh);
-		wait_on_buffer(bh);
-		if (buffer_req(bh) && !buffer_uptodate(bh))
-		{
-			printk ("IO error syncing ext inode ["
-				"%s:%08lx]\n",
-				kdevname(inode->i_dev), inode->i_ino);
-			err = -1;
-		}
-	}
-	else if (!bh)
-		err = -1;
-	brelse (bh);
-	return err;
-}
-
-
-static struct file_system_type ext_fs_type = {
-        ext_read_super, "ext", 1, NULL
-};
-
-int init_ext_fs(void)
-{
-        return register_filesystem(&ext_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
-	return init_ext_fs();
-}
-
-void cleanup_module(void)
-{
-        unregister_filesystem(&ext_fs_type);
-}
-
-#endif
diff -u --recursive --new-file v2.1.20/linux/fs/ext/namei.c linux/fs/ext/namei.c
--- v2.1.20/linux/fs/ext/namei.c	Tue Oct 29 19:58:20 1996
+++ linux/fs/ext/namei.c	Thu Jan  1 02:00:00 1970
@@ -1,903 +0,0 @@
-/*
- *  linux/fs/ext/namei.c
- *
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/namei.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-#include <asm/uaccess.h>
-
-/*
- * comment out this line if you want names > EXT_NAME_LEN chars to be
- * truncated. Else they will be disallowed.
- */
-/* #define NO_TRUNCATE */
-
-/*
- * EXT_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a power of 2 and must be greater or equal than 8
- * because a directory entry needs 8 bytes for its fixed part
- * (4 bytes for the inode, 2 bytes for the entry length and 2 bytes
- * for the name length)
- */
-#define EXT_DIR_PAD 8
-
-/*
- *
- * EXT_DIR_MIN_SIZE is the minimal size of a directory entry
- *
- * During allocations, a directory entry is split into 2 ones
- * *ONLY* if the size of the unused part is greater than or 
- * equal to EXT_DIR_MIN_SIZE
- */
-#define EXT_DIR_MIN_SIZE 12
-
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use ext_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, ext_match returns 1 for success, 0 for failure.
- */
-static int ext_match(int len,const char * name,struct ext_dir_entry * de)
-{
-	if (!de || !de->inode || len > EXT_NAME_LEN)
-		return 0;
-	/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
-	if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
-		return 1;
-	if (len != de->name_len)
-		return 0;
-	return !memcmp(name, de->name, len);
-}
-
-/*
- *	ext_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- *
- * addition for the ext file system : this function returns the previous
- * and next directory entries in the parameters prev_dir and next_dir
- */
-static struct buffer_head * ext_find_entry(struct inode * dir,
-	const char * name, int namelen, struct ext_dir_entry ** res_dir,
-	struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
-{
-	long offset;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de;
-
-	*res_dir = NULL;
-	if (!dir)
-		return NULL;
-#ifdef NO_TRUNCATE
-	if (namelen > EXT_NAME_LEN)
-		return NULL;
-#else
-	if (namelen > EXT_NAME_LEN)
-		namelen = EXT_NAME_LEN;
-#endif
-	bh = ext_bread(dir,0,0);
-	if (!bh)
-		return NULL;
-	if (prev_dir)
-		*prev_dir = NULL;
-	if (next_dir)
-		*next_dir = NULL;
-	offset = 0;
-	de = (struct ext_dir_entry *) bh->b_data;
-	while (offset < dir->i_size) {
-		if ((char *)de >= BLOCK_SIZE+bh->b_data) {
-			brelse(bh);
-			bh = NULL;
-			bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
-			if (!bh)
-				continue;
-			de = (struct ext_dir_entry *) bh->b_data;
-			if (prev_dir)
-				*prev_dir = NULL;
-		}
-		if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
-		    de->rec_len < de->name_len + 8 ||
-		    (((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
-			printk ("ext_find_entry: bad dir entry\n");
-			printk ("dev=%s, dir=%ld, offset=%ld, "
-				"rec_len=%d, name_len=%d\n",
-				kdevname(dir->i_dev), dir->i_ino, offset,
-				de->rec_len, de->name_len);
-			de = (struct ext_dir_entry *) (bh->b_data+BLOCK_SIZE);
-			offset = ((offset / BLOCK_SIZE) + 1) * BLOCK_SIZE;
-			continue;
-/*			brelse (bh);
-			return NULL; */
-		}
-		if (ext_match(namelen,name,de)) {
-			*res_dir = de;
-			if (next_dir)
-				if (offset + de->rec_len < dir->i_size &&
-				    ((char *)de) + de->rec_len < BLOCK_SIZE+bh->b_data)
-					*next_dir = (struct ext_dir_entry *)
-						((char *) de + de->rec_len);
-				else
-					*next_dir = NULL;
-			return bh;
-		}
-		offset += de->rec_len;
-		if (prev_dir)
-			*prev_dir = de;
-		de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-	}
-	brelse(bh);
-	return NULL;
-}
-
-int ext_lookup(struct inode * dir,const char * name, int len,
-	struct inode ** result)
-{
-	int ino;
-	struct ext_dir_entry * de;
-	struct buffer_head * bh;
-
-	*result = NULL;
-	if (!dir)
-		return -ENOENT;
-	if (!S_ISDIR(dir->i_mode)) {
-		iput(dir);
-		return -ENOENT;
-	}
-	if (!(bh = ext_find_entry(dir,name,len,&de,NULL,NULL))) {
-		iput(dir);
-		return -ENOENT;
-	}
-	ino = de->inode;
-	brelse(bh);
-	if (!(*result = iget(dir->i_sb,ino))) {
-		iput(dir);
-		return -EACCES;
-	}
-	iput(dir);
-	return 0;
-}
-
-/*
- *	ext_add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as ext_find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * ext_add_entry(struct inode * dir,
-	const char * name, int namelen, struct ext_dir_entry ** res_dir)
-{
-	int i;
-	long offset;
-	unsigned short rec_len;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de, * de1;
-
-	*res_dir = NULL;
-	if (!dir)
-		return NULL;
-#ifdef NO_TRUNCATE
-	if (namelen > EXT_NAME_LEN)
-		return NULL;
-#else
-	if (namelen > EXT_NAME_LEN)
-		namelen = EXT_NAME_LEN;
-#endif
-	if (!namelen)
-		return NULL;
-	bh = ext_bread(dir,0,0);
-	if (!bh)
-		return NULL;
-	rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
-	offset = 0;
-	de = (struct ext_dir_entry *) bh->b_data;
-	while (1) {
-		if ((char *)de >= BLOCK_SIZE+bh->b_data && offset < dir->i_size) {
-#ifdef EXTFS_DEBUG
-printk ("ext_add_entry: skipping to next block\n");
-#endif
-			brelse(bh);
-			bh = NULL;
-			bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
-			if (!bh)
-				return NULL;
-			de = (struct ext_dir_entry *) bh->b_data;
-		}
-		if (offset >= dir->i_size) {
-			/* Check that the directory entry fits in the block */
-			if (offset % BLOCK_SIZE == 0  ||
-			    (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
-				if ((offset % BLOCK_SIZE) != 0) {
-					/* If the entry does not fit in the
-					   block, the remainder of the block
-					   becomes an unused entry */
-					de->inode = 0;
-					de->rec_len = BLOCK_SIZE
-						- (offset & (BLOCK_SIZE - 1));
-					de->name_len = 0;
-					offset += de->rec_len;
-					dir->i_size += de->rec_len;
-					dir->i_dirt = 1;
-#if 0
-					dir->i_ctime = CURRENT_TIME;
-#endif
-					mark_buffer_dirty(bh, 1);
-				}
-				brelse (bh);
-				bh = NULL;
-#ifdef EXTFS_DEBUG
-printk ("ext_add_entry : creating next block\n");
-#endif
-				bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
-				if (!bh)
-					return NULL; /* Other thing to do ??? */
-				de = (struct ext_dir_entry *) bh->b_data;
-			}
-			/* Allocate the entry */
-			de->inode=0;
-			de->rec_len = rec_len;
-			dir->i_size += de->rec_len;
-			dir->i_dirt = 1;
-#if 0
-			dir->i_ctime = CURRENT_TIME;
-#endif
-		}
-		if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
-		    de->rec_len < de->name_len + 8 ||
-		    (((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
-			printk ("ext_addr_entry: bad dir entry\n");
-			printk ("dev=%s, dir=%ld, offset=%ld, "
-				"rec_len=%d, name_len=%d\n",
-				kdevname(dir->i_dev), dir->i_ino, offset,
-				de->rec_len, de->name_len);
-			brelse (bh);
-			return NULL;
-		}
-		if (!de->inode && de->rec_len >= rec_len) {
-			if (de->rec_len > rec_len
-			    && de->rec_len - rec_len >= EXT_DIR_MIN_SIZE) {
-				/* The found entry is too big : it is split
-				   into 2 ones :
-				   - the 1st one will be used to hold the name,
-				   - the 2nd one is unused */
-				de1 = (struct ext_dir_entry *) ((char *) de + rec_len);
-				de1->inode = 0;
-				de1->rec_len = de->rec_len - rec_len;
-				de1->name_len = 0;
-				de->rec_len = rec_len;
-			}
-			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-			dir->i_dirt = 1;
-			de->name_len = namelen;
-			for (i=0; i < namelen ; i++)
-				de->name[i] = name[i];
-			mark_buffer_dirty(bh, 1);
-			*res_dir = de;
-			return bh;
-		}
-		offset += de->rec_len;
-		de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-	}
-	brelse(bh);
-	return NULL;
-}
-
-int ext_create(struct inode * dir,const char * name, int len, int mode,
-	struct inode ** result)
-{
-	struct inode * inode;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de;
-
-	*result = NULL;
-	if (!dir)
-		return -ENOENT;
-	inode = ext_new_inode(dir);
-	if (!inode) {
-		iput(dir);
-		return -ENOSPC;
-	}
-	inode->i_op = &ext_file_inode_operations;
-	inode->i_mode = mode;
-	inode->i_dirt = 1;
-	bh = ext_add_entry(dir,name,len,&de);
-	if (!bh) {
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput(inode);
-		iput(dir);
-		return -ENOSPC;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
-	iput(dir);
-	*result = inode;
-	return 0;
-}
-
-int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
-{
-	struct inode * inode;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de;
-
-	if (!dir)
-		return -ENOENT;
-	bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
-	if (bh) {
-		brelse(bh);
-		iput(dir);
-		return -EEXIST;
-	}
-	inode = ext_new_inode(dir);
-	if (!inode) {
-		iput(dir);
-		return -ENOSPC;
-	}
-	inode->i_uid = current->fsuid;
-	inode->i_mode = mode;
-	inode->i_op = NULL;
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &ext_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &ext_dir_inode_operations;
-		if (dir->i_mode & S_ISGID)
-			inode->i_mode |= S_ISGID;
-	}
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &ext_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
-	if (S_ISBLK(mode) || S_ISCHR(mode))
-		inode->i_rdev = to_kdev_t(rdev);
-#if 0
-	inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
-	inode->i_dirt = 1;
-	bh = ext_add_entry(dir,name,len,&de);
-	if (!bh) {
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput(inode);
-		iput(dir);
-		return -ENOSPC;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
-	iput(dir);
-	iput(inode);
-	return 0;
-}
-
-int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
-{
-	struct inode * inode;
-	struct buffer_head * bh, *dir_block;
-	struct ext_dir_entry * de;
-	
-	bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
-	if (bh) {
-		brelse(bh);
-		iput(dir);
-		return -EEXIST;
-	}
-	inode = ext_new_inode(dir);
-	if (!inode) {
-		iput(dir);
-		return -ENOSPC;
-	}
-	inode->i_op = &ext_dir_inode_operations;
-	inode->i_size = 2 * 16; /* Each entry is coded on 16 bytes for "." and ".."
-					- 4 bytes for the inode number,
-					- 2 bytes for the record length
-					- 2 bytes for the name length
-					- 8 bytes for the name */
-#if 0
-	inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
-	dir_block = ext_bread(inode,0,1);
-	if (!dir_block) {
-		iput(dir);
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput(inode);
-		return -ENOSPC;
-	}
-	de = (struct ext_dir_entry *) dir_block->b_data;
-	de->inode=inode->i_ino;
-	de->rec_len=16;
-	de->name_len=1;
-	strcpy(de->name,".");
-	de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-	de->inode = dir->i_ino;
-	de->rec_len=16;
-	de->name_len=2;
-	strcpy(de->name,"..");
-	inode->i_nlink = 2;
-	mark_buffer_dirty(dir_block, 1);
-	brelse(dir_block);
-	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
-	if (dir->i_mode & S_ISGID)
-		inode->i_mode |= S_ISGID;
-	inode->i_dirt = 1;
-	bh = ext_add_entry(dir,name,len,&de);
-	if (!bh) {
-		iput(dir);
-		inode->i_nlink=0;
-		iput(inode);
-		return -ENOSPC;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh, 1);
-	dir->i_nlink++;
-	dir->i_dirt = 1;
-	iput(dir);
-	iput(inode);
-	brelse(bh);
-	return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct inode * inode)
-{
-	unsigned long offset;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de, * de1;
-
-	if (inode->i_size < 2 * 12 || !(bh = ext_bread(inode,0,0))) {
-	    	printk("warning - bad directory on dev %s\n",
-		       kdevname(inode->i_dev));
-		return 1;
-	}
-	de = (struct ext_dir_entry *) bh->b_data;
-	de1 = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-	if (de->inode != inode->i_ino || !de1->inode || 
-	    strcmp(".",de->name) || strcmp("..",de1->name)) {
-	    	printk("warning - bad directory on dev %s\n",
-		       kdevname(inode->i_dev));
-		return 1;
-	}
-	offset = de->rec_len + de1->rec_len;
-	de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len);
-	while (offset < inode->i_size ) {
-		if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
-			brelse(bh);
-			bh = ext_bread(inode, offset >> BLOCK_SIZE_BITS,1);
-			if (!bh) {
-				offset += BLOCK_SIZE;
-				continue;
-			}
-			de = (struct ext_dir_entry *) bh->b_data;
-		}
-		if (de->rec_len < 8 || de->rec_len %4 != 0 ||
-		    de->rec_len < de->name_len + 8) {
-			printk ("empty_dir: bad dir entry\n");
-			printk ("dev=%s, dir=%ld, offset=%ld, "
-				"rec_len=%d, name_len=%d\n",
-				kdevname(inode->i_dev), inode->i_ino,
-				offset, de->rec_len, de->name_len);
-			brelse (bh);
-			return 1;
-		}
-		if (de->inode) {
-			brelse(bh);
-			return 0;
-		}
-		offset += de->rec_len;
-		de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-	}
-	brelse(bh);
-	return 1;
-}
-
-static inline void ext_merge_entries (struct ext_dir_entry * de,
-	struct ext_dir_entry * pde, struct ext_dir_entry * nde)
-{
-	if (nde && !nde->inode)
-		de->rec_len += nde->rec_len;
-	if (pde && !pde->inode)
-		pde->rec_len += de->rec_len;
-}
-
-int ext_rmdir(struct inode * dir, const char * name, int len)
-{
-	int retval;
-	struct inode * inode;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de, * pde, * nde;
-
-	inode = NULL;
-	bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
-	retval = -ENOENT;
-	if (!bh)
-		goto end_rmdir;
-	retval = -EPERM;
-	if (!(inode = iget(dir->i_sb, de->inode)))
-		goto end_rmdir;
-        if ((dir->i_mode & S_ISVTX) && !fsuser() &&
-            current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid)
-		goto end_rmdir;
-	if (inode->i_dev != dir->i_dev)
-		goto end_rmdir;
-	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-		goto end_rmdir;
-	if (!S_ISDIR(inode->i_mode)) {
-		retval = -ENOTDIR;
-		goto end_rmdir;
-	}
-	if (!empty_dir(inode)) {
-		retval = -ENOTEMPTY;
-		goto end_rmdir;
-	}
-	if (inode->i_count > 1) {
-		retval = -EBUSY;
-		goto end_rmdir;
-	}
-	if (inode->i_nlink != 2)
-		printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
-	de->inode = 0;
-	de->name_len = 0;
-	ext_merge_entries (de, pde, nde);
-	mark_buffer_dirty(bh, 1);
-	inode->i_nlink=0;
-	inode->i_dirt=1;
-	dir->i_nlink--;
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	dir->i_dirt=1;
-	retval = 0;
-end_rmdir:
-	iput(dir);
-	iput(inode);
-	brelse(bh);
-	return retval;
-}
-
-int ext_unlink(struct inode * dir, const char * name, int len)
-{
-	int retval;
-	struct inode * inode;
-	struct buffer_head * bh;
-	struct ext_dir_entry * de, * pde, * nde;
-
-	retval = -ENOENT;
-	inode = NULL;
-	bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
-	if (!bh)
-		goto end_unlink;
-	if (!(inode = iget(dir->i_sb, de->inode)))
-		goto end_unlink;
-	retval = -EPERM;
-	if ((dir->i_mode & S_ISVTX) && !fsuser() &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid)
-		goto end_unlink;
-	if (S_ISDIR(inode->i_mode))
-		goto end_unlink;
-	if (!inode->i_nlink) {
-		printk("Deleting nonexistent file (%s:%ld), %d\n",
-		       kdevname(inode->i_dev), inode->i_ino,
-		       inode->i_nlink);
-		inode->i_nlink=1;
-	}
-	de->inode = 0;
-	de->name_len = 0;
-	ext_merge_entries (de, pde, nde);
-	mark_buffer_dirty(bh, 1);
-	inode->i_nlink--;
-	inode->i_dirt = 1;
-	inode->i_ctime = CURRENT_TIME;
-	dir->i_ctime = dir->i_mtime = inode->i_ctime;
-	dir->i_dirt = 1;
-	retval = 0;
-end_unlink:
-	brelse(bh);
-	iput(inode);
-	iput(dir);
-	return retval;
-}
-
-int ext_symlink(struct inode * dir, const char * name, int len, const char * symname)
-{
-	struct ext_dir_entry * de;
-	struct inode * inode = NULL;
-	struct buffer_head * bh = NULL, * name_block = NULL;
-	int i;
-	char c;
-
-	if (!(inode = ext_new_inode(dir))) {
-		iput(dir);
-		return -ENOSPC;
-	}
-	inode->i_mode = S_IFLNK | 0777;
-	inode->i_op = &ext_symlink_inode_operations;
-	name_block = ext_bread(inode,0,1);
-	if (!name_block) {
-		iput(dir);
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput(inode);
-		return -ENOSPC;
-	}
-	i = 0;
-	while (i < 1023 && (c = *(symname++)))
-		name_block->b_data[i++] = c;
-	name_block->b_data[i] = 0;
-	mark_buffer_dirty(name_block, 1);
-	brelse(name_block);
-	inode->i_size = i;
-	inode->i_dirt = 1;
-	bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
-	if (bh) {
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput(inode);
-		brelse(bh);
-		iput(dir);
-		return -EEXIST;
-	}
-	bh = ext_add_entry(dir,name,len,&de);
-	if (!bh) {
-		inode->i_nlink--;
-		inode->i_dirt = 1;
-		iput(inode);
-		iput(dir);
-		return -ENOSPC;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
-	iput(dir);
-	iput(inode);
-	return 0;
-}
-
-int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
-{
-	struct ext_dir_entry * de;
-	struct buffer_head * bh;
-
-	if (S_ISDIR(oldinode->i_mode)) {
-		iput(oldinode);
-		iput(dir);
-		return -EPERM;
-	}
-	if (oldinode->i_nlink > 32000) {
-		iput(oldinode);
-		iput(dir);
-		return -EMLINK;
-	}
-	bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
-	if (bh) {
-		brelse(bh);
-		iput(dir);
-		iput(oldinode);
-		return -EEXIST;
-	}
-	bh = ext_add_entry(dir,name,len,&de);
-	if (!bh) {
-		iput(dir);
-		iput(oldinode);
-		return -ENOSPC;
-	}
-	de->inode = oldinode->i_ino;
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
-	iput(dir);
-	oldinode->i_nlink++;
-	oldinode->i_ctime = CURRENT_TIME;
-	oldinode->i_dirt = 1;
-	iput(oldinode);
-	return 0;
-}
-
-static int subdir(struct inode * new_inode, struct inode * old_inode)
-{
-	int ino;
-	int result;
-
-	new_inode->i_count++;
-	result = 0;
-	for (;;) {
-		if (new_inode == old_inode) {
-			result = 1;
-			break;
-		}
-		if (new_inode->i_dev != old_inode->i_dev)
-			break;
-		ino = new_inode->i_ino;
-		if (ext_lookup(new_inode,"..",2,&new_inode))
-			break;
-		if (new_inode->i_ino == ino)
-			break;
-	}
-	iput(new_inode);
-	return result;
-}
-
-#define PARENT_INO(buffer) \
-((struct ext_dir_entry *) ((char *) buffer + \
-((struct ext_dir_entry *) buffer)->rec_len))->inode
-
-#define PARENT_NAME(buffer) \
-((struct ext_dir_entry *) ((char *) buffer + \
-((struct ext_dir_entry *) buffer)->rec_len))->name
-
-/*
- * rename uses retrying to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
- * Anybody can rename anything with this: the permission checks are left to the
- * higher-level routines.
- */
-static int do_ext_rename(struct inode * old_dir, const char * old_name, int old_len,
-	struct inode * new_dir, const char * new_name, int new_len)
-{
-	struct inode * old_inode, * new_inode;
-	struct buffer_head * old_bh, * new_bh, * dir_bh;
-	struct ext_dir_entry * old_de, * new_de, * pde, * nde;
-	int retval;
-
-	goto start_up;
-try_again:
-	brelse(old_bh);
-	brelse(new_bh);
-	brelse(dir_bh);
-	iput(old_inode);
-	iput(new_inode);
-	current->counter = 0;
-	schedule();
-start_up:
-	old_inode = new_inode = NULL;
-	old_bh = new_bh = dir_bh = NULL;
-	old_bh = ext_find_entry(old_dir,old_name,old_len,&old_de,&pde,&nde);
-	retval = -ENOENT;
-	if (!old_bh)
-		goto end_rename;
-	old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
-	if (!old_inode)
-		goto end_rename;
-	retval = -EPERM;
-	if ((old_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != old_inode->i_uid &&
-	    current->fsuid != old_dir->i_uid && !fsuser())
-		goto end_rename;
-	new_bh = ext_find_entry(new_dir,new_name,new_len,&new_de,NULL,NULL);
-	if (new_bh) {
-		new_inode = __iget(new_dir->i_sb, new_de->inode,0); /* don't cross mnt-points */
-		if (!new_inode) {
-			brelse(new_bh);
-			new_bh = NULL;
-		}
-	}
-	if (new_inode == old_inode) {
-		retval = 0;
-		goto end_rename;
-	}
-	if (new_inode && S_ISDIR(new_inode->i_mode)) {
-		retval = -EEXIST;
-		goto end_rename;
-	}
-	retval = -EPERM;
-	if (new_inode && (new_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != new_inode->i_uid &&
-	    current->fsuid != new_dir->i_uid && !fsuser())
-		goto end_rename;
-	if (S_ISDIR(old_inode->i_mode)) {
-		retval = -EEXIST;
-		if (new_bh)
-			goto end_rename;
-		if ((retval = permission(old_inode, MAY_WRITE)) != 0)
-			goto end_rename;
-		retval = -EINVAL;
-		if (subdir(new_dir, old_inode))
-			goto end_rename;
-		retval = -EIO;
-		dir_bh = ext_bread(old_inode,0,0);
-		if (!dir_bh)
-			goto end_rename;
-		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
-			goto end_rename;
-	}
-	if (!new_bh)
-		new_bh = ext_add_entry(new_dir,new_name,new_len,&new_de);
-	retval = -ENOSPC;
-	if (!new_bh)
-		goto end_rename;
-/* sanity checking before doing the rename - avoid races */
-	if (new_inode && (new_de->inode != new_inode->i_ino))
-		goto try_again;
-	if (new_de->inode && !new_inode)
-		goto try_again;
-	if (old_de->inode != old_inode->i_ino)
-		goto try_again;
-/* ok, that's it */
-	old_de->inode = 0;
-	old_de->name_len = 0;
-	new_de->inode = old_inode->i_ino;
-	ext_merge_entries (old_de, pde, nde);
-	if (new_inode) {
-		new_inode->i_nlink--;
-		new_inode->i_dirt = 1;
-	}
-	mark_buffer_dirty(old_bh, 1);
-	mark_buffer_dirty(new_bh, 1);
-	if (dir_bh) {
-		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-		mark_buffer_dirty(dir_bh, 1);
-		old_dir->i_nlink--;
-		new_dir->i_nlink++;
-		old_dir->i_dirt = 1;
-		new_dir->i_dirt = 1;
-	}
-	retval = 0;
-end_rename:
-	brelse(dir_bh);
-	brelse(old_bh);
-	brelse(new_bh);
-	iput(old_inode);
-	iput(new_inode);
-	iput(old_dir);
-	iput(new_dir);
-	return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
-int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
-	struct inode * new_dir, const char * new_name, int new_len,
-	int must_be_dir)
-{
-	static struct wait_queue * wait = NULL;
-	static int lock = 0;
-	int result;
-
-	while (lock)
-		sleep_on(&wait);
-	lock = 1;
-	result = do_ext_rename(old_dir, old_name, old_len,
-		new_dir, new_name, new_len);
-	lock = 0;
-	wake_up(&wait);
-	return result;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/ext/symlink.c linux/fs/ext/symlink.c
--- v2.1.20/linux/fs/ext/symlink.c	Tue Oct 29 19:58:42 1996
+++ linux/fs/ext/symlink.c	Thu Jan  1 02:00:00 1970
@@ -1,110 +0,0 @@
-/*
- *  linux/fs/ext/symlink.c
- *
- *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/symlink.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  ext symlink handling code
- */
-
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-
-static int ext_readlink(struct inode *, char *, int);
-static int ext_follow_link(struct inode *, struct inode *, int, int, struct inode **);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations ext_symlink_inode_operations = {
-	NULL,			/* no file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	ext_readlink,		/* readlink */
-	ext_follow_link,	/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	NULL,			/* truncate */
-	NULL			/* permission */
-};
-
-static int ext_follow_link(struct inode * dir, struct inode * inode,
-	int flag, int mode, struct inode ** res_inode)
-{
-	int error;
-	struct buffer_head * bh;
-
-	*res_inode = NULL;
-	if (!dir) {
-		dir = current->fs->root;
-		dir->i_count++;
-	}
-	if (!inode) {
-		iput(dir);
-		return -ENOENT;
-	}
-	if (!S_ISLNK(inode->i_mode)) {
-		iput(dir);
-		*res_inode = inode;
-		return 0;
-	}
-	if (current->link_count > 5) {
-		iput(dir);
-		iput(inode);
-		return -ELOOP;
-	}
-	if (!(bh = ext_bread(inode, 0, 0))) {
-		iput(inode);
-		iput(dir);
-		return -EIO;
-	}
-	iput(inode);
-	current->link_count++;
-	error = open_namei(bh->b_data,flag,mode,res_inode,dir);
-	current->link_count--;
-	brelse(bh);
-	return error;
-}
-
-static int ext_readlink(struct inode * inode, char * buffer, int buflen)
-{
-	struct buffer_head * bh;
-	int i;
-	char c;
-
-	if (!S_ISLNK(inode->i_mode)) {
-		iput(inode);
-		return -EINVAL;
-	}
-	if (buflen > 1023)
-		buflen = 1023;
-	bh = ext_bread(inode, 0, 0);
-	iput(inode);
-	if (!bh)
-		return 0;
-	i = 0;
-	while (i<buflen && (c = bh->b_data[i])) {
-		i++;
-		put_user(c,buffer++);
-	}
-	brelse(bh);
-	return i;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/ext/truncate.c linux/fs/ext/truncate.c
--- v2.1.20/linux/fs/ext/truncate.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/ext/truncate.c	Thu Jan  1 02:00:00 1970
@@ -1,252 +0,0 @@
-/*
- *  linux/fs/ext/truncate.c
- *
- *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
- *
- *  from
- *
- *  linux/fs/minix/truncate.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-static int trunc_direct(struct inode * inode)
-{
-	int i, tmp;
-	unsigned long * p;
-	struct buffer_head * bh;
-	int retry = 0;
-#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
-
-repeat:
-	for (i = DIRECT_BLOCK ; i < 9 ; i++) {
-		p = inode->u.ext_i.i_data+i;
-		if (!(tmp = *p))
-			continue;
-		bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
-		if (i < DIRECT_BLOCK) {
-			brelse(bh);
-			goto repeat;
-		}
-		if ((bh && bh->b_count != 1) || tmp != *p) {
-			retry = 1;
-			brelse(bh);
-			continue;
-		}
-		*p = 0;
-		inode->i_dirt = 1;
-		brelse(bh);
-		ext_free_block(inode->i_sb,tmp);
-	}
-	return retry;
-}
-
-static int trunc_indirect(struct inode * inode, int offset, unsigned long * p)
-{
-	int i, tmp;
-	struct buffer_head * bh;
-	struct buffer_head * ind_bh;
-	unsigned long * ind;
-	int retry = 0;
-#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
-
-	tmp = *p;
-	if (!tmp)
-		return 0;
-	ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
-	if (tmp != *p) {
-		brelse(ind_bh);
-		return 1;
-	}
-	if (!ind_bh) {
-		*p = 0;
-		return 0;
-	}
-repeat:
-	for (i = INDIRECT_BLOCK ; i < 256 ; i++) {
-		if (i < 0)
-			i = 0;
-		if (i < INDIRECT_BLOCK)
-			goto repeat;
-		ind = i+(unsigned long *) ind_bh->b_data;
-		tmp = *ind;
-		if (!tmp)
-			continue;
-		bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
-		if (i < INDIRECT_BLOCK) {
-			brelse(bh);
-			goto repeat;
-		}
-		if ((bh && bh->b_count != 1) || tmp != *ind) {
-			retry = 1;
-			brelse(bh);
-			continue;
-		}
-		*ind = 0;
-		mark_buffer_dirty(ind_bh, 1);
-		brelse(bh);
-		ext_free_block(inode->i_sb,tmp);
-	}
-	ind = (unsigned long *) ind_bh->b_data;
-	for (i = 0; i < 256; i++)
-		if (*(ind++))
-			break;
-	if (i >= 256)
-		if (ind_bh->b_count != 1)
-			retry = 1;
-		else {
-			tmp = *p;
-			*p = 0;
-			inode->i_dirt = 1;
-			ext_free_block(inode->i_sb,tmp);
-		}
-	brelse(ind_bh);
-	return retry;
-}
-
-static int trunc_dindirect(struct inode * inode, int offset, unsigned long * p)
-{
-	int i,tmp;
-	struct buffer_head * dind_bh;
-	unsigned long * dind;
-	int retry = 0;
-#define DINDIRECT_BLOCK ((DIRECT_BLOCK-offset)>>8)
-
-	tmp = *p;
-	if (!tmp)
-		return 0;
-	dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
-	if (tmp != *p) {
-		brelse(dind_bh);
-		return 1;
-	}
-	if (!dind_bh) {
-		*p = 0;
-		return 0;
-	}
-repeat:
-	for (i = DINDIRECT_BLOCK ; i < 256 ; i ++) {
-		if (i < 0)
-			i = 0;
-		if (i < DINDIRECT_BLOCK)
-			goto repeat;
-		dind = i+(unsigned long *) dind_bh->b_data;
-		tmp = *dind;
-		if (!tmp)
-			continue;
-		retry |= trunc_indirect(inode,offset+(i<<8),dind);
-		mark_buffer_dirty(dind_bh, 1);
-	}
-	dind = (unsigned long *) dind_bh->b_data;
-	for (i = 0; i < 256; i++)
-		if (*(dind++))
-			break;
-	if (i >= 256)
-		if (dind_bh->b_count != 1)
-			retry = 1;
-		else {
-			tmp = *p;
-			*p = 0;
-			inode->i_dirt = 1;
-			ext_free_block(inode->i_sb,tmp);
-		}
-	brelse(dind_bh);
-	return retry;
-}
-
-static int trunc_tindirect(struct inode * inode)
-{
-	int i,tmp;
-	struct buffer_head * tind_bh;
-	unsigned long * tind, * p;
-	int retry = 0;
-#define TINDIRECT_BLOCK ((DIRECT_BLOCK-(256*256+256+9))>>16)
-
-	p = inode->u.ext_i.i_data+11;
-	if (!(tmp = *p))
-		return 0;
-	tind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
-	if (tmp != *p) {
-		brelse(tind_bh);
-		return 1;
-	}
-	if (!tind_bh) {
-		*p = 0;
-		return 0;
-	}
-repeat:
-	for (i = TINDIRECT_BLOCK ; i < 256 ; i ++) {
-		if (i < 0)
-			i = 0;
-		if (i < TINDIRECT_BLOCK)
-			goto repeat;
-		tind = i+(unsigned long *) tind_bh->b_data;
-		retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
-		mark_buffer_dirty(tind_bh, 1);
-	}
-	tind = (unsigned long *) tind_bh->b_data;
-	for (i = 0; i < 256; i++)
-		if (*(tind++))
-			break;
-	if (i >= 256)
-		if (tind_bh->b_count != 1)
-			retry = 1;
-		else {
-			tmp = *p;
-			*p = 0;
-			inode->i_dirt = 1;
-			ext_free_block(inode->i_sb,tmp);
-		}
-	brelse(tind_bh);
-	return retry;
-}
-
-void ext_truncate(struct inode * inode)
-{
-	int retry;
-
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	     S_ISLNK(inode->i_mode)))
-		return;
-	while (1) {
-		retry = trunc_direct(inode);
-		retry |= trunc_indirect(inode,9,inode->u.ext_i.i_data+9);
-		retry |= trunc_dindirect(inode,9+256,inode->u.ext_i.i_data+10);
-		retry |= trunc_tindirect(inode);
-		if (!retry)
-			break;
-		current->counter = 0;
-		schedule();
-	}
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_dirt = 1;
-}
-
-/*
- * Called when an inode is released. Note that this is different
- * from ext_open: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
- */
-void ext_release(struct inode * inode, struct file * filp)
-{
-	printk("ext_release not implemented\n");
-}
diff -u --recursive --new-file v2.1.20/linux/fs/fat/fatfs_syms.c linux/fs/fat/fatfs_syms.c
--- v2.1.20/linux/fs/fat/fatfs_syms.c	Mon Dec 30 15:39:13 1996
+++ linux/fs/fat/fatfs_syms.c	Fri Jan  3 11:33:26 1997
@@ -4,6 +4,7 @@
  * Exported kernel symbols for the low-level FAT-based fs support.
  *
  */
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.20/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.1.20/linux/fs/filesystems.c	Thu Apr 25 12:32:39 1996
+++ linux/fs/filesystems.c	Tue Jan 14 12:59:10 1997
@@ -10,9 +10,7 @@
 #include <linux/fs.h>
 
 #include <linux/minix_fs.h>
-#include <linux/ext_fs.h>
 #include <linux/ext2_fs.h>
-#include <linux/xia_fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 #include <linux/proc_fs.h>
@@ -24,6 +22,7 @@
 #include <linux/ncp_fs.h>
 #include <linux/affs_fs.h>
 #include <linux/ufs_fs.h>
+#include <linux/romfs_fs.h>
 #include <linux/major.h>
 
 extern void device_setup(void);
@@ -42,18 +41,10 @@
 
 	binfmt_setup();
 
-#ifdef CONFIG_EXT_FS
-	init_ext_fs();
-#endif
-
 #ifdef CONFIG_EXT2_FS
 	init_ext2_fs();
 #endif
 
-#ifdef CONFIG_XIA_FS
-	init_xiafs_fs();
-#endif
-
 #ifdef CONFIG_MINIX_FS
 	init_minix_fs();
 #endif
@@ -110,6 +101,11 @@
 	init_ufs_fs();
 #endif
 
+#ifdef CONFIG_ROMFS_FS
+	init_romfs_fs();
+#endif
+
 	mount_root();
 	return 0;
 }
+
diff -u --recursive --new-file v2.1.20/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.1.20/linux/fs/isofs/inode.c	Thu Jan  2 15:55:23 1997
+++ linux/fs/isofs/inode.c	Fri Jan  3 11:33:26 1997
@@ -8,6 +8,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/stat.h>
diff -u --recursive --new-file v2.1.20/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- v2.1.20/linux/fs/msdos/msdosfs_syms.c	Mon Dec 30 15:39:13 1996
+++ linux/fs/msdos/msdosfs_syms.c	Fri Jan  3 11:33:26 1997
@@ -5,6 +5,7 @@
  * These symbols are used by umsdos.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.20/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.20/linux/fs/ncpfs/inode.c	Tue Dec 31 21:41:08 1996
+++ linux/fs/ncpfs/inode.c	Fri Jan  3 11:33:26 1997
@@ -6,8 +6,8 @@
  *
  */
 
-#include <linux/module.h>
 #include <linux/config.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.1.20/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.20/linux/fs/nfs/inode.c	Mon Dec 30 15:39:14 1996
+++ linux/fs/nfs/inode.c	Fri Jan  3 11:33:26 1997
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.20/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.1.20/linux/fs/proc/procfs_syms.c	Mon Dec 30 15:39:14 1996
+++ linux/fs/proc/procfs_syms.c	Fri Jan  3 11:33:26 1997
@@ -1,5 +1,5 @@
-#include <linux/module.h>
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 
diff -u --recursive --new-file v2.1.20/linux/fs/romfs/Makefile linux/fs/romfs/Makefile
--- v2.1.20/linux/fs/romfs/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/fs/romfs/Makefile	Fri Jan  3 13:03:42 1997
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux romfs-filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := romfs.o
+O_OBJS   := inode.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.20/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.1.20/linux/fs/romfs/inode.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/romfs/inode.c	Tue Jan 14 12:51:18 1997
@@ -0,0 +1,666 @@
+/*
+ * ROMFS file system, Linux implementation
+ *
+ * Copyright (C) 1997  Janos Farkas <chexum@shadow.banki.hu>
+ *
+ * Using parts of the minix filesystem
+ * Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * and parts of the affs filesystem additionally
+ * Copyright (C) 1993  Ray Burr
+ * Copyright (C) 1996  Hans-Joachim Widmaier
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Changes
+ *					Changed for 2.1.19 modules
+ *	Jan 1997			Initial release
+ */
+
+/* todo:
+ *	use malloced memory for file names?
+ *	considering write access...
+ *	network (tftp) files?
+ */
+
+/*
+ * Sorry about some optimizations and for some goto's.  I just wanted
+ * to squeeze some more bytes out of this code.. :)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/romfs_fs.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+
+#include <asm/uaccess.h>
+
+static int inline min(int a, int b)
+{
+	return a<b ? a : b;
+}
+
+static __s32
+romfs_checksum(void *data, int size)
+{
+	__s32 sum, *ptr;
+
+	sum = 0; ptr = data;
+	size>>=2;
+	while (size>0) {
+		sum += ntohl(*ptr++);
+		size--;
+	}
+	return sum;
+}
+
+static struct super_operations romfs_ops;
+
+static struct super_block *
+romfs_read_super(struct super_block *s, void *data, int silent)
+{
+	struct buffer_head *bh;
+	kdev_t dev = s->s_dev;
+	struct romfs_super_block *rsb;
+	int sz;
+
+	MOD_INC_USE_COUNT;
+
+	/* I would parse the options, but there are none.. :) */
+
+	lock_super(s);
+	set_blocksize(dev, ROMBSIZE);
+	s->s_blocksize = ROMBSIZE;
+	s->s_blocksize_bits = ROMBSBITS;
+	bh = bread(dev, 0, ROMBSIZE);
+	if (!bh) {
+                printk ("romfs: unable to read superblock\n");
+		goto outnobh;
+	}
+
+	rsb = (struct romfs_super_block *)bh->b_data;
+	sz = ntohl(rsb->size);
+	if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1
+	   || sz < ROMFH_SIZE) {
+		if (!silent)
+			printk ("VFS: Can't find a romfs filesystem on dev "
+				"%s.\n", kdevname(dev));
+		goto out;
+	}
+	if (romfs_checksum(rsb, min(sz,512))) {
+		printk ("romfs: bad initial checksum on dev "
+			"%s.\n", kdevname(dev));
+	}
+
+	s->s_magic = ROMFS_MAGIC;
+	s->u.romfs_sb.s_maxsize = sz;
+
+	s->s_flags |= MS_RDONLY;
+
+	/* Find the start of the fs */
+	sz = (ROMFH_SIZE +
+	      strnlen(rsb->name, ROMFS_MAXFN) + 1 + ROMFH_PAD)
+	     & ROMFH_MASK;
+
+	brelse(bh);
+
+	s->s_op	= &romfs_ops;
+
+	unlock_super(s);
+
+	if (!(s->s_mounted = iget(s, sz)))
+		goto outnobh;
+
+	/* Ehrhm; sorry.. :)  And thanks to Hans-Joachim Widmaier  :) */
+	if (0) {
+out:
+		brelse(bh);
+outnobh:
+		s->s_dev = 0;
+		unlock_super(s);
+		MOD_DEC_USE_COUNT;
+		s = NULL;
+	}
+
+	return s;
+}
+
+/* Nothing to do.. */
+
+static void
+romfs_put_super(struct super_block *sb)
+{
+	lock_super(sb);
+	sb->s_dev = 0;
+	unlock_super(sb);
+	MOD_DEC_USE_COUNT;
+	return;
+}
+
+
+/* That's simple too. */
+
+static void
+romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+{
+	struct statfs tmp;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.f_type = ROMFS_MAGIC;
+	tmp.f_bsize = ROMBSIZE;
+	tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS;
+	copy_to_user(buf, &tmp, bufsize);
+}
+
+static int
+romfs_strnlen(struct inode *i, unsigned long offset, unsigned long count)
+{
+	struct buffer_head *bh;
+	unsigned long avail, maxsize, res;
+
+	maxsize = i->i_sb->u.romfs_sb.s_maxsize;
+	if (offset >= maxsize)
+		return -1;
+
+	/* strnlen is almost always valid */
+	if (count > maxsize || offset+count > maxsize)
+		count = maxsize-offset;
+
+	bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+	if (!bh)
+		return -1;		/* error */
+
+	avail = ROMBSIZE - (offset & ROMBMASK);
+	maxsize = min(count, avail);
+	res = strnlen(((char *)bh->b_data)+(offset&ROMBMASK), maxsize);
+	brelse(bh);
+
+	if (res < maxsize)
+		return res;		/* found all of it */
+
+	while (res < count) {
+		offset += maxsize;
+
+		bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+		if (!bh)
+			return -1;
+		maxsize = min(count-res, ROMBSIZE);
+		avail = strnlen(bh->b_data, maxsize);
+		res += avail;
+		brelse(bh);
+		if (avail < maxsize)
+			return res;
+	}
+	return res;
+}
+
+static int
+romfs_copyfrom(struct inode *i, void *dest, unsigned long offset, unsigned long count)
+{
+	struct buffer_head *bh;
+	unsigned long avail, maxsize, res;
+
+	maxsize = i->i_sb->u.romfs_sb.s_maxsize;
+	if (offset >= maxsize || count > maxsize || offset+count>maxsize)
+		return -1;
+
+	bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+	if (!bh)
+		return -1;		/* error */
+
+	avail = ROMBSIZE - (offset & ROMBMASK);
+	maxsize = min(count, avail);
+	memcpy(dest, ((char *)bh->b_data) + (offset & ROMBMASK), maxsize);
+	brelse(bh);
+
+	res = maxsize;			/* all of it */
+
+	while (res < count) {
+		offset += maxsize;
+		dest += maxsize;
+
+		bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+		if (!bh)
+			return -1;
+		maxsize = min(count-res, ROMBSIZE);
+		memcpy(dest, bh->b_data, maxsize);
+		brelse(bh);
+		res += maxsize;
+	}
+	return res;
+}
+
+/* Directory operations */
+
+static int
+romfs_readdir(struct inode *i, struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct romfs_inode ri;
+	unsigned long offset, maxoff;
+	int j, ino, nextfh;
+	int stored = 0;
+	char fsname[ROMFS_MAXFN];	/* XXX dynamic? */
+
+	if (!i || !S_ISDIR(i->i_mode))
+		return -EBADF;
+
+	maxoff = i->i_sb->u.romfs_sb.s_maxsize;
+
+	offset = filp->f_pos;
+	if (!offset) {
+		offset = i->i_ino & ROMFH_MASK;
+		if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
+			return stored;
+		offset = ntohl(ri.spec) & ROMFH_MASK;
+	}
+
+	/* Not really failsafe, but we are read-only... */
+	for(;;) {
+		if (!offset || offset >= maxoff) {
+			offset = 0xffffffff;
+			filp->f_pos = offset;
+			return stored;
+		}
+		filp->f_pos = offset;
+
+		/* Fetch inode info */
+		if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
+			return stored;
+
+		j = romfs_strnlen(i, offset+ROMFH_SIZE, sizeof(fsname)-1);
+		if (j < 0)
+			return stored;
+
+		fsname[j]=0;
+		romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j);
+
+		ino = offset;
+		nextfh = ntohl(ri.next);
+		if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
+			ino = ntohl(ri.spec);
+		if (filldir(dirent, fsname, j, offset, ino) < 0) {
+			return stored;
+		}
+		stored++;
+		offset = nextfh & ROMFH_MASK;
+	}
+}
+
+static int
+romfs_lookup(struct inode *dir, const char *name, int len, struct inode **result)
+{
+	unsigned long offset, maxoff;
+	int fslen, res;
+	char fsname[ROMFS_MAXFN];	/* XXX dynamic? */
+	struct romfs_inode ri;
+
+	*result = NULL;
+	if (!dir || !S_ISDIR(dir->i_mode)) {
+		res = -EBADF;
+		goto out;
+	}
+
+	offset = dir->i_ino & ROMFH_MASK;
+	if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) {
+		res = -ENOENT;
+		goto out;
+	}
+
+	maxoff = dir->i_sb->u.romfs_sb.s_maxsize;
+	offset = ntohl(ri.spec) & ROMFH_MASK;
+
+	for(;;) {
+		if (!offset || offset >= maxoff
+		    || romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) {
+			res = -ENOENT;
+			goto out;
+		}
+
+		/* try to match the first 16 bytes of name */
+		fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE);
+		if (len < ROMFH_SIZE) {
+			if (len == fslen) {
+				/* both are shorter, and same size */
+				romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
+				if (strncmp (name, fsname, len) == 0)
+					break;
+			}
+		} else if (fslen >= ROMFH_SIZE) {
+			/* both are longer; XXX optimize max size */
+			fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1);
+			if (len == fslen) {
+				romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
+				if (strncmp(name, fsname, len) == 0)
+					break;
+			}
+		}
+		/* next entry */
+		offset = ntohl(ri.next) & ROMFH_MASK;
+	}
+
+	/* Hard link handling */
+	if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
+		offset = ntohl(ri.spec) & ROMFH_MASK;
+
+	res = 0;
+	if (!(*result = iget(dir->i_sb, offset)))
+		res = -EACCES;
+
+out:
+	iput(dir);
+	return res;
+}
+
+/*
+ * Ok, we do readpage, to be able to execute programs.  Unfortunately,
+ * bmap is not applicable, since we have looser alignments.
+ *
+ * XXX I'm not quite sure that I need to muck around the PG_xx bits..
+ */
+
+static int
+romfs_readpage(struct inode * inode, struct page * page)
+{
+	unsigned long buf;
+	unsigned long offset, avail, readlen;
+	int result = -EIO;
+
+	buf = page_address(page);
+	page->count++;
+	offset = page->offset;
+	if (offset < inode->i_size) {
+		avail = inode->i_size-offset;
+		readlen = min(avail, PAGE_SIZE);
+		if (romfs_copyfrom(inode, (void *)buf, inode->u.romfs_i.i_dataoffset+offset, readlen) == readlen) {
+			if (readlen < PAGE_SIZE) {
+				memset((void *)(buf+readlen),0,PAGE_SIZE-readlen);
+			}
+			result = 0;
+			set_bit(PG_uptodate, &page->flags);
+		} else {
+			memset((void *)buf, 0, PAGE_SIZE);
+		}
+	}
+	free_page(buf);
+	return result;
+}
+
+static int
+romfs_readlink(struct inode *inode, char *buffer, int len)
+{
+	int mylen;
+	char buf[ROMFS_MAXFN];		/* XXX dynamic */
+
+	if (!inode || !S_ISLNK(inode->i_mode)) {
+		mylen = -EBADF;
+		goto out;
+	}
+
+	mylen = min(sizeof(buf), inode->i_size);
+
+	if (romfs_copyfrom(inode, buf, inode->u.romfs_i.i_dataoffset, mylen) <= 0) {
+		mylen = -EIO;
+		goto out;
+	}
+	copy_to_user(buffer, buf, mylen);
+
+out:
+	iput(inode);
+	return mylen;
+}
+
+static int
+romfs_follow_link(struct inode *dir, struct inode *inode,
+	int flag, int mode, struct inode **res_inode)
+{
+	int error, len;
+	char *buf;
+
+	*res_inode = NULL;
+	if (!dir) {
+		dir = current->fs->root;
+		dir->i_count++;
+	}
+
+	if (!inode) {
+		iput(dir);
+		return -ENOENT;
+	}
+	if (!S_ISLNK(inode->i_mode)) {
+		*res_inode = inode;
+		iput(dir);
+		return 0;
+	}
+	if (current->link_count > 5) {
+		iput(inode);
+		iput(dir);
+		return -ELOOP;
+	}
+
+	/* Eek. Short enough. */
+	len = inode->i_size;
+	if (!(buf = kmalloc(len+1, GFP_KERNEL))) {
+		iput(inode);
+		iput(dir);
+		/* correct?  spin? */
+		return -EAGAIN;
+	}
+	error = romfs_copyfrom(inode, buf, inode->u.romfs_i.i_dataoffset, len);
+	if (error != len) {
+		iput(inode);
+		iput(dir);
+		error = -EIO;
+	} else {
+		iput(inode);
+		buf[len] = 0;
+		current->link_count++;
+		error = open_namei(buf, flag, mode, res_inode, dir);
+		current->link_count--;
+	}
+
+	kfree(buf);
+	return error;
+}
+
+/* Mapping from our types to the kernel */
+
+static struct file_operations romfs_file_operations = {
+	NULL,			/* lseek - default */
+        generic_file_read,	/* read */
+	NULL,			/* write - bad */
+	NULL,			/* readdir */
+	NULL,			/* select - default */
+	NULL,			/* ioctl */
+	generic_file_mmap,	/* mmap */
+	NULL,			/* open */
+	NULL,			/* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL			/* revalidate */
+};
+
+static struct inode_operations romfs_file_inode_operations = {
+	&romfs_file_operations,
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	romfs_readpage,		/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap -- not really */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL,			/* smap */
+};
+
+static struct file_operations romfs_dir_operations = {
+	NULL,			/* lseek - default */
+        NULL,			/* read */
+	NULL,			/* write - bad */
+	romfs_readdir,		/* readdir */
+	NULL,			/* select - default */
+	NULL,			/* ioctl */
+	NULL,			/* mmap */
+	NULL,			/* open */
+	NULL,			/* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL			/* revalidate */
+};
+
+/* Merged dir/symlink op table.  readdir/lookup/readlink/follow_link
+ * will protect from type mismatch.
+ */
+
+static struct inode_operations romfs_dirlink_inode_operations = {
+	&romfs_dir_operations,
+	NULL,			/* create */
+	romfs_lookup,		/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	romfs_readlink,		/* readlink */
+	romfs_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL,			/* smap */
+};
+
+static mode_t romfs_modemap[] =
+{
+	0, S_IFDIR, S_IFREG, S_IFLNK+0777,
+	S_IFBLK, S_IFCHR, S_IFSOCK, S_IFIFO
+};
+
+static struct inode_operations *romfs_inoops[] =
+{
+	NULL,				/* hardlink, handled elsewhere */
+	&romfs_dirlink_inode_operations,
+	&romfs_file_inode_operations,
+	&romfs_dirlink_inode_operations,
+	&blkdev_inode_operations,	/* standard handlers */
+	&chrdev_inode_operations,
+	NULL,				/* socket */
+	NULL,				/* fifo */
+};
+
+static void
+romfs_read_inode(struct inode *i)
+{
+	int nextfh, ino;
+	struct romfs_inode ri;
+
+	i->i_op = NULL;
+
+	ino = i->i_ino & ROMFH_MASK;
+
+	/* Loop for finding the real hard link */
+	for(;;) {
+		if (romfs_copyfrom(i, &ri, ino, ROMFH_SIZE) <= 0) {
+			printk("romfs: read error for inode 0x%x\n", ino);
+			return;
+		}
+		nextfh = ntohl(ri.next);
+		if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
+			break;
+
+		ino = ntohl(ri.spec) & ROMFH_MASK;
+	}
+
+	i->i_nlink = 1;		/* Hard to decide.. */
+	i->i_size = ntohl(ri.size);
+	i->i_mtime = i->i_atime = i->i_ctime = 0;
+	i->i_uid = i->i_gid = 0;
+
+	i->i_op = romfs_inoops[nextfh & ROMFH_TYPE];
+
+	/* Precalculate the data offset */
+	ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN);
+	if (ino >= 0)
+		ino = ((ROMFH_SIZE+ino+1+ROMFH_PAD)&ROMFH_MASK);
+	else
+		ino = 0;
+	i->u.romfs_i.i_metasize = ino;
+	i->u.romfs_i.i_dataoffset = ino+(i->i_ino&ROMFH_MASK);
+
+	/* Compute permissions */
+	ino = S_IRUGO|S_IWUSR;
+	ino |= romfs_modemap[nextfh & ROMFH_TYPE];
+	if (nextfh & ROMFH_EXEC) {
+		ino |= S_IXUGO;
+	}
+	i->i_mode = ino;
+
+	if (S_ISFIFO(ino))
+		init_fifo(i);
+	else if (S_ISDIR(ino))
+		i->i_size = i->u.romfs_i.i_metasize;
+	else if (S_ISBLK(ino) || S_ISCHR(ino)) {
+		i->i_mode &= ~(S_IRWXG|S_IRWXO);
+		ino = ntohl(ri.spec);
+		i->i_rdev = MKDEV(ino>>16,ino&0xffff);
+	}
+}
+
+static struct super_operations romfs_ops = {
+	romfs_read_inode,	/* read inode */
+	NULL,			/* notify change */
+	NULL,			/* write inode */
+	NULL,			/* put inode */
+	romfs_put_super,	/* put super */
+	NULL,			/* write super */
+	romfs_statfs,		/* statfs */
+	NULL			/* remount */
+};
+
+static struct file_system_type romfs_fs_type = {
+	romfs_read_super, "romfs", 1, NULL
+};
+
+int
+init_romfs_fs(void)
+{
+	return register_filesystem(&romfs_fs_type);
+}
+
+#ifdef MODULE
+
+/* Yes, works even as a module... :) */
+
+EXPORT_NO_SYMBOLS;
+
+int
+init_module(void)
+{
+	return init_romfs_fs();
+}
+
+void
+cleanup_module(void)
+{
+	unregister_filesystem(&romfs_fs_type);
+}
+#endif
diff -u --recursive --new-file v2.1.20/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.20/linux/fs/smbfs/inode.c	Mon Dec 30 15:39:14 1996
+++ linux/fs/smbfs/inode.c	Fri Jan  3 11:33:26 1997
@@ -5,6 +5,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.20/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.20/linux/fs/sysv/inode.c	Mon Dec 30 15:39:14 1996
+++ linux/fs/sysv/inode.c	Fri Jan  3 11:33:26 1997
@@ -20,6 +20,7 @@
  *  the superblock.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.20/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.20/linux/fs/ufs/ufs_super.c	Tue Dec 31 21:41:08 1996
+++ linux/fs/ufs/ufs_super.c	Fri Jan  3 11:33:26 1997
@@ -20,6 +20,7 @@
  * Gertjan van Wingerde <gertjan@cs.vu.nl>
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.20/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.1.20/linux/fs/vfat/namei.c	Mon Dec 30 15:39:14 1996
+++ linux/fs/vfat/namei.c	Fri Jan  3 11:33:26 1997
@@ -10,6 +10,7 @@
  *    the problem, send a script that demonstrates it.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/Makefile linux/fs/xiafs/Makefile
--- v2.1.20/linux/fs/xiafs/Makefile	Tue Aug 15 15:07:02 1995
+++ linux/fs/xiafs/Makefile	Thu Jan  1 02:00:00 1970
@@ -1,14 +0,0 @@
-#
-# Makefile for the XIAFS filesystem routines.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-O_TARGET := xiafs.o
-O_OBJS   := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o
-M_OBJS   := $(O_TARGET)
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/bitmap.c linux/fs/xiafs/bitmap.c
--- v2.1.20/linux/fs/xiafs/bitmap.c	Sun Nov 26 19:23:10 1995
+++ linux/fs/xiafs/bitmap.c	Thu Jan  1 02:00:00 1970
@@ -1,389 +0,0 @@
-/*
- *  linux/fs/xiafs/bitmap.c
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- *  
- *  Based on Linus' minix/bitmap.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- *  
- *  This software may be redistributed per Linux Copyright.
- */
-
-/* bitmap.c contains the code that handles the inode and block bitmaps */
-
-#include <linux/sched.h>
-#include <linux/locks.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/bitops.h>
-
-#include "xiafs_mac.h"
-
-
-char internal_error_message[]="XIA-FS: internal error %s %d\n"; 
-
-static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit) 
-{
-    /* This routine searches first 0 bit from (start_bit) to (end_bit-1).
-     * If found the bit is set to 1 and the bit # is returned, otherwise,
-     * -1 is returned. Race condition is avoid by using "btsl" and 
-     * "goto repeat".  ---Frank.
-     */
-
-    int end, i, j, tmp;
-    u_long *bmap;
-
-    bmap=(u_long *)bh->b_data;
-    end = end_bit >> 5;
-
-repeat:
-    i=start_bit >> 5;
-    if ( (tmp=(~bmap[i]) & (0xffffffff << (start_bit & 31))) )        
-        goto zone_found;
-    while (++i < end)
-        if (~bmap[i]) {
-	    tmp=~bmap[i];
-	    goto zone_found;
-	}
-    if ( !(tmp=~bmap[i] & ((1 << (end_bit & 31)) -1)) )
-        return -1;
-zone_found:    
-    for (j=0; j < 32; j++)
-        if (tmp & (1 << j))
-	    break;
-    if (set_bit(j,bmap+i)) {
-        start_bit=j + (i << 5) + 1;
-	goto repeat;
-    }
-    mark_buffer_dirty(bh, 1);
-    return j + (i << 5);
-}
-
-static void clear_buf(struct buffer_head * bh) 
-{
-    register int i;
-    register long * lp;
-
-    lp=(long *)bh->b_data;
-    for (i= bh->b_size >> 2; i-- > 0; )
-        *lp++=0;
-}
-
-static void que(struct buffer_head * bmap[], int bznr[], int pos)
-{
-    struct buffer_head * tbh;
-    int tmp;
-    int i;
-    
-    tbh=bmap[pos];
-    tmp=bznr[pos];
-    for (i=pos; i > 0; i--) {
-        bmap[i]=bmap[i-1];
-	bznr[i]=bznr[i-1];
-    }
-    bmap[0]=tbh;
-    bznr[0]=tmp;
-}
-
-#define get_imap_zone(sb, bit_nr, not_que) \
-      	get__map_zone((sb), (sb)->u.xiafs_sb.s_imap_buf, \
-		      (sb)->u.xiafs_sb.s_imap_iznr, \
-		      (sb)->u.xiafs_sb.s_imap_cached, 1, \
-		      (sb)->u.xiafs_sb.s_imap_zones, _XIAFS_IMAP_SLOTS, \
-		      bit_nr, not_que)
-
-#define get_zmap_zone(sb, bit_nr, not_que) \
-      	get__map_zone((sb), (sb)->u.xiafs_sb.s_zmap_buf, \
-		      (sb)->u.xiafs_sb.s_zmap_zznr, \
-		      (sb)->u.xiafs_sb.s_zmap_cached, \
-		      1+(sb)->u.xiafs_sb.s_imap_zones, \
-		      (sb)->u.xiafs_sb.s_zmap_zones, _XIAFS_ZMAP_SLOTS, \
-		      bit_nr, not_que)
-
-static struct buffer_head * 
-get__map_zone(struct super_block *sb, struct buffer_head * bmap_buf[],
-	  int bznr[], u_char cache, int first_zone, 
-	  int bmap_zones, int slots, u_long bit_nr, int * not_que)
-{
-    struct buffer_head * tmp_bh;
-    int z_nr, i;
-
-    z_nr = bit_nr >> XIAFS_BITS_PER_Z_BITS(sb);
-    if (z_nr >= bmap_zones) {
-        printk("XIA-FS: bad inode/zone number (%s %d)\n", WHERE_ERR);
-	return NULL;
-    }
-    if (!cache)
-        return bmap_buf[z_nr];
-    lock_super(sb);
-    for (i=0; i < slots; i++) 
-        if (bznr[i]==z_nr)
-	    break;
-    if (i < slots) {			/* cache hit */
-        if (not_que) {
-	    *not_que=i;
-	    return bmap_buf[i];
-	} else {
-	    que(bmap_buf, bznr, i);
-	    return bmap_buf[0];
-	}
-    }
-    tmp_bh=bread(sb->s_dev, z_nr+first_zone, XIAFS_ZSIZE(sb)); /* cache not hit */
-    if (!tmp_bh) {
-        printk("XIA-FS: read bitmap failed (%s %d)\n", WHERE_ERR);
-	unlock_super(sb);
-	return NULL;
-    }
-    brelse(bmap_buf[slots-1]);
-    bmap_buf[slots-1]=tmp_bh;
-    bznr[slots-1]=z_nr;
-    if (not_que)
-        *not_que=slots-1;
-    else
-        que(bmap_buf, bznr, slots-1);
-    return tmp_bh;
-}
-
-#define xiafs_unlock_super(sb, cache)	if (cache) unlock_super(sb);
-
-#define get_free_ibit(sb, prev_bit) \
-   	get_free__bit(sb, sb->u.xiafs_sb.s_imap_buf, \
-		      sb->u.xiafs_sb.s_imap_iznr, \
-		      sb->u.xiafs_sb.s_imap_cached, \
-		      1, sb->u.xiafs_sb.s_imap_zones, \
-		      _XIAFS_IMAP_SLOTS, prev_bit);
-
-#define get_free_zbit(sb, prev_bit) \
-   	get_free__bit(sb, sb->u.xiafs_sb.s_zmap_buf, \
-		      sb->u.xiafs_sb.s_zmap_zznr, \
-		      sb->u.xiafs_sb.s_zmap_cached, \
-		      1 + sb->u.xiafs_sb.s_imap_zones, \
-		      sb->u.xiafs_sb.s_zmap_zones, \
-		      _XIAFS_ZMAP_SLOTS, prev_bit);
-
-static u_long 
-get_free__bit(struct super_block *sb, struct buffer_head * bmap_buf[],
-	      int bznr[], u_char cache, int first_zone, int bmap_zones, 
-	      int slots, u_long prev_bit)
-{
-    struct buffer_head * bh;
-    int not_done=0;
-    u_long pos, start_bit, end_bit, total_bits;
-    int z_nr, tmp;
- 
-    total_bits=bmap_zones << XIAFS_BITS_PER_Z_BITS(sb); 
-    if (prev_bit >= total_bits)
-        prev_bit=0;
-    pos=prev_bit+1;
-    end_bit=XIAFS_BITS_PER_Z(sb);
-
-    do {
-        if (pos >= total_bits)
-	    pos=0;
-        if (!not_done) {		/* first time */
-	    not_done=1;
-	    start_bit= pos & (end_bit-1);     
-	} else 
-	    start_bit=0;
-	if ( pos < prev_bit && pos+end_bit >= prev_bit) {   /* last time */
-	    not_done=0;
-	    end_bit=prev_bit & (end_bit-1);   /* only here end_bit modified */
-	}
-        bh = get__map_zone(sb, bmap_buf, bznr, cache, first_zone, 
-			   bmap_zones, slots, pos, &z_nr);
-	if (!bh)
-	    return 0;
-	tmp=find_first_zero(bh, start_bit, end_bit);
-	if (tmp >= 0)
-	    break;
-	xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
-	pos=(pos & ~(end_bit-1))+end_bit;
-    } while (not_done);
-
-    if (tmp < 0) 
-        return 0;
-    if (cache)
-      que(bmap_buf, bznr, z_nr);
-    xiafs_unlock_super(sb, cache);
-    return (pos & ~(XIAFS_BITS_PER_Z(sb)-1))+tmp;
-}
-
-void xiafs_free_zone(struct super_block * sb, int d_addr)
-{
-    struct buffer_head * bh;
-    unsigned int bit, offset;
-
-    if (!sb) {
-        printk(INTERN_ERR);
-	return;
-    }
-    if (d_addr < sb->u.xiafs_sb.s_firstdatazone ||
-	d_addr >= sb->u.xiafs_sb.s_nzones) {
-        printk("XIA-FS: bad zone number (%s %d)\n", WHERE_ERR);
-	return;
-    }
-    bh = get_hash_table(sb->s_dev, d_addr, XIAFS_ZSIZE(sb));
-    if (bh)
-        mark_buffer_clean(bh);
-    brelse(bh);
-    bit=d_addr - sb->u.xiafs_sb.s_firstdatazone + 1;
-    bh = get_zmap_zone(sb, bit, NULL);
-    if (!bh)
-	return;
-    offset = bit & (XIAFS_BITS_PER_Z(sb) -1);
-    if (!clear_bit(offset, bh->b_data))
-        printk("XIA-FS: dev %s"
-	       " block bit %u (0x%x) already cleared (%s %d)\n",
-	       kdevname(sb->s_dev), bit, bit, WHERE_ERR);
-    mark_buffer_dirty(bh, 1);
-    xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
-}
-
-int xiafs_new_zone(struct super_block * sb, u_long prev_addr)
-{
-    struct buffer_head * bh;
-    int prev_znr, tmp;
-
-    if (!sb) {
-        printk(INTERN_ERR);
-	return 0;
-    }
-    if (prev_addr < sb->u.xiafs_sb.s_firstdatazone || 
-	prev_addr >= sb->u.xiafs_sb.s_nzones) {
-        prev_addr=sb->u.xiafs_sb.s_firstdatazone;
-    }      
-    prev_znr=prev_addr-sb->u.xiafs_sb.s_firstdatazone+1;
-    tmp=get_free_zbit(sb, prev_znr);
-    if (!tmp)
-        return 0;
-    tmp += sb->u.xiafs_sb.s_firstdatazone -1;
-    if (!(bh = getblk(sb->s_dev, tmp, XIAFS_ZSIZE(sb)))) {
-        printk("XIA-FS: I/O error (%s %d)\n", WHERE_ERR);
-	return 0;
-    }
-    if (bh->b_count != 1) {
-        printk(INTERN_ERR);
-	return 0;
-    }
-    clear_buf(bh);
-    mark_buffer_uptodate(bh, 1);
-    mark_buffer_dirty(bh, 1);
-    brelse(bh);
-    return tmp;
-}
-
-void xiafs_free_inode(struct inode * inode)
-{
-    struct buffer_head * bh;
-    struct super_block * sb;
-    unsigned long ino;
-
-    if (!inode)
-        return;
-    if (!inode->i_dev || inode->i_count!=1
-	|| inode->i_nlink || !inode->i_sb || inode->i_ino < 3
-	|| inode->i_ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
-        printk("XIA-FS: bad inode (%s %d)\n", WHERE_ERR);
-	return;
-    }
-    sb = inode->i_sb;
-    ino = inode->i_ino;
-    bh = get_imap_zone(sb, ino, NULL);
-    if (!bh)
-	return;
-    clear_inode(inode);
-    if (!clear_bit(ino & (XIAFS_BITS_PER_Z(sb)-1), bh->b_data))
-        printk("XIA-FS: dev %s"
-	       "inode bit %ld (0x%lx) already cleared (%s %d)\n",
-	       kdevname(inode->i_dev), ino, ino, WHERE_ERR);
-    mark_buffer_dirty(bh, 1);
-    xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
-}
-
-struct inode * xiafs_new_inode(struct inode * dir)
-{
-    struct super_block * sb;
-    struct inode * inode;
-    ino_t tmp;
-
-    sb = dir->i_sb;
-    if (!dir || !(inode = get_empty_inode()))
-        return NULL;
-    inode->i_sb = sb;
-    inode->i_flags = inode->i_sb->s_flags;
-
-    tmp=get_free_ibit(sb, dir->i_ino); 
-    if (!tmp) {
-        iput(inode);
-	return NULL;
-    }
-    inode->i_count = 1;
-    inode->i_nlink = 1;
-    inode->i_dev = sb->s_dev;
-    inode->i_uid = current->fsuid;
-    inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-    inode->i_dirt = 1;
-    inode->i_ino = tmp;
-    inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-    inode->i_op = NULL;
-    inode->i_blocks = 0;
-    inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
-    insert_inode_hash(inode);
-    return inode;
-}
-
-static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
-
-static u_long count_zone(struct buffer_head * bh)
-{
-    int i, tmp;
-    u_long sum;
-
-    sum=0;
-    for (i=bh->b_size; i-- > 0; ) {
-        tmp=bh->b_data[i];
-        sum += nibblemap[tmp & 0xf] + nibblemap[(tmp & 0xff) >> 4];
-    }
-    return sum;
-} 
-
-unsigned long xiafs_count_free_inodes(struct super_block *sb)
-{
-    struct buffer_head * bh;
-    int izones, i, not_que;
-    u_long sum;
-
-    sum=0;
-    izones=sb->u.xiafs_sb.s_imap_zones;
-    for (i=0; i < izones; i++) {
-        bh=get_imap_zone(sb, i << XIAFS_BITS_PER_Z_BITS(sb), &not_que);
-	if (bh) {
-	    sum += count_zone(bh);
-	    xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
-	}
-    }
-    i=izones << XIAFS_BITS_PER_Z_BITS(sb);
-    return i - sum;
-}
-
-unsigned long xiafs_count_free_zones(struct super_block *sb)
-{
-    struct buffer_head * bh;
-    int zzones, i, not_que;
-    u_long sum;
-
-    sum=0;
-    zzones=sb->u.xiafs_sb.s_zmap_zones;
-    for (i=0; i < zzones; i++) {
-        bh=get_zmap_zone(sb, i << XIAFS_BITS_PER_Z_BITS(sb), &not_que);
-	if (bh) {
-	    sum += count_zone(bh);
-	    xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
-	}
-    }
-    i=zzones << XIAFS_BITS_PER_Z_BITS(sb);
-    return i - sum;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/dir.c linux/fs/xiafs/dir.c
--- v2.1.20/linux/fs/xiafs/dir.c	Tue Oct 29 19:58:46 1996
+++ linux/fs/xiafs/dir.c	Thu Jan  1 02:00:00 1970
@@ -1,131 +0,0 @@
-/*
- *  linux/fs/xiafs/dir.c
- *  
- *  Copyright (C) Q. Frank Xia, 1993.
- *  
- *  Based on Linus' minix/dir.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- *
- *  This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-#include "xiafs_mac.h"
-
-static long xiafs_dir_read(struct inode *, struct file *, char *, unsigned long);
-static int xiafs_readdir(struct inode *, struct file *, void *, filldir_t);
-
-static struct file_operations xiafs_dir_operations = {
-    NULL,		/* lseek - default */
-    xiafs_dir_read,	/* read */
-    NULL,		/* write - bad */
-    xiafs_readdir,	/* readdir */
-    NULL,		/* select - default */
-    NULL,		/* ioctl - default */
-    NULL,		/* mmap */
-    NULL,		/* no special open code */
-    NULL,		/* no special release code */
-    file_fsync		/* default fsync */
-};
-
-/*
- * directories can handle most operations...
- */
-struct inode_operations xiafs_dir_inode_operations = {
-    &xiafs_dir_operations,	/* default directory file-ops */
-    xiafs_create,			/* create */
-    xiafs_lookup,			/* lookup */
-    xiafs_link,			/* link */
-    xiafs_unlink,			/* unlink */
-    xiafs_symlink,		/* symlink */
-    xiafs_mkdir,			/* mkdir */
-    xiafs_rmdir,			/* rmdir */
-    xiafs_mknod,			/* mknod */
-    xiafs_rename,			/* rename */
-    NULL,			/* readlink */
-    NULL,			/* follow_link */
-    NULL,			/* readpage */
-    NULL,			/* writepage */
-    NULL,			/* bmap */
-    xiafs_truncate,		/* truncate */
-    NULL			/* permission */
-};
-
-static long xiafs_dir_read(struct inode * inode, struct file * filp,
-	char * buf, unsigned long count)
-{
-  return -EISDIR;
-}
-
-static int xiafs_readdir(struct inode * inode, struct file * filp,
-	void * dirent, filldir_t filldir)
-{
-    u_int offset, i;
-    struct buffer_head * bh;
-    struct xiafs_direct * de;
-
-    if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
-        return -EBADF;
-    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
-        return -EBADF;
-    while (filp->f_pos < inode->i_size) {
-        offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
-	bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
-	if (!bh) {
-	    filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
-	    continue;
-	}
-	for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) {
-	    de = (struct xiafs_direct *) (bh->b_data + i);
-	    if (!de->d_rec_len)
-		break;
-	    i += de->d_rec_len;
-	}
-	offset = i;
-	de = (struct xiafs_direct *) (offset + bh->b_data);
-	
-	while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
-	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
-		de->d_rec_len < 12 || 
-		(char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
-		de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len ||
-		de->d_name_len > _XIAFS_NAME_LEN ||
-		de->d_name[de->d_name_len] ) {
-	        printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
-		brelse(bh);
-		return 0;
-	    }  
-	    if (de->d_ino) {
-		if (!IS_RDONLY (inode)) {
-		    inode->i_atime=CURRENT_TIME;
-		    inode->i_dirt=1;
-		}
-		if (filldir(dirent, de->d_name, de->d_name_len, filp->f_pos, de->d_ino) < 0) {
-		    brelse(bh);
-		    return 0;
-		}
-	    }
-	    offset += de->d_rec_len;
-	    filp->f_pos += de->d_rec_len;
-	    de = (struct xiafs_direct *) (offset + bh->b_data);
-	}
-	brelse(bh);
-	if (offset > XIAFS_ZSIZE(inode->i_sb)) {
-	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-	    return 0;
-	}
-    }
-    if (!IS_RDONLY (inode)) {
-	inode->i_atime=CURRENT_TIME;		    
-	inode->i_dirt=1;
-    }
-    return 0;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/file.c linux/fs/xiafs/file.c
--- v2.1.20/linux/fs/xiafs/file.c	Tue Oct 29 19:58:46 1996
+++ linux/fs/xiafs/file.c	Thu Jan  1 02:00:00 1970
@@ -1,256 +0,0 @@
-/*
- *  linux/fs/xiafs/file.c
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- *  
- *  Based on Linus' minix/file.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- *
- *  This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/pagemap.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "xiafs_mac.h"
-
-#define	NBUF	32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-static long xiafs_file_read(struct inode *, struct file *, char *, unsigned long);
-static long xiafs_file_write(struct inode *, struct file *, const char *, unsigned long);
-
-/*
- * We have mostly NULL's here: the current defaults are ok for
- * the xiafs filesystem.
- */
-static struct file_operations xiafs_file_operations = {
-    NULL,			/* lseek - default */
-    xiafs_file_read,		/* read */
-    xiafs_file_write,		/* write */
-    NULL,			/* readdir - bad */
-    NULL,			/* select - default */
-    NULL,			/* ioctl - default */
-    generic_file_mmap,		/* mmap */
-    NULL,			/* no special open is needed */
-    NULL,			/* release */
-    xiafs_sync_file		/* fsync */
-};
-
-struct inode_operations xiafs_file_inode_operations = {
-    &xiafs_file_operations,	/* default file operations */
-    NULL,			/* create */
-    NULL,			/* lookup */
-    NULL,			/* link */
-    NULL,			/* unlink */
-    NULL,			/* symlink */
-    NULL,			/* mkdir */
-    NULL,			/* rmdir */
-    NULL,			/* mknod */
-    NULL,			/* rename */
-    NULL,			/* readlink */
-    NULL,			/* follow_link */
-    generic_readpage,		/* readpage */
-    NULL,			/* writepage */
-    xiafs_bmap,			/* bmap */
-    xiafs_truncate,		/* truncate */
-    NULL			/* permission */
-};
-
-static long
-xiafs_file_read(struct inode * inode, struct file * filp, char * buf, unsigned long count)
-{
-    int read, left, chars;
-    int zone_nr, zones, f_zones, offset;
-    int bhrequest, uptodate;
-    struct buffer_head ** bhb, ** bhe;
-    struct buffer_head * bhreq[NBUF];
-    struct buffer_head * buflist[NBUF];
-
-    if (!inode) {
-        printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
-	return -EINVAL;
-    }
-    if (!S_ISREG(inode->i_mode)) {
-        printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
-	return -EINVAL;
-    }
-    offset = filp->f_pos;
-    left = inode->i_size - offset;
-    if (left > count)
-	left = count;
-    if (left <= 0)
-	return 0;
-    read = 0;
-    zone_nr = offset >> XIAFS_ZSIZE_BITS(inode->i_sb);
-    offset &= XIAFS_ZSIZE(inode->i_sb) -1 ;
-    f_zones =(inode->i_size+XIAFS_ZSIZE(inode->i_sb)-1)>>XIAFS_ZSIZE_BITS(inode->i_sb);
-    zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
-    bhb = bhe = buflist;
-    if (filp->f_reada) {
-        if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
-	  zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
-	if (zone_nr + zones > f_zones)
-	    zones = f_zones - zone_nr;
-    }
-
-    /* We do this in a two stage process.  We first try to request
-       as many blocks as we can, then we wait for the first one to
-       complete, and then we try to wrap up as many as are actually
-       done.  This routine is rather generic, in that it can be used
-       in a filesystem by substituting the appropriate function in
-       for getblk.
-       
-       This routine is optimized to make maximum use of the various
-       buffers and caches. */
-
-    do {
-        bhrequest = 0;
-	uptodate = 1;
-	while (zones--) {
-	    *bhb = xiafs_getblk(inode, zone_nr++, 0);
-	    if (*bhb && !buffer_uptodate(*bhb)) {
-	        uptodate = 0;
-		bhreq[bhrequest++] = *bhb;
-	    }
-
-	    if (++bhb == &buflist[NBUF])
-	        bhb = buflist;
-	    
-	    /* If the block we have on hand is uptodate, go ahead
-	       and complete processing. */
-	    if (uptodate)
-	        break;
-	    if (bhb == bhe)
-	        break;
-	}
-
-	/* Now request them all */
-	if (bhrequest)
-	    ll_rw_block(READ, bhrequest, bhreq);
-
-	do { /* Finish off all I/O that has actually completed */
-	    if (*bhe) {
-	        wait_on_buffer(*bhe);
-		if (!buffer_uptodate(*bhe)) {	/* read error? */
-		    brelse(*bhe);
-		    if (++bhe == &buflist[NBUF])
-		      bhe = buflist;
-		    left = 0;
-		    break;
-		}
-	    }
-	    if (left < XIAFS_ZSIZE(inode->i_sb) - offset)
-	        chars = left;
-	    else
-	        chars = XIAFS_ZSIZE(inode->i_sb) - offset;
-	    filp->f_pos += chars;
-	    left -= chars;
-	    read += chars;
-	    if (*bhe) {
-	        copy_to_user(buf,offset+(*bhe)->b_data,chars);
-		brelse(*bhe);
-		buf += chars;
-	    } else {
-	        while (chars-->0)
-		    put_user(0,buf++);
-	    }
-	    offset = 0;
-	    if (++bhe == &buflist[NBUF])
-	        bhe = buflist;
-	} while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
-    } while (left > 0);
-
-/* Release the read-ahead blocks */
-    while (bhe != bhb) {
-        brelse(*bhe);
-	if (++bhe == &buflist[NBUF])
-	    bhe = buflist;
-    };
-    if (!read)
-        return -EIO;
-    filp->f_reada = 1;
-    if (!IS_RDONLY (inode)) {
-	inode->i_atime = CURRENT_TIME;
-	inode->i_dirt = 1;
-    }
-    return read;
-}
-
-static long
-xiafs_file_write(struct inode * inode, struct file * filp, const char * buf, unsigned long count)
-{
-    off_t pos;
-    int written, c;
-    struct buffer_head * bh;
-    char * cp;
-
-    if (!inode) {
-        printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
-	return -EINVAL;
-    }
-    if (!S_ISREG(inode->i_mode)) {
-        printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
-	return -EINVAL;
-    }
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
-    if (filp->f_flags & O_APPEND)
-        pos = inode->i_size;
-    else
-        pos = filp->f_pos;
-    written = 0;
-    while (written < count) {
-        bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
-	if (!bh) {
-	    if (!written)
-	        written = -ENOSPC;
-	    break;
-	}
-	c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
-	if (c > count-written)
-	    c = count-written;
-	if (c != XIAFS_ZSIZE(inode->i_sb) && !buffer_uptodate(bh)) {
-	    ll_rw_block(READ, 1, &bh);
-	    wait_on_buffer(bh);
-	    if (!buffer_uptodate(bh)) {
-	        brelse(bh);
-		if (!written)
-		    written = -EIO;
-		break;
-	    }
-	}
-	cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
-	copy_from_user(cp,buf,c);
-	update_vm_cache(inode,pos,cp,c);
-	pos += c;
-	if (pos > inode->i_size) {
-	    inode->i_size = pos;
-	    inode->i_dirt = 1;
-	}
-	written += c;
-	buf += c;
-	mark_buffer_uptodate(bh, 1);
-	mark_buffer_dirty(bh, 0);
-	brelse(bh);
-    }
-    inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-    filp->f_pos = pos;
-    inode->i_dirt = 1;
-
-    return written;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/fsync.c linux/fs/xiafs/fsync.c
--- v2.1.20/linux/fs/xiafs/fsync.c	Tue Oct 29 19:58:47 1996
+++ linux/fs/xiafs/fsync.c	Thu Jan  1 02:00:00 1970
@@ -1,159 +0,0 @@
-/*
- *  linux/fs/xiafs/fsync.c
- *
- *  Changes Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
- *  from
- *  Copyright (C) 1991, 1992 Linus Torvalds
- *
- *  xiafs fsync primitive
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/locks.h>
-
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "xiafs_mac.h"
-
-
-#define blocksize (XIAFS_ZSIZE(inode->i_sb))
-#define addr_per_block (XIAFS_ADDRS_PER_Z(inode->i_sb))
-
-static int sync_block (struct inode * inode, unsigned long * block, int wait)
-{
-	struct buffer_head * bh;
-	int tmp;
-	
-	if (!*block)
-		return 0;
-	tmp = *block;
-	bh = get_hash_table(inode->i_dev, *block, blocksize);
-	if (!bh)
-		return 0;
-	if (*block != tmp) {
-		brelse (bh);
-		return 1;
-	}
-	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
-		brelse(bh);
-		return -1;
-	}
-	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
-	{
-		brelse(bh);
-		return 0;
-	}
-	ll_rw_block(WRITE, 1, &bh);
-	bh->b_count--;
-	return 0;
-}
-
-static int sync_iblock (struct inode * inode, unsigned long * iblock, 
-			struct buffer_head **bh, int wait) 
-{
-	int rc, tmp;
-	
-	*bh = NULL;
-	tmp = *iblock;
-	if (!tmp)
-		return 0;
-	rc = sync_block (inode, iblock, wait);
-	if (rc)
-		return rc;
-	*bh = bread(inode->i_dev, tmp, blocksize);
-	if (tmp != *iblock) {
-		brelse(*bh);
-		*bh = NULL;
-		return 1;
-	}
-	if (!*bh)
-		return -1;
-	return 0;
-}
-
-
-static int sync_direct(struct inode *inode, int wait)
-{
-	int i;
-	int rc, err = 0;
-
-	for (i = 0; i < 8; i++) {
-		rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	return err;
-}
-
-static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
-{
-	int i;
-	struct buffer_head * ind_bh;
-	int rc, err = 0;
-
-	rc = sync_iblock (inode, iblock, &ind_bh, wait);
-	if (rc || !ind_bh)
-		return rc;
-	
-	for (i = 0; i < addr_per_block; i++) {
-		rc = sync_block (inode, 
-				 ((unsigned long *) ind_bh->b_data) + i,
-				 wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(ind_bh);
-	return err;
-}
-
-static int sync_dindirect(struct inode *inode, unsigned long *diblock,
-			  int wait)
-{
-	int i;
-	struct buffer_head * dind_bh;
-	int rc, err = 0;
-
-	rc = sync_iblock (inode, diblock, &dind_bh, wait);
-	if (rc || !dind_bh)
-		return rc;
-	
-	for (i = 0; i < addr_per_block; i++) {
-		rc = sync_indirect (inode,
-				    ((unsigned long *) dind_bh->b_data) + i,
-				    wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(dind_bh);
-	return err;
-}
-
-int xiafs_sync_file(struct inode * inode, struct file * file)
-{
-	int wait, err = 0;
-	
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	     S_ISLNK(inode->i_mode)))
-		return -EINVAL;
-	for (wait=0; wait<=1; wait++)
-	{
-		err |= sync_direct(inode, wait);
-		err |= sync_indirect(inode, &inode->u.xiafs_i.i_ind_zone, wait);
-		err |= sync_dindirect(inode, &inode->u.xiafs_i.i_dind_zone, wait);
-	}
-	err |= xiafs_sync_inode (inode);
-	return (err < 0) ? -EIO : 0;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c
--- v2.1.20/linux/fs/xiafs/inode.c	Mon Dec 30 15:39:14 1996
+++ linux/fs/xiafs/inode.c	Thu Jan  1 02:00:00 1970
@@ -1,538 +0,0 @@
-/*
- *  linux/fs/xiafs/inode.c
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- *
- *  Based on Linus' minix/inode.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- *
- *  This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/xia_fs.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "xiafs_mac.h"
-
-static u_long random_nr;
-
-void xiafs_put_inode(struct inode *inode)
-{
-    if (inode->i_nlink)
-        return;
-    inode->i_size = 0;
-    xiafs_truncate(inode);
-    xiafs_free_inode(inode);
-}
-
-void xiafs_put_super(struct super_block *sb)
-{
-    int i;
-
-    lock_super(sb);
-    sb->s_dev = 0;
-    for(i = 0 ; i < _XIAFS_IMAP_SLOTS ; i++)
-        brelse(sb->u.xiafs_sb.s_imap_buf[i]);
-    for(i = 0 ; i < _XIAFS_ZMAP_SLOTS ; i++)
-        brelse(sb->u.xiafs_sb.s_zmap_buf[i]);
-    unlock_super(sb);
-    MOD_DEC_USE_COUNT;
-}
-
-static struct super_operations xiafs_sops = {
-    xiafs_read_inode,
-    NULL,
-    xiafs_write_inode,
-    xiafs_put_inode,
-    xiafs_put_super,
-    NULL,
-    xiafs_statfs,
-    NULL
-};
-
-struct super_block *xiafs_read_super(struct super_block *s, void *data,
-				     int silent)
-{
-    struct buffer_head *bh;
-    struct xiafs_super_block *sp;
-    int i, z;
-    kdev_t dev;
-
-    MOD_INC_USE_COUNT;
-    dev = s->s_dev;
-    lock_super(s);
-
-    set_blocksize(dev, BLOCK_SIZE);
-
-    if (!(bh = bread(dev, 0, BLOCK_SIZE))) {
-        s->s_dev = 0;
-	unlock_super(s);
-	printk("XIA-FS: read super_block failed (%s %d)\n", WHERE_ERR);
-	MOD_DEC_USE_COUNT;
-	return NULL;
-    }
-    sp = (struct xiafs_super_block *) bh->b_data;
-    s->s_magic = sp->s_magic;
-    if (s->s_magic != _XIAFS_SUPER_MAGIC) {
-        s->s_dev = 0;
-	unlock_super(s);
-	brelse(bh);
-	if (!silent)
-		printk("VFS: Can't find a xiafs filesystem on dev "
-		       "%s.\n", kdevname(dev));
-	MOD_DEC_USE_COUNT;
-	return NULL;
-    }
-    s->s_blocksize = sp->s_zone_size;
-    s->s_blocksize_bits = 10 + sp->s_zone_shift;
-    if (s->s_blocksize != BLOCK_SIZE &&
-	(s->s_blocksize == 1024 || s->s_blocksize == 2048 ||
-	 s->s_blocksize == 4096)) {
-      brelse(bh);
-      set_blocksize(dev, s->s_blocksize);
-      bh = bread (dev, 0,  s->s_blocksize);
-      if(!bh) {
-	MOD_DEC_USE_COUNT;
-	return NULL;
-      }
-      sp = (struct xiafs_super_block *) (((char *)bh->b_data) + BLOCK_SIZE) ;
-    };
-    s->u.xiafs_sb.s_nzones = sp->s_nzones;
-    s->u.xiafs_sb.s_ninodes = sp->s_ninodes;
-    s->u.xiafs_sb.s_ndatazones = sp->s_ndatazones;
-    s->u.xiafs_sb.s_imap_zones = sp->s_imap_zones;
-    s->u.xiafs_sb.s_zmap_zones = sp->s_zmap_zones;
-    s->u.xiafs_sb.s_firstdatazone = sp->s_firstdatazone;
-    s->u.xiafs_sb.s_zone_shift = sp->s_zone_shift;
-    s->u.xiafs_sb.s_max_size = sp->s_max_size;
-    brelse(bh);
-    for (i=0;i < _XIAFS_IMAP_SLOTS;i++) {
-        s->u.xiafs_sb.s_imap_buf[i] = NULL;
-	s->u.xiafs_sb.s_imap_iznr[i] = -1;
-    }
-    for (i=0;i < _XIAFS_ZMAP_SLOTS;i++) {
-        s->u.xiafs_sb.s_zmap_buf[i] = NULL;
-	s->u.xiafs_sb.s_zmap_zznr[i] = -1;
-    }
-    z=1;
-    if ( s->u.xiafs_sb.s_imap_zones > _XIAFS_IMAP_SLOTS )
-        s->u.xiafs_sb.s_imap_cached=1;
-    else {
-        s->u.xiafs_sb.s_imap_cached=0;
-	for (i=0 ; i < s->u.xiafs_sb.s_imap_zones ; i++) {
-	    if (!(s->u.xiafs_sb.s_imap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s))))
-	        goto xiafs_read_super_fail;
-	    s->u.xiafs_sb.s_imap_iznr[i]=i;
-	}
-    }
-    if ( s->u.xiafs_sb.s_zmap_zones > _XIAFS_ZMAP_SLOTS )
-        s->u.xiafs_sb.s_zmap_cached=1;
-    else {
-        s->u.xiafs_sb.s_zmap_cached=0;
-	for (i=0 ; i < s->u.xiafs_sb.s_zmap_zones ; i++) {
-	    if (!(s->u.xiafs_sb.s_zmap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s))))
-	        goto xiafs_read_super_fail;
-	    s->u.xiafs_sb.s_zmap_zznr[i]=i;
-	}
-    }
-    /* set up enough so that it can read an inode */
-    s->s_dev = dev;
-    s->s_op = &xiafs_sops;
-    s->s_mounted = iget(s, _XIAFS_ROOT_INO);
-    if (!s->s_mounted)
-        goto xiafs_read_super_fail;
-    unlock_super(s);
-    random_nr=CURRENT_TIME;
-    return s;
-
-xiafs_read_super_fail:
-    for(i=0; i < _XIAFS_IMAP_SLOTS; i++)
-        brelse(s->u.xiafs_sb.s_imap_buf[i]);
-    for(i=0; i < _XIAFS_ZMAP_SLOTS; i++)
-        brelse(s->u.xiafs_sb.s_zmap_buf[i]);
-    s->s_dev = 0;
-    unlock_super(s);
-    printk("XIA-FS: read bitmaps failed (%s %d)\n", WHERE_ERR);
-    MOD_DEC_USE_COUNT;
-    return NULL;
-}
-
-void xiafs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
-	struct statfs tmp;
-
-	tmp.f_type = _XIAFS_SUPER_MAGIC;
-	tmp.f_bsize = XIAFS_ZSIZE(sb);
-	tmp.f_blocks = sb->u.xiafs_sb.s_ndatazones;
-	tmp.f_bfree = xiafs_count_free_zones(sb);
-	tmp.f_bavail = tmp.f_bfree;
-	tmp.f_files = sb->u.xiafs_sb.s_ninodes;
-	tmp.f_ffree = xiafs_count_free_inodes(sb);
-	tmp.f_namelen = _XIAFS_NAME_LEN;
-	copy_to_user(buf, &tmp, bufsiz);
-}
-
-static int zone_bmap(struct buffer_head * bh, int nr)
-{
-    int tmp;
-
-    if (!bh)
-        return 0;
-    tmp = ((u_long *) bh->b_data)[nr];
-    brelse(bh);
-    return tmp;
-}
-
-int xiafs_bmap(struct inode * inode,int zone)
-{
-    int i;
-
-    if (zone < 0) {
-        printk("XIA-FS: block < 0 (%s %d)\n", WHERE_ERR);
-	return 0;
-    }
-    if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) {
-        printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
-	return 0;
-    }
-    if (!IS_RDONLY (inode)) {
-	inode->i_atime = CURRENT_TIME;
-	inode->i_dirt = 1;
-    }
-    if (zone < 8)
-        return inode->u.xiafs_i.i_zone[zone];
-    zone -= 8;
-    if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) {
-        i = inode->u.xiafs_i.i_ind_zone;
-	if (i)
-	    i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)), zone);
-	return i;
-    }
-    zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
-    i = inode->u.xiafs_i.i_dind_zone;
-    if (i)
-      i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)),
-		    zone >> XIAFS_ADDRS_PER_Z_BITS(inode->i_sb));
-    if (i)
-      i= zone_bmap(bread(inode->i_dev,i, XIAFS_ZSIZE(inode->i_sb)),
-		   zone & (XIAFS_ADDRS_PER_Z(inode->i_sb)-1));
-    return i;
-}
-
-static u_long get_prev_addr(struct inode * inode, int zone)
-{
-    u_long tmp;
-
-    if (zone > 0)
-        while (--zone >= 0)		/* only files with holes suffer */
-	    if ((tmp=xiafs_bmap(inode, zone)))
-	        return tmp;
-    random_nr=(random_nr+23)%inode->i_sb->u.xiafs_sb.s_ndatazones;
-    return random_nr + inode->i_sb->u.xiafs_sb.s_firstdatazone;
-}
-
-static struct buffer_head *
-dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr)
-{
-    int tmp;
-    struct buffer_head * result;
-
-repeat:
-    if ((tmp=*lp)) {
-        result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-	if (tmp == *lp)
-	    return result;
-	brelse(result);
-	goto repeat;
-    }
-    if (!create)
-        return NULL;
-    tmp = xiafs_new_zone(inode->i_sb, prev_addr);
-    if (!tmp)
-        return NULL;
-    result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-    if (*lp) {
-        xiafs_free_zone(inode->i_sb, tmp);
-        brelse(result);
-        goto repeat;
-    }
-    *lp = tmp;
-    inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
-    return result;
-}
-
-static struct buffer_head *
-indt_getblk(struct inode * inode, struct buffer_head * bh,
-	    int nr, int create, u_long prev_addr)
-{
-    int tmp;
-    u_long *lp;
-    struct buffer_head * result;
-
-    if (!bh)
-        return NULL;
-    if (!buffer_uptodate(bh)) {
-        ll_rw_block(READ, 1, &bh);
-	wait_on_buffer(bh);
-	if (!buffer_uptodate(bh)) {
-	    brelse(bh);
-	    return NULL;
-	}
-    }
-    lp = nr + (u_long *) bh->b_data;
-repeat:
-    if ((tmp=*lp)) {
-        result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-	if (tmp == *lp) {
-	    brelse(bh);
-	    return result;
-	}
-	brelse(result);
-	goto repeat;
-    }
-    if (!create) {
-        brelse(bh);
-	return NULL;
-    }
-    tmp = xiafs_new_zone(inode->i_sb, prev_addr);
-    if (!tmp) {
-        brelse(bh);
-	return NULL;
-    }
-    result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-    if (*lp) {
-        xiafs_free_zone(inode->i_sb, tmp);
-	brelse(result);
-	goto repeat;
-    }
-    *lp = tmp;
-    inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
-    mark_buffer_dirty(bh, 1);
-    brelse(bh);
-    return result;
-}
-
-struct buffer_head * xiafs_getblk(struct inode * inode, int zone, int create)
-{
-    struct buffer_head * bh;
-    u_long prev_addr=0;
-
-    if (zone<0) {
-        printk("XIA-FS: zone < 0 (%s %d)\n", WHERE_ERR);
-	return NULL;
-    }
-    if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) {
-	if (!create)
-            printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
-	return NULL;
-    }
-    if (create)
-        prev_addr=get_prev_addr(inode, zone);
-    if (zone < 8)
-        return dt_getblk(inode, zone+inode->u.xiafs_i.i_zone, create, prev_addr);
-    zone -= 8;
-    if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) {
-        bh = dt_getblk(inode, &(inode->u.xiafs_i.i_ind_zone), create, prev_addr);
-	bh = indt_getblk(inode, bh, zone, create, prev_addr);
-	return bh;
-    }
-    zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
-    bh = dt_getblk(inode, &(inode->u.xiafs_i.i_dind_zone), create, prev_addr);
-    bh = indt_getblk(inode, bh, zone>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb),
-		     create, prev_addr);
-    bh = indt_getblk(inode, bh, zone&(XIAFS_ADDRS_PER_Z(inode->i_sb)-1),
-		     create, prev_addr);
-    return bh;
-}
-
-struct buffer_head * xiafs_bread(struct inode * inode, int zone, int create)
-{
-    struct buffer_head * bh;
-
-    bh = xiafs_getblk(inode, zone, create);
-    if (!bh || buffer_uptodate(bh))
-        return bh;
-    ll_rw_block(READ, 1, &bh);
-    wait_on_buffer(bh);
-    if (buffer_uptodate(bh))
-        return bh;
-    brelse(bh);
-    return NULL;
-}
-
-void xiafs_read_inode(struct inode * inode)
-{
-    struct buffer_head * bh;
-    struct xiafs_inode * raw_inode;
-    int zone;
-    ino_t ino;
-
-    ino = inode->i_ino;
-    inode->i_op = NULL;
-    inode->i_mode=0;
-    if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
-    	printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
-    	return;
-    }
-    zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
-		inode->i_sb->u.xiafs_sb.s_zmap_zones +
-		(ino-1)/ XIAFS_INODES_PER_Z(inode->i_sb);
-    if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
-    	printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
-    	return;
-    }
-    raw_inode = ((struct xiafs_inode *) bh->b_data) +
-                 ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) - 1));
-    inode->i_mode = raw_inode->i_mode;
-    inode->i_uid = raw_inode->i_uid;
-    inode->i_gid = raw_inode->i_gid;
-    inode->i_nlink = raw_inode->i_nlinks;
-    inode->i_size = raw_inode->i_size;
-    inode->i_mtime = raw_inode->i_mtime;
-    inode->i_atime = raw_inode->i_atime;
-    inode->i_ctime = raw_inode->i_ctime;
-    inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
-    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-        inode->i_blocks=0;
-        inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
-    } else {
-        XIAFS_GET_BLOCKS(raw_inode, inode->i_blocks);
-        for (zone = 0; zone < 8; zone++)
-	    inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[zone] & 0xffffff;
-	inode->u.xiafs_i.i_ind_zone       = raw_inode->i_ind_zone   & 0xffffff;
-	inode->u.xiafs_i.i_dind_zone      = raw_inode->i_dind_zone  & 0xffffff;
-    }
-    brelse(bh);
-    if (S_ISREG(inode->i_mode))
-        inode->i_op = &xiafs_file_inode_operations;
-    else if (S_ISDIR(inode->i_mode))
-        inode->i_op = &xiafs_dir_inode_operations;
-    else if (S_ISLNK(inode->i_mode))
-        inode->i_op = &xiafs_symlink_inode_operations;
-    else if (S_ISCHR(inode->i_mode))
-        inode->i_op = &chrdev_inode_operations;
-    else if (S_ISBLK(inode->i_mode))
-        inode->i_op = &blkdev_inode_operations;
-    else if (S_ISFIFO(inode->i_mode))
-    	init_fifo(inode);
-}
-
-static struct buffer_head *  xiafs_update_inode(struct inode * inode)
-{
-    struct buffer_head * bh;
-    struct xiafs_inode * raw_inode;
-    int zone;
-    ino_t ino;
-
-    if (IS_RDONLY (inode)) {
-	printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR);
-	inode->i_dirt = 0;
-	return 0;
-    }
-
-    ino = inode->i_ino;
-    if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
-    	printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
-    	inode->i_dirt=0;
-    	return 0;
-    }
-    zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
-                inode->i_sb->u.xiafs_sb.s_zmap_zones +
-		(ino-1) / XIAFS_INODES_PER_Z(inode->i_sb);
-    if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
-        printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
-	inode->i_dirt=0;
-	return 0;
-    }
-    raw_inode = ((struct xiafs_inode *)bh->b_data) +
-                ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) -1));
-    raw_inode->i_mode = inode->i_mode;
-    raw_inode->i_uid = inode->i_uid;
-    raw_inode->i_gid = inode->i_gid;
-    raw_inode->i_nlinks = inode->i_nlink;
-    raw_inode->i_size = inode->i_size;
-    raw_inode->i_atime = inode->i_atime;
-    raw_inode->i_ctime = inode->i_ctime;
-    raw_inode->i_mtime = inode->i_mtime;
-    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-        raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
-    else {
-        XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks);
-        for (zone = 0; zone < 8; zone++)
-	    raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000)
-	                             | (inode->u.xiafs_i.i_zone[zone] & 0xffffff);
-	raw_inode->i_ind_zone = (raw_inode->i_ind_zone & 0xff000000)
-	                             | (inode->u.xiafs_i.i_ind_zone   & 0xffffff);
-	raw_inode->i_dind_zone = (raw_inode->i_dind_zone & 0xff000000)
-	                             | (inode->u.xiafs_i.i_dind_zone  & 0xffffff);
-    }
-    inode->i_dirt=0;
-    mark_buffer_dirty(bh, 1);
-    return bh;
-}
-
-
-void xiafs_write_inode(struct inode * inode)
-{
-    struct buffer_head * bh;
-    bh = xiafs_update_inode(inode);
-    brelse (bh);
-}
-
-int xiafs_sync_inode (struct inode *inode)
-{
-    int err = 0;
-    struct buffer_head *bh;
-
-    bh = xiafs_update_inode(inode);
-    if (bh && buffer_dirty(bh))
-    {
-    	ll_rw_block(WRITE, 1, &bh);
-    	wait_on_buffer(bh);
-    	if (buffer_req(bh) && !buffer_uptodate(bh))
-    	{
-    	    printk ("IO error syncing xiafs inode [%s:%lu]\n",
-		    kdevname(inode->i_dev), inode->i_ino);
-    	    err = -1;
-    	}
-    }
-    else if (!bh)
-    	err = -1;
-    brelse (bh);
-    return err;
-}
-
-/* Every kernel module contains stuff like this. */
-
-static struct file_system_type xiafs_fs_type = {
-	xiafs_read_super, "xiafs", 1, NULL
-};
-
-int init_xiafs_fs(void)
-{
-        return register_filesystem(&xiafs_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
-	return init_xiafs_fs();
-}
-
-void cleanup_module(void)
-{
-	unregister_filesystem(&xiafs_fs_type);
-}
-
-#endif
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/namei.c linux/fs/xiafs/namei.c
--- v2.1.20/linux/fs/xiafs/namei.c	Tue Oct 29 19:58:47 1996
+++ linux/fs/xiafs/namei.c	Thu Jan  1 02:00:00 1970
@@ -1,854 +0,0 @@
-/*
- *  Linux/fs/xiafs/namei.c
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- *  
- *  Based on Linus' minix/namei.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- * 
- *  This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/sched.h>
-#include <linux/xia_fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-#include <asm/uaccess.h>
-
-#include "xiafs_mac.h"
-
-#define RNDUP4(x)	((3+(u_long)(x)) & ~3)
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use xiafs_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, xiafs_match returns 1 for success, 0 for failure.
- */
-static int xiafs_match(int len, const char * name, struct xiafs_direct * dep)
-{
-    int i;
-
-    if (!dep || !dep->d_ino || len > _XIAFS_NAME_LEN)
-        return 0;
-    /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
-    if (!len && (dep->d_name[0]=='.') && (dep->d_name[1]=='\0'))
-        return 1;
-    if (len != dep->d_name_len)
-        return 0;
-    for (i=0; i < len; i++)
-        if (*name++ != dep->d_name[i])
-	    return 0;
-    return 1;
-}
-
-/*
- *	xiafs_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- */
-static struct buffer_head * 
-xiafs_find_entry(struct inode * inode, const char * name, int namelen, 
-	       struct xiafs_direct ** res_dir, struct xiafs_direct ** res_pre)
-{
-    int i, zones, pos;
-    struct buffer_head * bh;
-    struct xiafs_direct * dep, * dep_pre;
-
-    *res_dir = NULL;
-    if (!inode)
-        return NULL;
-    if (namelen > _XIAFS_NAME_LEN)
-        return NULL;
-
-    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1)) {
-        printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR);
-	return NULL;
-    }
-    zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
-    for (i=0; i < zones; i++ ) {
-        bh = xiafs_bread(inode, i, 0);
-	if (!bh)
-	    continue;
-	dep_pre=dep=(struct xiafs_direct *)bh->b_data;
-	if (!i && (dep->d_rec_len != 12 || !dep->d_ino || 
-		   dep->d_name_len != 1 || strcmp(dep->d_name, "."))) {
-	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-	    brelse(bh);
-	    return NULL;
-	}
-	pos = 0;
-	while ( pos < XIAFS_ZSIZE(inode->i_sb) ) {
-	    if (dep->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
-		dep->d_rec_len < 12 || 
-		dep->d_rec_len+(char *)dep > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
-		dep->d_name_len + 8 > dep->d_rec_len || dep->d_name_len <= 0 ||
-		dep->d_name[dep->d_name_len] ) {
-	        brelse(bh);
-		return NULL;
-	    }
-	    if (xiafs_match(namelen, name, dep)) {
-	        *res_dir=dep;
-		if (res_pre) 
-		    *res_pre=dep_pre;
-		return bh;
-	    }
-	    pos += dep->d_rec_len;
-	    dep_pre=dep;
-	    dep=(struct xiafs_direct *)(bh->b_data + pos);
-	}
-	brelse(bh);
-	if (pos > XIAFS_ZSIZE(inode->i_sb)) {
-	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-	    return NULL;
-	}
-    }
-    return NULL;
-}
-
-int xiafs_lookup(struct inode * dir, const char * name, int len,
-	       struct inode ** result)
-{
-    int ino;
-    struct xiafs_direct * dep;
-    struct buffer_head * bh;
-
-    *result = NULL;
-    if (!dir)
-        return -ENOENT;
-    if (!S_ISDIR(dir->i_mode)) {
-        iput(dir);
-	return -ENOENT;
-    }
-    if (!(bh = xiafs_find_entry(dir, name, len, &dep, NULL))) {
-        iput(dir);
-	return -ENOENT;
-    }
-    ino = dep->d_ino;
-    brelse(bh);
-    if (!(*result = iget(dir->i_sb, ino))) {
-        iput(dir);
-	return -EACCES;
-    }
-    iput(dir);
-    return 0;
-}
-
-/*
- *	xiafs_add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as xiafs_find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * xiafs_add_entry(struct inode * dir,
-	const char * name, int namelen, struct xiafs_direct ** res_dir, 
-	struct xiafs_direct ** res_pre)
-{
-    int i, pos, offset;
-    struct buffer_head * bh;
-    struct xiafs_direct * de, * de_pre;
-
-    *res_dir = NULL;
-    if (!dir || !namelen || namelen > _XIAFS_NAME_LEN)
-        return NULL;
-
-    if (dir->i_size & (XIAFS_ZSIZE(dir->i_sb) - 1)) {
-        printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR);
-	return NULL;
-    }
-    pos=0;
-    for ( ; ; ) {
-        bh =  xiafs_bread(dir, pos >> XIAFS_ZSIZE_BITS(dir->i_sb), pos ? 1:0);
-	if (!bh)
-	    return NULL;
-	de_pre=de=(struct xiafs_direct *)bh->b_data;
-	if (!pos) {
-	    if (de->d_rec_len != 12 || !de->d_ino || de->d_name_len != 1 ||
-		strcmp(de->d_name, ".")) {
-	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-		brelse(bh);
-		return NULL;
-	    }
-	    offset = 12;
-	    de_pre=de=(struct xiafs_direct *)(bh->b_data+12);
-	} else
-	    offset = 0;
-	while (offset < XIAFS_ZSIZE(dir->i_sb)) {
-	    if (pos >= dir->i_size) {
-	        de->d_ino=0;
-		de->d_name_len=0;
-		de->d_name[0]=0;
-		de->d_rec_len=XIAFS_ZSIZE(dir->i_sb);
-		dir->i_size += XIAFS_ZSIZE(dir->i_sb);
-		dir->i_dirt = 1;
-	    } else {
-	        if (de->d_ino > dir->i_sb->u.xiafs_sb.s_ninodes ||
-		    de->d_rec_len < 12 || 
-		    (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(dir->i_sb) ||
-		    de->d_name_len + 8 > de->d_rec_len ||
-		    de->d_name[de->d_name_len]) {
-		    printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
-		    brelse(bh);
-		    return NULL;
-		}
-		if (de->d_ino &&
-		    RNDUP4(de->d_name_len)+RNDUP4(namelen)+16<=de->d_rec_len) {
-		    i=RNDUP4(de->d_name_len)+8;
-		    de_pre=de;
-		    de=(struct xiafs_direct *)(i+(u_char *)de_pre);
-		    de->d_ino=0;
-		    de->d_rec_len=de_pre->d_rec_len-i;
-		    de_pre->d_rec_len=i;
-		}
-	    }
-	    if (!de->d_ino && RNDUP4(namelen)+8 <= de->d_rec_len) {
-		/*
-		 * XXX all times should be set by caller upon successful
-		 * completion.
-		 */
-	        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-		dir->i_dirt = 1;
-		memcpy(de->d_name, name, namelen);
-		de->d_name[namelen]=0;
-		de->d_name_len=namelen;
-		mark_buffer_dirty(bh, 1);
-		*res_dir = de;
-		if (res_pre)
-		    *res_pre = de_pre;
-		return bh;
-	    }
-	    offset+=de->d_rec_len;
-	    de_pre=de;
-	    de=(struct xiafs_direct *)(bh->b_data+offset);
-	}
-	brelse(bh);
-	if (offset > XIAFS_ZSIZE(dir->i_sb)) {
-	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-	    return NULL;
-	}
-	pos+=XIAFS_ZSIZE(dir->i_sb);
-    }
-    return NULL;
-}
-
-int xiafs_create(struct inode * dir, const char * name, int len, int mode,
-	struct inode ** result)
-{
-    struct inode * inode;
-    struct buffer_head * bh;
-    struct xiafs_direct * de;
-
-    *result = NULL;
-    if (!dir)
-        return -ENOENT;
-    inode = xiafs_new_inode(dir);
-    if (!inode) {
-        iput(dir);
-	return -ENOSPC;
-    }
-    inode->i_op = &xiafs_file_inode_operations;
-    inode->i_mode = mode;
-    inode->i_dirt = 1;
-    bh = xiafs_add_entry(dir, name, len, &de, NULL);
-    if (!bh) {
-        inode->i_nlink--;
-	inode->i_dirt = 1;
-	iput(inode);
-	iput(dir);
-	return -ENOSPC;
-    }
-    de->d_ino = inode->i_ino;
-    mark_buffer_dirty(bh, 1);
-    brelse(bh);
-    iput(dir);
-    *result = inode;
-    return 0;
-}
-
-int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev)
-{
-    struct inode * inode;
-    struct buffer_head * bh;
-    struct xiafs_direct * de;
-
-    if (!dir)
-        return -ENOENT;
-    bh = xiafs_find_entry(dir,name,len,&de, NULL);
-    if (bh) {
-        brelse(bh);
-	iput(dir);
-	return -EEXIST;
-    }
-    inode = xiafs_new_inode(dir);
-    if (!inode) {
-        iput(dir);
-	return -ENOSPC;
-    }
-    inode->i_uid = current->fsuid;
-    inode->i_mode = mode;
-    inode->i_op = NULL;
-    if (S_ISREG(inode->i_mode))
-        inode->i_op = &xiafs_file_inode_operations;
-    else if (S_ISDIR(inode->i_mode)) {
-        inode->i_op = &xiafs_dir_inode_operations;
-	if (dir->i_mode & S_ISGID)
-	    inode->i_mode |= S_ISGID;
-    }
-    else if (S_ISLNK(inode->i_mode))
-        inode->i_op = &xiafs_symlink_inode_operations;
-    else if (S_ISCHR(inode->i_mode))
-        inode->i_op = &chrdev_inode_operations;
-    else if (S_ISBLK(inode->i_mode))
-        inode->i_op = &blkdev_inode_operations;
-    else if (S_ISFIFO(inode->i_mode))
-    	init_fifo(inode);
-    if (S_ISBLK(mode) || S_ISCHR(mode))
-        inode->i_rdev = to_kdev_t(rdev);
-    inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
-    inode->i_dirt = 1;
-    bh = xiafs_add_entry(dir, name, len, &de, NULL);
-    if (!bh) {
-        inode->i_nlink--;
-	inode->i_dirt = 1;
-	iput(inode);
-	iput(dir);
-	return -ENOSPC;
-    }
-    de->d_ino = inode->i_ino;
-    mark_buffer_dirty(bh, 1);
-    brelse(bh);
-    iput(dir);
-    iput(inode);
-    return 0;
-}
-
-int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
-{
-    struct inode * inode;
-    struct buffer_head * bh, *dir_block;
-    struct xiafs_direct * de;
-	
-    bh = xiafs_find_entry(dir,name,len,&de, NULL);
-    if (bh) {
-        brelse(bh);
-	iput(dir);
-	return -EEXIST;
-    }
-    if (dir->i_nlink > 64000) {
-        iput(dir);
-        return -EMLINK;
-    }
-    inode = xiafs_new_inode(dir);
-    if (!inode) {
-        iput(dir);
-	return -ENOSPC;
-    }
-    inode->i_op = &xiafs_dir_inode_operations;
-    inode->i_size = XIAFS_ZSIZE(dir->i_sb);
-    inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-    inode->i_dirt = 1;
-    dir_block = xiafs_bread(inode,0,1);
-    if (!dir_block) {
-        iput(dir);
-	inode->i_nlink--;
-	inode->i_dirt = 1;
-	iput(inode);
-	return -ENOSPC;
-    }
-    de = (struct xiafs_direct *) dir_block->b_data;
-    de->d_ino=inode->i_ino;
-    strcpy(de->d_name,".");
-    de->d_name_len=1;
-    de->d_rec_len=12;
-    de =(struct xiafs_direct *)(12 + dir_block->b_data);
-    de->d_ino = dir->i_ino;
-    strcpy(de->d_name,"..");
-    de->d_name_len=2;
-    de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
-    inode->i_nlink = 2;
-    mark_buffer_dirty(dir_block, 1);
-    brelse(dir_block);
-    inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->fs->umask);
-    if (dir->i_mode & S_ISGID)
-        inode->i_mode |= S_ISGID;
-    inode->i_dirt = 1;
-    bh = xiafs_add_entry(dir, name, len, &de, NULL);
-    if (!bh) {
-        iput(dir);
-	inode->i_nlink=0;
-	iput(inode);
-	return -ENOSPC;
-    }
-    de->d_ino = inode->i_ino;
-    mark_buffer_dirty(bh, 1);
-    dir->i_nlink++;
-    dir->i_dirt = 1;
-    iput(dir);
-    iput(inode);
-    brelse(bh);
-    return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct inode * inode)
-{
-    int i, zones, offset;
-    struct buffer_head * bh;
-    struct xiafs_direct * de;
-
-    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
-        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-	return 1;
-    }
-
-    zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
-    for (i=0; i < zones; i++) {
-        bh =  xiafs_bread(inode, i, 0);
-	if (!i) {
-	    if (!bh) {
-	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-		return 1;
-	    }
-	    de=(struct xiafs_direct *)bh->b_data;
-	    if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
-		    de->d_rec_len != 12 ) {
-	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-		brelse(bh);
-		return 1;	 
-	    }
-	    de=(struct xiafs_direct *)(12 + bh->b_data);
-	    if (!de->d_ino || strcmp("..", de->d_name)) {
-	    	printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-		brelse(bh);
-		return 1;
-	    }
-	    offset=de->d_rec_len+12;
-	}
-	else
-	    offset = 0;
-	if (!bh)
-	    continue;
-	while (offset < XIAFS_ZSIZE(inode->i_sb)) {
-	    de=(struct xiafs_direct *)(bh->b_data+offset);
-	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
-		de->d_rec_len < 12 || 
-		(char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
-		de->d_name_len + 8 > de->d_rec_len ||
-		de->d_name[de->d_name_len]) {
-	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
-		brelse(bh);
-		return 1;
-	    }
-	    if (de->d_ino) {
-	        brelse(bh);
-		return 0;
-	    }
-	    offset+=de->d_rec_len;
-	}
-	brelse(bh);
-    }
-    return 1;
-}
-
-static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre)
-{
-    if (de==de_pre) {
-        de->d_ino=0;
-	return;
-    }
-    while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) {
-        if (de_pre->d_rec_len < 12) {
-	    printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
-	    return;
-	}
-        de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre);
-    }
-    if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) {
-        printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
-	return;
-    }
-    de_pre->d_rec_len+=de->d_rec_len;
-}
-
-int xiafs_rmdir(struct inode * dir, const char * name, int len)
-{
-    int retval;
-    struct inode * inode;
-    struct buffer_head * bh;
-    struct xiafs_direct * de, * de_pre;
-
-    inode = NULL;
-    bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
-    retval = -ENOENT;
-    if (!bh)
-        goto end_rmdir;
-    retval = -EPERM;
-    if (!(inode = iget(dir->i_sb, de->d_ino)))
-        goto end_rmdir;
-    if ((dir->i_mode & S_ISVTX) && !fsuser() &&
-            current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid)
-        goto end_rmdir;
-    if (inode->i_dev != dir->i_dev)
-        goto end_rmdir;
-    if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-        goto end_rmdir;
-    if (!S_ISDIR(inode->i_mode)) {
-        retval = -ENOTDIR;
-	goto end_rmdir;
-    }
-    if (!empty_dir(inode)) {
-        retval = -ENOTEMPTY;
-	goto end_rmdir;
-    }
-    if (inode->i_count > 1) {
-        retval = -EBUSY;
-	goto end_rmdir;
-    }
-    if (inode->i_nlink != 2)
-        printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
-    xiafs_rm_entry(de, de_pre);
-    mark_buffer_dirty(bh, 1);
-    inode->i_nlink=0;
-    inode->i_dirt=1;
-    dir->i_nlink--;
-    inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-    dir->i_dirt=1;
-    retval = 0;
-end_rmdir:
-    iput(dir);
-    iput(inode);
-    brelse(bh);
-    return retval;
-}
-
-int xiafs_unlink(struct inode * dir, const char * name, int len)
-{
-    int retval;
-    struct inode * inode;
-    struct buffer_head * bh;
-    struct xiafs_direct * de, * de_pre;
-
-repeat:
-    retval = -ENOENT;
-    inode = NULL;
-    bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
-    if (!bh)
-        goto end_unlink;
-    if (!(inode = iget(dir->i_sb, de->d_ino)))
-        goto end_unlink;
-    retval = -EPERM;
-    if (S_ISDIR(inode->i_mode))
-        goto end_unlink;
-    if (de->d_ino != inode->i_ino) {
-        iput(inode);
-	brelse(bh);
-	current->counter = 0;
-	schedule();
-	goto repeat;
-    }
-    if ((dir->i_mode & S_ISVTX) && !fsuser() &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid)
-        goto end_unlink;
-    if (!inode->i_nlink) {
-        printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
-	inode->i_nlink=1;
-    }
-    xiafs_rm_entry(de, de_pre);
-    mark_buffer_dirty(bh, 1);
-    inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-    dir->i_dirt = 1;
-    inode->i_nlink--;
-    inode->i_dirt = 1;
-    retval = 0;
-end_unlink:
-    brelse(bh);
-    iput(inode);
-    iput(dir);
-    return retval;
-}
-
-int xiafs_symlink(struct inode * dir, const char * name, 
-		int len, const char * symname)
-{
-    struct xiafs_direct * de;
-    struct inode * inode = NULL;
-    struct buffer_head * bh = NULL, * name_block = NULL;
-    int i;
-    char c;
-
-    bh = xiafs_find_entry(dir,name,len, &de, NULL);
-    if (bh) {
-	brelse(bh);
-	iput(dir);
-	return -EEXIST;
-    }
-    if (!(inode = xiafs_new_inode(dir))) {
-        iput(dir);
-	return -ENOSPC;
-    }
-    inode->i_mode = S_IFLNK | S_IRWXUGO;
-    inode->i_op = &xiafs_symlink_inode_operations;
-    name_block = xiafs_bread(inode,0,1);
-    if (!name_block) {
-        iput(dir);
-	inode->i_nlink--;
-	inode->i_dirt = 1;
-	iput(inode);
-	return -ENOSPC;
-    }
-    for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
-        name_block->b_data[i] = c;
-    name_block->b_data[i] = 0;
-    mark_buffer_dirty(name_block, 1);
-    brelse(name_block);
-    inode->i_size = i;
-    inode->i_dirt = 1;
-    bh = xiafs_add_entry(dir, name, len, &de, NULL);
-    if (!bh) {
-        inode->i_nlink--;
-	inode->i_dirt = 1;
-	iput(inode);
-	iput(dir);
-	return -ENOSPC;
-    }
-    de->d_ino = inode->i_ino;
-    mark_buffer_dirty(bh, 1);
-    brelse(bh);
-    iput(dir);
-    iput(inode);
-    return 0;
-}
-
-int xiafs_link(struct inode * oldinode, struct inode * dir, 
-	     const char * name, int len)
-{
-    struct xiafs_direct * de;
-    struct buffer_head * bh;
-
-    if (S_ISDIR(oldinode->i_mode)) {
-        iput(oldinode);
-	iput(dir);
-	return -EPERM;
-    }
-    if (oldinode->i_nlink > 64000) {
-        iput(oldinode);
-	iput(dir);
-	return -EMLINK;
-    }
-    bh = xiafs_find_entry(dir, name, len, &de, NULL);
-    if (bh) {
-        brelse(bh);
-	iput(dir);
-	iput(oldinode);
-	return -EEXIST;
-    }
-    bh = xiafs_add_entry(dir, name, len, &de, NULL);
-    if (!bh) {
-        iput(dir);
-	iput(oldinode);
-	return -ENOSPC;
-    }
-    de->d_ino = oldinode->i_ino;
-    mark_buffer_dirty(bh, 1);
-    brelse(bh);
-    iput(dir);
-    oldinode->i_nlink++;
-    oldinode->i_ctime = CURRENT_TIME;
-    oldinode->i_dirt = 1;
-    iput(oldinode);
-    return 0;
-}
-
-static int subdir(struct inode * new_inode, struct inode * old_inode)
-{
-    int ino;
-    int result;
-
-    new_inode->i_count++;
-    result = 0;
-    for (;;) {
-        if (new_inode == old_inode) {
-	    result = 1;
-	    break;
-	}
-	if (new_inode->i_dev != old_inode->i_dev)
-	    break;
-	ino = new_inode->i_ino;
-	if (xiafs_lookup(new_inode,"..",2,&new_inode))
-	    break;
-	if (new_inode->i_ino == ino)
-	    break;
-    }
-    iput(new_inode);
-    return result;
-}
-
-#define PARENT_INO(buffer) \
-    (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
-
-/*
- * rename uses retry to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
- * Anybody can rename anything with this: the permission checks are left to the
- * higher-level routines.
- */
-static int do_xiafs_rename(struct inode * old_dir, const char * old_name, 
-			 int old_len, struct inode * new_dir, 
-			 const char * new_name, int new_len,
-			 int must_be_dir)
-{
-    struct inode * old_inode, * new_inode;
-    struct buffer_head * old_bh, * new_bh, * dir_bh;
-    struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
-    int retval;
-
-try_again:
-    old_inode = new_inode = NULL;
-    old_bh = new_bh = dir_bh = NULL;
-    old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
-    retval = -ENOENT;
-    if (!old_bh)
-        goto end_rename;
-    old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0); /* don't cross mnt-points */
-    if (!old_inode)
-        goto end_rename;
-    if (must_be_dir && !S_ISDIR(old_inode->i_mode))
-	goto end_rename;
-    retval = -EPERM;
-    if ((old_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != old_inode->i_uid &&
-	    current->fsuid != old_dir->i_uid && !fsuser())
-        goto end_rename;
-    new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
-    if (new_bh) {
-        new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
-	if (!new_inode) {
-	    brelse(new_bh);
-	    new_bh = NULL;
-	}
-    }
-    if (new_inode == old_inode) {
-        retval = 0;
-	goto end_rename;
-    }
-    if (new_inode && S_ISDIR(new_inode->i_mode)) {
-        retval = -EEXIST;
-	goto end_rename;
-    }
-    retval = -EPERM;
-    if (new_inode && (new_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != new_inode->i_uid &&
- 	    current->fsuid != new_dir->i_uid && !fsuser())
-        goto end_rename;
-    if (S_ISDIR(old_inode->i_mode)) {
-        retval = -EEXIST;
-	if (new_bh)
-	    goto end_rename;
-	if ((retval = permission(old_inode, MAY_WRITE)) != 0)
-	    goto end_rename;
-	retval = -EINVAL;
-	if (subdir(new_dir, old_inode))
-	    goto end_rename;
-	retval = -EIO;
-	dir_bh = xiafs_bread(old_inode,0,0);
-	if (!dir_bh)
-	    goto end_rename;
-	if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
-	    goto end_rename;
-	retval = -EMLINK;
-	if (new_dir->i_nlink > 64000)
-	    goto end_rename;
-    }
-    if (!new_bh)
-        new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre);
-    retval = -ENOSPC;
-    if (!new_bh) 
-        goto end_rename;
-    /* sanity checking */
-    if ( (new_inode && (new_de->d_ino != new_inode->i_ino))
-	    || (new_de->d_ino && !new_inode)
-	    || (old_de->d_ino != old_inode->i_ino)) {
-        xiafs_rm_entry(new_de, new_de_pre);
-        brelse(old_bh);
-	brelse(new_bh);
-	brelse(dir_bh);
-	iput(old_inode);
-	iput(new_inode);
-	current->counter=0;
-	schedule();
-	goto try_again;
-    }
-    xiafs_rm_entry(old_de, old_de_pre);
-    new_de->d_ino = old_inode->i_ino;
-    if (new_inode) {
-        new_inode->i_nlink--;
-	new_inode->i_dirt = 1;
-    }
-    mark_buffer_dirty(old_bh, 1);
-    mark_buffer_dirty(new_bh, 1);
-    if (dir_bh) {
-        PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-	mark_buffer_dirty(dir_bh, 1);
-	old_dir->i_nlink--;
-	new_dir->i_nlink++;
-	old_dir->i_dirt = 1;
-	new_dir->i_dirt = 1;
-    }
-    retval = 0;
-end_rename:
-    brelse(dir_bh);
-    brelse(old_bh);
-    brelse(new_bh);
-    iput(old_inode);
-    iput(new_inode);
-    iput(old_dir);
-    iput(new_dir);
-    return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
-int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len,
-	struct inode * new_dir, const char * new_name, int new_len,
-	int must_be_dir)
-{
-    static struct wait_queue * wait = NULL;
-    static int lock = 0;
-    int result;
-
-    while (lock)
-        sleep_on(&wait);
-    lock = 1;
-    result = do_xiafs_rename(old_dir, old_name, old_len,
-			   new_dir, new_name, new_len,
-			   must_be_dir);
-    lock = 0;
-    wake_up(&wait);
-    return result;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/symlink.c linux/fs/xiafs/symlink.c
--- v2.1.20/linux/fs/xiafs/symlink.c	Tue Oct 29 19:58:47 1996
+++ linux/fs/xiafs/symlink.c	Thu Jan  1 02:00:00 1970
@@ -1,120 +0,0 @@
-/*
- *  linux/fs/xiafs/symlink.c
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- *  
- *  Based on Linus' minix/symlink.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- *
- *  This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-static int 
-xiafs_readlink(struct inode *, char *, int);
-
-static int 
-xiafs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations xiafs_symlink_inode_operations = {
-	NULL,			/* no file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	xiafs_readlink,		/* readlink */
-	xiafs_follow_link,	/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	NULL,			/* truncate */
-	NULL			/* permission */
-};
-
-static int xiafs_readlink(struct inode * inode, char * buffer, int buflen)
-{
-    struct buffer_head * bh;
-    int i;
-    char c;
-
-    if (!S_ISLNK(inode->i_mode)) {
-        iput(inode);
-	return -EINVAL;
-    }
-    if (buflen > BLOCK_SIZE)
-        buflen = BLOCK_SIZE;
-    bh = xiafs_bread(inode, 0, 0);
-    if (!IS_RDONLY (inode)) {
- 	inode->i_atime=CURRENT_TIME;
- 	inode->i_dirt=1;
-    }
-    iput(inode);
-    if (!bh)
-        return 0;
-    for (i=0; i < buflen && (c=bh->b_data[i]); i++)
-      put_user(c, buffer++);
-    if (i < buflen-1)
-      put_user('\0', buffer);
-    brelse(bh);
-    return i;
-}
-
-static int xiafs_follow_link(struct inode * dir, struct inode * inode,
-	int flag, int mode, struct inode ** res_inode)
-{
-    int error;
-    struct buffer_head * bh;
-
-    *res_inode = NULL;
-    if (!dir) {
-        dir = current->fs->root;
-	dir->i_count++;
-    }
-    if (!inode) {
-        iput(dir);
-	return -ENOENT;
-    }
-    if (!S_ISLNK(inode->i_mode)) {
-        iput(dir);
-	*res_inode = inode;
-	return 0;
-    }
-    if (!IS_RDONLY (inode)) {
-	inode->i_atime=CURRENT_TIME;
-	inode->i_dirt=1;
-    }
-    if (current->link_count > 5) {
-        iput(inode);
-	iput(dir);
-	return -ELOOP;
-    }
-    if (!(bh = xiafs_bread(inode, 0, 0))) {
-        iput(inode);
-        iput(dir);
-	return -EIO;
-    }
-    iput(inode);
-    current->link_count++;
-    error = open_namei(bh->b_data,flag,mode,res_inode,dir);
-    current->link_count--;
-    brelse(bh);
-    return error;
-}
-
-
-
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/truncate.c linux/fs/xiafs/truncate.c
--- v2.1.20/linux/fs/xiafs/truncate.c	Wed Nov  8 12:30:22 1995
+++ linux/fs/xiafs/truncate.c	Thu Jan  1 02:00:00 1970
@@ -1,197 +0,0 @@
-/*
- *  linux/fs/xiafs/truncate.c
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- *  
- *  Based on Linus' minix/truncate.c
- *  Copyright (C) Linus Torvalds, 1991, 1992.
- *
- *  This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#include "xiafs_mac.h"
-
-/*
- * Linus' comment:
- *
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-#define DT_ZONE		((inode->i_size + XIAFS_ZSIZE(inode->i_sb) - 1) \
-			 >> XIAFS_ZSIZE_BITS(inode->i_sb) )
-
-static int trunc_direct(struct inode * inode)
-{
-    u_long * lp;
-    struct buffer_head * bh;
-    int i, tmp;
-    int retry = 0;
-
-repeat:
-    for (i = DT_ZONE ; i < 8 ; i++) {
-        if (i < DT_ZONE)
-	    goto repeat;
-        lp=i + inode->u.xiafs_i.i_zone;
-        if (!(tmp = *lp))
-	    continue;
-	bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-	if (i < DT_ZONE) {
-	    brelse(bh);
-	    goto repeat;
-	}
-	if ((bh && bh->b_count != 1) || tmp != *lp)
-	    retry = 1;
-	else {
-	    *lp = 0;
-	    inode->i_dirt = 1;
-	    inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
-	    xiafs_free_zone(inode->i_sb, tmp);
-	}
-	brelse(bh);
-    }
-    return retry;
-}
-
-static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
-{
-
-#define INDT_ZONE 	(DT_ZONE - addr_off)
-
-    struct buffer_head * bh, * ind_bh;
-    int i, tmp;
-    u_long * indp;
-    int retry = 0;
-
-    if ( !(tmp=*lp) )
-        return 0;
-    ind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-    if (tmp != *lp) {
-        brelse(ind_bh);
-	return 1;
-    }
-    if (!ind_bh) {
-        *lp = 0;
-	return 0;
-    }
-repeat:
-    for (i = INDT_ZONE<0?0:INDT_ZONE; i < XIAFS_ADDRS_PER_Z(inode->i_sb); i++) {
-        if (i < INDT_ZONE)
-	    goto repeat;
-        indp = i+(u_long *) ind_bh->b_data;
-	if (!(tmp=*indp))
-	    continue;
-	bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-	if (i < INDT_ZONE) {
-	    brelse(bh);
-	    goto repeat;
-	}
-	if ((bh && bh->b_count != 1) || tmp != *indp)
-	    retry = 1;
-	else {
-	    *indp = 0;
-	    mark_buffer_dirty(ind_bh, 1);
-	    inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
-	    xiafs_free_zone(inode->i_sb, tmp);
-	}
-	brelse(bh);
-    }
-    indp = (u_long *) ind_bh->b_data;
-    for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*indp++); i++) ;
-    if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) {
-      if (ind_bh->b_count != 1)
-	   retry = 1;
-      else {
-	  tmp = *lp;
-	  *lp = 0;
-	  inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
-	  xiafs_free_zone(inode->i_sb, tmp);
-      }
-    }
-    brelse(ind_bh);
-    return retry;
-}
-		
-static int trunc_dindirect(struct inode * inode)
-{
-
-#define DINDT_ZONE \
-    ((DT_ZONE-XIAFS_ADDRS_PER_Z(inode->i_sb)-8)>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb))
-
-    int i, tmp;
-    struct buffer_head * dind_bh;
-    u_long * dindp, * lp;
-    int retry = 0;
-
-    lp = &(inode->u.xiafs_i.i_dind_zone);
-    if (!(tmp = *lp))
-        return 0;
-    dind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
-    if (tmp != *lp) {
-        brelse(dind_bh);
-	return 1;
-    }
-    if (!dind_bh) {
-        *lp = 0;
-	return 0;
-    }
-repeat:
-    for (i=DINDT_ZONE<0?0:DINDT_ZONE ; i < XIAFS_ADDRS_PER_Z(inode->i_sb) ; i ++) {
-        if (i < DINDT_ZONE)
-	    goto repeat;
-        dindp = i+(u_long *) dind_bh->b_data;
-	retry |= trunc_indirect(inode, 
-				8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)), 
-				dindp);
-	mark_buffer_dirty(dind_bh, 1);
-    }
-    dindp = (u_long *) dind_bh->b_data;
-    for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++);
-    if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) {
-        if (dind_bh->b_count != 1)
-	    retry = 1;
-	else {
-	    tmp = *lp;
-	    *lp = 0;
-	    inode->i_dirt = 1;
-	    inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
-	    xiafs_free_zone(inode->i_sb, tmp);
-	}
-    }
-    brelse(dind_bh);
-    return retry;
-}
-
-void xiafs_truncate(struct inode * inode)
-{
-    int retry;
-
-    if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	  S_ISLNK(inode->i_mode)))
-        return;
-    while (1) {
-        retry = trunc_direct(inode);
-        retry |= trunc_indirect(inode, 8, &(inode->u.xiafs_i.i_ind_zone)); 
-        retry |= trunc_dindirect(inode);
-	if (!retry)
-	    break;
-	current->counter = 0;
-	schedule();
-    }
-    inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-    inode->i_dirt = 1;
-}
diff -u --recursive --new-file v2.1.20/linux/fs/xiafs/xiafs_mac.h linux/fs/xiafs/xiafs_mac.h
--- v2.1.20/linux/fs/xiafs/xiafs_mac.h	Wed Aug 10 19:26:28 1994
+++ linux/fs/xiafs/xiafs_mac.h	Thu Jan  1 02:00:00 1970
@@ -1,32 +0,0 @@
-/*
- *  linux/fs/xiafs/xiafs_mac.h
- *
- *  Copyright (C) Q. Frank Xia, 1993.
- */
-
-extern char internal_error_message[];
-#define INTERN_ERR		internal_error_message, __FILE__, __LINE__
-#define WHERE_ERR		__FILE__, __LINE__
-
-#define XIAFS_ZSHIFT(sp)		((sp)->u.xiafs_sb.s_zone_shift)
-#define XIAFS_ZSIZE(sp)		(BLOCK_SIZE << XIAFS_ZSHIFT(sp))
-#define XIAFS_ZSIZE_BITS(sp)	(BLOCK_SIZE_BITS + XIAFS_ZSHIFT(sp))
-#define XIAFS_ADDRS_PER_Z(sp)   	(BLOCK_SIZE >> (2 - XIAFS_ZSHIFT(sp)))
-#define XIAFS_ADDRS_PER_Z_BITS(sp) 	(BLOCK_SIZE_BITS - 2 + XIAFS_ZSHIFT(sp))
-#define XIAFS_BITS_PER_Z(sp)	(BLOCK_SIZE  << (3 + XIAFS_ZSHIFT(sp)))
-#define XIAFS_BITS_PER_Z_BITS(sp)	(BLOCK_SIZE_BITS + 3 + XIAFS_ZSHIFT(sp))
-#define XIAFS_INODES_PER_Z(sp)	(_XIAFS_INODES_PER_BLOCK << XIAFS_ZSHIFT(sp))
-
-/* Use the most significant bytes of zone pointers to store block counter. */
-/* This is ugly, but it works. Note, We have another 7 bytes for "expansion". */
-
-#define XIAFS_GET_BLOCKS(row_ip, blocks)  \
-  blocks=((((row_ip)->i_zone[0] >> 24) & 0xff )|\
-	  (((row_ip)->i_zone[1] >> 16) & 0xff00 )|\
-	  (((row_ip)->i_zone[2] >>  8) & 0xff0000 ) )
-
-/* XIAFS_PUT_BLOCKS should be called before saving zone pointers */
-#define XIAFS_PUT_BLOCKS(row_ip, blocks)  \
-  (row_ip)->i_zone[2]=((blocks)<< 8) & 0xff000000;\
-  (row_ip)->i_zone[1]=((blocks)<<16) & 0xff000000;\
-  (row_ip)->i_zone[0]=((blocks)<<24) & 0xff000000
diff -u --recursive --new-file v2.1.20/linux/include/asm-alpha/uaccess.h linux/include/asm-alpha/uaccess.h
--- v2.1.20/linux/include/asm-alpha/uaccess.h	Tue Nov 19 15:53:56 1996
+++ linux/include/asm-alpha/uaccess.h	Fri Jan  3 18:48:36 1997
@@ -122,7 +122,7 @@
 	".section __ex_table,\"a\"\n"			\
 	"	.gprel32 1b\n"				\
 	"	lda %0, 2b-1b(%1)\n"			\
-	".text"						\
+	".previous"					\
 		: "=r"(__gu_val), "=r"(__gu_err)	\
 		: "m"(__m(addr)), "1"(__gu_err))
 
@@ -132,7 +132,7 @@
 	".section __ex_table,\"a\"\n"			\
 	"	.gprel32 1b\n"				\
 	"	lda %0, 2b-1b(%1)\n"			\
-	".text"						\
+	".previous"					\
 		: "=r"(__gu_val), "=r"(__gu_err)	\
 		: "m"(__m(addr)), "1"(__gu_err))
 
@@ -145,7 +145,7 @@
 	".section __ex_table,\"a\"\n"			\
 	"	.gprel32 1b\n"				\
 	"	lda %0, 2b-1b(%1)\n"			\
-	".text"						\
+	".previous"					\
 		: "=r"(__gu_val), "=r"(__gu_err)	\
 		: "m"(__m(addr)), "1"(__gu_err))
 
@@ -155,7 +155,7 @@
 	".section __ex_table,\"a\"\n"			\
 	"	.gprel32 1b\n"				\
 	"	lda %0, 2b-1b(%1)\n"			\
-	".text"						\
+	".previous"					\
 		: "=r"(__gu_val), "=r"(__gu_err)	\
 		: "m"(__m(addr)), "1"(__gu_err))
 #else
@@ -176,7 +176,7 @@
 	"	lda %0, 3b-1b(%2)\n"					\
 	"	.gprel32 2b\n"						\
 	"	lda %0, 2b-1b(%2)\n"					\
-	".text"								\
+	".previous"							\
 		: "=&r"(__gu_val), "=&r"(__gu_tmp), "=r"(__gu_err)	\
 		: "r"(addr), "2"(__gu_err));				\
 }
@@ -188,7 +188,7 @@
 	".section __ex_table,\"a\"\n"					\
 	"	.gprel32 1b\n"						\
 	"	lda %0, 2b-1b(%1)\n"					\
-	".text"								\
+	".previous"							\
 		: "=&r"(__gu_val), "=r"(__gu_err)			\
 		: "r"(addr), "1"(__gu_err))
 #endif
@@ -236,7 +236,7 @@
 	".section __ex_table,\"a\"\n"				\
 	"	.gprel32 1b\n"					\
 	"	lda $31,2b-1b(%0)\n"				\
-	".text"							\
+	".previous"						\
 		: "=r"(__pu_err)				\
 		: "m" (__m(addr)), "rJ" (x), "0"(__pu_err))
 
@@ -246,7 +246,7 @@
 	".section __ex_table,\"a\"\n"				\
 	"	.gprel32 1b\n"					\
 	"	lda $31,2b-1b(%0)\n"				\
-	".text"							\
+	".previous"						\
 		: "=r"(__pu_err)				\
 		: "m"(__m(addr)), "rJ"(x), "0"(__pu_err))
 
@@ -259,7 +259,7 @@
 	".section __ex_table,\"a\"\n"				\
 	"	.gprel32 1b\n"					\
 	"	lda $31,2b-1b(%0)\n"				\
-	".text"							\
+	".previous"						\
 		: "=r"(__pu_err)				\
 		: "m"(__m(addr)), "rJ"(x), "0"(__pu_err))
 
@@ -269,7 +269,7 @@
 	".section __ex_table,\"a\"\n"				\
 	"	.gprel32 1b\n"					\
 	"	lda $31,2b-1b(%0)\n"				\
-	".text"							\
+	".previous"						\
 		: "=r"(__pu_err)				\
 		: "m"(__m(addr)), "rJ"(x), "0"(__pu_err))
 #else
@@ -300,7 +300,7 @@
 	"	lda $31, 5b-3b(%0)\n"				\
 	"	.gprel32 4b\n"					\
 	"	lda $31, 5b-4b(%0)\n"				\
-	".text"							\
+	".previous"						\
 		: "=r"(__pu_err), "=&r"(__pu_tmp1),		\
 		  "=&r"(__pu_tmp2), "=&r"(__pu_tmp3),		\
 		  "=&r"(__pu_tmp4)				\
@@ -322,7 +322,7 @@
 	"	lda $31, 3b-1b(%0)\n"				\
 	"	.gprel32 2b\n"					\
 	"	lda $31, 3b-2b(%0)\n"				\
-	".text"							\
+	".previous"						\
 		: "=r"(__pu_err),				\
 	  	  "=&r"(__pu_tmp1), "=&r"(__pu_tmp2)		\
 		: "r"((unsigned long)(x)), "r"(addr), "0"(__pu_err)); \
diff -u --recursive --new-file v2.1.20/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.1.20/linux/include/asm-i386/uaccess.h	Thu Jan  2 15:55:24 1997
+++ linux/include/asm-i386/uaccess.h	Tue Jan 14 13:40:10 1997
@@ -153,10 +153,11 @@
 		".section .fixup,\"ax\"\n"			\
 		"3:	movl %3,%0\n"				\
 		"	jmp 2b\n"				\
+		".previous\n"					\
 		".section __ex_table,\"a\"\n"			\
 		"	.align 4\n"				\
 		"	.long 1b,3b\n"				\
-		".text"						\
+		".previous"					\
 		: "=r"(err)					\
 		: ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
 
@@ -200,10 +201,11 @@
 		"3:	movl %3,%0\n"				\
 		"	xor"itype" %"rtype"1,%"rtype"1\n"	\
 		"	jmp 2b\n"				\
+		".previous\n"					\
 		".section __ex_table,\"a\"\n"			\
 		"	.align 4\n"				\
 		"	.long 1b,3b\n"				\
-		".text"						\
+		".previous"					\
 		: "=r"(err), ltype (x)				\
 		: "m"(__m(addr)), "i"(-EFAULT), "0"(err))
 
@@ -222,11 +224,12 @@
 		".section .fixup,\"ax\"\n"				\
 		"3:	lea 0(%1,%0,4),%0\n"				\
 		"	jmp 2b\n"					\
+		".previous\n"						\
 		".section __ex_table,\"a\"\n"				\
 		"	.align 4\n"					\
 		"	.long 0b,3b\n"					\
 		"	.long 1b,2b\n"					\
-		".text"							\
+		".previous"						\
 		: "=c"(size)						\
 		: "r"(size & 3), "0"(size / 4), "D"(to), "S"(from)	\
 		: "di", "si", "memory")
@@ -242,10 +245,11 @@
 			".section .fixup,\"ax\"\n"		\
 			"2:	shl $2,%0\n"			\
 			"	jmp 1b\n"			\
+			".previous\n"				\
 			".section __ex_table,\"a\"\n"		\
 			"	.align 4\n"			\
 			"	.long 0b,2b\n"			\
-			".text"					\
+			".previous"				\
 			: "=c"(size)				\
 			: "S"(from), "D"(to), "0"(size/4)	\
 			: "di", "si", "memory");		\
@@ -259,11 +263,12 @@
 			"3:	shl $2,%0\n"			\
 			"4:	incl %0\n"			\
 			"	jmp 2b\n"			\
+			".previous\n"				\
 			".section __ex_table,\"a\"\n"		\
 			"	.align 4\n"			\
 			"	.long 0b,3b\n"			\
 			"	.long 1b,4b\n"			\
-			".text"					\
+			".previous"				\
 			: "=c"(size)				\
 			: "S"(from), "D"(to), "0"(size/4)	\
 			: "di", "si", "memory");		\
@@ -277,11 +282,12 @@
 			"3:	shl $2,%0\n"			\
 			"4:	addl $2,%0\n"			\
 			"	jmp 2b\n"			\
+			".previous\n"				\
 			".section __ex_table,\"a\"\n"		\
 			"	.align 4\n"			\
 			"	.long 0b,3b\n"			\
 			"	.long 1b,4b\n"			\
-			".text"					\
+			".previous"				\
 			: "=c"(size)				\
 			: "S"(from), "D"(to), "0"(size/4)	\
 			: "di", "si", "memory");		\
@@ -297,12 +303,13 @@
 			"5:	addl $2,%0\n"			\
 			"6:	incl %0\n"			\
 			"	jmp 3b\n"			\
+			".previous\n"				\
 			".section __ex_table,\"a\"\n"		\
 			"	.align 4\n"			\
 			"	.long 0b,4b\n"			\
 			"	.long 1b,5b\n"			\
 			"	.long 2b,6b\n"			\
-			".text"					\
+			".previous"				\
 			: "=c"(size)				\
 			: "S"(from), "D"(to), "0"(size/4)	\
 			: "di", "si", "memory");		\
@@ -405,11 +412,12 @@
 		".section .fixup,\"ax\"\n"				\
 		"3:	lea 0(%1,%0,4),%0\n"				\
 		"	jmp 2b\n"					\
+		".previous\n"						\
 		".section __ex_table,\"a\"\n"				\
 		"	.align 4\n"					\
 		"	.long 0b,3b\n"					\
 		"	.long 1b,2b\n"					\
-		".text"							\
+		".previous"						\
 		: "=c"(size)						\
 		: "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0)	\
 		: "di")
@@ -449,10 +457,11 @@
 		".section .fixup,\"ax\"\n"				   \
 		"3:	movl %2,%0\n"					   \
 		"	jmp 2b\n"					   \
+		".previous\n"						   \
 		".section __ex_table,\"a\"\n"				   \
 		"	.align 4\n"					   \
 		"	.long 0b,3b\n"					   \
-		".text"							   \
+		".previous"						   \
 		: "=d"(res), "=c"(count)				   \
 		: "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
 		: "si", "di", "ax", "memory")
@@ -491,10 +500,11 @@
 		".section .fixup,\"ax\"\n"
 		"2:	xorl %0,%0\n"
 		"	jmp 1b\n"
+		".previous\n"
 		".section __ex_table,\"a\"\n"
 		"	.align 4\n"
 		"	.long 0b,2b\n"
-		".text"
+		".previous"
 		:"=c" (res), "=D" (s)
 		:"1" (s), "a" (0), "0" (-__addr_ok(s)));
 	return res & -__addr_ok(s);
diff -u --recursive --new-file v2.1.20/linux/include/asm-m68k/uaccess.h linux/include/asm-m68k/uaccess.h
--- v2.1.20/linux/include/asm-m68k/uaccess.h	Sun Dec 22 16:37:40 1996
+++ linux/include/asm-m68k/uaccess.h	Fri Jan  3 18:48:37 1997
@@ -82,11 +82,12 @@
      "   .even\n"					\
      "2: movel %3,%0\n"					\
      "   jra 1b\n"					\
+     ".previous\n"					\
      ".section __ex_table,\"a\"\n"			\
      "   .align 4\n"					\
      "   .long 21b,2b\n"				\
      "   .long 1b,2b\n"					\
-     ".text"						\
+     ".previous"					\
      : "=d"(err)					\
      : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
 
@@ -125,10 +126,11 @@
      "3: movel %3,%0\n"				\
      "   sub" #bwl " %1,%1\n"			\
      "   jra 2b\n"				\
+     ".previous\n"				\
      ".section __ex_table,\"a\"\n"		\
      "   .align 4\n"				\
      "   .long 1b,3b\n"				\
-     ".text"					\
+     ".previous"				\
      : "=d"(err), reg(x)			\
      : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
 
@@ -162,12 +164,13 @@
 	 "   jra 6b\n"
 	 "9: addql #1,%2\n"
 	 "   jra 6b\n"
+         ".previous\n"
 	 ".section __ex_table,\"a\"\n"
 	 "   .align 4\n"
 	 "   .long 1b,7b\n"
 	 "   .long 3b,8b\n"
 	 "   .long 5b,9b\n"
-	 ".text"
+	 ".previous"
 	 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
 	 : "r"(n & 3), "0"(to), "1"(from), "2"(n/4)
 	 : "d0", "memory");
@@ -204,6 +207,7 @@
 	 "   jra 5b\n"
 	 "8: addql #1,%2\n"
 	 "   jra 5b\n"
+	 ".previous\n"
 	 ".section __ex_table,\"a\"\n"
 	 "   .align 4\n"
 	 "   .long 22b,6b\n"
@@ -212,7 +216,7 @@
 	 "   .long 4b,7b\n"
 	 "   .long 25b,8b\n"
 	 "   .long 5b,8b\n"
-	 ".text"
+	 ".previous"
 	 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
 	 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4));
     return n;
@@ -229,12 +233,12 @@
 	 "11: lsll #2,%2\n"				\
 	 fixup "\n"					\
 	 "    jra 12f\n"				\
+	 ".previous\n"					\
 	 ".section __ex_table,\"a\"\n"			\
 	 "    .align 4\n"				\
 	 "    .long 10b,11b\n"				\
-	 ".text\n"					\
+	 ".previous\n"					\
 	 copy "\n"					\
-	 ".text\n"					\
 	 "12:"						\
 	 : "=a"(to), "=a"(from), "=d"(n)		\
 	 : "0"(to), "1"(from), "2"(n/4)			\
@@ -255,10 +259,11 @@
 	     "   .even\n"
 	     "3: addql #1,%2\n"
 	     "   jra 2b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,3b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -272,10 +277,11 @@
 	     "   .even\n"
 	     "3: addql #2,%2\n"
 	     "   jra 2b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,3b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -292,11 +298,12 @@
 	     "4: addql #2,%2\n"
 	     "5: addql #1,%2\n"
 	     "   jra 3b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,4b\n"
 	     "   .long 2b,5b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -310,10 +317,11 @@
 	     "   .even\n"
 	     "3: addql #4,%2\n"
 	     "   jra 2b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,3b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -330,11 +338,12 @@
 	     "4: addql #4,%2\n"
 	     "5: addql #4,%2\n"
 	     "   jra 3b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,4b\n"
 	     "   .long 2b,5b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -354,12 +363,13 @@
 	     "6: addql #4,%2\n"
 	     "7: addql #4,%2\n"
 	     "   jra 4b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,5b\n"
 	     "   .long 2b,6b\n"
 	     "   .long 3b,7b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -382,13 +392,14 @@
 	     "8: addql #4,%2\n"
 	     "9: addql #4,%2\n"
 	     "   jra 5b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 1b,6b\n"
 	     "   .long 2b,7b\n"
 	     "   .long 3b,8b\n"
 	     "   .long 4b,9b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -406,7 +417,8 @@
 				 "2: movesb (%1)+,%%d0\n"
 				 "   moveb %%d0,(%0)+\n"
 				 ".section __ex_table,\"a\"\n"
-				 "   .long 2b,1b");
+				 "   .long 2b,1b\n"
+				 ".previous");
 	    break;
 	case 2:
 	    __copy_from_user_big(to, from, n,
@@ -416,7 +428,8 @@
 				 "2: movesw (%1)+,%%d0\n"
 				 "   movew %%d0,(%0)+\n"
 				 ".section __ex_table,\"a\"\n"
-				 "   .long 2b,1b");
+				 "   .long 2b,1b\n"
+				 ".previous");
 	    break;
 	case 3:
 	    __copy_from_user_big(to, from, n,
@@ -430,7 +443,8 @@
 				 "   moveb %%d0,(%0)+\n"
 				 ".section __ex_table,\"a\"\n"
 				 "   .long 3b,1b\n"
-				 "   .long 4b,2b");
+				 "   .long 4b,2b\n"
+				 ".previous");
 	    break;
 	}
 	break;
@@ -449,13 +463,13 @@
 	 "12: lsll #2,%2\n"				\
 	 fixup "\n"					\
 	 "    jra 13f\n"				\
+	 ".previous\n"					\
 	 ".section __ex_table,\"a\"\n"			\
 	 "    .align 4\n"				\
 	 "    .long 31b,12b\n"				\
 	 "    .long 11b,12b\n"				\
-	 ".text\n"					\
+	 ".previous\n"					\
 	 copy "\n"					\
-	 ".text\n"					\
 	 "13:"						\
 	 : "=a"(to), "=a"(from), "=d"(n)		\
 	 : "0"(to), "1"(from), "2"(n/4)			\
@@ -476,11 +490,12 @@
 	     "   .even\n"
 	     "2: addql #1,%2\n"
 	     "   jra 1b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n  "
 	     "   .long 21b,2b\n"
 	     "   .long 1b,2b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -494,11 +509,12 @@
 	     "   .even\n"
 	     "2: addql #2,%2\n"
 	     "   jra 1b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 21b,2b\n"
 	     "   .long 1b,2b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -515,13 +531,14 @@
 	     "3: addql #2,%2\n"
 	     "4: addql #1,%2\n"
 	     "   jra 2b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 21b,3b\n"
 	     "   .long 1b,3b\n"
 	     "   .long 22b,4b\n"
 	     "   .long 2b,4b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -535,11 +552,12 @@
 	     "   .even\n"
 	     "2: addql #4,%2\n"
 	     "   jra 1b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 21b,2b\n"
 	     "   .long 1b,2b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -556,13 +574,14 @@
 	     "3: addql #4,%2\n"
 	     "4: addql #4,%2\n"
 	     "   jra 2b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 21b,3b\n"
 	     "   .long 1b,3b\n"
 	     "   .long 22b,4b\n"
 	     "   .long 2b,4b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -582,6 +601,7 @@
 	     "5: addql #4,%2\n"
 	     "6: addql #4,%2\n"
 	     "   jra 3b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 21b,4b\n"
@@ -590,7 +610,7 @@
 	     "   .long 2b,5b\n"
 	     "   .long 23b,6b\n"
 	     "   .long 3b,6b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -613,6 +633,7 @@
 	     "7: addql #4,%2\n"
 	     "8: addql #4,%2\n"
 	     "   jra 4b\n"
+	     ".previous\n"
 	     ".section __ex_table,\"a\"\n"
 	     "   .align 4\n"
 	     "   .long 21b,5b\n"
@@ -623,7 +644,7 @@
 	     "   .long 3b,7b\n"
 	     "   .long 24b,8b\n"
 	     "   .long 4b,8b\n"
-	     ".text"
+	     ".previous"
 	     : "=a"(to), "=a"(from), "=d"(n)
 	     : "0"(to), "1"(from), "2"(0)
 	     : "d0", "memory");
@@ -643,7 +664,8 @@
 			       "2:"
 			       ".section __ex_table,\"a\"\n"
 			       "   .long 22b,1b\n"
-			       "   .long 2b,1b");
+			       "   .long 2b,1b\n"
+			       ".previous");
 	    break;
 	case 2:
 	    __copy_to_user_big(to, from, n,
@@ -655,7 +677,8 @@
 			       "2:"
 			       ".section __ex_table,\"a\"\n"
 			       "   .long 22b,1b\n"
-			       "   .long 2b,1b");
+			       "   .long 2b,1b\n"
+			       ".previous");
 	    break;
 	case 3:
 	    __copy_to_user_big(to, from, n,
@@ -672,7 +695,8 @@
 			       "   .long 23b,1b\n"
 			       "   .long 3b,1b\n"
 			       "   .long 24b,2b\n"
-			       "   .long 4b,2b");
+			       "   .long 4b,2b\n"
+			       ".previous");
 	    break;
 	}
 	break;
@@ -711,11 +735,12 @@
 	 "   .even\n"
 	 "4: movel %4,%0\n"
 	 "   jra 3b\n"
+	 ".previous\n"
 	 ".section __ex_table,\"a\"\n"
 	 "   .align 4\n"
 	 "   .long 1b,4b\n"
 	 "   .long 12b,4b\n"
-	 ".text"
+	 ".previous"
 	 : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
 	 : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
 	 : "d0", "memory");
@@ -740,11 +765,12 @@
 	 "   .even\n"
 	 "3: moveq %2,%0\n"
 	 "   jra 2b\n"
+	 ".previous\n"
 	 ".section __ex_table,\"a\"\n"
 	 "   .align 4\n"
 	 "   .long 1b,3b\n"
 	 "   .long 12b,3b\n"
-	 ".text"
+	 ".previous"
 	 : "=d"(res), "=a"(src)
 	 : "i"(0), "0"(res), "1"(src)
 	 : "d0");
@@ -781,6 +807,7 @@
 	 "   jra 5b\n"
 	 "8: addql #1,%1\n"
 	 "   jra 5b\n"
+	 ".previous\n"
 	 ".section __ex_table,\"a\"\n"
 	 "   .align 4\n"
 	 "   .long 1b,6b\n"
@@ -789,7 +816,7 @@
 	 "   .long 4b,7b\n"
 	 "   .long 25b,8b\n"
 	 "   .long 5b,8b\n"
-	 ".text"
+	 ".previous"
 	 : "=a"(to), "=d"(n)
 	 : "r"(n & 3), "r"(0), "0"(to), "1"(n/4));
     return n;
diff -u --recursive --new-file v2.1.20/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h
--- v2.1.20/linux/include/asm-sparc/uaccess.h	Wed Dec 18 15:59:02 1996
+++ linux/include/asm-sparc/uaccess.h	Fri Jan  3 18:48:37 1997
@@ -59,7 +59,7 @@
  *
  * There is a special way how to put a range of potentially faulting
  * insns (like twenty ldd/std's with now intervening other instructions)
- * You specify address of first in insn and 0 in fixup and in the next 
+ * You specify address of first in insn and 0 in fixup and in the next
  * exception_table_entry you specify last potentially faulting insn + 1
  * and in fixup the routine which should handle the fault.
  * That fixup code will get
@@ -163,11 +163,12 @@
 	".align	4\n"							\
 "3:\n\t"								\
 	"b	2b\n\t"							\
-	" mov	%3, %0\n\n\t"						\
+	" mov	%3, %0\n\t"						\
+        ".previous\n\n\t"						\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\t"						\
-	".text\n\n\t"							\
+	".previous\n\n\t"						\
        : "=&r" (ret) : "r" (x), "r" (__m(addr)),			\
 	 "i" (-EFAULT))
 
@@ -179,7 +180,7 @@
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, __ret_efault\n\n\t"					\
-	".text\n\n\t"							\
+	".previous\n\n\t"						\
        : "=r" (foo) : "r" (x), "r" (__m(addr)));			\
 else									\
 __asm__ __volatile(							\
@@ -189,11 +190,12 @@
 	".align	4\n"							\
 "3:\n\t"								\
 	"ret\n\t"							\
-	" restore %%g0, %3, %%o0\n\n\t"					\
+	" restore %%g0, %3, %%o0\n\t"					\
+	".previous\n\n\t"						\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\n\t"						\
-	".text\n\n\t"							\
+	".previous\n\n\t"						\
        : "=r" (foo) : "r" (x), "r" (__m(addr)), "i" (ret))
 
 extern int __put_user_bad(void);
@@ -250,10 +252,11 @@
 	"clr	%1\n\t"							\
 	"b	2b\n\t"							\
 	" mov	%3, %0\n\n\t"						\
+	".previous\n\t"							\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\n\t"						\
-	".text\n\t"							\
+	".previous\n\t"							\
        : "=&r" (ret), "=&r" (x) : "r" (__m(addr)),			\
 	 "i" (-EFAULT))
 
@@ -265,7 +268,7 @@
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b,__ret_efault\n\n\t"					\
-	".text\n\t"							\
+	".previous\n\t"							\
        : "=&r" (x) : "r" (__m(addr)));					\
 else									\
 __asm__ __volatile__(							\
@@ -276,10 +279,11 @@
 "3:\n\t"								\
 	"ret\n\t"							\
 	" restore %%g0, %2, %%o0\n\n\t"					\
+	".previous\n\t"							\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\n\t"						\
-	".text\n\t"							\
+	".previous\n\t"							\
        : "=&r" (x) : "r" (__m(addr)), "i" (retval))
 
 extern int __get_user_bad(void);
diff -u --recursive --new-file v2.1.20/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.1.20/linux/include/asm-sparc64/uaccess.h	Tue Dec 31 21:41:11 1996
+++ linux/include/asm-sparc64/uaccess.h	Fri Jan  3 18:48:37 1997
@@ -58,7 +58,7 @@
  *
  * There is a special way how to put a range of potentially faulting
  * insns (like twenty ldd/std's with now intervening other instructions)
- * You specify address of first in insn and 0 in fixup and in the next 
+ * You specify address of first in insn and 0 in fixup and in the next
  * exception_table_entry you specify last potentially faulting insn + 1
  * and in fixup the routine which should handle the fault.
  * That fixup code will get
@@ -167,10 +167,11 @@
 "3:\n\t"								\
 	"b	2b\n\t"							\
 	" mov	%3, %0\n\n\t"						\
+	".previous\n\t"							\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\t"						\
-	".text\n\n\t"							\
+	".previous\n\n\t"						\
        : "=&r" (ret) : "r" (x), "r" (__m(addr)),			\
 	 "i" (-EFAULT))
 
@@ -182,7 +183,7 @@
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, __ret_efault\n\n\t"					\
-	".text\n\n\t"							\
+	".previous\n\n\t"						\
        : "=r" (foo) : "r" (x), "r" (__m(addr)));			\
 else									\
 __asm__ __volatile(							\
@@ -193,10 +194,11 @@
 "3:\n\t"								\
 	"ret\n\t"							\
 	" restore %%g0, %3, %%o0\n\n\t"					\
+	".previous\n\t"							\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\n\t"						\
-	".text\n\n\t"							\
+	".previous\n\n\t"						\
        : "=r" (foo) : "r" (x), "r" (__m(addr)), "i" (ret))
 
 extern int __put_user_bad(void);
@@ -257,10 +259,11 @@
 	"clr	%1\n\t"							\
 	"b	2b\n\t"							\
 	" mov	%3, %0\n\n\t"						\
+	".previous\n\t"							\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\n\t"						\
-	".text\n\t"							\
+	".previous\n\t"							\
        : "=&r" (ret), "=&r" (x) : "r" (__m(addr)),			\
 	 "i" (-EFAULT))
 
@@ -272,7 +275,7 @@
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b,__ret_efault\n\n\t"					\
-	".text\n\t"							\
+	".previous\n\t"							\
        : "=&r" (x) : "r" (__m(addr)));					\
 else									\
 __asm__ __volatile__(							\
@@ -283,10 +286,11 @@
 "3:\n\t"								\
 	"ret\n\t"							\
 	" restore %%g0, %2, %%o0\n\n\t"					\
+	".previous\n\t"							\
 	".section __ex_table,#alloc\n\t"				\
 	".align	4\n\t"							\
 	".word	1b, 3b\n\n\t"						\
-	".text\n\t"							\
+	".previous\n\t"							\
        : "=&r" (x) : "r" (__m(addr)), "i" (retval))
 
 extern int __get_user_bad(void);
diff -u --recursive --new-file v2.1.20/linux/include/linux/ext_fs.h linux/include/linux/ext_fs.h
--- v2.1.20/linux/include/linux/ext_fs.h	Wed Jul  3 11:53:06 1996
+++ linux/include/linux/ext_fs.h	Thu Jan  1 02:00:00 1970
@@ -1,111 +0,0 @@
-#ifndef _LINUX_EXT_FS_H
-#define _LINUX_EXT_FS_H
-
-/*
- * The ext filesystem constants/structures
- */
-
-#define EXT_NAME_LEN 255
-#define EXT_ROOT_INO 1
-
-#define EXT_SUPER_MAGIC 0x137D
-
-#define EXT_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_inode)))
-
-struct ext_inode {
-	unsigned short i_mode;
-	unsigned short i_uid;
-	unsigned long i_size;
-	unsigned long i_time;
-	unsigned short i_gid;
-	unsigned short i_nlinks;
-	unsigned long i_zone[12];
-};
-
-struct ext_free_inode {
-	unsigned long count;
-	unsigned long free[14];
-	unsigned long next;
-};
-
-struct ext_free_block {
-	unsigned long count;
-	unsigned long free[254];
-	unsigned long next;
-};
-
-struct ext_super_block {
-	unsigned long s_ninodes;
-	unsigned long s_nzones;
-	unsigned long s_firstfreeblock;
-	unsigned long s_freeblockscount;
-	unsigned long s_firstfreeinode;
-	unsigned long s_freeinodescount;
-	unsigned long s_firstdatazone;
-	unsigned long s_log_zone_size;
-	unsigned long s_max_size;
-	unsigned long s_reserved1;
-	unsigned long s_reserved2;
-	unsigned long s_reserved3;
-	unsigned long s_reserved4;
-	unsigned long s_reserved5;
-	unsigned short s_magic;
-};
-
-struct ext_dir_entry {
-	unsigned long inode;
-	unsigned short rec_len;
-	unsigned short name_len;
-	char name[EXT_NAME_LEN];
-};
-
-#ifdef __KERNEL__
-extern int ext_open(struct inode * inode, struct file * filp);
-extern void ext_release(struct inode * inode, struct file * filp);
-extern int ext_lookup(struct inode * dir,const char * name, int len,
-                      struct inode ** result);
-extern int ext_create(struct inode * dir,const char * name, int len, int mode,
-	struct inode ** result);
-extern int ext_mkdir(struct inode * dir, const char * name, int len, int mode);
-extern int ext_rmdir(struct inode * dir, const char * name, int len);
-extern int ext_unlink(struct inode * dir, const char * name, int len);
-extern int ext_symlink(struct inode * inode, const char * name, int len,
-	const char * symname);
-extern int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
-extern int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
-extern int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
-	struct inode * new_dir, const char * new_name, int new_len, int must_be_dir);
-extern struct inode * ext_new_inode(const struct inode * dir);
-extern void ext_free_inode(struct inode * inode);
-extern unsigned long ext_count_free_inodes(struct super_block *sb);
-extern int ext_new_block(struct super_block * sb);
-extern void ext_free_block(struct super_block * sb, int block);
-extern unsigned long ext_count_free_blocks(struct super_block *sb);
-
-extern int ext_bmap(struct inode *,int);
-
-extern struct buffer_head * ext_getblk(struct inode *, int, int);
-extern struct buffer_head * ext_bread(struct inode *, int, int);
-
-extern void ext_truncate(struct inode *);
-extern void ext_put_super(struct super_block *);
-extern void ext_write_super(struct super_block *);
-extern struct super_block *ext_read_super(struct super_block *,void *,int);
-extern int init_ext_fs(void);
-extern void ext_read_inode(struct inode *);
-extern void ext_write_inode(struct inode *);
-extern void ext_put_inode(struct inode *);
-extern void ext_statfs(struct super_block *, struct statfs *, int);
-extern int ext_sync_inode(struct inode *);
-extern int ext_sync_file(struct inode *, struct file *);
-
-extern int ext_lseek(struct inode *, struct file *, off_t, int);
-extern int ext_read(struct inode *, struct file *, char *, int);
-extern int ext_write(struct inode *, struct file *, char *, int);
-
-extern struct inode_operations ext_file_inode_operations;
-extern struct inode_operations ext_dir_inode_operations;
-extern struct inode_operations ext_symlink_inode_operations;
-
-#endif /*__KERNEL__ */
-#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/ext_fs_i.h linux/include/linux/ext_fs_i.h
--- v2.1.20/linux/include/linux/ext_fs_i.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/ext_fs_i.h	Thu Jan  1 02:00:00 1970
@@ -1,11 +0,0 @@
-#ifndef _EXT_FS_I
-#define _EXT_FS_I
-
-/*
- * extended file system inode data in memory
- */
-struct ext_inode_info {
-	unsigned long i_data[16];
-};
-
-#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/ext_fs_sb.h linux/include/linux/ext_fs_sb.h
--- v2.1.20/linux/include/linux/ext_fs_sb.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/ext_fs_sb.h	Thu Jan  1 02:00:00 1970
@@ -1,21 +0,0 @@
-#ifndef _EXT_FS_SB
-#define _EXT_FS_SB
-
-/*
- * extended-fs super-block data in memory
- */
-struct ext_sb_info {
-			unsigned long s_ninodes;
-			unsigned long s_nzones;
-			unsigned long s_firstdatazone;
-			unsigned long s_log_zone_size;
-			unsigned long s_max_size;
-			unsigned long s_firstfreeblocknumber;
-			unsigned long s_freeblockscount;
-			struct buffer_head * s_firstfreeblock;
-			unsigned long s_firstfreeinodenumber;
-			unsigned long s_freeinodescount;
-			struct buffer_head * s_firstfreeinodeblock;
-};
-
-#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.20/linux/include/linux/fs.h	Mon Dec 30 15:39:15 1996
+++ linux/include/linux/fs.h	Tue Jan 14 13:39:58 1997
@@ -221,17 +221,16 @@
 
 #include <linux/pipe_fs_i.h>
 #include <linux/minix_fs_i.h>
-#include <linux/ext_fs_i.h>
 #include <linux/ext2_fs_i.h>
 #include <linux/hpfs_fs_i.h>
 #include <linux/msdos_fs_i.h>
 #include <linux/umsdos_fs_i.h>
 #include <linux/iso_fs_i.h>
 #include <linux/nfs_fs_i.h>
-#include <linux/xia_fs_i.h>
 #include <linux/sysv_fs_i.h>
 #include <linux/affs_fs_i.h>
 #include <linux/ufs_fs_i.h>
+#include <linux/romfs_fs_i.h>
 
 /*
  * Attribute flags.  These should be or-ed together to figure out what
@@ -310,17 +309,16 @@
 	union {
 		struct pipe_inode_info pipe_i;
 		struct minix_inode_info minix_i;
-		struct ext_inode_info ext_i;
 		struct ext2_inode_info ext2_i;
 		struct hpfs_inode_info hpfs_i;
 		struct msdos_inode_info msdos_i;
 		struct umsdos_inode_info umsdos_i;
 		struct iso_inode_info isofs_i;
 		struct nfs_inode_info nfs_i;
-		struct xiafs_inode_info xiafs_i;
 		struct sysv_inode_info sysv_i;
 		struct affs_inode_info affs_i;
 		struct ufs_inode_info ufs_i;
+		struct romfs_inode_info romfs_i;
 		struct socket socket_i;
 		void * generic_ip;
 	} u;
@@ -411,16 +409,15 @@
 extern int fasync_helper(struct inode *, struct file *, int, struct fasync_struct **);
 
 #include <linux/minix_fs_sb.h>
-#include <linux/ext_fs_sb.h>
 #include <linux/ext2_fs_sb.h>
 #include <linux/hpfs_fs_sb.h>
 #include <linux/msdos_fs_sb.h>
 #include <linux/iso_fs_sb.h>
 #include <linux/nfs_fs_sb.h>
-#include <linux/xia_fs_sb.h>
 #include <linux/sysv_fs_sb.h>
 #include <linux/affs_fs_sb.h>
 #include <linux/ufs_fs_sb.h>
+#include <linux/romfs_fs_sb.h>
 
 struct super_block {
 	kdev_t s_dev;
@@ -440,16 +437,15 @@
 	struct wait_queue * s_wait;
 	union {
 		struct minix_sb_info minix_sb;
-		struct ext_sb_info ext_sb;
 		struct ext2_sb_info ext2_sb;
 		struct hpfs_sb_info hpfs_sb;
 		struct msdos_sb_info msdos_sb;
 		struct isofs_sb_info isofs_sb;
 		struct nfs_sb_info nfs_sb;
-		struct xiafs_sb_info xiafs_sb;
 		struct sysv_sb_info sysv_sb;
 		struct affs_sb_info affs_sb;
 		struct ufs_sb_info ufs_sb;
+		struct romfs_sb_info romfs_sb;
 		void *generic_sbp;
 	} u;
 };
diff -u --recursive --new-file v2.1.20/linux/include/linux/in6.h linux/include/linux/in6.h
--- v2.1.20/linux/include/linux/in6.h	Thu Dec 12 17:02:46 1996
+++ linux/include/linux/in6.h	Tue Jan 14 08:16:49 1997
@@ -96,6 +96,7 @@
 #define IPV6_RXSRCRT		5
 #define IPV6_PKTOPTIONS		6
 #define IPV6_CHECKSUM		7
+#define IPV6_HOPLIMIT		8
 
 /*
  *	Alternative names
diff -u --recursive --new-file v2.1.20/linux/include/linux/modsetver.h linux/include/linux/modsetver.h
--- v2.1.20/linux/include/linux/modsetver.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/modsetver.h	Fri Jan  3 11:33:26 1997
@@ -0,0 +1,10 @@
+/* Symbol versioning nastiness.  */
+
+#define __SYMBOL_VERSION(x)       __ver_ ## x
+#define __VERSIONED_SYMBOL2(x,v)  x ## _R ## v
+#define __VERSIONED_SYMBOL1(x,v)  __VERSIONED_SYMBOL2(x,v)
+#define __VERSIONED_SYMBOL(x)     __VERSIONED_SYMBOL1(x,__SYMBOL_VERSION(x))
+
+#ifndef _set_ver
+#define _set_ver(x)		  __VERSIONED_SYMBOL(x)
+#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/module.h linux/include/linux/module.h
--- v2.1.20/linux/include/linux/module.h	Mon Dec 30 15:39:15 1996
+++ linux/include/linux/module.h	Tue Jan 14 13:40:08 1997
@@ -8,14 +8,17 @@
 #define _LINUX_MODULE_H
 
 #ifdef __GENKSYMS__
-# undef MODVERSIONS
-# define MODVERSIONS
+#  define _set_ver(sym) sym
+#  undef  MODVERSIONS
+#  define MODVERSIONS
 #else /* ! __GENKSYMS__ */
-# if defined(MODVERSIONS) && !defined(MODULE) && defined(EXPORT_SYMTAB)
+# if !defined(MODVERSIONS) && defined(EXPORT_SYMTAB)
+#   define _set_ver(sym) sym
 #   include <linux/modversions.h>
 # endif
 #endif /* __GENKSYMS__ */
 
+
 /* Don't need to bring in all of uaccess.h just for this decl.  */
 struct exception_table_entry;
 
@@ -39,6 +42,9 @@
 	struct module_ref *next_ref;
 };
 
+/* TBD */
+struct module_persist;
+
 struct module
 {
 	unsigned long size_of_struct;	/* == sizeof(module) */
@@ -62,6 +68,11 @@
 #ifdef __alpha__
 	unsigned long gp;
 #endif
+	/* Members past this point are extensions to the basic
+	   module support and are optional.  Use mod_opt_member()
+	   to examine them.  */
+	const struct module_persist *persist_start;
+	const struct module_persist *persist_end;
 };
 
 struct module_info
@@ -78,6 +89,7 @@
 #define MOD_DELETED		2
 #define MOD_AUTOCLEAN		4
 #define MOD_VISITED  		8
+#define MOD_USED_ONCE		16
 
 /* Values for query_module's which.  */
 
@@ -91,12 +103,23 @@
 
 #define GET_USE_COUNT(module)	((module)->usecount)
 
+/* When the struct module is extended, new values must be examined using
+   this macro.  It returns a pointer to the member if available, NULL
+   otherwise. */
+
+#define mod_opt_member(mod,member) 					\
+	({ struct module *_mod = (mod);					\
+	   __typeof__(_mod->member) *_mem = &_mod->member;		\
+	   ((char *)(_mem+1) > (char *)_mod + _mod->size_of_struct	\
+	    ? (__typeof__(_mod->member) *)NULL : _mem);			\
+	})
+
 /* Indirect stringification.  */
 
 #define __MODULE_STRING_1(x)	#x
 #define __MODULE_STRING(x)	__MODULE_STRING_1(x)
 
-#ifdef MODULE
+#if defined(MODULE) && !defined(__GENKSYMS__)
 
 /* Embedded module documentation macros.  */
 
@@ -106,6 +129,10 @@
 const char __module_author[] __attribute__((section(".modinfo"))) = 	   \
 "author=" name
 
+#define MODULE_DESCRIPTION(desc)					   \
+const char __module_description[] __attribute__((section(".modinfo"))) =   \
+"description=" desc
+
 /* Could potentially be used by kerneld...  */
 
 #define MODULE_SUPPORTED_DEVICE(dev)					   \
@@ -130,27 +157,32 @@
 __attribute__((section(".modinfo"))) =		\
 "parm_" __MODULE_STRING(var) "=" type
 
+#define MODULE_PARM_DESC(var,desc)		\
+const char __module_parm_desc_##var[]		\
+__attribute__((section(".modinfo"))) =		\
+"parm_desc_" __MODULE_STRING(var) "=" desc
+
 /* The attributes of a section are set the first time the section is
-   seen; we want .modinfo to not be allocated.  This header should be
-   included before any functions or variables are defined.  */
+   seen; we want .modinfo to not be allocated.  */
 
-__asm__(".section .modinfo\n\t.text");
+__asm__(".section .modinfo\n\t.previous");
 
 /* Define the module variable, and usage macros.  */
 extern struct module __this_module;
 
-#define MOD_INC_USE_COUNT \
-	(__this_module.usecount++, __this_module.flags |= MOD_VISITED)
-#define MOD_DEC_USE_COUNT \
+#define MOD_INC_USE_COUNT 					\
+	(__this_module.usecount++,				\
+	 __this_module.flags |= MOD_VISITED|MOD_USED_ONCE)
+#define MOD_DEC_USE_COUNT					\
 	(__this_module.usecount--, __this_module.flags |= MOD_VISITED)
-#define MOD_IN_USE \
+#define MOD_IN_USE						\
 	(__this_module.usecount != 0)
 
 #ifndef __NO_VERSION__
 #include <linux/version.h>
 const char __module_kernel_version[] __attribute__((section(".modinfo"))) =
 "kernel_version=" UTS_RELEASE;
-#if defined(MODVERSIONS) && !defined(__GENKSYMS__)
+#ifdef MODVERSIONS
 const char __module_using_checksums[] __attribute__((section(".modinfo"))) =
 "using_checksums=1";
 #endif
@@ -159,8 +191,12 @@
 #else /* MODULE */
 
 #define MODULE_AUTHOR(name)
+#define MODULE_DESCRIPTION(desc)
 #define MODULE_SUPPORTED_DEVICE(name)
 #define MODULE_PARM(var,type)
+#define MODULE_PARM_DESC(var,desc)
+
+#ifndef __GENKSYMS__
 
 #define MOD_INC_USE_COUNT	do { } while (0)
 #define MOD_DEC_USE_COUNT	do { } while (0)
@@ -168,6 +204,8 @@
 
 extern struct module *module_list;
 
+#endif /* !__GENKSYMS__ */
+
 #endif /* MODULE */
 
 /* Export a symbol either from the kernel or a module.
@@ -183,30 +221,48 @@
 
 /* We want the EXPORT_SYMBOL tag left intact for recognition.  */
 
+#elif !defined(EXPORT_SYMTAB)
+
+#define __EXPORT_SYMBOL(sym,str)   error EXPORT_SYMTAB_not_defined
+#define EXPORT_SYMBOL(var)	   error EXPORT_SYMTAB_not_defined
+#define EXPORT_SYMBOL_NOVERS(var)  error EXPORT_SYMTAB_not_defined
+
+#elif !defined(AUTOCONF_INCLUDED)
+
+#define __EXPORT_SYMBOL(sym,str)   error config_must_be_included_before_module
+#define EXPORT_SYMBOL(var)	   error config_must_be_included_before_module
+#define EXPORT_SYMBOL_NOVERS(var)  error config_must_be_included_before_module
+
 #elif !defined(CONFIG_MODULES)
 
+#define __EXPORT_SYMBOL(sym,str)
 #define EXPORT_SYMBOL(var)
 #define EXPORT_SYMBOL_NOVERS(var)
-#define EXPORT_NO_SYMBOLS
 
 #else
 
-#define EXPORT_SYMBOL(var)				\
-const struct module_symbol __export_##var 		\
-__attribute__((section("__ksymtab"))) = {		\
-	(unsigned long)&var, __MODULE_STRING(var)	\
-}							\
+#define __EXPORT_SYMBOL(sym, str)			\
+const char __kstrtab_##sym[]				\
+__attribute__((section(".kstrtab"))) = str;		\
+const struct module_symbol __ksymtab_##sym 		\
+__attribute__((section("__ksymtab"))) =			\
+{ (unsigned long)&sym, __kstrtab_##sym }
+
+#if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS)
+#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+#else
+#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
+#endif
+
+#define EXPORT_SYMBOL_NOVERS(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
 
-#define EXPORT_SYMBOL_NOVERS(var) EXPORT_SYMBOL(var)
+#endif /* __GENKSYMS__ */
 
 #ifdef MODULE
 /* Force a module to export no symbols.  */
-#define EXPORT_NO_SYMBOLS				\
-__asm__(".section __ksymtab\n.text")
+#define EXPORT_NO_SYMBOLS  __asm__(".section __ksymtab\n.previous")
 #else
 #define EXPORT_NO_SYMBOLS
 #endif /* MODULE */
-
-#endif
 
 #endif /* _LINUX_MODULE_H */
diff -u --recursive --new-file v2.1.20/linux/include/linux/romfs_fs.h linux/include/linux/romfs_fs.h
--- v2.1.20/linux/include/linux/romfs_fs.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/romfs_fs.h	Tue Jan 14 12:51:18 1997
@@ -0,0 +1,62 @@
+#ifndef __LINUX_ROMFS_FS_H
+#define __LINUX_ROMFS_FS_H
+
+/* The basic structures of the romfs filesystem */
+
+#define ROMBSIZE BLOCK_SIZE
+#define ROMBSBITS BLOCK_SIZE_BITS
+#define ROMBMASK (ROMBSIZE-1)
+#define ROMFS_MAGIC 0x7275
+
+#define ROMFS_MAXFN 128
+
+#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
+#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
+#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define ROMSB_WORD0 __mk4('-','r','o','m')
+#define ROMSB_WORD1 __mk4('1','f','s','-')
+
+/* On-disk "super block" */
+
+struct romfs_super_block {
+	__u32 word0;
+	__u32 word1;
+	__u32 size;
+	__u32 checksum;
+	char name[0];		/* volume name */
+};
+
+/* On disk inode */
+
+struct romfs_inode {
+	__u32 next;		/* low 4 bits see ROMFH_ */
+	__u32 spec;
+	__u32 size;
+	__u32 checksum;
+	char name[0];
+};
+
+#define ROMFH_TYPE 7
+#define ROMFH_HRD 0
+#define ROMFH_DIR 1
+#define ROMFH_REG 2
+#define ROMFH_SYM 3
+#define ROMFH_BLK 4
+#define ROMFH_CHR 5
+#define ROMFH_SCK 6
+#define ROMFH_FIF 7
+#define ROMFH_EXEC 8
+
+/* Alignment */
+
+#define ROMFH_SIZE 16
+#define ROMFH_PAD (ROMFH_SIZE-1)
+#define ROMFH_MASK (~ROMFH_PAD)
+
+#ifdef __KERNEL__
+
+/* Not much now */
+extern int init_romfs_fs(void);
+
+#endif /* __KERNEL__ */
+#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/romfs_fs_i.h linux/include/linux/romfs_fs_i.h
--- v2.1.20/linux/include/linux/romfs_fs_i.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/romfs_fs_i.h	Fri Jan  3 13:03:42 1997
@@ -0,0 +1,11 @@
+#ifndef __ROMFS_FS_I
+#define __ROMFS_FS_I
+
+/* inode in-kernel data */
+
+struct romfs_inode_info {
+	unsigned long i_metasize;	/* size of non-data area */
+	unsigned long i_dataoffset;	/* from the start of fs */
+};
+
+#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/romfs_fs_sb.h linux/include/linux/romfs_fs_sb.h
--- v2.1.20/linux/include/linux/romfs_fs_sb.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/romfs_fs_sb.h	Fri Jan  3 13:03:42 1997
@@ -0,0 +1,10 @@
+#ifndef __ROMFS_FS_SB
+#define __ROMFS_FS_SB
+
+/* romfs superblock in-core data */
+
+struct romfs_sb_info {
+	unsigned long s_maxsize;
+};
+
+#endif
diff -u --recursive --new-file v2.1.20/linux/include/linux/xia_fs.h linux/include/linux/xia_fs.h
--- v2.1.20/linux/include/linux/xia_fs.h	Wed Jul  3 11:53:06 1996
+++ linux/include/linux/xia_fs.h	Thu Jan  1 02:00:00 1970
@@ -1,121 +0,0 @@
-#ifndef _XIA_FS_H
-#define _XIA_FS_H
-
-/*
- * include/linux/xia_fs.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix_fs.h.
- * Copyright (C) Linus Torvalds, 1991, 1992.
- */
-
-#define _XIAFS_SUPER_MAGIC 0x012FD16D
-#define _XIAFS_ROOT_INO 1
-#define _XIAFS_BAD_INO  2
-
-#define _XIAFS_NAME_LEN 248
-
-#define _XIAFS_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof(struct xiafs_inode)))
-
-struct xiafs_inode {		/* 64 bytes */
-    mode_t   i_mode;
-    nlink_t  i_nlinks;
-    uid_t    i_uid;
-    gid_t    i_gid;
-    size_t   i_size;		/* 8 */
-    time_t   i_ctime;
-    time_t   i_atime;
-    time_t   i_mtime;
-    daddr_t  i_zone[8];
-    daddr_t  i_ind_zone;
-    daddr_t  i_dind_zone;
-};
-
-/*
- * linux super-block data on disk
- */
-struct xiafs_super_block {
-    u_char  s_boot_segment[512];	/*  1st sector reserved for boot */
-    u_long  s_zone_size;		/*  0: the name says it		 */
-    u_long  s_nzones;			/*  1: volume size, zone aligned */ 
-    u_long  s_ninodes;			/*  2: # of inodes		 */
-    u_long  s_ndatazones;		/*  3: # of data zones		 */
-    u_long  s_imap_zones;		/*  4: # of imap zones           */
-    u_long  s_zmap_zones;		/*  5: # of zmap zones		 */
-    u_long  s_firstdatazone;		/*  6: first data zone           */
-    u_long  s_zone_shift;		/*  7: z size = 1KB << z shift   */
-    u_long  s_max_size;			/*  8: max size of a single file */
-    u_long  s_reserved0;		/*  9: reserved			 */
-    u_long  s_reserved1;		/* 10: 				 */
-    u_long  s_reserved2;		/* 11:				 */
-    u_long  s_reserved3;		/* 12:				 */
-    u_long  s_firstkernzone;		/* 13: first kernel zone	 */
-    u_long  s_kernzones;		/* 14: kernel size in zones	 */
-    u_long  s_magic;			/* 15: magic number for xiafs    */
-};
-
-struct xiafs_direct {
-    ino_t   d_ino;
-    u_short d_rec_len;
-    u_char  d_name_len;
-    char    d_name[_XIAFS_NAME_LEN+1];
-};
-
-#ifdef __KERNEL__
-
-extern int xiafs_lookup(struct inode * dir,const char * name, int len, 
-			struct inode ** result);
-extern int xiafs_create(struct inode * dir,const char * name, int len, int mode,
-		      	struct inode ** result);
-extern int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode);
-extern int xiafs_rmdir(struct inode * dir, const char * name, int len);
-extern int xiafs_unlink(struct inode * dir, const char * name, int len);
-extern int xiafs_symlink(struct inode * inode, const char * name, int len,
-		       	const char * symname);
-extern int xiafs_link(struct inode * oldinode, struct inode * dir, 
-		    	const char * name, int len);
-extern int xiafs_mknod(struct inode * dir, const char * name, int len, 
-		     	int mode, int rdev);
-extern int xiafs_rename(struct inode * old_dir, const char * old_name, 
-		      	int old_len, struct inode * new_dir, 
-		      	const char * new_name, int new_len,
-		      	int must_be_dir);
-extern struct inode * xiafs_new_inode(struct inode * dir);
-extern void xiafs_free_inode(struct inode * inode);
-extern unsigned long xiafs_count_free_inodes(struct super_block *sb);
-extern int xiafs_new_zone(struct super_block * sb, u_long prev_addr);
-extern void xiafs_free_zone(struct super_block * sb, int block);
-extern unsigned long xiafs_count_free_zones(struct super_block *sb);
-
-extern int xiafs_bmap(struct inode *,int);
-
-extern struct buffer_head * xiafs_getblk(struct inode *, int, int);
-extern struct buffer_head * xiafs_bread(struct inode *, int, int);
-
-extern void xiafs_truncate(struct inode *);
-extern void xiafs_put_super(struct super_block *);
-extern struct super_block *xiafs_read_super(struct super_block *,void *,int);
-extern int init_xiafs_fs(void);
-extern void xiafs_read_inode(struct inode *);
-extern void xiafs_write_inode(struct inode *);
-extern void xiafs_put_inode(struct inode *);
-extern void xiafs_statfs(struct super_block *, struct statfs *, int);
-extern int xiafs_sync_inode(struct inode *);
-extern int xiafs_sync_file(struct inode *, struct file *);
-
-extern struct inode_operations xiafs_file_inode_operations;
-extern struct inode_operations xiafs_dir_inode_operations;
-extern struct inode_operations xiafs_symlink_inode_operations;
-
-#endif /* __KERNEL__ */
-
-#endif  /* _XIA_FS_H */
-
-
-
-
-
-
-
-
diff -u --recursive --new-file v2.1.20/linux/include/linux/xia_fs_i.h linux/include/linux/xia_fs_i.h
--- v2.1.20/linux/include/linux/xia_fs_i.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/xia_fs_i.h	Thu Jan  1 02:00:00 1970
@@ -1,19 +0,0 @@
-#ifndef _XIA_FS_I_H
-#define _XIA_FS_I_H
-
-/*
- * include/linux/xia_fs_i.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- * 
- * Based on Linus' minix_fs_i.h.
- * Copyright (C) Linus Torvalds, 1991, 1992.
- */
-
-struct xiafs_inode_info { 		/* for data zone pointers */
-    unsigned long  i_zone[8];
-    unsigned long  i_ind_zone;
-    unsigned long  i_dind_zone;
-};
-
-#endif  /* _XIA_FS_I_H */
diff -u --recursive --new-file v2.1.20/linux/include/linux/xia_fs_sb.h linux/include/linux/xia_fs_sb.h
--- v2.1.20/linux/include/linux/xia_fs_sb.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/xia_fs_sb.h	Thu Jan  1 02:00:00 1970
@@ -1,36 +0,0 @@
-#ifndef _XIA_FS_SB_H
-#define _XIA_FS_SB_H
-
-/*
- * include/linux/xia_fs_sb.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix_fs_sb.h.
- * Copyright (C) Linus Torvalds, 1991, 1992.
- */
-
-#define _XIAFS_IMAP_SLOTS 8
-#define _XIAFS_ZMAP_SLOTS 32
-
-struct xiafs_sb_info {
-    u_long   s_nzones;
-    u_long   s_ninodes;
-    u_long   s_ndatazones;
-    u_long   s_imap_zones;
-    u_long   s_zmap_zones;
-    u_long   s_firstdatazone;
-    u_long   s_zone_shift;
-    u_long   s_max_size;				/*  32 bytes */
-    struct buffer_head * s_imap_buf[_XIAFS_IMAP_SLOTS];	/*  32 bytes */
-    struct buffer_head * s_zmap_buf[_XIAFS_ZMAP_SLOTS];	/* 128 bytes */
-    int      s_imap_iznr[_XIAFS_IMAP_SLOTS];		/*  32 bytes */
-    int      s_zmap_zznr[_XIAFS_ZMAP_SLOTS];		/* 128 bytes */
-    u_char   s_imap_cached;			/* flag for cached imap */
-    u_char   s_zmap_cached;			/* flag for cached imap */
-};
-
-#endif /* _XIA_FS_SB_H */
-
-
-
diff -u --recursive --new-file v2.1.20/linux/include/net/ipv6.h linux/include/net/ipv6.h
--- v2.1.20/linux/include/net/ipv6.h	Fri Nov 15 23:49:10 1996
+++ linux/include/net/ipv6.h	Tue Jan 14 13:45:30 1997
@@ -214,7 +214,8 @@
 						struct in6_addr * saddr,
 						struct device *dev,
 						struct ipv6_options *opt,
-						int proto, int noblock);
+						int proto, int hlimit,
+						int noblock);
 
 /*
  *	rcv function (called from netdevice level)
diff -u --recursive --new-file v2.1.20/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.20/linux/include/net/sock.h	Thu Jan  2 15:55:25 1997
+++ linux/include/net/sock.h	Tue Jan 14 13:42:14 1997
@@ -149,8 +149,11 @@
 
 	__u8			recvsrcrt:1,
 	                        rxinfo:1,
+				rxhlim:1,
+				hopopts:1,
+				dstopts:1,
 				mc_loop:1,
-                                unused:4;
+                                unused:2;
 
 	/* device for outgoing mcast packets */
 
diff -u --recursive --new-file v2.1.20/linux/include/net/transp_v6.h linux/include/net/transp_v6.h
--- v2.1.20/linux/include/net/transp_v6.h	Sat Nov 30 12:03:12 1996
+++ linux/include/net/transp_v6.h	Tue Jan 14 13:47:18 1997
@@ -28,7 +28,8 @@
 extern int			datagram_send_ctl(struct msghdr *msg,
 						  struct device **src_dev,
 						  struct in6_addr **src_addr,
-						  struct ipv6_options *opt);
+						  struct ipv6_options *opt,
+						  int *hlimit);
 
 #define		LOOPBACK4_IPV6		__constant_htonl(0x7f000006)
 
diff -u --recursive --new-file v2.1.20/linux/init/main.c linux/init/main.c
--- v2.1.20/linux/init/main.c	Thu Jan  2 15:55:25 1997
+++ linux/init/main.c	Tue Jan 14 12:57:24 1997
@@ -6,6 +6,7 @@
  *  GK 2/5/95  -  Changed to support mounting root fs via NFS
  *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
  *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
+ *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
  */
 
 #define __KERNEL_SYSCALLS__
@@ -53,8 +54,6 @@
 extern char _stext, _etext;
 extern char *linux_banner;
 
-static char printbuf[1024];
-
 extern int console_loglevel;
 
 static int init(void *);
@@ -237,9 +236,6 @@
 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 
-static char * argv_rc[] = { "/bin/sh", NULL };
-static char * envp_rc[] = { "HOME=/", "TERM=linux", NULL };
-
 char *get_options(char *str, int *ints)
 {
 	char *cur = str;
@@ -917,39 +913,6 @@
  	cpu_idle(NULL);
 }
 
-static int printf(const char *fmt, ...)
-{
-	va_list args;
-	int i;
-
-	va_start(args, fmt);
-	write(1,printbuf,i=vsprintf(printbuf, fmt, args));
-	va_end(args);
-	return i;
-}
-
-static int do_rc(void * rc)
-{
-	close(0);
-	if (open(rc,O_RDONLY,0))
-		return -1;
-	return execve("/bin/sh", argv_rc, envp_rc);
-}
-
-static int do_shell(void * shell)
-{
-	char *argv[2];
-
-	close(0);close(1);close(2);
-	setsid();
-	(void) open("/dev/tty1",O_RDWR,0);
-	(void) dup(0);
-	(void) dup(0);
-	argv[0] = shell;
-	argv[1] = NULL;
-	return execve(shell, argv, envp_rc);
-}
-
 #ifdef CONFIG_BLK_DEV_INITRD
 static int do_linuxrc(void * shell)
 {
@@ -971,7 +934,6 @@
 
 static int init(void * unused)
 {
-	int pid,i;
 #ifdef CONFIG_BLK_DEV_INITRD
 	int real_root_mountflags;
 #endif
@@ -1042,32 +1004,18 @@
 			
 	(void) dup(0);
 	(void) dup(0);
+	
+	/*
+	 * We try each of these until one succeeds.
+	 *
+	 * The Bourne shell can be used instead of init if we are 
+	 * trying to recover a really broken machine.
+	 */
 
-	if (!execute_command) {
-		execve("/etc/init",argv_init,envp_init);
-		execve("/bin/init",argv_init,envp_init);
-		execve("/sbin/init",argv_init,envp_init);
-		/* if this fails, fall through to original stuff */
-
-		pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD);
-		if (pid>0)
-			while (pid != wait(&i))
-				/* nothing */;
-	}
-
-	while (1) {
-		pid = kernel_thread(do_shell,
-			execute_command ? execute_command : "/bin/sh",
-			SIGCHLD);
-		if (pid < 0) {
-			printf("Fork failed in init\n\r");
-			continue;
-		}
-		while (1)
-			if (pid == wait(&i))
-				break;
-		printf("\n\rchild %d died with code %04x\n\r",pid,i);
-		sync();
-	}
-	return -1;
+	execve(execute_command,argv_init,envp_init);
+	execve("/etc/init",argv_init,envp_init);
+	execve("/bin/init",argv_init,envp_init);
+	execve("/sbin/init",argv_init,envp_init);
+	execve("/bin/sh",argv_init,envp_init);
+	panic("No init found.  Try passing init= option to kernel.");
 }
diff -u --recursive --new-file v2.1.20/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.20/linux/kernel/ksyms.c	Mon Dec 30 15:39:16 1996
+++ linux/kernel/ksyms.c	Fri Jan  3 11:33:26 1997
@@ -9,8 +9,8 @@
  *   by Bjorn Ekwall <bj0rn@blox.se>
  */
 
-#include <linux/module.h>
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
@@ -330,7 +330,6 @@
 EXPORT_SYMBOL(___strtok);
 EXPORT_SYMBOL(init_fifo);
 EXPORT_SYMBOL(super_blocks);
-EXPORT_SYMBOL(reuse_list);
 EXPORT_SYMBOL(fifo_inode_operations);
 EXPORT_SYMBOL(chrdev_inode_operations);
 EXPORT_SYMBOL(blkdev_inode_operations);
diff -u --recursive --new-file v2.1.20/linux/kernel/module.c linux/kernel/module.c
--- v2.1.20/linux/kernel/module.c	Mon Dec 30 15:39:16 1996
+++ linux/kernel/module.c	Tue Jan 14 09:02:10 1997
@@ -43,9 +43,7 @@
 	NULL,			/* cleanup */
 	__start___ex_table,	/* ex_table_start */
 	__stop___ex_table,	/* ex_table_end */
-#ifdef __alpha__
-	NULL,			/* gp */
-#endif
+	/* Rest are NULL */
 };
 
 struct module *module_list = &kernel_module;
@@ -186,11 +184,14 @@
 		goto err1;
 	}
 
-	/* In the future we can check for various known sizes, but for
-	   now there is only one.  */
+	/* Check for legal module header sizes.  */
 	if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)
 		goto err1;
-	if (mod_user_size != sizeof(struct module)) {
+	switch (mod_user_size) {
+	  case sizeof(struct module):
+	  case &((struct module *)0L)->persist_start:
+		break;
+	  default:
 		printk(KERN_ERR "init_module: Invalid module header size.\n"
 		       KERN_ERR "A new version of the modutils is likely "
 				"needed.\n");
@@ -378,8 +379,9 @@
 		next = mod->next;
 		if (mod->refs == NULL &&
 		    mod->usecount == 0 &&
-		    ((mod->flags & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED))
-		     == (MOD_AUTOCLEAN|MOD_RUNNING))) {
+		    ((mod->flags
+		      & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED|MOD_USED_ONCE))
+		     == (MOD_AUTOCLEAN|MOD_RUNNING|MOD_USED_ONCE))) {
 			if (mod->flags & MOD_VISITED)
 				mod->flags &= ~MOD_VISITED;
 			else
diff -u --recursive --new-file v2.1.20/linux/net/802/p8022.c linux/net/802/p8022.c
--- v2.1.20/linux/net/802/p8022.c	Thu Jan  2 15:55:26 1997
+++ linux/net/802/p8022.c	Fri Jan  3 11:33:27 1997
@@ -16,6 +16,7 @@
  *		4 entries at most). The current demux assumes this.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.1.20/linux/net/802/p8022tr.c linux/net/802/p8022tr.c
--- v2.1.20/linux/net/802/p8022tr.c	Thu Jan  2 15:55:26 1997
+++ linux/net/802/p8022tr.c	Fri Jan  3 11:33:27 1997
@@ -8,6 +8,7 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.1.20/linux/net/802/psnap.c linux/net/802/psnap.c
--- v2.1.20/linux/net/802/psnap.c	Mon Dec 30 15:39:16 1996
+++ linux/net/802/psnap.c	Fri Jan  3 11:33:27 1997
@@ -10,6 +10,7 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.1.20/linux/net/Makefile linux/net/Makefile
--- v2.1.20/linux/net/Makefile	Thu Jan  2 15:55:26 1997
+++ linux/net/Makefile	Fri Jan  3 11:33:27 1997
@@ -89,13 +89,21 @@
   endif
 endif
 
-L_TARGET     := network.a
-L_OBJS	     := socket.o protocols.o sysctl_net.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
+# We must attach netsyms.o to socket.o, as otherwise there is nothing
+# to pull the object file from the archive.
+
+SOCK         := socket.o
 ifeq ($(CONFIG_NET),y)
 ifeq ($(CONFIG_MODULES),y)
-LX_OBJS = netsyms.o
+O_TARGET     := sock_n_syms.o
+O_OBJS       := socket.o
+OX_OBJS      := netsyms.o
+SOCK         := $(O_TARGET)
 endif
 endif
+
+L_TARGET     := network.a
+L_OBJS	     := $(SOCK) protocols.o sysctl_net.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
 
 M_OBJS	     :=
 
diff -u --recursive --new-file v2.1.20/linux/net/core/firewall.c linux/net/core/firewall.c
--- v2.1.20/linux/net/core/firewall.c	Thu Jan  2 15:55:26 1997
+++ linux/net/core/firewall.c	Fri Jan  3 11:33:27 1997
@@ -6,6 +6,7 @@
  *	much hacked by:	Alan Cox
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/firewall.h>
diff -u --recursive --new-file v2.1.20/linux/net/ipv4/Makefile linux/net/ipv4/Makefile
--- v2.1.20/linux/net/ipv4/Makefile	Thu Dec 12 19:37:25 1996
+++ linux/net/ipv4/Makefile	Fri Jan  3 11:33:27 1997
@@ -14,6 +14,7 @@
 	     tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o\
 	     raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o ip_fw.o \
 	     sysctl_net_ipv4.o fib.o ip_nat_dumb.o
+IPV4X_OBJS :=
 
 MOD_LIST_NAME := IPV4_MODULES
 M_OBJS :=
@@ -39,7 +40,7 @@
 endif
 
 ifeq ($(CONFIG_IP_MASQUERADE),y)
-IPV4_OBJS += ip_masq.o ip_masq_app.o
+IPV4X_OBJS += ip_masq.o ip_masq_app.o
 M_OBJS += ip_masq_ftp.o ip_masq_irc.o ip_masq_raudio.o
 endif
 
@@ -53,6 +54,7 @@
 
 ifdef CONFIG_INET
 O_OBJS := $(IPV4_OBJS)
+OX_OBJS := $(IPV4X_OBJS)
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.20/linux/net/ipv4/ip_masq_ftp.c linux/net/ipv4/ip_masq_ftp.c
--- v2.1.20/linux/net/ipv4/ip_masq_ftp.c	Mon Dec 30 15:39:17 1996
+++ linux/net/ipv4/ip_masq_ftp.c	Fri Jan  3 11:33:27 1997
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <asm/system.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.20/linux/net/ipv4/ip_masq_irc.c linux/net/ipv4/ip_masq_irc.c
--- v2.1.20/linux/net/ipv4/ip_masq_irc.c	Mon Dec 30 15:39:17 1996
+++ linux/net/ipv4/ip_masq_irc.c	Fri Jan  3 11:33:27 1997
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.20/linux/net/ipv4/ip_masq_raudio.c linux/net/ipv4/ip_masq_raudio.c
--- v2.1.20/linux/net/ipv4/ip_masq_raudio.c	Mon Dec 30 15:39:17 1996
+++ linux/net/ipv4/ip_masq_raudio.c	Fri Jan  3 11:33:27 1997
@@ -37,6 +37,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <asm/system.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.20/linux/net/ipv6/datagram.c linux/net/ipv6/datagram.c
--- v2.1.20/linux/net/ipv6/datagram.c	Thu Dec 12 19:37:30 1996
+++ linux/net/ipv6/datagram.c	Tue Jan 14 08:16:49 1997
@@ -65,6 +65,22 @@
 		cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len);
 	}
 
+	if (np->rxhlim && (len >= sizeof(struct cmsghdr) + sizeof(int)))
+	{
+		int *hlim;
+		
+		cmsg->cmsg_len = (sizeof(struct cmsghdr) + sizeof(int));
+		cmsg->cmsg_level = SOL_IPV6;
+		cmsg->cmsg_type = IPV6_HOPLIMIT;
+		
+		hlim = (int *) cmsg->cmsg_data;
+		*hlim = skb->nh.ipv6h->hop_limit;
+		
+		len -= cmsg->cmsg_len;
+		msg->msg_controllen += cmsg->cmsg_len;
+		cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len);
+	}
+
 	if (opt->srcrt)
 	{
 		int hdrlen = sizeof(struct rt0_hdr) + (opt->srcrt->hdrlen << 3);
@@ -90,14 +106,15 @@
 			 
 
 int datagram_send_ctl(struct msghdr *msg, struct device **src_dev,
-		      struct in6_addr **src_addr, struct ipv6_options *opt)
+		      struct in6_addr **src_addr, struct ipv6_options *opt, 
+		      int *hlimit)
 {
 	struct inet6_dev *in6_dev = NULL;
 	struct in6_pktinfo *src_info;
 	struct cmsghdr *cmsg;
 	struct ipv6_rt_hdr *rthdr;
 	int len;
-	int err = -EINVAL;
+	int err = 0;
 
 	for (cmsg = msg->msg_control; cmsg; cmsg = cmsg_nxthdr(msg, cmsg))
 	{
@@ -113,6 +130,7 @@
 			if (cmsg->cmsg_len < (sizeof(struct cmsghdr) +
 					      sizeof(struct in6_pktinfo)))
 			{
+				err = -EINVAL;
 				goto exit_f;
 			}
 
@@ -123,6 +141,7 @@
 				in6_dev = ipv6_dev_by_index(src_info->ipi6_ifindex);
 				if (in6_dev == NULL)
 				{
+					err = -ENODEV;
 					goto exit_f;
 				}
 
@@ -137,11 +156,11 @@
 
 				if ( ifp == NULL)
 				{
+					err = -EINVAL;
 					goto exit_f;
 				}
 
 				*src_addr = &src_info->ipi6_addr;
-				err = 0;
 			}
 
 			break;
@@ -155,6 +174,7 @@
 			/* validate option length */
 			if (len < sizeof(struct ipv6_rt_hdr))
 			{
+				err = -EINVAL;
 				goto exit_f;
 			}
 
@@ -165,28 +185,46 @@
 			 */
 			if (rthdr->type)
 			{
+				err = -EINVAL;
 				goto exit_f;
 			}
 
 			if (((rthdr->hdrlen + 1) << 3) < len)
-			{				
+			{	
+				err = -EINVAL;
 				goto exit_f;
 			}
 
 			/* segments left must also match */
 			if ((rthdr->hdrlen >> 1) != rthdr->segments_left)
 			{
+				err = -EINVAL;
 				goto exit_f;
 			}
 			
 			opt->opt_nflen += ((rthdr->hdrlen + 1) << 3);
 			opt->srcrt = rthdr;
-			err = 0;
 
 			break;
+			
+		case IPV6_HOPLIMIT:
+			
+			len = cmsg->cmsg_len;
+			len -= sizeof(struct cmsghdr);
+			
+			if (len < sizeof(int))
+			{
+				err = -EINVAL;
+				goto exit_f;
+			}
+
+			*hlimit = *((int *) cmsg->cmsg_data);
+			break;
+			
 		default:
 			printk(KERN_DEBUG "invalid cmsg type: %d\n",
 			       cmsg->cmsg_type);
+			err = -EINVAL;
 			break;
 		}
 	}
diff -u --recursive --new-file v2.1.20/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- v2.1.20/linux/net/ipv6/icmp.c	Thu Dec 12 19:37:30 1996
+++ linux/net/ipv6/icmp.c	Tue Jan 14 08:16:49 1997
@@ -267,7 +267,7 @@
 
 
 	ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len,
-			saddr, src_dev, NULL, IPPROTO_ICMPV6, 1);
+			saddr, src_dev, NULL, IPPROTO_ICMPV6, 0, 1);
 }
 
 static void icmpv6_echo_reply(struct sk_buff *skb)
@@ -302,7 +302,7 @@
 	msg.daddr = &hdr->saddr;
        
 	ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len, saddr,
-			skb->dev, NULL, IPPROTO_ICMPV6, 1);
+			skb->dev, NULL, IPPROTO_ICMPV6, 0, 1);
 }
 
 static __inline__ int ipv6_ext_hdr(u8 nexthdr)
diff -u --recursive --new-file v2.1.20/linux/net/ipv6/ipv6_output.c linux/net/ipv6/ipv6_output.c
--- v2.1.20/linux/net/ipv6/ipv6_output.c	Thu Dec 12 19:37:30 1996
+++ linux/net/ipv6/ipv6_output.c	Tue Jan 14 08:16:49 1997
@@ -397,11 +397,10 @@
 int ipv6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
 		    struct in6_addr *dest, unsigned short int length,
 		    struct in6_addr *saddr, struct device *dev,
-		    struct ipv6_options *opt, int proto,		    
+		    struct ipv6_options *opt, int proto, int hlimit,
 		    int noblock)
 {
 	rt6_output_method_t output_method = default_output_method;
-	int	hlimit;
 	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
 	struct dest_entry *dc = NULL;
 	struct in6_addr *daddr = dest;
@@ -420,17 +419,21 @@
 	}
 
 	addr_type = ipv6_addr_type(daddr);
-	if (addr_type & IPV6_ADDR_MULTICAST)
+	
+	if (hlimit < 1)
 	{
-		hlimit = np->mcast_hops;
-		if (dev == NULL)
+		if (addr_type & IPV6_ADDR_MULTICAST)
 		{
-			dev = np->mc_if;
+			hlimit = np->mcast_hops;
+			if (dev == NULL)
+			{
+				dev = np->mc_if;
+			}
 		}
+		else
+			hlimit = np->hop_limit;
 	}
-	else
-		hlimit = np->hop_limit;
-	
+		
 	if (addr_type & (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_SITELOCAL |
 			 IPV6_ADDR_MULTICAST))
 	{
diff -u --recursive --new-file v2.1.20/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c
--- v2.1.20/linux/net/ipv6/ipv6_sockglue.c	Thu Dec 12 19:37:31 1996
+++ linux/net/ipv6/ipv6_sockglue.c	Tue Jan 14 08:16:49 1997
@@ -133,6 +133,11 @@
 		retv = 0;
 		break;
 
+	case IPV6_HOPLIMIT:
+		np->rxhlim = val;
+		retv = 0;
+		break;
+
 	case IPV6_UNICAST_HOPS:
 		if (val > 255)
 		{
diff -u --recursive --new-file v2.1.20/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
--- v2.1.20/linux/net/ipv6/raw.c	Thu Dec 12 19:37:31 1996
+++ linux/net/ipv6/raw.c	Tue Jan 14 08:16:49 1997
@@ -149,7 +149,7 @@
 		*addr_len = sizeof(struct sockaddr_in6);
 	}
 
-	if (msg->msg_control)
+	if (msg->msg_controllen)
 	{
 		int err;
 
@@ -248,6 +248,7 @@
 	struct in6_addr *daddr;
 	struct raw6_opt *raw_opt;
 	u16 proto;
+	int hlimit = 0;
 	int err;
 	
 
@@ -315,7 +316,7 @@
 		opt = &opt_space;
 		memset(opt, 0, sizeof(struct ipv6_options));
 
-		err = datagram_send_ctl(msg, &dev, &saddr, opt);
+		err = datagram_send_ctl(msg, &dev, &saddr, opt, &hlimit);
 		if (err < 0)
 		{
 			printk(KERN_DEBUG "invalid msg_control\n");
@@ -346,12 +347,13 @@
 		}
 
 		err = ipv6_build_xmit(sk, rawv6_frag_cksum, &hdr, daddr, len,
-				      saddr, dev, opt, proto, msg->msg_flags&MSG_DONTWAIT);
+				      saddr, dev, opt, proto, hlimit,
+				      msg->msg_flags&MSG_DONTWAIT);
 	}
 	else
 	{
 		err = ipv6_build_xmit(sk, rawv6_getfrag, msg->msg_iov, daddr,
-				      len, saddr, dev, opt, proto,
+				      len, saddr, dev, opt, proto, hlimit,
 				      msg->msg_flags&MSG_DONTWAIT);
 	}
 
diff -u --recursive --new-file v2.1.20/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.1.20/linux/net/ipv6/udp.c	Thu Dec 12 19:37:31 1996
+++ linux/net/ipv6/udp.c	Tue Jan 14 08:16:49 1997
@@ -506,6 +506,7 @@
 	struct in6_addr *saddr = NULL;
 	int len = ulen + sizeof(struct udphdr);
 	int addr_type;
+	int hlimit = 0;
 	int err;
 
 	
@@ -560,7 +561,7 @@
 		opt = &opt_space;
 		memset(opt, 0, sizeof(struct ipv6_options));
 
-		err = datagram_send_ctl(msg, &dev, &saddr, opt);
+		err = datagram_send_ctl(msg, &dev, &saddr, opt, &hlimit);
 		if (err < 0)
 		{
 			printk(KERN_DEBUG "invalid msg_control\n");
@@ -581,7 +582,8 @@
 	udh.pl_len = len;
 	
 	err = ipv6_build_xmit(sk, udpv6_getfrag, &udh, daddr, len,
-			      saddr, dev, opt, IPPROTO_UDP, msg->msg_flags&MSG_DONTWAIT);
+			      saddr, dev, opt, IPPROTO_UDP, hlimit,
+			      msg->msg_flags&MSG_DONTWAIT);
 	
 	if (err < 0)
 		return err;
diff -u --recursive --new-file v2.1.20/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.1.20/linux/net/ipx/af_ipx.c	Thu Jan  2 15:55:28 1997
+++ linux/net/ipx/af_ipx.c	Fri Jan  3 11:33:27 1997
@@ -62,9 +62,8 @@
  *	"AS-IS" and at no charge.
  */
 
-#include <linux/module.h>
-
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
diff -u --recursive --new-file v2.1.20/linux/net/socket.c linux/net/socket.c
--- v2.1.20/linux/net/socket.c	Thu Jan  2 15:55:29 1997
+++ linux/net/socket.c	Tue Jan 14 08:16:49 1997
@@ -1193,9 +1193,10 @@
 	struct iovec *iov=iovstack;
 	struct msghdr msg_sys;
 	void * krn_msg_ctl = NULL;
+	void * usr_msg_ctl = NULL;
 	int err;
 	int total_len;
-	int len;
+	int len = 0;
 
 	/* kernel mode address */
 	char addr[MAX_SOCK_ADDR];
@@ -1233,6 +1234,12 @@
 
 	if (msg_sys.msg_controllen)
 	{
+		/*
+		 *	FIXME:
+		 *	I'm assuming that the kernel may have to examine
+		 *	the acciliary control messages passed by the user.
+		 *	Find out what POSIX says about this...
+		 */
 		krn_msg_ctl = kmalloc(msg_sys.msg_controllen, GFP_KERNEL);
 		
 		if (!krn_msg_ctl)
@@ -1243,7 +1250,11 @@
 		err = copy_from_user(krn_msg_ctl, msg_sys.msg_control,
 				     msg_sys.msg_controllen);
 		if (err)
+		{
+			err = -EFAULT;
 			goto flush_it;
+		}
+		usr_msg_ctl = msg_sys.msg_control;
 		msg_sys.msg_control = krn_msg_ctl;
 	}
 
@@ -1263,12 +1274,11 @@
 	{
 		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
 					uaddr_len);
-
 	}
 	
-	if (!err && msg_sys.msg_controllen)
+	if (err >= 0 && msg_sys.msg_controllen)
 	{
-		err = copy_to_user(msg_sys.msg_control, krn_msg_ctl,
+		err = copy_to_user(usr_msg_ctl, krn_msg_ctl,
 				   msg_sys.msg_controllen);
 	}
 
@@ -1281,7 +1291,7 @@
 		kfree(krn_msg_ctl);
 	}
 
-	if (err)
+	if (err < 0)
 		return err;
 
 	if (put_user(msg_sys.msg_flags, &msg->msg_flags))
diff -u --recursive --new-file v2.1.20/linux/scripts/Configure linux/scripts/Configure
--- v2.1.20/linux/scripts/Configure	Fri May 31 13:46:27 1996
+++ linux/scripts/Configure	Fri Jan  3 11:33:27 1997
@@ -422,6 +422,7 @@
 echo "/*" > $CONFIG_H
 echo " * Automatically generated C config: don't edit" >> $CONFIG_H
 echo " */" >> $CONFIG_H
+echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
 
 DEFAULT=""
 if [ "$1" = "-d" ] ; then
diff -u --recursive --new-file v2.1.20/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.1.20/linux/scripts/Menuconfig	Tue Oct 29 19:58:51 1996
+++ linux/scripts/Menuconfig	Fri Jan  3 11:33:27 1997
@@ -1020,6 +1020,7 @@
 	echo "/*" >$CONFIG_H
 	echo " * Automatically generated by make menuconfig: don't edit" >>$CONFIG_H
 	echo " */" >>$CONFIG_H
+	echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
 
 	MAKE=:	#To prevent sound Makefile from running.
 	
diff -u --recursive --new-file v2.1.20/linux/scripts/mkdep.c linux/scripts/mkdep.c
--- v2.1.20/linux/scripts/mkdep.c	Sun Dec 22 16:38:16 1996
+++ linux/scripts/mkdep.c	Fri Jan  3 11:33:27 1997
@@ -9,7 +9,7 @@
 #include <sys/mman.h>
 
 char *filename, *command, __depname[256] = "\n\t@touch ";
-int needsconfig, hasconfig, hasdep;
+int needsconfig, hasconfig, hasmodules, hasdep;
 
 #define depname (__depname+9)
 
@@ -26,8 +26,11 @@
 	int plen;
 	struct path_struct *path = path_array+type;
 
-	if (len == 14 && !memcmp(name, "linux/config.h", len))
-		hasconfig = 1;
+	if (len == 14)
+		if (!memcmp(name, "linux/config.h", len))
+			hasconfig = 1;
+		else if (!memcmp(name, "linux/module.h", len))
+			hasmodules = 1;
 
 	plen = path->len;
 	memcpy(path->buffer+plen, name, len);
@@ -287,9 +290,9 @@
 					command = "";
 			}
 		}
-		needsconfig = hasconfig = hasdep = 0;
+		needsconfig = hasconfig = hasmodules = hasdep = 0;
 		do_depend();
-		if (hasconfig && !needsconfig)
+		if (hasconfig && !hasmodules && !needsconfig)
 			fprintf(stderr, "%s doesn't need config\n", filename);
 	}
 	return 0;
diff -u --recursive --new-file v2.1.20/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.1.20/linux/scripts/tkgen.c	Thu Jun  6 13:30:41 1996
+++ linux/scripts/tkgen.c	Fri Jan  3 11:33:27 1997
@@ -978,6 +978,7 @@
   printf("\tputs $autocfg \"/*\"\n");
   printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
   printf("\tputs $autocfg \" */\"\n");
+  printf("\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n");
   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
     {
       switch (cfg->tok)
