]> git.neil.brown.name Git - history.git/commitdiff
pl15a fixes the buffer cache growing problem, adds emulation for a 0.99.15a
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:21 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:21 +0000 (15:09 -0500)
few unimportant floating point instructions (i287 instructions that
are No-Ops on the i387, so "emulating" them is easy :^) and fixes a
silly bug when mmap'ing stuff write-only.  It also fixes a buggy lock
in the networking.

16 files changed:
Makefile
drivers/FPU-emu/fpu_aux.c
drivers/char/console.c
drivers/char/tty_ioctl.c
drivers/scsi/scsi.c
fs/buffer.c
fs/ext2/inode.c
include/asm/io.h
init/main.c
mm/memory.c
mm/mmap.c
net/inet/dev.c
net/inet/ip.c
net/inet/ip.h
net/inet/raw.c
net/inet/tcp.h

index 06a544ed3974c9869dccc410e93e766d25df44e2..b15808f5dc5de0be28aa8f98ced6c8537bc0ad01 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 15
-ALPHA =
+ALPHA = a
 
 all:   Version zImage
 
index c1835d4a8ed314b5e4a5ac2210157fb9680f688b..d9f3a22085012cf9f226acf3f9f607900bff7b1d 100644 (file)
@@ -17,6 +17,9 @@
 #include "control_w.h"
 
 
+static void fnop(void)
+{
+}
 
 void fclex(void)
 {
@@ -47,9 +50,16 @@ void finit()
   FPU_entry_eip = ip_offset = 0;
 }
 
+/*
+ * These are nops on the i387..
+ */
+#define feni fnop
+#define fdisi fnop
+#define fsetpm fnop
+
 static FUNC const finit_table[] = {
-  Un_impl, Un_impl, fclex, finit,
-  Un_impl, FPU_illegal, FPU_illegal, FPU_illegal
+  feni, fdisi, fclex, finit,
+  fsetpm, FPU_illegal, FPU_illegal, FPU_illegal
 };
 
 void finit_()
@@ -75,11 +85,6 @@ void fstsw_()
 }
 
 
-
-static void fnop(void)
-{
-}
-
 static FUNC const fp_nop_table[] = {
   fnop, FPU_illegal, FPU_illegal, FPU_illegal,
   FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
index a22889856a7a7ff003e4fa071ac6dc6e3217ee1b..cfd1e0c4b6d9a11e05a40ffdaa224bfc149bb8e3 100644 (file)
@@ -1800,12 +1800,11 @@ int paste_selection(struct tty_struct *tty)
        if (! *bp)
                return 0;
        unblank_screen();
-       while (*bp)
-       {
+       while (*bp) {
                put_tty_queue(*bp, &tty->read_q);
                bp++;
+               TTY_READ_FLUSH(tty);
        }
-       TTY_READ_FLUSH(tty);
        return 0;
 }
 
index 1f4b50e44b259faf8984138c48890ff5d031448d..bb9474da6a509283da103fd8225aaa24b40b8f8e 100644 (file)
@@ -550,6 +550,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                        return set_selection(arg);
                                case 3:
                                        return paste_selection(tty);
+                               case 4:
+                                       unblank_screen();
+                                       return 0;
 #endif /* CONFIG_SELECTION */
                                default: 
                                        return -EINVAL;
index a2083b8278783f0553b07aa85fb1001e133269ba..60257554b0a5722a9f416b03d22d6d95ed67c008 100644 (file)
@@ -136,6 +136,8 @@ static struct blist blacklist[] =
    {"SEAGATE", "ST296","921"},   /* Responds to all lun */
    {"SONY","CD-ROM CDU-541","4.3d"},
    {"TANDBERG","TDC 3600","U07"},  /* Locks up if polled for lun != 0 */
+   {"TEAC","CD-ROM","1.06"},   /* causes failed REQUEST SENSE on lun 1 for seagate
+                                * controller, which causes SCSI code to reset bus.*/
    {"TEXEL","CD-ROM","1.06"},   /* causes failed REQUEST SENSE on lun 1 for seagate
                                 * controller, which causes SCSI code to reset bus.*/
    {NULL, NULL, NULL}};        
index 1d008685252f1edea9e7a46ffc4f3fd5f4f3fffb..31c203d9b31909b1f05124b2aff0e52deb61b025 100644 (file)
@@ -956,7 +956,11 @@ int shrink_buffers(unsigned int priority)
        bh = free_list;
        i = nr_buffers >> priority;
        for ( ; i-- > 0 ; bh = bh->b_next_free) {
-               if (bh->b_count || !bh->b_this_page)
+               if (bh->b_count) {
+                       put_last_free(bh);
+                       continue;
+               }
+               if (!bh->b_this_page)
                        continue;
                if (bh->b_lock)
                        if (priority)
@@ -975,6 +979,29 @@ int shrink_buffers(unsigned int priority)
        return 0;
 }
 
+void show_buffers(void)
+{
+       struct buffer_head * bh;
+       int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
+
+       printk("Buffer memory:   %6dkB\n",buffermem>>10);
+       printk("Buffer heads:    %6d\n",nr_buffer_heads);
+       printk("Buffer blocks:   %6d\n",nr_buffers);
+       bh = free_list;
+       do {
+               found++;
+               if (bh->b_lock)
+                       locked++;
+               if (bh->b_dirt)
+                       dirty++;
+               if (bh->b_count)
+                       used++, lastused = found;
+               bh = bh->b_next_free;
+       } while (bh != free_list);
+       printk("Buffer mem: %d buffers, %d used (last=%d), %d locked, %d dirty\n",
+               found, used, lastused, locked, dirty);
+}
+
 /*
  * This initializes the initial buffer free list.  nr_buffers is set
  * to one less the actual number of buffers, as a sop to backwards
index 3f0230e63e52ad3b831230442bac10c2636a31be..050b0f2ff47b90b10a4f25866e069fcf9dcef488 100644 (file)
@@ -69,10 +69,11 @@ void ext2_discard_prealloc (struct inode * inode)
 {
 #ifdef EXT2_PREALLOCATE
        if (inode->u.ext2_i.i_prealloc_count) {
+               int i = inode->u.ext2_i.i_prealloc_count;
+               inode->u.ext2_i.i_prealloc_count = 0;
                ext2_free_blocks (inode->i_sb,
                                  inode->u.ext2_i.i_prealloc_block,
-                                 inode->u.ext2_i.i_prealloc_count);
-               inode->u.ext2_i.i_prealloc_count = 0;
+                                 i);
        }
 #endif
 }
index a2527c1e0b4b334ae9ceac9bbb022b50e1d99832..09c494ce84d7d99fd8eb9e35b36671ef0fa2a8e4 100644 (file)
@@ -1,6 +1,19 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
+/*
+ * This file contains the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
+ * versions of the single-IO instructions (inb_p/inw_p/..).
+ *
+ * This file is not meant to be obfuscating: it's just complicated
+ * to (a) handle it all in a way that makes gcc able to optimize it
+ * as well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ */
+
 /*
  * Thanks to James van Artsdalen for a better timing-fix than
  * the two short jumps: using outb's to a nonexistent port seems
index 41309a4baf8b7335b33edf8532edfc3986c6b6c8..f86cf12afcd0ee2d39b1fe5798e7bf548c9208db 100644 (file)
@@ -326,6 +326,17 @@ static void parse_options(char *line)
        envp_init[envs+1] = NULL;
 }
 
+static void copy_options(char * to, char * from)
+{
+       char c = ' ';
+
+       do {
+               if (c == ' ' && !memcmp("mem=", from, 4))
+                       memory_end = simple_strtoul(from+4, &from, 0);
+               c = *(to++) = *(from++);
+       } while (c);
+}
+
 static void copro_timeout(void)
 {
        fpu_error = 1;
@@ -351,7 +362,7 @@ asmlinkage void start_kernel(void)
        memory_end = (1<<20) + (EXT_MEM_K<<10);
        memory_end &= PAGE_MASK;
        ramdisk_size = RAMDISK_SIZE;
-       strcpy(command_line,COMMAND_LINE);
+       copy_options(command_line,COMMAND_LINE);
 #ifdef CONFIG_MAX_16M
        if (memory_end > 16*1024*1024)
                memory_end = 16*1024*1024;
index 57cee25f01366b4ea91d1e1cc83a0eca80c194ce..0168a8de0c7cd559516a2fa6536a9c52da88ad86 100644 (file)
@@ -981,9 +981,6 @@ void show_mem(void)
        printk("Free pages:      %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10));
        printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10));
        printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-       printk("Buffer memory:   %6dkB\n",buffermem>>10);
-       printk("Buffer heads:    %6d\n",nr_buffer_heads);
-       printk("Buffer blocks:   %6d\n",nr_buffers);
        i = high_memory >> PAGE_SHIFT;
        while (i-- > 0) {
                total++;
@@ -998,6 +995,7 @@ void show_mem(void)
        printk("%d free pages\n",free);
        printk("%d reserved pages\n",reserved);
        printk("%d pages shared\n",shared);
+       show_buffers();
 }
 
 /*
index 5fea243bd37661bfc27e90ccb772ff265a3b7858..794ad2361b3b2d47065b49eedc506d4ada8e10f7 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -113,9 +113,9 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
                mask |= PAGE_READONLY;
        if (prot & PROT_WRITE)
                if ((flags & MAP_TYPE) == MAP_PRIVATE)
-                       mask |= PAGE_COW;
+                       mask |= PAGE_COPY;
                else
-                       mask |= PAGE_RW;
+                       mask |= PAGE_SHARED;
        if (!mask)
                return -EINVAL;
 
index 22002f0f4261e12cc7c2cd15fe240e5a5e2fec80..e5bc51339fb1102cefde513acfcc1c6b92a2e021 100644 (file)
@@ -193,81 +193,49 @@ ip_addr_match(unsigned long me, unsigned long him)
 
 
 /* Check the address for our address, broadcasts, etc. */
-int
-chk_addr(unsigned long addr)
+int chk_addr(unsigned long addr)
 {
-  struct device *dev;
-  unsigned long dst;
-
-  DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
-  dst = ntohl(addr);
-
-  /* Accept both `all ones' and `all zeros' as BROADCAST. */
-  if (dst == INADDR_ANY || dst == INADDR_BROADCAST) {
-       DPRINTF((DBG_DEV, "BROADCAST\n"));
-       return(IS_BROADCAST);
-  }
+       struct device *dev;
+       unsigned long mask;
 
-  /* Accept all of the `loopback' class A net. */
-  if ((dst & IN_CLASSA_NET) == 0x7F000000L) {
-       DPRINTF((DBG_DEV, "LOOPBACK\n"));
+       /* Accept both `all ones' and `all zeros' as BROADCAST. */
+       if (addr == INADDR_ANY || addr == INADDR_BROADCAST)
+               return IS_BROADCAST;
 
-       /*
-        * We force `loopback' to be equal to MY_ADDR.
-        */
-       return(IS_MYADDR);
-       /* return(IS_LOOPBACK); */
-  }
+       mask = get_mask(addr);
 
-  /* OK, now check the interface addresses. */
-  for (dev = dev_base; dev != NULL; dev = dev->next) {
-        if (!(dev->flags&IFF_UP))
-               continue;
-       if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
-               return(IS_MYADDR);
-       /* Is it the exact IP address? */
-       if (addr == dev->pa_addr) {
-               DPRINTF((DBG_DEV, "MYADDR\n"));
-               return(IS_MYADDR);
-       }
+       /* Accept all of the `loopback' class A net. */
+       if ((addr & mask) == htonl(0x7F000000L))
+               return IS_MYADDR;
 
-       /* Nope. Check for a subnetwork broadcast. */
-       if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask)) {
-               if ((addr & ~dev->pa_mask) == 0) {
-                       DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
-                       return(IS_BROADCAST);
+       /* OK, now check the interface addresses. */
+       for (dev = dev_base; dev != NULL; dev = dev->next) {
+               if (!(dev->flags & IFF_UP))
+                       continue;
+               if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
+                       return IS_MYADDR;
+               /* Is it the exact IP address? */
+               if (addr == dev->pa_addr)
+                       return IS_MYADDR;
+               /* Is it our broadcast address? */
+               if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
+                       return IS_BROADCAST;
+               /* Nope. Check for a subnetwork broadcast. */
+               if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0) {
+                       if ((addr & ~dev->pa_mask) == 0)
+                               return IS_BROADCAST;
+                       if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
+                               return IS_BROADCAST;
                }
-               if (((addr & ~dev->pa_mask) | dev->pa_mask)
-                                               == INADDR_BROADCAST) {
-                       DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
-                       return(IS_BROADCAST);
+               /* Nope. Check for Network broadcast. */
+               if (((addr ^ dev->pa_addr) & mask) == 0) {
+                       if ((addr & ~mask) == 0)
+                               return IS_BROADCAST;
+                       if ((addr & ~mask) == ~mask)
+                               return IS_BROADCAST;
                }
        }
-
-       /* Nope. Check for Network broadcast. */
-       if(IN_CLASSA(dst)) {
-         if( addr == (dev->pa_addr | 0xffffff00)) {
-           DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
-           return(IS_BROADCAST);
-         }
-       }
-       else if(IN_CLASSB(dst)) {
-         if( addr == (dev->pa_addr | 0xffff0000)) {
-           DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
-           return(IS_BROADCAST);
-         }
-       }
-       else {   /* IN_CLASSC */
-         if( addr == (dev->pa_addr | 0xff000000)) {
-           DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
-           return(IS_BROADCAST);
-         }
-       }
-  }
-
-  DPRINTF((DBG_DEV, "NONE\n"));
-  
-  return(0);           /* no match at all */
+       return 0;               /* no match at all */
 }
 
 
index fdef4c640ba307a8c8f49a75d3d9d63affefccc1..d95e4cdd9307d1b96bce568cd9b66f7134e5c4e0 100644 (file)
@@ -764,7 +764,6 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        skb->len = (len - qp->maclen);
        skb->h.raw = skb->data;
        skb->free = 1;
-       skb->lock = 1;
  
        /* Copy the original MAC and IP headers into the new buffer. */
        ptr = (unsigned char *) skb->h.raw;
index 7f2ecc00d89e18ccebe615bf338ad4a0a52fbdf2..31035bbd3bfcd11e87b6da8e96fee0afbb699238 100644 (file)
@@ -78,6 +78,7 @@ extern void           ip_queue_xmit(struct sock *sk,
                                      struct device *dev, struct sk_buff *skb,
                                      int free);
 extern void            ip_retransmit(struct sock *sk, int all);
+extern void            ip_do_retransmit(struct sock *sk, int all);
 extern int             ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
 extern int             ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
 
index 91563d7f654e2bfe68037aa8ba0bdf5ee155b77a..24f1da02f12861380adf81d1ea679fb70f6759c7 100644 (file)
@@ -115,7 +115,7 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
   /* Now we need to copy this into memory. */
   skb->sk = sk;
   skb->len = len + skb->ip_hdr->ihl*sizeof(long);
-  skb->h.raw = skb->ip_hdr;
+  skb->h.raw = (unsigned char *) skb->ip_hdr;
   skb->dev = dev;
   skb->saddr = daddr;
   skb->daddr = saddr;
index 007f3eee4ca766dc64f887f1acd1fa32ac459513..e154d5e7a5c31bde491bb2df5a3b6439f4973323 100644 (file)
@@ -124,6 +124,7 @@ extern int  tcp_rcv(struct sk_buff *skb, struct device *dev,
 
 extern int     tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 
+extern void tcp_send_probe0(struct sock *sk);
 extern void tcp_enqueue_partial(struct sk_buff *, struct sock *);
 extern struct sk_buff * tcp_dequeue_partial(struct sock *);