From b6a6af4610d932658487464c645cf794f8666e21 Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 5 Sep 2003 18:23:40 +0000 Subject: [PATCH] merge b_devel into b_llpmd --- lustre/kernel_patches/patches/kgdb_eth.patch | 1185 ++++++++++++++++++++++++++ lustre/tests/set_dates.sh | 4 + 2 files changed, 1189 insertions(+) create mode 100644 lustre/kernel_patches/patches/kgdb_eth.patch create mode 100644 lustre/tests/set_dates.sh diff --git a/lustre/kernel_patches/patches/kgdb_eth.patch b/lustre/kernel_patches/patches/kgdb_eth.patch new file mode 100644 index 0000000..5c8eaa2 --- /dev/null +++ b/lustre/kernel_patches/patches/kgdb_eth.patch @@ -0,0 +1,1185 @@ +Index: linux-2.6.0-test1/arch/i386/kernel/kgdb_stub.c +=================================================================== +--- linux-2.6.0-test1.orig/arch/i386/kernel/kgdb_stub.c 2003-09-02 14:16:10.000000000 +0800 ++++ linux-2.6.0-test1/arch/i386/kernel/kgdb_stub.c 2003-09-02 14:32:02.000000000 +0800 +@@ -30,6 +30,7 @@ + * + * Written by: Glenn Engel $ + * Updated by: David Grothe ++ * Updated by: Robert Walsh + * ModuleState: Experimental $ + * + * NOTES: See Below $ +@@ -112,6 +113,7 @@ + #include + #include + #include ++#include + + /************************************************************************ + * +@@ -122,8 +124,16 @@ + /* Thread reference */ + typedef unsigned char threadref[8]; + +-extern void putDebugChar(int); /* write a single character */ +-extern int getDebugChar(void); /* read and return a single char */ ++extern int tty_putDebugChar(int); /* write a single character */ ++extern int tty_getDebugChar(void); /* read and return a single char */ ++extern void tty_flushDebugChar(void); /* flush pending characters */ ++extern int eth_putDebugChar(int); /* write a single character */ ++extern int eth_getDebugChar(void); /* read and return a single char */ ++extern void eth_flushDebugChar(void); /* flush pending characters */ ++extern void gdb_eth_set_trapmode(int); ++extern void gdb_eth_reply_arp(void); /*send arp request */ ++extern int gdb_eth_is_initializing; ++ + + /************************************************************************/ + /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +@@ -264,6 +274,35 @@ + } + + /* ++ * I/O dispatch functions... ++ * Based upon gdb_eth, either call the ethernet ++ * handler or the serial one.. ++ */ ++void putDebugChar(int c) ++{ ++ if (gdb_eth == -1) ++ tty_putDebugChar(c); ++ else ++ eth_putDebugChar(c); ++} ++ ++int getDebugChar(void) ++{ ++ if (gdb_eth == -1) ++ return tty_getDebugChar(); ++ else ++ return eth_getDebugChar(); ++} ++ ++void flushDebugChar(void) ++{ ++ if (gdb_eth == -1) ++ tty_flushDebugChar(); ++ else ++ eth_flushDebugChar(); ++} ++ ++/* + * Gdb calls functions by pushing agruments, including a return address + * on the stack and the adjusting EIP to point to the function. The + * whole assumption in GDB is that we are on a different stack than the +@@ -389,7 +428,6 @@ + xmitcsum = -1; + + count = 0; +- + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) { + ch = getDebugChar() & 0x7f; +@@ -429,6 +467,7 @@ + + if (remote_debug) + printk("R:%s\n", buffer); ++ flushDebugChar(); + } + + /* send the packet in buffer. */ +@@ -441,25 +480,64 @@ + char ch; + + /* $#. */ +- do { +- if (remote_debug) +- printk("T:%s\n", buffer); +- putDebugChar('$'); +- checksum = 0; +- count = 0; +- +- while ((ch = buffer[count])) { +- putDebugChar(ch); +- checksum += ch; +- count += 1; +- } + +- putDebugChar('#'); +- putDebugChar(hexchars[checksum >> 4]); +- putDebugChar(hexchars[checksum % 16]); +- +- } while ((getDebugChar() & 0x7f) != '+'); ++ if (gdb_eth == -1){ ++ do { ++ if (remote_debug) ++ printk("T:%s\n", buffer); ++ putDebugChar('$'); ++ checksum = 0; ++ count = 0; ++ ++ while ((ch = buffer[count])) { ++ putDebugChar(ch); ++ checksum += ch; ++ count += 1; ++ } ++ ++ putDebugChar('#'); ++ putDebugChar(hexchars[checksum >> 4]); ++ putDebugChar(hexchars[checksum % 16]); ++ flushDebugChar(); ++ ++ } while ((getDebugChar() & 0x7f) != '+'); ++ }else{ ++ ++ /*for udp, we can not transfer too much bytes once */ ++ /*we only transfer MAX_SEND_COUNT size byts each time */ ++#define MAX_SEND_COUNT 30 ++ int send_count=0, i=0; ++ char send_buf[30]; + ++ do { ++ if (remote_debug) ++ printk("T:%s\n", buffer); ++ putDebugChar('$'); ++ checksum = 0; ++ count = 0; ++ send_count = 0; ++ while ((ch = buffer[count])) { ++ if (send_count >= MAX_SEND_COUNT){ ++ for(i=0; i < MAX_SEND_COUNT; i++){ ++ putDebugChar(send_buf[i]); ++ } ++ flushDebugChar(); ++ send_count = 0; ++ }else{ ++ send_buf[send_count] = ch; ++ checksum += ch; ++ count ++; ++ send_count++; ++ } ++ } ++ for(i=0; i < send_count; i++) ++ putDebugChar(send_buf[i]); ++ putDebugChar('#'); ++ putDebugChar(hexchars[checksum >> 4]); ++ putDebugChar(hexchars[checksum % 16]); ++ flushDebugChar(); ++ } while ((getDebugChar() & 0x7f) != '+'); ++ } + } + + static char remcomInBuffer[BUFMAX]; +@@ -1143,6 +1221,13 @@ + print_regs(®s); + return (0); + } ++ /* ++ * If we're using eth mode, set the 'mode' in the netdevice. ++ */ ++ ++ if(gdb_eth != -1) { ++ gdb_eth_set_trapmode(1); ++ } + + kgdb_local_irq_save(flags); + +@@ -1156,8 +1241,8 @@ + * NMI and will wait there for the following spin locks to be + * released. + */ ++ + #ifdef CONFIG_SMP +- + #if 0 + if (cpu_callout_map & ~MAX_CPU_MASK) { + printk("kgdb : too many cpus, possibly not mapped" +@@ -1372,6 +1457,7 @@ + gdb_i386vector = exceptionVector; + gdb_i386errcode = err_code; + kgdb_info.called_from = __builtin_return_address(0); ++ + #ifdef CONFIG_SMP + /* + * OK, we can now communicate, lets tell gdb about the sync. +@@ -1400,8 +1486,13 @@ + remcomOutBuffer[2] = hexchars[signo % 16]; + remcomOutBuffer[3] = 0; + +- putpacket(remcomOutBuffer); ++ if (gdb_eth_is_initializing) { ++ gdb_eth_is_initializing = 0; ++ } else { ++ putpacket(remcomOutBuffer); ++ } + ++ gdb_eth_reply_arp(); + while (1 == 1) { + error = 0; + remcomOutBuffer[0] = 0; +@@ -1419,7 +1510,9 @@ + remote_debug ? "on" : "off"); + break; + case 'g': /* return the value of the CPU registers */ ++ + get_gdb_regs(usethread, ®s, gdb_regs); ++ + mem2hex((char *) gdb_regs, + remcomOutBuffer, NUMREGBYTES, 0); + break; +@@ -1536,6 +1629,10 @@ + + newPC = regs.eip; + ++ if (gdb_eth != -1) { ++ gdb_eth_set_trapmode(0); ++ } ++ + /* clear the trace bit */ + regs.eflags &= 0xfffffeff; + +@@ -1856,9 +1953,7 @@ + kgdb_local_irq_restore(flags); + return (0); + } +-#if 0 +-exit_just_unlock: +-#endif ++ exit_just_unlock: + #endif + /* Release kgdb spinlock */ + KGDB_SPIN_UNLOCK(&kgdb_spinlock); +@@ -2213,3 +2308,72 @@ + typedef int gdb_debug_hook(int exceptionVector, + int signo, int err_code, struct pt_regs *linux_regs); + gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception; /* histerical reasons... */ ++ ++static int __init kgdb_opt_gdbeth(char *str) ++{ ++ gdb_eth = simple_strtoul(str,NULL,10); ++ return 1; ++} ++ ++static int __init kgdb_opt_gdbeth_remote(char *str) ++{ ++ gdb_ethremote = in_aton(str); ++ return 1; ++} ++ ++static int __init kgdb_opt_gdbeth_listen(char *str) ++{ ++ gdb_listenport = simple_strtoul(str,NULL,10); ++ return 1; ++} ++ ++static int __init kgdb_opt_gdbeth_hwaddr(char *str) ++{ ++ int i; ++ char *p; ++ ++ p = str; ++ i = 0; ++ while(1) ++ { ++ unsigned int c; ++ sscanf(p, "%x:", &c); ++ gdb_sendhwaddr[i++] = c; ++ while((*p != 0) && (*p != ':')) ++ p++; ++ if (*p == 0) ++ break; ++ p++; ++ } ++ ++ return 1; ++} ++static int __init kgdb_opt_gdbeth_rchwaddr(char *str) ++{ ++ int i; ++ char *p; ++ ++ p = str; ++ i = 0; ++ while(1) ++ { ++ unsigned int c; ++ sscanf(p, "%x:", &c); ++ gdb_receivehwaddr[i++] = c; ++ while((*p != 0) && (*p != ':')) ++ p++; ++ if (*p == 0) ++ break; ++ p++; ++ } ++ ++ return 1; ++} ++ ++ ++__setup("gdbeth=", kgdb_opt_gdbeth); ++__setup("gdbeth_remote=", kgdb_opt_gdbeth_remote); ++__setup("gdbeth_listenport=", kgdb_opt_gdbeth_listen); ++__setup("gdbeth_sendhwaddr=", kgdb_opt_gdbeth_hwaddr); ++__setup("gdbeth_receivehwaddr=", kgdb_opt_gdbeth_rchwaddr); ++ +Index: linux-2.6.0-test1/arch/i386/lib/kgdb_serial.c +=================================================================== +--- linux-2.6.0-test1.orig/arch/i386/lib/kgdb_serial.c 2003-09-02 14:16:11.000000000 +0800 ++++ linux-2.6.0-test1/arch/i386/lib/kgdb_serial.c 2003-09-02 14:32:02.000000000 +0800 +@@ -155,12 +155,12 @@ + * 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 ++ * When the gdb stub routine tty_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 ++ * since the stubs do all of that via tty_putDebugChar() which + * writes one byte after waiting for the interface to become + * ready. + * +@@ -226,7 +226,7 @@ + /* + * Hook an IRQ for KGDB. + * +- * This routine is called from putDebugChar, below. ++ * This routine is called from tty_putDebugChar, below. + */ + static int ints_disabled = 1; + int +@@ -331,7 +331,7 @@ + } + + /* +- * getDebugChar ++ * tty_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 +@@ -345,11 +345,11 @@ + /* Caller takes needed protections */ + + int +-getDebugChar(void) ++tty_getDebugChar(void) + { + volatile int chr, dum, time, end_time; + +- dbprintk(("getDebugChar(port %x): ", gdb_async_info->port)); ++ dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port)); + + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 0); +@@ -375,7 +375,7 @@ + dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ')); + return (chr); + +-} /* getDebugChar */ ++} /* tty_getDebugChar */ + + static int count = 3; + static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED; +@@ -383,6 +383,9 @@ + static int __init + kgdb_enable_ints(void) + { ++ if (gdb_eth != -1) { ++ return 0; ++ } + if (gdb_async_info == NULL) { + gdb_hook_interrupt(&local_info, 1); + } +@@ -444,7 +447,7 @@ + } + + /* +- * putDebugChar ++ * tty_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 +@@ -452,9 +455,9 @@ + * pretended to send the char. Caller takes needed protections. + */ + void +-putDebugChar(int chr) ++tty_putDebugChar(int chr) + { +- dbprintk(("putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n", ++ dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n", + gdb_async_info->port, + chr, + chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1)); +@@ -480,6 +483,14 @@ + } + } + +-} /* putDebugChar */ ++} /* tty_putDebugChar */ ++ ++/* ++ * This does nothing for the serial port, since it doesn't buffer. ++ */ ++ ++void tty_flushDebugChar(void) ++{ ++} + + module_init(kgdb_enable_ints); +Index: linux-2.6.0-test1/include/linux/netdevice.h +=================================================================== +--- linux-2.6.0-test1.orig/include/linux/netdevice.h 2003-09-02 14:29:27.000000000 +0800 ++++ linux-2.6.0-test1/include/linux/netdevice.h 2003-09-02 14:32:02.000000000 +0800 +@@ -469,6 +469,11 @@ + + /* statistics sub-directory */ + struct kobject stats_kobj; ++ ++#ifdef CONFIG_KGDB ++ int kgdb_is_trapped; ++ void (*kgdb_net_poll_rx)(struct net_device *); ++#endif + }; + + #define SET_MODULE_OWNER(dev) do { } while (0) +@@ -524,6 +529,11 @@ + extern struct net_device *dev_get_by_index(int ifindex); + extern struct net_device *__dev_get_by_index(int ifindex); + extern int dev_restart(struct net_device *dev); ++#ifdef CONFIG_KGDB ++int gdb_eth_is_trapped(void); ++int gdb_net_interrupt(struct sk_buff *skb); ++void gdb_send_arp_request(void); ++#endif + + typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len); + extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf); +@@ -582,12 +592,20 @@ + + static inline void netif_wake_queue(struct net_device *dev) + { ++#ifdef CONFIG_KGDB ++ if (gdb_eth_is_trapped()) ++ return; ++#endif + if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state)) + __netif_schedule(dev); + } + + static inline void netif_stop_queue(struct net_device *dev) + { ++#ifdef CONFIG_KGDB ++ if (gdb_eth_is_trapped()) ++ return; ++#endif + set_bit(__LINK_STATE_XOFF, &dev->state); + } + +Index: linux-2.6.0-test1/include/asm-i386/kgdb.h +=================================================================== +--- linux-2.6.0-test1.orig/include/asm-i386/kgdb.h 2003-09-02 14:16:20.000000000 +0800 ++++ linux-2.6.0-test1/include/asm-i386/kgdb.h 2003-09-02 14:32:03.000000000 +0800 +@@ -18,6 +18,16 @@ + #ifndef BREAKPOINT + #define BREAKPOINT asm(" int $3") + #endif ++ ++extern int gdb_eth; ++extern unsigned gdb_ethremote; ++extern unsigned short gdb_listenport; ++extern unsigned char gdb_sendhwaddr[6]; ++extern unsigned char gdb_receivehwaddr[6]; ++ ++extern int gdb_tty_hook(void); ++extern int gdb_eth_hook(void); ++ + /* + * GDB debug stub (or any debug stub) can point the 'linux_debug_hook' + * pointer to its routine and it will be entered as the first thing +@@ -34,6 +44,7 @@ + extern int kgdb_handle_exception(int trapno, + int signo, int err_code, struct pt_regs *regs); + extern int in_kgdb(struct pt_regs *regs); ++extern void kgdb_null(void); + + #ifdef CONFIG_KGDB_TS + void kgdb_tstamp(int line, char *source, int data0, int data1); +Index: linux-2.6.0-test1/drivers/net/e100/e100_main.c +=================================================================== +--- linux-2.6.0-test1.orig/drivers/net/e100/e100_main.c 2003-09-02 14:29:27.000000000 +0800 ++++ linux-2.6.0-test1/drivers/net/e100/e100_main.c 2003-09-02 14:32:03.000000000 +0800 +@@ -567,6 +567,15 @@ + } + #endif + ++#ifdef CONFIG_KGDB ++static void e100_rx_poll(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ e100intr(dev->irq, (void *)dev, 0); ++ enable_irq(dev->irq); ++} ++#endif ++ + static int __devinit + e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) + { +@@ -662,7 +671,9 @@ + dev->set_multicast_list = &e100_set_multi; + dev->set_mac_address = &e100_set_mac; + dev->do_ioctl = &e100_ioctl; +- ++#ifdef CONFIG_KGDB ++ dev->kgdb_net_poll_rx = e100_rx_poll; ++#endif + if (bdp->flags & USE_IPCB) + dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +Index: linux-2.6.0-test1/drivers/net/3c59x.c +=================================================================== +--- linux-2.6.0-test1.orig/drivers/net/3c59x.c 2003-09-02 14:29:27.000000000 +0800 ++++ linux-2.6.0-test1/drivers/net/3c59x.c 2003-09-02 14:32:03.000000000 +0800 +@@ -1063,6 +1063,22 @@ + return rc; + } + ++#ifdef CONFIG_KGDB ++static void vortex_rx_poll(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ vortex_interrupt(dev->irq, (void *)dev, 0); ++ enable_irq(dev->irq); ++} ++ ++static void boomerang_rx_poll(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ boomerang_interrupt(dev->irq, (void *)dev, 0); ++ enable_irq(dev->irq); ++} ++#endif ++ + /* + * Start up the PCI/EISA device which is described by *gendev. + * Return 0 on success. +@@ -1449,6 +1465,14 @@ + dev->set_multicast_list = set_rx_mode; + dev->tx_timeout = vortex_tx_timeout; + dev->watchdog_timeo = (watchdog * HZ) / 1000; ++#ifdef CONFIG_KGDB ++ if (vp->full_bus_master_tx) { ++ dev->kgdb_net_poll_rx = boomerang_rx_poll; ++ } else { ++ dev->kgdb_net_poll_rx = vortex_rx_poll; ++ } ++#endif ++ + #ifdef HAVE_POLL_CONTROLLER + dev->poll_controller = &vorboom_poll; + #endif +Index: linux-2.6.0-test1/drivers/net/Makefile +=================================================================== +--- linux-2.6.0-test1.orig/drivers/net/Makefile 2003-07-14 11:32:32.000000000 +0800 ++++ linux-2.6.0-test1/drivers/net/Makefile 2003-09-02 14:32:03.000000000 +0800 +@@ -32,6 +32,8 @@ + + obj-$(CONFIG_OAKNET) += oaknet.o 8390.o + ++obj-$(CONFIG_KGDB) += kgdb_eth.o ++ + obj-$(CONFIG_DGRS) += dgrs.o + obj-$(CONFIG_RCPCI) += rcpci.o + obj-$(CONFIG_VORTEX) += 3c59x.o +Index: linux-2.6.0-test1/drivers/net/kgdb_eth.c +=================================================================== +--- linux-2.6.0-test1.orig/drivers/net/kgdb_eth.c 2003-09-02 14:32:02.000000000 +0800 ++++ linux-2.6.0-test1/drivers/net/kgdb_eth.c 2003-09-02 21:41:42.000000000 +0800 +@@ -0,0 +1,547 @@ ++/* ++ * Network interface GDB stub ++ * ++ * Written by San Mehat (nettwerk@biodome.org) ++ * Based upon 'gdbserial' by David Grothe (dave@gcom.com) ++ * and Scott Foehner (sfoehner@engr.sgi.com) ++ * ++ * Twiddled for 2.5 by Robert Walsh (rjwalsh@durables.org) ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 void breakpoint(void); ++ ++unsigned int gdb_ethremote = 0; ++unsigned short gdb_listenport = 6443; ++unsigned short gdb_sendport= 6442; ++int gdb_eth = -1; /* Default tty mode */ ++unsigned char gdb_sendhwaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; ++unsigned char gdb_receivehwaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; ++int gdb_eth_is_initializing = 0; ++int gdb_eth_debug = 0; ++ ++struct net_device *gdb_netdevice = NULL; ++ ++//static int initialized = -1; ++//static struct work_struct irq_bp; ++ ++static void bpwork_func(void *p) ++{ ++ udelay(500); ++ BREAKPOINT; ++} ++ ++static struct workqueue_struct *irq_bp; ++DECLARE_WORK(bpwork, bpwork_func, NULL); ++ ++/* ++ * 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 -1; // no data ++} /* read_char */ ++ ++//static unsigned char daddr[6] = {0x00,0x06,0x25,0xA9,0x9F,0x6A}; ++//static unsigned char daddr[6] = {0x00,0x50,0xFC,0xB8,0x22,0x03}; ++//static unsigned char daddr[6] = {0x00,0x08,0x74,0x96,0x6D,0x9B}; ++//static unsigned char daddr[6] = {0x00,0x07,0xE9,0xD4,0xBE,0x85}; ++//static unsigned char daddr[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; ++ ++/* ++ * Wait until the interface can accept a char, then write it. ++ */ ++static void write_buffer(char *buf, int len) ++{ ++ int total_len, eth_len, ip_len, udp_len; ++ struct in_device *in_dev; ++ struct sk_buff *skb; ++ struct udphdr *udph; ++ struct iphdr *iph; ++ struct ethhdr *eth; ++ ++ if (!(in_dev = (struct in_device *) gdb_netdevice->ip_ptr)) ++ panic("No in_device available for interface!\n"); ++ if (!(in_dev->ifa_list)) ++ panic("No interface address set for interface!\n"); ++ udp_len = len + sizeof(struct udphdr); ++ ip_len = eth_len = udp_len + sizeof(struct iphdr); ++ total_len = eth_len + ETH_HLEN; ++ ++ if (!(skb = alloc_skb(total_len, GFP_ATOMIC))) ++ return; ++ ++ atomic_set(&skb->users, 1); ++ skb_reserve(skb, total_len - 1); ++ ++ memcpy(skb->data , (unsigned char *) buf, len); ++ skb->len += len; ++ ++ udph = (struct udphdr *) skb_push(skb, sizeof(*udph)); ++ udph->source = htons(gdb_listenport); ++ udph->dest = htons(gdb_sendport); ++ udph->len = htons(udp_len); ++ udph->check = 0; ++ ++ iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); ++ iph->version = 4; ++ iph->ihl = 5; ++ iph->tos = 0; ++ iph->tot_len = htons(ip_len); ++ iph->id = 0; ++ iph->frag_off= 0; ++ iph->ttl = 64; ++ iph->protocol= IPPROTO_UDP; ++ iph->check = 0; ++ iph->saddr = in_dev->ifa_list->ifa_address; ++ iph->daddr = gdb_ethremote; ++ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); ++ ++ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); ++ eth->h_proto = htons(ETH_P_IP); ++ memcpy(eth->h_source, gdb_sendhwaddr, gdb_netdevice->addr_len); ++// memcpy(eth->h_dest, daddr, gdb_netdevice->addr_len); ++ memcpy(eth->h_dest, gdb_receivehwaddr, gdb_netdevice->addr_len); ++ ++#if 0 ++repeat_poll: ++#endif ++ spin_lock(&gdb_netdevice->xmit_lock); ++ gdb_netdevice->xmit_lock_owner = smp_processor_id(); ++#if 0 ++ if (netif_queue_stopped(gdb_netdevice)) ++ { ++ gdb_netdevice->xmit_lock_owner = -1; ++ spin_unlock(&gdb_netdevice->xmit_lock); ++ gdb_netdevice->poll_controller(gdb_netdevice); ++ zap_completion_queue(); ++ goto repeat_poll; ++ } ++#endif ++ gdb_netdevice->hard_start_xmit(skb, gdb_netdevice); ++ gdb_netdevice->xmit_lock_owner = -1; ++ spin_unlock(&gdb_netdevice->xmit_lock); ++ ++ // kfree_skb(skb); ++} /* write_char */ ++/* in interrupt state the target machine will not response the arp request */ ++ ++static struct sk_buff *send_skb = NULL; ++void gdb_eth_reply_arp(void) ++{ ++ if (send_skb){ ++#if 0 ++repeat_poll: ++#endif ++ spin_lock(&gdb_netdevice->xmit_lock); ++ gdb_netdevice->xmit_lock_owner = smp_processor_id(); ++#if 0 ++ if (netif_queue_stopped(gdb_netdevice)){ ++ gdb_netdevice->xmit_lock_owner = -1; ++ spin_unlock(&gdb_netdevice->xmit_lock); ++ gdb_netdevice->poll_controller(gdb_netdevice); ++ zap_completion_queue(); ++ goto repeat_poll; ++ } ++#endif ++ gdb_netdevice->hard_start_xmit(send_skb, gdb_netdevice); ++ gdb_netdevice->xmit_lock_owner = -1; ++ spin_unlock(&gdb_netdevice->xmit_lock); ++ send_skb = NULL; ++ ++ } ++} ++static int make_arp_request( struct sk_buff *skb) ++{ ++ struct arphdr *arp; ++ unsigned char *arp_ptr; ++ int type = ARPOP_REPLY; ++ int ptype = ETH_P_ARP; ++ u32 sip, tip; ++ unsigned char *sha, *tha; ++ struct in_device *in_dev = (struct in_device *) gdb_netdevice->ip_ptr; ++ /* ++ * No arp on this interface. ++ */ ++ if (gdb_netdevice->flags &IFF_NOARP) ++ return 0; ++ if (!pskb_may_pull(skb, (sizeof(struct arphdr) + ++ (2 * gdb_netdevice->addr_len) + ++ (2 * sizeof(u32))))) ++ return 0; ++ ++ skb->h.raw = skb->nh.raw = skb->data; ++ arp = skb->nh.arph; ++ ++ if ((arp->ar_hrd != htons(ARPHRD_ETHER) && ++ arp->ar_hrd != htons(ARPHRD_IEEE802)) || ++ arp->ar_pro != htons(ETH_P_IP)) ++ return 0; ++ ++/* Understand only these message types */ ++ ++ if (arp->ar_op != htons(ARPOP_REQUEST)) ++ return 0; ++/* ++ * Extract fields ++ */ ++ arp_ptr= (unsigned char *)(arp+1); ++ sha = arp_ptr; ++ arp_ptr += gdb_netdevice->addr_len; ++ memcpy(&sip, arp_ptr, 4); ++ arp_ptr += 4; ++ tha = arp_ptr; ++ arp_ptr += gdb_netdevice->addr_len; ++ memcpy(&tip, arp_ptr, 4); ++ if (tip != in_dev->ifa_list->ifa_address){ ++ return 0; ++ } ++ if (gdb_ethremote != sip){ ++ return 0; ++ } ++/* ++ * Check for bad requests for 127.x.x.x and requests for multicast ++ * addresses. If this is one such, delete it. ++ */ ++ ++ if (LOOPBACK(tip) || MULTICAST(tip)) ++ return 0; ++ ++/* ++ * reply the arp request ++ */ ++ send_skb = alloc_skb(sizeof(struct arphdr)+ 2*(gdb_netdevice->addr_len+4) ++ + LL_RESERVED_SPACE(gdb_netdevice), GFP_ATOMIC); ++ if (send_skb == NULL) ++ return 0; ++ ++ skb_reserve(send_skb, LL_RESERVED_SPACE(gdb_netdevice)); ++ send_skb->nh.raw = send_skb->data; ++ arp = (struct arphdr *) skb_put(send_skb,sizeof(struct arphdr) + 2*(gdb_netdevice->addr_len+4)); ++ send_skb->dev = gdb_netdevice; ++ send_skb->protocol = htons(ETH_P_ARP); ++ ++ /* ++ * Fill the device header for the ARP frame ++ */ ++ if (gdb_netdevice->hard_header && ++ gdb_netdevice->hard_header(send_skb, gdb_netdevice, ptype, gdb_receivehwaddr, gdb_sendhwaddr, send_skb->len) < 0){ ++ kfree_skb(send_skb); ++ return 0; ++ } ++ /* ++ * Fill out the arp protocol part. ++ * ++ * we only support ethernet device type, ++ * which (according to RFC 1390) should always equal 1 (Ethernet). ++ */ ++ arp->ar_hrd = htons(gdb_netdevice->type); ++ arp->ar_pro = htons(ETH_P_IP); ++ ++ arp->ar_hln = gdb_netdevice->addr_len; ++ arp->ar_pln = 4; ++ arp->ar_op = htons(type); ++ ++ arp_ptr=(unsigned char *)(arp+1); ++ ++ memcpy(arp_ptr, gdb_netdevice->dev_addr, gdb_netdevice->addr_len); ++ arp_ptr += gdb_netdevice->addr_len; ++ memcpy(arp_ptr, &tip, 4); ++ arp_ptr += 4; ++ memcpy(arp_ptr, gdb_sendhwaddr, gdb_netdevice->addr_len); ++ arp_ptr+=gdb_netdevice->addr_len; ++ memcpy(arp_ptr, &sip, 4); ++ return 0; ++} ++/* ++ * Accept an skbuff from net_device layer and ++ * add the payload onto gdb 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. ++ * ++ * NOTE: Return value of 1 means it was for us and is an ++ * indication to the calling driver to destroy the sk_buff ++ * and not send it up the stack ++ */ ++ ++int gdb_net_interrupt(struct sk_buff *skb) ++{ ++ unsigned char chr; ++ struct iphdr *iph = (struct iphdr*)skb->data; ++ struct udphdr *udph= (struct udphdr*)(skb->data+(iph->ihl<<2)); ++ unsigned char *data = (unsigned char *) udph + sizeof(struct udphdr); ++ int len; ++ int i; ++ ++ if ((gdb_eth != -1) && (!gdb_netdevice) && ++ (iph->protocol == IPPROTO_UDP) && ++ (be16_to_cpu(udph->dest) == gdb_listenport)) { ++ gdb_sendport = be16_to_cpu(udph->source); ++ ++ while(gdb_eth_is_initializing); ++ if(!gdb_netdevice) ++ gdb_eth_hook(); ++ if (!gdb_netdevice) { ++ /* Lets not even try again. */ ++ gdb_eth = -1; ++ return 0; ++ } ++ } ++ if (!gdb_netdevice) { ++ return 0; ++ } ++ if (skb->protocol == __constant_htons(ETH_P_ARP) && !send_skb){ ++ make_arp_request(skb); ++ return 0; ++ } ++ if (iph->protocol != IPPROTO_UDP) ++ return 0; ++ ++ if (be16_to_cpu(udph->dest) != gdb_listenport) ++ return 0; ++ ++ len = be16_to_cpu(iph->tot_len) - (sizeof(struct udphdr) + ++ sizeof(struct iphdr)); ++ for (i = 0; i < len; i++) ++ { ++ chr = *data++; ++ if (chr == 3) ++ { ++ queue_work(irq_bp, &bpwork); ++// flush_workqueue(irq_bp); ++ continue; ++/* ++ if (!in_interrupt()) ++ { ++ breakpoint(); ++ } ++ else ++ { ++ schedule_work(&irq_bp); // XXX: is this really necessary?? ++ } ++ 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) ; ++ } ++ ++ return 1; ++} /* gdb_interrupt */ ++ ++ ++int gdb_eth_hook(void) ++{ ++ char gdb_netdev[16]; ++ extern void kgdb_respond_ok(void); ++ ++ if (gdb_sendhwaddr[0] == 0xff) ++ panic("ERROR! 'gdbeth_sendhwaddr' option not set!\n"); ++ if (gdb_receivehwaddr[0] == 0xff) ++ panic("ERROR! 'gdbeth_receivehwaddr' option not set!\n"); ++ if (gdb_ethremote == 0) ++ panic("ERROR! 'gdbeth_remote' option not set!\n"); ++ ++ sprintf(gdb_netdev,"eth%d",gdb_eth); ++ ++#ifdef CONFIG_SMP ++ if (num_online_cpus() > CONFIG_NO_KGDB_CPUS){ ++ printk("kgdb: too manu cpus. Cannot enable debugger with more than %d cpus\n", CONFIG_NO_KGDB_CPUS); ++ return -1; ++ } ++#endif ++ for (gdb_netdevice = dev_base; ++ gdb_netdevice != NULL; ++ gdb_netdevice = gdb_netdevice->next){ ++ if (strncmp(gdb_netdevice->name, gdb_netdev, IFNAMSIZ) == 0) ++ break; ++ } ++ if (!gdb_netdevice){ ++ printk("KGDB NET : Unable to find interface %s\n",gdb_netdev); ++ return -ENODEV; ++ } ++ ++ /* ++ * 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. ++ */ ++ if (gdb_eth_debug){ ++ printk(KERN_INFO "Waiting for remote gdb connection from %x on local port %d\n", ++ gdb_ethremote, gdb_listenport); ++ printk(KERN_INFO "We are sending on port %d to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", ++ gdb_sendport, ++ gdb_sendhwaddr[0], ++ gdb_sendhwaddr[1], ++ gdb_sendhwaddr[2], ++ gdb_sendhwaddr[3], ++ gdb_sendhwaddr[4], ++ gdb_sendhwaddr[5]); ++ printk("Connected.\n"); ++ } ++ gdb_eth_is_initializing = 1; ++ queue_work(irq_bp, &bpwork); ++ 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 eth_getDebugChar(void) ++{ ++ volatile int chr ; ++ ++ while((chr = read_char()) < 0) ++ { ++ if (send_skb){ ++ gdb_eth_reply_arp(); ++ } ++ if (gdb_netdevice->kgdb_net_poll_rx) ++ gdb_netdevice->kgdb_net_poll_rx(gdb_netdevice); ++ else ++ { ++ printk("KGDB NET: Error - Device %s is not supported!\n", ++ gdb_netdevice->name); ++ panic("Please add support for kgdb net to this driver"); ++ } ++ } ++ return chr; ++ ++} /* eth_getDebugChar */ ++ ++#define ETH_QUEUE_SIZE 256 ++static char eth_queue[ETH_QUEUE_SIZE]; ++static int outgoing_queue; ++ ++void eth_flushDebugChar(void) ++{ ++ if(outgoing_queue) { ++ write_buffer(eth_queue, outgoing_queue); ++ ++ outgoing_queue = 0; ++ } ++} ++ ++static void put_char_on_queue(int chr) ++{ ++ eth_queue[outgoing_queue++] = chr; ++ if(outgoing_queue == ETH_QUEUE_SIZE) ++ { ++ eth_flushDebugChar(); ++ } ++} ++ ++/* ++ * eth_putDebugChar ++ * ++ * This is a GDB stub routine. It waits until the interface is ready ++ * to transmit a char and then sends it. ++ */ ++void eth_putDebugChar(int chr) ++{ ++ if (gdb_eth_debug) ++ printk(KERN_INFO "eth_putDebugChar: chr=%02x '%c'\n", chr, ++ chr > ' ' && chr < 0x7F ? chr : ' ') ; ++ put_char_on_queue(chr) ; /* this routine will wait */ ++} /* putDebugChar */ ++ ++void gdb_eth_set_trapmode(int mode) ++{ ++ if (!gdb_netdevice) ++ return; ++ gdb_netdevice->kgdb_is_trapped = mode; ++} ++ ++int gdb_eth_is_trapped() ++{ ++ if (!gdb_netdevice) ++ return 0; ++ return gdb_netdevice->kgdb_is_trapped; ++} ++ ++static int __init ++kgdb_eth_init(void) ++{ ++ irq_bp = create_workqueue("kgdb"); ++ return 0; ++} ++ ++module_init(kgdb_eth_init); +Index: linux-2.6.0-test1/net/core/dev.c +=================================================================== +--- linux-2.6.0-test1.orig/net/core/dev.c 2003-09-02 14:29:27.000000000 +0800 ++++ linux-2.6.0-test1/net/core/dev.c 2003-09-02 14:32:03.000000000 +0800 +@@ -188,7 +188,9 @@ + extern int netdev_sysfs_init(void); + extern int netdev_register_sysfs(struct net_device *); + extern void netdev_unregister_sysfs(struct net_device *); +- ++#ifdef CONFIG_KGDB ++extern int gdb_net_interrupt(struct sk_buff *skb); ++#endif + + /******************************************************************************* + +@@ -1349,6 +1351,21 @@ + struct softnet_data *queue; + unsigned long flags; + ++#ifdef CONFIG_KGDB ++ /* See if kgdb_eth wants this packet */ ++ if (!gdb_net_interrupt(skb)) { ++ /* No.. if we're 'trapped' then junk it */ ++ if (gdb_eth_is_trapped()) { ++ kfree_skb(skb); ++ return NET_RX_DROP; ++ } ++ } else { ++ /* kgdb_eth ate the packet... drop it silently */ ++ kfree_skb(skb); ++ return NET_RX_DROP; ++ } ++#endif ++ + + /* + * The code is rearranged so that the path is the most diff --git a/lustre/tests/set_dates.sh b/lustre/tests/set_dates.sh new file mode 100644 index 0000000..b2a9979 --- /dev/null +++ b/lustre/tests/set_dates.sh @@ -0,0 +1,4 @@ +#!/bin/sh +[ `hostname` = "uml1" ] && date --set="Mar 14 20:21:41 MDT 1973" #101010101 +[ `hostname` = "uml2" ] && date --set="May 26 22:43:22 MDT 1976" #202020202 +[ `hostname` = "uml3" ] && date --set="Aug 9 01:05:03 MDT 1979" #303030303 -- 1.8.3.1