Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[fs/lustre-release.git] / lustre / kernel_patches / patches / netconsole-2.4.20-rh.patch
diff --git a/lustre/kernel_patches/patches/netconsole-2.4.20-rh.patch b/lustre/kernel_patches/patches/netconsole-2.4.20-rh.patch
new file mode 100644 (file)
index 0000000..c5f1ed0
--- /dev/null
@@ -0,0 +1,469 @@
+Index: linux-2.4.20-rh/drivers/net/netconsole.c
+===================================================================
+--- linux-2.4.20-rh.orig/drivers/net/netconsole.c      2003-07-22 16:02:23.000000000 +0800
++++ linux-2.4.20-rh/drivers/net/netconsole.c   2003-11-11 07:42:33.000000000 +0800
+@@ -12,6 +12,8 @@
+  *
+  * 2001-09-17    started by Ingo Molnar.
+  * 2002-03-14    simultaneous syslog packet option by Michael K. Johnson
++ * 2003-10-30    Add sysrq command processing by Wangdi <wangdi@clusterfs.com>
++ * 
+  */
+ /****************************************************************
+@@ -51,6 +53,7 @@
+ #include <linux/tty_driver.h>
+ #include <linux/etherdevice.h>
+ #include <linux/elf.h>
++#include "netconsole.h"
+ static struct net_device *netconsole_dev;
+ static u16 source_port, netdump_target_port, netlog_target_port, syslog_target_port;
+@@ -62,12 +65,11 @@
+ static unsigned int mhz = 500, idle_timeout;
+ static unsigned long long mhz_cycles, jiffy_cycles;
+-#include "netconsole.h"
+ #define MAX_UDP_CHUNK 1460
+ #define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
+-#define DEBUG 0
++#define DEBUG 0 
+ #if DEBUG
+ # define Dprintk(x...) printk(KERN_INFO x)
+ #else
+@@ -187,6 +189,22 @@
+               }
+       }
+ }
++void (*irqfunc)(int, void *, struct pt_regs *);
++
++static void netdump_poll(struct net_device *dev)
++{
++      int budget = 1;
++
++      disable_irq(dev->irq);
++      
++      irqfunc(dev->irq, dev, 0);
++      
++      if(dev->poll && test_bit(__LINK_STATE_RX_SCHED, &dev->state))
++              dev->poll(dev, &budget);
++
++      enable_irq(dev->irq);
++
++}
+ static struct sk_buff * alloc_netconsole_skb(struct net_device *dev, int len, int reserve)
+ {
+@@ -209,7 +227,7 @@
+                               once = 0;
+                       }
+                       Dprintk("alloc skb: polling controller ...\n");
+-                      dev->poll_controller(dev);
++                      netdump_poll(dev);
+                       goto repeat;
+               }
+       }
+@@ -231,7 +249,7 @@
+               spin_unlock(&dev->xmit_lock);
+               Dprintk("xmit skb: polling controller ...\n");
+-              dev->poll_controller(dev);
++              netdump_poll(dev);
+               zap_completion_queue();
+               goto repeat_poll;
+       }
+@@ -426,18 +444,79 @@
+ static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
+ static unsigned int log_offset;
++static int thread_stopped = 0;
++/*Interrupt function for netdump */
++static int sysrq_mode = 0;
++static int stop_sysrq_thread = 0;
++#define Set_Sysrq_mode()       (sysrq_mode = 1)
++#define Clear_Sysrq_mode()     (sysrq_mode = 0)
++static char send_cache[MAX_PRINT_CHUNK];
++static unsigned int send_cache_pos = 0;
++wait_queue_head_t sysrq_thread_queue;
++wait_queue_head_t sysrq_thread_waiter_queue;
++
++#define SEND_MSG_BUFFER(buf, len)                     \
++do                                                    \
++{                                                     \
++      reply_t reply;                                  \
++      unsigned int flags;                             \
++      __save_flags(flags);                            \
++      __cli();                                        \
++      reply.code = REPLY_LOG;                         \
++      reply.nr = 0;                                   \
++      reply.info = 0;                                 \
++      spin_lock(&sequence_lock);                      \
++      send_netlog_skb(dev, buf, len, &reply); \
++      spin_unlock(&sequence_lock);                    \
++      __restore_flags(flags);                         \
++}while(0);
++
++void netconsole_do_sysrq(req_t *req)
++{
++        struct pt_regs regs;
++      struct net_device *dev = netconsole_dev;
++
++      if (!dev)
++              return;
++      Set_Sysrq_mode();
++      get_current_regs(&regs);
++      handle_sysrq((int)req->from, &regs, NULL);
++      
++      if (send_cache_pos != 0){
++              SEND_MSG_BUFFER(send_cache, send_cache_pos);
++              memset(send_cache, 0, MAX_PRINT_CHUNK);
++              send_cache_pos = 0;
++      } 
++
++      Clear_Sysrq_mode();
++}
+ static void write_netconsole_msg(struct console *con, const char *msg0, unsigned int msg_len)
+ {
+       int len, left, i;
+       struct net_device *dev;
+       const char *msg = msg0;
+       reply_t reply;
+-
++      
+       dev = netconsole_dev;
+       if (!dev || netdump_mode)
+               return;
+-
+-      if (dev->poll_controller && netif_running(dev)) {
++      if (sysrq_mode){
++              unsigned long total_len = send_cache_pos + msg_len;
++              unsigned long left_len = msg_len;
++              while (total_len >=  MAX_PRINT_CHUNK){
++                      unsigned long send_len = MAX_PRINT_CHUNK - send_cache_pos; 
++                      memcpy(send_cache + send_cache_pos, msg, send_len);
++                      SEND_MSG_BUFFER(send_cache, MAX_PRINT_CHUNK);
++                      send_cache_pos = 0;
++                      total_len -= MAX_PRINT_CHUNK;
++                      left_len -= send_len; 
++              }
++              if (left_len > 0){
++                      memcpy(send_cache + send_cache_pos, msg + (msg_len -left_len), left_len);
++                      send_cache_pos += left_len;
++              }
++              return; 
++      }else if (netif_running(dev)) {
+               unsigned long flags;
+               __save_flags(flags);
+@@ -567,8 +646,6 @@
+       req_t *req;
+       struct net_device *dev;
+-      if (!netdump_mode)
+-              return NET_RX_SUCCESS;
+ #if DEBUG
+       {
+               static int packet_count;
+@@ -722,8 +799,16 @@
+       Dprintk("... netdump from:    %08x.\n", req->from);
+       Dprintk("... netdump to:      %08x.\n", req->to);
+-      add_new_req(req);
++      if (netdump_mode) 
++              add_new_req(req);
++      else if (req->command == COMM_SYSRQ){
++              add_new_req(req);
++              wake_up(&sysrq_thread_queue);   
++              return NET_RX_DROP;
++      }
+ out:
++      if (!netdump_mode)
++              return NET_RX_SUCCESS;
+       return NET_RX_DROP;
+ }
+@@ -763,6 +848,7 @@
+       kunmap_atomic(kaddr, KM_NETDUMP);
+ }
++
+ /*
+  * This function waits for the client to acknowledge the receipt
+  * of the netdump startup reply, with the possibility of packets
+@@ -792,7 +878,7 @@
+               // wait 1 sec.
+               udelay(100);
+               Dprintk("handshake: polling controller ...\n");
+-              dev->poll_controller(dev);
++              netdump_poll(dev);              
+               zap_completion_queue();
+               req = get_new_req();
+               if (req)
+@@ -904,7 +990,7 @@
+       while (netdump_mode) {
+               __cli();
+               Dprintk("main netdump loop: polling controller ...\n");
+-              dev->poll_controller(dev);
++              netdump_poll(dev);
+               zap_completion_queue();
+ #if !CLI
+               __sti();
+@@ -1009,6 +1095,32 @@
+       printk("NETDUMP END!\n");
+       __restore_flags(flags);
+ }
++static int netconsole_sysrq_schedule(void *arg) 
++{
++      struct task_struct *tsk = current;
++
++      sprintf(tsk->comm, "sysrq_schedule");
++      sigfillset(&tsk->blocked);
++
++      /* main loop */
++      thread_stopped = 0;     
++      for (;;) {
++              wait_event_interruptible(sysrq_thread_queue,
++                                       !list_empty(&request_list) || stop_sysrq_thread);
++              while (!list_empty(&request_list)) {
++                      req_t *req = get_new_req();
++                      if (req->command == COMM_SYSRQ)
++                              netconsole_do_sysrq(req);       
++              }
++              if (stop_sysrq_thread)
++                      break;
++              wake_up(&sysrq_thread_waiter_queue);
++      }
++      thread_stopped = 1;     
++      wake_up(&sysrq_thread_waiter_queue);
++      return 0;
++}
++
+ static char *dev;
+ static int netdump_target_eth_byte0 = 255;
+@@ -1087,11 +1199,12 @@
+ static struct console netconsole =
+        { flags: CON_ENABLED, write: write_netconsole_msg };
+-
+ static int init_netconsole(void)
+ {
+       struct net_device *ndev = NULL;
+       struct in_device *in_dev;
++      struct irqaction *action;
++      int rc = 0;
+       printk(KERN_INFO "netlog: using network device <%s>\n", dev);
+       // this will be valid once the device goes up.
+@@ -1101,10 +1214,6 @@
+               printk(KERN_ERR "netlog: network device %s does not exist, aborting.\n", dev);
+               return -1;
+       }
+-      if (!ndev->poll_controller) {
+-              printk(KERN_ERR "netlog: %s's network driver does not implement netlogging yet, aborting.\n", dev);
+-              return -1;
+-      }
+       in_dev = in_dev_get(ndev);
+       if (!in_dev) {
+               printk(KERN_ERR "netlog: network device %s is not an IP protocol device, aborting.\n", dev);
+@@ -1137,8 +1246,6 @@
+       if (!netdump_target_ip && !netlog_target_ip && !syslog_target_ip) {
+               printk(KERN_ERR "netlog: target_ip parameter not specified, aborting.\n");
+               return -1;
+-      }
+-      if (netdump_target_ip) {
+ #define IP(x) ((unsigned char *)&netdump_target_ip)[x]
+               printk(KERN_INFO "netlog: using netdump target IP %u.%u.%u.%u\n",
+                       IP(3), IP(2), IP(1), IP(0));
+@@ -1214,12 +1321,27 @@
+       mhz_cycles = (unsigned long long)mhz * 1000000ULL;
+       jiffy_cycles = (unsigned long long)mhz * (1000000/HZ);
+-
+-      INIT_LIST_HEAD(&request_list);
+-
++      
+       ndev->rx_hook = netconsole_rx_hook;
+       netdump_func = netconsole_netdump;
+       netconsole_dev = ndev;
++      /* find irq function of the ndev*/
++      action=find_irq_action(ndev->irq, ndev);
++        if (!action) {
++              printk(KERN_ERR "couldn't find irq handler for <%s>", dev);
++              return -1;
++      }
++      irqfunc = action->handler;
++
++      stop_sysrq_thread = 0;
++      INIT_LIST_HEAD(&request_list);
++      init_waitqueue_head(&sysrq_thread_queue);
++      init_waitqueue_head(&sysrq_thread_waiter_queue);
++      if ((rc = kernel_thread(netconsole_sysrq_schedule, NULL, 0)) < 0 ){
++              printk(KERN_ERR "Can not start netconsole sysrq thread: rc %d\n", rc); 
++            return -1; 
++      }
++
+ #define STARTUP_MSG "[...network console startup...]\n"
+       write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
+@@ -1230,7 +1352,11 @@
+ static void cleanup_netconsole(void)
+ {
+-      printk(KERN_INFO "netlog: network logging shut down.\n");
++      stop_sysrq_thread = 1;
++      
++      wake_up(&sysrq_thread_queue);
++      wait_event(sysrq_thread_waiter_queue, thread_stopped); 
++      printk(KERN_INFO"netlog: network logging shut down.\n");
+       unregister_console(&netconsole);
+ #define SHUTDOWN_MSG "[...network console shutdown...]\n"
+Index: linux-2.4.20-rh/drivers/net/netconsole.h
+===================================================================
+--- linux-2.4.20-rh.orig/drivers/net/netconsole.h      2003-07-22 16:02:23.000000000 +0800
++++ linux-2.4.20-rh/drivers/net/netconsole.h   2003-10-30 01:48:45.000000000 +0800
+@@ -29,7 +29,7 @@
+  *
+  ****************************************************************/
+-#define NETCONSOLE_VERSION 0x04
++#define NETCONSOLE_VERSION 0x03
+ enum netdump_commands {
+       COMM_NONE = 0,
+@@ -42,6 +42,8 @@
+       COMM_START_NETDUMP_ACK = 7,
+       COMM_GET_REGS = 8,
+       COMM_SHOW_STATE = 9,
++      COMM_START_WRITE_NETDUMP_ACK = 10,
++        COMM_SYSRQ = 11,
+ };
+ #define NETDUMP_REQ_SIZE (8+4*4)
+@@ -69,6 +71,7 @@
+       REPLY_REGS = 10,
+       REPLY_MAGIC = 11,
+       REPLY_SHOW_STATE = 12,
++      REPLY_SYSRQ = 13,
+ };
+ typedef struct netdump_reply_s {
+@@ -78,4 +81,22 @@
+ } reply_t;
+ #define HEADER_LEN (1 + sizeof(reply_t))
+-
++/* for netconsole */
++static inline void get_current_regs(struct pt_regs *regs)
++{
++       __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
++       __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
++       __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
++       __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
++       __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
++       __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
++       __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
++       __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
++       __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
++       __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
++       __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
++       __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
++       __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
++       regs->eip = (unsigned long)current_text_addr();
++}
++              
+Index: linux-2.4.20-rh/arch/i386/kernel/irq.c
+===================================================================
+--- linux-2.4.20-rh.orig/arch/i386/kernel/irq.c        2003-10-30 08:29:38.000000000 +0800
++++ linux-2.4.20-rh/arch/i386/kernel/irq.c     2003-10-30 08:30:13.000000000 +0800
+@@ -1043,7 +1043,20 @@
+       register_irq_proc(irq);
+       return 0;
+ }
++struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
++{
++      struct irqaction *a, *r=0;
++      spin_lock_irq(&irq_desc[irq].lock);
++      for(a=irq_desc[irq].action; a; a=a->next) {
++              if(a->dev_id == dev_id) {
++                      r=a;
++                      break;
++              }
++      }
++      spin_unlock_irq(&irq_desc[irq].lock);
++      return r;
++}
+ static struct proc_dir_entry * root_irq_dir;
+ static struct proc_dir_entry * irq_dir [NR_IRQS];
+Index: linux-2.4.20-rh/net/core/dev.c
+===================================================================
+--- linux-2.4.20-rh.orig/net/core/dev.c        2003-10-29 01:40:26.000000000 +0800
++++ linux-2.4.20-rh/net/core/dev.c     2003-10-30 01:48:45.000000000 +0800
+@@ -1475,6 +1475,16 @@
+       skb_bond(skb);
++      if (unlikely(skb->dev->rx_hook != NULL)) {
++              int ret;
++
++              ret = skb->dev->rx_hook(skb);
++              if (ret == NET_RX_DROP){
++                      kfree_skb(skb);
++                      return ret;
++              }
++        }
++
+       netdev_rx_stat[smp_processor_id()].total++;
+ #ifdef CONFIG_NET_FASTROUTE
+Index: linux-2.4.20-rh/include/asm-i386/irq.h
+===================================================================
+--- linux-2.4.20-rh.orig/include/asm-i386/irq.h        2003-10-28 16:18:18.000000000 +0800
++++ linux-2.4.20-rh/include/asm-i386/irq.h     2003-10-30 10:24:49.000000000 +0800
+@@ -38,7 +38,7 @@
+ extern void disable_irq_nosync(unsigned int);
+ extern void enable_irq(unsigned int);
+ extern void release_x86_irqs(struct task_struct *);
+-
++extern struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #define ARCH_HAS_NMI_WATCHDOG         /* See include/linux/nmi.h */
+ #endif
+Index: linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c
+===================================================================
+--- linux-2.4.20-rh.orig/arch/i386/kernel/i386_ksyms.c 2003-10-28 19:44:57.000000000 +0800
++++ linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c      2003-10-30 11:14:55.000000000 +0800
+@@ -68,6 +68,7 @@
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(enable_irq);
+ EXPORT_SYMBOL(disable_irq);
++EXPORT_SYMBOL(find_irq_action);
+ EXPORT_SYMBOL(disable_irq_nosync);
+ EXPORT_SYMBOL(probe_irq_mask);
+ EXPORT_SYMBOL(kernel_thread);
+@@ -199,7 +200,6 @@
+ EXPORT_SYMBOL(edd);
+ EXPORT_SYMBOL(eddnr);
+ #endif
+-
+ EXPORT_SYMBOL_GPL(show_mem);
+ EXPORT_SYMBOL_GPL(show_state);
+ EXPORT_SYMBOL_GPL(show_regs);
+Index: linux-2.4.20-rh/kernel/panic.c
+===================================================================
+--- linux-2.4.20-rh.orig/kernel/panic.c        2003-10-31 07:25:19.000000000 +0800
++++ linux-2.4.20-rh/kernel/panic.c     2003-10-31 07:25:59.000000000 +0800
+@@ -219,8 +219,6 @@
+       }
+ #endif
+-      if (netdump_func)
+-              BUG();
+       if (in_interrupt())
+               printk(KERN_EMERG "In interrupt handler - not syncing\n");
+       else if (!current->pid)