diff -u --recursive --new-file pre2.0.8/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- pre2.0.8/linux/Documentation/ioctl-number.txt	Fri May 17 15:32:10 1996
+++ linux/Documentation/ioctl-number.txt	Tue May 28 07:39:18 1996
@@ -55,7 +55,6 @@
 Ioctl	Include File		Comments
 ========================================================
 0x00	linux/fs.h		only FIBMAP, FIGETBSZ
-0x00	linux/mc146818rtc.h	conflict!
 0x02	linux/fd.h
 0x03	linux/hdreg.h
 0x04	linux/umsdos_fs.h
@@ -90,6 +89,7 @@
 'm'	linux/mtio.h		conflict!
 'm'	linux/soundcard.h	conflict!
 'n'	linux/ncp_fs.h
+'p'	linux/mc146818rtc.h
 'r'	linux/msdos_fs.h
 's'	linux/cdk.h
 't'	linux/if_ppp.h		no conflict
diff -u --recursive --new-file pre2.0.8/linux/MAINTAINERS linux/MAINTAINERS
--- pre2.0.8/linux/MAINTAINERS	Sun May 12 22:54:22 1996
+++ linux/MAINTAINERS	Wed May 29 09:51:41 1996
@@ -68,6 +68,12 @@
 			it has been replaced by a better system and you
 			should be using that.
 
+EXT2 FILE SYSTEM
+P:	Remy Card
+M:	Remy.Card@linux.org
+L:	linux-kernel@vger.rutgers.edu
+S:	Maintained
+
 3C501 NETWORK DRIVER
 P:	Alan Cox
 M:	net-patches@lxorguk.ukuu.org.uk
diff -u --recursive --new-file pre2.0.8/linux/Makefile linux/Makefile
--- pre2.0.8/linux/Makefile	Tue May 28 08:09:54 1996
+++ linux/Makefile	Tue May 28 07:39:47 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 99
-SUBLEVEL = 8
+SUBLEVEL = 9
 
 ARCH = i386
 
diff -u --recursive --new-file pre2.0.8/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- pre2.0.8/linux/arch/i386/kernel/time.c	Tue May  7 16:22:17 1996
+++ linux/arch/i386/kernel/time.c	Tue May 28 10:14:17 1996
@@ -10,6 +10,8 @@
  * 1995-03-26    Markus Kuhn
  *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
  *      precision CMOS clock update
+ * 1996-05-03    Ingo Molnar
+ *      fixed time warps in do_[slow|fast]_gettimeoffset()
  */
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -31,57 +33,102 @@
 
 #ifndef	CONFIG_APM	/* cycle counter may be unreliable */
 /* Cycle counter value at the previous timer interrupt.. */
-static unsigned long long last_timer_cc = 0;
-static unsigned long long init_timer_cc = 0;
+static struct {
+	unsigned long low;
+	unsigned long high;
+} init_timer_cc, last_timer_cc;
 
+/*
+ * This is more assembly than C, but it's also rather
+ * timing-critical and we have to use assembler to get
+ * reasonable 64-bit arithmetic
+ */
 static unsigned long do_fast_gettimeoffset(void)
 {
-	unsigned long time_low, time_high;
-	unsigned long quotient, remainder;
+	register unsigned long eax asm("ax");
+	register unsigned long edx asm("dx");
+	unsigned long tmp, quotient, low_timer, missing_time;
+
+	/* Last jiffie when do_fast_gettimeoffset() was called.. */
+	static unsigned long last_jiffies=0;
+
+	/* Cached "clocks per usec" value.. */
+	static unsigned long cached_quotient=0;
+
+	/* The "clocks per usec" value is calculated once each jiffie */
+	tmp = jiffies;
+	quotient = cached_quotient;
+	low_timer = last_timer_cc.low;
+	missing_time = 0;
+	if (last_jiffies != tmp) {
+		last_jiffies = tmp;
+		/*
+		 * test for hanging bottom handler (this means xtime is not 
+		 * updated yet)
+		 */
+		if (test_bit(TIMER_BH, &bh_active) )
+		{
+			missing_time = 997670/HZ;
+		}
 
-	/* Get last timer tick in absolute kernel time */
-	__asm__("subl %2,%0\n\t"
-		"sbbl %3,%1"
-		:"=r" (time_low), "=r" (time_high)
-		:"m" (*(0+(long *)&init_timer_cc)),
-		 "m" (*(1+(long *)&init_timer_cc)),
-		 "0" (*(0+(long *)&last_timer_cc)),
-		 "1" (*(1+(long *)&last_timer_cc)));
-	/*
-	 * Divide the 64-bit time with the 32-bit jiffy counter,
-	 * getting the quotient in clocks.
-	 *
-	 * Giving quotient = "average internal clocks per jiffy"
-	 */
-	__asm__("divl %2"
-		:"=a" (quotient), "=d" (remainder)
-		:"r" (jiffies),
-		 "0" (time_low), "1" (time_high));
+		/* Get last timer tick in absolute kernel time */
+		eax = low_timer;
+		edx = last_timer_cc.high;
+		__asm__("subl "SYMBOL_NAME_STR(init_timer_cc)",%0\n\t"
+			"sbbl "SYMBOL_NAME_STR(init_timer_cc)"+4,%1"
+			:"=a" (eax), "=d" (edx)
+			:"0" (eax), "1" (edx));
+
+		/*
+		 * Divide the 64-bit time with the 32-bit jiffy counter,
+		 * getting the quotient in clocks.
+		 *
+		 * Giving quotient = "average internal clocks per usec"
+		 */
+		__asm__("divl %2"
+			:"=a" (eax), "=d" (edx)
+			:"r" (tmp),
+			 "0" (eax), "1" (edx));
+
+		edx = 997670/HZ;
+		tmp = eax;
+		eax = 0;
+
+		__asm__("divl %2"
+			:"=a" (eax), "=d" (edx)
+			:"r" (tmp),
+			 "0" (eax), "1" (edx));
+		cached_quotient = eax;
+		quotient = eax;
+	}
 
 	/* Read the time counter */
 	__asm__(".byte 0x0f,0x31"
-		:"=a" (time_low), "=d" (time_high));
+		:"=a" (eax), "=d" (edx));
 
 	/* .. relative to previous jiffy (32 bits is enough) */
-	time_low -= (unsigned long) last_timer_cc;
+	edx = 0;
+	eax -= low_timer;
 
 	/*
-	 * Time offset = (1000000/HZ * remainder) / quotient.
+	 * Time offset = (997670/HZ * time_low) / quotient.
 	 */
-	__asm__("mull %1\n\t"
-		"divl %2"
-		:"=a" (quotient), "=d" (remainder)
+
+	__asm__("mull %2"
+		:"=a" (eax), "=d" (edx)
 		:"r" (quotient),
-		 "0" (time_low), "1" (1000000/HZ));
+		 "0" (eax), "1" (edx));
 
 	/*
-	 * Due to rounding errors (and jiffies inconsistencies),
+ 	 * Due to rounding errors (and jiffies inconsistencies),
 	 * we need to check the result so that we'll get a timer
 	 * that is monotonous.
 	 */
-	if (quotient >= 1000000/HZ)
-		quotient = 1000000/HZ-1;
-	return quotient;
+	if (edx >= 997670/HZ)
+		edx = 997670/HZ-1;
+
+	eax = edx + missing_time;
+	return eax;
 }
 #endif
 
@@ -122,21 +169,63 @@
 static unsigned long do_slow_gettimeoffset(void)
 {
 	int count;
+	static int count_p = 0;
 	unsigned long offset = 0;
+	static unsigned long jiffies_p = 0;
+
+	/*
+	 * cache volatile jiffies temporaly, we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
 
 	/* timer count may underflow right here */
 	outb_p(0x00, 0x43);	/* latch the count ASAP */
 	count = inb_p(0x40);	/* read the latched count */
 	count |= inb(0x40) << 8;
-	/* we know probability of underflow is always MUCH less than 1% */
-	if (count > (LATCH - LATCH/100)) {
-		/* check for pending timer interrupt */
-		outb_p(0x0a, 0x20);
-		if (inb(0x20) & 1)
-			offset = TICK_SIZE;
-	}
+
+ 	jiffies_t = jiffies;
+
+	/*
+	 * avoiding timer inconsistencies (they are rare, but they happen)...
+	 * there are three kinds of problems that must be avoided here:
+	 *  1. the timer counter underflows
+	 *  2. hardware problem with the timer, not giving us continuous time,
+	 *     the counter does small "jumps" upwards on some Pentium systems,
+	 *     thus causes time warps
+	 *  3. we are after the timer interrupt, but the bottom half handler
+	 *     hasn't executed yet.
+	 */
+	if( count > count_p ) {
+		if( jiffies_t == jiffies_p ) {
+			if( count > LATCH-LATCH/100 )
+				offset = TICK_SIZE;
+			else
+				/*
+				 * argh, the timer is bugging we cant do nothing 
+				 * but to give the previous clock value.
+				 */
+				count = count_p;
+		} else {
+			if( test_bit(TIMER_BH, &bh_active) ) {
+				/*
+				 * we have detected a counter underflow.
+			 	 */
+				offset = TICK_SIZE;
+				count_p = count;		
+			} else {
+				count_p = count;
+				jiffies_p = jiffies_t;
+			}
+		}
+	} else {
+		count_p = count;
+		jiffies_p = jiffies_t;
+ 	}
+
+
 	count = ((LATCH-1) - count) * TICK_SIZE;
 	count = (count + LATCH/2) / LATCH;
+
 	return offset + count;
 }
 
@@ -283,8 +372,8 @@
 {
 	/* read Pentium cycle counter */
 	__asm__(".byte 0x0f,0x31"
-		:"=a" (((unsigned long *) &last_timer_cc)[0]),
-		 "=d" (((unsigned long *) &last_timer_cc)[1]));
+		:"=a" (last_timer_cc.low),
+		 "=d" (last_timer_cc.high));
 	timer_interrupt(irq, NULL, regs);
 }
 #endif
@@ -375,8 +464,8 @@
 		do_gettimeoffset = do_fast_gettimeoffset;
 		/* read Pentium cycle counter */
 		__asm__(".byte 0x0f,0x31"
-			:"=a" (((unsigned long *) &init_timer_cc)[0]),
-			 "=d" (((unsigned long *) &init_timer_cc)[1]));
+			:"=a" (init_timer_cc.low),
+			 "=d" (init_timer_cc.high));
 		irq0.handler = pentium_timer_interrupt;
 	}
 #endif
diff -u --recursive --new-file pre2.0.8/linux/arch/ppc/boot/mk_type41.c linux/arch/ppc/boot/mk_type41.c
--- pre2.0.8/linux/arch/ppc/boot/mk_type41.c	Tue May 28 08:09:54 1996
+++ linux/arch/ppc/boot/mk_type41.c	Tue May 28 07:46:04 1996
@@ -40,7 +40,7 @@
 	}
 	if ((out_fd = creat(argv[2], 0666)) < 0)
 	{
-		fprintf(stderr, "Can't create outpue file: '%s': %s\n", argv[2], strerror(errno));
+		fprintf(stderr, "Can't create output file: '%s': %s\n", argv[2], strerror(errno));
 		exit(2);
 	}
 	if (fstat(in_fd, &info) < 0)
@@ -185,7 +185,7 @@
      * the next two.
      *   - size of the diskette is (assumed to be)
      *     (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
-     *   - unlike the above sector nunbers, the beginning sector is zero-based!
+     *   - unlike the above sector numbers, the beginning sector is zero-based!
      */
 #if 0     
     pe->beginning_sector  = LeDword(1);
diff -u --recursive --new-file pre2.0.8/linux/arch/ppc/kernel/include/elf/ChangeLog linux/arch/ppc/kernel/include/elf/ChangeLog
--- pre2.0.8/linux/arch/ppc/kernel/include/elf/ChangeLog	Tue May 28 08:09:55 1996
+++ linux/arch/ppc/kernel/include/elf/ChangeLog	Tue May 28 07:46:04 1996
@@ -9,7 +9,7 @@
 
 Tue Feb 14 13:59:13 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
-	* common.h (EM_PPC): Use offical value of 20, not 17.
+	* common.h (EM_PPC): Use official value of 20, not 17.
 	(EM_PPC_OLD): Define this to be the old value of EM_PPC.
 
 
@@ -108,7 +108,7 @@
 	* common.h (EM_HPPA, NT_VERSION, STN_UNDEF, DT_*): New macros.
 	* external.h (Elf_External_Dyn): New type.
 
-	* internal.h (Elf_Intenral_Shdr): New field `size'.
+	* internal.h (Elf_Internal_Shdr): New field `size'.
 	(Elf_Internal_Dyn): New type.
 
 Tue Apr 20 16:03:45 1993  Fred Fish  (fnf@cygnus.com)
diff -u --recursive --new-file pre2.0.8/linux/arch/ppc/kernel/ppc_machine.h linux/arch/ppc/kernel/ppc_machine.h
--- pre2.0.8/linux/arch/ppc/kernel/ppc_machine.h	Tue May 28 08:09:55 1996
+++ linux/arch/ppc/kernel/ppc_machine.h	Tue May 28 07:46:04 1996
@@ -10,7 +10,7 @@
 #define MSR_TGPR	(1<<17)		/* TLB Update registers in use */
 #define MSR_ILE		(1<<16)		/* Interrupt Little-Endian enable */
 #define MSR_EE		(1<<15)		/* External Interrupt enable */
-#define MSR_PR		(1<<14)		/* Supervisor/User privelege */
+#define MSR_PR		(1<<14)		/* Supervisor/User privilege */
 #define MSR_FP		(1<<13)		/* Floating Point enable */
 #define MSR_ME		(1<<12)		/* Machine Check enable */
 #define MSR_FE0		(1<<11)		/* Floating Exception mode 0 */
diff -u --recursive --new-file pre2.0.8/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- pre2.0.8/linux/arch/ppc/kernel/process.c	Tue May 28 08:09:55 1996
+++ linux/arch/ppc/kernel/process.c	Tue May 28 07:46:04 1996
@@ -2,7 +2,7 @@
  *  linux/arch/ppc/kernel/process.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Adapted for PowerPC by Gary THomas
+ *  Adapted for PowerPC by Gary Thomas
  */
 
 /*
diff -u --recursive --new-file pre2.0.8/linux/arch/ppc/kernel/support.c linux/arch/ppc/kernel/support.c
--- pre2.0.8/linux/arch/ppc/kernel/support.c	Tue May 28 08:09:55 1996
+++ linux/arch/ppc/kernel/support.c	Tue May 28 07:46:04 1996
@@ -1,5 +1,5 @@
 /*
- * Miscallaneous support routines
+ * Miscellaneous support routines
  */
 
 #include <asm/bitops.h>
diff -u --recursive --new-file pre2.0.8/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- pre2.0.8/linux/arch/ppc/kernel/syscalls.c	Tue May 28 08:09:55 1996
+++ linux/arch/ppc/kernel/syscalls.c	Tue May 28 07:46:04 1996
@@ -19,7 +19,7 @@
 
 /*
  * sys_pipe() is the normal C calling standard for creating
- * a pipe. It's not the way unix tranditionally does this, though.
+ * a pipe. It's not the way unix traditionally does this, though.
  */
 asmlinkage int sys_pipe(unsigned long * fildes)
 {
diff -u --recursive --new-file pre2.0.8/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- pre2.0.8/linux/drivers/char/rtc.c	Sun May 12 10:16:07 1996
+++ linux/drivers/char/rtc.c	Tue May 28 07:39:18 1996
@@ -30,11 +30,10 @@
  *
  */
 
-#define RTC_VERSION		"1.06"
+#define RTC_VERSION		"1.07"
 
 #define RTC_IRQ 	8	/* Can't see this changing soon.	*/
-#define RTC_IO_BASE	0x70	/* Or this...				*/
-#define RTC_IO_EXTENT	0x10	/* Only really 0x70 to 0x71, but...	*/
+#define RTC_IO_EXTENT	0x10	/* Only really two ports, but...	*/
 
 /*
  *	Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
@@ -539,7 +538,7 @@
 	}
 	misc_register(&rtc_dev);
 	/* Check region? Naaah! Just snarf it up. */
-	request_region(RTC_IO_BASE, RTC_IO_EXTENT, "rtc");
+	request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
 	init_timer(&rtc_irq_timer);
 	rtc_irq_timer.function = rtc_dropped_irq;
 	rtc_wait = NULL;
diff -u --recursive --new-file pre2.0.8/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- pre2.0.8/linux/drivers/net/eexpress.c	Tue May  7 16:22:27 1996
+++ linux/drivers/net/eexpress.c	Wed May 29 09:49:25 1996
@@ -1,4 +1,4 @@
-/* $Id: eexpress.c,v 1.12 1996/04/15 17:27:30 phil Exp $
+/* $Id: eexpress.c,v 1.13 1996/05/19 15:59:51 phil Exp $
  *
  * Intel EtherExpress device driver for Linux
  *
@@ -86,7 +86,7 @@
 
 static char version[] = 
 "eexpress.c: v0.10 04-May-95 John Sullivan <js10039@cam.ac.uk>\n"
-"            v0.13 10-Apr-96 Philip Blundell <phil@tazenda.demon.co.uk>\n";
+"            v0.14 19-May-96 Philip Blundell <phil@tazenda.demon.co.uk>\n";
 
 #include <linux/module.h>
 
@@ -103,6 +103,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 
 #include <linux/netdevice.h>
@@ -1060,15 +1061,25 @@
         printk("%s: eexp_hw_init586()\n", dev->name);
 #endif
 
-	PRIV(dev)->started = 0;
+	lp->started = 0;
 	set_loopback;
 
 	outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
 	outb_p(i586_RST,ioaddr+EEPROM_Ctrl);
+	udelay(2000);  /* delay 20ms */
+        {
+		unsigned short ofs, i;
+		for (ofs = 0; ofs < lp->rx_buf_end; ofs += 32) {
+			outw_p(ofs, ioaddr+SM_PTR);
+			for (i = 0; i < 16; i++) {
+				outw_p(0, ioaddr+SM_ADDR(i<<1));
+			}
+		}
+	}
 
 	outw_p(lp->rx_buf_end,ioaddr+WRITE_PTR);
 	start_code[28] = (dev->flags & IFF_PROMISC)?(start_code[28] | 1):(start_code[28] & ~1);
-	PRIV(dev)->promisc = dev->flags & IFF_PROMISC;
+	lp->promisc = dev->flags & IFF_PROMISC;
 	/* We may die here */
 	outsw(ioaddr, start_code, sizeof(start_code)>>1);
 	outw(CONF_HW_ADDR,ioaddr+WRITE_PTR);
@@ -1205,8 +1216,8 @@
 
 static struct device dev_eexp[EEXP_MAX_CARDS] = 
 {
-        NULL,         /* will allocate dynamically */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe 
+        { NULL,         /* will allocate dynamically */
+	  0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe },  
 };
 
 int irq[EEXP_MAX_CARDS] = {0, };
diff -u --recursive --new-file pre2.0.8/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- pre2.0.8/linux/drivers/net/ne.c	Tue May  7 16:22:29 1996
+++ linux/drivers/net/ne.c	Tue May 28 07:39:18 1996
@@ -229,6 +229,12 @@
 	}
     }
 
+    /* We should have a "dev" from Space.c or the static module table. */
+    if (dev == NULL) {
+	printk(KERN_ERR "ne.c: Passed a NULL device.\n");
+	dev = init_etherdev(0, 0);
+    }
+
     if (ei_debug  &&  version_printed++ == 0)
 	printk(version);
 
@@ -344,12 +350,6 @@
 	return ENXIO;
 #endif
 
-    }
-
-    /* We should have a "dev" from Space.c or the static module table. */
-    if (dev == NULL) {
-	printk("ne.c: Passed a NULL device.\n");
-	dev = init_etherdev(0, 0);
     }
 
     if (pci_irq_line) {
diff -u --recursive --new-file pre2.0.8/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- pre2.0.8/linux/drivers/net/ppp.c	Mon May 20 08:21:01 1996
+++ linux/drivers/net/ppp.c	Wed May 29 07:32:38 1996
@@ -6,7 +6,7 @@
  *  Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
  *  ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
  *
- *  ==FILEVERSION 960303==
+ *  ==FILEVERSION 960528==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the number above to the
diff -u --recursive --new-file pre2.0.8/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- pre2.0.8/linux/drivers/scsi/scsi.c	Wed May 15 11:01:15 1996
+++ linux/drivers/scsi/scsi.c	Wed May 29 09:49:26 1996
@@ -580,7 +580,7 @@
   printk("\n");
 #endif
 
-if (host_byte(SCpnt->result) != DID_OK) {
+  if (SCpnt->result) {
     if (((driver_byte (SCpnt->result) & DRIVER_SENSE) ||
          (status_byte (SCpnt->result) & CHECK_CONDITION)) &&
         ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
@@ -1569,9 +1569,15 @@
 		    case SUGGEST_IS_OK:
 			break;
 		    case SUGGEST_REMAP:
+#ifdef DEBUG
+			printk("SENSE SUGGEST REMAP - status = FINISHED\n");
+#endif
+			status = FINISHED;
+			exit = DRIVER_SENSE | SUGGEST_ABORT;
+			break;
 		    case SUGGEST_RETRY:
 #ifdef DEBUG
-			printk("SENSE SUGGEST REMAP or SUGGEST RETRY - status = MAYREDO\n");
+			printk("SENSE SUGGEST RETRY - status = MAYREDO\n");
 #endif
 			status = MAYREDO;
 			exit = DRIVER_SENSE | SUGGEST_RETRY;
@@ -1606,6 +1612,9 @@
 		    status = REDO;
 		    break;
 		case SUGGEST_REMAP:
+		    status = FINISHED;
+		    exit =  DRIVER_SENSE | SUGGEST_ABORT;
+		    break;
 		case SUGGEST_RETRY:
 		    status = MAYREDO;
 		    exit = DRIVER_SENSE | SUGGEST_RETRY;
diff -u --recursive --new-file pre2.0.8/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- pre2.0.8/linux/drivers/scsi/scsi_ioctl.c	Mon May 20 08:21:02 1996
+++ linux/drivers/scsi/scsi_ioctl.c	Wed May 29 09:49:25 1996
@@ -150,7 +150,7 @@
     result = SCpnt->result;
     SCpnt->request.rq_status = RQ_INACTIVE;
 
-    if(SCpnt->device->scsi_request_fn)
+    if (!SCpnt->device->was_reset && SCpnt->device->scsi_request_fn)
 	(*SCpnt->device->scsi_request_fn)();
 
     wake_up(&SCpnt->device->device_wait);
diff -u --recursive --new-file pre2.0.8/linux/fs/isofs/util.c linux/fs/isofs/util.c
--- pre2.0.8/linux/fs/isofs/util.c	Wed Nov  8 12:26:10 1995
+++ linux/fs/isofs/util.c	Wed May 29 07:26:48 1996
@@ -6,7 +6,7 @@
  *  convert numbers according to section 7.3.3, etc.
  *
  *  isofs special functions.  This file was lifted in its entirety from
- * the bsd386 iso9660 filesystem, by Pace Williamson.
+ *  the 386bsd iso9660 filesystem, by Pace Willisson <pace@blitz.com>.
  */
 
 int
diff -u --recursive --new-file pre2.0.8/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- pre2.0.8/linux/fs/nfs/dir.c	Sat Apr 27 15:19:58 1996
+++ linux/fs/nfs/dir.c	Tue May 28 07:45:19 1996
@@ -476,8 +476,12 @@
 	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 	error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
 		name, &sattr, &fhandle, &fattr);
-	if (!error)
-		nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
+	if (!error) {
+		if (fattr.fileid == dir->i_ino)
+			printk("Sony NewsOS 4.1R buggy nfs server?\n");
+		else
+			nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
+	}
 	iput(dir);
 	return error;
 }
diff -u --recursive --new-file pre2.0.8/linux/fs/read_write.c linux/fs/read_write.c
--- pre2.0.8/linux/fs/read_write.c	Fri May 17 15:32:18 1996
+++ linux/fs/read_write.c	Wed May 29 15:43:55 1996
@@ -100,7 +100,7 @@
 	return 0;
 }
 
-asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
+asmlinkage int sys_read(unsigned int fd,char * buf,int count)
 {
 	int error;
 	struct file * file;
@@ -112,7 +112,7 @@
 		return -EBADF;
 	if (!file->f_op || !file->f_op->read)
 		return -EINVAL;
-	if (!count)
+	if (count <= 0)
 		return 0;
 	error = locks_verify_area(FLOCK_VERIFY_READ,inode,file,file->f_pos,count);
 	if (error)
diff -u --recursive --new-file pre2.0.8/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h
--- pre2.0.8/linux/include/asm-alpha/bitops.h	Sun Apr 21 12:39:02 1996
+++ linux/include/asm-alpha/bitops.h	Wed May 29 18:47:38 1996
@@ -31,7 +31,7 @@
 		:"=&r" (temp),
 		 "=m" (*m),
 		 "=&r" (oldbit)
-		:"r" (1UL << (nr & 31)),
+		:"Ir" (1UL << (nr & 31)),
 		 "m" (*m));
 	return oldbit != 0;
 }
@@ -54,7 +54,7 @@
 		:"=&r" (temp),
 		 "=m" (*m),
 		 "=&r" (oldbit)
-		:"r" (1UL << (nr & 31)),
+		:"Ir" (1UL << (nr & 31)),
 		 "m" (*m));
 	return oldbit != 0;
 }
@@ -75,7 +75,7 @@
 		:"=&r" (temp),
 		 "=m" (*m),
 		 "=&r" (oldbit)
-		:"r" (1UL << (nr & 31)),
+		:"Ir" (1UL << (nr & 31)),
 		 "m" (*m));
 	return oldbit != 0;
 }
diff -u --recursive --new-file pre2.0.8/linux/include/asm-i386/checksum.h linux/include/asm-i386/checksum.h
--- pre2.0.8/linux/include/asm-i386/checksum.h	Sun May  5 08:52:04 1996
+++ linux/include/asm-i386/checksum.h	Tue May 28 12:27:59 1996
@@ -46,7 +46,7 @@
 					  unsigned int ihl) {
 	unsigned int sum;
 
-	__asm__("
+	__asm__ __volatile__("
 	    movl (%1), %0
 	    subl $4, %2
 	    jbe 2f
diff -u --recursive --new-file pre2.0.8/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- pre2.0.8/linux/include/asm-i386/system.h	Fri Apr  5 13:35:28 1996
+++ linux/include/asm-i386/system.h	Wed May 29 18:06:39 1996
@@ -199,18 +199,21 @@
 	switch (size) {
 		case 1:
 			__asm__("xchgb %b0,%1"
-				:"=&q" (x), "=m" (*__xg(ptr))
-				:"0" (x), "m" (*__xg(ptr)));
+				:"=q" (x)
+				:"m" (*__xg(ptr)), "0" (x)
+				:"memory");
 			break;
 		case 2:
 			__asm__("xchgw %w0,%1"
-				:"=&r" (x), "=m" (*__xg(ptr))
-				:"0" (x), "m" (*__xg(ptr)));
+				:"=r" (x)
+				:"m" (*__xg(ptr)), "0" (x)
+				:"memory");
 			break;
 		case 4:
 			__asm__("xchgl %0,%1"
-				:"=&r" (x), "=m" (*__xg(ptr))
-				:"0" (x), "m" (*__xg(ptr)));
+				:"=r" (x)
+				:"m" (*__xg(ptr)), "0" (x)
+				:"memory");
 			break;
 	}
 	return x;
diff -u --recursive --new-file pre2.0.8/linux/include/asm-ppc/posix_types.h linux/include/asm-ppc/posix_types.h
--- pre2.0.8/linux/include/asm-ppc/posix_types.h	Tue May 28 08:09:57 1996
+++ linux/include/asm-ppc/posix_types.h	Tue May 28 07:46:04 1996
@@ -1,5 +1,5 @@
 #ifndef _PPC_POSIX_TYPES_H
-#define _PPc_POSIX_TYPES_H
+#define _PPC_POSIX_TYPES_H
 
 /*
  * This file is generally used by user-level software, so you need to
@@ -95,4 +95,4 @@
 
 #endif /* __GNUC__ */
 
-#endif /* _PPc_POSIX_TYPES_H */
+#endif /* _PPC_POSIX_TYPES_H */
diff -u --recursive --new-file pre2.0.8/linux/include/linux/mc146818rtc.h linux/include/linux/mc146818rtc.h
--- pre2.0.8/linux/include/linux/mc146818rtc.h	Tue May  7 16:22:38 1996
+++ linux/include/linux/mc146818rtc.h	Tue May 28 07:39:19 1996
@@ -107,25 +107,7 @@
 #endif
 
 /*
- * ioctl calls that are permitted to the /dev/rtc interface, if 
- * CONFIG_RTC was enabled.
- */
-
-#define RTC_AIE_ON	0x01		/* Alarm int. enable on		*/
-#define RTC_AIE_OFF	0x02		/* ... off			*/
-#define RTC_UIE_ON	0x03		/* Update int. enable on	*/
-#define RTC_UIE_OFF	0x04		/* ... off			*/
-#define RTC_PIE_ON	0x05		/* Periodic int. enable on	*/
-#define RTC_PIE_OFF	0x06		/* ... off			*/
-#define RTC_ALM_SET	0x07		/* Set alarm (struct tm)	*/
-#define RTC_ALM_READ	0x08		/* Read alarm (struct tm)	*/
-#define RTC_RD_TIME	0x09		/* Read RTC time (struct tm)	*/
-#define RTC_SET_TIME	0x0a		/* Set time of RTC (not used)	*/
-#define RTC_IRQP_READ	0x0b		/* Read periodic IRQ rate (Hz)	*/
-#define RTC_IRQP_SET	0x0c		/* Set periodic IRQ rate (Hz)	*/
-
-/*
- * The struct used to pass data via the above ioctl. Similar to the
+ * The struct used to pass data via the following ioctl. Similar to the
  * struct tm in <time.h>, but it needs to be here so that the kernel 
  * source is self contained, allowing cross-compiles, etc. etc.
  */
@@ -141,5 +123,25 @@
 	int tm_yday;
 	int tm_isdst;
 };
+
+/*
+ * ioctl calls that are permitted to the /dev/rtc interface, if 
+ * CONFIG_RTC was enabled.
+ */
+
+#define RTC_AIE_ON	_IO('p', 0x01)	/* Alarm int. enable on		*/
+#define RTC_AIE_OFF	_IO('p', 0x02)	/* ... off			*/
+#define RTC_UIE_ON	_IO('p', 0x03)	/* Update int. enable on	*/
+#define RTC_UIE_OFF	_IO('p', 0x04)	/* ... off			*/
+#define RTC_PIE_ON	_IO('p', 0x05)	/* Periodic int. enable on	*/
+#define RTC_PIE_OFF	_IO('p', 0x06)	/* ... off			*/
+
+#define RTC_ALM_SET	_IOW('p', 0x07, struct rtc_time) /* Set alarm time  */
+#define RTC_ALM_READ	_IOR('p', 0x08, struct rtc_time) /* Read alarm time */
+#define RTC_RD_TIME	_IOR('p', 0x09, struct rtc_time) /* Read RTC time   */
+#define RTC_SET_TIME	_IOW('p', 0x0a, struct rtc_time) /* Set RTC time    */
+#define RTC_IRQP_READ	_IOR('p', 0x0b, unsigned long)	 /* Read IRQ rate   */
+#define RTC_IRQP_SET	_IOW('p', 0x0c, unsigned long)	 /* Set IRQ rate    */
+
 
 #endif /* _MC146818RTC_H */
diff -u --recursive --new-file pre2.0.8/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- pre2.0.8/linux/kernel/ksyms.c	Tue May 21 19:52:39 1996
+++ linux/kernel/ksyms.c	Wed May 29 16:42:27 1996
@@ -163,7 +163,6 @@
 	X(__bforget),
 	X(ll_rw_block),
 	X(__wait_on_buffer),
-	X(__wait_on_page),
 	X(mark_buffer_uptodate),
 	X(unlock_buffer),
 	X(dcache_lookup),
diff -u --recursive --new-file pre2.0.8/linux/mm/filemap.c linux/mm/filemap.c
--- pre2.0.8/linux/mm/filemap.c	Tue May 21 19:52:39 1996
+++ linux/mm/filemap.c	Wed May 29 16:44:11 1996
@@ -42,6 +42,19 @@
  */
 
 /*
+ * This is a special fast page-free routine that _only_ works
+ * on page-cache pages that we are currently using. We can
+ * just decrement the page count, because we know that the page
+ * has a count > 1 (the page cache itself counts as one, and
+ * we're currently using it counts as one). So we don't need
+ * the full free_page() stuff..
+ */
+static inline void release_page(struct page * page)
+{
+	atomic_dec(&page->count);
+}
+
+/*
  * Invalidate the pages of an inode, removing all pages that aren't
  * locked down (those are sure to be up-to-date anyway, so we shouldn't
  * invalidate them).
@@ -228,12 +241,9 @@
 			len = count;
 		page = find_page(inode, pos);
 		if (page) {
-			unsigned long addr;
-
 			wait_on_page(page);
-			addr = page_address(page);
-			memcpy((void *) (offset + addr), buf, len);
-			free_page(addr);
+			memcpy((void *) (offset + page_address(page)), buf, len);
+			release_page(page);
 		}
 		count -= len;
 		buf += len;
@@ -273,7 +283,7 @@
 #if 1
 	page = find_page(inode, offset);
 	if (page) {
-		page->count--;
+		release_page(page);
 		return page_cache;
 	}
 	/*
@@ -291,12 +301,15 @@
 
 /* 
  * Wait for IO to complete on a locked page.
+ *
+ * This must be called with the caller "holding" the page,
+ * ie with increased "page->count" so that the page won't
+ * go away during the wait..
  */
 void __wait_on_page(struct page *page)
 {
 	struct wait_queue wait = { current, NULL };
 
-	page->count++;
 	add_wait_queue(&page->wait, &wait);
 repeat:
 	run_task_queue(&tq_disk);
@@ -306,7 +319,6 @@
 		goto repeat;
 	}
 	remove_wait_queue(&page->wait, &wait);
-	page->count--;
 	current->state = TASK_RUNNING;
 }
 
@@ -558,9 +570,6 @@
 	unsigned long pos, ppos, page_cache;
 	int reada_ok;
 
-	if (count <= 0)
-		return 0;
-
 	error = 0;
 	read = 0;
 	page_cache = 0;
@@ -608,45 +617,18 @@
 
 	for (;;) {
 		struct page *page;
-		unsigned long offset, addr, nr;
 
 		if (pos >= inode->i_size)
 			break;
-		offset = pos & ~PAGE_MASK;
-		nr = PAGE_SIZE - offset;
-		/*
-		 * Try to find the data in the page cache..
-		 */
-		page = find_page(inode, pos & PAGE_MASK);
-		if (page)
-			goto found_page;
 
 		/*
-		 * Ok, it wasn't cached, so we need to create a new
-		 * page..
-		 */
-		if (page_cache)
-			goto new_page;
-
-		error = -ENOMEM;
-		page_cache = __get_free_page(GFP_KERNEL);
-		if (!page_cache)
-			break;
-		error = 0;
-
-		/*
-		 * That could have slept, so we need to check again..
+		 * Try to find the data in the page cache..
 		 */
-		if (pos >= inode->i_size)
-			break;
 		page = find_page(inode, pos & PAGE_MASK);
 		if (!page)
-			goto new_page;
+			goto no_cached_page;
 
 found_page:
-		addr = page_address(page);
-		if (nr > count)
-			nr = count;
 /*
  * Try to read ahead only if the current page is filled or being filled.
  * Otherwise, if we were reading ahead, decrease max read ahead size to
@@ -659,15 +641,27 @@
 		else if (reada_ok && filp->f_ramax > MIN_READAHEAD)
 				filp->f_ramax = MIN_READAHEAD;
 
-		if (PageLocked(page))
-			__wait_on_page(page);
+		wait_on_page(page);
 
 		if (!PageUptodate(page))
-			goto read_page;
+			goto page_read_error;
+
+success:
+		/*
+		 * Ok, we have the page, it's up-to-date and ok,
+		 * so now we can finally copy it to user space...
+		 */
+	{
+		unsigned long offset, nr;
+		offset = pos & ~PAGE_MASK;
+		nr = PAGE_SIZE - offset;
+		if (nr > count)
+			nr = count;
+
 		if (nr > inode->i_size - pos)
 			nr = inode->i_size - pos;
-		memcpy_tofs(buf, (void *) (addr + offset), nr);
-		free_page(addr);
+		memcpy_tofs(buf, (void *) (page_address(page) + offset), nr);
+		release_page(page);
 		buf += nr;
 		pos += nr;
 		read += nr;
@@ -675,13 +669,28 @@
 		if (count)
 			continue;
 		break;
-	
+	}
+
+no_cached_page:
+		/*
+		 * Ok, it wasn't cached, so we need to create a new
+		 * page..
+		 */
+		if (!page_cache) {
+			page_cache = __get_free_page(GFP_KERNEL);
+			/*
+			 * That could have slept, so go around to the
+			 * very beginning..
+			 */
+			if (page_cache)
+				continue;
+			error = -ENOMEM;
+			break;
+		}
 
-new_page:
 		/*
 		 * Ok, add the new page to the hash-queues...
 		 */
-		addr = page_cache;
 		page = mem_map + MAP_NR(page_cache);
 		page_cache = 0;
 		add_to_page_cache(page, inode, pos & PAGE_MASK);
@@ -694,7 +703,6 @@
 		 * identity of the reader can decide if we can read the
 		 * page or not..
 		 */
-read_page:
 /*
  * We have to read the page.
  * If we were reading ahead, we had previously tried to read this page,
@@ -706,12 +714,25 @@
 			filp->f_ramax = MIN_READAHEAD;
 
 		error = inode->i_op->readpage(inode, page);
+		if (!error)
+			goto found_page;
+		release_page(page);
+		break;
+
+page_read_error:
+		/*
+		 * We found the page, but it wasn't up-to-date.
+		 * Try to re-read it _once_. We do this synchronously,
+		 * because this happens only if there were errors.
+		 */
+		error = inode->i_op->readpage(inode, page);
 		if (!error) {
-			if (!PageError(page))
-				goto found_page;
-			error = -EIO;
+			wait_on_page(page);
+			if (PageUptodate(page) && !PageError(page))
+				goto success;
+			error = -EIO; /* Some unspecified error occurred.. */
 		}
-		free_page(addr);
+		release_page(page);
 		break;
 	}
 
@@ -729,78 +750,125 @@
 }
 
 /*
- * Find a cached page and wait for it to become up-to-date, return
- * the page address.  Increments the page count.
+ * Semantics for shared and private memory areas are different past the end
+ * of the file. A shared mapping past the last page of the file is an error
+ * and results in a SIGBUS, while a private mapping just maps in a zero page.
+ *
+ * The goto's are kind of ugly, but this streamlines the normal case of having
+ * it in the page cache, and handles the special cases reasonably without
+ * having a lot of duplicated code.
  */
-static inline unsigned long fill_page(struct inode * inode, unsigned long offset)
+static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address, int no_share)
 {
+	unsigned long offset;
 	struct page * page;
-	unsigned long new_page;
+	struct inode * inode = area->vm_inode;
+	unsigned long old_page, new_page;
+
+	new_page = 0;
+	offset = (address & PAGE_MASK) - area->vm_start + area->vm_offset;
+	if (offset >= inode->i_size && (area->vm_flags & VM_SHARED) && area->vm_mm == current->mm)
+		goto no_page;
 
+	/*
+	 * Do we have something in the page cache already?
+	 */
 	page = find_page(inode, offset);
-	if (page)
-		goto found_page_dont_free;
+	if (!page)
+		goto no_cached_page;
+
+found_page:
+	/*
+	 * Ok, found a page in the page cache, now we need to check
+	 * that it's up-to-date
+	 */
+	wait_on_page(page);
+	if (!PageUptodate(page))
+		goto page_read_error;
+
+success:
+	/*
+	 * Found the page, need to check sharing and possibly
+	 * copy it over to another page..
+	 */
+	old_page = page_address(page);
+	if (!no_share) {
+		/*
+		 * Ok, we can share the cached page directly.. Get rid
+		 * of any potential extra pages.
+		 */
+		if (new_page)
+			free_page(new_page);
+
+		flush_page_to_ram(old_page);
+		return old_page;
+	}
+
+	/*
+	 * Check that we have another page to copy it over to..
+	 */
+	if (!new_page) {
+		new_page = __get_free_page(GFP_KERNEL);
+		if (!new_page)
+			goto failure;
+	}
+	memcpy((void *) new_page, (void *) old_page, PAGE_SIZE);
+	flush_page_to_ram(new_page);
+	release_page(page);
+	return new_page;
+
+no_cached_page:
 	new_page = __get_free_page(GFP_KERNEL);
+	if (!new_page)
+		goto no_page;
+
+	/*
+	 * During getting the above page we might have slept,
+	 * so we need to re-check the situation with the page
+	 * cache.. The page we just got may be useful if we
+	 * can't share, so don't get rid of it here.
+	 */
 	page = find_page(inode, offset);
 	if (page)
 		goto found_page;
-	if (!new_page)
-		goto failure;
+
+	/*
+	 * Now, create a new page-cache page from the page we got
+	 */
 	page = mem_map + MAP_NR(new_page);
 	new_page = 0;
 	add_to_page_cache(page, inode, offset);
-	inode->i_op->readpage(inode, page);
+
+	if (inode->i_op->readpage(inode, page) != 0)
+		goto failure;
+
+	/*
+	 * Do a very limited read-ahead if appropriate
+	 */
 	if (PageLocked(page))
 		new_page = try_to_read_ahead(inode, offset + PAGE_SIZE, 0);
-found_page:
-	if (new_page)
-		free_page(new_page);
-found_page_dont_free:
-	wait_on_page(page);
-	if (PageUptodate(page)) {
-success:	
-		return page_address(page);
-	}
-	/* If not marked as error, try _once_ to read it again */
-	if (!PageError(page)) {
-		inode->i_op->readpage(inode, page);
-		wait_on_page(page);
-		if (PageUptodate(page))
-			goto success;
-	}
-	page->count--;
-failure:
-	return 0;
-}
-
-/*
- * Semantics for shared and private memory areas are different past the end
- * of the file. A shared mapping past the last page of the file is an error
- * and results in a SIGBUS, while a private mapping just maps in a zero page.
- */
-static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address, int no_share)
-{
-	unsigned long offset;
-	struct inode * inode = area->vm_inode;
-	unsigned long page;
+	goto found_page;
 
-	offset = (address & PAGE_MASK) - area->vm_start + area->vm_offset;
-	if (offset >= inode->i_size && (area->vm_flags & VM_SHARED) && area->vm_mm == current->mm)
-		return 0;
+page_read_error:
+	/*
+	 * Umm, take care of errors if the page isn't up-to-date.
+	 * Try to re-read it _once_.
+	 */
+	if (inode->i_op->readpage(inode, page) != 0)
+		goto failure;
+	if (PageError(page))
+		goto failure;
+	if (PageUptodate(page))
+		goto success;
 
-	page = fill_page(inode, offset);
-	if (page && no_share) {
-		unsigned long new_page = __get_free_page(GFP_KERNEL);
-		if (new_page) {
-			memcpy((void *) new_page, (void *) page, PAGE_SIZE);
-			flush_page_to_ram(new_page);
-		}
-		free_page(page);
-		return new_page;
-	}
-	if (page)
-		flush_page_to_ram(page);
-	return page;
+	/*
+	 * Uhhuh.. Things didn't work out. Return zero to tell the
+	 * mm layer so, possibly freeing the page cache page first.
+	 */
+failure:
+	release_page(page);
+no_page:
+	return 0;
 }
 
 /*
diff -u --recursive --new-file pre2.0.8/linux/mm/kmalloc.c linux/mm/kmalloc.c
--- pre2.0.8/linux/mm/kmalloc.c	Fri Apr  5 13:35:28 1996
+++ linux/mm/kmalloc.c	Wed May 29 17:59:34 1996
@@ -171,6 +171,38 @@
 #define BLOCKSIZE(order)        (blocksize[order])
 #define AREASIZE(order)		(PAGE_SIZE<<(sizes[order].gfporder))
 
+/*
+ * Create a small cache of page allocations: this helps a bit with
+ * those pesky 8kB+ allocations for NFS when we're temporarily
+ * out of memory..
+ *
+ * This is a _truly_ small cache, we just cache one single page
+ * order (for orders 0, 1 and 2, that is  4, 8 and 16kB on x86).
+ */
+#define MAX_CACHE_ORDER 3
+struct page_descriptor * kmalloc_cache[MAX_CACHE_ORDER];
+
+static inline struct page_descriptor * get_kmalloc_pages(unsigned long priority,
+	unsigned long order, int dma)
+{
+	struct page_descriptor * tmp;
+
+	tmp = (struct page_descriptor *) __get_free_pages(priority, order, dma);
+	if (!tmp && !dma && order < MAX_CACHE_ORDER)
+		tmp = xchg(kmalloc_cache+order, tmp);
+	return tmp;
+}
+
+static inline void free_kmalloc_pages(struct page_descriptor * page,
+	unsigned long order, int dma)
+{
+	if (!dma && order < MAX_CACHE_ORDER) {
+		page = xchg(kmalloc_cache+order, page);
+		if (!page)
+			return;
+	}
+	free_pages((unsigned long) page, order);
+}
 
 long kmalloc_init(long start_mem, long end_mem)
 {
@@ -260,8 +292,7 @@
 		/* sz is the size of the blocks we're dealing with */
 		sz = BLOCKSIZE(order);
 
-		page = (struct page_descriptor *) __get_free_pages(priority,
-				sizes[order].gfporder, dma);
+		page = get_kmalloc_pages(priority, sizes[order].gfporder, dma);
 
 		if (!page)
 			goto no_free_page;
@@ -322,7 +353,7 @@
 
 void kfree(void *ptr)
 {
-	int size;
+	int size, dma;
 	unsigned long flags;
 	int order;
 	register struct block_header *p;
@@ -331,10 +362,12 @@
 	if (!ptr)
 		return;
 	p = ((struct block_header *) ptr) - 1;
+	dma = 0;
 	page = PAGE_DESC(p);
 	order = page->order;
 	pg = &sizes[order].firstfree;
 	if (p->bh_flags == MF_DMA) {
+		dma = 1;
 		p->bh_flags = MF_USED;
 		pg = &sizes[order].dmafree;
 	}
@@ -378,7 +411,7 @@
 			pg = &tmp->next;
 		}
 		sizes[order].npages--;
-		free_pages((long) page, sizes[order].gfporder);
+		free_kmalloc_pages(page, sizes[order].gfporder, dma);
 	}
 	sizes[order].nfrees++;
 	sizes[order].nbytesmalloced -= size;
diff -u --recursive --new-file pre2.0.8/linux/mm/page_io.c linux/mm/page_io.c
--- pre2.0.8/linux/mm/page_io.c	Tue Apr 23 13:57:14 1996
+++ linux/mm/page_io.c	Wed May 29 16:52:31 1996
@@ -76,10 +76,10 @@
 	else
 		kstat.pswpout++;
 	page = mem_map + MAP_NR(buf);
+	atomic_inc(&page->count);
 	wait_on_page(page);
 	if (p->swap_device) {
 		if (!wait) {
-			page->count++;
 			set_bit(PG_free_after, &page->flags);
 			set_bit(PG_decr_after, &page->flags);
 			set_bit(PG_swap_unlock_after, &page->flags);
@@ -87,6 +87,11 @@
 			nr_async_pages++;
 		}
 		ll_rw_page(rw,p->swap_device,offset,buf);
+		/*
+		 * NOTE! We don't decrement the page count if we
+		 * don't wait - that will happen asynchronously
+		 * when the IO completes.
+		 */
 		if (!wait)
 			return;
 		wait_on_page(page);
@@ -130,6 +135,7 @@
 		ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf);
 	} else
 		printk("rw_swap_page: no swap file or device\n");
+	atomic_dec(&page->count);
 	if (offset && !clear_bit(offset,p->swap_lockmap))
 		printk("rw_swap_page: lock already cleared\n");
 	wake_up(&lock_queue);
diff -u --recursive --new-file pre2.0.8/linux/mm/swapfile.c linux/mm/swapfile.c
--- pre2.0.8/linux/mm/swapfile.c	Tue May  7 16:22:40 1996
+++ linux/mm/swapfile.c	Tue May 28 07:39:18 1996
@@ -318,12 +318,13 @@
 	struct inode * inode;
 	struct file filp;
 	int i, type, prev;
+	int err;
 
 	if (!suser())
 		return -EPERM;
-	i = namei(specialfile,&inode);
-	if (i)
-		return i;
+	err = namei(specialfile,&inode);
+	if (err)
+		return err;
 	prev = -1;
 	for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
 		p = swap_info + type;
@@ -353,13 +354,21 @@
 		swap_list.next = swap_list.head;
 	}
 	p->flags = SWP_USED;
-	i = try_to_unuse(type);
-	if (i) {
+	err = try_to_unuse(type);
+	if (err) {
 		iput(inode);
+		/* re-insert swap space back into swap_list */
+		for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next)
+			if (p->prio >= swap_info[i].prio)
+				break;
+		p->next = i;
+		if (prev < 0)
+			swap_list.head = swap_list.next = p - swap_info;
+		else
+			swap_info[prev].next = p - swap_info;
 		p->flags = SWP_WRITEOK;
-		return i;
+		return err;
 	}
-
 	if(p->swap_device){
 		memset(&filp, 0, sizeof(filp));		
 		filp.f_inode = inode;
diff -u --recursive --new-file pre2.0.8/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- pre2.0.8/linux/net/ipv4/ip_fw.c	Tue May 28 08:10:01 1996
+++ linux/net/ipv4/ip_fw.c	Wed May 29 14:24:12 1996
@@ -541,7 +541,13 @@
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 			if (policy&IP_FW_F_REDIR) {
 				if (redirport)
-					*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp]);
+					if ((*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp])) == 0) {
+						/* Wildcard redirection.
+						 * Note that redirport will become
+						 * 0xFFFF for non-TCP/UDP packets.
+						 */
+						*redirport = dst_port;
+					}
 				answer = FW_REDIRECT;
 			} else
 #endif
