## Automatically generated incremental diff
## From:   linux-2.0.31-pre6
## To:     linux-2.0.31-pre7
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.0.31-pre6/arch/i386/mm/fault.c linux-2.0.31-pre7/arch/i386/mm/fault.c
--- linux-2.0.31-pre6/arch/i386/mm/fault.c	1996-09-11 07:57:13.000000000 -0700
+++ linux-2.0.31-pre7/arch/i386/mm/fault.c	2003-08-15 15:04:04.000000000 -0700
@@ -130,10 +130,9 @@
 		printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
 		return;
 	}
-	if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
+	if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-		pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
-	} else
+	else
 		printk(KERN_ALERT "Unable to handle kernel paging request");
 	printk(" at virtual address %08lx\n",address);
 	__asm__("movl %%cr3,%0" : "=r" (page));
diff -urN linux-2.0.31-pre6/CREDITS linux-2.0.31-pre7/CREDITS
--- linux-2.0.31-pre6/CREDITS	2003-08-15 15:04:03.000000000 -0700
+++ linux-2.0.31-pre7/CREDITS	2003-08-15 15:04:04.000000000 -0700
@@ -715,10 +715,9 @@
 N: Alain L. Knaff
 E: Alain.Knaff@imag.fr
 D: floppy driver
-S: Appartement 310B
-S: 11, rue General Mangin
-S: 38100 Grenoble
-S: France
+S: 19, rue Jean l'Aveugle
+S: L-1148 Luxembourg-City
+S: Luxembourg
 
 N: Harald Koenig
 E: koenig@tat.physik.uni-tuebingen.de
diff -urN linux-2.0.31-pre6/Documentation/Changes linux-2.0.31-pre7/Documentation/Changes
--- linux-2.0.31-pre6/Documentation/Changes	2003-08-15 15:04:03.000000000 -0700
+++ linux-2.0.31-pre7/Documentation/Changes	2003-08-15 15:04:04.000000000 -0700
@@ -5,7 +5,10 @@
 important packages for Linux as well as instructions for newcomers to
 the 2.0.x series of kernels.  By glancing through it, you should be
 able to find out what you need to upgrade in order to successfully run
-the latest kernels.
+the latest kernels.  Note that I tend to mention the earliest releases
+of software known to work, not necessarily the latest and greatest
+versions, as the goal is to provide you with a list of sure-to-work
+software.
 
    It was originally based on material from the linux-kernel mailing
 list, Jared Mauch's web page "Software Victims of the 1.3 Kernel
@@ -35,9 +38,9 @@
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
    Voyez le site http://www.linux-kheops.com/traduc/kernels/ pour la
-traduction francais (merci, David Bourgin).  (French translation)
+traduction francaise (merci, David Bourgin).  (French translation)
 
-Last updated: November 5, 1996.
+Last updated: August 14, 1997.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -48,7 +51,7 @@
 - Dynamic linker (ld.so) 1.7.14
 - GNU CC		 2.7.2.1
 - Binutils		 2.7.0.3
-- Linux C Library	 Stable:  5.2.18, Beta:  5.4.10
+- Linux C Library	 Stable:  5.2.18, Beta:  5.4.33
 - Linux C++ Library	 2.7.2.1
 - Termcap		 2.0.8
 - Procps		 1.01
@@ -123,22 +126,24 @@
 `release.libc-5.2.18' file, since GNU make and a few other fairly
 important utils can be broken by the upgrade.
 
-   The current (beta) Linux C Library release is 5.3.12. In this
-release there are some important changes that may cause troubles to
-buggy programs (programs that call free() on a pointer not returned by
-malloc() work with previous libc, but not with this release) so read the
-`release.libc-5.3.12' file carefully!  In the latest libc releases a
-dirent bug, which erroneously defined d->reclen to d->namlen if USE_GNU
-was defined, has been fixed.  Unfortunately, some GNU packages depend
-on this bug.  GNU make 3.xx is one of them.  To fix that you need to
-patch and recompile those programs (a patch for make is included in the
-file `release.libc-.5.3.9', and the address to obtain a precompiled
-binary is at the end of this file).
+   A current common Linux C Library release is 5.3.12. In this release
+there are some important changes that may cause troubles to buggy
+programs (programs that call free() on a pointer not returned by
+malloc(), such as Netscape, work with previous libc, but not with this
+release) so read the `release.libc-5.3.12' file carefully!  In the
+latest libc releases a dirent bug, which erroneously defined d->reclen
+to d->namlen if USE_GNU was defined, has been fixed.  Unfortunately,
+some GNU packages depend on this bug.  GNU make 3.xx is one of them.
+To fix that you need to patch and recompile those programs (a patch for
+make is included in the file `release.libc-.5.3.9', and the address to
+obtain a precompiled binary is at the end of this file).
 
    Also, the libc-5.3.x line has a known security hole relating to
 rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.10 is
-currently available as well, but it may have problems, so caveat emptor.
+experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.33 is
+currently available as well, but it may have problems, so caveat
+emptor.  It fixes lots of problems, but make break even more programs
+than 5.3.12.
 
    If you're getting an error message that is something to the effect of
 
@@ -273,7 +278,7 @@
 details.  Among the programs this has impacted are older sendmails.  If
 you get a message that sendmail cannot lock aliases.dir (or other
 files), you'll need to upgrade to at least 8.7.x. The latest sendmail
-is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.2.tar.gz.
+is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.7.tar.gz.
 
 Uugetty
 =======
@@ -295,7 +300,7 @@
 currently at release 2.5.  Some may find, especially when using the
 loop or xiafs file system, NFS, or automounting, that they need to
 upgrade to the latest release of mount, available from
-ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6g.tar.gz.
+ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5p.tar.gz.
 
 Console
 =======
@@ -626,10 +631,10 @@
 Installation notes for 5.2.18:
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
 
-The latest 5.4.10 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.10.bin.tar.gz
-Installation notes for 5.4.10:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.10
+The latest 5.4.33 release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.33.bin.tar.gz
+Installation notes for 5.4.33:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.33
 
 Patched make sources:
 ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz
@@ -679,14 +684,12 @@
 SysVinit utilities
 ==================
 
-ftp://sunsite.unc.edu/pub/Linux/system/daemons/init/sysvinit-2.64.tar.gz
-or for the very latest:
-ftp://ftp.debian.org/debian/unstable/source/base/sysvinit_2.71-1.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz
 
 Util-linux
 ==========
 
-ftp://sunsite.unc.edu/pub/Linux/system/misc/util-linux-2.6.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/system/Misc/util-linux-2.5.tar.gz
 
 Mtools
 ======
diff -urN linux-2.0.31-pre6/drivers/net/eth16i.c linux-2.0.31-pre7/drivers/net/eth16i.c
--- linux-2.0.31-pre6/drivers/net/eth16i.c	1997-04-08 08:47:45.000000000 -0700
+++ linux-2.0.31-pre7/drivers/net/eth16i.c	2003-08-15 15:04:04.000000000 -0700
@@ -61,6 +61,11 @@
    0.21         17.10-95        Removed the unnecessary extern 
 				init_etherdev() declaration. Some
 				other cleanups.
+
+   0.21a	15.08-97	Made signature check less restrictive to
+				detect card that have been used for booting
+				with a bootprom.
+				Kurt Huwig <kurt@huwig.de>
    Bugs:
 	In some cases the interface autoprobing code doesn't find 
 	the correct interface type. In this case you can 
@@ -72,7 +77,7 @@
 */
 
 static char *version = 
-	"eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@elt.icl.fi)\n";
+	"eth16i.c: v0.21a 15-08-97 Mika Kuoppala (miku@elt.icl.fi)/Kurt Huwig (kurt@huwig.de)\n";
 
 #include <linux/module.h>
 
@@ -722,10 +727,10 @@
 #endif
 
   if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
-      creg[2] &= 0x42;
+      creg[2] &= 0x40;
       creg[3] &= 0x03;
 
-      if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
+      if( !( (creg[2] == 0x40) && (creg[3] == 0x00)) )
 	return -1;
   }
 
diff -urN linux-2.0.31-pre6/drivers/net/ne.c linux-2.0.31-pre7/drivers/net/ne.c
--- linux-2.0.31-pre6/drivers/net/ne.c	2003-08-15 15:04:03.000000000 -0700
+++ linux-2.0.31-pre7/drivers/net/ne.c	2003-08-15 15:04:04.000000000 -0700
@@ -75,6 +75,8 @@
 	{PCI_VENDOR_ID_REALTEK,		PCI_DEVICE_ID_REALTEK_8029},
 	{PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940},
 	{PCI_VENDOR_ID_COMPEX,		PCI_DEVICE_ID_COMPEX_RL2000},
+	{PCI_VENDOR_ID_KTI,		PCI_DEVICE_ID_KTI_ET32P2},
+	{PCI_VENDOR_ID_NETVIN,		PCI_DEVICE_ID_NETVIN_NV5000SC},
 	{0,}
 };
 #endif
diff -urN linux-2.0.31-pre6/drivers/pci/pci.c linux-2.0.31-pre7/drivers/pci/pci.c
--- linux-2.0.31-pre6/drivers/pci/pci.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/drivers/pci/pci.c	2003-08-15 15:04:04.000000000 -0700
@@ -591,7 +591,9 @@
 	      case PCI_VENDOR_ID_COMPEX:	return "Compex";
 	      case PCI_VENDOR_ID_RP:		return "Comtrol";
 	      case PCI_VENDOR_ID_CYCLADES:	return "Cyclades";
+	      case PCI_VENDOR_ID_3DFX:		return "3DFX";
 	      case PCI_VENDOR_ID_SIGMA_DESIGNS:	return "Sigma Designs";
+ 	      case PCI_VENDOR_ID_OPTIBASE:	return "Optibase Inc.";
 	      case PCI_VENDOR_ID_SYMPHONY:	return "Symphony";
 	      case PCI_VENDOR_ID_TEKRAM:	return "Tekram";
 	      case PCI_VENDOR_ID_3DLABS:	return "3Dlabs";
diff -urN linux-2.0.31-pre6/drivers/scsi/Config.in linux-2.0.31-pre7/drivers/scsi/Config.in
--- linux-2.0.31-pre6/drivers/scsi/Config.in	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/drivers/scsi/Config.in	2003-08-15 15:04:04.000000000 -0700
@@ -21,7 +21,7 @@
 dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
 if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
     bool '   Enable tagged command queueing' CONFIG_AIC7XXX_TAGGED_QUEUEING Y
-    dep_tristate '   Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N
+    bool '   Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N
     if [ "$CONFIG_OVERRIDE_CMDS" != "n" ]; then
       int  '   Maximum number of commands per LUN' CONFIG_AIC7XXX_CMDS_PER_LUN 8
     fi
diff -urN linux-2.0.31-pre6/drivers/scsi/g_NCR5380.c linux-2.0.31-pre7/drivers/scsi/g_NCR5380.c
--- linux-2.0.31-pre6/drivers/scsi/g_NCR5380.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/drivers/scsi/g_NCR5380.c	2003-08-15 15:04:04.000000000 -0700
@@ -614,6 +614,7 @@
     int i;
     struct Scsi_Host *scsi_ptr;
     Scsi_Cmnd *ptr;
+    Scsi_Device *dev;
     struct NCR5380_hostdata *hostdata;
 
     cli();
diff -urN linux-2.0.31-pre6/drivers/scsi/scsi_syms.c linux-2.0.31-pre7/drivers/scsi/scsi_syms.c
--- linux-2.0.31-pre6/drivers/scsi/scsi_syms.c	1996-05-01 21:48:54.000000000 -0700
+++ linux-2.0.31-pre7/drivers/scsi/scsi_syms.c	2003-08-15 15:04:04.000000000 -0700
@@ -63,6 +63,7 @@
     X(print_Scsi_Cmnd),
     X(scsi_mark_host_reset),
     X(scsi_mark_bus_reset),
+    X(scsi_device_types),
 #if defined(CONFIG_PROC_FS)
     X(proc_print_scsidevice),
 #endif
diff -urN linux-2.0.31-pre6/fs/bad_inode.c linux-2.0.31-pre7/fs/bad_inode.c
--- linux-2.0.31-pre6/fs/bad_inode.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.0.31-pre7/fs/bad_inode.c	2003-08-15 15:04:04.000000000 -0700
@@ -0,0 +1,77 @@
+/*
+ *  linux/fs/bad_inode.c
+ *
+ *  Copyright (C) 1997, Stephen Tweedie
+ *
+ *  Provide stub functions for unreadable inodes
+ */
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+
+static int return_EIO()
+{
+	return -EIO;
+}
+
+#define EIO_ERROR ((void *) (return_EIO))
+
+static struct file_operations bad_file_ops =
+{
+	EIO_ERROR,		/* lseek */
+	EIO_ERROR,		/* read */
+	EIO_ERROR,		/* write */
+	EIO_ERROR,		/* readdir */
+	EIO_ERROR,		/* select */
+	EIO_ERROR,		/* ioctl */
+	EIO_ERROR,		/* mmap */
+	EIO_ERROR,		/* open */
+	EIO_ERROR,		/* release */
+	EIO_ERROR,		/* fsync */
+	EIO_ERROR,		/* fasync */
+	EIO_ERROR,		/* check_media_change */
+	EIO_ERROR		/* revalidate */
+};
+
+static struct inode_operations bad_inode_ops =
+{
+	&bad_file_ops,		/* default file operations */
+	EIO_ERROR,		/* create */
+	EIO_ERROR,		/* lookup */
+	EIO_ERROR,		/* link */
+	EIO_ERROR,		/* unlink */
+	EIO_ERROR,		/* symlink */
+	EIO_ERROR,		/* mkdir */
+	EIO_ERROR,		/* rmdir */
+	EIO_ERROR,		/* mknod */
+	EIO_ERROR,		/* rename */
+	EIO_ERROR,		/* readlink */
+	EIO_ERROR,		/* follow_link */
+	EIO_ERROR,		/* readpage */
+	EIO_ERROR,		/* writepage */
+	EIO_ERROR,		/* bmap */
+	EIO_ERROR,		/* truncate */
+	EIO_ERROR,		/* permission */
+	EIO_ERROR		/* smap */
+};
+
+
+/* 
+ * When a filesystem is unable to read an inode due to an I/O error in
+ * its read_inode() function, it can call make_bad_inode() to return a
+ * set of stubs which will return EIO errors as required. 
+ *
+ * We only need to do limited initialisation: all other fields are
+ * preinitialised to zero automatically.
+ */
+void make_bad_inode(struct inode * inode) 
+{
+	inode->i_mode = S_IFREG;
+	inode->i_flags = S_BAD_INODE;
+	inode->i_atime = CURRENT_TIME;
+	inode->i_mtime = CURRENT_TIME;
+	inode->i_ctime = CURRENT_TIME;
+	inode->i_op = &bad_inode_ops;	
+}
+
diff -urN linux-2.0.31-pre6/fs/buffer.c linux-2.0.31-pre7/fs/buffer.c
--- linux-2.0.31-pre6/fs/buffer.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/fs/buffer.c	2003-08-15 15:04:04.000000000 -0700
@@ -672,6 +672,7 @@
 		};
 	}
 
+#if 0
 	/*
 	 * In order to protect our reserved pages, 
 	 * return now if we got any buffers.
@@ -682,6 +683,8 @@
 	/* and repeat until we find something good */
 	if (!grow_buffers(GFP_ATOMIC, size))
 		wakeup_bdflush(1);
+#endif
+	wakeup_bdflush(1);
 
 	/* decrease needed even if there is no success */
 	needed -= PAGE_SIZE;
@@ -1719,11 +1722,11 @@
 			continue;
 		}
 		run_task_queue(&tq_disk);
-		wake_up(&bdflush_done);
 		
 		/* If there are still a lot of dirty buffers around, skip the sleep
 		   and flush some more */
 		if(nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
+			wake_up(&bdflush_done);
 			current->signal = 0;
 			interruptible_sleep_on(&bdflush_wait);
 		}
diff -urN linux-2.0.31-pre6/fs/ext2/balloc.c linux-2.0.31-pre7/fs/ext2/balloc.c
--- linux-2.0.31-pre6/fs/ext2/balloc.c	1996-01-04 04:14:20.000000000 -0800
+++ linux-2.0.31-pre7/fs/ext2/balloc.c	2003-08-15 15:04:04.000000000 -0700
@@ -43,6 +43,10 @@
 	unsigned long desc;
 	struct ext2_group_desc * gdp;
 
+	/*
+	 * This panic should never trigger on a bad filesystem: the caller
+	 * should have verified the block/group number already.
+	 */
 	if (block_group >= sb->u.ext2_sb.s_groups_count)
 		ext2_panic (sb, "get_group_desc",
 			    "block_group >= groups_count - "
@@ -63,22 +67,37 @@
 	return gdp + desc;
 }
 
-static void read_block_bitmap (struct super_block * sb,
-			       unsigned int block_group,
-			       unsigned long bitmap_nr)
+/*
+ * Read the bitmap for a given block_group, reading into the specified 
+ * slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_block_bitmap (struct super_block * sb,
+			      unsigned int block_group,
+			      unsigned long bitmap_nr)
 {
 	struct ext2_group_desc * gdp;
 	struct buffer_head * bh;
+	int retval = 0;
 	
 	gdp = get_group_desc (sb, block_group, NULL);
 	bh = bread (sb->s_dev, gdp->bg_block_bitmap, sb->s_blocksize);
-	if (!bh)
-		ext2_panic (sb, "read_block_bitmap",
+	if (!bh) {
+		ext2_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %lu",
 			    block_group, (unsigned long) gdp->bg_block_bitmap);
+		retval = -EIO;
+	}
+	/*
+	 * On IO error, just leave a zero in the superblock's block pointer for
+	 * this group.  The IO will be retried next time.
+	 */
 	sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
 	sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
+	return retval;
 }
 
 /*
@@ -91,11 +110,13 @@
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ *
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load__block_bitmap (struct super_block * sb,
 			       unsigned int block_group)
 {
-	int i, j;
+	int i, j, retval = 0;
 	unsigned long block_bitmap_number;
 	struct buffer_head * block_bitmap;
 
@@ -114,7 +135,9 @@
 			else
 				return block_group;
 		} else {
-			read_block_bitmap (sb, block_group, block_group);
+			retval = read_block_bitmap (sb, block_group, block_group);
+			if (retval < 0)
+				return retval;
 			return block_group;
 		}
 	}
@@ -134,6 +157,14 @@
 		}
 		sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number;
 		sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap;
+
+		/*
+		 * There's still one special case here --- if block_bitmap == 0
+		 * then our last attempt to read the bitmap failed and we have
+		 * just ended up caching that failure.  Try again to read it.
+		 */
+		if (!block_bitmap)
+			retval = read_block_bitmap (sb, block_group, 0);
 	} else {
 		if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
 			sb->u.ext2_sb.s_loaded_block_bitmaps++;
@@ -145,24 +176,71 @@
 			sb->u.ext2_sb.s_block_bitmap[j] =
 				sb->u.ext2_sb.s_block_bitmap[j - 1];
 		}
-		read_block_bitmap (sb, block_group, 0);
+		retval = read_block_bitmap (sb, block_group, 0);
 	}
-	return 0;
+	return retval;
 }
 
+/*
+ * Load the block bitmap for a given block group.  First of all do a couple
+ * of fast lookups for common cases and then pass the request onto the guts
+ * of the bitmap loader.
+ *
+ * Return the slot number of the group in the superblock bitmap cache's on
+ * success, or a -ve error code.
+ *
+ * There is still one inconsistancy here --- if the number of groups in this
+ * filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of 
+ * differentiating between a group for which we have never performed a bitmap
+ * IO request, and a group for which the last bitmap read request failed.
+ */
 static inline int load_block_bitmap (struct super_block * sb,
 				     unsigned int block_group)
 {
-	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
-	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group)
-		return 0;
+	int slot;
 	
-	if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
-	    sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
-	    sb->u.ext2_sb.s_block_bitmap[block_group]) 
-		return block_group;
+	/*
+	 * Do the lookup for the slot.  First of all, check if we're asking
+	 * for the same slot as last time, and did we succeed that last time?
+	 */
+	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
+	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
+	    sb->u.ext2_sb.s_block_bitmap[block_group]) {
+		slot = 0;
+	}
+	/*
+	 * Or can we do a fast lookup based on a loaded group on a filesystem
+	 * small enough to be mapped directly into the superblock?
+	 */
+	else if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
+		 sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
+		 sb->u.ext2_sb.s_block_bitmap[block_group]) {
+		slot = block_group;
+	} 
+	/*
+	 * If not, then do a full lookup for this block group.
+	 */
+	else {
+		slot = load__block_bitmap (sb, block_group);
+	}
 
-	return load__block_bitmap (sb, block_group);
+	/*
+	 * <0 means we just got an error
+	 */
+	if (slot < 0)
+		return slot;
+	
+	/*
+	 * If it's a valid slot, we may still have cached a previous IO error,
+	 * in which case the bh in the superblock cache will be zero.
+	 */
+	if (!sb->u.ext2_sb.s_block_bitmap[slot])
+		return -EIO;
+	
+	/*
+	 * Must have been read in OK to get this far.
+	 */
+	return slot;
 }
 
 void ext2_free_blocks (const struct inode * inode, unsigned long block,
@@ -199,12 +277,19 @@
 	block_group = (block - es->s_first_data_block) /
 		      EXT2_BLOCKS_PER_GROUP(sb);
 	bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
-	if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
-		ext2_panic (sb, "ext2_free_blocks",
+	if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) {
+		ext2_error (sb, "ext2_free_blocks",
 			    "Freeing blocks across group boundary - "
 			    "Block = %lu, count = %lu",
 			    block, count);
+		unlock_super (sb);
+		return;
+	}
+	
 	bitmap_nr = load_block_bitmap (sb, block_group);
+	if (bitmap_nr < 0)
+		goto error_return;
+		
 	bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 	gdp = get_group_desc (sb, block_group, &bh2);
 
@@ -214,11 +299,14 @@
 	     in_range (block, gdp->bg_inode_table,
 		       sb->u.ext2_sb.s_itb_per_group) ||
 	     in_range (block + count - 1, gdp->bg_inode_table,
-		       sb->u.ext2_sb.s_itb_per_group)))
-		ext2_panic (sb, "ext2_free_blocks",
+		       sb->u.ext2_sb.s_itb_per_group))) {
+		ext2_error (sb, "ext2_free_blocks",
 			    "Freeing blocks in system zones - "
 			    "Block = %lu, count = %lu",
 			    block, count);
+		unlock_super (sb);
+		return;
+	}
 
 	for (i = 0; i < count; i++) {
 		if (!clear_bit (bit + i, bh->b_data))
@@ -242,6 +330,7 @@
 		wait_on_buffer (bh);
 	}
 	sb->s_dirt = 1;
+error_return:
 	unlock_super (sb);
 	return;
 }
@@ -301,6 +390,12 @@
 			goal_attempts++;
 #endif
 		bitmap_nr = load_block_bitmap (sb, i);
+		if (bitmap_nr < 0) {
+			*err = -EIO;
+			unlock_super (sb);
+			return 0;
+		}
+		
 		bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
 		ext2_debug ("goal is at %d:%d.\n", i, j);
@@ -372,7 +467,14 @@
 		unlock_super (sb);
 		return 0;
 	}
+
 	bitmap_nr = load_block_bitmap (sb, i);
+	if (bitmap_nr < 0) {
+		*err = -EIO;
+		unlock_super (sb);
+		return 0;
+	}
+		
 	bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 	r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
 	j = (r - bh->b_data) << 3;
@@ -415,10 +517,14 @@
 	if (test_opt (sb, CHECK_STRICT) &&
 	    (tmp == gdp->bg_block_bitmap ||
 	     tmp == gdp->bg_inode_bitmap ||
-	     in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
-		ext2_panic (sb, "ext2_new_block",
+	     in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group))) {
+		ext2_error (sb, "ext2_new_block",
 			    "Allocating block in system zone - "
 			    "block = %u", tmp);
+		unlock_super (sb);
+		*err = -EIO;
+		return 0;
+	}
 
 	if (set_bit (j, bh->b_data)) {
 		ext2_warning (sb, "ext2_new_block",
@@ -511,7 +617,11 @@
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
 		gdp = get_group_desc (sb, i, NULL);
 		desc_count += gdp->bg_free_blocks_count;
+
 		bitmap_nr = load_block_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+		
 		x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
 				     sb->s_blocksize);
 		printk ("group %d: stored = %d, counted = %lu\n",
@@ -556,6 +666,9 @@
 		gdp = get_group_desc (sb, i, NULL);
 		desc_count += gdp->bg_free_blocks_count;
 		bitmap_nr = load_block_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+
 		bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
 		if (!test_bit (0, bh->b_data))
diff -urN linux-2.0.31-pre6/fs/ext2/ialloc.c linux-2.0.31-pre7/fs/ext2/ialloc.c
--- linux-2.0.31-pre6/fs/ext2/ialloc.c	1996-11-30 02:21:20.000000000 -0800
+++ linux-2.0.31-pre7/fs/ext2/ialloc.c	2003-08-15 15:04:04.000000000 -0700
@@ -62,22 +62,37 @@
 	return gdp + desc;
 }
 
-static void read_inode_bitmap (struct super_block * sb,
-			       unsigned long block_group,
-			       unsigned int bitmap_nr)
+/*
+ * Read the inode allocation bitmap for a given block_group, reading
+ * into the specified slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_inode_bitmap (struct super_block * sb,
+			      unsigned long block_group,
+			      unsigned int bitmap_nr)
 {
 	struct ext2_group_desc * gdp;
 	struct buffer_head * bh;
+	int retval = 0;
 
 	gdp = get_group_desc (sb, block_group, NULL);
 	bh = bread (sb->s_dev, gdp->bg_inode_bitmap, sb->s_blocksize);
-	if (!bh)
-		ext2_panic (sb, "read_inode_bitmap",
+	if (!bh) {
+		ext2_error (sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
 			    "block_group = %lu, inode_bitmap = %lu",
 			    block_group, (unsigned long) gdp->bg_inode_bitmap);
+		retval = -EIO;
+	}
+	/*
+	 * On IO error, just leave a zero in the superblock's block pointer for
+	 * this group.  The IO will be retried next time.
+	 */
 	sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
 	sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
+	return retval;
 }
 
 /*
@@ -90,11 +105,13 @@
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ *
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load_inode_bitmap (struct super_block * sb,
 			      unsigned int block_group)
 {
-	int i, j;
+	int i, j, retval = 0;
 	unsigned long inode_bitmap_number;
 	struct buffer_head * inode_bitmap;
 
@@ -114,7 +131,9 @@
 			else
 				return block_group;
 		} else {
-			read_inode_bitmap (sb, block_group, block_group);
+			retval = read_inode_bitmap (sb, block_group, block_group);
+			if (retval < 0)
+				return retval;
 			return block_group;
 		}
 	}
@@ -135,6 +154,14 @@
 		}
 		sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
 		sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap;
+
+		/*
+		 * There's still one special case here --- if inode_bitmap == 0
+		 * then our last attempt to read the bitmap failed and we have
+		 * just ended up caching that failure.  Try again to read it.
+		 */
+		if (!inode_bitmap)
+			retval = read_inode_bitmap (sb, block_group, 0);
 	} else {
 		if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
 			sb->u.ext2_sb.s_loaded_inode_bitmaps++;
@@ -146,9 +173,9 @@
 			sb->u.ext2_sb.s_inode_bitmap[j] =
 				sb->u.ext2_sb.s_inode_bitmap[j - 1];
 		}
-		read_inode_bitmap (sb, block_group, 0);
+		retval = read_inode_bitmap (sb, block_group, 0);
 	}
-	return 0;
+	return retval;
 }
 
 void ext2_free_inode (struct inode * inode)
@@ -198,6 +225,11 @@
 	block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(sb);
 	bit = (inode->i_ino - 1) % EXT2_INODES_PER_GROUP(sb);
 	bitmap_nr = load_inode_bitmap (sb, block_group);
+	if (bitmap_nr < 0) {
+		unlock_super (sb);
+		return;
+	}
+	
 	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
 	if (!clear_bit (bit, bh->b_data))
 		ext2_warning (sb, "ext2_free_inode",
@@ -352,6 +384,13 @@
 		return NULL;
 	}
 	bitmap_nr = load_inode_bitmap (sb, i);
+	if (bitmap_nr < 0) {
+		unlock_super (sb);
+		iput(inode);
+		*err = -EIO;
+		return NULL;
+	}
+	
 	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
 	if ((j = find_first_zero_bit ((unsigned long *) bh->b_data,
 				      EXT2_INODES_PER_GROUP(sb))) <
@@ -465,6 +504,9 @@
 		gdp = get_group_desc (sb, i, NULL);
 		desc_count += gdp->bg_free_inodes_count;
 		bitmap_nr = load_inode_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+		
 		x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
 				     EXT2_INODES_PER_GROUP(sb) / 8);
 		printk ("group %d: stored = %d, counted = %lu\n",
@@ -497,6 +539,9 @@
 		gdp = get_group_desc (sb, i, NULL);
 		desc_count += gdp->bg_free_inodes_count;
 		bitmap_nr = load_inode_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+		
 		x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
 				     EXT2_INODES_PER_GROUP(sb) / 8);
 		if (gdp->bg_free_inodes_count != x)
diff -urN linux-2.0.31-pre6/fs/ext2/inode.c linux-2.0.31-pre7/fs/ext2/inode.c
--- linux-2.0.31-pre6/fs/ext2/inode.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/fs/ext2/inode.c	2003-08-15 15:04:04.000000000 -0700
@@ -432,9 +432,12 @@
 	group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
 	desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
 	bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
-	if (!bh)
-		ext2_panic (inode->i_sb, "ext2_read_inode",
+	if (!bh) {
+		ext2_error (inode->i_sb, "ext2_read_inode",
 			    "Descriptor not loaded");
+		goto bad_inode;
+	}
+	
 	gdp = (struct ext2_group_desc *) bh->b_data;
 	/*
 	 * Figure out the offset within the block group inode table
@@ -443,10 +446,13 @@
 		EXT2_INODE_SIZE(inode->i_sb);
 	block = gdp[desc].bg_inode_table +
 		(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-		ext2_panic (inode->i_sb, "ext2_read_inode",
-			    "unable to read i-node block - "
+	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+		ext2_error (inode->i_sb, "ext2_read_inode",
+			    "unable to read inode block - "
 			    "inode=%lu, block=%lu", inode->i_ino, block);
+		goto bad_inode;
+	}
+	
 	offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
 	raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -506,6 +512,11 @@
 		inode->i_flags |= S_IMMUTABLE;
 	if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL)
 		inode->i_flags |= MS_NOATIME;
+	return;
+	
+bad_inode:
+	make_bad_inode(inode);
+	return;
 }
 
 static int ext2_update_inode(struct inode * inode, int do_sync)
@@ -545,10 +556,23 @@
 		EXT2_INODE_SIZE(inode->i_sb);
 	block = gdp[desc].bg_inode_table +
 		(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-		ext2_panic (inode->i_sb, "ext2_write_inode",
-			    "unable to read i-node block - "
+	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+		ext2_error (inode->i_sb, "ext2_write_inode",
+			    "unable to read inode block - "
 			    "inode=%lu, block=%lu", inode->i_ino, block);
+		/*
+		 * Unfortunately we're in a lose-lose situation.  I think that
+		 * keeping the inode in-core with the dirty bit set is 
+		 * the worse option, since that will soak up inodes until
+		 * the end of the world.  Clearing the dirty bit is nasty if
+		 * we haven't succeeded in writing out, but it's less nasty
+		 * than the alternative. -- sct
+		 */
+		inode->i_dirt = 0;
+		
+		return -EIO;
+	}
+	
 	offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;
 	raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -579,10 +603,11 @@
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
 		if (buffer_req(bh) && !buffer_uptodate(bh)) {
-			printk ("IO error syncing ext2 inode ["
-				"%s:%08lx]\n",
-				kdevname(inode->i_dev), inode->i_ino);
-			err = -1;
+			ext2_error (inode->i_sb, 
+				    "IO error syncing ext2 inode ["
+				    "%s:%08lx]\n",
+				    kdevname(inode->i_dev), inode->i_ino);
+			err = -EIO;
 		}
 	}
 	brelse (bh);
diff -urN linux-2.0.31-pre6/fs/isofs/inode.c linux-2.0.31-pre7/fs/isofs/inode.c
--- linux-2.0.31-pre6/fs/isofs/inode.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/fs/isofs/inode.c	2003-08-15 15:04:04.000000000 -0700
@@ -187,6 +187,11 @@
   vol_desc_start=0;
   if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
     {
+      /* Whoops.  We must save the old FS, since otherwise
+       * we would destroy the kernels idea about FS on root
+       * mount in read_super... [chexum]
+       */
+      unsigned long old_fs=get_fs();
       inode_fake.i_rdev=dev;
       ms_info.addr_format=CDROM_LBA;
       set_fs(KERNEL_DS);
@@ -194,7 +199,7 @@
 				       NULL,
 				       CDROMMULTISESSION,
 				       (unsigned long) &ms_info);
-      set_fs(USER_DS);
+      set_fs(old_fs);
 #if 0 
       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
       if (i==0)
diff -urN linux-2.0.31-pre6/fs/isofs/rock.c linux-2.0.31-pre7/fs/isofs/rock.c
--- linux-2.0.31-pre6/fs/isofs/rock.c	1996-05-18 01:15:09.000000000 -0700
+++ linux-2.0.31-pre7/fs/isofs/rock.c	2003-08-15 15:04:04.000000000 -0700
@@ -287,7 +287,7 @@
 	CHECK_CE;
 	break;
       case SIG('E','R'):
-	printk("ISO9660 Extensions: ");
+	printk(KERN_DEBUG"ISO9660 Extensions: ");
 	{ int p;
 	  for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
 	};
diff -urN linux-2.0.31-pre6/fs/Makefile linux-2.0.31-pre7/fs/Makefile
--- linux-2.0.31-pre6/fs/Makefile	1996-05-08 08:28:01.000000000 -0700
+++ linux-2.0.31-pre7/fs/Makefile	2003-08-15 15:04:04.000000000 -0700
@@ -13,7 +13,7 @@
 O_OBJS    = open.o read_write.o inode.o devices.o file_table.o buffer.o \
 		super.o  block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
 		ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
-		dcache.o $(BINFMTS) 
+		dcache.o bad_inode.o $(BINFMTS) 
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = minix ext ext2 fat msdos vfat proc isofs nfs xiafs umsdos \
diff -urN linux-2.0.31-pre6/fs/namei.c linux-2.0.31-pre7/fs/namei.c
--- linux-2.0.31-pre6/fs/namei.c	1997-03-17 17:28:54.000000000 -0800
+++ linux-2.0.31-pre7/fs/namei.c	2003-08-15 15:04:04.000000000 -0700
@@ -6,6 +6,8 @@
 
 /*
  * Some corrections by tytso.
+ *
+ * Aug 97 - cevans - fix security problem with O_TRUNC and append only files
  */
 
 #include <asm/segment.h>
@@ -282,6 +284,10 @@
 			return error;
 	} else
 		iput(base);
+	if ((inode->i_flags & S_BAD_INODE) != 0) {
+		iput(inode);
+		return -EIO;
+	}
 	*res_inode = inode;
 	return 0;
 }
@@ -424,8 +430,9 @@
 	}
 	/*
 	 * An append-only file must be opened in append mode for writing
+	 * Additionally, we must disallow O_TRUNC -- cevans
 	 */
-	if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND))) {
+	if (IS_APPEND(inode) && (((flag & FMODE_WRITE) && !(flag & O_APPEND)) || (flag & O_TRUNC))) {
 		iput(inode);
 		return -EPERM;
 	}
diff -urN linux-2.0.31-pre6/fs/ncpfs/dir.c linux-2.0.31-pre7/fs/ncpfs/dir.c
--- linux-2.0.31-pre6/fs/ncpfs/dir.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/fs/ncpfs/dir.c	2003-08-15 15:04:04.000000000 -0700
@@ -1226,13 +1226,13 @@
 static int
 utc2local(int time)
 {
-        return time - sys_tz.tz_minuteswest*60;
+        return time - sys_tz.tz_minuteswest*60 + sys_tz.tz_dsttime*3600;
 }
 
 static int
 local2utc(int time)
 {
-        return time + sys_tz.tz_minuteswest*60;
+        return time + sys_tz.tz_minuteswest*60 - sys_tz.tz_dsttime*3600;
 }
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
diff -urN linux-2.0.31-pre6/fs/smbfs/inode.c linux-2.0.31-pre7/fs/smbfs/inode.c
--- linux-2.0.31-pre6/fs/smbfs/inode.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/fs/smbfs/inode.c	2003-08-15 15:04:04.000000000 -0700
@@ -382,7 +382,7 @@
 		return -EPERM;
 
 	if (((attr->ia_valid & ATTR_GID) &&
-	     (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
+	     (attr->ia_gid != SMB_SERVER(inode)->m.gid)))
 		return -EPERM;
 
 	if (((attr->ia_valid & ATTR_MODE) &&
diff -urN linux-2.0.31-pre6/include/linux/fs.h linux-2.0.31-pre7/include/linux/fs.h
--- linux-2.0.31-pre6/include/linux/fs.h	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/include/linux/fs.h	2003-08-15 15:04:04.000000000 -0700
@@ -74,6 +74,7 @@
 #define S_APPEND	256	/* Append-only file */
 #define S_IMMUTABLE	512	/* Immutable file */
 #define MS_NOATIME	1024	/* Do not update access times. */
+#define S_BAD_INODE	2048	/* Marker for unreadable inodes */
 
 /*
  * Flags that can be altered by MS_REMOUNT
@@ -635,6 +636,7 @@
 extern void insert_inode_hash(struct inode *);
 extern void clear_inode(struct inode *);
 extern struct inode * get_pipe_inode(void);
+extern void make_bad_inode(struct inode *);
 extern int get_unused_fd(void);
 extern void put_unused_fd(int);
 extern struct file * get_empty_filp(void);
diff -urN linux-2.0.31-pre6/include/linux/pci.h linux-2.0.31-pre7/include/linux/pci.h
--- linux-2.0.31-pre6/include/linux/pci.h	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/include/linux/pci.h	2003-08-15 15:04:04.000000000 -0700
@@ -574,19 +574,16 @@
 #define PCI_DEVICE_ID_CYCLOM_Z_Lo	0x0200
 #define PCI_DEVICE_ID_CYCLOM_Z_Hi	0x0201
 
-#define PCI_VENDOR_ID_SIGMA_DESIGNS	0x1236
-#define PCI_DEVICE_ID_SD_REALMAGIC64GX	0x6401
-
 #define PCI_VENDOR_ID_3DFX		0x121a
 #define PCI_DEVICE_ID_3DFX_VOODOO	0x0001
 
-#define PCI_VENDOR_ID_SIGMADES		0x1236
-#define PCI_DEVICE_ID_SIGMADES_6425	0x6401
+#define PCI_VENDOR_ID_SIGMA_DESIGNS	0x1236
+#define PCI_DEVICE_ID_SD_REALMAGIC64GX	0x6401
 
 #define PCI_VENDOR_ID_OPTIBASE		0x1255
 #define PCI_DEVICE_ID_OPTIBASE_FORGE	0x1110
 #define PCI_DEVICE_ID_OPTIBASE_FUSION	0x1210
-#define PCI_DEVICE_ID_OPTIBASE_VPLEX	0x2120
+#define PCI_DEVICE_ID_OPTIBASE_VPLEX	0x2110
 #define PCI_DEVICE_ID_OPTIBASE_VPLEXCC	0x2120
 #define PCI_DEVICE_ID_OPTIBASE_VQUEST	0x2130
 
diff -urN linux-2.0.31-pre6/include/net/tcp.h linux-2.0.31-pre7/include/net/tcp.h
--- linux-2.0.31-pre6/include/net/tcp.h	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/include/net/tcp.h	2003-08-15 15:04:04.000000000 -0700
@@ -49,7 +49,7 @@
  * break TCP port selection. This function must also NOT wrap around
  * when the next number exceeds the largest possible port (2^16-1).
  */
-static __inline__ int tcp_bhashnext(__u16 short lport, __u16 h)
+static __inline__ int tcp_bhashnext(__u16 lport, __u16 h)
 {
         __u32 s;	/* don't change this to a smaller type! */
 
@@ -237,6 +237,8 @@
 
 extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 
+extern void tcp_v4_unhash(struct sock *sk);
+
 extern void tcp_read_wakeup(struct sock *);
 extern void tcp_write_xmit(struct sock *);
 extern void tcp_time_wait(struct sock *);
@@ -358,6 +360,8 @@
 		break;
 
 	case TCP_CLOSE:
+		/* Preserve the invariant */
+		tcp_v4_unhash(sk);
 		/* Should be about 2 rtt's */
 		reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
 		/* fall through */
diff -urN linux-2.0.31-pre6/net/core/sock.c linux-2.0.31-pre7/net/core/sock.c
--- linux-2.0.31-pre6/net/core/sock.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/net/core/sock.c	2003-08-15 15:04:04.000000000 -0700
@@ -347,6 +347,28 @@
 			val = sk->bsdism;
 			break;
 
+#ifdef CONFIG_NET
+                case SO_BINDTODEVICE:
+		{
+			struct ifreq req;
+
+                        /* Return the bound device (if any) */
+                        err=verify_area(VERIFY_WRITE,optval,sizeof(req));
+                        if(err)
+                                return err;
+
+                        memset((char *) &req, 0, sizeof(req));
+
+                        if (sk->bound_device) {
+                            strncpy(req.ifr_name, sk->bound_device->name, sizeof(req.ifr_name));
+                            (*(struct sockaddr_in *) &req.ifr_addr).sin_family = sk->bound_device->family;
+                            (*(struct sockaddr_in *) &req.ifr_addr).sin_addr.s_addr = sk->bound_device->pa_addr;
+                        }
+                        memcpy_tofs(optval, &req, sizeof(req));
+                        return 0;
+		}
+#endif
+
 		default:
 			return(-ENOPROTOOPT);
 	}
diff -urN linux-2.0.31-pre6/net/ipv4/af_inet.c linux-2.0.31-pre7/net/ipv4/af_inet.c
--- linux-2.0.31-pre6/net/ipv4/af_inet.c	1997-04-08 08:47:47.000000000 -0700
+++ linux-2.0.31-pre7/net/ipv4/af_inet.c	2003-08-15 15:04:04.000000000 -0700
@@ -620,8 +620,12 @@
 #endif		 
 	if (snum == 0) 
 		snum = sk->prot->good_socknum();
-	if (snum < PROT_SOCK && !suser()) 
+        if (snum < PROT_SOCK) {
+		if (!suser()) 
 		return(-EACCES);
+		if (snum == 0)
+			return(-EAGAIN);
+	}
 	
 	chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr);
 	if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR &&
diff -urN linux-2.0.31-pre6/net/ipv4/route.c linux-2.0.31-pre7/net/ipv4/route.c
--- linux-2.0.31-pre6/net/ipv4/route.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/net/ipv4/route.c	2003-08-15 15:04:04.000000000 -0700
@@ -924,6 +924,8 @@
 {
 	struct rtable *rt, **rtp;
 
+	ip_rt_bh_mask &= ~RT_BH_FREE;
+
 	rtp = &rt_free_queue;
 
 	while ((rt = *rtp) != NULL)
diff -urN linux-2.0.31-pre6/net/ipv4/tcp.c linux-2.0.31-pre7/net/ipv4/tcp.c
--- linux-2.0.31-pre6/net/ipv4/tcp.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/net/ipv4/tcp.c	2003-08-15 15:04:04.000000000 -0700
@@ -205,7 +205,7 @@
  *		Theodore Ts'o	:	Do secure TCP sequence numbers.
  *		David S. Miller	:	New socket lookup architecture for ISS.
  *					This code is dedicated to John Dyson.
- *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
+ *		Elliot Poger	:	Added support for SO_BINDTODEVICE.
  *					
  * To Fix:
  *		Fast path the code. Two things here - fix the window calculation
@@ -529,45 +529,47 @@
 	int retval = 0, i, end, bc;
 
 	SOCKHASH_LOCK();
-        i = tcp_bhashfn(start);
-        end = i + TCP_BHTABLE_SIZE;
-        bc = binding_contour;
-        do {
-                struct sock *sk = tcp_bound_hash[i&(TCP_BHTABLE_SIZE-1)];
-                if(!sk) {
-                        /* find the smallest value no smaller than start
-                         * that has this hash value.
-                         */
-                        retval = tcp_bhashnext(start-1,i&(TCP_BHTABLE_SIZE-1));
-
-                        /* Check for decreasing load. */
-                        if (bc != 0)
-                                binding_contour = 0;
-                        goto done;
-                } else {
-                        int j = 0;
-                        do { sk = sk->bind_next; } while (++j < size && sk);
-                        if (j < size) {
-                                best = i&(TCP_BHTABLE_SIZE-1);
-                                size = j;
-                                if (bc && size <= bc)
-                                        goto verify;
-                        }
-                }
-        } while(++i != end);
-        i = best;
+	i = tcp_bhashfn(start);
+	end = i + TCP_BHTABLE_SIZE;
+	bc = binding_contour;
+	do {
+		struct sock *sk = tcp_bound_hash[i&(TCP_BHTABLE_SIZE-1)];
+		if(!sk) {
+			/* find the smallest value no smaller than start
+			 * that has this hash value.
+			 */
+			retval = tcp_bhashnext(start-1,i&(TCP_BHTABLE_SIZE-1));
 
-        /* Socket load is increasing, adjust our load average. */
-        binding_contour = size;
+			/* Check for decreasing load. */
+			if (bc != 0)
+				binding_contour = 0;
+			goto done;
+		} else {
+			int j = 0;
+			do { sk = sk->bind_next; } while (++j < size && sk);
+			if (j < size) {
+				best = i&(TCP_BHTABLE_SIZE-1);
+				size = j;
+				if (bc && size <= bc) {
+					i = best;
+					goto verify;
+				}
+			}
+		}
+	} while(++i != end);
+	i = best;
+
+	/* Socket load is increasing, adjust our load average. */
+	binding_contour = size;
 verify:
-        if (size < binding_contour)
-                binding_contour = size;
+	if (size < binding_contour)
+		binding_contour = size;
 
-        retval = tcp_bhashnext(start-1,i);
+	retval = tcp_bhashnext(start-1,i);
 
 	best = retval;	/* mark the starting point to avoid infinite loops */
-        while(tcp_lport_inuse(retval)) {
-               	retval = tcp_bhashnext(retval,i);
+	while(tcp_lport_inuse(retval)) {
+		retval = tcp_bhashnext(retval,i);
 		if (retval > 32767)	/* Upper bound */
 			retval = tcp_bhashnext(PROT_SOCK,i);
 		if (retval == best) {
@@ -575,12 +577,12 @@
 			retval = 0;
 			break;
 		}
-        }
+	}
 
 done:
-        start = (retval + 1);
-        if (start > 32767 || start < PROT_SOCK)
-                start = PROT_SOCK;
+	start = (retval + 1);
+	if (start > 32767 || start < PROT_SOCK)
+		start = PROT_SOCK;
 	SOCKHASH_UNLOCK();
 
 	return retval;
@@ -2042,7 +2044,7 @@
 
 	/* Now that the socket is dead, if we are in the FIN_WAIT2 state
 	 * we may need to set up a timer.
-         */
+	 */
 	if (sk->state==TCP_FIN_WAIT2)
 	{
 		int timer_active=del_timer(&sk->timer);
diff -urN linux-2.0.31-pre6/net/ipv4/tcp_output.c linux-2.0.31-pre7/net/ipv4/tcp_output.c
--- linux-2.0.31-pre6/net/ipv4/tcp_output.c	2003-08-15 15:04:04.000000000 -0700
+++ linux-2.0.31-pre7/net/ipv4/tcp_output.c	2003-08-15 15:04:04.000000000 -0700
@@ -175,7 +175,7 @@
 
 	tcp_statistics.TcpOutSegs++;  
 	skb->seq = ntohl(th->seq);
-	skb->end_seq = skb->seq + size - 4*th->doff;
+	skb->end_seq = skb->seq + size - 4*th->doff + th->fin;
 
 	/*
 	 *	We must queue if
@@ -880,6 +880,8 @@
 			return;
 		}
 	}
+
+	clear_delayed_acks(sk);
 	
 	/*
 	 *	We ought to check if the end of the queue is a buffer and
diff -urN linux-2.0.31-pre6/net/ipv4/timer.c linux-2.0.31-pre7/net/ipv4/timer.c
--- linux-2.0.31-pre6/net/ipv4/timer.c	1996-02-22 06:50:46.000000000 -0800
+++ linux-2.0.31-pre7/net/ipv4/timer.c	2003-08-15 15:04:04.000000000 -0700
@@ -139,12 +139,10 @@
 
 		case TIME_CLOSE:
 			/* We've waited long enough, close the socket. */
-			sk->state = TCP_CLOSE;
-			delete_timer (sk);
+			tcp_set_state(sk, TCP_CLOSE);
 			if (!sk->dead)
 				sk->state_change(sk);
 			sk->shutdown = SHUTDOWN_MASK;
-			reset_timer (sk, TIME_DONE, TCP_DONE_TIME);
 			break;
 
 		default:
