]> git.neil.brown.name Git - history.git/commitdiff
Import 2.0.31pre7 2.0.31pre7
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:31 +0000 (15:11 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:31 +0000 (15:11 -0500)
29 files changed:
CREDITS
Documentation/Changes
arch/i386/mm/fault.c
drivers/net/eth16i.c
drivers/net/ne.c
drivers/pci/pci.c
drivers/scsi/Config.in
drivers/scsi/g_NCR5380.c
drivers/scsi/scsi_syms.c
fs/Makefile
fs/bad_inode.c [new file with mode: 0644]
fs/buffer.c
fs/ext2/balloc.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/isofs/inode.c
fs/isofs/rock.c
fs/namei.c
fs/ncpfs/dir.c
fs/smbfs/inode.c
include/linux/fs.h
include/linux/pci.h
include/net/tcp.h
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_output.c
net/ipv4/timer.c

diff --git a/CREDITS b/CREDITS
index c7a3a35a2ec861388d80a4b8c36ee4468d335d27..a440de4ffca57bf7698b92a5af4721d7c0257155 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -715,10 +715,9 @@ S: USA
 N: Alain L. Knaff
 E: Alain.Knaff@imag.fr
 D: floppy driver
-S: Appartement 310B
-S: 11, rue General Mangin
-S: 38100 Grenoble
-S: France
+S: 19, rue Jean l'Aveugle
+S: L-1148 Luxembourg-City
+S: Luxembourg
 
 N: Harald Koenig
 E: koenig@tat.physik.uni-tuebingen.de
index 19533d0cac49e2bdc8e3b3299de9172ed56dc6a7..4f471c6fcff8e4aff2cd2a39b8dfe4aa1ad418df 100644 (file)
@@ -5,7 +5,10 @@ This document contains a list of the latest stable releases of the most
 important packages for Linux as well as instructions for newcomers to
 the 2.0.x series of kernels.  By glancing through it, you should be
 able to find out what you need to upgrade in order to successfully run
-the latest kernels.
+the latest kernels.  Note that I tend to mention the earliest releases
+of software known to work, not necessarily the latest and greatest
+versions, as the goal is to provide you with a list of sure-to-work
+software.
 
    It was originally based on material from the linux-kernel mailing
 list, Jared Mauch's web page "Software Victims of the 1.3 Kernel
@@ -35,9 +38,9 @@ bunshou no nihongo ban wa
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
    Voyez le site http://www.linux-kheops.com/traduc/kernels/ pour la
-traduction francais (merci, David Bourgin).  (French translation)
+traduction francaise (merci, David Bourgin).  (French translation)
 
-Last updated: November 5, 1996.
+Last updated: August 14, 1997.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -48,7 +51,7 @@ Current Releases
 - Dynamic linker (ld.so) 1.7.14
 - GNU CC                2.7.2.1
 - Binutils              2.7.0.3
-- Linux C Library       Stable:  5.2.18, Beta:  5.4.10
+- Linux C Library       Stable:  5.2.18, Beta:  5.4.33
 - Linux C++ Library     2.7.2.1
 - Termcap               2.0.8
 - Procps                1.01
@@ -123,22 +126,24 @@ to this from 5.0.9 or earlier, be sure to read the
 `release.libc-5.2.18' file, since GNU make and a few other fairly
 important utils can be broken by the upgrade.
 
-   The current (beta) Linux C Library release is 5.3.12. In this
-release there are some important changes that may cause troubles to
-buggy programs (programs that call free() on a pointer not returned by
-malloc() work with previous libc, but not with this release) so read the
-`release.libc-5.3.12' file carefully!  In the latest libc releases a
-dirent bug, which erroneously defined d->reclen to d->namlen if USE_GNU
-was defined, has been fixed.  Unfortunately, some GNU packages depend
-on this bug.  GNU make 3.xx is one of them.  To fix that you need to
-patch and recompile those programs (a patch for make is included in the
-file `release.libc-.5.3.9', and the address to obtain a precompiled
-binary is at the end of this file).
+   A current common Linux C Library release is 5.3.12. In this release
+there are some important changes that may cause troubles to buggy
+programs (programs that call free() on a pointer not returned by
+malloc(), such as Netscape, work with previous libc, but not with this
+release) so read the `release.libc-5.3.12' file carefully!  In the
+latest libc releases a dirent bug, which erroneously defined d->reclen
+to d->namlen if USE_GNU was defined, has been fixed.  Unfortunately,
+some GNU packages depend on this bug.  GNU make 3.xx is one of them.
+To fix that you need to patch and recompile those programs (a patch for
+make is included in the file `release.libc-.5.3.9', and the address to
+obtain a precompiled binary is at the end of this file).
 
    Also, the libc-5.3.x line has a known security hole relating to
 rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.10 is
-currently available as well, but it may have problems, so caveat emptor.
+experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.33 is
+currently available as well, but it may have problems, so caveat
+emptor.  It fixes lots of problems, but make break even more programs
+than 5.3.12.
 
    If you're getting an error message that is something to the effect of
 
@@ -273,7 +278,7 @@ allowed.  For example, a file cannot be simultaneously locked with
 details.  Among the programs this has impacted are older sendmails.  If
 you get a message that sendmail cannot lock aliases.dir (or other
 files), you'll need to upgrade to at least 8.7.x. The latest sendmail
-is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.2.tar.gz.
+is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.7.tar.gz.
 
 Uugetty
 =======
@@ -295,7 +300,7 @@ Mount
 currently at release 2.5.  Some may find, especially when using the
 loop or xiafs file system, NFS, or automounting, that they need to
 upgrade to the latest release of mount, available from
-ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6g.tar.gz.
+ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5p.tar.gz.
 
 Console
 =======
@@ -626,10 +631,10 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.2.18.bin.tar.gz
 Installation notes for 5.2.18:
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
 
-The latest 5.4.10 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.10.bin.tar.gz
-Installation notes for 5.4.10:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.10
+The latest 5.4.33 release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.33.bin.tar.gz
+Installation notes for 5.4.33:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.33
 
 Patched make sources:
 ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz
@@ -679,14 +684,12 @@ ftp://sunsite.unc.edu/pub/Linux/system/Daemons/gpm-1.10.tar.gz
 SysVinit utilities
 ==================
 
-ftp://sunsite.unc.edu/pub/Linux/system/daemons/init/sysvinit-2.64.tar.gz
-or for the very latest:
-ftp://ftp.debian.org/debian/unstable/source/base/sysvinit_2.71-1.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz
 
 Util-linux
 ==========
 
-ftp://sunsite.unc.edu/pub/Linux/system/misc/util-linux-2.6.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/system/Misc/util-linux-2.5.tar.gz
 
 Mtools
 ======
index feb16196ee02c52c6ddc5843fc95239d7e52d388..fb208bac46ee8cc5b27369a7f259aadb080514b2 100644 (file)
@@ -130,10 +130,9 @@ bad_area:
                printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
                return;
        }
-       if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
+       if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE)
                printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-               pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
-       } else
+       else
                printk(KERN_ALERT "Unable to handle kernel paging request");
        printk(" at virtual address %08lx\n",address);
        __asm__("movl %%cr3,%0" : "=r" (page));
index 61ff8ac95c33d565aac16a4bfec6329459b17d7f..2cbb4a7538b406a72c0ba252100504ddeddda564 100644 (file)
    0.21         17.10-95        Removed the unnecessary extern 
                                init_etherdev() declaration. Some
                                other cleanups.
+
+   0.21a       15.08-97        Made signature check less restrictive to
+                               detect card that have been used for booting
+                               with a bootprom.
+                               Kurt Huwig <kurt@huwig.de>
    Bugs:
        In some cases the interface autoprobing code doesn't find 
        the correct interface type. In this case you can 
@@ -72,7 +77,7 @@
 */
 
 static char *version = 
-       "eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@elt.icl.fi)\n";
+       "eth16i.c: v0.21a 15-08-97 Mika Kuoppala (miku@elt.icl.fi)/Kurt Huwig (kurt@huwig.de)\n";
 
 #include <linux/module.h>
 
@@ -722,10 +727,10 @@ static int eth16i_check_signature(short ioaddr)
 #endif
 
   if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
-      creg[2] &= 0x42;
+      creg[2] &= 0x40;
       creg[3] &= 0x03;
 
-      if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
+      if( !( (creg[2] == 0x40) && (creg[3] == 0x00)) )
        return -1;
   }
 
index 4384bac78a570d84dddf0e9a89af3b10b88525b2..28cf9b9a425ba16984e23c01589478f811fad1d6 100644 (file)
@@ -75,6 +75,8 @@ pci_clone_list[] = {
        {PCI_VENDOR_ID_REALTEK,         PCI_DEVICE_ID_REALTEK_8029},
        {PCI_VENDOR_ID_WINBOND2,        PCI_DEVICE_ID_WINBOND2_89C940},
        {PCI_VENDOR_ID_COMPEX,          PCI_DEVICE_ID_COMPEX_RL2000},
+       {PCI_VENDOR_ID_KTI,             PCI_DEVICE_ID_KTI_ET32P2},
+       {PCI_VENDOR_ID_NETVIN,          PCI_DEVICE_ID_NETVIN_NV5000SC},
        {0,}
 };
 #endif
index 32325377aa2f28738681a048ef592c9106685a07..bec424d01789d141f04587bb1a1b9f2645ce4260 100644 (file)
@@ -591,7 +591,9 @@ const char *pci_strvendor(unsigned int vendor)
              case PCI_VENDOR_ID_COMPEX:        return "Compex";
              case PCI_VENDOR_ID_RP:            return "Comtrol";
              case PCI_VENDOR_ID_CYCLADES:      return "Cyclades";
+             case PCI_VENDOR_ID_3DFX:          return "3DFX";
              case PCI_VENDOR_ID_SIGMA_DESIGNS: return "Sigma Designs";
+             case PCI_VENDOR_ID_OPTIBASE:      return "Optibase Inc.";
              case PCI_VENDOR_ID_SYMPHONY:      return "Symphony";
              case PCI_VENDOR_ID_TEKRAM:        return "Tekram";
              case PCI_VENDOR_ID_3DLABS:        return "3Dlabs";
index 7f65b6314e515bee9709bb23eae2764337457eb5..d509842eb766c741fb5b7ad924fd8738828523b0 100644 (file)
@@ -21,7 +21,7 @@ dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
 dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
 if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
     bool '   Enable tagged command queueing' CONFIG_AIC7XXX_TAGGED_QUEUEING Y
-    dep_tristate '   Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N
+    bool '   Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N
     if [ "$CONFIG_OVERRIDE_CMDS" != "n" ]; then
       int  '   Maximum number of commands per LUN' CONFIG_AIC7XXX_CMDS_PER_LUN 8
     fi
index 79efcbde85885e555a630419f5639224a974946b..0d05c65a823cc64278eb7071c4f2fb88557ab301 100644 (file)
@@ -614,6 +614,7 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
     int i;
     struct Scsi_Host *scsi_ptr;
     Scsi_Cmnd *ptr;
+    Scsi_Device *dev;
     struct NCR5380_hostdata *hostdata;
 
     cli();
index a9d14f3b2aae237dad7abe5c6c9fd36c9598c2ca..932610f98fa31c396f33f94ca96a674ff4a52c9f 100644 (file)
@@ -63,6 +63,7 @@ struct symbol_table scsi_symbol_table = {
     X(print_Scsi_Cmnd),
     X(scsi_mark_host_reset),
     X(scsi_mark_bus_reset),
+    X(scsi_device_types),
 #if defined(CONFIG_PROC_FS)
     X(proc_print_scsidevice),
 #endif
index 4359e3acc466377f4ededf8257f241af86aacdad..0096c2c92988a5240d4eca63f46d03e10b3c1cf2 100644 (file)
@@ -13,7 +13,7 @@ O_TARGET := fs.o
 O_OBJS    = open.o read_write.o inode.o devices.o file_table.o buffer.o \
                super.o  block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
                ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
-               dcache.o $(BINFMTS) 
+               dcache.o bad_inode.o $(BINFMTS) 
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = minix ext ext2 fat msdos vfat proc isofs nfs xiafs umsdos \
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
new file mode 100644 (file)
index 0000000..d49632f
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  linux/fs/bad_inode.c
+ *
+ *  Copyright (C) 1997, Stephen Tweedie
+ *
+ *  Provide stub functions for unreadable inodes
+ */
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+
+static int return_EIO()
+{
+       return -EIO;
+}
+
+#define EIO_ERROR ((void *) (return_EIO))
+
+static struct file_operations bad_file_ops =
+{
+       EIO_ERROR,              /* lseek */
+       EIO_ERROR,              /* read */
+       EIO_ERROR,              /* write */
+       EIO_ERROR,              /* readdir */
+       EIO_ERROR,              /* select */
+       EIO_ERROR,              /* ioctl */
+       EIO_ERROR,              /* mmap */
+       EIO_ERROR,              /* open */
+       EIO_ERROR,              /* release */
+       EIO_ERROR,              /* fsync */
+       EIO_ERROR,              /* fasync */
+       EIO_ERROR,              /* check_media_change */
+       EIO_ERROR               /* revalidate */
+};
+
+static struct inode_operations bad_inode_ops =
+{
+       &bad_file_ops,          /* default file operations */
+       EIO_ERROR,              /* create */
+       EIO_ERROR,              /* lookup */
+       EIO_ERROR,              /* link */
+       EIO_ERROR,              /* unlink */
+       EIO_ERROR,              /* symlink */
+       EIO_ERROR,              /* mkdir */
+       EIO_ERROR,              /* rmdir */
+       EIO_ERROR,              /* mknod */
+       EIO_ERROR,              /* rename */
+       EIO_ERROR,              /* readlink */
+       EIO_ERROR,              /* follow_link */
+       EIO_ERROR,              /* readpage */
+       EIO_ERROR,              /* writepage */
+       EIO_ERROR,              /* bmap */
+       EIO_ERROR,              /* truncate */
+       EIO_ERROR,              /* permission */
+       EIO_ERROR               /* smap */
+};
+
+
+/* 
+ * When a filesystem is unable to read an inode due to an I/O error in
+ * its read_inode() function, it can call make_bad_inode() to return a
+ * set of stubs which will return EIO errors as required. 
+ *
+ * We only need to do limited initialisation: all other fields are
+ * preinitialised to zero automatically.
+ */
+void make_bad_inode(struct inode * inode) 
+{
+       inode->i_mode = S_IFREG;
+       inode->i_flags = S_BAD_INODE;
+       inode->i_atime = CURRENT_TIME;
+       inode->i_mtime = CURRENT_TIME;
+       inode->i_ctime = CURRENT_TIME;
+       inode->i_op = &bad_inode_ops;   
+}
+
index f560e0ea6ba90d6bae6b2ef5cf0840636eba1537..da0e556afc25f9956c37eec842165b8c1315b036 100644 (file)
@@ -672,6 +672,7 @@ repeat:
                };
        }
 
+#if 0
        /*
         * In order to protect our reserved pages, 
         * return now if we got any buffers.
@@ -682,6 +683,8 @@ repeat:
        /* and repeat until we find something good */
        if (!grow_buffers(GFP_ATOMIC, size))
                wakeup_bdflush(1);
+#endif
+       wakeup_bdflush(1);
 
        /* decrease needed even if there is no success */
        needed -= PAGE_SIZE;
@@ -1719,11 +1722,11 @@ int bdflush(void * unused)
                        continue;
                }
                run_task_queue(&tq_disk);
-               wake_up(&bdflush_done);
                
                /* If there are still a lot of dirty buffers around, skip the sleep
                   and flush some more */
                if(nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
+                       wake_up(&bdflush_done);
                        current->signal = 0;
                        interruptible_sleep_on(&bdflush_wait);
                }
index 1e0b69ed0397f277c2c1105316d204e3ff625386..64b02d964752f35724f339f9e375350d0c22595d 100644 (file)
@@ -43,6 +43,10 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
        unsigned long desc;
        struct ext2_group_desc * gdp;
 
+       /*
+        * This panic should never trigger on a bad filesystem: the caller
+        * should have verified the block/group number already.
+        */
        if (block_group >= sb->u.ext2_sb.s_groups_count)
                ext2_panic (sb, "get_group_desc",
                            "block_group >= groups_count - "
@@ -63,22 +67,37 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
        return gdp + desc;
 }
 
-static void read_block_bitmap (struct super_block * sb,
-                              unsigned int block_group,
-                              unsigned long bitmap_nr)
+/*
+ * Read the bitmap for a given block_group, reading into the specified 
+ * slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_block_bitmap (struct super_block * sb,
+                             unsigned int block_group,
+                             unsigned long bitmap_nr)
 {
        struct ext2_group_desc * gdp;
        struct buffer_head * bh;
+       int retval = 0;
        
        gdp = get_group_desc (sb, block_group, NULL);
        bh = bread (sb->s_dev, gdp->bg_block_bitmap, sb->s_blocksize);
-       if (!bh)
-               ext2_panic (sb, "read_block_bitmap",
+       if (!bh) {
+               ext2_error (sb, "read_block_bitmap",
                            "Cannot read block bitmap - "
                            "block_group = %d, block_bitmap = %lu",
                            block_group, (unsigned long) gdp->bg_block_bitmap);
+               retval = -EIO;
+       }
+       /*
+        * On IO error, just leave a zero in the superblock's block pointer for
+        * this group.  The IO will be retried next time.
+        */
        sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
        sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
+       return retval;
 }
 
 /*
@@ -91,11 +110,13 @@ static void read_block_bitmap (struct super_block * sb,
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ *
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load__block_bitmap (struct super_block * sb,
                               unsigned int block_group)
 {
-       int i, j;
+       int i, j, retval = 0;
        unsigned long block_bitmap_number;
        struct buffer_head * block_bitmap;
 
@@ -114,7 +135,9 @@ static int load__block_bitmap (struct super_block * sb,
                        else
                                return block_group;
                } else {
-                       read_block_bitmap (sb, block_group, block_group);
+                       retval = read_block_bitmap (sb, block_group, block_group);
+                       if (retval < 0)
+                               return retval;
                        return block_group;
                }
        }
@@ -134,6 +157,14 @@ static int load__block_bitmap (struct super_block * sb,
                }
                sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number;
                sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap;
+
+               /*
+                * There's still one special case here --- if block_bitmap == 0
+                * then our last attempt to read the bitmap failed and we have
+                * just ended up caching that failure.  Try again to read it.
+                */
+               if (!block_bitmap)
+                       retval = read_block_bitmap (sb, block_group, 0);
        } else {
                if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
                        sb->u.ext2_sb.s_loaded_block_bitmaps++;
@@ -145,24 +176,71 @@ static int load__block_bitmap (struct super_block * sb,
                        sb->u.ext2_sb.s_block_bitmap[j] =
                                sb->u.ext2_sb.s_block_bitmap[j - 1];
                }
-               read_block_bitmap (sb, block_group, 0);
+               retval = read_block_bitmap (sb, block_group, 0);
        }
-       return 0;
+       return retval;
 }
 
+/*
+ * Load the block bitmap for a given block group.  First of all do a couple
+ * of fast lookups for common cases and then pass the request onto the guts
+ * of the bitmap loader.
+ *
+ * Return the slot number of the group in the superblock bitmap cache's on
+ * success, or a -ve error code.
+ *
+ * There is still one inconsistancy here --- if the number of groups in this
+ * filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of 
+ * differentiating between a group for which we have never performed a bitmap
+ * IO request, and a group for which the last bitmap read request failed.
+ */
 static inline int load_block_bitmap (struct super_block * sb,
                                     unsigned int block_group)
 {
-       if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
-           sb->u.ext2_sb.s_block_bitmap_number[0] == block_group)
-               return 0;
+       int slot;
        
-       if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
-           sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
-           sb->u.ext2_sb.s_block_bitmap[block_group]) 
-               return block_group;
+       /*
+        * Do the lookup for the slot.  First of all, check if we're asking
+        * for the same slot as last time, and did we succeed that last time?
+        */
+       if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
+           sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
+           sb->u.ext2_sb.s_block_bitmap[block_group]) {
+               slot = 0;
+       }
+       /*
+        * Or can we do a fast lookup based on a loaded group on a filesystem
+        * small enough to be mapped directly into the superblock?
+        */
+       else if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
+                sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
+                sb->u.ext2_sb.s_block_bitmap[block_group]) {
+               slot = block_group;
+       } 
+       /*
+        * If not, then do a full lookup for this block group.
+        */
+       else {
+               slot = load__block_bitmap (sb, block_group);
+       }
 
-       return load__block_bitmap (sb, block_group);
+       /*
+        * <0 means we just got an error
+        */
+       if (slot < 0)
+               return slot;
+       
+       /*
+        * If it's a valid slot, we may still have cached a previous IO error,
+        * in which case the bh in the superblock cache will be zero.
+        */
+       if (!sb->u.ext2_sb.s_block_bitmap[slot])
+               return -EIO;
+       
+       /*
+        * Must have been read in OK to get this far.
+        */
+       return slot;
 }
 
 void ext2_free_blocks (const struct inode * inode, unsigned long block,
@@ -199,12 +277,19 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
        block_group = (block - es->s_first_data_block) /
                      EXT2_BLOCKS_PER_GROUP(sb);
        bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
-       if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
-               ext2_panic (sb, "ext2_free_blocks",
+       if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) {
+               ext2_error (sb, "ext2_free_blocks",
                            "Freeing blocks across group boundary - "
                            "Block = %lu, count = %lu",
                            block, count);
+               unlock_super (sb);
+               return;
+       }
+       
        bitmap_nr = load_block_bitmap (sb, block_group);
+       if (bitmap_nr < 0)
+               goto error_return;
+               
        bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
        gdp = get_group_desc (sb, block_group, &bh2);
 
@@ -214,11 +299,14 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
             in_range (block, gdp->bg_inode_table,
                       sb->u.ext2_sb.s_itb_per_group) ||
             in_range (block + count - 1, gdp->bg_inode_table,
-                      sb->u.ext2_sb.s_itb_per_group)))
-               ext2_panic (sb, "ext2_free_blocks",
+                      sb->u.ext2_sb.s_itb_per_group))) {
+               ext2_error (sb, "ext2_free_blocks",
                            "Freeing blocks in system zones - "
                            "Block = %lu, count = %lu",
                            block, count);
+               unlock_super (sb);
+               return;
+       }
 
        for (i = 0; i < count; i++) {
                if (!clear_bit (bit + i, bh->b_data))
@@ -242,6 +330,7 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
                wait_on_buffer (bh);
        }
        sb->s_dirt = 1;
+error_return:
        unlock_super (sb);
        return;
 }
@@ -301,6 +390,12 @@ repeat:
                        goal_attempts++;
 #endif
                bitmap_nr = load_block_bitmap (sb, i);
+               if (bitmap_nr < 0) {
+                       *err = -EIO;
+                       unlock_super (sb);
+                       return 0;
+               }
+               
                bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
                ext2_debug ("goal is at %d:%d.\n", i, j);
@@ -372,7 +467,14 @@ repeat:
                unlock_super (sb);
                return 0;
        }
+
        bitmap_nr = load_block_bitmap (sb, i);
+       if (bitmap_nr < 0) {
+               *err = -EIO;
+               unlock_super (sb);
+               return 0;
+       }
+               
        bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
        r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
        j = (r - bh->b_data) << 3;
@@ -415,10 +517,14 @@ got_block:
        if (test_opt (sb, CHECK_STRICT) &&
            (tmp == gdp->bg_block_bitmap ||
             tmp == gdp->bg_inode_bitmap ||
-            in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
-               ext2_panic (sb, "ext2_new_block",
+            in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group))) {
+               ext2_error (sb, "ext2_new_block",
                            "Allocating block in system zone - "
                            "block = %u", tmp);
+               unlock_super (sb);
+               *err = -EIO;
+               return 0;
+       }
 
        if (set_bit (j, bh->b_data)) {
                ext2_warning (sb, "ext2_new_block",
@@ -511,7 +617,11 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
                gdp = get_group_desc (sb, i, NULL);
                desc_count += gdp->bg_free_blocks_count;
+
                bitmap_nr = load_block_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+               
                x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
                                     sb->s_blocksize);
                printk ("group %d: stored = %d, counted = %lu\n",
@@ -556,6 +666,9 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
                gdp = get_group_desc (sb, i, NULL);
                desc_count += gdp->bg_free_blocks_count;
                bitmap_nr = load_block_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+
                bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
                if (!test_bit (0, bh->b_data))
index 35435d4adb7d75cb83a224f3735043cb37342dff..fd1131963975c84ddf9a7c5c252c34eea8cb43df 100644 (file)
@@ -62,22 +62,37 @@ static struct ext2_group_desc * get_group_desc (struct super_block * sb,
        return gdp + desc;
 }
 
-static void read_inode_bitmap (struct super_block * sb,
-                              unsigned long block_group,
-                              unsigned int bitmap_nr)
+/*
+ * Read the inode allocation bitmap for a given block_group, reading
+ * into the specified slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_inode_bitmap (struct super_block * sb,
+                             unsigned long block_group,
+                             unsigned int bitmap_nr)
 {
        struct ext2_group_desc * gdp;
        struct buffer_head * bh;
+       int retval = 0;
 
        gdp = get_group_desc (sb, block_group, NULL);
        bh = bread (sb->s_dev, gdp->bg_inode_bitmap, sb->s_blocksize);
-       if (!bh)
-               ext2_panic (sb, "read_inode_bitmap",
+       if (!bh) {
+               ext2_error (sb, "read_inode_bitmap",
                            "Cannot read inode bitmap - "
                            "block_group = %lu, inode_bitmap = %lu",
                            block_group, (unsigned long) gdp->bg_inode_bitmap);
+               retval = -EIO;
+       }
+       /*
+        * On IO error, just leave a zero in the superblock's block pointer for
+        * this group.  The IO will be retried next time.
+        */
        sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
        sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
+       return retval;
 }
 
 /*
@@ -90,11 +105,13 @@ static void read_inode_bitmap (struct super_block * sb,
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ *
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load_inode_bitmap (struct super_block * sb,
                              unsigned int block_group)
 {
-       int i, j;
+       int i, j, retval = 0;
        unsigned long inode_bitmap_number;
        struct buffer_head * inode_bitmap;
 
@@ -114,7 +131,9 @@ static int load_inode_bitmap (struct super_block * sb,
                        else
                                return block_group;
                } else {
-                       read_inode_bitmap (sb, block_group, block_group);
+                       retval = read_inode_bitmap (sb, block_group, block_group);
+                       if (retval < 0)
+                               return retval;
                        return block_group;
                }
        }
@@ -135,6 +154,14 @@ static int load_inode_bitmap (struct super_block * sb,
                }
                sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
                sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap;
+
+               /*
+                * There's still one special case here --- if inode_bitmap == 0
+                * then our last attempt to read the bitmap failed and we have
+                * just ended up caching that failure.  Try again to read it.
+                */
+               if (!inode_bitmap)
+                       retval = read_inode_bitmap (sb, block_group, 0);
        } else {
                if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
                        sb->u.ext2_sb.s_loaded_inode_bitmaps++;
@@ -146,9 +173,9 @@ static int load_inode_bitmap (struct super_block * sb,
                        sb->u.ext2_sb.s_inode_bitmap[j] =
                                sb->u.ext2_sb.s_inode_bitmap[j - 1];
                }
-               read_inode_bitmap (sb, block_group, 0);
+               retval = read_inode_bitmap (sb, block_group, 0);
        }
-       return 0;
+       return retval;
 }
 
 void ext2_free_inode (struct inode * inode)
@@ -198,6 +225,11 @@ void ext2_free_inode (struct inode * inode)
        block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(sb);
        bit = (inode->i_ino - 1) % EXT2_INODES_PER_GROUP(sb);
        bitmap_nr = load_inode_bitmap (sb, block_group);
+       if (bitmap_nr < 0) {
+               unlock_super (sb);
+               return;
+       }
+       
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
        if (!clear_bit (bit, bh->b_data))
                ext2_warning (sb, "ext2_free_inode",
@@ -352,6 +384,13 @@ repeat:
                return NULL;
        }
        bitmap_nr = load_inode_bitmap (sb, i);
+       if (bitmap_nr < 0) {
+               unlock_super (sb);
+               iput(inode);
+               *err = -EIO;
+               return NULL;
+       }
+       
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
        if ((j = find_first_zero_bit ((unsigned long *) bh->b_data,
                                      EXT2_INODES_PER_GROUP(sb))) <
@@ -465,6 +504,9 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
                gdp = get_group_desc (sb, i, NULL);
                desc_count += gdp->bg_free_inodes_count;
                bitmap_nr = load_inode_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+               
                x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
                                     EXT2_INODES_PER_GROUP(sb) / 8);
                printk ("group %d: stored = %d, counted = %lu\n",
@@ -497,6 +539,9 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
                gdp = get_group_desc (sb, i, NULL);
                desc_count += gdp->bg_free_inodes_count;
                bitmap_nr = load_inode_bitmap (sb, i);
+               if (bitmap_nr < 0)
+                       continue;
+               
                x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
                                     EXT2_INODES_PER_GROUP(sb) / 8);
                if (gdp->bg_free_inodes_count != x)
index 8e06a46d7bba51947bc998d8db60799c2513cde1..b94333d79a93930cbfe932a985f12e3b0c69f31a 100644 (file)
@@ -432,9 +432,12 @@ void ext2_read_inode (struct inode * inode)
        group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
        desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
        bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
-       if (!bh)
-               ext2_panic (inode->i_sb, "ext2_read_inode",
+       if (!bh) {
+               ext2_error (inode->i_sb, "ext2_read_inode",
                            "Descriptor not loaded");
+               goto bad_inode;
+       }
+       
        gdp = (struct ext2_group_desc *) bh->b_data;
        /*
         * Figure out the offset within the block group inode table
@@ -443,10 +446,13 @@ void ext2_read_inode (struct inode * inode)
                EXT2_INODE_SIZE(inode->i_sb);
        block = gdp[desc].bg_inode_table +
                (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-               ext2_panic (inode->i_sb, "ext2_read_inode",
-                           "unable to read i-node block - "
+       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+               ext2_error (inode->i_sb, "ext2_read_inode",
+                           "unable to read inode block - "
                            "inode=%lu, block=%lu", inode->i_ino, block);
+               goto bad_inode;
+       }
+       
        offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -506,6 +512,11 @@ void ext2_read_inode (struct inode * inode)
                inode->i_flags |= S_IMMUTABLE;
        if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL)
                inode->i_flags |= MS_NOATIME;
+       return;
+       
+bad_inode:
+       make_bad_inode(inode);
+       return;
 }
 
 static int ext2_update_inode(struct inode * inode, int do_sync)
@@ -545,10 +556,23 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
                EXT2_INODE_SIZE(inode->i_sb);
        block = gdp[desc].bg_inode_table +
                (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-               ext2_panic (inode->i_sb, "ext2_write_inode",
-                           "unable to read i-node block - "
+       if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+               ext2_error (inode->i_sb, "ext2_write_inode",
+                           "unable to read inode block - "
                            "inode=%lu, block=%lu", inode->i_ino, block);
+               /*
+                * Unfortunately we're in a lose-lose situation.  I think that
+                * keeping the inode in-core with the dirty bit set is 
+                * the worse option, since that will soak up inodes until
+                * the end of the world.  Clearing the dirty bit is nasty if
+                * we haven't succeeded in writing out, but it's less nasty
+                * than the alternative. -- sct
+                */
+               inode->i_dirt = 0;
+               
+               return -EIO;
+       }
+       
        offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -579,10 +603,11 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
                if (buffer_req(bh) && !buffer_uptodate(bh)) {
-                       printk ("IO error syncing ext2 inode ["
-                               "%s:%08lx]\n",
-                               kdevname(inode->i_dev), inode->i_ino);
-                       err = -1;
+                       ext2_error (inode->i_sb, 
+                                   "IO error syncing ext2 inode ["
+                                   "%s:%08lx]\n",
+                                   kdevname(inode->i_dev), inode->i_ino);
+                       err = -EIO;
                }
        }
        brelse (bh);
index 7e27be87f1846f8e541623febdf4433c73c4bf87..b00c408533855390f7ffdfcee0f2d942b7e33669 100644 (file)
@@ -187,6 +187,11 @@ static unsigned int isofs_get_last_session(kdev_t dev)
   vol_desc_start=0;
   if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
     {
+      /* Whoops.  We must save the old FS, since otherwise
+       * we would destroy the kernels idea about FS on root
+       * mount in read_super... [chexum]
+       */
+      unsigned long old_fs=get_fs();
       inode_fake.i_rdev=dev;
       ms_info.addr_format=CDROM_LBA;
       set_fs(KERNEL_DS);
@@ -194,7 +199,7 @@ static unsigned int isofs_get_last_session(kdev_t dev)
                                       NULL,
                                       CDROMMULTISESSION,
                                       (unsigned long) &ms_info);
-      set_fs(USER_DS);
+      set_fs(old_fs);
 #if 0 
       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
       if (i==0)
index 9f267e69dced6f510c82aaa870c98ea8865b2268..76c3168b2870ba0fd8c4487fc9a44501836531a2 100644 (file)
@@ -287,7 +287,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
        CHECK_CE;
        break;
       case SIG('E','R'):
-       printk("ISO9660 Extensions: ");
+       printk(KERN_DEBUG"ISO9660 Extensions: ");
        { int p;
          for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
        };
index d2714ee56ee37a210b23f99c9e80e32d9148b49d..0cdacc48f681fa90f643f55e1d4d52ba1e3de138 100644 (file)
@@ -6,6 +6,8 @@
 
 /*
  * Some corrections by tytso.
+ *
+ * Aug 97 - cevans - fix security problem with O_TRUNC and append only files
  */
 
 #include <asm/segment.h>
@@ -282,6 +284,10 @@ static int _namei(const char * pathname, struct inode * base,
                        return error;
        } else
                iput(base);
+       if ((inode->i_flags & S_BAD_INODE) != 0) {
+               iput(inode);
+               return -EIO;
+       }
        *res_inode = inode;
        return 0;
 }
@@ -424,8 +430,9 @@ int open_namei(const char * pathname, int flag, int mode,
        }
        /*
         * An append-only file must be opened in append mode for writing
+        * Additionally, we must disallow O_TRUNC -- cevans
         */
-       if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND))) {
+       if (IS_APPEND(inode) && (((flag & FMODE_WRITE) && !(flag & O_APPEND)) || (flag & O_TRUNC))) {
                iput(inode);
                return -EPERM;
        }
index 4250f886265f2861f4fc85a75ecd5e1e1e56db73..9d9c7d58c70ced702c8f6b5d693f4d09f031ecca 100644 (file)
@@ -1226,13 +1226,13 @@ extern struct timezone sys_tz;
 static int
 utc2local(int time)
 {
-        return time - sys_tz.tz_minuteswest*60;
+        return time - sys_tz.tz_minuteswest*60 + sys_tz.tz_dsttime*3600;
 }
 
 static int
 local2utc(int time)
 {
-        return time + sys_tz.tz_minuteswest*60;
+        return time + sys_tz.tz_minuteswest*60 - sys_tz.tz_dsttime*3600;
 }
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
index 8d772fb152ecee346ad632bed05ea92ec1993530..c54e6a1350318fdd50cd00e77ea399b36e77140f 100644 (file)
@@ -382,7 +382,7 @@ smb_notify_change(struct inode *inode, struct iattr *attr)
                return -EPERM;
 
        if (((attr->ia_valid & ATTR_GID) &&
-            (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
+            (attr->ia_gid != SMB_SERVER(inode)->m.gid)))
                return -EPERM;
 
        if (((attr->ia_valid & ATTR_MODE) &&
index c766396e12371f4bcd527b824cbdaae5076ec031..05f7d789e5bc0c89b9100b8d865c1a641000f49d 100644 (file)
@@ -74,6 +74,7 @@ extern int max_files, nr_files;
 #define S_APPEND       256     /* Append-only file */
 #define S_IMMUTABLE    512     /* Immutable file */
 #define MS_NOATIME     1024    /* Do not update access times. */
+#define S_BAD_INODE    2048    /* Marker for unreadable inodes */
 
 /*
  * Flags that can be altered by MS_REMOUNT
@@ -635,6 +636,7 @@ extern struct inode * get_empty_inode(void);
 extern void insert_inode_hash(struct inode *);
 extern void clear_inode(struct inode *);
 extern struct inode * get_pipe_inode(void);
+extern void make_bad_inode(struct inode *);
 extern int get_unused_fd(void);
 extern void put_unused_fd(int);
 extern struct file * get_empty_filp(void);
index 4295a33482d94591f50f9e5fb17339bbe6ae14aa..ec81a7778532c16703f1f0972dc2ce9628137902 100644 (file)
 #define PCI_DEVICE_ID_CYCLOM_Z_Lo      0x0200
 #define PCI_DEVICE_ID_CYCLOM_Z_Hi      0x0201
 
-#define PCI_VENDOR_ID_SIGMA_DESIGNS    0x1236
-#define PCI_DEVICE_ID_SD_REALMAGIC64GX 0x6401
-
 #define PCI_VENDOR_ID_3DFX             0x121a
 #define PCI_DEVICE_ID_3DFX_VOODOO      0x0001
 
-#define PCI_VENDOR_ID_SIGMADES         0x1236
-#define PCI_DEVICE_ID_SIGMADES_6425    0x6401
+#define PCI_VENDOR_ID_SIGMA_DESIGNS    0x1236
+#define PCI_DEVICE_ID_SD_REALMAGIC64GX 0x6401
 
 #define PCI_VENDOR_ID_OPTIBASE         0x1255
 #define PCI_DEVICE_ID_OPTIBASE_FORGE   0x1110
 #define PCI_DEVICE_ID_OPTIBASE_FUSION  0x1210
-#define PCI_DEVICE_ID_OPTIBASE_VPLEX   0x2120
+#define PCI_DEVICE_ID_OPTIBASE_VPLEX   0x2110
 #define PCI_DEVICE_ID_OPTIBASE_VPLEXCC 0x2120
 #define PCI_DEVICE_ID_OPTIBASE_VQUEST  0x2130
 
index 2fa5a9700480a3eb1642645896435dd63b6d1abf..b2534bac61cba5c0fa28205717aa07607f455cb5 100644 (file)
@@ -49,7 +49,7 @@ static __inline__ int tcp_bhashfn(__u16 lport)
  * break TCP port selection. This function must also NOT wrap around
  * when the next number exceeds the largest possible port (2^16-1).
  */
-static __inline__ int tcp_bhashnext(__u16 short lport, __u16 h)
+static __inline__ int tcp_bhashnext(__u16 lport, __u16 h)
 {
         __u32 s;       /* don't change this to a smaller type! */
 
@@ -237,6 +237,8 @@ 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_v4_unhash(struct sock *sk);
+
 extern void tcp_read_wakeup(struct sock *);
 extern void tcp_write_xmit(struct sock *);
 extern void tcp_time_wait(struct sock *);
@@ -358,6 +360,8 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
                break;
 
        case TCP_CLOSE:
+               /* Preserve the invariant */
+               tcp_v4_unhash(sk);
                /* Should be about 2 rtt's */
                reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
                /* fall through */
index 398315fc30799e73a7ed07f0de368b94f06d2ff2..bed75939ac4d8b50163a2f194e46dc0b4bceee63 100644 (file)
@@ -347,6 +347,28 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
                        val = sk->bsdism;
                        break;
 
+#ifdef CONFIG_NET
+                case SO_BINDTODEVICE:
+               {
+                       struct ifreq req;
+
+                        /* Return the bound device (if any) */
+                        err=verify_area(VERIFY_WRITE,optval,sizeof(req));
+                        if(err)
+                                return err;
+
+                        memset((char *) &req, 0, sizeof(req));
+
+                        if (sk->bound_device) {
+                            strncpy(req.ifr_name, sk->bound_device->name, sizeof(req.ifr_name));
+                            (*(struct sockaddr_in *) &req.ifr_addr).sin_family = sk->bound_device->family;
+                            (*(struct sockaddr_in *) &req.ifr_addr).sin_addr.s_addr = sk->bound_device->pa_addr;
+                        }
+                        memcpy_tofs(optval, &req, sizeof(req));
+                        return 0;
+               }
+#endif
+
                default:
                        return(-ENOPROTOOPT);
        }
index b3c673e5ba7430f21aef49071e6bb72f6c6e494c..4fe8a32c9d745c41ef48478818100b3e2fa820fd 100644 (file)
@@ -620,8 +620,12 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 #endif          
        if (snum == 0) 
                snum = sk->prot->good_socknum();
-       if (snum < PROT_SOCK && !suser()) 
+        if (snum < PROT_SOCK) {
+               if (!suser()) 
                return(-EACCES);
+               if (snum == 0)
+                       return(-EAGAIN);
+       }
        
        chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr);
        if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR &&
index bea126823b3555caf7fd15cfaa931d17d3337e61..a417ac82c900274b7326bdd0258ad07ad27f70e6 100644 (file)
@@ -924,6 +924,8 @@ static __inline__ void rt_kick_free_queue(void)
 {
        struct rtable *rt, **rtp;
 
+       ip_rt_bh_mask &= ~RT_BH_FREE;
+
        rtp = &rt_free_queue;
 
        while ((rt = *rtp) != NULL)
index f1ffe88335934700b70e61d7ed1014ca9f340d1a..fdb1d65d3e7aae31b72939a12749ff97b6a617f5 100644 (file)
  *             Theodore Ts'o   :       Do secure TCP sequence numbers.
  *             David S. Miller :       New socket lookup architecture for ISS.
  *                                     This code is dedicated to John Dyson.
- *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
+ *             Elliot Poger    :       Added support for SO_BINDTODEVICE.
  *                                     
  * To Fix:
  *             Fast path the code. Two things here - fix the window calculation
@@ -529,45 +529,47 @@ unsigned short tcp_good_socknum(void)
        int retval = 0, i, end, bc;
 
        SOCKHASH_LOCK();
-        i = tcp_bhashfn(start);
-        end = i + TCP_BHTABLE_SIZE;
-        bc = binding_contour;
-        do {
-                struct sock *sk = tcp_bound_hash[i&(TCP_BHTABLE_SIZE-1)];
-                if(!sk) {
-                        /* find the smallest value no smaller than start
-                         * that has this hash value.
-                         */
-                        retval = tcp_bhashnext(start-1,i&(TCP_BHTABLE_SIZE-1));
-
-                        /* Check for decreasing load. */
-                        if (bc != 0)
-                                binding_contour = 0;
-                        goto done;
-                } else {
-                        int j = 0;
-                        do { sk = sk->bind_next; } while (++j < size && sk);
-                        if (j < size) {
-                                best = i&(TCP_BHTABLE_SIZE-1);
-                                size = j;
-                                if (bc && size <= bc)
-                                        goto verify;
-                        }
-                }
-        } while(++i != end);
-        i = best;
-
-        /* Socket load is increasing, adjust our load average. */
-        binding_contour = size;
+       i = tcp_bhashfn(start);
+       end = i + TCP_BHTABLE_SIZE;
+       bc = binding_contour;
+       do {
+               struct sock *sk = tcp_bound_hash[i&(TCP_BHTABLE_SIZE-1)];
+               if(!sk) {
+                       /* find the smallest value no smaller than start
+                        * that has this hash value.
+                        */
+                       retval = tcp_bhashnext(start-1,i&(TCP_BHTABLE_SIZE-1));
+
+                       /* Check for decreasing load. */
+                       if (bc != 0)
+                               binding_contour = 0;
+                       goto done;
+               } else {
+                       int j = 0;
+                       do { sk = sk->bind_next; } while (++j < size && sk);
+                       if (j < size) {
+                               best = i&(TCP_BHTABLE_SIZE-1);
+                               size = j;
+                               if (bc && size <= bc) {
+                                       i = best;
+                                       goto verify;
+                               }
+                       }
+               }
+       } while(++i != end);
+       i = best;
+
+       /* Socket load is increasing, adjust our load average. */
+       binding_contour = size;
 verify:
-        if (size < binding_contour)
-                binding_contour = size;
+       if (size < binding_contour)
+               binding_contour = size;
 
-        retval = tcp_bhashnext(start-1,i);
+       retval = tcp_bhashnext(start-1,i);
 
        best = retval;  /* mark the starting point to avoid infinite loops */
-        while(tcp_lport_inuse(retval)) {
-                       retval = tcp_bhashnext(retval,i);
+       while(tcp_lport_inuse(retval)) {
+               retval = tcp_bhashnext(retval,i);
                if (retval > 32767)     /* Upper bound */
                        retval = tcp_bhashnext(PROT_SOCK,i);
                if (retval == best) {
@@ -575,12 +577,12 @@ verify:
                        retval = 0;
                        break;
                }
-        }
+       }
 
 done:
-        start = (retval + 1);
-        if (start > 32767 || start < PROT_SOCK)
-                start = PROT_SOCK;
+       start = (retval + 1);
+       if (start > 32767 || start < PROT_SOCK)
+               start = PROT_SOCK;
        SOCKHASH_UNLOCK();
 
        return retval;
@@ -2042,7 +2044,7 @@ static void tcp_close(struct sock *sk, unsigned long timeout)
 
        /* Now that the socket is dead, if we are in the FIN_WAIT2 state
         * we may need to set up a timer.
-         */
+        */
        if (sk->state==TCP_FIN_WAIT2)
        {
                int timer_active=del_timer(&sk->timer);
index 92df9b6c3f8f26111647a6a89a9b2c30979d8996..a8e367c747ca8059ad68137b43bb81997569d623 100644 (file)
@@ -175,7 +175,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
 
        tcp_statistics.TcpOutSegs++;  
        skb->seq = ntohl(th->seq);
-       skb->end_seq = skb->seq + size - 4*th->doff;
+       skb->end_seq = skb->seq + size - 4*th->doff + th->fin;
 
        /*
         *      We must queue if
@@ -880,6 +880,8 @@ void tcp_send_fin(struct sock *sk)
                        return;
                }
        }
+
+       clear_delayed_acks(sk);
        
        /*
         *      We ought to check if the end of the queue is a buffer and
index 458a7c72b93af6704f434d4d8787e6d2b0fd5c7c..397e236897ceb7dacebd275a4e9470bb9369f1d4 100644 (file)
@@ -139,12 +139,10 @@ void net_timer (unsigned long data)
 
                case TIME_CLOSE:
                        /* We've waited long enough, close the socket. */
-                       sk->state = TCP_CLOSE;
-                       delete_timer (sk);
+                       tcp_set_state(sk, TCP_CLOSE);
                        if (!sk->dead)
                                sk->state_change(sk);
                        sk->shutdown = SHUTDOWN_MASK;
-                       reset_timer (sk, TIME_DONE, TCP_DONE_TIME);
                        break;
 
                default: