Whamcloud - gitweb
* merged current b_devel
authoreeb <eeb>
Thu, 17 Jul 2003 13:03:16 +0000 (13:03 +0000)
committereeb <eeb>
Thu, 17 Jul 2003 13:03:16 +0000 (13:03 +0000)
lustre/kernel_patches/patches/ext3-map_inode_page.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3_map_inode_page_chaos.patch [new file with mode: 0644]
lustre/kernel_patches/patches/linux-2.4.18-14-kgdb-1.6.patch [new file with mode: 0644]
lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch [new file with mode: 0644]
lustre/kernel_patches/pc/ext3-map_inode_page.pc [new file with mode: 0644]
lustre/kernel_patches/pc/ext3_map_inode_page_chaos.pc [new file with mode: 0644]
lustre/kernel_patches/pc/linux-2.4.18-14-kgdb-1.6.pc [new file with mode: 0644]
lustre/kernel_patches/pc/vfs_intent-2.4.20-hp.pc [new file with mode: 0644]
lustre/kernel_patches/series/chaos-kgdb [new file with mode: 0644]
lustre/kernel_patches/txt/ext3-map_inode_page.txt [new file with mode: 0644]
lustre/kernel_patches/txt/ext3_map_inode_page_chaos.txt [new file with mode: 0644]

diff --git a/lustre/kernel_patches/patches/ext3-map_inode_page.patch b/lustre/kernel_patches/patches/ext3-map_inode_page.patch
new file mode 100644 (file)
index 0000000..c9b7c15
--- /dev/null
@@ -0,0 +1,86 @@
+
+
+
+ fs/ext3/ext3-exports.c |    3 ++
+ fs/ext3/inode.c        |   55 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 58 insertions(+)
+
+--- linux-2.4.20-l18/fs/ext3/inode.c~ext3-map_inode_page       Tue Jul  8 20:07:23 2003
++++ linux-2.4.20-l18-phil/fs/ext3/inode.c      Wed Jul  9 03:56:41 2003
+@@ -2867,3 +2867,58 @@ int ext3_prep_san_write(struct inode *in
+               ret = ret2;
+       return ret;
+ }
++
++int ext3_map_inode_page(struct inode *inode, struct page *page,
++                        unsigned long *blocks, int *created, int create)
++{
++        unsigned int blocksize, blocks_per_page;
++        unsigned long iblock;
++        struct buffer_head dummy;
++        void *handle;
++        int i, rc = 0, failed = 0, needed_blocks;
++
++        blocksize = inode->i_sb->s_blocksize;
++        blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
++        iblock = page->index >> (PAGE_SHIFT - inode->i_sb->s_blocksize_bits);
++
++        for (i = 0; i < blocks_per_page; i++, iblock++) {
++                blocks[i] = ext3_bmap(inode->i_mapping, iblock);
++                if (blocks[i] == 0) {
++                        failed++;
++                        created[i] = -1;
++                } else {
++                        created[i] = 0;
++                }
++        }
++
++        if (failed == 0 || create == 0)
++                return 0;
++
++        needed_blocks = ext3_writepage_trans_blocks(inode) * failed;
++        lock_kernel();
++        handle = ext3_journal_start(inode, needed_blocks);
++        unlock_kernel();
++        if (IS_ERR(handle))
++                return PTR_ERR(handle);
++
++        iblock = page->index >> (PAGE_SHIFT - inode->i_sb->s_blocksize_bits);
++        for (i = 0; i < blocks_per_page; i++, iblock++) {
++                if (blocks[i] != 0)
++                        continue;
++
++                rc = ext3_get_block_handle(handle, inode, iblock, &dummy, 1);
++                if (rc) {
++                        printk(KERN_INFO "ext3_map_inode_page: error reading "
++                               "block %ld\n", iblock);
++                        goto out;
++                }
++                blocks[i] = dummy.b_blocknr;
++                created[i] = 1;
++        }
++
++ out:
++      lock_kernel();
++      ext3_journal_stop(handle, inode);
++      unlock_kernel();
++        return rc;
++}
+--- linux-2.4.20-l18/fs/ext3/ext3-exports.c~ext3-map_inode_page        Tue Jul  8 20:07:10 2003
++++ linux-2.4.20-l18-phil/fs/ext3/ext3-exports.c       Tue Jul  8 20:09:02 2003
+@@ -9,6 +9,8 @@
+ int ext3_prep_san_write(struct inode *inode, long *blocks,
+                       int nblocks, loff_t newsize);
++int ext3_map_inode_page(struct inode *inode, struct page *page,
++                        unsigned long *block, int *created, int create);
+ EXPORT_SYMBOL(ext3_force_commit);
+ EXPORT_SYMBOL(ext3_bread);
+@@ -18,3 +20,4 @@ EXPORT_SYMBOL(ext3_xattr_get);
+ EXPORT_SYMBOL(ext3_xattr_list);
+ EXPORT_SYMBOL(ext3_xattr_set);
+ EXPORT_SYMBOL(ext3_prep_san_write);
++EXPORT_SYMBOL(ext3_map_inode_page);
+
+_
diff --git a/lustre/kernel_patches/patches/ext3_map_inode_page_chaos.patch b/lustre/kernel_patches/patches/ext3_map_inode_page_chaos.patch
new file mode 100644 (file)
index 0000000..1b9296b
--- /dev/null
@@ -0,0 +1,85 @@
+
+
+
+ fs/ext3/ext3-exports.c |   12 ++++++++++
+ fs/ext3/inode.c        |   55 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 67 insertions(+)
+
+--- linux-2.4.18-p4smp/fs/ext3/inode.c~ext3_map_inode_page_chaos       2003-07-09 13:32:38.000000000 -0600
++++ linux-2.4.18-p4smp-braam/fs/ext3/inode.c   2003-07-09 17:11:19.000000000 -0600
+@@ -2892,3 +2892,58 @@ int ext3_prep_san_write(struct inode *in
+               ret = ret2;
+       return ret;
+ }
++
++int ext3_map_inode_page(struct inode *inode, struct page *page,
++                        unsigned long *blocks, int *created, int create)
++{
++        unsigned int blocksize, blocks_per_page;
++        unsigned long iblock;
++        struct buffer_head dummy;
++        void *handle;
++        int i, rc = 0, failed = 0, needed_blocks;
++
++        blocksize = inode->i_sb->s_blocksize;
++        blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
++        iblock = page->index >> (PAGE_SHIFT - inode->i_sb->s_blocksize_bits);
++
++        for (i = 0; i < blocks_per_page; i++, iblock++) {
++                blocks[i] = ext3_bmap(inode->i_mapping, iblock);
++                if (blocks[i] == 0) {
++                        failed++;
++                        created[i] = -1;
++                } else {
++                        created[i] = 0;
++                }
++        }
++
++        if (failed == 0 || create == 0)
++                return 0;
++
++        needed_blocks = ext3_writepage_trans_blocks(inode) * failed;
++        lock_kernel();
++        handle = ext3_journal_start(inode, needed_blocks);
++        unlock_kernel();
++        if (IS_ERR(handle))
++                return PTR_ERR(handle);
++
++        iblock = page->index >> (PAGE_SHIFT - inode->i_sb->s_blocksize_bits);
++        for (i = 0; i < blocks_per_page; i++, iblock++) {
++                if (blocks[i] != 0)
++                        continue;
++
++                rc = ext3_get_block_handle(handle, inode, iblock, &dummy, 1);
++                if (rc) {
++                        printk(KERN_INFO "ext3_map_inode_page: error reading "
++                               "block %ld\n", iblock);
++                        goto out;
++                }
++                blocks[i] = dummy.b_blocknr;
++                created[i] = 1;
++        }
++
++ out:
++      lock_kernel();
++      ext3_journal_stop(handle, inode);
++      unlock_kernel();
++        return rc;
++}
+--- /dev/null  2003-01-30 03:24:37.000000000 -0700
++++ linux-2.4.18-p4smp-braam/fs/ext3/ext3-exports.c    2003-07-09 17:11:19.000000000 -0600
+@@ -0,0 +1,12 @@
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/locks.h>
++#include <linux/slab.h>
++#include <linux/ext3_jbd.h>
++#include <linux/ext3_fs.h>
++#include <linux/ext3_xattr.h>
++ 
++extern int ext3_map_inode_page(struct inode *inode, struct page *page,
++                        unsigned long *blocks, int *created, int create);
++EXPORT_SYMBOL(ext3_map_inode_page);
+
+_
diff --git a/lustre/kernel_patches/patches/linux-2.4.18-14-kgdb-1.6.patch b/lustre/kernel_patches/patches/linux-2.4.18-14-kgdb-1.6.patch
new file mode 100644 (file)
index 0000000..deca885
--- /dev/null
@@ -0,0 +1,3165 @@
+ Documentation/Configure.help      |   23 
+ Documentation/i386/gdb-serial.txt |  386 ++++++++++
+ Makefile                          |    4 
+ arch/i386/Makefile                |    6 
+ arch/i386/config.in               |   39 -
+ arch/i386/kernel/Makefile         |   18 
+ arch/i386/kernel/entry.S          |   27 
+ arch/i386/kernel/gdbstart.c       |  148 ++++
+ arch/i386/kernel/gdbstub.c        | 1402 ++++++++++++++++++++++++++++++++++++++
+ arch/i386/kernel/nmi.c            |   30 
+ arch/i386/kernel/signal.c         |    3 
+ arch/i386/kernel/traps.c          |   44 +
+ arch/i386/mm/fault.c              |   31 
+ drivers/char/Makefile             |    1 
+ drivers/char/gdbserial.c          |  280 +++++++
+ drivers/char/serial.c             |  147 +++
+ drivers/char/tty_io.c             |    6 
+ include/asm-i386/ioctls.h         |    1 
+ include/asm-i386/page.h           |    4 
+ include/asm-i386/processor.h      |    3 
+ include/linux/dcache.h            |    1 
+ include/linux/gdb.h               |   63 +
+ include/linux/sched.h             |   13 
+ init/main.c                       |    9 
+ kernel/ksyms.c                    |    5 
+ kernel/sched.c                    |   18 
+ 26 files changed, 2679 insertions(+), 33 deletions(-)
+
+--- linux-2.4.18-p4smp/arch/i386/config.in~linux-2.4.18-14-kgdb-1.6    2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/config.in       2003-07-09 13:18:12.000000000 -0600
+@@ -456,25 +456,26 @@ mainmenu_option next_comment
+ comment 'Kernel hacking'
+ bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+-if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+-   bool '  Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
+-   bool '  Use Scan technique for doing stack trace' CONFIG_STACK_TRACE_SCAN
+-   if [ "$CONFIG_FRAME_POINTER" = "y" ]; then
+-      bool '  Use Frame Pointer Walk technique for doing stack trace' CONFIG_STACK_TRACE_FPTR
+-   fi
+-   int 'Number of parameters to show in stack trace' CONFIG_STACK_TRACE_PARAM_COUNT 4
+-   bool '  Debug high memory support' CONFIG_DEBUG_HIGHMEM
+-   bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
+-   bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
+-   bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
+-   bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+-   bool '  Kernel Core Dump Facility' CONFIG_MCL_COREDUMP
+-   if [ "$CONFIG_MCL_COREDUMP" = "y" ]; then
+-      bool '  Reboot using bootimg' CONFIG_BOOTIMG
+-   fi
+-   bool '  OPROFILE support' CONFIG_OPROFILE
+-fi
+-
++bool 'KGDB: Remote (serial) kernel debugging with gdb' CONFIG_X86_REMOTE_DEBUG
++ if [ "$CONFIG_X86_REMOTE_DEBUG" != "n" ]; then
++    bool 'KGDB: Thread analysis' CONFIG_KGDB_THREAD
++    bool 'KGDB: Console messages through gdb' CONFIG_GDB_CONSOLE
++ else
++    bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
++    if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
++       bool '  Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
++       bool '  Debug high memory support' CONFIG_DEBUG_HIGHMEM
++       bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
++       bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
++       bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
++       bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
++       bool '  Kernel Core Dump Facility' CONFIG_MCL_COREDUMP
++       if [ "$CONFIG_MCL_COREDUMP" = "y" ]; then
++            bool '  Reboot using bootimg' CONFIG_BOOTIMG
++       fi
++      bool '  OPROFILE support' CONFIG_OPROFILE
++    fi
++ fi
+ endmenu
+ source lib/Config.in
+--- linux-2.4.18-p4smp/arch/i386/kernel/entry.S~linux-2.4.18-14-kgdb-1.6       2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/entry.S  2003-07-09 13:15:23.000000000 -0600
+@@ -266,7 +266,7 @@ ret_from_exception:
+       ALIGN
+ reschedule:
+-      call SYMBOL_NAME(schedule)    # test
++      call SYMBOL_NAME(user_schedule)    # test
+       jmp ret_from_sys_call
+ ENTRY(divide_error)
+@@ -404,6 +404,31 @@ ENTRY(spurious_interrupt_bug)
+       pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
+       jmp error_code
++#ifdef CONFIG_KGDB_THREAD
++ENTRY(kern_schedule)
++      pushl   %ebp
++      movl    %esp, %ebp
++      pushl   %ss             
++      pushl   %ebp
++      pushfl
++      pushl   %cs
++      pushl   4(%ebp)
++      pushl   %eax            
++      pushl   %es
++      pushl   %ds
++      pushl   %eax
++      pushl   (%ebp)
++      pushl   %edi
++      pushl   %esi
++      pushl   %edx
++      pushl   %ecx
++      pushl   %ebx
++      call    kern_do_schedule
++      movl    %ebp, %esp
++      pop     %ebp
++      ret
++#endif
++
+ .data
+ ENTRY(sys_call_table)
+       .long SYMBOL_NAME(sys_ni_syscall)       /* 0  -  old "setup()" system call*/
+--- /dev/null  2003-01-30 03:24:37.000000000 -0700
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/gdbstart.c       2003-07-09 13:15:23.000000000 -0600
+@@ -0,0 +1,148 @@
++/*
++ * This program opens a tty file and issues the GDB stub activating
++ * ioctl on it.
++ */
++
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <asm/ioctls.h>
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <sys/ioctl.h>
++#include <stdlib.h>
++#include <termios.h>
++#include <unistd.h>
++
++#define TIOCGDB               0x547F
++
++char          *tty_name = "/dev/ttyS0" ;      /* COM1 port */
++int            speed = 9600 ;                 /* default speed */
++struct termios         save_ts ;                      /* original term struct */
++
++void print_usage(void)
++{
++    printf("gdbstub [-s speed] [-t tty-dev]\n") ;
++    printf("  defaults:  /dev/ttyS0 with speed unmodified by this program\n");
++
++} /* print_usage */
++
++void tty_err(char *msg)
++{
++    char      buf[100] ;
++
++    strcpy(buf, msg) ;
++    strcat(buf, ": ") ;
++    strcat(buf, tty_name) ;
++    perror(buf) ;
++    exit(1) ;
++
++} /* tty_err */
++
++
++void setup_term(int fd)
++{
++    struct termios    ts ;
++    int                       speed_code ;
++
++    if (tcgetattr(fd, &ts) < 0) tty_err("tcgetattr") ;
++
++    save_ts = ts ;
++    switch (speed)
++    {
++    case 4800:
++      speed_code = B4800 ;
++      break ;
++    case 9600:
++      speed_code = B9600 ;
++      break ;
++    case 19200:
++      speed_code = B19200 ;
++      break ;
++    case 38400:
++      speed_code = B38400 ;
++      break ;
++    case 57600:
++      speed_code = B57600 ;
++      break ;
++    case 115200:
++      speed_code = B115200 ;
++      break ;
++    case 230400:
++      speed_code = B230400 ;
++      break ;
++    default:
++      printf("Invalid speed: %d\n", speed) ;
++      exit(1) ;
++    }
++
++    ts.c_cflag = CS8 | CREAD | CLOCAL ;
++    if (cfsetospeed(&ts, speed_code) < 0) tty_err("cfsetospeed") ;
++    if (cfsetispeed(&ts, speed_code) < 0) tty_err("cfsetispeed") ;
++
++    if (tcsetattr(fd, TCSANOW, &ts) < 0) tty_err("tcsetattr") ;
++
++} /* setup_term */
++
++void main(int argc, char **argv)
++{
++    int               opt ;
++    int               fil ;
++    int               rslt ;
++
++    while ((opt = getopt(argc, argv, "hs:t:")) > 0)
++    {
++      switch (opt)
++      {
++      case 's':
++          speed = atol(optarg) ;
++          break ;
++      case 't':
++          tty_name = optarg ;
++          break ;
++      case ':':
++          printf("Invalid option\n") ;
++          break ;
++      case '?':
++      case 'h':
++      default:
++          print_usage() ;
++          return ;
++      }
++    }
++
++    fil = open(tty_name, O_RDWR) ;
++    if (fil < 0)
++    {
++      perror(tty_name) ;
++      return ;
++    }
++
++
++    setup_term(fil) ;
++
++    /*
++     * When we issue this ioctl, control will not return until
++     * the debugger running on the remote host machine says "go".
++     */
++    printf("\nAbout to activate GDB stub in the kernel on %s\n", tty_name) ;
++    printf("Hit CR to continue, kill program to abort -- ") ;
++    getchar() ;
++    sync() ;
++    rslt = ioctl(fil, TIOCGDB, 0) ;
++    if (rslt < 0)
++    {
++      perror("TIOCGDB ioctl") ;
++      return ;
++    }
++
++    printf("\nGDB stub successfully activated\n") ;
++
++    for (;;)
++    {
++      pause() ;
++    }
++
++    if (tcsetattr(fil, TCSANOW, &save_ts) < 0) tty_err("tcsetattr") ;
++
++} /* main */
+--- /dev/null  2003-01-30 03:24:37.000000000 -0700
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/gdbstub.c        2003-07-09 13:15:23.000000000 -0600
+@@ -0,0 +1,1402 @@
++/*
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ */
++
++/*
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ */
++/****************************************************************************
++ *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
++ *
++ *  Module name: remcom.c $
++ *  Revision: 1.34 $
++ *  Date: 91/03/09 12:29:49 $
++ *  Contributor:     Lake Stevens Instrument Division$
++ *
++ *  Description:     low level support for gdb debugger. $
++ *
++ *  Considerations:  only works on target hardware $
++ *
++ *  Written by:      Glenn Engel $
++ *  Updated by:            Amit Kale<akale@veritas.com>
++ *  ModuleState:     Experimental $
++ *
++ *  NOTES:           See Below $
++ *
++ *  Modified for 386 by Jim Kingdon, Cygnus Support.
++ *  Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
++ *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
++ *      thread support,
++ *      support for multiple processors,
++ *    support for ia-32(x86) hardware debugging,
++ *    Console support,
++ *    handling nmi watchdog
++ *    Amit S. Kale ( akale@veritas.com )
++ *
++ *
++ *  To enable debugger support, two things need to happen.  One, a
++ *  call to set_debug_traps() is necessary in order to allow any breakpoints
++ *  or error conditions to be properly intercepted and reported to gdb.
++ *  Two, a breakpoint needs to be generated to begin communication.  This
++ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
++ *  simulates a breakpoint by executing an int 3.
++ *
++ *************
++ *
++ *    The following gdb commands are supported:
++ *
++ * command          function                               Return value
++ *
++ *    g             return the value of the CPU registers  hex data or ENN
++ *    G             set the value of the CPU registers     OK or ENN
++ *
++ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
++ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
++ *
++ *    c             Resume at current address              SNN   ( signal NN)
++ *    cAA..AA       Continue at address AA..AA             SNN
++ *
++ *    s             Step one instruction                   SNN
++ *    sAA..AA       Step one instruction from AA..AA       SNN
++ *
++ *    k             kill
++ *
++ *    ?             What was the last sigval ?             SNN   (signal NN)
++ *
++ * All commands and responses are sent with a packet which includes a
++ * checksum.  A packet consists of
++ *
++ * $<packet info>#<checksum>.
++ *
++ * where
++ * <packet info> :: <characters representing the command or response>
++ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
++ *
++ * When a packet is received, it is first acknowledged with either '+' or '-'.
++ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
++ *
++ * Example:
++ *
++ * Host:                  Reply:
++ * $m0,10#2a               +$00010203040506070809101112131415#42
++ *
++ ****************************************************************************/
++
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <asm/vm86.h>
++#include <asm/system.h>
++#include <asm/ptrace.h>                       /* for linux pt_regs struct */
++#include <linux/gdb.h>
++#ifdef CONFIG_GDB_CONSOLE
++#include <linux/console.h>
++#endif
++#include <linux/init.h>
++
++/************************************************************************
++ *
++ * external low-level support routines
++ */
++typedef void (*Function)(void);           /* pointer to a function */
++
++/* Thread reference */
++typedef unsigned char threadref[8];
++
++extern int putDebugChar(int);   /* write a single character      */
++extern int getDebugChar(void);   /* read and return a single char */
++
++/************************************************************************/
++/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
++/* at least NUMREGBYTES*2 are needed for register packets */
++/* Longer buffer is needed to list all threads */
++#define BUFMAX 1024
++
++static char initialized;  /* boolean flag. != 0 means we've been initialized */
++
++static const char hexchars[]="0123456789abcdef";
++
++/* Number of bytes of registers.  */
++#define NUMREGBYTES 64
++/*
++ * Note that this register image is in a different order than
++ * the register image that Linux produces at interrupt time.
++ *
++ * Linux's register image is defined by struct pt_regs in ptrace.h.
++ * Just why GDB uses a different order is a historical mystery.
++ */
++enum regnames {_EAX,          /* 0 */
++             _ECX,            /* 1 */
++             _EDX,            /* 2 */
++             _EBX,            /* 3 */
++             _ESP,            /* 4 */
++             _EBP,            /* 5 */
++             _ESI,            /* 6 */
++             _EDI,            /* 7 */
++             _PC              /* 8 also known as eip */,
++             _PS              /* 9 also known as eflags */,
++             _CS,             /* 10 */
++             _SS,             /* 11 */
++             _DS,             /* 12 */
++             _ES,             /* 13 */
++             _FS,             /* 14 */
++             _GS};            /* 15 */
++
++
++
++/***************************  ASSEMBLY CODE MACROS *************************/
++/*                                                                       */
++
++#define BREAKPOINT() asm("   int $3");
++
++/* Put the error code here just in case the user cares.  */
++int gdb_i386errcode;
++/* Likewise, the vector number here (since GDB only gets the signal
++   number through the usual means, and that's not very specific).  */
++int gdb_i386vector = -1;
++
++#if KGDB_MAX_NO_CPUS != 8
++#error change the definition of slavecpulocks
++#endif
++
++static spinlock_t slavecpulocks[KGDB_MAX_NO_CPUS] = { SPIN_LOCK_UNLOCKED,
++      SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED,
++      SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED,
++      SPIN_LOCK_UNLOCKED };
++volatile int procindebug[KGDB_MAX_NO_CPUS];
++
++volatile unsigned kgdb_step = 0;
++
++volatile unsigned kgdb_lock = 0;
++
++enum gdb_bptype
++{
++      bp_breakpoint = '0',
++      bp_hardware_breakpoint,
++      bp_write_watchpoint,
++      bp_read_watchpoint,
++      bp_access_watchpoint
++};
++
++enum gdb_bpstate
++{
++      bp_disabled,
++      bp_enabled
++};
++
++#define BREAK_INSTR_SIZE      1
++
++struct gdb_breakpoint
++{
++      unsigned int            bpt_addr;
++      unsigned char           saved_instr[BREAK_INSTR_SIZE];
++      enum gdb_bptype         type;
++      enum gdb_bpstate        state;
++};
++
++typedef struct gdb_breakpoint gdb_breakpoint_t;
++
++#define MAX_BREAKPOINTS       16
++
++gdb_breakpoint_t kgdb_break[MAX_BREAKPOINTS];
++static char gdb_bpt_instr[BREAK_INSTR_SIZE] = {0xcc};
++
++static void kgdb_usercode (void)
++{
++}
++
++int hex(char ch)
++{
++  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
++  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
++  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
++  return (-1);
++}
++
++
++/* scan for the sequence $<data>#<checksum>     */
++void getpacket(char * buffer)
++{
++  unsigned char checksum;
++  unsigned char xmitcsum;
++  int  i;
++  int  count;
++  char ch;
++
++  do {
++    /* wait around for the start character, ignore all other characters */
++    while ((ch = (getDebugChar() & 0x7f)) != '$');
++    checksum = 0;
++    xmitcsum = -1;
++
++    count = 0;
++
++    /* now, read until a # or end of buffer is found */
++    while (count < BUFMAX) {
++      ch = getDebugChar() & 0x7f;
++      if (ch == '#') break;
++      checksum = checksum + ch;
++      buffer[count] = ch;
++      count = count + 1;
++      }
++    buffer[count] = 0;
++
++    if (ch == '#') {
++      xmitcsum = hex(getDebugChar() & 0x7f) << 4;
++      xmitcsum += hex(getDebugChar() & 0x7f);
++
++      if (checksum != xmitcsum) putDebugChar('-');  /* failed checksum */
++      else {
++       putDebugChar('+');  /* successful transfer */
++       /* if a sequence char is present, reply the sequence ID */
++       if (buffer[2] == ':') {
++          putDebugChar( buffer[0] );
++          putDebugChar( buffer[1] );
++          /* remove sequence chars from buffer */
++          count = strlen(buffer);
++          for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
++       }
++      }
++    }
++  } while (checksum != xmitcsum);
++
++}
++
++/* send the packet in buffer.  */
++
++
++void putpacket(char * buffer)
++{
++  unsigned char checksum;
++  int  count;
++  char ch;
++
++  /*  $<packet info>#<checksum>. */
++  do {
++  putDebugChar('$');
++  checksum = 0;
++  count    = 0;
++
++  while ((ch=buffer[count])) {
++    if (! putDebugChar(ch)) return;
++    checksum += ch;
++    count += 1;
++  }
++
++  putDebugChar('#');
++  putDebugChar(hexchars[checksum >> 4]);
++  putDebugChar(hexchars[checksum % 16]);
++
++  } while ((getDebugChar() & 0x7f) != '+');
++
++}
++
++static char  remcomInBuffer[BUFMAX];
++static char  remcomOutBuffer[BUFMAX];
++static short error;
++
++static void regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs)
++{
++    gdb_regs[_EAX] =  regs->eax;
++    gdb_regs[_EBX] =  regs->ebx;
++    gdb_regs[_ECX] =  regs->ecx;
++    gdb_regs[_EDX] =  regs->edx;
++    gdb_regs[_ESI] =  regs->esi;
++    gdb_regs[_EDI] =  regs->edi;
++    gdb_regs[_EBP] =  regs->ebp;
++    gdb_regs[ _DS] =  regs->xds;
++    gdb_regs[ _ES] =  regs->xes;
++    gdb_regs[ _PS] =  regs->eflags;
++    gdb_regs[ _CS] =  regs->xcs;
++    gdb_regs[ _PC] =  regs->eip;
++    gdb_regs[_ESP] =  (int) (&regs->esp) ;
++    gdb_regs[ _SS] =  __KERNEL_DS;
++    gdb_regs[ _FS] =  0xFFFF;
++    gdb_regs[ _GS] =  0xFFFF;
++} /* regs_to_gdb_regs */
++
++static void gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs)
++{
++    regs->eax =     gdb_regs[_EAX] ;
++    regs->ebx =     gdb_regs[_EBX] ;
++    regs->ecx =     gdb_regs[_ECX] ;
++    regs->edx =     gdb_regs[_EDX] ;
++    regs->esi =     gdb_regs[_ESI] ;
++    regs->edi =     gdb_regs[_EDI] ;
++    regs->ebp =     gdb_regs[_EBP] ;
++    regs->xds =     gdb_regs[ _DS] ;
++    regs->xes =     gdb_regs[ _ES] ;
++    regs->eflags=     gdb_regs[ _PS] ;
++    regs->xcs =     gdb_regs[ _CS] ;
++    regs->eip =     gdb_regs[ _PC] ;
++#if 0                                 /* can't change these */
++    regs->esp =     gdb_regs[_ESP] ;
++    regs->xss =     gdb_regs[ _SS] ;
++    regs->fs  =     gdb_regs[ _FS] ;
++    regs->gs  =     gdb_regs[ _GS] ;
++#endif
++
++} /* gdb_regs_to_regs */
++
++/* Indicate to caller of mem2hex or hex2mem that there has been an
++   error.  */
++static volatile int kgdb_memerr = 0;
++volatile int kgdb_memerr_expected = 0;
++static volatile int kgdb_memerr_cnt = 0;
++static          int garbage_loc = -1 ;
++
++int
++get_char (char *addr)
++{
++  return *addr;
++}
++
++void
++set_char ( char *addr, int val)
++{
++  *addr = val;
++}
++
++static void
++get_mem (char *addr,
++       unsigned char *buf,
++       int count)
++{
++      while (count) {
++              *buf++ = get_char(addr++);
++              if (kgdb_memerr)
++                      return;
++              count--;
++      }
++}
++
++static void
++set_mem (char *addr,
++       char *buf,
++       int count)
++{
++      while (count) {
++              set_char(addr++,*buf++);
++              if (kgdb_memerr)
++                      return;
++              count--;
++      }
++}
++
++/* convert the memory pointed to by mem into hex, placing result in buf */
++/* return a pointer to the last char put in buf (null) */
++/* If MAY_FAULT is non-zero, then we should set kgdb_memerr in response to
++   a fault; if zero treat a fault like any other fault in the stub.  */
++char* mem2hex( char* mem,
++             char* buf,
++             int   count,
++             int may_fault)
++{
++      int i;
++      unsigned char ch;
++
++      if (may_fault)
++      {
++          kgdb_memerr_expected = 1 ;
++          kgdb_memerr = 0 ;
++      }
++      for (i=0;i<count;i++) {
++
++        ch = get_char (mem++);
++
++        if (may_fault && kgdb_memerr)
++        {
++          *buf = 0 ;                          /* truncate buffer */
++          return (buf);
++        }
++          *buf++ = hexchars[ch >> 4];
++          *buf++ = hexchars[ch % 16];
++      }
++      *buf = 0;
++      if (may_fault)
++        kgdb_memerr_expected = 0 ;
++      return(buf);
++}
++
++/* convert the hex array pointed to by buf into binary to be placed in mem */
++/* return a pointer to the character AFTER the last byte written */
++char* hex2mem( char* buf,
++             char* mem,
++             int   count,
++             int may_fault)
++{
++      int i;
++      unsigned char ch;
++
++      if (may_fault)
++      {
++          kgdb_memerr_expected = 1 ;
++          kgdb_memerr = 0 ;
++      }
++      for (i=0;i<count;i++) {
++          ch = hex(*buf++) << 4;
++          ch = ch + hex(*buf++);
++        set_char (mem++, ch);
++
++        if (may_fault && kgdb_memerr)
++        {
++          return (mem);
++        }
++      }
++      if (may_fault)
++        kgdb_memerr_expected = 0 ;
++      return(mem);
++}
++
++
++/**********************************************/
++/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
++/* RETURN NUMBER OF CHARS PROCESSED           */
++/**********************************************/
++int hexToInt(char **ptr, int *intValue)
++{
++    int numChars = 0;
++    int hexValue;
++
++    *intValue = 0;
++
++    while (**ptr)
++    {
++        hexValue = hex(**ptr);
++        if (hexValue >=0)
++        {
++            *intValue = (*intValue <<4) | hexValue;
++            numChars ++;
++        }
++        else
++            break;
++
++        (*ptr)++;
++    }
++
++    return (numChars);
++}
++
++#ifdef CONFIG_KGDB_THREAD
++static int
++stubhex (
++     int ch)
++{
++  if (ch >= 'a' && ch <= 'f')
++    return ch - 'a' + 10;
++  if (ch >= '0' && ch <= '9')
++    return ch - '0';
++  if (ch >= 'A' && ch <= 'F')
++    return ch - 'A' + 10;
++  return -1;
++}
++
++
++static int
++stub_unpack_int (
++     char *buff,
++     int fieldlength)
++{
++  int nibble;
++  int retval = 0;
++
++  while (fieldlength)
++    {
++      nibble = stubhex (*buff++);
++      retval |= nibble;
++      fieldlength--;
++      if (fieldlength)
++      retval = retval << 4;
++    }
++  return retval;
++}
++#endif
++
++static char *
++pack_hex_byte (
++     char *pkt,
++     int byte)
++{
++  *pkt++ = hexchars[(byte >> 4) & 0xf];
++  *pkt++ = hexchars[(byte & 0xf)];
++  return pkt;
++}
++
++#define BUF_THREAD_ID_SIZE 16
++
++#ifdef CONFIG_KGDB_THREAD
++static char *
++pack_threadid (
++     char *pkt,
++     threadref *id)
++{
++  char *limit;
++  unsigned char *altid;
++
++  altid = (unsigned char *) id;
++  limit = pkt + BUF_THREAD_ID_SIZE;
++  while (pkt < limit)
++    pkt = pack_hex_byte (pkt, *altid++);
++  return pkt;
++}
++
++static char *
++unpack_byte (
++     char *buf,
++     int *value)
++{
++  *value = stub_unpack_int (buf, 2);
++  return buf + 2;
++}
++
++static char *
++unpack_threadid (
++     char *inbuf,
++     threadref *id)
++{
++  char *altref;
++  char *limit = inbuf + BUF_THREAD_ID_SIZE;
++  int x, y;
++
++  altref = (char *) id;
++
++  while (inbuf < limit)
++    {
++      x = stubhex (*inbuf++);
++      y = stubhex (*inbuf++);
++      *altref++ = (x << 4) | y;
++    }
++  return inbuf;
++}
++#endif
++
++void
++int_to_threadref (
++     threadref *id,
++     int value)
++{
++  unsigned char *scan;
++
++  scan = (unsigned char *) id;
++  {
++    int i = 4;
++    while (i--)
++      *scan++ = 0;
++  }
++  *scan++ = (value >> 24) & 0xff;
++  *scan++ = (value >> 16) & 0xff;
++  *scan++ = (value >> 8) & 0xff;
++  *scan++ = (value & 0xff);
++}
++
++#ifdef CONFIG_KGDB_THREAD
++static int
++threadref_to_int (
++     threadref *ref)
++{
++  int i, value = 0;
++  unsigned char *scan;
++
++  scan = (char *) ref;
++  scan += 4;
++  i = 4;
++  while (i-- > 0)
++    value = (value << 8) | ((*scan++) & 0xff);
++  return value;
++}
++
++
++struct task_struct *
++getthread (
++      int pid)
++{
++      task_t *thread;
++      thread = find_task_by_pid(pid);
++      if (thread) {
++              return thread;
++      }
++      thread = &init_task;
++      do {
++              if (thread->pid == pid) {
++                      return thread;
++              }
++              thread = thread->next_task;
++      } while (thread != &init_task);
++      return NULL;
++}
++#endif
++
++struct hw_breakpoint {
++      unsigned enabled;
++      unsigned type;
++      unsigned len;
++      unsigned addr;
++} breakinfo[4] = { { enabled:0 }, { enabled:0 }, { enabled:0 }, { enabled:0 }};
++
++void correct_hw_break( void )
++{
++      int breakno;
++      int correctit;
++      int breakbit;
++      unsigned dr7;
++
++      asm volatile ( 
++              "movl %%db7, %0\n"
++              : "=r" (dr7)
++              : );
++      do
++      {
++              unsigned addr0, addr1, addr2, addr3;
++              asm volatile (
++                      "movl %%db0, %0\n"
++                      "movl %%db1, %1\n"
++                      "movl %%db2, %2\n"
++                      "movl %%db3, %3\n"
++                      : "=r" (addr0), "=r" (addr1), "=r" (addr2),
++                      "=r" (addr3) : );
++      } while (0);
++      correctit = 0;
++      for (breakno = 0; breakno < 3; breakno++) {
++              breakbit = 2 << (breakno << 1);
++              if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
++                      correctit = 1;
++                      dr7 |= breakbit;
++                      dr7 &= ~(0xf0000 << (breakno << 2));
++                      dr7 |= (((breakinfo[breakno].len << 2) |
++                             breakinfo[breakno].type) << 16) <<
++                             (breakno << 2);
++                      switch (breakno) {
++                      case 0:
++                              asm volatile ("movl %0, %%dr0\n"
++                                      : 
++                                      : "r" (breakinfo[breakno].addr) );
++                              break;
++
++                      case 1:
++                              asm volatile ("movl %0, %%dr1\n"
++                                      : 
++                                      : "r" (breakinfo[breakno].addr) );
++                              break;
++
++                      case 2:
++                              asm volatile ("movl %0, %%dr2\n"
++                                      : 
++                                      : "r" (breakinfo[breakno].addr) );
++                              break;
++
++                      case 3:
++                              asm volatile ("movl %0, %%dr3\n"
++                                      : 
++                                      : "r" (breakinfo[breakno].addr) );
++                              break;
++                      }
++              } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled){
++                      correctit = 1;
++                      dr7 &= ~breakbit;
++                      dr7 &= ~(0xf0000 << (breakno << 2));
++              }
++      }
++      if (correctit) {
++              asm volatile ( "movl %0, %%db7\n"
++                             :
++                             : "r" (dr7));
++      }
++}
++
++int remove_hw_break(
++      unsigned breakno)
++{
++      if (!breakinfo[breakno].enabled) {
++              return -1;
++      }
++      breakinfo[breakno].enabled = 0;
++      return 0;
++}
++
++int set_hw_break(
++      unsigned breakno,
++      unsigned type,
++      unsigned len,
++      unsigned addr)
++{
++      if (breakinfo[breakno].enabled) {
++              return -1;
++      }
++      breakinfo[breakno].enabled = 1;
++      breakinfo[breakno].type = type;
++      breakinfo[breakno].len = len;
++      breakinfo[breakno].addr = addr;
++      return 0;
++}
++
++static int
++set_break (
++      unsigned addr)
++{
++      int i, breakno = -1;
++
++      for (i = 0; i < MAX_BREAKPOINTS; i++) {
++              if ((kgdb_break[i].state == bp_enabled) &&
++                  (kgdb_break[i].bpt_addr == addr)) {
++                      breakno = -1;
++                      break;
++              }
++
++              if (kgdb_break[i].state == bp_disabled) {
++                      if ((breakno == -1) || (kgdb_break[i].bpt_addr == addr))
++                              breakno = i;
++              }
++      }
++      if (breakno == -1)
++              return -1;
++
++      get_mem((char *)addr,kgdb_break[breakno].saved_instr,BREAK_INSTR_SIZE);
++      if (kgdb_memerr)
++              return -1;
++
++      set_mem((char *)addr,gdb_bpt_instr,BREAK_INSTR_SIZE);
++      if (kgdb_memerr)
++              return -1;
++
++      kgdb_break[breakno].state = bp_enabled;
++      kgdb_break[breakno].type = bp_breakpoint;
++      kgdb_break[breakno].bpt_addr = addr;
++
++      return 0;
++}
++
++static int
++remove_break (unsigned addr)
++{
++      int i;
++
++      for (i=0; i<MAX_BREAKPOINTS; i++) {
++              if ((kgdb_break[i].state == bp_enabled) &&
++                  (kgdb_break[i].bpt_addr == addr)) {
++                      set_mem((char *)addr, kgdb_break[i].saved_instr,
++                                      BREAK_INSTR_SIZE);
++                      if (kgdb_memerr)
++                              return -1;
++                      kgdb_break[i].state = bp_disabled;
++                      return 0;
++              }
++      }
++      return -1;
++}
++
++static void
++clear_disabled_break()
++{
++              int i;
++              for (i=0; i<MAX_BREAKPOINTS; i++) {
++                              if (kgdb_break[i].state == bp_disabled)
++                                              kgdb_break[i].bpt_addr = 0;
++              }
++}
++
++void gdb_wait(struct pt_regs *regs)
++{
++      unsigned flags;
++      int processor;
++      
++      local_irq_save(flags);
++      processor = smp_processor_id();
++      procindebug[processor] = 1;
++      current->thread.kgdbregs = regs;
++
++      /* Wait till master processor goes completely into the debugger */
++      while (!procindebug[kgdb_lock - 1]) {
++              int i = 10;     /* an arbitrary number */
++
++              while (--i)
++                      asm volatile ("nop": : : "memory");
++
++      }
++
++      /* Wait till master processor is done with debugging */
++      spin_lock(slavecpulocks + processor);
++      correct_hw_break();
++
++      /* Signal the master processor that we are done */
++      procindebug[processor] = 0;
++      spin_unlock(slavecpulocks + processor);
++      local_irq_restore(flags);
++}
++
++void
++printexceptioninfo(
++      int exceptionNo,
++      int errorcode,
++      char *buffer)
++{
++      unsigned dr6;
++      int i;
++      switch (exceptionNo) {
++      case 1:                 /* debug exception */
++              break;
++      case 3:                 /* breakpoint */
++              sprintf(buffer, "Software breakpoint");
++              return;
++      default:
++              sprintf(buffer, "Details not available");
++              return;
++      }
++      asm volatile ("movl %%db6, %0\n"
++                    : "=r" (dr6)
++                    : );
++      if (dr6 & 0x4000) {
++              sprintf(buffer, "Single step");
++              return;
++      }
++      for (i = 0; i < 4; ++i) {
++              if (dr6 & (1 << i)) {
++                      sprintf(buffer, "Hardware breakpoint %d", i);
++                      return;
++              }
++      }
++      sprintf(buffer, "Unknown trap");
++      return;
++}
++
++/*
++ * This function does all command procesing for interfacing to gdb.
++ *
++ * NOTE:  The INT nn instruction leaves the state of the interrupt
++ *        enable flag UNCHANGED.  That means that when this routine
++ *        is entered via a breakpoint (INT 3) instruction from code
++ *        that has interrupts enabled, then interrupts will STILL BE
++ *        enabled when this routine is entered.  The first thing that
++ *        we do here is disable interrupts so as to prevent recursive
++ *        entries and bothersome serial interrupts while we are
++ *        trying to run the serial port in polled mode.
++ *
++ * For kernel version 2.1.xx the cli() actually gets a spin lock so
++ * it is always necessary to do a restore_flags before returning
++ * so as to let go of that lock.
++ */
++int handle_exception(int exceptionVector,
++                   int signo,
++                   int err_code,
++                   struct pt_regs *linux_regs)
++{
++      struct task_struct      *usethread = NULL;
++      int                     addr, length;
++      int                     breakno, breaktype;
++      char                    *ptr;
++      int                     newPC;
++      unsigned long           flags;
++      int                     gdb_regs[NUMREGBYTES/4];
++      int                     i;
++      int                     dr6;
++      int                     ret;
++      int                     maxbpt, bpt_done;
++      unsigned long           bptaddr;
++      struct pt_regs          tempregs;
++#ifdef CONFIG_KGDB_THREAD
++      int                     nothreads;
++      int                     maxthreads;
++      int                     threadid;
++      threadref               thref;
++      struct task_struct      *thread = NULL;
++#endif
++      unsigned                procid;
++
++#define       regs    (*linux_regs)
++
++      /*
++       * If the entry is not from the kernel then return to the Linux
++       * trap handler and let it process the interrupt normally.
++       */
++      if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->xcs)) {
++              return(0);
++      }
++
++      if (kgdb_memerr_expected)
++      {
++              /*
++               * This fault occured because of the get_char or set_char
++               * routines.  These two routines use either eax of edx to
++               * indirectly reference the location in memory that they
++               * are working with.  For a page fault, when we return
++               * the instruction will be retried, so we have to make
++               * sure that these registers point to valid memory.
++               */
++              kgdb_memerr = 1 ;               /* set mem error flag */
++              kgdb_memerr_expected = 0 ;
++              kgdb_memerr_cnt++ ;     /* helps in debugging */
++              regs.eax = (long) &garbage_loc ;        /* make valid address */
++              regs.edx = (long) &garbage_loc ;        /* make valid address */
++              return(0) ;
++      }
++
++      /* Hold kgdb_lock */
++      procid = smp_processor_id();
++      while (cmpxchg(&kgdb_lock, 0, (procid + 1)) != 0) {
++              int i = 25;     /* an arbitrary number */
++
++              while (--i)
++                      asm volatile ("nop": : : "memory");
++      }
++
++      kgdb_step = 0;
++
++      local_irq_save(flags);
++
++      /* Disable hardware debugging while we are in kgdb */
++      __asm__("movl %0,%%db7"
++              : /* no output */
++              : "r" (0));
++
++      for (i = 0; i < smp_num_cpus; i++) {
++              spin_lock(&slavecpulocks[i]);
++      }
++
++      /* spin_lock code is good enough as a barrier so we don't
++       * need one here */
++      procindebug[smp_processor_id()] = 1;
++
++      /* Master processor is completely in the debugger */
++
++      gdb_i386vector  = exceptionVector;
++      gdb_i386errcode = err_code ;
++
++      /* reply to host that an exception has occurred */
++      remcomOutBuffer[0] = 'S';
++      remcomOutBuffer[1] =  hexchars[signo >> 4];
++      remcomOutBuffer[2] =  hexchars[signo % 16];
++      remcomOutBuffer[3] = 0;
++
++      putpacket(remcomOutBuffer);
++
++      while (1==1) {
++              error = 0;
++              remcomOutBuffer[0] = 0;
++              getpacket(remcomInBuffer);
++              switch (remcomInBuffer[0]) {
++              case '?' : 
++                      remcomOutBuffer[0] = 'S';
++                      remcomOutBuffer[1] =  hexchars[signo >> 4];
++                      remcomOutBuffer[2] =  hexchars[signo % 16];
++                      remcomOutBuffer[3] = 0;
++                      break;
++              case 'g' : /* return the value of the CPU registers */
++                      if (!usethread || usethread == current) {
++                              regs_to_gdb_regs(gdb_regs, &regs) ;
++                      } else {
++                              memset(gdb_regs, 0, NUMREGBYTES);
++                              if (usethread->thread.kgdbregs) {
++                                      kgdb_memerr_expected = 1 ;
++                                      kgdb_memerr = 0;
++                                      get_char((char *)usethread->thread.kgdbregs);
++                                      kgdb_memerr_expected = 0;
++                                      if (kgdb_memerr) {
++                                              *(((char *)&tempregs) + i) = '\0';
++                                              gdb_regs[_PC] = kgdb_usercode;
++                                      } else {
++                                              regs_to_gdb_regs(gdb_regs,
++                                                      usethread->thread.kgdbregs);
++                                      }
++                              } else {
++                                      gdb_regs[_PC] = kgdb_usercode;
++                              }
++                      }
++                      mem2hex((char*) gdb_regs, remcomOutBuffer, NUMREGBYTES, 0);
++                      break;
++              case 'G' : /* set the value of the CPU registers - return OK */
++                      hex2mem(&remcomInBuffer[1], (char*) gdb_regs, NUMREGBYTES, 0);
++                      if (!usethread || usethread == current) {
++                              gdb_regs_to_regs(gdb_regs, &regs) ;
++                              strcpy(remcomOutBuffer,"OK");
++                      } else {
++                              strcpy(remcomOutBuffer,"E00");
++                      }
++                      break;
++
++              /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
++              case 'm' :
++                      /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
++                      ptr = &remcomInBuffer[1];
++                      if (hexToInt(&ptr,&addr))
++                      if (*(ptr++) == ',')
++                      if (hexToInt(&ptr,&length))
++                      {
++                              ptr = 0;
++                              mem2hex((char*) addr, remcomOutBuffer, length, 1);
++                              if (kgdb_memerr) {
++                                      strcpy (remcomOutBuffer, "E03");
++                              }
++                      }
++
++                      if (ptr)
++                      {
++                              strcpy(remcomOutBuffer,"E01");
++                      }
++                      break;
++
++            /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
++            case 'M' :
++                              /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
++                              ptr = &remcomInBuffer[1];
++                              if (hexToInt(&ptr,&addr))
++                              if (*(ptr++) == ',')
++                                      if (hexToInt(&ptr,&length))
++                                              if (*(ptr++) == ':')
++                                              {
++                                                      hex2mem(ptr, (char*) addr, length, 1);
++
++                                                      if (kgdb_memerr) {
++                                                              strcpy (remcomOutBuffer, "E03");
++                                                      } else {
++                                                              strcpy(remcomOutBuffer,"OK");
++                                                      }
++
++                                                      ptr = 0;
++                                              }
++                              if (ptr)
++                              {
++                                      strcpy(remcomOutBuffer,"E02");
++                              }
++                              break;
++
++           /* cAA..AA    Continue at address AA..AA(optional) */
++           /* sAA..AA   Step one instruction from AA..AA(optional) */
++           /* D         Detach from debugger */
++           case 'c' :
++           case 's' :
++           case 'D' :
++
++                      /* try to read optional parameter, pc unchanged if no parm */
++                      ptr = &remcomInBuffer[1];
++                      if (hexToInt(&ptr,&addr))
++                      {
++                              regs.eip = addr;
++                      }
++
++                      newPC = regs.eip ;
++
++                      /* clear the trace bit */
++                      regs.eflags &= 0xfffffeff;
++
++                      /* set the trace bit if we're stepping */
++                      if (remcomInBuffer[0] == 's') {
++                              regs.eflags |= 0x100;
++                              kgdb_step = 1;
++                      }
++                      if (remcomInBuffer[0] == 'D') {
++                              clear_disabled_break();
++                              strcpy(remcomOutBuffer,"+");
++                              putpacket(remcomOutBuffer);
++                      }
++
++                      asm volatile ("movl %%db6, %0\n"
++                              : "=r" (dr6)
++                              : );
++                      if (!(dr6 & 0x4000)) {
++                              for (breakno = 0; breakno < 4; ++breakno) {
++                                      if (dr6 & (1 << breakno)) {
++                                              if (breakinfo[breakno].type == 0) {
++                                                      /* Set restore flag */
++                                                      regs.eflags |= 0x10000;
++                                                      break;
++                                              }
++                                      }
++                              }
++                      }
++                      correct_hw_break();
++                      asm volatile ( 
++                              "movl %0, %%db6\n"
++                              : 
++                              : "r" (0) );
++
++                      procindebug[smp_processor_id()] = 0;
++
++                      /* Signal the slave processors to quit from
++                       * the debugger */
++                      for (i = 0; i < smp_num_cpus; i++) {
++                              spin_unlock(&slavecpulocks[i]);
++                      }
++
++                      /* Wait till all the processors have quit
++                       * from the debugger */
++
++                      for (i = 0; i < smp_num_cpus; i++) {
++                              while (procindebug[i]) {
++                                      int j = 10; /* an arbitrary number */
++
++                                      while (--j) {
++                                              asm volatile ("nop"
++                                                      : : : "memory");
++                                      }
++                              }
++                      }
++
++                      /* Release kgdb_lock */
++                      asm volatile (
++#ifndef CONFIG_X86_OOSTORE
++                      "movb $0,%0"
++#else
++                      "lock movb $0,%0"
++#endif
++                      : "=m" (kgdb_lock) : : "memory");
++
++                      local_irq_restore(flags) ;
++                      return(0) ;
++
++              /* kill the program */
++              case 'k' :  /* do nothing */
++              break;
++
++              /* query */
++              case 'q' :
++                      switch (remcomInBuffer[1]) {
++#ifdef CONFIG_KGDB_THREAD
++                      case 'L':       
++                              /* List threads */
++                              unpack_byte(remcomInBuffer+3, &maxthreads);
++                              unpack_threadid(remcomInBuffer+5, &thref);
++
++                              remcomOutBuffer[0] = 'q';
++                              remcomOutBuffer[1] = 'M';
++                              remcomOutBuffer[4] = '0';
++                              pack_threadid(remcomOutBuffer+5, &thref);       
++
++                              threadid = threadref_to_int(&thref);
++                              for (nothreads = 0;
++                                      nothreads < maxthreads && threadid< PID_MAX;
++                                      threadid++ )
++                              {
++                                      read_lock(&tasklist_lock);
++                                      thread = getthread(threadid);
++                                      read_unlock(&tasklist_lock);
++                                      if (thread) {
++                                              int_to_threadref(&thref, threadid);
++                                              pack_threadid(remcomOutBuffer+21+nothreads*16,
++                                                            &thref);
++                                              nothreads++;
++                                      }
++                              }
++                              if (threadid == PID_MAX) {
++                                      remcomOutBuffer[4] = '1';
++                              }
++                              pack_hex_byte(remcomOutBuffer+2, nothreads);
++                              remcomOutBuffer[21+nothreads*16] = '\0';
++                              break;
++
++                      case 'C':
++                              /* Current thread id */
++                              remcomOutBuffer[0] = 'Q';
++                              remcomOutBuffer[1] = 'C';
++                              threadid = current->pid;
++                              int_to_threadref(&thref, threadid);
++                              pack_threadid(remcomOutBuffer+2, &thref);       
++                              remcomOutBuffer[18] = '\0';
++                              break;
++#endif
++
++                      case 'E':
++                              /* Print exception info */
++                              printexceptioninfo(exceptionVector, err_code, remcomOutBuffer);
++                              break;
++                      }
++                      break;
++
++#ifdef CONFIG_KGDB_THREAD
++              /* task related */
++              case 'H' :       
++                      switch (remcomInBuffer[1]) {
++                              case 'g':
++                                      ptr = &remcomInBuffer[2];
++                                      hexToInt(&ptr, &threadid);
++                                      thread = getthread(threadid);
++                                      if (!thread) {
++                                              remcomOutBuffer[0] = 'E';
++                                              remcomOutBuffer[1] = '\0';
++                                              break;
++                                      }
++                                      usethread = thread;
++                                      /* follow through */
++                              case 'c':
++                                      remcomOutBuffer[0] = 'O';
++                                      remcomOutBuffer[1] = 'K';
++                                      remcomOutBuffer[2] = '\0';
++                              break;
++                      }
++                      break;
++
++              /* Query thread status */
++              case 'T':
++                      ptr = &remcomInBuffer[1];
++                      hexToInt(&ptr, &threadid);
++                      thread = getthread(threadid);
++                      if (thread) {
++                              remcomOutBuffer[0] = 'O';
++                              remcomOutBuffer[1] = 'K';
++                              remcomOutBuffer[2] = '\0';
++                      } else {
++                              remcomOutBuffer[0] = 'E';
++                              remcomOutBuffer[1] = '\0';
++                      }
++                      break;
++#endif
++
++              case 'Y':
++                      ptr = &remcomInBuffer[1];
++                      hexToInt(&ptr, &breakno);
++                      ptr++;
++                      hexToInt(&ptr, &breaktype);
++                      ptr++;
++                      hexToInt(&ptr, &length);
++                      ptr++;
++                      hexToInt(&ptr, &addr);
++                      if (set_hw_break(breakno & 0x3, breaktype & 0x3 , length & 0x3, addr)
++                              == 0) {
++                              strcpy(remcomOutBuffer, "OK");
++                      } else {
++                              strcpy(remcomOutBuffer, "ERROR");
++                      }
++                      break;
++
++              /* Remove hardware breakpoint */      
++              case 'y':
++                      ptr = &remcomInBuffer[1];
++                      hexToInt(&ptr, &breakno);
++                      if (remove_hw_break(breakno & 0x3) == 0) {
++                              strcpy(remcomOutBuffer, "OK");
++                      } else {
++                              strcpy(remcomOutBuffer, "ERROR");
++                      }
++                      break;
++              case 'Z':
++              case 'z':
++                      ptr = &remcomInBuffer[1];
++                      if (*ptr++ != bp_breakpoint)
++                              break;
++                      if (*(ptr++) != ',') {
++                              strcpy(remcomOutBuffer, "ERROR");
++                              break;
++                      }
++                      hexToInt(&ptr, &addr);
++                      if (remcomInBuffer[0] == 'Z')
++                              ret = set_break(addr);
++                      else
++                              ret = remove_break(addr);
++
++                      if (ret == 0) {
++                              strcpy(remcomOutBuffer, "OK");
++                      } else {
++                              strcpy(remcomOutBuffer, "ERROR");
++                      }
++                      break;
++
++              } /* switch */
++
++              /* reply to the request */
++              putpacket(remcomOutBuffer);
++      }
++}
++
++/* this function is used to set up exception handlers for tracing and
++   breakpoints */
++void set_debug_traps(void)
++{
++      int i = 0;
++      /*
++       * linux_debug_hook is defined in traps.c.  We store a pointer
++       * to our own exception handler into it.
++       */
++      linux_debug_hook = handle_exception ;
++
++      for (i=0; i<MAX_BREAKPOINTS; i++) {
++                      kgdb_break[i].bpt_addr = 0;
++                      kgdb_break[i].state = bp_disabled;
++      }
++
++      /*
++       * In case GDB is started before us, ack any packets (presumably
++       * "$?#xx") sitting there.  */
++      putDebugChar ('+');
++
++      initialized = 1;
++}
++
++/* This function will generate a breakpoint exception.  It is used at the
++   beginning of a program to sync up with a debugger and can be used
++   otherwise as a quick means to stop program execution and "break" into
++   the debugger. */
++
++void breakpoint(void)
++{
++      if (initialized)
++              BREAKPOINT();
++}
++
++#ifdef CONFIG_GDB_CONSOLE
++char  gdbconbuf[BUFMAX];
++
++void gdb_console_write(struct console *co, const char *s,
++                              unsigned count)
++{
++      int     i;
++      int     wcount;
++      char    *bufptr;
++
++      if (!gdb_initialized) {
++              return;
++      }
++      gdbconbuf[0] = 'O';
++      bufptr = gdbconbuf + 1;
++      while (count > 0) {
++              if ((count << 1) > (BUFMAX - 2)) {
++                      wcount = (BUFMAX - 2) >> 1;
++              } else {
++                      wcount = count;
++              }
++              count -= wcount;
++              for (i = 0; i < wcount; i++) {
++                      bufptr = pack_hex_byte(bufptr, s[i]);
++              }
++              *bufptr = '\0';
++              s += wcount;
++
++              putpacket(gdbconbuf);
++
++      }
++}
++#endif
++static int __init kgdb_opt_gdb(void)
++{
++      gdb_enter = 1;
++      return 1;
++}
++static int __init kgdb_opt_gdbttyS(char *str)
++{
++      gdb_ttyS = simple_strtoul(str,NULL,10);
++      return 1;
++}
++static int __init kgdb_opt_gdbbaud(char *str)
++{
++      gdb_baud = simple_strtoul(str,NULL,10);
++      return 1;
++}
++
++/*
++ * Sequence of these lines has to be maintained because gdb option is a prefix
++ * of the other two options
++ */
++
++__setup("gdbttyS=", kgdb_opt_gdbttyS);
++__setup("gdbbaud=", kgdb_opt_gdbbaud);
++__setup("gdb", kgdb_opt_gdb);
+--- linux-2.4.18-p4smp/arch/i386/kernel/Makefile~linux-2.4.18-14-kgdb-1.6      2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/Makefile 2003-07-09 13:15:23.000000000 -0600
+@@ -10,7 +10,15 @@
+ .S.o:
+       $(CC) $(AFLAGS) -traditional -c $< -o $*.o
+-all: kernel.o head.o init_task.o
++ifeq ($(CONFIG_X86_REMOTE_DEBUG),y)
++GDBSTART=gdbstart
++GDBCLEAN= -rm -f gdbstart /sbin/gdbstart
++else
++GDBSTART=
++GDBCLEAN=
++endif
++
++all: kernel.o head.o init_task.o $(GDBSTART)
+ O_TARGET := kernel.o
+@@ -33,6 +41,7 @@ endif
+ obj-$(CONFIG_MCA)             += mca.o
+ obj-$(CONFIG_E820_PROC)       += e820.o rpmhelper.o
+ obj-$(CONFIG_MTRR)            += mtrr.o
++obj-$(CONFIG_X86_REMOTE_DEBUG)        += gdbstub.o
+ obj-$(CONFIG_X86_MSR)         += msr.o
+ obj-$(CONFIG_X86_CPUID)               += cpuid.o
+ obj-$(CONFIG_MICROCODE)               += microcode.o
+@@ -51,4 +60,11 @@ obj-$(CONFIG_ABI)           += lcall7.o
+ obj-$(CONFIG_MCL_COREDUMP)    += crash.o
++gdbstart:     gdbstart.o
++              ${HOSTCC} -o gdbstart gdbstart.o
++gdbstart.o:   gdbstart.c
++              ${HOSTCC} -c -o gdbstart.o gdbstart.c
++
++kernelclean:  dummy
++
+ include $(TOPDIR)/Rules.make
+--- linux-2.4.18-p4smp/arch/i386/kernel/nmi.c~linux-2.4.18-14-kgdb-1.6 2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/nmi.c    2003-07-09 13:15:23.000000000 -0600
+@@ -25,6 +25,20 @@
+ #include <asm/mtrr.h>
+ #include <asm/mpspec.h>
++#ifdef CONFIG_X86_REMOTE_DEBUG
++extern gdb_debug_hook * linux_debug_hook;
++#define       CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)            \
++   {                                                                  \
++      if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) \
++      {                                                               \
++              (*linux_debug_hook)(trapnr, signr, error_code, regs) ;  \
++              after;                                                  \
++      }                                                               \
++    }
++#else
++#define       CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)    
++#endif
++
+ unsigned int nmi_watchdog = NMI_NONE;
+ static unsigned int nmi_hz = HZ;
+ unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
+@@ -347,7 +361,20 @@ void nmi_watchdog_tick (struct pt_regs *
+                 x86_do_profile(regs->eip);
+       sum = irq_stat[cpu].apic_timer_irqs;
++#ifdef CONFIG_X86_REMOTE_DEBUG
++      if (kgdb_lock) {
++
++              /*
++               * The machine is in kgdb, hold this cpu if already
++               * not held.
++               */
++              if (!procindebug[cpu] && kgdb_lock != (cpu + 1)) {
++                      gdb_wait(regs);
++              }
++              alert_counter[cpu] = 0;
++      } else
++#endif
+       if (last_irq_sums[cpu] == sum) {
+               /*
+                * Ayiee, looks like this CPU is stuck ...
+@@ -355,6 +382,9 @@ void nmi_watchdog_tick (struct pt_regs *
+                */
+               alert_counter[cpu]++;
+               if (alert_counter[cpu] == 5*nmi_hz) {
++
++                      CHK_REMOTE_DEBUG(2,SIGSEGV,0,regs,)
++
+                       spin_lock(&nmi_print_lock);
+                       /*
+                        * We are in trouble anyway, lets at least try
+--- linux-2.4.18-p4smp/arch/i386/kernel/signal.c~linux-2.4.18-14-kgdb-1.6      2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/signal.c 2003-07-09 13:15:23.000000000 -0600
+@@ -701,7 +701,8 @@ int do_signal(struct pt_regs *regs, sigs
+                * have been cleared if the watchpoint triggered
+                * inside the kernel.
+                */
+-              __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
++              if (current->thread.debugreg[7])
++                      __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
+               /* Whee!  Actually deliver the signal.  */
+               handle_signal(signr, ka, &info, oldset, regs);
+--- linux-2.4.18-p4smp/arch/i386/kernel/traps.c~linux-2.4.18-14-kgdb-1.6       2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/kernel/traps.c  2003-07-09 13:19:30.000000000 -0600
+@@ -49,12 +49,33 @@
+ #endif
+ #include <linux/irq.h>
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#include <linux/gdb.h>
++#endif
+ #include <linux/module.h>
+ #ifdef CONFIG_MCL_COREDUMP
+ #include <linux/crash.h>
+ #endif
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#include <linux/gdb.h>
++#endif
++
++#ifdef CONFIG_X86_REMOTE_DEBUG
++gdb_debug_hook * linux_debug_hook;
++#define       CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)            \
++    {                                                                 \
++      if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) \
++      {                                                               \
++              (*linux_debug_hook)(trapnr, signr, error_code, regs) ;  \
++              after;                                                  \
++      }                                                               \
++    }
++#else
++#define       CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)    
++#endif
++
+ asmlinkage int system_call(void);
+ asmlinkage void lcall7(void);
+ asmlinkage void lcall27(void);
+@@ -409,6 +430,7 @@ void die(const char * str, struct pt_reg
+       bust_spinlocks(1);
+       handle_BUG(regs);
+       printk("%s: %04lx\n", str, err & 0xffff);
++      CHK_REMOTE_DEBUG(1,SIGTRAP,err,regs,)
+       show_registers(regs);
+       if (netdump_func)
+               netdump_func(regs);
+@@ -479,6 +501,7 @@ static void inline do_trap(int trapnr, i
+ #define DO_ERROR(trapnr, signr, str, name) \
+ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+ { \
++      CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\
+       do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ }
+@@ -496,7 +519,10 @@ asmlinkage void do_##name(struct pt_regs
+ #define DO_VM86_ERROR(trapnr, signr, str, name) \
+ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+ { \
++      CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,goto skip_trap)\
+       do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
++skip_trap: \
++      return; \
+ }
+ #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+@@ -548,6 +574,7 @@ gp_in_kernel:
+                       regs->eip = fixup;
+                       return;
+               }
++              CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,)
+               die("general protection fault", regs, error_code);
+       }
+ }
+@@ -659,7 +686,7 @@ asmlinkage void do_debug(struct pt_regs 
+       __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
+       /* If the user set TF, it's simplest to clear it right away. */
+-      if ((eip >=PAGE_OFFSET) && (regs->eflags & TF_MASK))
++      if ((eip >=PAGE_OFFSET) && (regs->eflags & TF_MASK) && !kgdb_step)
+               goto clear_TF;
+       /* Mask out spurious debug traps due to lazy DR7 setting */
+@@ -675,7 +702,7 @@ asmlinkage void do_debug(struct pt_regs 
+       tsk->thread.debugreg[6] = condition;
+       /* Mask out spurious TF errors due to lazy TF clearing */
+-      if (condition & DR_STEP) {
++      if (condition & DR_STEP && !kgdb_step) {
+               /*
+                * The TF error should be masked out only if the current
+                * process is not traced and if the TRAP flag has been set
+@@ -698,11 +725,13 @@ asmlinkage void do_debug(struct pt_regs 
+       info.si_errno = 0;
+       info.si_code = TRAP_BRKPT;
+       
+-      /* If this is a kernel mode trap, save the user PC on entry to 
+-       * the kernel, that's what the debugger can make sense of.
+-       */
+-      info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : 
+-                                              (void *)regs->eip;
++
++      /* If this is a kernel mode trap, we need to reset db7 to allow us
++       * to continue sanely */
++      if ((regs->xcs & 3) == 0)
++              goto clear_dr7;
++
++      info.si_addr = (void *)regs->eip;
+       force_sig_info(SIGTRAP, &info, tsk);
+       /* Disable additional traps. They'll be re-enabled when
+@@ -712,6 +741,7 @@ clear_dr7:
+       __asm__("movl %0,%%db7"
+               : /* no output */
+               : "r" (0));
++      CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,)
+       return;
+ debug_vm86:
+--- linux-2.4.18-p4smp/arch/i386/Makefile~linux-2.4.18-14-kgdb-1.6     2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/Makefile        2003-07-09 13:15:23.000000000 -0600
+@@ -105,6 +105,11 @@ arch/i386/mm: dummy
+       $(MAKE) linuxsubdirs SUBDIRS=arch/i386/mm
+ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
++ifeq ($(CONFIG_X86_REMOTE_DEBUG),y)
++CLEANKERNEL = $(MAKE) -C arch/$(ARCH)/kernel kernelclean
++else
++CLEANKERNEL =
++endif
+ vmlinux: arch/i386/vmlinux.lds
+@@ -140,6 +145,7 @@ install: vmlinux
+ archclean:
+       @$(MAKEBOOT) clean
++      @$(CLEANKERNEL)
+ archmrproper:
+--- linux-2.4.18-p4smp/arch/i386/mm/fault.c~linux-2.4.18-14-kgdb-1.6   2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/arch/i386/mm/fault.c      2003-07-09 13:15:23.000000000 -0600
+@@ -2,6 +2,11 @@
+  *  linux/arch/i386/mm/fault.c
+  *
+  *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Change History
++ *
++ *    Tigran Aivazian <tigran@sco.com>        Remote debugging support.
++ *
+  */
+ #include <linux/signal.h>
+@@ -19,6 +24,9 @@
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h>            /* For unblank_screen() */
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#include <linux/gdb.h>
++#endif
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -183,6 +191,15 @@ asmlinkage void do_page_fault(struct pt_
+       if (in_interrupt() || !mm)
+               goto no_context;
++#ifdef CONFIG_X86_REMOTE_DEBUG
++      if (kgdb_memerr_expected) {
++              if (linux_debug_hook != (gdb_debug_hook *) NULL) {
++                      (*linux_debug_hook)(14, SIGSEGV, error_code, regs) ;
++                      return;            /* return w/modified regs */
++              }
++      }
++#endif
++
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, address);
+@@ -301,6 +318,19 @@ no_context:
+               return;
+       }
++#ifdef CONFIG_X86_REMOTE_DEBUG
++      if (kgdb_memerr_expected) {
++              if (linux_debug_hook != (gdb_debug_hook *) NULL) {
++                      (*linux_debug_hook)(14, SIGSEGV, error_code, regs);
++                      return; /* Return with modified registers */
++              }
++      } else {
++              if (linux_debug_hook != (gdb_debug_hook *) NULL) {
++                      (*linux_debug_hook)(14, SIGSEGV, error_code, regs);
++              }
++      }
++#endif
++
+ /*
+  * Oops. The kernel tried to access some bad page. We'll have to
+  * terminate things with extreme prejudice.
+@@ -308,6 +338,7 @@ no_context:
+       bust_spinlocks(1);
++
+       if (address < PAGE_SIZE)
+               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+       else
+--- linux-2.4.18-p4smp/Documentation/Configure.help~linux-2.4.18-14-kgdb-1.6   2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/Documentation/Configure.help      2003-07-09 13:15:23.000000000 -0600
+@@ -20274,6 +20274,29 @@ CONFIG_SGIWD93_SCSI
+   If you have a Western Digital WD93 SCSI controller on
+   an SGI MIPS system, say Y.  Otherwise, say N.
++KGDB: Remote (serial) kernel debugging with gdb
++CONFIG_X86_REMOTE_DEBUG
++  If you say Y here, it will be possible to remotely debug the x86
++  kernel using gdb. This enlarges your kernel image disk size by
++  several megabytes and requires a machine with more than 16 MB,
++  better 32 MB RAM to avoid excessive linking time. 
++  To use this feature you need to perform some basic setup described
++  briefly in Documentation/i386/gdb-serial.txt.
++  This is only useful for kernel hackers. If unsure, say N.
++
++KGDB: Thread analysis
++CONFIG_KGDB_THREAD
++  With thread analysis enabled, gdb can talk to kgdb stub to list
++  threads and to get stack trace for a thread. This option also enables
++  some code which helps gdb get exact status of thread. Thread analysis
++  adds some overhead to schedule and down functions. You can disable this
++  option if you do not want to compromise on speed.
++
++KGDB: Console messagegs through gdb
++CONFIG_GDB_CONSOLE
++  If you say Y here, console messages will appear through gdb.
++  Other consoles such as tty or ttyS will continue to work as usual.
++  
+ Magic System Request Key support
+ CONFIG_MAGIC_SYSRQ
+   If you say Y here, you will have some control over the system even
+--- /dev/null  2003-01-30 03:24:37.000000000 -0700
++++ linux-2.4.18-p4smp-braam/Documentation/i386/gdb-serial.txt 2003-07-09 13:15:23.000000000 -0600
+@@ -0,0 +1,386 @@
++Version
++=======
++
++This version of the gdbstub package was developed and tested on
++kernel version 2.3.48.  It will not install on a 2.2 kernel.  It may
++not work on earlier versions of 2.3 kernels.  It is possible that
++it will continue to work on later versions of 2.3 and then
++versions of 2.4 (I hope).
++
++
++Debugging Setup
++===============
++
++Designate one machine as the "development" machine.  This is the
++machine on which you run your compiles and which has your source
++code for the kernel.  Designate a second machine as the "target"
++machine.  This is the machine that will run your experimental
++kernel.
++
++The two machines will be connected together via a serial line out
++one or the other of the COM ports of the PC.  You will need a modem
++eliminator and the appropriate cables.
++
++On the DEVELOPMENT machine you need to apply the patch for the gdb
++hooks.  You have probably already done that if you are reading this
++file.
++
++On your DEVELOPMENT machine, go to your kernel source directory and
++do "make menuconfig".  Go down to the kernel hacking menu item and
++open it up.  Enable the kernel gdb stub code by selecting that item.
++
++Save and exit the menuconfig program.  Then do "make clean" and
++"make bzImage" (or whatever target you want to make).  This gets
++the kernel compiled with the "-g" option set -- necessary for
++debugging.
++
++You have just built the kernel on your DEVELOPMENT machine that you
++intend to run on our TARGET machine.
++
++To install this new kernel, use the following installation procedure.
++Remember, you are on the DEVELOPMENT machine patching the kernel source
++for the kernel that you intend to run on the TARGET machine.
++
++Copy this kernel to your target machine using your usual procedures.
++I usually arrange to copy development:/usr/src/linux/arch/i386/boot/zImage
++to /vmlinuz on the TARGET machine via a LAN based NFS access.  That is,
++I run the cp command on the target and copy from the development machine
++via the LAN.  Run Lilo on the new kernel on the target machine so that it
++will boot!  Then boot the kernel on the target machine.
++
++There is an utility program named "gdbstart" in the
++development:/usr/src/linux/arch/i386/kernel directory.
++You should copy this program over to your target machine, probably into
++/sbin.  This utility program is run on the target machine to
++activate the kernel hooks for the debugger.  It is invoked as follows:
++
++    gdbstart [-s speed] [-t tty-dev]
++    defaults:  /dev/ttyS0 with speed unmodified by gdbstart
++
++Don't run the program just yet.  We'll get to that in a bit.
++
++Decide on which tty port you want the machines to communicate, then
++cable them up back-to-back using the null modem.  COM1 is /dev/ttyS0
++and COM2 is /dev/ttyS1.
++
++On the DEVELOPMENT machine, create a file called .gdbinit in the
++directory /usr/src/linux.  An example .gdbinit file looks like this:
++
++define rmt
++set remotebaud 38400
++target remote /dev/ttyS0
++end
++
++Assuming that you added my gdbinit stuff to your .gdbinit, edit .gdbinit
++and find the section that looks like this:
++
++      define rmt
++      set remotebaud 38400
++      target remote /dev/ttyS0
++      end
++
++Change the "target" definition so that it specifies the tty port that
++you intend to use.  Change the "remotebaud" definition to match the
++data rate that you are going to use for the com line.
++
++On the TARGET machine I find it helpful to create shell script file
++named "debug" in the root home directory with the following contents:
++
++      gdbstart -s 38400 -t /dev/ttyS0 <<EOF
++      <blank line>
++      EOF
++
++This runs the gdbstart program and gives it the carriage return that
++it prompts for.  This sets the data rate from the target machine's side.
++
++You are now ready to try it out.
++
++On your TARGET machine, freshly rebooted with your gdbstub-equipped
++kernel, type "debug" in the root home directory.  The system will appear
++to hang with some messages on the screen from the debug stub.  What
++it is doing is waiting for contact from the development machine.
++
++On your DEVELOPMENT machine, cd /usr/src/linux and enter "gdb vmlinux".
++When gdb gets the symbols loaded and prompts you, enter "rmt" (that's
++the macro from the .gdbinit file that you just edited).  If everything
++is working correctly you should see gdb print out a few lines indicating
++that a breakpoint has been taken.  It will actually show a line of
++code in the target kernel inside the gdbstub activation code.
++
++The gdb interaction should look something like this:
++
++    linux-dev:/usr/src/linux# gdb vmlinux
++    GDB is free software and you are welcome to distribute copies of it
++     under certain conditions; type "show copying" to see the conditions.
++    There is absolutely no warranty for GDB; type "show warranty" for details.
++    GDB 4.15.1 (i486-slackware-linux), 
++    Copyright 1995 Free Software Foundation, Inc...
++    (gdb) rmt
++    breakpoint () at i386-stub.c:750
++    750     }
++    (gdb) 
++
++
++You can now use whatever gdb commands you like to set breakpoints.
++Enter "continue" to start your target machine executing again.  At this
++point the target system will run at full speed until it encounters
++your breakpoint or gets a segment violation in the kernel, or whatever.
++
++
++Triggering gdbstub at Kernel Boot Time
++======================================
++
++The gdbstub patch now has the ability for gdb to connect to the kernel during
++bootup (as opposed to waiting for the system to come all the way up and then
++running the gdbstart program on the target machine).  This new functionality was
++added by Scott Foehner <sfoehner@engr.sgi.com> at SGI.
++
++To force a kernel that has been compiled with gdbstub to pause during the boot
++process and wait for a connection from gdb, the paramter "gdb" should be passed
++to the kernel. This can be done by typing "gdb" after the name of the kernel
++on the LILO command line.  The patch defaults to use ttyS1 at a baud rate of
++38400. These parameters can be changed by using "gdbttyS=<port number>" and
++"gdbbaud=<baud rate>" on the command line.
++
++Example:
++
++LILO boot: linux gdb gdbttyS=1 gdbbaud=38400
++
++Note that this command is entered on the TARGET machine as it is booting
++the kernel that was compiled on the DEVELOPMENT machine.
++
++An alternate approach is to place a line in the /etc/lilo.conf file on
++your TARGET machine.  Under the heading for the kernel that you intend
++to boot, place a line that looks like this:
++
++    append = "gdb gdbttyS=1 gdbbaud=38400"
++
++This will cause the kernel to enter the gdbstub automatically at boot
++time.
++
++BE SURE to run "lilo" after changing the /etc/lilo.conf file.
++
++
++The "gdbstart" Program
++=====================
++
++This utility program is used to set up the com port and data rate
++for the connection from the target system to the development system.
++Its usage has been described above.
++
++This version of the patch uses the same tty ioctl for kernel versions
++2.0.30 onwards.  Thus, the gdbstart utility does not need to be re-compiled
++to install the patch in a later version of the kernel.  The ioctl added
++to the kernel for this purpose is far enough "off the end" of existing
++ioctls (as of 2.1.120) that it should not interfere with any new kernel
++tty ioctls for quite some time (famous last words).
++
++The source for the gdbstart program resides in the arch/i386/kernel directory.
++
++
++Debugging hints
++===============
++
++You can break into the target machine at any time from the development
++machine by typing ^C.  If the target machine has interrupts enabled
++this will stop it in the kernel and enter the debugger.
++
++There is unfortunately no way of breaking into the kernel if it is
++in a loop with interrupts disabled, so if this happens to you then
++you need to place exploratory breakpoints or printk's into the kernel
++to find out where it is looping.
++
++There is a copy of an e-mail in the kgdb distribution directory which
++describes how to create an NMI on an ISA bus machine using a paper
++clip.  I have a sophisticated version of this made by wiring a push
++button switch into a PC104/ISA bus adapter card.  The adapter card
++nicely furnishes wire wrap pins for all the ISA bus signals.
++
++When you are done debugging the kernel on the target machine it is
++a good idea to leave it in a running state.  This makes reboots
++faster, bypassing the fsck.  So do a gdb "continue" as the last gdb
++command if this is possible.  To terminate gdb itself on the development
++machine and leave the target machine running, type ^Z to suspend gdb
++and then kill it with "kill %1" or something similar.
++
++If gdbstub Does Not Work
++========================
++
++If it doesn't work, you will have to troubleshoot it.  Do the easy things
++first like double checking your cabling and data rates.  You might
++try some non-kernel based programs to see if the back-to-back connection
++works properly.  Just something simple like cat /etc/hosts >/dev/ttyS0
++on one machine and cat /dev/ttyS0 on the other will tell you if you
++can send data from one machine to the other.  There is no point in tearing
++out your hair in the kernel if the line doesn't work.
++
++All of the real action takes place in the file
++/usr/src/linux/arch/i386/kernel/gdbstub.c.  That is the code on the target
++machine that interacts with gdb on the development machine.  In gdb you can
++turn on a debug switch with the following command:
++
++      set remotedebug
++
++This will print out the protocol messages that gdb is exchanging with
++the target machine.
++
++Another place to look is /usr/src/linux/drivers/char/gdbserial.c
++That is the code that talks to the serial port on the target side.
++There might be a problem there.
++
++If you are really desperate you can use printk debugging in the
++gdbstub code in the target kernel until you get it working.  In particular,
++there is a global variable in /usr/src/linux/arch/i386/kernel/gdbstub.c
++named "remote_debug".  Compile your kernel with this set to 1, rather
++than 0 and the debug stub will print out lots of stuff as it does
++what it does.
++
++
++Debugging Loadable Modules
++==========================
++
++This technique comes courtesy of Edouard Parmelan
++<Edouard.Parmelan@quadratec.fr>
++
++When you run gdb, enter the command
++
++source gdbinit-modules
++
++This will read in a file of gdb macros that was installed in your
++kernel source directory with kgdb was installed.  This file implements
++the following commands:
++
++mod-list
++    Lists the loaded modules in the form <module-address> <module-name>
++
++mod-print-symbols <module-address>
++    Prints all the symbols in the indicated module.
++
++mod-add-symbols <module-address> <object-file-path-name>
++    Loads the symbols from the object file and associates them
++    with the indicated module.
++
++After you have loaded the module that you want to debug, use the command
++mod-list to find the <module-address> of your module.  Then use that
++address in the mod-add-symbols command to load your module's symbols.
++From that point onward you can debug your module as if it were a part
++of the kernel.
++
++The file gdbinit-modules also contains a command named mod-add-lis as
++an example of how to construct a command of your own to load your
++favorite module.  The idea is to "can" the pathname of the module
++in the command so you don't have to type so much.
++
++Threads
++=======
++
++Each process in a target machine is seen as a gdb thread. gdb thread related
++commands (info threads, thread n) can be used. 
++
++ia-32 hardware breakpoints
++==========================
++
++gdb stub contains support for hardware breakpoints using debugging features
++of ia-32(x86) processors. These breakpoints do not need code modification.
++They use debugging registers. 4 hardware breakpoints are available in ia-32
++processors.
++
++Each hardware breakpoint can be of one of the following three types.
++1. Execution breakpoint - An Execution breakpoint is triggered when code at the
++      breakpoint address is executed.
++
++      As limited number of hardware breakpoints are available, it is advisable
++      to use software breakpoints ( break command ) instead of execution
++      hardware breakpoints, unless modification of code is to be avoided.
++
++2. Write breakpoint - A write breakpoint is triggered when memory location at the
++      breakpoint address is written.
++
++      A write or can be placed for data of variable length. Length of a write
++      breakpoint indicates length of the datatype to be watched. Length is 1
++      for 1 byte data , 2 for 2 byte data, 3 for 4 byte data.
++
++3. Access breakpoint - An access breakpoint is triggered when memory location at
++      the breakpoint address is either read or written.
++
++      Access breakpoints also have lengths similar to write breakpoints.
++
++IO breakpoints in ia-32 are not supported.
++
++Since gdb stub at present does not use the protocol used by gdb for hardware
++breakpoints, hardware breakpoints are accessed through gdb macros. gdb macros
++for hardware breakpoints are described below.
++
++hwebrk        - Places an execution breakpoint
++      hwebrk breakpointno address
++hwwbrk        - Places a write breakpoint
++      hwwbrk breakpointno length address
++hwabrk        - Places an access breakpoint
++      hwabrk breakpointno length address
++hwrmbrk       - Removes a breakpoint
++      hwrmbrk breakpointno
++exinfo        - Tells whether a software or hardware breakpoint has occured.
++      Prints number of the hardware breakpoint if a hardware breakpoint has
++      occured.
++
++Arguments required by these commands are as follows
++breakpointno  - 0 to 3
++length                - 1 to 3
++address               - Memory location in hex digits ( without 0x ) e.g c015e9bc
++
++MP support
++==========
++
++When a breakpoint occurs or user issues a break ( Ctrl + C ) to gdb client,
++all the processors are forced to enter the debugger. Current thread
++corresponds to the thread running on the processor where breakpoint occured.
++Threads running on other processor(s) appear similar to other non running
++threads in the 'info threads' output.
++
++ia-32 hardware debugging registers on all processors are set to same values.
++Hence any hardware breakpoints may occur on any processor.
++
++gdb troubleshooting
++===================
++
++1. gdb hangs
++Kill it. restart gdb. Connect to target machine.
++
++2. gdb cannot connect to target machine (after killing a gdb and restarting
++another)
++If the target machine was not inside debugger when you killed gdb, gdb cannot
++connect because the target machine won't respond.
++In this case echo "Ctrl+C"(ascii 3) in the serial line.
++e.g. echo -e "\003" > /dev/ttyS1 
++This forces that target machine into debugger after which you can connect.
++
++3. gdb cannot connect even after echoing Ctrl+C into serial line
++Try changing serial line settings min to 1 and time to 0
++e.g. stty min 1 time 0 < /dev/ttyS1
++Try echoing again
++
++check serial line speed and set it to correct value if required
++e.g. stty ispeed 115200 ospeed 115200 < /dev/ttyS1
++
++Final Items
++===========
++
++I picked up this code from Dave Grothe and enhanced it.
++
++If you make some really cool modification to this stuff, or if you 
++fix a bug, please let me know.
++
++Amit S. Kale
++<akale@veritas.com>
++
++(First kgdb by David Grothe <dave@gcom.com>)
++
++(modified by Tigran Aivazian <tigran@sco.com>)
++    Putting gdbstub into the kernel config menu.
++
++(modified by Scott Foehner <sfoehner@engr.sgi.com>)
++    Hooks for entering gdbstub at boot time.
++
++(modified by Amit S. Kale <akale@veritas.com>)
++    Threads, ia-32 hw debugging, mp support, console support,
++    nmi watchdog handling.
+--- /dev/null  2003-01-30 03:24:37.000000000 -0700
++++ linux-2.4.18-p4smp-braam/drivers/char/gdbserial.c  2003-07-09 13:15:23.000000000 -0600
+@@ -0,0 +1,280 @@
++/*
++ * Serial interface GDB stub
++ *
++ * Written (hacked together) by David Grothe (dave@gcom.com)
++ *
++ * Modified by Scott Foehner (sfoehner@engr.sgi.com) to allow connect
++ * on boot-up
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial.h>
++#include <linux/serial_reg.h>
++#include <linux/serialP.h>
++#include <linux/config.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/termios.h>
++#include <linux/gdb.h>
++
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/segment.h>
++#include <asm/bitops.h>
++#include <asm/system.h>
++#include <asm/irq.h>
++#include <asm/atomic.h>
++
++#undef        PRNT                            /* define for debug printing */
++
++#define       GDB_BUF_SIZE    512             /* power of 2, please */
++
++static char   gdb_buf[GDB_BUF_SIZE] ;
++static int    gdb_buf_in_inx ;
++static atomic_t       gdb_buf_in_cnt ;
++static int    gdb_buf_out_inx ;
++
++extern void   set_debug_traps(void) ;         /* GDB routine */
++extern struct serial_state *  gdb_serial_setup(int ttyS, int baud);
++extern void   shutdown_for_gdb(struct async_struct * info) ;
++                                              /* in serial.c */
++
++int gdb_irq;
++int gdb_port;
++int gdb_ttyS = 1;     /* Default: ttyS1 */
++int gdb_baud = 38400; 
++int gdb_enter = 0;    /* Default: do not do gdb_hook on boot */
++int gdb_initialized = 0;
++
++static int initialized = -1;
++
++/*
++ * Get a byte from the hardware data buffer and return it
++ */
++static int    read_data_bfr(void)
++{
++    if (inb(gdb_port + UART_LSR) & UART_LSR_DR)
++      return(inb(gdb_port + UART_RX));
++
++    return( -1 ) ;
++
++} /* read_data_bfr */
++
++
++/*
++ * Get a char if available, return -1 if nothing available.
++ * Empty the receive buffer first, then look at the interface hardware.
++ */
++static int    read_char(void)
++{
++    if (atomic_read(&gdb_buf_in_cnt) != 0)    /* intr routine has q'd chars */
++    {
++      int             chr ;
++
++      chr = gdb_buf[gdb_buf_out_inx++] ;
++      gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ;
++      atomic_dec(&gdb_buf_in_cnt) ;
++      return(chr) ;
++    }
++
++    return(read_data_bfr()) ; /* read from hardware */
++
++} /* read_char */
++
++/*
++ * Wait until the interface can accept a char, then write it.
++ */
++static void   write_char(int chr)
++{
++    while ( !(inb(gdb_port + UART_LSR) & UART_LSR_THRE) ) ;
++
++    outb(chr, gdb_port+UART_TX);
++
++} /* write_char */
++
++/*
++ * This is the receiver interrupt routine for the GDB stub.
++ * It will receive a limited number of characters of input
++ * from the gdb  host machine and save them up in a buffer.
++ *
++ * When the gdb stub routine getDebugChar() is called it
++ * draws characters out of the buffer until it is empty and
++ * then reads directly from the serial port.
++ *
++ * We do not attempt to write chars from the interrupt routine
++ * since the stubs do all of that via putDebugChar() which
++ * writes one byte after waiting for the interface to become
++ * ready.
++ *
++ * The debug stubs like to run with interrupts disabled since,
++ * after all, they run as a consequence of a breakpoint in
++ * the kernel.
++ *
++ * Perhaps someone who knows more about the tty driver than I
++ * care to learn can make this work for any low level serial
++ * driver.
++ */
++static void gdb_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++    int                        chr ;
++    int                        iir ;
++
++    do
++    {
++      chr = read_data_bfr() ;
++      iir = inb(gdb_port + UART_IIR) ;
++#ifdef PRNT
++      printk("gdb_interrupt: chr=%02x '%c'  after read iir=%02x\n", chr,
++              chr > ' ' && chr < 0x7F ? chr : ' ', iir) ;
++#endif
++      if (chr < 0) continue ;
++
++        if (chr == 3)                   /* Ctrl-C means remote interrupt */
++        {
++            breakpoint();
++            continue ;
++        }
++
++      if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE)
++      {                               /* buffer overflow, clear it */
++          gdb_buf_in_inx = 0 ;
++          atomic_set(&gdb_buf_in_cnt, 0) ;
++          gdb_buf_out_inx = 0 ;
++          break ;
++      }
++
++      gdb_buf[gdb_buf_in_inx++] = chr ;
++      gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ;
++      atomic_inc(&gdb_buf_in_cnt) ;
++    }
++    while (iir & UART_IIR_RDI);
++
++} /* gdb_interrupt */
++
++/*
++ * Just a NULL routine for testing.
++ */
++void gdb_null(void)
++{
++} /* gdb_null */
++
++
++int     gdb_hook(void)
++{
++    int         retval ;
++    struct serial_state *ser;
++
++#ifdef CONFIG_SMP
++    if (smp_num_cpus > KGDB_MAX_NO_CPUS) { 
++        printk("kgdb: too manu cpus. Cannot enable debugger with more than 8 cpus\n");
++      return (-1);
++    }
++#endif
++
++    /*
++     * Call first time just to get the ser ptr
++     */
++    if((ser = gdb_serial_setup(gdb_ttyS, gdb_baud)) == 0) {
++        printk ("gdb_serial_setup() error");
++        return(-1);
++    }
++
++    gdb_port = ser->port;
++    gdb_irq = ser->irq;
++
++    if (ser->info != NULL)
++    {
++      shutdown_for_gdb(ser->info) ;
++      /*
++       * Call second time to do the setup now that we have
++       * shut down the previous user of the interface.
++       */
++      gdb_serial_setup(gdb_ttyS, gdb_baud) ;
++    }
++
++    retval = request_irq(gdb_irq,
++                         gdb_interrupt,
++                         SA_INTERRUPT,
++                         "GDB-stub", NULL);
++    if (retval == 0)
++        initialized = 1;
++    else
++    {
++        initialized = 0;
++      printk("gdb_hook: request_irq(irq=%d) failed: %d\n", gdb_irq, retval);
++    }
++
++    /*
++     * Call GDB routine to setup the exception vectors for the debugger
++     */
++    set_debug_traps() ;
++
++    /*
++     * Call the breakpoint() routine in GDB to start the debugging
++     * session.
++     */
++    printk("Waiting for connection from remote gdb... ") ;
++    breakpoint() ;
++    gdb_null() ;
++
++    printk("Connected.\n");
++
++    gdb_initialized = 1;
++    return(0) ;
++
++} /* gdb_hook_interrupt2 */
++
++/*
++ * getDebugChar
++ *
++ * This is a GDB stub routine.  It waits for a character from the
++ * serial interface and then returns it.  If there is no serial
++ * interface connection then it returns a bogus value which will
++ * almost certainly cause the system to hang.
++ */
++int   getDebugChar(void)
++{
++    volatile int      chr ;
++
++#ifdef PRNT
++    printk("getDebugChar: ") ;
++#endif
++
++    while ( (chr = read_char()) < 0 ) ;
++
++
++#ifdef PRNT
++    printk("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ') ;
++#endif
++    return(chr) ;
++
++} /* getDebugChar */
++
++/*
++ * putDebugChar
++ *
++ * This is a GDB stub routine.  It waits until the interface is ready
++ * to transmit a char and then sends it.  If there is no serial
++ * interface connection then it simply returns to its caller, having
++ * pretended to send the char.
++ */
++void  putDebugChar(int chr)
++{
++#ifdef PRNT
++    printk("putDebugChar: chr=%02x '%c'\n", chr,
++              chr > ' ' && chr < 0x7F ? chr : ' ') ;
++#endif
++
++    write_char(chr) ; /* this routine will wait */
++
++} /* putDebugChar */
++
+--- linux-2.4.18-p4smp/drivers/char/Makefile~linux-2.4.18-14-kgdb-1.6  2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/drivers/char/Makefile     2003-07-09 13:15:23.000000000 -0600
+@@ -142,6 +142,7 @@ ifeq ($(CONFIG_DUMMY_KEYB),y)
+   KEYBD = dummy_keyb.o
+ endif
++obj-$(CONFIG_X86_REMOTE_DEBUG) += gdbserial.o
+ obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
+ obj-$(CONFIG_SERIAL) += $(SERIAL)
+ obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
+--- linux-2.4.18-p4smp/drivers/char/serial.c~linux-2.4.18-14-kgdb-1.6  2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/drivers/char/serial.c     2003-07-09 13:15:23.000000000 -0600
+@@ -4,6 +4,7 @@
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
+  *            1998, 1999  Theodore Ts'o
++ *  Copyright (C) 2000 VERITAS Software Corporation.
+  *
+  *  Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92.  Now
+  *  much more extensible to support other serial cards based on the
+@@ -34,6 +35,10 @@
+  *  4/98: Added changes to support the ARM architecture proposed by
+  *      Russell King
+  *
++ *  3/99: Added TIOCGDB for remote debugging with gdb if compiled with
++ *        CONFIG_X86_REMOTE_DEBUG
++ *      Tigran Aivazian
++ *
+  *  5/99: Updated to include support for the XR16C850 and ST16C654
+  *        uarts.  Stuart MacDonald <stuartm@connecttech.com>
+  *
+@@ -66,6 +71,8 @@
+  *        to waiting processes
+  *        Sapan Bhatia <sapan@corewars.org>
+  *
++ * 10/00: added console support for kgdb. Amit Kale <akale@veritas.com>
++ *
+  */
+ static char *serial_version = "5.05c";
+@@ -215,7 +222,7 @@ static char *serial_revdate = "2001-07-0
+ #include <asm/uaccess.h>
+ #endif
+ #include <linux/delay.h>
+-#ifdef CONFIG_SERIAL_CONSOLE
++#if defined(CONFIG_SERIAL_CONSOLE) || defined (CONFIG_GDB_CONSOLE)
+ #include <linux/console.h>
+ #endif
+ #ifdef ENABLE_SERIAL_PCI
+@@ -235,6 +242,9 @@ static char *serial_revdate = "2001-07-0
+ #if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */
+ #include "serial_compat.h"
+ #endif
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#include <linux/gdb.h>
++#endif
+ #include <asm/system.h>
+ #include <asm/io.h>
+@@ -1586,6 +1596,12 @@ static void shutdown(struct async_struct
+       spin_unlock_irqrestore( &info->irq_spinlock, flags);
+ }
++#ifdef CONFIG_X86_REMOTE_DEBUG
++void shutdown_for_gdb(struct async_struct * info)
++{
++    shutdown(info) ;
++}
++#endif
+ #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+ static int baud_table[] = {
+@@ -2698,6 +2714,12 @@ static int rs_ioctl(struct tty_struct *t
+                       printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
+                       return 0;
++#ifdef CONFIG_X86_REMOTE_DEBUG
++              case TIOCGDB:
++                      gdb_ttyS = MINOR(tty->device) & 0x03F ;
++                      gdb_baud = tty_get_baud_rate(tty) ;
++                      return gdb_hook();
++#endif
+               default:
+                       return -ENOIOCTLCMD;
+               }
+@@ -6043,6 +6065,129 @@ void __init serial_console_init(void)
+ #endif
+ /*
++ * ------------------------------------------------------------
++ * Serial GDB driver (most in gdbserial.c)
++ * ------------------------------------------------------------
++ */
++
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#ifdef CONFIG_GDB_CONSOLE
++static struct console gdbcons = {
++      name: "gdb",
++      write: gdb_console_write,
++      flags: CON_PRINTBUFFER | CON_ENABLED,
++      index: -1,
++};
++#endif
++
++
++/* 
++ *  Takes:
++ *    ttyS - integer specifying which serial port to use for debugging
++ *    baud - baud rate of specified serial port
++ *  Returns:
++ *    port for use by the gdb serial driver
++ */
++struct serial_state *
++gdb_serial_setup(int ttyS, int baud)
++{
++        struct serial_state *ser;
++        unsigned cval;
++        int     bits = 8;
++        int     parity = 'n';
++        int     cflag = CREAD | HUPCL | CLOCAL;
++        int     quot = 0;
++
++        /*
++         *      Now construct a cflag setting.
++         */
++        switch(baud) {
++                case 1200:
++                        cflag |= B1200;
++                        break;
++                case 2400:
++                        cflag |= B2400;
++                        break;
++                case 4800:
++                        cflag |= B4800;
++                        break;
++                case 19200:
++                        cflag |= B19200;
++                        break;
++                case 38400:
++                        cflag |= B38400;
++                        break;
++                case 57600:
++                        cflag |= B57600;
++                        break;
++                case 115200:
++                        cflag |= B115200;
++                        break;
++                case 9600:
++                default:
++                        cflag |= B9600;
++                        break;
++        }
++        switch(bits) {
++                case 7:
++                        cflag |= CS7;
++                        break;
++                default:
++                case 8:
++                        cflag |= CS8;
++                        break;
++        }
++        switch(parity) {
++                case 'o': case 'O':
++                        cflag |= PARODD;
++                        break;
++                case 'e': case 'E':
++                        cflag |= PARENB;
++                        break;
++        }
++
++        /*
++         *      Divisor, bytesize and parity
++         */
++
++        ser = rs_table + ttyS;
++      ser->flags &= ~ASYNC_BOOT_AUTOCONF;
++        quot = ser->baud_base / baud;
++        cval = cflag & (CSIZE | CSTOPB);
++        cval >>= 4;
++        if (cflag & PARENB)
++                cval |= UART_LCR_PARITY;
++        if (!(cflag & PARODD))
++                cval |= UART_LCR_EPAR;
++
++        /*
++         *      Disable UART interrupts, set DTR and RTS high
++         *      and set speed.
++         */
++      cval = 0x3;
++        outb(cval | UART_LCR_DLAB, ser->port + UART_LCR);       /* set DLAB */
++        outb(quot & 0xff, ser->port + UART_DLL);         /* LS of divisor */
++        outb(quot >> 8, ser->port + UART_DLM);           /* MS of divisor */
++        outb(cval, ser->port + UART_LCR);                /* reset DLAB */
++        outb(UART_IER_RDI, ser->port + UART_IER);        /* turn on interrupts*/
++        outb(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);
++
++        /*
++         *      If we read 0xff from the LSR, there is no UART here.
++         */
++        if (inb(ser->port + UART_LSR) == 0xff)
++                return 0;
++        return ser;
++}
++#ifdef CONFIG_GDB_CONSOLE
++void __init gdb_console_init(void)
++{
++      register_console(&gdbcons);
++}
++#endif
++#endif /* CONFIG_X86_REMOTE_DEBUG */
++
++/*
+   Local variables:
+   compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h   -DEXPORT_SYMTAB -c serial.c"
+   End:
+--- linux-2.4.18-p4smp/drivers/char/tty_io.c~linux-2.4.18-14-kgdb-1.6  2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/drivers/char/tty_io.c     2003-07-09 13:15:23.000000000 -0600
+@@ -90,6 +90,9 @@
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/smp_lock.h>
++#ifdef CONFIG_GDB_CONSOLE
++#include <linux/gdb.h>
++#endif
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -2233,6 +2236,9 @@ void __init console_init(void)
+ #ifdef CONFIG_AU1000_SERIAL_CONSOLE
+       au1000_serial_console_init();
+ #endif
++#ifdef CONFIG_GDB_CONSOLE
++      gdb_console_init();
++#endif
+ #ifdef CONFIG_SERIAL_CONSOLE
+ #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+       console_8xx_init();
+--- linux-2.4.18-p4smp/include/asm-i386/ioctls.h~linux-2.4.18-14-kgdb-1.6      2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/include/asm-i386/ioctls.h 2003-07-09 13:15:23.000000000 -0600
+@@ -68,6 +68,7 @@
+ #define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+ #define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+ #define FIOQSIZE      0x5460
++#define TIOCGDB         0x547F  /* enable GDB stub mode on this tty */
+ /* Used for packet mode */
+ #define TIOCPKT_DATA           0
+--- linux-2.4.18-p4smp/include/asm-i386/page.h~linux-2.4.18-14-kgdb-1.6        2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/include/asm-i386/page.h   2003-07-09 13:15:23.000000000 -0600
+@@ -95,6 +95,9 @@ typedef struct { unsigned long pgprot; }
+  * undefined" opcode for parsing in the trap handler.
+  */
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#define BUG() KGDB_ASSERT("BUG", 0)
++#else
+ #if 1 /* Set to zero for a slightly smaller kernel */
+ #define BUG()                         \
+  __asm__ __volatile__(        "ud2\n"         \
+@@ -104,6 +107,7 @@ typedef struct { unsigned long pgprot; }
+ #else
+ #define BUG() __asm__ __volatile__("ud2\n")
+ #endif
++#endif
+ #define PAGE_BUG(page) do { \
+       BUG(); \
+--- linux-2.4.18-p4smp/include/asm-i386/processor.h~linux-2.4.18-14-kgdb-1.6   2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/include/asm-i386/processor.h      2003-07-09 13:20:27.000000000 -0600
+@@ -390,6 +390,9 @@ struct thread_struct {
+ /* IO permissions */
+       int             ioperm;
+       unsigned long   io_bitmap[IO_BITMAP_SIZE+1];
++#ifdef CONFIG_X86_REMOTE_DEBUG
++      struct pt_regs *kgdbregs;
++#endif
+ /* performance counters */
+       struct vperfctr *perfctr;
+ };
+--- linux-2.4.18-p4smp/include/linux/dcache.h~linux-2.4.18-14-kgdb-1.6 2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/include/linux/dcache.h    2003-07-09 13:15:23.000000000 -0600
+@@ -4,6 +4,7 @@
+ #ifdef __KERNEL__
+ #include <asm/atomic.h>
++#include <linux/gdb.h>
+ #include <linux/mount.h>
+ /*
+--- /dev/null  2003-01-30 03:24:37.000000000 -0700
++++ linux-2.4.18-p4smp-braam/include/linux/gdb.h       2003-07-09 13:15:23.000000000 -0600
+@@ -0,0 +1,63 @@
++#ifndef _GDB_H_
++#define _GDB_H_
++
++/*
++ * Copyright (C) 2001 Amit S. Kale
++ */
++
++/* gdb locks */
++#define KGDB_MAX_NO_CPUS 8
++
++extern int gdb_enter; /* 1 = enter debugger on boot */
++extern int gdb_ttyS;
++extern int gdb_baud;
++extern int gdb_initialized;
++
++extern int gdb_hook(void);
++extern void breakpoint(void);
++
++typedef int     gdb_debug_hook(int trapno,
++                               int signo,
++                               int err_code,
++                               struct pt_regs *regs);
++extern gdb_debug_hook  *linux_debug_hook;
++
++extern volatile unsigned kgdb_lock;
++
++extern volatile int kgdb_memerr_expected;
++
++extern volatile unsigned kgdb_step;
++
++struct console;
++void gdb_console_write(struct console *co, const char *s,
++                              unsigned count);
++void gdb_console_init(void);
++
++extern volatile int procindebug[KGDB_MAX_NO_CPUS];
++
++void gdb_wait(struct pt_regs *regs);
++
++#define KGDB_ASSERT(message, condition)       do {                    \
++      if (!(condition)) {                                     \
++              printk("kgdb assertion failed: %s\n", message); \
++              asm ("int $0x3");                               \
++      }                                                       \
++} while (0)
++
++#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
++
++#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
++
++#define KA_VALID_KPTR(ptr)  (!(ptr) ||        \
++             ((void *)(ptr) >= (void *)PAGE_OFFSET &&  \
++             (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
++
++#define KA_VALID_PTRORERR(errptr) (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
++
++#ifndef CONFIG_SMP
++#define KA_HELD_GKL() 1
++#else
++#define KA_HELD_GKL() (current->lock_depth >= 0)
++#endif
++
++#endif /* _GDB_H_ */
+--- linux-2.4.18-p4smp/include/linux/sched.h~linux-2.4.18-14-kgdb-1.6  2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/include/linux/sched.h     2003-07-09 13:15:23.000000000 -0600
+@@ -159,7 +159,9 @@ extern int set_user(uid_t new_ruid, int 
+ #define       MAX_SCHEDULE_TIMEOUT    LONG_MAX
+ extern signed long FASTCALL(schedule_timeout(signed long timeout));
+-asmlinkage void schedule(void);
++asmlinkage void do_schedule(void);
++asmlinkage void kern_schedule(void);
++asmlinkage void kern_do_schedule(struct pt_regs);
+ extern int schedule_task(struct tq_struct *task);
+ extern void flush_scheduled_tasks(void);
+@@ -1025,6 +1027,15 @@ static inline int need_resched(void)
+       return unlikely(current->need_resched);
+ }
++static inline void schedule(void)
++{
++#ifdef CONFIG_KGDB_THREAD
++      kern_schedule();
++#else
++      do_schedule();
++#endif
++}
++
+ #endif /* __KERNEL__ */
+ #endif
+--- linux-2.4.18-p4smp/init/main.c~linux-2.4.18-14-kgdb-1.6    2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/init/main.c       2003-07-09 13:15:23.000000000 -0600
+@@ -57,6 +57,10 @@
+ #include <linux/nubus.h>
+ #endif
++#ifdef CONFIG_X86_REMOTE_DEBUG
++#include <linux/gdb.h>
++#endif
++
+ #ifdef CONFIG_ISAPNP
+ #include <linux/isapnp.h>
+ #endif
+@@ -476,6 +480,11 @@ asmlinkage void __init start_kernel(void
+        *      make syscalls (and thus be locked).
+        */
+       smp_init();
++#ifdef CONFIG_X86_REMOTE_DEBUG
++      if (gdb_enter) {
++              gdb_hook();             /* right at boot time */
++      }
++#endif
+       /* Do the rest non-__init'ed, we're now alive */
+       rest_init();
+--- linux-2.4.18-p4smp/kernel/ksyms.c~linux-2.4.18-14-kgdb-1.6 2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/kernel/ksyms.c    2003-07-09 13:15:23.000000000 -0600
+@@ -478,7 +478,10 @@ EXPORT_SYMBOL(sleep_on);
+ EXPORT_SYMBOL(sleep_on_timeout);
+ EXPORT_SYMBOL(interruptible_sleep_on);
+ EXPORT_SYMBOL(interruptible_sleep_on_timeout);
+-EXPORT_SYMBOL(schedule);
++EXPORT_SYMBOL(do_schedule);
++#ifdef CONFIG_KGDB_THREAD
++EXPORT_SYMBOL(kern_schedule);
++#endif
+ EXPORT_SYMBOL(schedule_timeout);
+ EXPORT_SYMBOL(sys_sched_yield);
+ EXPORT_SYMBOL(set_user_nice);
+--- linux-2.4.18-p4smp/kernel/sched.c~linux-2.4.18-14-kgdb-1.6 2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/kernel/sched.c    2003-07-09 13:15:23.000000000 -0600
+@@ -797,7 +797,7 @@ void scheduling_functions_start_here(voi
+ /*
+  * 'schedule()' is the main scheduler function.
+  */
+-asmlinkage void schedule(void)
++asmlinkage void do_schedule(void)
+ {
+       task_t *prev, *next;
+       runqueue_t *rq;
+@@ -879,6 +879,22 @@ switch_tasks:
+               goto need_resched;
+ }
++asmlinkage void user_schedule(void)
++{
++#ifdef CONFIG_KGDB_THREAD
++      current->thread.kgdbregs = NULL;
++#endif
++      do_schedule();
++}
++
++#ifdef CONFIG_KGDB_THREAD
++asmlinkage void kern_do_schedule(struct pt_regs regs)
++{
++      current->thread.kgdbregs = &regs;
++      do_schedule();
++}
++#endif
++
+ /*
+  * The core wakeup function.  Non-exclusive wakeups (nr_exclusive == 0) just
+  * wake everything up.  If it's an exclusive wakeup (nr_exclusive == small +ve
+--- linux-2.4.18-p4smp/Makefile~linux-2.4.18-14-kgdb-1.6       2003-07-09 13:14:53.000000000 -0600
++++ linux-2.4.18-p4smp-braam/Makefile  2003-07-09 13:15:23.000000000 -0600
+@@ -101,9 +101,13 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH)
+ CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
+         -fno-strict-aliasing -fno-common
++ifeq ($(CONFIG_X86_REMOTE_DEBUG),y)
++CFLAGS += -g
++else
+ ifndef CONFIG_FRAME_POINTER
+ CFLAGS += -fomit-frame-pointer
+ endif
++endif
+ AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
+ ifeq ($(CONFIG_MCL_COREDUMP),y)
+
+_
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch
new file mode 100644 (file)
index 0000000..55046ea
--- /dev/null
@@ -0,0 +1,1793 @@
+ fs/dcache.c               |   19 ++
+ fs/exec.c                 |   15 +-
+ fs/namei.c                |  321 ++++++++++++++++++++++++++++++++++++++--------
+ fs/namespace.c            |   28 +++-
+ fs/open.c                 |  123 +++++++++++++++--
+ fs/proc/base.c            |    3 
+ fs/stat.c                 |   50 ++++---
+ include/linux/dcache.h    |   54 +++++++
+ include/linux/fs.h        |   30 ++++
+ include/linux/fs_struct.h |    4 
+ kernel/exit.c             |    3 
+ kernel/fork.c             |    3 
+ kernel/ksyms.c            |    1 
+ 13 files changed, 552 insertions(+), 102 deletions(-)
+
+--- linux/fs/exec.c~vfs_intent-2.4.20-hp       Sat Jul 12 14:04:49 2003
++++ linux-mmonroe/fs/exec.c    Sat Jul 12 14:05:24 2003
+@@ -116,8 +116,9 @@ asmlinkage long sys_uselib(const char * 
+       struct file * file;
+       struct nameidata nd;
+       int error;
++      struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY };
+-      error = user_path_walk(library, &nd);
++      error = user_path_walk_it(library, &nd, &it);
+       if (error)
+               goto out;
+@@ -129,7 +130,8 @@ asmlinkage long sys_uselib(const char * 
+       if (error)
+               goto exit;
+-      file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
++      file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
++      intent_release(&it);
+       error = PTR_ERR(file);
+       if (IS_ERR(file))
+               goto out;
+@@ -372,8 +374,9 @@ struct file *open_exec(const char *name)
+       struct inode *inode;
+       struct file *file;
+       int err = 0;
++      struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY };
+-      err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
++      err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
+       file = ERR_PTR(err);
+       if (!err) {
+               inode = nd.dentry->d_inode;
+@@ -385,7 +388,8 @@ struct file *open_exec(const char *name)
+                               err = -EACCES;
+                       file = ERR_PTR(err);
+                       if (!err) {
+-                              file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
++                              file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
++                              intent_release(&it);
+                               if (!IS_ERR(file)) {
+                                       err = deny_write_access(file);
+                                       if (err) {
+@@ -397,6 +401,7 @@ out:
+                               return file;
+                       }
+               }
++              intent_release(&it);
+               path_release(&nd);
+       }
+       goto out;
+@@ -1128,7 +1133,7 @@ int do_coredump(long signr, struct pt_re
+               goto close_fail;
+       if (!file->f_op->write)
+               goto close_fail;
+-      if (do_truncate(file->f_dentry, 0) != 0)
++      if (do_truncate(file->f_dentry, 0, 0) != 0)
+               goto close_fail;
+       retval = binfmt->core_dump(signr, regs, file);
+--- linux/fs/dcache.c~vfs_intent-2.4.20-hp     Thu Nov 28 15:53:15 2002
++++ linux-mmonroe/fs/dcache.c  Sat Jul 12 14:05:24 2003
+@@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry)
+               spin_unlock(&dcache_lock);
+               return 0;
+       }
++
++      /* network invalidation by Lustre */
++      if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
++              spin_unlock(&dcache_lock);
++              return 0;
++      }
++
+       /*
+        * Check whether to do a partial shrink_dcache
+        * to get rid of unused child entries.
+@@ -830,13 +837,19 @@ void d_delete(struct dentry * dentry)
+  * Adds a dentry to the hash according to its name.
+  */
+  
+-void d_rehash(struct dentry * entry)
++void __d_rehash(struct dentry * entry, int lock)
+ {
+       struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
+       if (!list_empty(&entry->d_hash)) BUG();
+-      spin_lock(&dcache_lock);
++      if (lock) spin_lock(&dcache_lock);
+       list_add(&entry->d_hash, list);
+-      spin_unlock(&dcache_lock);
++      if (lock) spin_unlock(&dcache_lock);
++}
++EXPORT_SYMBOL(__d_rehash);
++
++void d_rehash(struct dentry * entry)
++{
++      __d_rehash(entry, 1);
+ }
+ #define do_switch(x,y) do { \
+--- linux/fs/namespace.c~vfs_intent-2.4.20-hp  Thu Nov 28 15:53:15 2002
++++ linux-mmonroe/fs/namespace.c       Sat Jul 12 14:05:24 2003
+@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount *
+ {
+       old_nd->dentry = mnt->mnt_mountpoint;
+       old_nd->mnt = mnt->mnt_parent;
++      UNPIN(old_nd->dentry, old_nd->mnt, 1);
+       mnt->mnt_parent = mnt;
+       mnt->mnt_mountpoint = mnt->mnt_root;
+       list_del_init(&mnt->mnt_child);
+@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount *
+ {
+       mnt->mnt_parent = mntget(nd->mnt);
+       mnt->mnt_mountpoint = dget(nd->dentry);
++      PIN(nd->dentry, nd->mnt, 1);
+       list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
+       list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+       nd->dentry->d_mounted++;
+@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata 
+ {
+       struct nameidata old_nd;
+       struct vfsmount *mnt = NULL;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       int err = mount_is_safe(nd);
+       if (err)
+               return err;
+       if (!old_name || !*old_name)
+               return -EINVAL;
+-      err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
+-      if (err)
++      err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it);
++      if (err) {
++              intent_release(&it);
+               return err;
++      }
+       down_write(&current->namespace->sem);
+       err = -EINVAL;
+@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata 
+       }
+       up_write(&current->namespace->sem);
++      intent_release(&it);
+       path_release(&old_nd);
+       return err;
+ }
+@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di
+                 unsigned long flags, void *data_page)
+ {
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       int retval = 0;
+       int mnt_flags = 0;
+@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di
+       flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
+       /* ... and get the mountpoint */
+-      retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
+-      if (retval)
++      retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
++      if (retval) {
++              intent_release(&it);
+               return retval;
+-
++      }
+       if (flags & MS_REMOUNT)
+               retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
+                                   data_page);
+@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di
+       else
+               retval = do_add_mount(&nd, type_page, flags, mnt_flags,
+                                     dev_name, data_page);
++
++      intent_release(&it);
+       path_release(&nd);
+       return retval;
+ }
+@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha
+ {
+       struct vfsmount *tmp;
+       struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
++      struct lookup_intent new_it = { .it_op = IT_GETATTR };
++      struct lookup_intent old_it = { .it_op = IT_GETATTR };
+       int error;
+       if (!capable(CAP_SYS_ADMIN))
+@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha
+       lock_kernel();
+-      error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
++      error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it);
+       if (error)
+               goto out0;
+       error = -EINVAL;
+       if (!check_mnt(new_nd.mnt))
+               goto out1;
+-      error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
++      error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it);
+       if (error)
+               goto out1;
+@@ -970,8 +982,10 @@ out2:
+       up(&old_nd.dentry->d_inode->i_zombie);
+       up_write(&current->namespace->sem);
+       path_release(&user_nd);
++      intent_release(&old_it);
+       path_release(&old_nd);
+ out1:
++      intent_release(&new_it);
+       path_release(&new_nd);
+ out0:
+       unlock_kernel();
+--- linux/fs/namei.c~vfs_intent-2.4.20-hp      Sat Jul 12 14:04:48 2003
++++ linux-mmonroe/fs/namei.c   Sat Jul 12 14:08:01 2003
+@@ -94,6 +94,13 @@
+  * XEmacs seems to be relying on it...
+  */
++void intent_release(struct lookup_intent *it)
++{
++      if (it && it->it_op_release)
++              it->it_op_release(it);
++
++}
++
+ /* In order to reduce some races, while at the same time doing additional
+  * checking and hopefully speeding things up, we copy filenames to the
+  * kernel data space before using them..
+@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
+  * Internal lookup() using the new generic dcache.
+  * SMP-safe
+  */
+-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
++static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
++                                  int flags, struct lookup_intent *it)
+ {
+       struct dentry * dentry = d_lookup(parent, name);
++      if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
++              if (!dentry->d_op->d_revalidate_it(dentry, flags, it) &&
++                  !d_invalidate(dentry)) {
++                      dput(dentry);
++                      dentry = NULL;
++              }
++              return dentry;
++      } else
+       if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
+               if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
+                       dput(dentry);
+@@ -281,11 +297,14 @@ static struct dentry * cached_lookup(str
+  * make sure that nobody added the entry to the dcache in the meantime..
+  * SMP-safe
+  */
+-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
++static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
++                                int flags, struct lookup_intent *it)
+ {
+       struct dentry * result;
+       struct inode *dir = parent->d_inode;
++again:
++
+       down(&dir->i_sem);
+       /*
+        * First re-do the cached lookup just in case it was created
+@@ -300,6 +319,9 @@ static struct dentry * real_lookup(struc
+               result = ERR_PTR(-ENOMEM);
+               if (dentry) {
+                       lock_kernel();
++                      if (dir->i_op->lookup_it)
++                              result = dir->i_op->lookup_it(dir, dentry, it, flags);
++                      else
+                       result = dir->i_op->lookup(dir, dentry);
+                       unlock_kernel();
+                       if (result)
+@@ -321,6 +343,12 @@ static struct dentry * real_lookup(struc
+                       dput(result);
+                       result = ERR_PTR(-ENOENT);
+               }
++      } else if (result->d_op && result->d_op->d_revalidate_it) {
++              if (!result->d_op->d_revalidate_it(result, flags, it) &&
++                  !d_invalidate(result)) {
++                      dput(result);
++                      goto again;
++              }
+       }
+       return result;
+ }
+@@ -332,7 +360,8 @@ static struct dentry * real_lookup(struc
+  * Without that kind of total limit, nasty chains of consecutive
+  * symlinks can cause almost arbitrarily long lookups. 
+  */
+-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
++static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
++                               struct lookup_intent *it)
+ {
+       int err;
+       if (current->link_count >= 5)
+@@ -346,10 +375,18 @@ static inline int do_follow_link(struct 
+       current->link_count++;
+       current->total_link_count++;
+       UPDATE_ATIME(dentry->d_inode);
++      nd->it = it;
+       err = dentry->d_inode->i_op->follow_link(dentry, nd);
++      if (!err && it != NULL && !(it->it_int_flags & IT_FL_FOLLOWED)) {
++              /* vfs_follow_link was never called */
++              intent_release(it);
++              path_release(nd);
++              err = -ENOLINK;
++      }
+       current->link_count--;
+       return err;
+ loop:
++      intent_release(it);
+       path_release(nd);
+       return -ELOOP;
+ }
+@@ -379,15 +416,26 @@ int follow_up(struct vfsmount **mnt, str
+       return __follow_up(mnt, dentry);
+ }
+-static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
++static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry,
++                              struct lookup_intent *it)
+ {
+       struct vfsmount *mounted;
+       spin_lock(&dcache_lock);
+       mounted = lookup_mnt(*mnt, *dentry);
+       if (mounted) {
++              int opc = 0, mode = 0;
+               *mnt = mntget(mounted);
+               spin_unlock(&dcache_lock);
++              if (it) {
++                      opc = it->it_op;
++                      mode = it->it_mode;
++              }
++              intent_release(it);
++              if (it) {
++                      it->it_op = opc;
++                      it->it_mode = mode;
++              }
+               dput(*dentry);
+               mntput(mounted->mnt_parent);
+               *dentry = dget(mounted->mnt_root);
+@@ -399,7 +447,7 @@ static inline int __follow_down(struct v
+ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
+ {
+-      return __follow_down(mnt,dentry);
++      return __follow_down(mnt,dentry,NULL);
+ }
+  
+ static inline void follow_dotdot(struct nameidata *nd)
+@@ -435,7 +483,7 @@ static inline void follow_dotdot(struct 
+               mntput(nd->mnt);
+               nd->mnt = parent;
+       }
+-      while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry))
++      while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry, NULL))
+               ;
+ }
+@@ -447,7 +495,8 @@ static inline void follow_dotdot(struct 
+  *
+  * We expect 'base' to be positive and a directory.
+  */
+-int link_path_walk(const char * name, struct nameidata *nd)
++int link_path_walk_it(const char *name, struct nameidata *nd,
++                    struct lookup_intent *it)
+ {
+       struct dentry *dentry;
+       struct inode *inode;
+@@ -520,15 +569,15 @@ int link_path_walk(const char * name, st
+                               break;
+               }
+               /* This does the actual lookups.. */
+-              dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
++              dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
+               if (!dentry) {
+-                      dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
++                      dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
+                       err = PTR_ERR(dentry);
+                       if (IS_ERR(dentry))
+                               break;
+               }
+               /* Check mountpoints.. */
+-              while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
++              while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, NULL))
+                       ;
+               err = -ENOENT;
+@@ -540,7 +589,7 @@ int link_path_walk(const char * name, st
+                       goto out_dput;
+               if (inode->i_op->follow_link) {
+-                      err = do_follow_link(dentry, nd);
++                      err = do_follow_link(dentry, nd, NULL);
+                       dput(dentry);
+                       if (err)
+                               goto return_err;
+@@ -556,7 +605,7 @@ int link_path_walk(const char * name, st
+                       nd->dentry = dentry;
+               }
+               err = -ENOTDIR; 
+-              if (!inode->i_op->lookup)
++              if (!inode->i_op->lookup && !inode->i_op->lookup_it)
+                       break;
+               continue;
+               /* here ends the main loop */
+@@ -583,19 +632,19 @@ last_component:
+                       if (err < 0)
+                               break;
+               }
+-              dentry = cached_lookup(nd->dentry, &this, 0);
++              dentry = cached_lookup(nd->dentry, &this, 0, it);
+               if (!dentry) {
+-                      dentry = real_lookup(nd->dentry, &this, 0);
++                      dentry = real_lookup(nd->dentry, &this, 0, it);
+                       err = PTR_ERR(dentry);
+                       if (IS_ERR(dentry))
+                               break;
+               }
+-              while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
++              while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, it))
+                       ;
+               inode = dentry->d_inode;
+               if ((lookup_flags & LOOKUP_FOLLOW)
+                   && inode && inode->i_op && inode->i_op->follow_link) {
+-                      err = do_follow_link(dentry, nd);
++                      err = do_follow_link(dentry, nd, it);
+                       dput(dentry);
+                       if (err)
+                               goto return_err;
+@@ -609,7 +658,8 @@ last_component:
+                       goto no_inode;
+               if (lookup_flags & LOOKUP_DIRECTORY) {
+                       err = -ENOTDIR; 
+-                      if (!inode->i_op || !inode->i_op->lookup)
++                      if (!inode->i_op ||
++                          (!inode->i_op->lookup && !inode->i_op->lookup_it))
+                               break;
+               }
+               goto return_base;
+@@ -633,6 +683,23 @@ return_reval:
+                * Check the cached dentry for staleness.
+                */
+               dentry = nd->dentry;
++      revalidate_again:
++              if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
++                      err = -ESTALE;
++                      if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) {
++                              struct dentry *new;
++                              err = permission(dentry->d_parent->d_inode,
++                                               MAY_EXEC);
++                              if (err)
++                                      break;
++                              new = real_lookup(dentry->d_parent,
++                                                &dentry->d_name, 0, NULL);
++                              d_invalidate(dentry);
++                              dput(dentry);
++                              dentry = new;
++                              goto revalidate_again;
++                      }
++              } else
+               if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
+                       err = -ESTALE;
+                       if (!dentry->d_op->d_revalidate(dentry, 0)) {
+@@ -646,15 +713,28 @@ out_dput:
+               dput(dentry);
+               break;
+       }
++      if (err)
++              intent_release(it);
+       path_release(nd);
+ return_err:
+       return err;
+ }
++int link_path_walk(const char * name, struct nameidata *nd)
++{
++      return link_path_walk_it(name, nd, NULL);
++}
++
++int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
++{
++      current->total_link_count = 0;
++      return link_path_walk_it(name, nd, it);
++}
++
+ int path_walk(const char * name, struct nameidata *nd)
+ {
+       current->total_link_count = 0;
+-      return link_path_walk(name, nd);
++      return link_path_walk_it(name, nd, NULL);
+ }
+ /* SMP-safe */
+@@ -739,6 +819,17 @@ walk_init_root(const char *name, struct 
+ }
+ /* SMP-safe */
++int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
++                 struct lookup_intent *it)
++{
++      int error = 0;
++      if (path_init(path, flags, nd))
++              error = path_walk_it(path, nd, it);
++      return error;
++}
++
++
++/* SMP-safe */
+ int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
+ {
+       int error = 0;
+@@ -753,6 +844,7 @@ int path_init(const char *name, unsigned
+ {
+       nd->last_type = LAST_ROOT; /* if there are only slashes... */
+       nd->flags = flags;
++      nd->it = NULL;
+       if (*name=='/')
+               return walk_init_root(name,nd);
+       read_lock(&current->fs->lock);
+@@ -767,7 +859,8 @@ int path_init(const char *name, unsigned
+  * needs parent already locked. Doesn't follow mounts.
+  * SMP-safe.
+  */
+-struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
++struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
++                             struct lookup_intent *it)
+ {
+       struct dentry * dentry;
+       struct inode *inode;
+@@ -790,13 +883,16 @@ struct dentry * lookup_hash(struct qstr 
+                       goto out;
+       }
+-      dentry = cached_lookup(base, name, 0);
++      dentry = cached_lookup(base, name, 0, it);
+       if (!dentry) {
+               struct dentry *new = d_alloc(base, name);
+               dentry = ERR_PTR(-ENOMEM);
+               if (!new)
+                       goto out;
+               lock_kernel();
++              if (inode->i_op->lookup_it)
++                      dentry = inode->i_op->lookup_it(inode, new, it, 0);
++              else
+               dentry = inode->i_op->lookup(inode, new);
+               unlock_kernel();
+               if (!dentry)
+@@ -808,6 +904,12 @@ out:
+       return dentry;
+ }
++struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
++{
++      return lookup_hash_it(name, base, NULL);
++}
++
++
+ /* SMP-safe */
+ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
+ {
+@@ -829,7 +931,7 @@ struct dentry * lookup_one_len(const cha
+       }
+       this.hash = end_name_hash(hash);
+-      return lookup_hash(&this, base);
++      return lookup_hash_it(&this, base, NULL);
+ access:
+       return ERR_PTR(-EACCES);
+ }
+@@ -860,6 +962,23 @@ int __user_walk(const char *name, unsign
+       return err;
+ }
++int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
++                 struct lookup_intent *it)
++{
++      char *tmp;
++      int err;
++
++      tmp = getname(name);
++      err = PTR_ERR(tmp);
++      if (!IS_ERR(tmp)) {
++              err = 0;
++              if (path_init(tmp, flags, nd))
++                      err = path_walk_it(tmp, nd, it);
++              putname(tmp);
++      }
++      return err;
++}
++
+ /*
+  * It's inline, so penalty for filesystems that don't use sticky bit is
+  * minimal.
+@@ -955,7 +1074,8 @@ static inline int lookup_flags(unsigned 
+       return retval;
+ }
+-int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
++static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode,
++                       struct lookup_intent *it)
+ {
+       int error;
+@@ -968,12 +1088,15 @@ int vfs_create(struct inode *dir, struct
+               goto exit_lock;
+       error = -EACCES;        /* shouldn't it be ENOSYS? */
+-      if (!dir->i_op || !dir->i_op->create)
++      if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it))
+               goto exit_lock;
+       DQUOT_INIT(dir);
+       lock_kernel();
+-      error = dir->i_op->create(dir, dentry, mode);
++      if (dir->i_op->create_it)
++              error = dir->i_op->create_it(dir, dentry, mode, it);
++      else
++              error = dir->i_op->create(dir, dentry, mode);
+       unlock_kernel();
+ exit_lock:
+       up(&dir->i_zombie);
+@@ -982,6 +1105,11 @@ exit_lock:
+       return error;
+ }
++int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
++{
++      return vfs_create_it(dir, dentry, mode, NULL);
++}
++
+ /*
+  *    open_namei()
+  *
+@@ -996,7 +1124,8 @@ exit_lock:
+  * for symlinks (where the permissions are checked later).
+  * SMP-safe
+  */
+-int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
++int open_namei_it(const char *pathname, int flag, int mode,
++                struct nameidata *nd, struct lookup_intent *it)
+ {
+       int acc_mode, error = 0;
+       struct inode *inode;
+@@ -1010,7 +1139,7 @@ int open_namei(const char * pathname, in
+        * The simplest case - just a plain lookup.
+        */
+       if (!(flag & O_CREAT)) {
+-              error = path_lookup(pathname, lookup_flags(flag), nd);
++              error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
+               if (error)
+                       return error;
+               dentry = nd->dentry;
+@@ -1020,6 +1149,10 @@ int open_namei(const char * pathname, in
+       /*
+        * Create - we need to know the parent.
+        */
++      if (it) {
++              it->it_mode = mode;
++              it->it_op |= IT_CREAT;
++      }
+       error = path_lookup(pathname, LOOKUP_PARENT, nd);
+       if (error)
+               return error;
+@@ -1035,7 +1168,7 @@ int open_namei(const char * pathname, in
+       dir = nd->dentry;
+       down(&dir->d_inode->i_sem);
+-      dentry = lookup_hash(&nd->last, nd->dentry);
++      dentry = lookup_hash_it(&nd->last, nd->dentry, it);
+ do_last:
+       error = PTR_ERR(dentry);
+@@ -1044,11 +1177,12 @@ do_last:
+               goto exit;
+       }
++      it->it_mode = mode;
+       /* Negative dentry, just create the file */
+       if (!dentry->d_inode) {
+               if (!IS_POSIXACL(dir->d_inode))
+                       mode &= ~current->fs->umask;
+-              error = vfs_create(dir->d_inode, dentry, mode);
++              error = vfs_create_it(dir->d_inode, dentry, mode, it);
+               up(&dir->d_inode->i_sem);
+               dput(nd->dentry);
+               nd->dentry = dentry;
+@@ -1073,7 +1207,7 @@ do_last:
+               error = -ELOOP;
+               if (flag & O_NOFOLLOW)
+                       goto exit_dput;
+-              while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
++              while (__follow_down(&nd->mnt,&dentry,it) && d_mountpoint(dentry));
+       }
+       error = -ENOENT;
+       if (!dentry->d_inode)
+@@ -1152,7 +1286,7 @@ ok:
+               if (!error) {
+                       DQUOT_INIT(inode);
+                       
+-                      error = do_truncate(dentry, 0);
++                      error = do_truncate(dentry, 0, 1);
+               }
+               put_write_access(inode);
+               if (error)
+@@ -1164,8 +1298,10 @@ ok:
+       return 0;
+ exit_dput:
++      intent_release(it);
+       dput(dentry);
+ exit:
++      intent_release(it);
+       path_release(nd);
+       return error;
+@@ -1184,7 +1320,16 @@ do_link:
+        * are done. Procfs-like symlinks just set LAST_BIND.
+        */
+       UPDATE_ATIME(dentry->d_inode);
++      nd->it = it;
+       error = dentry->d_inode->i_op->follow_link(dentry, nd);
++      if (error) {
++              intent_release(it);
++      } else if (it != NULL && !(it->it_int_flags & IT_FL_FOLLOWED)) {
++              /* vfs_follow_link was never called */
++              intent_release(it);
++              path_release(nd);
++              error = -ENOLINK;
++      }
+       dput(dentry);
+       if (error)
+               return error;
+@@ -1206,13 +1351,20 @@ do_link:
+       }
+       dir = nd->dentry;
+       down(&dir->d_inode->i_sem);
+-      dentry = lookup_hash(&nd->last, nd->dentry);
++      dentry = lookup_hash_it(&nd->last, nd->dentry, it);
+       putname(nd->last.name);
+       goto do_last;
+ }
++int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
++{
++      return open_namei_it(pathname, flag, mode, nd, NULL);
++}
++
++
+ /* SMP-safe */
+-static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
++static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
++                                  struct lookup_intent *it)
+ {
+       struct dentry *dentry;
+@@ -1220,7 +1372,7 @@ static struct dentry *lookup_create(stru
+       dentry = ERR_PTR(-EEXIST);
+       if (nd->last_type != LAST_NORM)
+               goto fail;
+-      dentry = lookup_hash(&nd->last, nd->dentry);
++      dentry = lookup_hash_it(&nd->last, nd->dentry, it);
+       if (IS_ERR(dentry))
+               goto fail;
+       if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
+@@ -1276,7 +1428,16 @@ asmlinkage long sys_mknod(const char * f
+       error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
+-      dentry = lookup_create(&nd, 0);
++
++      if (nd.dentry->d_inode->i_op->mknod_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->mknod_raw(&nd, mode, dev);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto out2;
++      }
++
++      dentry = lookup_create(&nd, 0, NULL);
+       error = PTR_ERR(dentry);
+       if (!IS_POSIXACL(nd.dentry->d_inode))
+@@ -1298,6 +1459,7 @@ asmlinkage long sys_mknod(const char * f
+               dput(dentry);
+       }
+       up(&nd.dentry->d_inode->i_sem);
++out2:
+       path_release(&nd);
+ out:
+       putname(tmp);
+@@ -1345,7 +1507,14 @@ asmlinkage long sys_mkdir(const char * p
+               error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
+-              dentry = lookup_create(&nd, 1);
++              if (nd.dentry->d_inode->i_op->mkdir_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->mkdir_raw(&nd, mode);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
++              dentry = lookup_create(&nd, 1, NULL);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+                       if (!IS_POSIXACL(nd.dentry->d_inode))
+@@ -1354,6 +1523,7 @@ asmlinkage long sys_mkdir(const char * p
+                       dput(dentry);
+               }
+               up(&nd.dentry->d_inode->i_sem);
++out2:
+               path_release(&nd);
+ out:
+               putname(tmp);
+@@ -1454,8 +1624,16 @@ asmlinkage long sys_rmdir(const char * p
+                       error = -EBUSY;
+                       goto exit1;
+       }
++      if (nd.dentry->d_inode->i_op->rmdir_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++              error = op->rmdir_raw(&nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit1;
++      }
+       down(&nd.dentry->d_inode->i_sem);
+-      dentry = lookup_hash(&nd.last, nd.dentry);
++      dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
+       error = PTR_ERR(dentry);
+       if (!IS_ERR(dentry)) {
+               error = vfs_rmdir(nd.dentry->d_inode, dentry);
+@@ -1513,8 +1691,15 @@ asmlinkage long sys_unlink(const char * 
+       error = -EISDIR;
+       if (nd.last_type != LAST_NORM)
+               goto exit1;
++      if (nd.dentry->d_inode->i_op->unlink_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++              error = op->unlink_raw(&nd);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit1;
++      }
+       down(&nd.dentry->d_inode->i_sem);
+-      dentry = lookup_hash(&nd.last, nd.dentry);
++      dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
+       error = PTR_ERR(dentry);
+       if (!IS_ERR(dentry)) {
+               /* Why not before? Because we want correct error value */
+@@ -1581,15 +1766,23 @@ asmlinkage long sys_symlink(const char *
+               error = path_lookup(to, LOOKUP_PARENT, &nd);
+               if (error)
+                       goto out;
+-              dentry = lookup_create(&nd, 0);
++              if (nd.dentry->d_inode->i_op->symlink_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->symlink_raw(&nd, from);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out2;
++              }
++              dentry = lookup_create(&nd, 0, NULL);
+               error = PTR_ERR(dentry);
+               if (!IS_ERR(dentry)) {
+                       error = vfs_symlink(nd.dentry->d_inode, dentry, from);
+                       dput(dentry);
+               }
+               up(&nd.dentry->d_inode->i_sem);
++      out2:
+               path_release(&nd);
+-out:
++      out:
+               putname(to);
+       }
+       putname(from);
+@@ -1665,7 +1858,14 @@ asmlinkage long sys_link(const char * ol
+               error = -EXDEV;
+               if (old_nd.mnt != nd.mnt)
+                       goto out_release;
+-              new_dentry = lookup_create(&nd, 0);
++              if (nd.dentry->d_inode->i_op->link_raw) {
++                      struct inode_operations *op = nd.dentry->d_inode->i_op;
++                      error = op->link_raw(&old_nd, &nd);
++                      /* the file system wants to use normal vfs path now */
++                      if (error != -EOPNOTSUPP)
++                              goto out_release;
++              }
++              new_dentry = lookup_create(&nd, 0, NULL);
+               error = PTR_ERR(new_dentry);
+               if (!IS_ERR(new_dentry)) {
+                       error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
+@@ -1709,7 +1909,7 @@ exit:
+  *       locking].
+  */
+ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
+-             struct inode *new_dir, struct dentry *new_dentry)
++                 struct inode *new_dir, struct dentry *new_dentry)
+ {
+       int error;
+       struct inode *target;
+@@ -1788,7 +1988,7 @@ out_unlock:
+ }
+ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
+-             struct inode *new_dir, struct dentry *new_dentry)
++                   struct inode *new_dir, struct dentry *new_dentry)
+ {
+       int error;
+@@ -1876,9 +2076,18 @@ static inline int do_rename(const char *
+       if (newnd.last_type != LAST_NORM)
+               goto exit2;
++      if (old_dir->d_inode->i_op->rename_raw) {
++              lock_kernel();
++              error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
++              unlock_kernel();
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto exit2;
++      }
++
+       double_lock(new_dir, old_dir);
+-      old_dentry = lookup_hash(&oldnd.last, old_dir);
++      old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
+       error = PTR_ERR(old_dentry);
+       if (IS_ERR(old_dentry))
+               goto exit3;
+@@ -1894,16 +2103,16 @@ static inline int do_rename(const char *
+               if (newnd.last.name[newnd.last.len])
+                       goto exit4;
+       }
+-      new_dentry = lookup_hash(&newnd.last, new_dir);
++      new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
+       error = PTR_ERR(new_dentry);
+       if (IS_ERR(new_dentry))
+               goto exit4;
++
+       lock_kernel();
+       error = vfs_rename(old_dir->d_inode, old_dentry,
+                                  new_dir->d_inode, new_dentry);
+       unlock_kernel();
+-
+       dput(new_dentry);
+ exit4:
+       dput(old_dentry);
+@@ -1954,20 +2163,28 @@ out:
+ }
+ static inline int
+-__vfs_follow_link(struct nameidata *nd, const char *link)
++__vfs_follow_link(struct nameidata *nd, const char *link,
++                struct lookup_intent *it)
+ {
+       int res = 0;
+       char *name;
+       if (IS_ERR(link))
+               goto fail;
++      if (it == NULL)
++              it = nd->it;
++      else if (it != nd->it)
++              printk("it != nd->it: tell phil@clusterfs.com\n");
++      if (it != NULL)
++              it->it_int_flags |= IT_FL_FOLLOWED;
++
+       if (*link == '/') {
+               path_release(nd);
+               if (!walk_init_root(link, nd))
+                       /* weird __emul_prefix() stuff did it */
+                       goto out;
+       }
+-      res = link_path_walk(link, nd);
++      res = link_path_walk_it(link, nd, it);
+ out:
+       if (current->link_count || res || nd->last_type!=LAST_NORM)
+               return res;
+@@ -1989,7 +2206,13 @@ fail:
+ int vfs_follow_link(struct nameidata *nd, const char *link)
+ {
+-      return __vfs_follow_link(nd, link);
++      return __vfs_follow_link(nd, link, NULL);
++}
++
++int vfs_follow_link_it(struct nameidata *nd, const char *link,
++                     struct lookup_intent *it)
++{
++      return __vfs_follow_link(nd, link, it);
+ }
+ /* get the link contents into pagecache */
+@@ -2031,7 +2254,7 @@ int page_follow_link(struct dentry *dent
+ {
+       struct page *page = NULL;
+       char *s = page_getlink(dentry, &page);
+-      int res = __vfs_follow_link(nd, s);
++      int res = __vfs_follow_link(nd, s, NULL);
+       if (page) {
+               kunmap(page);
+               page_cache_release(page);
+--- linux/fs/open.c~vfs_intent-2.4.20-hp       Thu Nov 28 15:53:15 2002
++++ linux-mmonroe/fs/open.c    Sat Jul 12 14:05:24 2003
+@@ -19,6 +19,8 @@
+ #include <asm/uaccess.h>
+ #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
++extern int path_walk_it(const char *name, struct nameidata *nd,
++                      struct lookup_intent *it);
+ int vfs_statfs(struct super_block *sb, struct statfs *buf)
+ {
+@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct 
+       write_unlock(&files->file_lock);
+ }
+-int do_truncate(struct dentry *dentry, loff_t length)
++int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
+ {
+       struct inode *inode = dentry->d_inode;
++      struct inode_operations *op = dentry->d_inode->i_op;
+       int error;
+       struct iattr newattrs;
+@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l
+       down(&inode->i_sem);
+       newattrs.ia_size = length;
+       newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+-      error = notify_change(dentry, &newattrs);
++      if (called_from_open)
++              newattrs.ia_valid |= ATTR_FROM_OPEN;
++      if (op->setattr_raw) {
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++      } else
++              error = notify_change(dentry, &newattrs);
+       up(&inode->i_sem);
+       return error;
+ }
+@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const
+       struct nameidata nd;
+       struct inode * inode;
+       int error;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       error = -EINVAL;
+       if (length < 0) /* sorry, but loff_t says... */
+               goto out;
+-      error = user_path_walk(path, &nd);
++      error = user_path_walk_it(path, &nd, &it);
+       if (error)
+               goto out;
+       inode = nd.dentry->d_inode;
+@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const
+       error = locks_verify_truncate(inode, NULL, length);
+       if (!error) {
+               DQUOT_INIT(inode);
+-              error = do_truncate(nd.dentry, length);
++              intent_release(&it);
++              error = do_truncate(nd.dentry, length, 0);
+       }
+       put_write_access(inode);
+ dput_and_out:
++      intent_release(&it);
+       path_release(&nd);
+ out:
+       return error;
+@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi
+       error = locks_verify_truncate(inode, file, length);
+       if (!error)
+-              error = do_truncate(dentry, length);
++              error = do_truncate(dentry, length, 0);
+ out_putf:
+       fput(file);
+ out:
+@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam
+       struct inode * inode;
+       struct iattr newattrs;
+-      error = user_path_walk(filename, &nd);
++      error = user_path_walk_it(filename, &nd, NULL);
+       if (error)
+               goto out;
+       inode = nd.dentry->d_inode;
++      /* this is safe without a Lustre lock because it only depends
++         on the super block */
+       error = -EROFS;
+       if (IS_RDONLY(inode))
+               goto dput_and_out;
+@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam
+                       goto dput_and_out;
+               newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
+-      } else {
++      }
++
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto dput_and_out;
++      }
++
++      error = -EPERM;
++      if (!times) {
+               if (current->fsuid != inode->i_uid &&
+                   (error = permission(inode,MAY_WRITE)) != 0)
+                       goto dput_and_out;
+       }
++
+       error = notify_change(nd.dentry, &newattrs);
+ dput_and_out:
+       path_release(&nd);
+@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena
+       struct inode * inode;
+       struct iattr newattrs;
+-      error = user_path_walk(filename, &nd);
++      error = user_path_walk_it(filename, &nd, NULL);
+       if (error)
+               goto out;
+       inode = nd.dentry->d_inode;
++      /* this is safe without a Lustre lock because it only depends
++         on the super block */
+       error = -EROFS;
+       if (IS_RDONLY(inode))
+               goto dput_and_out;
+@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena
+               newattrs.ia_atime = times[0].tv_sec;
+               newattrs.ia_mtime = times[1].tv_sec;
+               newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
+-      } else {
++      }
++
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto dput_and_out;
++      }
++
++      error = -EPERM;
++      if (!utimes) {
+               if (current->fsuid != inode->i_uid &&
+                   (error = permission(inode,MAY_WRITE)) != 0)
+                       goto dput_and_out;
+@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * 
+       int old_fsuid, old_fsgid;
+       kernel_cap_t old_cap;
+       int res;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
+               return -EINVAL;
+@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * 
+       else
+               current->cap_effective = current->cap_permitted;
+-      res = user_path_walk(filename, &nd);
++      res = user_path_walk_it(filename, &nd, &it);
+       if (!res) {
+               res = permission(nd.dentry->d_inode, mode);
+               /* SuS v2 requires we report a read only fs too */
+               if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
+                  && !special_file(nd.dentry->d_inode->i_mode))
+                       res = -EROFS;
++              intent_release(&it);
+               path_release(&nd);
+       }
+@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f
+ {
+       int error;
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+-      error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
++      error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
+       if (error)
+               goto out;
+@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f
+       set_fs_pwd(current->fs, nd.mnt, nd.dentry);
+ dput_and_out:
++      intent_release(&it);
+       path_release(&nd);
+ out:
+       return error;
+@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * 
+ {
+       int error;
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+-      error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
+-                    LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
++      error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
++                    LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
+       if (error)
+               goto out;
+@@ -454,6 +502,7 @@ asmlinkage long sys_chroot(const char * 
+       set_fs_altroot();
+       error = 0;
+ dput_and_out:
++      intent_release(&it);
+       path_release(&nd);
+ out:
+       return error;
+@@ -508,6 +557,18 @@ asmlinkage long sys_chmod(const char * f
+       if (IS_RDONLY(inode))
+               goto dput_and_out;
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = nd.dentry->d_inode->i_op;
++
++              newattrs.ia_mode = mode;
++              newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      goto dput_and_out;
++      }
++
+       error = -EPERM;
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               goto dput_and_out;
+@@ -538,6 +599,20 @@ static int chown_common(struct dentry * 
+       error = -EROFS;
+       if (IS_RDONLY(inode))
+               goto out;
++
++      if (inode->i_op->setattr_raw) {
++              struct inode_operations *op = dentry->d_inode->i_op;
++
++              newattrs.ia_uid = user;
++              newattrs.ia_gid = group;
++              newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
++              newattrs.ia_valid |= ATTR_RAW;
++              error = op->setattr_raw(inode, &newattrs);
++              /* the file system wants to use normal vfs path now */
++              if (error != -EOPNOTSUPP)
++                      return error;
++      }
++
+       error = -EPERM;
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               goto out;
+@@ -638,10 +713,12 @@ asmlinkage long sys_fchown(unsigned int 
+  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
+  * used by symlinks.
+  */
++
+ struct file *filp_open(const char * filename, int flags, int mode)
+ {
+       int namei_flags, error;
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = flags };
+       namei_flags = flags;
+       if ((namei_flags+1) & O_ACCMODE)
+@@ -649,14 +726,15 @@ struct file *filp_open(const char * file
+       if (namei_flags & O_TRUNC)
+               namei_flags |= 2;
+-      error = open_namei(filename, namei_flags, mode, &nd);
+-      if (!error)
+-              return dentry_open(nd.dentry, nd.mnt, flags);
++      error = open_namei_it(filename, namei_flags, mode, &nd, &it);
++      if (error)
++              return ERR_PTR(error);
+-      return ERR_PTR(error);
++      return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
+ }
+-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
++struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
++                          int flags, struct lookup_intent *it)
+ {
+       struct file * f;
+       struct inode *inode;
+@@ -693,12 +771,15 @@ struct file *dentry_open(struct dentry *
+       }
+       if (f->f_op && f->f_op->open) {
++              f->f_it = it;
+               error = f->f_op->open(inode,f);
++              f->f_it = NULL;
+               if (error)
+                       goto cleanup_all;
+       }
+       f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
++      intent_release(it);
+       return f;
+ cleanup_all:
+@@ -713,11 +794,17 @@ cleanup_all:
+ cleanup_file:
+       put_filp(f);
+ cleanup_dentry:
++      intent_release(it);
+       dput(dentry);
+       mntput(mnt);
+       return ERR_PTR(error);
+ }
++struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
++{
++      return dentry_open_it(dentry, mnt, flags, NULL);
++}
++
+ /*
+  * Find an empty file descriptor entry, and mark it busy.
+  */
+--- linux/fs/stat.c~vfs_intent-2.4.20-hp       Thu Sep 13 16:04:43 2001
++++ linux-mmonroe/fs/stat.c    Sat Jul 12 14:05:24 2003
+@@ -17,10 +17,12 @@
+  * Revalidate the inode. This is required for proper NFS attribute caching.
+  */
+ static __inline__ int
+-do_revalidate(struct dentry *dentry)
++do_revalidate(struct dentry *dentry, struct lookup_intent *it)
+ {
+       struct inode * inode = dentry->d_inode;
+-      if (inode->i_op && inode->i_op->revalidate)
++      if (inode->i_op && inode->i_op->revalidate_it)
++              return inode->i_op->revalidate_it(dentry, it);
++      else if (inode->i_op && inode->i_op->revalidate)
+               return inode->i_op->revalidate(dentry);
+       return 0;
+ }
+@@ -135,13 +137,15 @@ static int cp_new_stat(struct inode * in
+ asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
+ {
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       int error;
+-      error = user_path_walk(filename, &nd);
++      error = user_path_walk_it(filename, &nd, &it);
+       if (!error) {
+-              error = do_revalidate(nd.dentry);
++              error = do_revalidate(nd.dentry, &it);
+               if (!error)
+                       error = cp_old_stat(nd.dentry->d_inode, statbuf);
++              intent_release(&it);
+               path_release(&nd);
+       }
+       return error;
+@@ -151,13 +155,15 @@ asmlinkage long sys_stat(char * filename
+ asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
+ {
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       int error;
+-      error = user_path_walk(filename, &nd);
++      error = user_path_walk_it(filename, &nd, &it);
+       if (!error) {
+-              error = do_revalidate(nd.dentry);
++              error = do_revalidate(nd.dentry, &it);
+               if (!error)
+                       error = cp_new_stat(nd.dentry->d_inode, statbuf);
++              intent_release(&it);
+               path_release(&nd);
+       }
+       return error;
+@@ -172,13 +178,15 @@ asmlinkage long sys_newstat(char * filen
+ asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
+ {
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       int error;
+-      error = user_path_walk_link(filename, &nd);
++      error = user_path_walk_link_it(filename, &nd, &it);
+       if (!error) {
+-              error = do_revalidate(nd.dentry);
++              error = do_revalidate(nd.dentry, &it);
+               if (!error)
+                       error = cp_old_stat(nd.dentry->d_inode, statbuf);
++              intent_release(&it);
+               path_release(&nd);
+       }
+       return error;
+@@ -189,13 +197,15 @@ asmlinkage long sys_lstat(char * filenam
+ asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
+ {
+       struct nameidata nd;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+       int error;
+-      error = user_path_walk_link(filename, &nd);
++      error = user_path_walk_link_it(filename, &nd, &it);
+       if (!error) {
+-              error = do_revalidate(nd.dentry);
++              error = do_revalidate(nd.dentry, &it);
+               if (!error)
+                       error = cp_new_stat(nd.dentry->d_inode, statbuf);
++              intent_release(&it);
+               path_release(&nd);
+       }
+       return error;
+@@ -216,7 +226,7 @@ asmlinkage long sys_fstat(unsigned int f
+       if (f) {
+               struct dentry * dentry = f->f_dentry;
+-              err = do_revalidate(dentry);
++              err = do_revalidate(dentry, NULL);
+               if (!err)
+                       err = cp_old_stat(dentry->d_inode, statbuf);
+               fput(f);
+@@ -235,7 +245,7 @@ asmlinkage long sys_newfstat(unsigned in
+       if (f) {
+               struct dentry * dentry = f->f_dentry;
+-              err = do_revalidate(dentry);
++              err = do_revalidate(dentry, NULL);
+               if (!err)
+                       err = cp_new_stat(dentry->d_inode, statbuf);
+               fput(f);
+@@ -257,7 +267,7 @@ asmlinkage long sys_readlink(const char 
+               error = -EINVAL;
+               if (inode->i_op && inode->i_op->readlink &&
+-                  !(error = do_revalidate(nd.dentry))) {
++                  !(error = do_revalidate(nd.dentry, NULL))) {
+                       UPDATE_ATIME(inode);
+                       error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
+               }
+@@ -333,12 +343,14 @@ asmlinkage long sys_stat64(char * filena
+ {
+       struct nameidata nd;
+       int error;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+-      error = user_path_walk(filename, &nd);
++      error = user_path_walk_it(filename, &nd, &it);
+       if (!error) {
+-              error = do_revalidate(nd.dentry);
++              error = do_revalidate(nd.dentry, &it);
+               if (!error)
+                       error = cp_new_stat64(nd.dentry->d_inode, statbuf);
++              intent_release(&it);
+               path_release(&nd);
+       }
+       return error;
+@@ -348,12 +360,14 @@ asmlinkage long sys_lstat64(char * filen
+ {
+       struct nameidata nd;
+       int error;
++      struct lookup_intent it = { .it_op = IT_GETATTR };
+-      error = user_path_walk_link(filename, &nd);
++      error = user_path_walk_link_it(filename, &nd, &it);
+       if (!error) {
+-              error = do_revalidate(nd.dentry);
++              error = do_revalidate(nd.dentry, &it);
+               if (!error)
+                       error = cp_new_stat64(nd.dentry->d_inode, statbuf);
++              intent_release(&it);
+               path_release(&nd);
+       }
+       return error;
+@@ -368,7 +382,7 @@ asmlinkage long sys_fstat64(unsigned lon
+       if (f) {
+               struct dentry * dentry = f->f_dentry;
+-              err = do_revalidate(dentry);
++              err = do_revalidate(dentry, NULL);
+               if (!err)
+                       err = cp_new_stat64(dentry->d_inode, statbuf);
+               fput(f);
+--- linux/fs/proc/base.c~vfs_intent-2.4.20-hp  Sat Jul 12 14:04:46 2003
++++ linux-mmonroe/fs/proc/base.c       Sat Jul 12 14:05:24 2003
+@@ -481,6 +481,9 @@ static int proc_pid_follow_link(struct d
+       error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
+       nd->last_type = LAST_BIND;
++
++      if (nd->it != NULL)
++              nd->it->it_int_flags |= IT_FL_FOLLOWED;
+ out:
+       return error;
+ }
+--- linux/include/linux/dcache.h~vfs_intent-2.4.20-hp  Thu Nov 28 15:53:15 2002
++++ linux-mmonroe/include/linux/dcache.h       Sat Jul 12 14:06:04 2003
+@@ -5,8 +5,47 @@
+ #include <asm/atomic.h>
+ #include <linux/mount.h>
++#include <linux/string.h>
+ #include <linux/kernel.h>
++#define IT_OPEN     0x0001
++#define IT_CREAT    0x0002
++#define IT_READDIR  0x0004
++#define IT_GETATTR  0x0008
++#define IT_LOOKUP   0x0010
++#define IT_UNLINK   0x0020
++#define IT_GETXATTR 0x0040
++#define IT_EXEC     0x0080
++#define IT_PIN      0x0100
++
++#define IT_FL_LOCKED   0x0001
++#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */
++
++#define INTENT_MAGIC 0x19620323
++
++struct lookup_intent {
++      int it_op;
++      void (*it_op_release)(struct lookup_intent *);
++      int it_magic;
++      int it_mode;
++      int it_flags;
++      int it_disposition;
++      int it_status;
++      int it_int_flags;
++      __u64 it_lock_handle[2];
++      int it_lock_mode;
++      void *it_data;
++};
++
++static inline void intent_init(struct lookup_intent *it, int op, int flags)
++{
++      memset(it, 0, sizeof(*it));
++      it->it_magic = INTENT_MAGIC;
++      it->it_op = op;
++      it->it_flags = flags;
++}
++
++
+ /*
+  * linux/include/linux/dcache.h
+  *
+@@ -91,8 +130,22 @@ struct dentry_operations {
+       int (*d_delete)(struct dentry *);
+       void (*d_release)(struct dentry *);
+       void (*d_iput)(struct dentry *, struct inode *);
++      int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *);
++      void (*d_pin)(struct dentry *, struct vfsmount * , int);
++      void (*d_unpin)(struct dentry *, struct vfsmount *, int);
+ };
++#define PIN(de,mnt,flag)  if (de->d_op && de->d_op->d_pin) \
++                              de->d_op->d_pin(de, mnt, flag);
++#define UNPIN(de,mnt,flag)  if (de->d_op && de->d_op->d_unpin) \
++                              de->d_op->d_unpin(de, mnt, flag);
++
++
++/* defined in fs/namei.c */
++extern void intent_release(struct lookup_intent *it);
++/* defined in fs/dcache.c */
++extern void __d_rehash(struct dentry * entry, int lock);
++
+ /* the dentry parameter passed to d_hash and d_compare is the parent
+  * directory of the entries to be compared. It is used in case these
+  * functions need any directory specific information for determining
+@@ -124,6 +177,7 @@ d_iput:            no              no              yes
+                                        * s_nfsd_free_path semaphore will be down
+                                        */
+ #define DCACHE_REFERENCED     0x0008  /* Recently used, don't discard. */
++#define DCACHE_LUSTRE_INVALID 0x0010  /* Lustre invalidated */
+ extern spinlock_t dcache_lock;
+--- linux/include/linux/fs.h~vfs_intent-2.4.20-hp      Sat Jul 12 14:05:20 2003
++++ linux-mmonroe/include/linux/fs.h   Sat Jul 12 14:05:24 2003
+@@ -340,6 +340,9 @@ extern void set_bh_page(struct buffer_he
+ #define ATTR_MTIME_SET        256
+ #define ATTR_FORCE    512     /* Not a change, but a change it */
+ #define ATTR_ATTR_FLAG        1024
++#define ATTR_RAW      0x0800  /* file system, not vfs will massage attrs */
++#define ATTR_FROM_OPEN        0x1000  /* called from open path, ie O_TRUNC */
++#define ATTR_CTIME_SET 0x2000
+ /*
+  * This is the Inode Attributes structure, used for notify_change().  It
+@@ -576,6 +579,7 @@ struct file {
+       /* needed for tty driver, and maybe others */
+       void                    *private_data;
++      struct lookup_intent    *f_it;
+       /* preallocated helper kiobuf to speedup O_DIRECT */
+       struct kiobuf           *f_iobuf;
+@@ -697,6 +701,7 @@ struct nameidata {
+       struct qstr last;
+       unsigned int flags;
+       int last_type;
++      struct lookup_intent *it;
+ };
+ /*
+@@ -817,7 +822,8 @@ extern int vfs_symlink(struct inode *, s
+ extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
+ extern int vfs_rmdir(struct inode *, struct dentry *);
+ extern int vfs_unlink(struct inode *, struct dentry *);
+-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
++int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++             struct inode *new_dir, struct dentry *new_dentry);
+ /*
+  * File types
+@@ -877,21 +883,32 @@ struct file_operations {
+ struct inode_operations {
+       int (*create) (struct inode *,struct dentry *,int);
++      int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *);
++      struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags);
+       int (*link) (struct dentry *,struct inode *,struct dentry *);
++      int (*link_raw) (struct nameidata *,struct nameidata *);
+       int (*unlink) (struct inode *,struct dentry *);
++      int (*unlink_raw) (struct nameidata *);
+       int (*symlink) (struct inode *,struct dentry *,const char *);
++      int (*symlink_raw) (struct nameidata *,const char *);
+       int (*mkdir) (struct inode *,struct dentry *,int);
++      int (*mkdir_raw) (struct nameidata *,int);
+       int (*rmdir) (struct inode *,struct dentry *);
++      int (*rmdir_raw) (struct nameidata *);
+       int (*mknod) (struct inode *,struct dentry *,int,int);
++      int (*mknod_raw) (struct nameidata *,int,dev_t);
+       int (*rename) (struct inode *, struct dentry *,
+                       struct inode *, struct dentry *);
++      int (*rename_raw) (struct nameidata *, struct nameidata *);
+       int (*readlink) (struct dentry *, char *,int);
+       int (*follow_link) (struct dentry *, struct nameidata *);
+       void (*truncate) (struct inode *);
+       int (*permission) (struct inode *, int);
+       int (*revalidate) (struct dentry *);
++      int (*revalidate_it) (struct dentry *, struct lookup_intent *);
+       int (*setattr) (struct dentry *, struct iattr *);
++      int (*setattr_raw) (struct inode *, struct iattr *);
+       int (*getattr) (struct dentry *, struct iattr *);
+       int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
+       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+@@ -1088,10 +1105,14 @@ static inline int get_lease(struct inode
+ asmlinkage long sys_open(const char *, int, int);
+ asmlinkage long sys_close(unsigned int);      /* yes, it's really unsigned */
+-extern int do_truncate(struct dentry *, loff_t start);
++extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
+ extern struct file *filp_open(const char *, int, int);
+ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
++extern int open_namei_it(const char *filename, int namei_flags, int mode,
++                       struct nameidata *nd, struct lookup_intent *it);
++extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
++                          int flags, struct lookup_intent *it);
+ extern int filp_close(struct file *, fl_owner_t id);
+ extern char * getname(const char *);
+@@ -1353,6 +1374,7 @@ typedef int (*read_actor_t)(read_descrip
+ 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(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
+ 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 *));
+@@ -1364,6 +1386,8 @@ extern struct dentry * lookup_one_len(co
+ extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
+ #define user_path_walk(name,nd)        __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
+ #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
++#define user_path_walk_it(name,nd,it)  __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
++#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
+ extern void inode_init_once(struct inode *);
+ extern void iput(struct inode *);
+@@ -1499,6 +1523,8 @@ extern struct file_operations generic_ro
+ extern int vfs_readlink(struct dentry *, char *, int, const char *);
+ extern int vfs_follow_link(struct nameidata *, const char *);
++extern int vfs_follow_link_it(struct nameidata *, const char *,
++                            struct lookup_intent *it);
+ extern int page_readlink(struct dentry *, char *, int);
+ extern int page_follow_link(struct dentry *, struct nameidata *);
+ extern struct inode_operations page_symlink_inode_operations;
+--- linux/include/linux/fs_struct.h~vfs_intent-2.4.20-hp       Fri Jul 13 15:10:44 2001
++++ linux-mmonroe/include/linux/fs_struct.h    Sat Jul 12 14:05:24 2003
+@@ -34,10 +34,12 @@ static inline void set_fs_root(struct fs
+       write_lock(&fs->lock);
+       old_root = fs->root;
+       old_rootmnt = fs->rootmnt;
++      PIN(dentry, mnt, 1);
+       fs->rootmnt = mntget(mnt);
+       fs->root = dget(dentry);
+       write_unlock(&fs->lock);
+       if (old_root) {
++              UNPIN(old_root, old_rootmnt, 1);
+               dput(old_root);
+               mntput(old_rootmnt);
+       }
+@@ -57,10 +59,12 @@ static inline void set_fs_pwd(struct fs_
+       write_lock(&fs->lock);
+       old_pwd = fs->pwd;
+       old_pwdmnt = fs->pwdmnt;
++      PIN(dentry, mnt, 0);
+       fs->pwdmnt = mntget(mnt);
+       fs->pwd = dget(dentry);
+       write_unlock(&fs->lock);
+       if (old_pwd) {
++              UNPIN(old_pwd, old_pwdmnt, 0);
+               dput(old_pwd);
+               mntput(old_pwdmnt);
+       }
+--- linux/kernel/ksyms.c~vfs_intent-2.4.20-hp  Sat Jul 12 14:05:21 2003
++++ linux-mmonroe/kernel/ksyms.c       Sat Jul 12 14:05:24 2003
+@@ -296,6 +296,7 @@ EXPORT_SYMBOL(read_cache_page);
+ EXPORT_SYMBOL(set_page_dirty);
+ EXPORT_SYMBOL(vfs_readlink);
+ EXPORT_SYMBOL(vfs_follow_link);
++EXPORT_SYMBOL(vfs_follow_link_it);
+ EXPORT_SYMBOL(page_readlink);
+ EXPORT_SYMBOL(page_follow_link);
+ EXPORT_SYMBOL(page_symlink_inode_operations);
+--- linux/kernel/fork.c~vfs_intent-2.4.20-hp   Sat Jul 12 14:04:49 2003
++++ linux-mmonroe/kernel/fork.c        Sat Jul 12 14:05:24 2003
+@@ -388,10 +388,13 @@ static inline struct fs_struct *__copy_f
+               fs->umask = old->umask;
+               read_lock(&old->lock);
+               fs->rootmnt = mntget(old->rootmnt);
++              PIN(old->pwd, old->pwdmnt, 0);
++              PIN(old->root, old->rootmnt, 1);
+               fs->root = dget(old->root);
+               fs->pwdmnt = mntget(old->pwdmnt);
+               fs->pwd = dget(old->pwd);
+               if (old->altroot) {
++                      PIN(old->altroot, old->altrootmnt, 1);
+                       fs->altrootmnt = mntget(old->altrootmnt);
+                       fs->altroot = dget(old->altroot);
+               } else {
+--- linux/kernel/exit.c~vfs_intent-2.4.20-hp   Sat Jul 12 14:04:49 2003
++++ linux-mmonroe/kernel/exit.c        Sat Jul 12 14:05:24 2003
+@@ -239,11 +239,14 @@ static inline void __put_fs_struct(struc
+ {
+       /* No need to hold fs->lock if we are killing it */
+       if (atomic_dec_and_test(&fs->count)) {
++              UNPIN(fs->pwd, fs->pwdmnt, 0);
++              UNPIN(fs->root, fs->rootmnt, 1);
+               dput(fs->root);
+               mntput(fs->rootmnt);
+               dput(fs->pwd);
+               mntput(fs->pwdmnt);
+               if (fs->altroot) {
++                      UNPIN(fs->altroot, fs->altrootmnt, 1);
+                       dput(fs->altroot);
+                       mntput(fs->altrootmnt);
+               }
+
+_
diff --git a/lustre/kernel_patches/pc/ext3-map_inode_page.pc b/lustre/kernel_patches/pc/ext3-map_inode_page.pc
new file mode 100644 (file)
index 0000000..6631de4
--- /dev/null
@@ -0,0 +1,3 @@
+fs/ext3/inode.c
+fs/ext3/ext3-exports.c
+fs/ext3/Makefile
diff --git a/lustre/kernel_patches/pc/ext3_map_inode_page_chaos.pc b/lustre/kernel_patches/pc/ext3_map_inode_page_chaos.pc
new file mode 100644 (file)
index 0000000..9ed5141
--- /dev/null
@@ -0,0 +1,2 @@
+fs/ext3/inode.c
+fs/ext3/ext3-exports.c
diff --git a/lustre/kernel_patches/pc/linux-2.4.18-14-kgdb-1.6.pc b/lustre/kernel_patches/pc/linux-2.4.18-14-kgdb-1.6.pc
new file mode 100644 (file)
index 0000000..44dc7de
--- /dev/null
@@ -0,0 +1,26 @@
+arch/i386/config.in
+arch/i386/kernel/entry.S
+arch/i386/kernel/gdbstart.c
+arch/i386/kernel/gdbstub.c
+arch/i386/kernel/Makefile
+arch/i386/kernel/nmi.c
+arch/i386/kernel/signal.c
+arch/i386/kernel/traps.c
+arch/i386/Makefile
+arch/i386/mm/fault.c
+Documentation/Configure.help
+Documentation/i386/gdb-serial.txt
+drivers/char/gdbserial.c
+drivers/char/Makefile
+drivers/char/serial.c
+drivers/char/tty_io.c
+include/asm-i386/ioctls.h
+include/asm-i386/page.h
+include/asm-i386/processor.h
+include/linux/dcache.h
+include/linux/gdb.h
+include/linux/sched.h
+init/main.c
+kernel/ksyms.c
+kernel/sched.c
+Makefile
diff --git a/lustre/kernel_patches/pc/vfs_intent-2.4.20-hp.pc b/lustre/kernel_patches/pc/vfs_intent-2.4.20-hp.pc
new file mode 100644 (file)
index 0000000..f3375a3
--- /dev/null
@@ -0,0 +1,14 @@
+fs/exec.c
+fs/dcache.c
+fs/namespace.c
+fs/namei.c
+fs/nfsd/vfs.c
+fs/open.c
+fs/stat.c
+fs/proc/base.c
+include/linux/dcache.h
+include/linux/fs.h
+include/linux/fs_struct.h
+kernel/ksyms.c
+kernel/fork.c
+kernel/exit.c
diff --git a/lustre/kernel_patches/series/chaos-kgdb b/lustre/kernel_patches/series/chaos-kgdb
new file mode 100644 (file)
index 0000000..933af4a
--- /dev/null
@@ -0,0 +1,22 @@
+linux-2.4.18-14-kgdb-1.6.patch
+dev_read_only.patch
+exports.patch
+kmem_cache_validate.patch
+lustre_version.patch
+vfs_intent-2.4.18-18-chaos65.patch
+invalidate_show.patch
+iod-rmap-exports.patch
+export-truncate.patch
+htree-ext3-2.4.18.patch
+linux-2.4.18ea-0.8.26.patch
+ext3-2.4-ino_t.patch
+ext3-2.4.18-ino_sb_macro.patch
+ext3-orphan_lock.patch
+ext3-delete_thread-2.4.18.patch
+extN-misc-fixup.patch
+extN-noread.patch
+extN-wantedi.patch
+extN-san.patch
+extN-2.4.18-ino_sb_fixup.patch
+ext3_map_inode_page_chaos.patch
+iopen-2.4.18.patch
diff --git a/lustre/kernel_patches/txt/ext3-map_inode_page.txt b/lustre/kernel_patches/txt/ext3-map_inode_page.txt
new file mode 100644 (file)
index 0000000..010cdb7
--- /dev/null
@@ -0,0 +1,3 @@
+DESC
+(undescribed patch)
+EDESC
diff --git a/lustre/kernel_patches/txt/ext3_map_inode_page_chaos.txt b/lustre/kernel_patches/txt/ext3_map_inode_page_chaos.txt
new file mode 100644 (file)
index 0000000..010cdb7
--- /dev/null
@@ -0,0 +1,3 @@
+DESC
+(undescribed patch)
+EDESC