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

diff -urN linux-2.4.21-bk4/Makefile linux-2.4.21-bk5/Makefile
--- linux-2.4.21-bk4/Makefile	2003-07-09 02:53:51.000000000 -0700
+++ linux-2.4.21-bk5/Makefile	2003-07-09 02:53:58.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 21
-EXTRAVERSION = -bk4
+EXTRAVERSION = -bk5
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.21-bk4/arch/sh64/config.in linux-2.4.21-bk5/arch/sh64/config.in
--- linux-2.4.21-bk4/arch/sh64/config.in	2003-07-09 02:53:53.000000000 -0700
+++ linux-2.4.21-bk5/arch/sh64/config.in	2003-07-09 02:53:58.000000000 -0700
@@ -159,18 +159,18 @@
    source net/Config.in
 fi
 
-# mainmenu_option next_comment
-# comment 'ATA/IDE/MFM/RLL support'
-# 
-# tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
-# 
-# if [ "$CONFIG_IDE" != "n" ]; then
-#   source drivers/ide/Config.in
-# else
+mainmenu_option next_comment
+comment 'ATA/IDE/MFM/RLL support'
+
+tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+
+if [ "$CONFIG_IDE" != "n" ]; then
+  source drivers/ide/Config.in
+else
    define_bool CONFIG_BLK_DEV_IDE_MODES n
    define_bool CONFIG_BLK_DEV_HD n
-# fi
-# endmenu
+fi
+endmenu
 
 mainmenu_option next_comment
 comment 'SCSI support'
diff -urN linux-2.4.21-bk4/arch/sh64/kernel/pci_sh5.c linux-2.4.21-bk5/arch/sh64/kernel/pci_sh5.c
--- linux-2.4.21-bk4/arch/sh64/kernel/pci_sh5.c	2003-07-09 02:53:53.000000000 -0700
+++ linux-2.4.21-bk5/arch/sh64/kernel/pci_sh5.c	2003-07-09 02:53:58.000000000 -0700
@@ -124,7 +124,7 @@
         uval = SH5PCI_READ(CR);
 
 	/* Set command Register */
-        SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS);
+        SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS | CR_BMAM );
 
 	uval=SH5PCI_READ(CR);
         dprintk("CR is actually 0x%08x\n",uval);
@@ -318,33 +318,46 @@
 
 static int __init map_cayman_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	dprintk("map_cayman_irq for dev %d on bus %d slot %d, pin is %d\n",
-	       dev->devfn,dev->bus->number,slot,pin);
- 
+	int result = -1;
+
 	if (dev->bus->number == 0) {
-	        switch (slot) {
+	        switch ((slot + (pin-1)) & 3) {
 	        case 0:
-	          return IRQ_INTA;
+	          result = IRQ_INTA;
+		  break;
                 case 1:
-	          return IRQ_INTB;
+	          result = IRQ_INTB;
+		  break;
                 case 2:
-	          return IRQ_INTC;
+	          result = IRQ_INTC;
+		  break;
 		case 3:
-		  return IRQ_INTD;
+		  result = IRQ_INTD;
+		  break;
                 }
         }
 
 	if (dev->bus->number == 2) {
-	        switch(slot) {
+	        switch((slot + (pin-1)) & 3) {
 	        case 0:
-	          return IRQ_P2INTA;
+	          result = IRQ_P2INTA;
+		  break;
                 case 1:
-	          return IRQ_P2INTB;
+	          result = IRQ_P2INTB;
+		  break;
+                case 2:
+	          result = IRQ_P2INTC;
+		  break;
+                case 3:
+	          result = IRQ_P2INTD;
+		  break;
                 }
         }
 
-	/* FIXME - DO PROPER MAPPING FOR GODS SAKE */
-	return -1;
+	dprintk("map_cayman_irq for dev %d on bus %d slot %d, pin is %d : irq=%d\n",
+	       dev->devfn,dev->bus->number,slot,pin,result);
+
+	return result;
 }
 
 #ifdef DEBUG
diff -urN linux-2.4.21-bk4/arch/sh64/kernel/sh_ksyms.c linux-2.4.21-bk5/arch/sh64/kernel/sh_ksyms.c
--- linux-2.4.21-bk4/arch/sh64/kernel/sh_ksyms.c	2003-07-09 02:53:53.000000000 -0700
+++ linux-2.4.21-bk5/arch/sh64/kernel/sh_ksyms.c	2003-07-09 02:53:58.000000000 -0700
@@ -41,10 +41,13 @@
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
 
+#if 0
+/* Not yet - there's no declaration of drive_info anywhere. */
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
 extern struct drive_info_struct drive_info;
 EXPORT_SYMBOL(drive_info);
 #endif
+#endif
 
 /* platform dependent support */
 EXPORT_SYMBOL(dump_thread);
diff -urN linux-2.4.21-bk4/arch/sh64/kernel/traps.c linux-2.4.21-bk5/arch/sh64/kernel/traps.c
--- linux-2.4.21-bk4/arch/sh64/kernel/traps.c	2003-07-09 02:53:53.000000000 -0700
+++ linux-2.4.21-bk5/arch/sh64/kernel/traps.c	2003-07-09 02:53:58.000000000 -0700
@@ -90,20 +90,28 @@
 DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current)
 
 #if defined(CONFIG_SH64_ID2815_WORKAROUND)
+
+#define OPCODE_INVALID      0
+#define OPCODE_USER_VALID   1
+#define OPCODE_PRIV_VALID   2
+
+/* getcon/putcon - requires checking which control register is referenced. */
+#define OPCODE_CTRL_REG     3
+
 /* Table of valid opcodes for SHmedia mode.
    Form a 10-bit value by concatenating the major/minor opcodes i.e.
-   opcode[31:26,20:16].  The 5 MSBs of this value index into the following
-   array.  The 5 LSBs select the bit in the entry (bit 0 corresponds to
-   LSBs==5'b00000 etc). */
-static unsigned long valid_shmedia_opcodes[32] = {
-	0xeacfff8a,0x6e667676,0x40400000,0x2307150f,
-	0x8000002a,0x88ffaef7,0x40ffff07,0x2300fff3,
-	0x0022003f,0x7766022b,0x00000000,0x00000000,
-	0x88aa000f,0x80ef0022,0x00000000,0x00000000,
-	0xffffffff,0xffffffff,0xffffffff,0xffffffff,
-	0xffffffff,0xffffffff,0xffffffff,0xffffffff,
-	0x20cf80cc,0xffffffff,0xffffffff,0xffffffff,
-	0x002293fe,0xffffffff,0x00000000,0x00000000
+   opcode[31:26,20:16].  The 6 MSBs of this value index into the following
+   array.  The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to
+   LSBs==4'b0000 etc). */
+static unsigned long shmedia_opcode_table[64] = {
+	0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015,
+	0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000,
+	0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000,
+	0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000,
+	0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+	0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+	0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+	0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000
 };
 
 void do_reserved_inst(unsigned long error_code, struct pt_regs *regs)
@@ -131,25 +139,58 @@
 			get_user_error = __get_user(opcode, (unsigned long *)aligned_pc);
 		}
 		if (get_user_error >= 0) {
-			unsigned long index, mask;
+			unsigned long index, shift;
 			unsigned long major, minor, combined;
 			unsigned long reserved_field;
 			reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */
 			major = (opcode >> 26) & 0x3f;
 			minor = (opcode >> 16) & 0xf;
-			combined = (major << 6) | minor;
-			index = combined >> 5;
-			mask = 1UL << (combined & 0x1f);
-			if ((reserved_field == 0) && (valid_shmedia_opcodes[index] & mask)) {
-#if 0
-				printk("Fixed up errata #2815 at PC=%08lx for pid %d (opcode=%08lx)\n",
-					pc, current->pid, opcode);
-#endif
-				/* Now just return to restart the instruction,
-				   because the branch to the instruction will
-				   now be from a SHmedia RTE the silicon defect
-				   won't be triggered. */
-				return;
+			combined = (major << 4) | minor;
+			index = major;
+			shift = minor << 1;
+			if (reserved_field == 0) {
+				int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3;
+				switch (opcode_state) {
+					case OPCODE_INVALID:
+						/* Trap. */
+						break;
+					case OPCODE_USER_VALID:
+						/* Restart the instruction : the branch to the instruction will now be from an RTE
+						   not from SHcompact so the silicon defect won't be triggered. */
+						return;
+					case OPCODE_PRIV_VALID:
+						if (!user_mode(regs)) {
+							/* Should only ever get here if a module has
+							   SHcompact code inside it.  If so, the same fix up is needed. */
+							return; /* same reason */
+						}
+						/* Otherwise, user mode trying to execute a privileged instruction - 
+						   fall through to trap. */
+						break;
+					case OPCODE_CTRL_REG:
+						/* If in privileged mode, return as above. */
+						if (!user_mode(regs)) return; 
+						/* In user mode ... */
+						if (combined == 0x9f) { /* GETCON */
+							unsigned long regno = (opcode >> 20) & 0x3f;
+							if (regno >= 62) {
+								return;
+							}
+							/* Otherwise, reserved or privileged control register, => trap */
+						} else if (combined == 0x1bf) { /* PUTCON */
+							unsigned long regno = (opcode >> 4) & 0x3f;
+							if (regno >= 62) {
+								return;
+							}
+							/* Otherwise, reserved or privileged control register, => trap */
+						} else {
+							/* Trap */
+						}
+						break;
+					default:
+						/* Fall through to trap. */
+						break;
+				}
 			}
 			/* fall through to normal resinst processing */
 		} else {
@@ -161,7 +202,7 @@
 			signr = SIGSEGV;
 		}
 	}
-	
+
 	show_excp_regs("do_reserved_inst", trapnr, signr, regs);
 	current->thread.error_code = error_code;
 	current->thread.trap_no = trapnr;
diff -urN linux-2.4.21-bk4/arch/sh64/mach-cayman/irq.c linux-2.4.21-bk5/arch/sh64/mach-cayman/irq.c
--- linux-2.4.21-bk4/arch/sh64/mach-cayman/irq.c	2003-07-09 02:53:53.000000000 -0700
+++ linux-2.4.21-bk5/arch/sh64/mach-cayman/irq.c	2003-07-09 02:53:58.000000000 -0700
@@ -162,7 +162,7 @@
     return intc_irq_describe(p, irq);
   else if (irq < NR_INTC_IRQS + 8)
     return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS);
-  else if ((irq > NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32))
+  else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32))
     return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24)); 
   else
     return 0;
diff -urN linux-2.4.21-bk4/fs/dcache.c linux-2.4.21-bk5/fs/dcache.c
--- linux-2.4.21-bk4/fs/dcache.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/dcache.c	2003-06-13 07:51:37.000000000 -0700
@@ -702,25 +702,13 @@
  
 struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
 {
-	struct dentry *dentry = NULL;
-
-	spin_lock(&dcache_lock);
-	dentry = __d_lookup(parent,name);
-	if (dentry)
-		__dget_locked(dentry);
-	spin_unlock(&dcache_lock);
-	return dentry;
-}
-
-struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)  
-{
-
 	unsigned int len = name->len;
 	unsigned int hash = name->hash;
 	const unsigned char *str = name->name;
 	struct list_head *head = d_hash(parent,hash);
 	struct list_head *tmp;
 
+	spin_lock(&dcache_lock);
 	tmp = head->next;
 	for (;;) {
 		struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);
@@ -740,9 +728,12 @@
 			if (memcmp(dentry->d_name.name, str, len))
 				continue;
 		}
+		__dget_locked(dentry);
 		dentry->d_vfs_flags |= DCACHE_REFERENCED;
+		spin_unlock(&dcache_lock);
 		return dentry;
 	}
+	spin_unlock(&dcache_lock);
 	return NULL;
 }
 
diff -urN linux-2.4.21-bk4/fs/dquot.c linux-2.4.21-bk5/fs/dquot.c
--- linux-2.4.21-bk4/fs/dquot.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/dquot.c	2003-07-09 02:54:00.000000000 -0700
@@ -152,8 +152,6 @@
 static LIST_HEAD(free_dquots);
 static struct list_head dquot_hash[NR_DQHASH];
 
-struct dqstats dqstats;
-
 static void dqput(struct dquot *);
 static struct dquot *dqduplicate(struct dquot *);
 
diff -urN linux-2.4.21-bk4/fs/ext3/inode.c linux-2.4.21-bk5/fs/ext3/inode.c
--- linux-2.4.21-bk4/fs/ext3/inode.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk5/fs/ext3/inode.c	2003-07-09 02:54:00.000000000 -0700
@@ -1413,7 +1413,7 @@
 	length = blocksize - length;
 	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
-	page = grab_cache_page(mapping, index);
+	page = find_or_create_page(mapping, index, GFP_NOFS);
 	err = -ENOMEM;
 	if (!page)
 		goto out;
diff -urN linux-2.4.21-bk4/fs/intermezzo/journal.c linux-2.4.21-bk5/fs/intermezzo/journal.c
--- linux-2.4.21-bk4/fs/intermezzo/journal.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/intermezzo/journal.c	2002-11-28 15:53:15.000000000 -0800
@@ -617,7 +617,8 @@
 
         CDEBUG(D_CACHE, "looking up: %s\n", path);
 
-        error = path_lookup(path, LOOKUP_PARENT, nd);
+        if (path_init(path, LOOKUP_PARENT, nd))
+                error = path_walk(path, nd);
         if (error) {
                 EXIT;
                 return error;
diff -urN linux-2.4.21-bk4/fs/intermezzo/presto.c linux-2.4.21-bk5/fs/intermezzo/presto.c
--- linux-2.4.21-bk4/fs/intermezzo/presto.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/intermezzo/presto.c	2002-11-28 15:53:15.000000000 -0800
@@ -53,7 +53,8 @@
 
         ENTRY;
         err = 0;
-        err = path_lookup(name, flags, nd);
+        if (path_init(name, flags, nd)) 
+                err = path_walk(name, nd);
         return err;
 }
 
diff -urN linux-2.4.21-bk4/fs/intermezzo/vfs.c linux-2.4.21-bk5/fs/intermezzo/vfs.c
--- linux-2.4.21-bk4/fs/intermezzo/vfs.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/intermezzo/vfs.c	2003-06-13 07:51:37.000000000 -0700
@@ -702,7 +702,8 @@
 
         /* this looks up the parent */
 //        if (path_init(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, &nd))
-        error = path_lookup(pathname,  LOOKUP_PARENT, &nd);
+        if (path_init(pathname,  LOOKUP_PARENT, &nd))
+                error = path_walk(pathname, &nd);
         if (error) {
                 EXIT;
                 goto exit;
@@ -854,10 +855,12 @@
                 struct nameidata nd, old_nd;
 
                 error = 0;
-                error = path_lookup(from, LOOKUP_POSITIVE, &old_nd);
+                if (path_init(from, LOOKUP_POSITIVE, &old_nd))
+                        error = path_walk(from, &old_nd);
                 if (error)
                         goto exit;
-                error = path_lookup(to, LOOKUP_PARENT, &nd);
+                if (path_init(to, LOOKUP_PARENT, &nd))
+                        error = path_walk(to, &nd);
                 if (error)
                         goto out;
                 error = -EXDEV;
@@ -1059,7 +1062,8 @@
         if(IS_ERR(name))
                 return PTR_ERR(name);
 
-        error = path_lookup(name, LOOKUP_PARENT, &nd);
+        if (path_init(name, LOOKUP_PARENT, &nd))
+                error = path_walk(name, &nd);
         if (error)
                 goto exit;
         error = -EISDIR;
@@ -1219,7 +1223,8 @@
                 goto exit_from;
         }
 
-        error = path_lookup(to, LOOKUP_PARENT, &nd);
+        if (path_init(to, LOOKUP_PARENT, &nd)) 
+                error = path_walk(to, &nd);
         if (error) {
                 EXIT;
                 goto exit_to;
@@ -1376,7 +1381,8 @@
                 return error;
         }
 
-        error = path_lookup(pathname, LOOKUP_PARENT, &nd);
+        if (path_init(pathname, LOOKUP_PARENT, &nd))
+                error = path_walk(pathname, &nd);
         if (error)
                 goto out_name;
 
@@ -1521,7 +1527,8 @@
                 return PTR_ERR(name);
         }
 
-        error = path_lookup(name, LOOKUP_PARENT, &nd);
+        if (path_init(name, LOOKUP_PARENT, &nd))
+                error = path_walk(name, &nd);
         if (error) {
                 EXIT;
                 goto exit;
@@ -1686,7 +1693,8 @@
         if (IS_ERR(tmp))
                 return PTR_ERR(tmp);
 
-        error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+        if (path_init(tmp, LOOKUP_PARENT, &nd))
+                error = path_walk(tmp, &nd);
         if (error)
                 goto out;
         dentry = lookup_create(&nd, 0);
@@ -1965,11 +1973,14 @@
 
         ENTRY;
 
-        error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
+        if (path_init(oldname, LOOKUP_PARENT, &oldnd))
+                error = path_walk(oldname, &oldnd);
+
         if (error)
                 goto exit;
 
-        error = path_lookup(newname, LOOKUP_PARENT, &newnd);
+        if (path_init(newname, LOOKUP_PARENT, &newnd))
+                error = path_walk(newname, &newnd);
         if (error)
                 goto exit1;
 
diff -urN linux-2.4.21-bk4/fs/namei.c linux-2.4.21-bk5/fs/namei.c
--- linux-2.4.21-bk4/fs/namei.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/namei.c	2003-06-13 07:51:37.000000000 -0700
@@ -263,7 +263,7 @@
 static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
 {
 	struct dentry * dentry = d_lookup(parent, name);
-	
+
 	if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
 		if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
 			dput(dentry);
@@ -273,61 +273,6 @@
 	return dentry;
 }
 
-/*for fastwalking*/
-static inline void unlock_nd(struct nameidata *nd)
-{
-	struct vfsmount *mnt = nd->old_mnt;
-	struct dentry *dentry = nd->old_dentry;
-	mntget(nd->mnt);
-	dget_locked(nd->dentry);
-	nd->old_mnt = NULL;
-	nd->old_dentry = NULL;
-	spin_unlock(&dcache_lock);
-	dput(dentry);
-	mntput(mnt);
-}
-
-static inline void lock_nd(struct nameidata *nd)
-{
-	spin_lock(&dcache_lock);
-	nd->old_mnt = nd->mnt;
-	nd->old_dentry = nd->dentry;
-}
-
-/*
- * Short-cut version of permission(), for calling by
- * path_walk(), when dcache lock is held.  Combines parts
- * of permission() and vfs_permission(), and tests ONLY for
- * MAY_EXEC permission.
- *
- * If appropriate, check DAC only.  If not appropriate, or
- * short-cut DAC fails, then call permission() to do more
- * complete permission check.
- */
-static inline int exec_permission_lite(struct inode *inode)
-{
-	umode_t	mode = inode->i_mode;
-
-	if ((inode->i_op && inode->i_op->permission))
-		return -EAGAIN;
-
-	if (current->fsuid == inode->i_uid)
-		mode >>= 6;
-	else if (in_group_p(inode->i_gid))
-		mode >>= 3;
-
-	if (mode & MAY_EXEC)
-		return 0;
-
-	if ((inode->i_mode & S_IXUGO) && capable(CAP_DAC_OVERRIDE))
-		return 0;
-
-	if (S_ISDIR(inode->i_mode) && capable(CAP_DAC_READ_SEARCH))
-	return 0;
-
-	return -EACCES;
-}
-
 /*
  * This is called when everything else fails, and we actually have
  * to go to the low-level filesystem to find out what we should do..
@@ -409,10 +354,10 @@
 	return -ELOOP;
 }
 
-int follow_up(struct vfsmount **mnt, struct dentry **dentry)
+static inline int __follow_up(struct vfsmount **mnt, struct dentry **base)
 {
 	struct vfsmount *parent;
-	struct dentry *mountpoint;
+	struct dentry *dentry;
 	spin_lock(&dcache_lock);
 	parent=(*mnt)->mnt_parent;
 	if (parent == *mnt) {
@@ -420,27 +365,18 @@
 		return 0;
 	}
 	mntget(parent);
-	mountpoint=dget((*mnt)->mnt_mountpoint);
+	dentry=dget((*mnt)->mnt_mountpoint);
 	spin_unlock(&dcache_lock);
-	dput(*dentry);
-	*dentry = mountpoint;
+	dput(*base);
+	*base = dentry;
 	mntput(*mnt);
 	*mnt = parent;
 	return 1;
 }
 
-static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+int follow_up(struct vfsmount **mnt, struct dentry **dentry)
 {
-	int res = 0;
-	while (d_mountpoint(*dentry)) {
-		struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
-		if (!mounted)
-			break;
-		*mnt = mounted;
-		*dentry = mounted->mnt_root;
-		res = 1;
-	}
-	return res;
+	return __follow_up(mnt, dentry);
 }
 
 static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
@@ -466,83 +402,41 @@
 	return __follow_down(mnt,dentry);
 }
  
-static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
+static inline void follow_dotdot(struct nameidata *nd)
 {
 	while(1) {
 		struct vfsmount *parent;
-		if (*dentry == current->fs->root &&
-		    *mnt == current->fs->rootmnt)
+		struct dentry *dentry;
+		read_lock(&current->fs->lock);
+		if (nd->dentry == current->fs->root &&
+		    nd->mnt == current->fs->rootmnt)  {
+			read_unlock(&current->fs->lock);
 			break;
-		if (*dentry != (*mnt)->mnt_root) {
-			*dentry = (*dentry)->d_parent;
+		}
+		read_unlock(&current->fs->lock);
+		spin_lock(&dcache_lock);
+		if (nd->dentry != nd->mnt->mnt_root) {
+			dentry = dget(nd->dentry->d_parent);
+			spin_unlock(&dcache_lock);
+			dput(nd->dentry);
+			nd->dentry = dentry;
 			break;
 		}
-		parent=(*mnt)->mnt_parent;
-		if (parent == *mnt)
+		parent=nd->mnt->mnt_parent;
+		if (parent == nd->mnt) {
+			spin_unlock(&dcache_lock);
 			break;
-		*dentry=(*mnt)->mnt_mountpoint;
-		*mnt = parent;
+		}
+		mntget(parent);
+		dentry=dget(nd->mnt->mnt_mountpoint);
+		spin_unlock(&dcache_lock);
+		dput(nd->dentry);
+		nd->dentry = dentry;
+		mntput(nd->mnt);
+		nd->mnt = parent;
 	}
-	follow_mount(mnt, dentry);
-}
-
-struct path {
-	struct vfsmount *mnt;
-	struct dentry *dentry;
-};
-
-/*
- *  It's more convoluted than I'd like it to be, but... it's still fairly
- *  small and for now I'd prefer to have fast path as straight as possible.
- *  It _is_ time-critical.
- */
-static int do_lookup(struct nameidata *nd, struct qstr *name,
-		     struct path *path, struct path *cached_path,
-		     int flags)
-{
-	struct vfsmount *mnt = nd->mnt;
-	struct dentry *dentry = __d_lookup(nd->dentry, name);
-
-	if (!dentry)
-		goto dcache_miss;
-	if (dentry->d_op && dentry->d_op->d_revalidate)
-		goto need_revalidate;
-done:
-	path->mnt = mnt;
-	path->dentry = dentry;
-	return 0;
-
-dcache_miss:
-	unlock_nd(nd);
-
-need_lookup:
-	dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
-	if (IS_ERR(dentry))
-		goto fail;
-	mntget(mnt);
-relock:
-	dput(cached_path->dentry);
-	mntput(cached_path->mnt);
-	cached_path->mnt = mnt;
-	cached_path->dentry = dentry;
-	lock_nd(nd);
-	goto done;
-
-need_revalidate:
-	mntget(mnt);
-	dget_locked(dentry);
-	unlock_nd(nd);
-	if (dentry->d_op->d_revalidate(dentry, flags))
-		goto relock;
-	if (d_invalidate(dentry))
-		goto relock;
-	dput(dentry);
-	mntput(mnt);
-	goto need_lookup;
-
-fail:
-	lock_nd(nd);
-	return PTR_ERR(dentry);
+	while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry))
+		;
 }
 
 /*
@@ -555,15 +449,15 @@
  */
 int link_path_walk(const char * name, struct nameidata *nd)
 {
-	struct path next, pinned = {NULL, NULL};
+	struct dentry *dentry;
 	struct inode *inode;
 	int err;
 	unsigned int lookup_flags = nd->flags;
-	
+
 	while (*name=='/')
 		name++;
 	if (!*name)
-		goto return_base;
+		goto return_reval;
 
 	inode = nd->dentry->d_inode;
 	if (current->link_count)
@@ -575,12 +469,8 @@
 		struct qstr this;
 		unsigned int c;
 
-		err = exec_permission_lite(inode);
-		if (err == -EAGAIN) {
-			unlock_nd(nd);
-			err = permission(inode, MAY_EXEC);
-			lock_nd(nd);
-		}
+		err = permission(inode, MAY_EXEC);
+		dentry = ERR_PTR(err);
  		if (err)
 			break;
 
@@ -614,7 +504,7 @@
 			case 2:	
 				if (this.name[1] != '.')
 					break;
-				follow_dotdot(&nd->mnt, &nd->dentry);
+				follow_dotdot(nd);
 				inode = nd->dentry->d_inode;
 				/* fallthrough */
 			case 1:
@@ -630,30 +520,30 @@
 				break;
 		}
 		/* This does the actual lookups.. */
-		err = do_lookup(nd, &this, &next, &pinned, LOOKUP_CONTINUE);
-		if (err)
-			break;
+		dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
+		if (!dentry) {
+			dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
+			err = PTR_ERR(dentry);
+			if (IS_ERR(dentry))
+				break;
+		}
 		/* Check mountpoints.. */
-		follow_mount(&next.mnt, &next.dentry);
+		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
+			;
 
 		err = -ENOENT;
-		inode = next.dentry->d_inode;
+		inode = dentry->d_inode;
 		if (!inode)
-			break;
+			goto out_dput;
 		err = -ENOTDIR; 
 		if (!inode->i_op)
-			break;
+			goto out_dput;
 
 		if (inode->i_op->follow_link) {
-			mntget(next.mnt);
-			dget_locked(next.dentry);
-			unlock_nd(nd);
-			err = do_follow_link(next.dentry, nd);
-			dput(next.dentry);
-			mntput(next.mnt);
+			err = do_follow_link(dentry, nd);
+			dput(dentry);
 			if (err)
 				goto return_err;
-			lock_nd(nd);
 			err = -ENOENT;
 			inode = nd->dentry->d_inode;
 			if (!inode)
@@ -662,8 +552,8 @@
 			if (!inode->i_op)
 				break;
 		} else {
-			nd->mnt = next.mnt;
-			nd->dentry = next.dentry;
+			dput(nd->dentry);
+			nd->dentry = dentry;
 		}
 		err = -ENOTDIR; 
 		if (!inode->i_op->lookup)
@@ -682,47 +572,52 @@
 			case 2:	
 				if (this.name[1] != '.')
 					break;
-				follow_dotdot(&nd->mnt, &nd->dentry);
+				follow_dotdot(nd);
 				inode = nd->dentry->d_inode;
 				/* fallthrough */
 			case 1:
-				goto return_base;
+				goto return_reval;
 		}
 		if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
 			err = nd->dentry->d_op->d_hash(nd->dentry, &this);
 			if (err < 0)
 				break;
 		}
-		err = do_lookup(nd, &this, &next, &pinned, 0);
-		if (err)
-			break;
-		follow_mount(&next.mnt, &next.dentry);
-		inode = next.dentry->d_inode;
+		dentry = cached_lookup(nd->dentry, &this, 0);
+		if (!dentry) {
+			dentry = real_lookup(nd->dentry, &this, 0);
+			err = PTR_ERR(dentry);
+			if (IS_ERR(dentry))
+				break;
+		}
+		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
+			;
+		inode = dentry->d_inode;
 		if ((lookup_flags & LOOKUP_FOLLOW)
 		    && inode && inode->i_op && inode->i_op->follow_link) {
-			mntget(next.mnt);
-			dget_locked(next.dentry);
-			unlock_nd(nd);
-			err = do_follow_link(next.dentry, nd);
-			dput(next.dentry);
-			mntput(next.mnt);
+			err = do_follow_link(dentry, nd);
+			dput(dentry);
 			if (err)
 				goto return_err;
 			inode = nd->dentry->d_inode;
-			lock_nd(nd);
 		} else {
-			nd->mnt = next.mnt;
-			nd->dentry = next.dentry;
+			dput(nd->dentry);
+			nd->dentry = dentry;
 		}
 		err = -ENOENT;
 		if (!inode)
-			break;
+			goto no_inode;
 		if (lookup_flags & LOOKUP_DIRECTORY) {
 			err = -ENOTDIR; 
 			if (!inode->i_op || !inode->i_op->lookup)
 				break;
 		}
 		goto return_base;
+no_inode:
+		err = -ENOENT;
+		if (lookup_flags & (LOOKUP_POSITIVE|LOOKUP_DIRECTORY))
+			break;
+		goto return_base;
 lookup_parent:
 		nd->last = this;
 		nd->last_type = LAST_NORM;
@@ -732,24 +627,33 @@
 			nd->last_type = LAST_DOT;
 		else if (this.len == 2 && this.name[1] == '.')
 			nd->last_type = LAST_DOTDOT;
+return_reval:
+		/*
+		 * We bypassed the ordinary revalidation routines.
+		 * Check the cached dentry for staleness.
+		 */
+		dentry = nd->dentry;
+		if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
+			err = -ESTALE;
+			if (!dentry->d_op->d_revalidate(dentry, 0)) {
+				d_invalidate(dentry);
+				break;
+			}
+		}
 return_base:
-		unlock_nd(nd);
-		dput(pinned.dentry);
-		mntput(pinned.mnt);
 		return 0;
+out_dput:
+		dput(dentry);
+		break;
 	}
-	unlock_nd(nd);
 	path_release(nd);
 return_err:
-	dput(pinned.dentry);
-	mntput(pinned.mnt);
 	return err;
 }
 
 int path_walk(const char * name, struct nameidata *nd)
 {
 	current->total_link_count = 0;
-	lock_nd(nd);
 	return link_path_walk(name, nd);
 }
 
@@ -834,35 +738,28 @@
 	return 1;
 }
 
+/* SMP-safe */
+int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
+{
+	int error = 0;
+	if (path_init(path, flags, nd))
+		error = path_walk(path, nd);
+	return error;
+}
+
 
-int path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
+/* SMP-safe */
+int path_init(const char *name, unsigned int flags, struct nameidata *nd)
 {
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
-	if (*name=='/') {
-		read_lock(&current->fs->lock);
-		if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
-			nd->mnt = mntget(current->fs->altrootmnt);
-			nd->dentry = dget(current->fs->altroot);
-			read_unlock(&current->fs->lock);
-			if (__emul_lookup_dentry(name,nd))
-				return 0;
-			read_lock(&current->fs->lock);
-		}
-		read_unlock(&current->fs->lock);
-		spin_lock(&dcache_lock);
-		nd->mnt = current->fs->rootmnt;
-		nd->dentry = current->fs->root;
-	}
-	else{
-		spin_lock(&dcache_lock);
-		nd->mnt = current->fs->pwdmnt;
-		nd->dentry = current->fs->pwd;
-	}
-	nd->old_mnt = NULL;
-	nd->old_dentry = NULL;
-	current->total_link_count = 0;
-	return link_path_walk(name, nd);
+	if (*name=='/')
+		return walk_init_root(name,nd);
+	read_lock(&current->fs->lock);
+	nd->mnt = mntget(current->fs->pwdmnt);
+	nd->dentry = dget(current->fs->pwd);
+	read_unlock(&current->fs->lock);
+	return 1;
 }
 
 /*
@@ -2067,7 +1964,6 @@
 			/* weird __emul_prefix() stuff did it */
 			goto out;
 	}
-	lock_nd(nd);
 	res = link_path_walk(link, nd);
 out:
 	if (current->link_count || res || nd->last_type!=LAST_NORM)
diff -urN linux-2.4.21-bk4/fs/namespace.c linux-2.4.21-bk5/fs/namespace.c
--- linux-2.4.21-bk4/fs/namespace.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/namespace.c	2003-06-13 07:51:37.000000000 -0700
@@ -23,7 +23,6 @@
 
 struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
 int do_remount_sb(struct super_block *sb, int flags, void * data);
-int __init init_rootfs(void);
 void kill_super(struct super_block *sb);
 extern int __init init_rootfs(void);
 
diff -urN linux-2.4.21-bk4/fs/nfs/direct.c linux-2.4.21-bk5/fs/nfs/direct.c
--- linux-2.4.21-bk4/fs/nfs/direct.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk5/fs/nfs/direct.c	2003-07-09 02:54:00.000000000 -0700
@@ -0,0 +1,382 @@
+/*
+ * linux/fs/nfs/direct.c
+ *
+ * High-performance direct I/O for the NFS client
+ *
+ * When an application requests uncached I/O, all read and write requests
+ * are made directly to the server; data stored or fetched via these
+ * requests is not cached in the Linux page cache.  The client does not
+ * correct unaligned requests from applications.  All requested bytes are
+ * held on permanent storage before a direct write system call returns to
+ * an application.  Applications that manage their own data caching, such
+ * as databases, make very good use of direct I/O on local file systems.
+ *
+ * Solaris implements an uncached I/O facility called directio() that
+ * is used for backups and sequential I/O to very large files.  Solaris
+ * also supports uncaching whole NFS partitions with "-o forcedirectio,"
+ * an undocumented mount option.
+ *
+ * Note that I/O to read in executables (e.g. kernel_read) cannot use
+ * direct (kiobuf) reads because there is no vma backing the passed-in
+ * data buffer.
+ *
+ * Designed by Jeff Kimmel, Chuck Lever, and Trond Myklebust.
+ *
+ * Initial implementation:	12/2001 by Chuck Lever <cel@netapp.com>
+ *
+ * TODO:
+ *
+ * 1.  Use concurrent asynchronous network requests rather than
+ *     serialized synchronous network requests for normal (non-sync)
+ *     direct I/O.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/errno.h>
+#include <linux/nfs_fs.h>
+#include <linux/smp_lock.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/iobuf.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define NFSDBG_FACILITY		(NFSDBG_PAGECACHE | NFSDBG_VFS)
+#define VERF_SIZE		(2 * sizeof(__u32))
+
+static inline int
+nfs_direct_read_rpc(struct file *file, struct nfs_readargs *arg)
+{
+	int result;
+	struct inode * inode = file->f_dentry->d_inode;
+	struct nfs_fattr fattr;
+        struct rpc_message msg;
+        struct nfs_readres res = { &fattr, arg->count, 0 };
+
+#ifdef CONFIG_NFS_V3
+	msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ?
+						NFS3PROC_READ : NFSPROC_READ;
+#else
+	msg.rpc_proc = NFSPROC_READ;
+#endif
+	msg.rpc_argp = arg;
+        msg.rpc_resp = &res;
+
+	lock_kernel();
+        msg.rpc_cred = nfs_file_cred(file);
+        fattr.valid = 0;
+        result = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	nfs_refresh_inode(inode, &fattr);
+	unlock_kernel();
+
+	return result;
+}
+
+static inline int
+nfs_direct_write_rpc(struct file *file, struct nfs_writeargs *arg,
+	struct nfs_writeverf *verf)
+{
+	int result;
+	struct inode *inode = file->f_dentry->d_inode;
+	struct nfs_fattr fattr;
+        struct rpc_message msg;
+        struct nfs_writeres res = { &fattr, verf, 0 };
+
+#ifdef CONFIG_NFS_V3
+	msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ?
+						NFS3PROC_WRITE : NFSPROC_WRITE;
+#else
+	msg.rpc_proc = NFSPROC_WRITE;
+#endif
+	msg.rpc_argp = arg;
+        msg.rpc_resp = &res;
+
+	lock_kernel();
+	msg.rpc_cred = get_rpccred(nfs_file_cred(file));
+	fattr.valid = 0;
+        result = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	nfs_write_attributes(inode, &fattr);
+	put_rpccred(msg.rpc_cred);
+	unlock_kernel();
+
+#ifdef CONFIG_NFS_V3
+	if (NFS_PROTO(inode)->version == 3) {
+		if (result > 0) {
+			if ((arg->stable == NFS_FILE_SYNC) &&
+			    (verf->committed != NFS_FILE_SYNC)) {
+				printk(KERN_ERR
+				"%s: server didn't sync stable write request\n",
+				__FUNCTION__);
+				return -EIO;
+			}
+
+			if (result != arg->count) {
+				printk(KERN_INFO
+					"%s: short write, count=%u, result=%d\n",
+					__FUNCTION__, arg->count, result);
+			}
+		}
+		return result;
+	} else {
+#endif
+        	verf->committed = NFS_FILE_SYNC; /* NFSv2 always syncs data */
+		if (result == 0)
+			return arg->count;
+		return result;
+#ifdef CONFIG_NFS_V3
+	}
+#endif
+}
+
+#ifdef CONFIG_NFS_V3
+static inline int
+nfs_direct_commit_rpc(struct inode *inode, loff_t offset, size_t count,
+	struct nfs_writeverf *verf)
+{
+	int result;
+	struct nfs_fattr fattr;
+	struct nfs_writeargs	arg = { NFS_FH(inode), offset, count, 0, 0,
+					NULL };
+	struct nfs_writeres	res = { &fattr, verf, 0 };
+	struct rpc_message	msg = { NFS3PROC_COMMIT, &arg, &res, NULL };
+
+	fattr.valid = 0;
+
+	lock_kernel();
+	result = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	nfs_write_attributes(inode, &fattr);
+	unlock_kernel();
+
+	return result;
+}
+#else
+static inline int
+nfs_direct_commit_rpc(struct inode *inode, loff_t offset, size_t count,
+	struct nfs_writeverf *verf)
+{
+	return 0;
+}
+#endif
+
+/*
+ * Walk through the iobuf and create an iovec for each "rsize" bytes.
+ */
+static int
+nfs_direct_read(struct file *file, struct kiobuf *iobuf, loff_t offset,
+	size_t count)
+{
+	int curpage, total;
+	int result = 0;
+	struct inode *inode = file->f_dentry->d_inode;
+	int rsize = NFS_SERVER(inode)->rsize;
+	struct page *pages[NFS_READ_MAXIOV];
+	struct nfs_readargs args = { NFS_FH(inode), offset, 0, iobuf->offset,
+				     pages };
+
+	total = 0;
+	curpage = 0;
+        while (count) {
+		int len, request;
+		struct page **dest = pages;
+
+                request = count;
+                if (count > rsize)
+                        request = rsize;
+		args.count = request;
+		args.offset = offset;
+		args.pgbase = (iobuf->offset + total) & ~PAGE_MASK;
+		len = PAGE_SIZE - args.pgbase;
+
+		do {
+			struct page *page = iobuf->maplist[curpage];
+
+			if (curpage >= iobuf->nr_pages || !page) {
+				result = -EFAULT;
+				goto out_err;
+			}
+
+			*dest++ = page;
+			/* zero after the first iov */
+			if (request < len)
+				break;
+			request -= len;
+			len = PAGE_SIZE;
+			curpage++;
+		} while (request != 0);
+
+                result = nfs_direct_read_rpc(file, &args);
+
+                if (result < 0)
+                        break;
+
+                total += result;
+                if (result < args.count)   /* NFSv2ism */
+                        break;
+                count -= result;
+                offset += result;
+        };
+out_err:
+	if (!total)
+		return result;
+	return total;
+}
+
+/*
+ * Walk through the iobuf and create an iovec for each "wsize" bytes.
+ * If only one network write is necessary, or if the O_SYNC flag or
+ * 'sync' mount option are present, or if this is a V2 inode, use
+ * FILE_SYNC.  Otherwise, use UNSTABLE and finish with a COMMIT.
+ *
+ * The mechanics of this function are much the same as nfs_direct_read,
+ * with the added complexity of committing unstable writes.
+ */
+static int
+nfs_direct_write(struct file *file, struct kiobuf *iobuf,
+	loff_t offset, size_t count)
+{
+	int curpage, total;
+	int need_commit = 0;
+	int result = 0;
+	loff_t save_offset = offset;
+	struct inode *inode = file->f_dentry->d_inode;
+	int wsize = NFS_SERVER(inode)->wsize;
+	struct nfs_writeverf first_verf, ret_verf;
+	struct page *pages[NFS_WRITE_MAXIOV];
+        struct nfs_writeargs args = { NFS_FH(inode), 0, 0, NFS_FILE_SYNC, 0,
+				pages };
+
+#ifdef CONFIG_NFS_V3
+	if ((NFS_PROTO(inode)->version == 3) && (count > wsize) &&
+							(!IS_SYNC(inode)))
+		args.stable = NFS_UNSTABLE;
+#endif
+
+retry:
+	total = 0;
+	curpage = 0;
+        while (count) {
+		int len, request;
+		struct page **dest = pages;
+
+                request = count;
+                if (count > wsize)
+                        request = wsize;
+		args.count = request;
+		args.offset = offset;
+		args.pgbase = (iobuf->offset + total) & ~PAGE_MASK;
+		len = PAGE_SIZE - args.pgbase;
+
+		do {
+			struct page *page = iobuf->maplist[curpage];
+
+			if (curpage >= iobuf->nr_pages || !page) {
+				result = -EFAULT;
+				goto out_err;
+			}
+
+			*dest++ = page;
+			/* zero after the first iov */
+			if (request < len)
+				break;
+			request -= len;
+			len = PAGE_SIZE;
+			curpage++;
+		} while (request != 0);
+
+                result = nfs_direct_write_rpc(file, &args, &ret_verf);
+
+                if (result < 0)
+                        break;
+
+		if (!total)
+			memcpy(&first_verf.verifier, &ret_verf.verifier,
+								VERF_SIZE);
+		if (ret_verf.committed != NFS_FILE_SYNC) {
+			need_commit = 1;
+			if (memcmp(&first_verf.verifier, &ret_verf.verifier,
+								VERF_SIZE))
+				goto print_retry;
+		}
+
+                total += result;
+                count -= result;
+                offset += result;
+        };
+
+out_err:
+	/*
+	 * Commit data written so far, even in the event of an error
+	 */
+	if (need_commit) {
+		if (nfs_direct_commit_rpc(inode, save_offset,
+					iobuf->length - count, &ret_verf))
+			goto print_retry;
+		if (memcmp(&first_verf.verifier, &ret_verf.verifier,
+								VERF_SIZE))
+			goto print_retry;
+	}
+
+	if (!total)
+		return result;
+	return total;
+
+print_retry:
+	printk(KERN_INFO "%s: detected server restart; retrying with FILE_SYNC\n",
+			__FUNCTION__);
+	args.stable = NFS_FILE_SYNC;
+	offset = save_offset;
+	count = iobuf->length;
+	goto retry;
+}
+
+/*
+ * Read or write data, moving the data directly to/from the
+ * application's buffer without caching in the page cache.
+ *
+ * Rules for direct I/O
+ *
+ * 1.  block size = 512 bytes or more
+ * 2.  file byte offset is block aligned
+ * 3.  byte count is a multiple of block size
+ * 4.  user buffer is not aligned
+ * 5.  user buffer is faulted in and pinned
+ *
+ * These are verified before we get here.
+ */
+int
+nfs_direct_IO(int rw, struct file *file, struct kiobuf *iobuf,
+	unsigned long blocknr, int blocksize)
+{
+	int result = -EINVAL;
+	size_t count = iobuf->length;
+	struct dentry *dentry = file->f_dentry;
+	struct inode *inode = dentry->d_inode;
+	loff_t offset = blocknr << inode->i_blkbits;
+
+	switch (rw) {
+	case READ:
+		dfprintk(VFS,
+			"NFS: direct_IO(READ) (%s/%s) off/cnt(%Lu/%d)\n",
+				dentry->d_parent->d_name.name,
+					dentry->d_name.name, offset, count);
+
+		result = nfs_direct_read(file, iobuf, offset, count);
+		break;
+	case WRITE:
+		dfprintk(VFS,
+			"NFS: direct_IO(WRITE) (%s/%s) off/cnt(%Lu/%d)\n",
+				dentry->d_parent->d_name.name,
+					dentry->d_name.name, offset, count);
+
+		result = nfs_direct_write(file, iobuf, offset, count);
+		break;
+	default:
+		break;
+	}
+
+	dfprintk(VFS, "NFS: direct_IO result = %d\n", result);
+	return result;
+}
diff -urN linux-2.4.21-bk4/fs/nfsd/export.c linux-2.4.21-bk5/fs/nfsd/export.c
--- linux-2.4.21-bk4/fs/nfsd/export.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/nfsd/export.c	2002-11-28 15:53:15.000000000 -0800
@@ -214,7 +214,8 @@
 
 	/* Look up the dentry */
 	err = 0;
-	err = path_lookup(nxp->ex_path, LOOKUP_POSITIVE, &nd);
+	if (path_init(nxp->ex_path, LOOKUP_POSITIVE, &nd))
+		err = path_walk(nxp->ex_path, &nd);
 	if (err)
 		goto out_unlock;
 
@@ -410,7 +411,8 @@
 
 	err = -EPERM;
 	if (path) {
-		if (path_lookup(path, LOOKUP_POSITIVE, &nd))  {
+		if (path_init(path, LOOKUP_POSITIVE, &nd) &&
+		    path_walk(path, &nd)) {
 			printk("nfsd: exp_rootfh path not found %s", path);
 			return err;
 		}
diff -urN linux-2.4.21-bk4/fs/quota.c linux-2.4.21-bk5/fs/quota.c
--- linux-2.4.21-bk4/fs/quota.c	2003-07-09 02:53:55.000000000 -0700
+++ linux-2.4.21-bk5/fs/quota.c	2003-07-09 02:54:00.000000000 -0700
@@ -11,16 +11,20 @@
 #include <asm/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
+#include <linux/quotaops.h>
 #include <linux/quotacompat.h>
 
+struct dqstats dqstats;
 
 /* Check validity of quotactl */
 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
 {
 	if (type >= MAXQUOTAS)
 		return -EINVAL;
+	if (!sb && cmd != Q_SYNC)
+		return -ENODEV;
 	/* Is operation supported? */
-	if (!sb->s_qcop)
+	if (sb && !sb->s_qcop)
 		return -ENOSYS;
 
 	switch (cmd) {
@@ -51,7 +55,7 @@
 				return -ENOSYS;
 			break;
 		case Q_SYNC:
-			if (!sb->s_qcop->quota_sync)
+			if (sb && !sb->s_qcop->quota_sync)
 				return -ENOSYS;
 			break;
 		case Q_XQUOTAON:
@@ -188,8 +192,10 @@
 			return sb->s_qcop->set_dqblk(sb, type, id, &idq);
 		}
 		case Q_SYNC:
-			return sb->s_qcop->quota_sync(sb, type);
-
+			if (sb)
+				return sb->s_qcop->quota_sync(sb, type);
+			sync_dquots_dev(NODEV, type);
+			return 0;
 		case Q_XQUOTAON:
 		case Q_XQUOTAOFF:
 		case Q_XQUOTARM: {
@@ -250,7 +256,7 @@
 				return -ENOSYS;
 			break;
 		case Q_COMP_SYNC:
-			if (!sb->s_qcop->quota_sync)
+			if (sb && !sb->s_qcop->quota_sync)
 				return -ENOSYS;
 			break;
 		case Q_V1_SETQLIM:
@@ -399,7 +405,10 @@
 		case Q_COMP_QUOTAOFF:
 			return sb->s_qcop->quota_off(sb, type);
 		case Q_COMP_SYNC:
-			return sb->s_qcop->quota_sync(sb, type);
+			if (sb)
+				return sb->s_qcop->quota_sync(sb, type);
+			sync_dquots_dev(NODEV, type);
+			return 0;
 		case Q_V1_RSQUASH: {
 			int flag;
 
diff -urN linux-2.4.21-bk4/include/asm-sh64/hdreg.h linux-2.4.21-bk5/include/asm-sh64/hdreg.h
--- linux-2.4.21-bk4/include/asm-sh64/hdreg.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk5/include/asm-sh64/hdreg.h	2003-07-09 02:54:00.000000000 -0700
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-sh64/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASM_SH64_HDREG_H
+#define __ASM_SH64_HDREG_H
+
+//typedef unsigned short ide_ioreg_t;
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __ASM_SH64_HDREG_H */
diff -urN linux-2.4.21-bk4/include/asm-sh64/ide.h linux-2.4.21-bk5/include/asm-sh64/ide.h
--- linux-2.4.21-bk4/include/asm-sh64/ide.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk5/include/asm-sh64/ide.h	2003-07-09 02:54:00.000000000 -0700
@@ -0,0 +1,65 @@
+/*
+ *  linux/include/asm-sh64/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the sh64 architecture specific IDE code.
+ */
+
+#ifndef __ASM_SH64_IDE_H
+#define __ASM_SH64_IDE_H
+
+#ifdef __KERNEL__
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS	4
+#endif
+
+#if 0
+#include <asm/arch/ide.h>
+#endif
+
+#define ide_default_io_base(i)		((ide_ioreg_t)0)
+#define ide_default_irq(b)		(0)
+
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+{
+	ide_ioreg_t reg = data_port;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
+	if (irq != NULL)
+		*irq = 0;
+	hw->io_ports[IDE_IRQ_OFFSET] = 0;
+}
+
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifndef CONFIG_BLK_DEV_IDEPCI
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+}
+
+#include <asm-generic/ide_iops.h>
+
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH64_IDE_H */
diff -urN linux-2.4.21-bk4/include/asm-sh64/ioctls.h linux-2.4.21-bk5/include/asm-sh64/ioctls.h
--- linux-2.4.21-bk4/include/asm-sh64/ioctls.h	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/include/asm-sh64/ioctls.h	2003-07-09 02:54:00.000000000 -0700
@@ -20,6 +20,7 @@
 #define FIONBIO		_IOW('f', 126, int)
 #define FIONREAD	_IOR('f', 127, int)
 #define TIOCINQ		FIONREAD
+#define FIOQSIZE	_IOR('f', 128, loff_t)
 
 #define TCGETS		0x5401
 #define TCSETS		0x5402
diff -urN linux-2.4.21-bk4/include/asm-sh64/mc146818rtc.h linux-2.4.21-bk5/include/asm-sh64/mc146818rtc.h
--- linux-2.4.21-bk4/include/asm-sh64/mc146818rtc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk5/include/asm-sh64/mc146818rtc.h	2003-07-09 02:54:00.000000000 -0700
@@ -0,0 +1,7 @@
+/*
+ * linux/include/asm-sh64/mc146818rtc.h
+ *
+*/
+
+/* For now, an empty place-holder to get IDE to compile. */
+
diff -urN linux-2.4.21-bk4/include/linux/dcache.h linux-2.4.21-bk5/include/linux/dcache.h
--- linux-2.4.21-bk4/include/linux/dcache.h	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/include/linux/dcache.h	2002-11-28 15:53:15.000000000 -0800
@@ -219,7 +219,6 @@
 
 /* appendix may either be NULL or be used for transname suffixes */
 extern struct dentry * d_lookup(struct dentry *, struct qstr *);
-extern struct dentry * __d_lookup(struct dentry *, struct qstr *);
 
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
diff -urN linux-2.4.21-bk4/include/linux/fs.h linux-2.4.21-bk5/include/linux/fs.h
--- linux-2.4.21-bk4/include/linux/fs.h	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/include/linux/fs.h	2003-07-09 02:54:01.000000000 -0700
@@ -693,8 +693,6 @@
 	struct qstr last;
 	unsigned int flags;
 	int last_type;
-	struct dentry *old_dentry;
-	struct vfsmount *old_mnt;
 };
 
 /*
@@ -1341,7 +1339,6 @@
  *  - require a directory
  *  - ending slashes ok even for nonexistent files
  *  - internal "there are more path compnents" flag
- *  - locked when lookup done with dcache_lock held
  */
 #define LOOKUP_FOLLOW		(1)
 #define LOOKUP_DIRECTORY	(2)
@@ -1349,7 +1346,6 @@
 #define LOOKUP_POSITIVE		(8)
 #define LOOKUP_PARENT		(16)
 #define LOOKUP_NOALT		(32)
-
 /*
  * Type of the last component on LOOKUP_PARENT
  */
@@ -1377,6 +1373,7 @@
 extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
 
 extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
+extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
 extern int FASTCALL(path_walk(const char *, struct nameidata *));
 extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
 extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
diff -urN linux-2.4.21-bk4/include/linux/fs_struct.h linux-2.4.21-bk5/include/linux/fs_struct.h
--- linux-2.4.21-bk4/include/linux/fs_struct.h	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/include/linux/fs_struct.h	2001-07-13 15:10:44.000000000 -0700
@@ -32,12 +32,10 @@
 	struct dentry *old_root;
 	struct vfsmount *old_rootmnt;
 	write_lock(&fs->lock);
-	spin_lock(&dcache_lock);
 	old_root = fs->root;
 	old_rootmnt = fs->rootmnt;
 	fs->rootmnt = mntget(mnt);
 	fs->root = dget(dentry);
-	spin_unlock(&dcache_lock);
 	write_unlock(&fs->lock);
 	if (old_root) {
 		dput(old_root);
@@ -57,12 +55,10 @@
 	struct dentry *old_pwd;
 	struct vfsmount *old_pwdmnt;
 	write_lock(&fs->lock);
-	spin_lock(&dcache_lock);
 	old_pwd = fs->pwd;
 	old_pwdmnt = fs->pwdmnt;
 	fs->pwdmnt = mntget(mnt);
 	fs->pwd = dget(dentry);
-	spin_unlock(&dcache_lock);
 	write_unlock(&fs->lock);
 	if (old_pwd) {
 		dput(old_pwd);
diff -urN linux-2.4.21-bk4/include/linux/quotaops.h linux-2.4.21-bk5/include/linux/quotaops.h
--- linux-2.4.21-bk4/include/linux/quotaops.h	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/include/linux/quotaops.h	2003-07-09 02:54:02.000000000 -0700
@@ -185,6 +185,7 @@
  */
 #define sb_dquot_ops				(NULL)
 #define sb_quotactl_ops				(NULL)
+#define sync_dquots_dev(dev, type)		do { } while(0)
 #define DQUOT_INIT(inode)			do { } while(0)
 #define DQUOT_DROP(inode)			do { } while(0)
 #define DQUOT_ALLOC_INODE(inode)		(0)
diff -urN linux-2.4.21-bk4/kernel/ksyms.c linux-2.4.21-bk5/kernel/ksyms.c
--- linux-2.4.21-bk4/kernel/ksyms.c	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/kernel/ksyms.c	2003-07-09 02:54:02.000000000 -0700
@@ -149,8 +149,8 @@
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(follow_down);
 EXPORT_SYMBOL(lookup_mnt);
+EXPORT_SYMBOL(path_init);
 EXPORT_SYMBOL(path_walk);
-EXPORT_SYMBOL(path_lookup);
 EXPORT_SYMBOL(path_release);
 EXPORT_SYMBOL(__user_walk);
 EXPORT_SYMBOL(lookup_one_len);
diff -urN linux-2.4.21-bk4/net/sunrpc/clnt.c linux-2.4.21-bk5/net/sunrpc/clnt.c
--- linux-2.4.21-bk4/net/sunrpc/clnt.c	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/net/sunrpc/clnt.c	2003-07-09 02:54:03.000000000 -0700
@@ -709,14 +709,14 @@
 
 	dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
 	if (clnt->cl_softrtry) {
-		if (clnt->cl_chatty && !task->tk_exit)
+		if (clnt->cl_chatty)
 			printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
 				clnt->cl_protname, clnt->cl_server);
 		rpc_exit(task, -EIO);
 		return;
 	}
 
-	if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN) && rpc_ntimeo(&clnt->cl_rtt) > 7) {
+	if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) {
 		task->tk_flags |= RPC_CALL_MAJORSEEN;
 		printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
 			clnt->cl_protname, clnt->cl_server);
diff -urN linux-2.4.21-bk4/net/sunrpc/xprt.c linux-2.4.21-bk5/net/sunrpc/xprt.c
--- linux-2.4.21-bk4/net/sunrpc/xprt.c	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/net/sunrpc/xprt.c	2003-07-09 02:54:03.000000000 -0700
@@ -1046,21 +1046,6 @@
 }
 
 /*
- * Exponential backoff for UDP retries
- */
-static inline int
-xprt_expbackoff(struct rpc_task *task, struct rpc_rqst *req)
-{
-	int backoff;
-
-	req->rq_ntimeo++;
-	backoff = min(rpc_ntimeo(&task->tk_client->cl_rtt), XPRT_MAX_BACKOFF);
-	if (req->rq_ntimeo < (1 << backoff))
-		return 1;
-	return 0;
-}
-
-/*
  * RPC receive timeout handler.
  */
 static void
@@ -1073,14 +1058,7 @@
 	if (req->rq_received)
 		goto out;
 
-	if (!xprt->nocong) {
-		if (xprt_expbackoff(task, req)) {
-			rpc_add_timer(task, xprt_timer);
-			goto out_unlock;
-		}
-		rpc_inc_timeo(&task->tk_client->cl_rtt);
-		xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
-	}
+	xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
 	req->rq_nresend++;
 
 	dprintk("RPC: %4d xprt_timer (%s request)\n",
@@ -1090,7 +1068,6 @@
 out:
 	task->tk_timeout = 0;
 	rpc_wake_up_task(task);
-out_unlock:
 	spin_unlock(&xprt->sock_lock);
 }
 
@@ -1228,16 +1205,17 @@
 	return;
  out_receive:
 	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
+	spin_lock_bh(&xprt->sock_lock);
 	/* Set the task's receive timeout value */
 	if (!xprt->nocong) {
 		task->tk_timeout = rpc_calc_rto(&clnt->cl_rtt,
 				rpcproc_timer(clnt, task->tk_msg.rpc_proc));
-		req->rq_ntimeo = 0;
+		task->tk_timeout <<= clnt->cl_timeout.to_retries
+			- req->rq_timeout.to_retries;
 		if (task->tk_timeout > req->rq_timeout.to_maxval)
 			task->tk_timeout = req->rq_timeout.to_maxval;
 	} else
 		task->tk_timeout = req->rq_timeout.to_current;
-	spin_lock_bh(&xprt->sock_lock);
 	/* Don't race with disconnect */
 	if (!xprt_connected(xprt))
 		task->tk_status = -ENOTCONN;
diff -urN linux-2.4.21-bk4/net/unix/af_unix.c linux-2.4.21-bk5/net/unix/af_unix.c
--- linux-2.4.21-bk4/net/unix/af_unix.c	2003-07-09 02:53:56.000000000 -0700
+++ linux-2.4.21-bk5/net/unix/af_unix.c	2002-11-28 15:53:16.000000000 -0800
@@ -590,8 +590,9 @@
 	int err = 0;
 	
 	if (sunname->sun_path[0]) {
-		err = path_lookup(sunname->sun_path, 
-			      LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd);
+		if (path_init(sunname->sun_path, 
+			      LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd))
+			err = path_walk(sunname->sun_path, &nd);
 		if (err)
 			goto fail;
 		err = permission(nd.dentry->d_inode,MAY_WRITE);
@@ -684,7 +685,8 @@
 		 * Get the parent directory, calculate the hash for last
 		 * component.
 		 */
-		err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
+		if (path_init(sunaddr->sun_path, LOOKUP_PARENT, &nd))
+			err = path_walk(sunaddr->sun_path, &nd);
 		if (err)
 			goto out_mknod_parent;
 		/*
