]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.3 1.1.3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:27 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:27 +0000 (15:09 -0500)
48 files changed:
Configure
Makefile
config.in
drivers/block/ll_rw_blk.c
drivers/scsi/fdomain.c
fs/block_dev.c
fs/buffer.c
fs/devices.c
fs/ext/file.c
fs/ext/freelists.c
fs/ext/inode.c
fs/ext/namei.c
fs/ext/truncate.c
fs/ext2/balloc.c
fs/ext2/file.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext2/truncate.c
fs/minix/bitmap.c
fs/minix/file.c
fs/minix/inode.c
fs/minix/namei.c
fs/minix/truncate.c
fs/msdos/fat.c
fs/msdos/file.c
fs/msdos/inode.c
fs/msdos/misc.c
fs/msdos/namei.c
fs/proc/array.c
fs/proc/root.c
fs/sysv/balloc.c
fs/sysv/file.c
fs/sysv/ialloc.c
fs/sysv/inode.c
fs/sysv/namei.c
fs/sysv/truncate.c
fs/xiafs/bitmap.c
fs/xiafs/file.c
fs/xiafs/inode.c
fs/xiafs/namei.c
fs/xiafs/truncate.c
include/linux/ext2_fs.h
include/linux/fs.h
include/linux/mm.h
include/linux/sys.h
mm/swap.c

index d936ab76c547719cfbf29628b9ffb891e3f51b2a..22fffb16ed1d843068fe9815c9f19366bce4b725 100644 (file)
--- a/Configure
+++ b/Configure
 #
 # Each line in the config file is a command.
 #
-#      # internal comment
-#
-#              Lines beginning with a `#' are ignored.
-#
-#      : message
-#
-#              `:' causes the line to be echoed to the screen.
-#
-#      * external comment
-#
-#              `*' causes the line to be placed in the output
-#              configuration file as a comment as well as being
-#              echoed to the screen.
-#
-#      if condition
-#              ... commands ...
-#      else
-#              ... commands ...
-#      fi
-#
-#              This does the obvious thing.  The `else' clause is
-#              optional.  Conditionals can be nested.
-#
-#              The `condition' can be any valid bash expression.
-#              They typically involve tests against environment
-#              variables set by configuration options.  For example,
-#
-#              if [ "$CONFIG_SCSI" = "y" ]
-#                      ...More stuff...
-#              fi
-#
-#              Note!  That there is no `then' keyword.
-#
-#      bool 'prompt' CONFIG_VARIABLE default
-#
-#              This prompts the user for a boolean value.
-#              The prompt may not contain an apostrophe.
-#              `default' should be either `y' or `n'.
-#              The user's response is recorded in four places.
-#
-#              In .config, if `y'
-#                      CONFIG_VARIABLE = CONFIG_VARIABLE
-#              In .config, if `n'
-#                      # CONFIG_VARIABLE is not set
-#                      
-#              In autoconf.h, if `y'
-#                      #define CONFIG_VARIABLE 1
-#              In autoconf.h, if `n'
-#                      #undef CONFIG_VARIABLE
-#
-#              In config.in, if `y'
-#                      bool 'prompt' CONFIG_VARIABLE y
-#              In config.in, if `n'
-#                      bool 'prompt' CONFIG_VARIABLE n
-#
-#              In the environment of the Configure script, if `y'
-#                      CONFIG_VARIABLE = y
-#              In the environment of the Configure script, if `n'
-#                      CONFIG_VARIABLE = n
-#
-#              The value is placed into the environment of the Configure
-#              script so that later parts of config.in can use the `if'
-#              command to inspect the results of previous queries.
-#
-#      int 'prompt' CONFIG_VARIABLE default
-#
-#              This prompts the user for an integer value.
-#              The prompt may not contain an apostrophe.
-#              `default' should be an integer.
-#
-#              The response is recorded as follows.
-#
-#              In .config
-#                      CONFIG_VARIABLE = response
-#              In autoconf.h
-#                      #define CONFIG_VARIABLE (response)
-#              In config.in
-#                      int 'prompt' CONFIG_VARIABLE response
-#              In the environment of the Configure script
-#                      CONFIG_VARIABLE = response
-#
 # 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13
 # with an empty IFS.
 
@@ -114,58 +33,85 @@ set -f -h
 #      readln prompt default
 #
 function readln () {
-       echo -n "$1"
-       IFS='@' read ans </dev/tty || exit 1
-       [ -z "$ans" ] && ans=$2
+       if [ "$DEFAULT" = "-d" ]; then
+               echo "$1"
+               ans=$2
+       else
+               echo -n "$1"
+               IFS='@' read ans </dev/tty || exit 1
+               [ -z "$ans" ] && ans=$2
+       fi
+}
+
+#
+# change updates the "config.new" file according to the answer
+#
+#      change define old new
+#
+function change () {
+       if [ "$2" != "$3" ]; then
+               sed "s/$1 $2$/$1 $3/" < $CONFIG_NEW > .tmpc
+               mv .tmpc $CONFIG_NEW
+       fi
 }
 
+#
+# comment does some pretty-printing
+#
+#      comment 'xxx'
+# 
+function comment () {
+       echo "*"; echo "* $1" ; echo "*"
+       (echo "" ; echo "#"; echo "# $1" ; echo "#") >>$CONFIG
+       (echo "" ; echo "/*"; echo " * $1" ; echo " */") >>$CONFIG_H
+}
+
+#
 # bool processes a boolean argument
 #
-#      bool tail
+#      bool question define default
 #
 function bool () {
-       # Slimier hack to get bash to rescan a line.
-       eval "set -- $1"
        ans=""
        while [ "$ans" != "y" -a "$ans" != "n" ]; do
                readln "$1 ($2) [$3] " "$3"
        done
        if [ "$ans" = "y" ]; then
-               echo "$2 = $2" >>$CONFIG
+               echo "  $2 = $2" >>$CONFIG
                echo "#define $2 1" >>$CONFIG_H
        else
                echo "# $2 is not set" >>$CONFIG
-               echo "#undef $2" >>$CONFIG_H
+               echo "#undef  $2" >>$CONFIG_H
        fi
-       raw_input_line="bool '$1' $2 $ans"
+       change $2 $3 $ans
        eval "$2=$ans"
 }
 
+#
 # int processes an integer argument
 #
-#      int tail
+#      int question define default
 #
 function int () {
        # Slimier hack to get bash to rescan a line.
-       eval "set -- $1"
        ans="x"
        while [ $[$ans+0] != "$ans" ]; do
                readln "$1 ($2) [$3] " "$3"
        done
-       echo "$2 = $ans" >>$CONFIG
+       echo "  $2 = $ans" >>$CONFIG
        echo "#define $2 ($ans)" >>$CONFIG_H
-       raw_input_line="int '$1' $2 $ans"
        eval "$2=$ans"
 }
 
 CONFIG=.tmpconfig
-CONFIG_H=include/linux/autoconf.h
-trap "rm -f $CONFIG $CONFIG_H config.new ; exit 1" 1 2
+CONFIG_H=.tmpconfig.h
+CONFIG_NEW=config.new
+trap "rm -f $CONFIG $CONFIG_H $CONFIG_NEW ; exit 1" 1 2
 
 #
 # Make sure we start out with a clean slate.
 #
-> config.new
+cp config.in $CONFIG_NEW
 echo "#" > $CONFIG
 echo "# Automatically generated make config: don't edit" >> $CONFIG
 echo "#" >> $CONFIG
@@ -174,62 +120,16 @@ echo "/*" > $CONFIG_H
 echo " * Automatically generated C config: don't edit" >> $CONFIG_H
 echo " */" >> $CONFIG_H
 
-stack=''
-branch='t'
-
-while IFS='@' read raw_input_line
-do
-       # Slimy hack to get bash to rescan a line.
-       read cmd rest <<-END_OF_COMMAND
-               $raw_input_line
-       END_OF_COMMAND
-
-       if [ "$cmd" = "*" ]; then
-               if [ "$branch" = "t" ]; then
-                       echo "$raw_input_line"
-                       echo "# $rest" >>$CONFIG
-                       if [ "$prevcmd" != "*" ]; then
-                               echo >>$CONFIG_H
-                               echo "/* $rest" >>$CONFIG_H
-                       else
-                               echo " * $rest" >>$CONFIG_H
-                       fi
-                       prevcmd="*"
-               fi
-       else
-               [ "$prevcmd" = "*" ] && echo " */" >>$CONFIG_H
-               prevcmd=""
-               case "$cmd" in
-               :)      [ "$branch" = "t" ] && echo "$raw_input_line" ;;
-               int)    [ "$branch" = "t" ] && int "$rest" ;;
-               bool)   [ "$branch" = "t" ] && bool "$rest" ;;
-               exec)   [ "$branch" = "t" ] && ( sh -c "$rest" ) ;;
-               if)     stack="$branch $stack"
-                       if [ "$branch" = "t" ] && eval "$rest"; then
-                               branch=t
-                       else
-                               branch=f
-                       fi ;;
-               else)   if [ "$branch" = "t" ]; then
-                               branch=f
-                       else
-                               read branch rest <<-END_OF_STACK
-                                       $stack
-                               END_OF_STACK
-                       fi ;;
-               fi)     [ -z "$stack" ] && echo "Error!  Extra fi." 1>&2
-                       read branch stack <<-END_OF_STACK
-                               $stack
-                       END_OF_STACK
-                       ;;
-               esac
-       fi
-       echo "$raw_input_line" >>config.new
-done
-[ "$prevcmd" = "*" ] && echo " */" >>$CONFIG_H
+DEFAULT=$1
+
+. ./config.in
 
-[ -z "$stack" ] || echo "Error!  Untermiated if." 1>&2
+if [ "$CONFIG_SOUND" = "y" ] ; then
+       $MAKE -C drivers/sound config || exit 1
+fi
 
+mv .tmpconfig .config
+mv .tmpconfig.h include/linux/autoconf.h
 mv config.in config.old
 mv config.new config.in
 
index c06f8b79d3bbbf615f83fb3972398001053124c7..e48ee72ab4ac140f71bdefea7bfba34c5e9dba76 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 2
+SUBLEVEL = 3
 
 all:   Version zImage
 
@@ -116,12 +116,11 @@ endif
 Version: dummy
        rm -f tools/version.h
 
+oldconfig:
+       $(CONFIG_SHELL) Configure -d $(OPTS)
+
 config:
-       $(CONFIG_SHELL) Configure $(OPTS) < config.in
-       @if grep -s '^CONFIG_SOUND' .tmpconfig ; then \
-               $(MAKE) -C drivers/sound config; \
-               else : ; fi
-       mv .tmpconfig .config
+       $(CONFIG_SHELL) Configure $(OPTS)
 
 linuxsubdirs: dummy
        set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
index 42e4599177a751d202c9664ae71b06d99c0640ba..77babfaf3b7463b6cc6e83ffbf936105f2f8cbff 100644 (file)
--- a/config.in
+++ b/config.in
@@ -2,9 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
-*
-* General setup
-*
+
+comment 'General setup'
+
 bool 'Kernel math emulation' CONFIG_MATH_EMULATION y
 bool 'Normal harddisk support' CONFIG_BLK_DEV_HD y
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
@@ -12,59 +12,60 @@ bool 'TCP/IP networking' CONFIG_INET y
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
 bool 'System V IPC' CONFIG_SYSVIPC y
 bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y
-*
-* Program binary formats
-*
+
+comment 'Program binary formats'
+
 bool 'Elf executables' CONFIG_BINFMT_ELF y
 bool 'COFF executables' CONFIG_BINFMT_COFF y
-*
-* SCSI support
-*
+
+comment 'SCSI support'
+
 bool 'SCSI support?' CONFIG_SCSI n
-if [ "$CONFIG_SCSI" = "n" ]
-:
-: Skipping SCSI configuration options...
-:
+
+if [ "$CONFIG_SCSI" = "n" ]; then
+
+comment 'Skipping SCSI configuration options...'
+
 else
-       *
-       * SCSI support type (disk, tape, CDrom)
-       *
+
+comment 'SCSI support type (disk, tape, CDrom)'
+
 bool 'Scsi disk support' CONFIG_BLK_DEV_SD y
-bool 'Scsi tape support' CONFIG_CHR_DEV_ST y
-bool 'Scsi CDROM support' CONFIG_BLK_DEV_SR y
-bool 'Scsi generic support' CONFIG_CHR_DEV_SG y
-       *
-       * SCSI low-level drivers
-       *
-bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X y
+bool 'Scsi tape support' CONFIG_CHR_DEV_ST n
+bool 'Scsi CDROM support' CONFIG_BLK_DEV_SR n
+bool 'Scsi generic support' CONFIG_CHR_DEV_SG n
+
+comment 'SCSI low-level drivers'
+
+bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n
 bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y
-bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 y
-bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN y
-bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 y
-bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 y
-bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE y
-bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 y
-bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR y
-bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST y
+bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n
+bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n
+bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n
+bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n
+bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n
+bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n
+bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n
+bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n
 fi
-*
-* Network device support
-*
+
+comment 'Network device support'
+
 bool 'Network device support?' CONFIG_ETHERCARDS y
-if [ "$CONFIG_ETHERCARDS" = "n" ]
-:
-: Skipping ethercard configuration options...
-:
+if [ "$CONFIG_ETHERCARDS" = "n" ]; then
+
+comment 'Skipping ethercard configuration options...'
+
 else
 bool 'SLIP (serial line) support' CONFIG_SLIP n
-if [ "$CONFIG_SLIP" = "y" ]
+if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' SL_COMPRESSED y
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
 #bool 'PPP (point-to-point) support' CONFIG_PPP n
 bool 'PLIP (parallel port) support' CONFIG_PLIP n
 bool 'NE2000/NE1000 support' CONFIG_NE2000 n
-bool 'WD80*3 support' CONFIG_WD80x3 y
+bool 'WD80E3 support' CONFIG_WD80x3 y
 bool 'SMC Ultra support' CONFIG_ULTRA n
 bool '3c501 support' CONFIG_EL1 n
 bool '3c503 support' CONFIG_EL2 n
@@ -77,20 +78,22 @@ bool 'AT1700 support' CONFIG_AT1700 n
 #bool 'Zenith Z-Note support' CONFIG_ZNET n
 #bool 'EtherExpress support' CONFIG_EEXPRESS n
 bool 'DEPCA support' CONFIG_DEPCA n
-#bool 'NI52** support' CONFIG_NI52 n
-#bool 'NI65** support' CONFIG_NI65 n
+#bool 'NI52EE support' CONFIG_NI52 n
+#bool 'NI65EE support' CONFIG_NI65 n
 #bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n
 #bool 'Cabletron E21xx support (not recommended)' CONFIG_E21 n
 bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
 bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
 fi
-*
+
+comment 'CD-ROM drivers'
+
 bool 'Sony CDU31A CDROM driver support' CONFIG_CDU31A n
 bool 'Mitsumi CDROM driver support' CONFIG_MCD n
 bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n
-*
-* Filesystems
-*
+
+comment 'Filesystems'
+
 bool 'Standard (minix) fs support' CONFIG_MINIX_FS y
 bool 'Extended fs support' CONFIG_EXT_FS n
 bool 'Second extended fs support' CONFIG_EXT2_FS y
@@ -101,13 +104,13 @@ bool 'NFS filesystem support' CONFIG_NFS_FS y
 bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
 bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
 bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
-*
-*  character devices
-*
+
+comment 'character devices'
+
 bool 'Parallel printer support' CONFIG_PRINTER n
 bool 'Logitech busmouse support' CONFIG_BUSMOUSE n
 bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE y
-if [ "$CONFIG_PSMOUSE" = "y" ]
+if [ "$CONFIG_PSMOUSE" = "y" ]; then
 bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y
 fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
@@ -115,23 +118,18 @@ bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
 bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
 bool 'QIC-02 tape support' CONFIG_TAPE_QIC02 n
 bool 'QIC-117 tape support' CONFIG_FTAPE n
-if [ "$CONFIG_FTAPE" = "y" ]
+if [ "$CONFIG_FTAPE" = "y" ]; then
 int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
 fi
-*
-* Sound
-*
+
+comment 'Sound'
+
 bool 'Sound card support' CONFIG_SOUND n
-*
-* Kernel hacking
-*
+
+comment 'Kernel hacking'
+
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
 bool 'Kernel profiling support' CONFIG_PROFILE n
-if [ "$CONFIG_SCSI" = "y" ]
+if [ "$CONFIG_SCSI" = "y" ]; then
 bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
 fi
-if [ "$CONFIG_SOUND" = "y" ]
-  exec touch .makesound
-else
-  exec rm -f .makesound
-fi
index 5e42788dd5dad201e8a3ee73c693509cecb4d456..a39d1b4fe65d2e236ad6972c50d13ec7f31ad510 100644 (file)
@@ -156,7 +156,7 @@ static void add_request(struct blk_dev_struct * dev, struct request * req)
        req->next = NULL;
        cli();
        if (req->bh)
-               req->bh->b_dirt = 0;
+               mark_buffer_clean(req->bh);
        if (!(tmp = dev->current_request)) {
                dev->current_request = req;
                (dev->request_fn)();
@@ -240,12 +240,12 @@ repeat:
                            !req->waiting &&
                            req->cmd == rw &&
                            req->sector + req->nr_sectors == sector &&
-                           req->nr_sectors < 254)
+                           req->nr_sectors < 244)
                        {
                                req->bhtail->b_reqnext = bh;
                                req->bhtail = bh;
                                req->nr_sectors += count;
-                               bh->b_dirt = 0;
+                               mark_buffer_clean(bh);
                                sti();
                                return;
                        }
@@ -254,14 +254,14 @@ repeat:
                            !req->waiting &&
                            req->cmd == rw &&
                            req->sector - count == sector &&
-                           req->nr_sectors < 254)
+                           req->nr_sectors < 244)
                        {
                                req->nr_sectors += count;
                                bh->b_reqnext = req->bh;
                                req->buffer = bh->b_data;
                                req->current_nr_sectors = count;
                                req->sector = sector;
-                               bh->b_dirt = 0;
+                               mark_buffer_clean(bh);
                                req->bh = bh;
                                sti();
                                return;
index 8746a1c0cb6adfe7df0ed28d7942e8d74aeb10fa..8823f792699abeafb582fae7f9752b4f3ec436b6 100644 (file)
@@ -1,10 +1,10 @@
 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Fri Apr  1 23:47:55 1994 by faith@cs.unc.edu
+ * Revised: Thu Apr  7 20:30:09 1994 by faith@cs.unc.edu
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994 Rickard E. Faith
  *
- * $Id: fdomain.c,v 5.15 1994/04/02 04:48:04 root Exp $
+ * $Id: fdomain.c,v 5.16 1994/04/08 00:30:15 root Exp $
 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 #include <linux/string.h>
 #include <linux/ioport.h>
 
-#define VERSION          "$Revision: 5.15 $"
+#define VERSION          "$Revision: 5.16 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -282,6 +282,9 @@ static int               TMC_Status_port;
 static int               Write_FIFO_port;
 static int               Write_SCSI_Data_port;
 
+static int               FIFO_Size = 0x2000; /* 8k FIFO for
+                                               pre-tmc18c30 chips */
+
 extern void              fdomain_16x0_intr( int unused );
 
 static void *addresses[] = {
@@ -421,7 +424,10 @@ static int fdomain_is_valid_port( int port )
       outb( 0x80, port + IO_Control );
       if (inb( port + Configuration2 ) & 0x80 == 0x80) {
         outb( 0x00, port + IO_Control );
-        if (inb( port + Configuration2 ) & 0x80 == 0x00) chip = tmc18c30;
+        if (inb( port + Configuration2 ) & 0x80 == 0x00) {
+           chip = tmc18c30;
+           FIFO_Size = 0x800;  /* 2k FIFO */
+        }
       }
 #else
 
@@ -429,7 +435,10 @@ static int fdomain_is_valid_port( int port )
                                    have problems.  Lets assume it is an
                                    18c30 if the RAM is disabled. */
 
-      if (inb( port + Configuration2 ) & 0x02) chip = tmc18c30;
+      if (inb( port + Configuration2 ) & 0x02) {
+        chip      = tmc18c30;
+        FIFO_Size = 0x800;     /* 2k FIFO */
+      }
 #endif
                                /* If that failed, we are an 18c50. */
    }
@@ -1127,7 +1136,7 @@ void fdomain_16x0_intr( int unused )
    }
 
    if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
-      while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
+      while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
 #if EVERY_ACCESS
         printk( "DC=%d, ", data_count ) ;
 #endif
index cf4ab3b28277e4f4c9e7e5b4113a791c54fbcca5..89b4f755fb15c91640af1582331b5cc6f418b8bf 100644 (file)
 extern int *blk_size[];
 extern int *blksize_size[];
 
+#define NBUF 64
+
 int block_write(struct inode * inode, struct file * filp, char * buf, int count)
 {
-       int blocksize, blocksize_bits, i;
-       int block;
+       int blocksize, blocksize_bits, i, j;
+       int block, blocks;
        int offset;
        int chars;
        int written = 0;
+       int cluster_list[4];
+       struct buffer_head * bhlist[NBUF];
+       int blocks_per_cluster;
        unsigned int size;
        unsigned int dev;
        struct buffer_head * bh;
@@ -38,6 +43,8 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
                i >>= 1;
        }
 
+       blocks_per_cluster = PAGE_SIZE / blocksize;
+
        block = filp->f_pos >> blocksize_bits;
        offset = filp->f_pos & (blocksize-1);
 
@@ -51,11 +58,50 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
                chars = blocksize - offset;
                if (chars > count)
                        chars=count;
+
+#if 0
                if (chars == blocksize)
                        bh = getblk(dev, block, blocksize);
                else
-                       bh = breada(dev, block, blocksize, offset, 
-                                   size << blocksize_bits);
+                       bh = breada(dev,block,block+1,block+2,-1);
+
+#else
+               for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
+               if((block % blocks_per_cluster) == 0)
+                 generate_cluster(dev, cluster_list, blocksize);
+               bh = getblk(dev, block, blocksize);
+
+               if (chars != blocksize && !bh->b_uptodate) {
+                 if(!filp->f_reada ||
+                    !read_ahead[MAJOR(dev)]) {
+                   /* We do this to force the read of a single buffer */
+                   brelse(bh);
+                   bh = bread(dev,block,blocksize);
+                 } else {
+                   /* Read-ahead before write */
+                   blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
+                   if (block + blocks > size) blocks = size - block;
+                   if (blocks > NBUF) blocks=NBUF;
+                   blocks -= (block % blocks_per_cluster);
+                   if(!blocks) blocks = 1;
+                   bhlist[0] = bh;
+                   for(i=1; i<blocks; i++){
+                     if(((i+block) % blocks_per_cluster) == 0) {
+                       for(j=0; j<blocks_per_cluster; j++) cluster_list[j] = block+i+j;
+                       generate_cluster(dev, cluster_list, blocksize);
+                     };
+                     bhlist[i] = getblk (dev, block+i, blocksize);
+                     if(!bhlist[i]){
+                       while(i >= 0) brelse(bhlist[i--]);
+                       return written? written: -EIO;
+                     };
+                   };
+                   ll_rw_block(READ, blocks, bhlist);
+                   for(i=1; i<blocks; i++) brelse(bhlist[i]);
+                     
+                 };
+               };
+#endif
                block++;
                if (!bh)
                        return written?written:-EIO;
@@ -68,23 +114,23 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
                p += chars;
                buf += chars;
                bh->b_uptodate = 1;
-               dirtify_buffer(bh, 0);
+               mark_buffer_dirty(bh, 0);
                brelse(bh);
        }
+       filp->f_reada = 1;
        return written;
 }
 
-#define NBUF 32
-
 int block_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
        unsigned int block;
        unsigned int offset;
        int blocksize;
        int blocksize_bits, i;
-       unsigned int left;
-       unsigned int blocks;
+       unsigned int blocks, rblocks, left;
        int bhrequest, uptodate;
+       int cluster_list[4];
+       int blocks_per_cluster;
        struct buffer_head ** bhb, ** bhe;
        struct buffer_head * buflist[NBUF];
        struct buffer_head * bhreq[NBUF];
@@ -110,6 +156,8 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
        else
                size = INT_MAX;
 
+       blocks_per_cluster = PAGE_SIZE / blocksize;
+
        if (offset > size)
                left = 0;
        else
@@ -122,12 +170,16 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
        block = offset >> blocksize_bits;
        offset &= blocksize-1;
        size >>= blocksize_bits;
-       blocks = (left + offset + blocksize - 1) >> blocksize_bits;
+       rblocks = blocks = (left + offset + blocksize - 1) >> blocksize_bits;
        bhb = bhe = buflist;
        if (filp->f_reada) {
-               blocks += read_ahead[MAJOR(dev)] / (blocksize >> 9);
+               if(blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9))
+                 blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9);
                if (block + blocks > size)
                        blocks = size - block;
+               blocks -= (block % blocks_per_cluster);
+               if(rblocks > blocks) blocks = rblocks;
+               
        }
 
        /* We do this in a two stage process.  We first try and request
@@ -145,6 +197,12 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
                uptodate = 1;
                while (blocks) {
                        --blocks;
+#if 1
+                       if((block % blocks_per_cluster) == 0) {
+                         for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
+                         generate_cluster(dev, cluster_list, blocksize);
+                       }
+#endif
                        *bhb = getblk(dev, block++, blocksize);
                        if (*bhb && !(*bhb)->b_uptodate) {
                                uptodate = 0;
@@ -163,8 +221,10 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
                }
 
                /* Now request them all */
-               if (bhrequest)
+               if (bhrequest) {
                        ll_rw_block(READ, bhrequest, bhreq);
+                       refill_freelist(blocksize);
+               }
 
                do { /* Finish off all I/O that has actually completed */
                        if (*bhe) {
index 49f1e4ae028b32ce5a9dc3c2e6b649d8720f51ec..9706d0f180740b8b9a0b37f0b04f72cc4273d6f6 100644 (file)
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/errno.h>
+#include <linux/malloc.h>
 
 #include <asm/system.h>
+#include <asm/segment.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_SCSI
@@ -46,23 +48,76 @@ extern int check_cdu31a_media_change(int, int);
 extern int check_mcd_media_change(int, int);
 #endif
 
+#define NR_SIZES 4
 static char buffersize_index[9] = {-1,  0,  1, -1,  2, -1, -1, -1, 3};
+static short int bufferindex_size[NR_SIZES] = {512, 1024, 2048, 4096};
 
 #define BUFSIZE_INDEX(X) (buffersize_index[(X)>>9])
 
 static int grow_buffers(int pri, int size);
-
-static struct buffer_head * hash_table[NR_HASH];
-static struct buffer_head * free_list = NULL;
+static int shrink_specific_buffers(unsigned int priority, int size);
+static int maybe_shrink_lav_buffers(int);
+
+static int nr_hash = 0;  /* Size of hash table */
+static struct buffer_head ** hash_table;
+struct buffer_head ** buffer_pages;
+static struct buffer_head * lru_list[NR_LIST] = {NULL, };
+static struct buffer_head * free_list[NR_SIZES] = {NULL, };
 static struct buffer_head * unused_list = NULL;
 static struct wait_queue * buffer_wait = NULL;
 
 int nr_buffers = 0;
+int nr_buffers_type[NR_LIST] = {0,};
+int nr_buffers_size[NR_SIZES] = {0,};
+int nr_buffers_st[NR_SIZES][NR_LIST] = {{0,},};
+int buffer_usage[NR_SIZES] = {0,};  /* Usage counts used to determine load average */
+int buffers_lav[NR_SIZES] = {0,};  /* Load average of buffer usage */
+int nr_free[NR_SIZES] = {0,};
 int buffermem = 0;
 int nr_buffer_heads = 0;
 static int min_free_pages = 20;        /* nr free pages needed before buffer grows */
 extern int *blksize_size[];
 
+/* Here is the parameter block for the bdflush process. */
+static void wakeup_bdflush(int);
+
+#define N_PARAM 9
+#define LAV
+
+static union bdflush_param{
+       struct {
+               int nfract;  /* Percentage of buffer cache dirty to 
+                               activate bdflush */
+               int ndirty;  /* Maximum number of dirty blocks to write out per
+                               wake-cycle */
+               int nrefill; /* Number of clean buffers to try and obtain
+                               each time we call refill */
+               int nref_dirt; /* Dirty buffer threshold for activating bdflush
+                                 when trying to refill buffers. */
+               int clu_nfract;  /* Percentage of buffer cache to scan to 
+                                   search for free clusters */
+               int age_buffer;  /* Time for normal buffer to age before 
+                                   we flush it */
+               int age_super;  /* Time for superblock to age before we 
+                                  flush it */
+               int lav_const;  /* Constant used for load average (time
+                                  constant */
+               int lav_ratio;  /* Used to determine how low a lav for a
+                                  particular size can go before we start to
+                                  trim back the buffers */
+       } b_un;
+       unsigned int data[N_PARAM];
+} bdf_prm = {{25, 500, 64, 256, 15, 3000, 500, 1884, 2}};
+
+/* The lav constant is set for 1 minute, as long as the update process runs
+   every 5 seconds.  If you change the frequency of update, the time
+   constant will also change. */
+
+
+/* These are the min and max parameter values that we will allow to be assigned */
+static int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   100,   100, 1, 1};
+static int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 60000, 60000, 2047, 5};
+
 /*
  * Rewrote the wait-routines to use the "new" wait-queue functionality,
  * and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -93,61 +148,81 @@ repeat:
    return until all buffer writes have completed.  Sync() may return
    before the writes have finished; fsync() may not. */
 
+
+/* Godamity-damn.  Some buffers (bitmaps for filesystems)
+   spontaneously dirty themselves without ever brelse being called.
+   We will ultimately want to put these in a separate list, but for
+   now we search all of the lists for dirty buffers */
+
 static int sync_buffers(dev_t dev, int wait)
 {
        int i, retry, pass = 0, err = 0;
-       struct buffer_head * bh;
+       int nlist, ncount;
+       struct buffer_head * bh, *next;
 
        /* One pass for no-wait, three for wait:
           0) write out all dirty, unlocked buffers;
           1) write out all dirty buffers, waiting if locked;
-          2) wait for completion by waiting for all buffers to unlock.
-        */
-repeat:
+          2) wait for completion by waiting for all buffers to unlock. */
+ repeat:
        retry = 0;
-       bh = free_list;
-       for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
-               if (dev && bh->b_dev != dev)
-                       continue;
-#ifdef 0 /* Disable bad-block debugging code */
-               if (bh->b_req && !bh->b_lock &&
-                   !bh->b_dirt && !bh->b_uptodate)
-                       printk ("Warning (IO error) - orphaned block %08x on %04x\n",
-                               bh->b_blocknr, bh->b_dev);
-#endif
-               if (bh->b_lock)
-               {
-                       /* Buffer is locked; skip it unless wait is
-                          requested AND pass > 0. */
-                       if (!wait || !pass) {
-                               retry = 1;
-                               continue;
-                       }
-                       wait_on_buffer (bh);
-               }
-               /* If an unlocked buffer is not uptodate, there has been 
-                  an IO error. Skip it. */
-               if (wait && bh->b_req && !bh->b_lock &&
-                   !bh->b_dirt && !bh->b_uptodate)
-               {
-                       err = 1;
-                       continue;
-               }
-               /* Don't write clean buffers.  Don't write ANY buffers
-                  on the third pass. */
-               if (!bh->b_dirt || pass>=2)
-                       continue;
-               bh->b_count++;
-               ll_rw_block(WRITE, 1, &bh);
-               bh->b_count--;
-               retry = 1;
-       }
+       ncount = 0;
+       /* We search all lists as a failsafe mechanism, not because we expect
+          there to be dirty buffers on any of the other lists. */
+       for(nlist = 0; nlist < NR_LIST; nlist++)
+        {
+        repeat1:
+                bh = lru_list[nlist];
+                if(!bh) continue;
+                for (i = nr_buffers_type[nlist]*2 ; i-- > 0 ; bh = next) {
+                        if(bh->b_list != nlist) goto repeat1;
+                        next = bh->b_next_free;
+                        if(!lru_list[nlist]) break;
+                        if (dev && bh->b_dev != dev)
+                                 continue;
+                        if (bh->b_lock)
+                         {
+                                 /* Buffer is locked; skip it unless wait is
+                                    requested AND pass > 0. */
+                                 if (!wait || !pass) {
+                                         retry = 1;
+                                         continue;
+                                 }
+                                 wait_on_buffer (bh);
+                         }
+                        /* If an unlocked buffer is not uptodate, there has
+                            been an IO error. Skip it. */
+                        if (wait && bh->b_req && !bh->b_lock &&
+                            !bh->b_dirt && !bh->b_uptodate)
+                         {
+                                 err = 1;
+                                 printk("Weird - unlocked, clean and not uptodate buffer on %d list %d\n", nlist);
+                                 continue;
+                         }
+                        /* Don't write clean buffers.  Don't write ANY buffers
+                           on the third pass. */
+                        if (!bh->b_dirt || pass>=2)
+                                 continue;
+                        bh->b_count++;
+                        bh->b_flushtime = 0;
+                        ll_rw_block(WRITE, 1, &bh);
+
+                        if(nlist != BUF_DIRTY) { 
+                                printk("[%d %x %d] ", nlist, bh->b_dev, bh->b_blocknr);
+                                ncount++;
+                        };
+                        bh->b_count--;
+                        retry = 1;
+                }
+        }
+       if (ncount) printk("sys_sync: %d dirty buffers not on dirty list\n", ncount);
+       
        /* If we are waiting for the sync to succeed, and if any dirty
           blocks were written, then repeat; on the second pass, only
           wait for buffers being written (do not pass to write any
           more buffers on the second pass). */
        if (wait && retry && ++pass<=2)
-               goto repeat;
+                goto repeat;
        return err;
 }
 
@@ -195,15 +270,20 @@ asmlinkage int sys_fsync(unsigned int fd)
 void invalidate_buffers(dev_t dev)
 {
        int i;
+       int nlist;
        struct buffer_head * bh;
 
-       bh = free_list;
-       for (i = nr_buffers*2 ; --i > 0 ; bh = bh->b_next_free) {
-               if (bh->b_dev != dev)
-                       continue;
-               wait_on_buffer(bh);
-               if (bh->b_dev == dev)
-                       bh->b_uptodate = bh->b_dirt = bh->b_req = 0;
+       for(nlist = 0; nlist < NR_LIST; nlist++) {
+               bh = lru_list[nlist];
+               for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; 
+                    bh = bh->b_next_free) {
+                       if (bh->b_dev != dev)
+                                continue;
+                       wait_on_buffer(bh);
+                       if (bh->b_dev == dev)
+                                bh->b_flushtime = bh->b_uptodate = 
+                                         bh->b_dirt = bh->b_req = 0;
+               }
        }
 }
 
@@ -280,7 +360,7 @@ void check_disk_change(dev_t dev)
 #endif
 }
 
-#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
+#define _hashfn(dev,block) (((unsigned)(dev^block))%nr_hash)
 #define hash(dev,block) hash_table[_hashfn(dev,block)]
 
 static inline void remove_from_hash_queue(struct buffer_head * bh)
@@ -294,59 +374,118 @@ static inline void remove_from_hash_queue(struct buffer_head * bh)
        bh->b_next = bh->b_prev = NULL;
 }
 
-static inline void remove_from_free_list(struct buffer_head * bh)
+static inline void remove_from_lru_list(struct buffer_head * bh)
 {
        if (!(bh->b_prev_free) || !(bh->b_next_free))
-               panic("VFS: Free block list corrupted");
+               panic("VFS: LRU block list corrupted");
+       if (bh->b_dev == 0xffff) panic("LRU list corrupted");
        bh->b_prev_free->b_next_free = bh->b_next_free;
        bh->b_next_free->b_prev_free = bh->b_prev_free;
-       if (free_list == bh)
-               free_list = bh->b_next_free;
+
+       if (lru_list[bh->b_list] == bh)
+                lru_list[bh->b_list] = bh->b_next_free;
+       if(lru_list[bh->b_list] == bh)
+                lru_list[bh->b_list] = NULL;
+       bh->b_next_free = bh->b_prev_free = NULL;
+}
+
+static inline void remove_from_free_list(struct buffer_head * bh)
+{
+        int isize = BUFSIZE_INDEX(bh->b_size);
+       if (!(bh->b_prev_free) || !(bh->b_next_free))
+               panic("VFS: Free block list corrupted");
+       if(bh->b_dev != 0xffff) panic("Free list corrupted");
+       if(!free_list[isize])
+                panic("Free list empty");
+       nr_free[isize]--;
+       if(bh->b_next_free == bh)
+                free_list[isize] = NULL;
+       else {
+               bh->b_prev_free->b_next_free = bh->b_next_free;
+               bh->b_next_free->b_prev_free = bh->b_prev_free;
+               if (free_list[isize] == bh)
+                        free_list[isize] = bh->b_next_free;
+       };
        bh->b_next_free = bh->b_prev_free = NULL;
 }
 
 static inline void remove_from_queues(struct buffer_head * bh)
 {
+        if(bh->b_dev == 0xffff) {
+               remove_from_free_list(bh); /* Free list entries should not be
+                                             in the hash queue */
+               return;
+       };
+       nr_buffers_type[bh->b_list]--;
+       nr_buffers_st[BUFSIZE_INDEX(bh->b_size)][bh->b_list]--;
        remove_from_hash_queue(bh);
-       remove_from_free_list(bh);
+       remove_from_lru_list(bh);
 }
 
-static inline void put_first_free(struct buffer_head * bh)
+static inline void put_last_lru(struct buffer_head * bh)
 {
-       if (!bh || (bh == free_list))
+       if (!bh)
                return;
-       remove_from_free_list(bh);
-/* add to front of free list */
-       bh->b_next_free = free_list;
-       bh->b_prev_free = free_list->b_prev_free;
-       free_list->b_prev_free->b_next_free = bh;
-       free_list->b_prev_free = bh;
-       free_list = bh;
+       if (bh == lru_list[bh->b_list]) {
+               lru_list[bh->b_list] = bh->b_next_free;
+               return;
+       }
+       if(bh->b_dev == 0xffff) panic("Wrong block for lru list");
+       remove_from_lru_list(bh);
+/* add to back of free list */
+
+       if(!lru_list[bh->b_list]) {
+               lru_list[bh->b_list] = bh;
+               lru_list[bh->b_list]->b_prev_free = bh;
+       };
+
+       bh->b_next_free = lru_list[bh->b_list];
+       bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
+       lru_list[bh->b_list]->b_prev_free->b_next_free = bh;
+       lru_list[bh->b_list]->b_prev_free = bh;
 }
 
 static inline void put_last_free(struct buffer_head * bh)
 {
+        int isize;
        if (!bh)
                return;
-       if (bh == free_list) {
-               free_list = bh->b_next_free;
-               return;
-       }
-       remove_from_free_list(bh);
+
+       isize = BUFSIZE_INDEX(bh->b_size);      
+       bh->b_dev = 0xffff;  /* So it is obvious we are on the free list */
 /* add to back of free list */
-       bh->b_next_free = free_list;
-       bh->b_prev_free = free_list->b_prev_free;
-       free_list->b_prev_free->b_next_free = bh;
-       free_list->b_prev_free = bh;
+
+       if(!free_list[isize]) {
+               free_list[isize] = bh;
+               bh->b_prev_free = bh;
+       };
+
+       nr_free[isize]++;
+       bh->b_next_free = free_list[isize];
+       bh->b_prev_free = free_list[isize]->b_prev_free;
+       free_list[isize]->b_prev_free->b_next_free = bh;
+       free_list[isize]->b_prev_free = bh;
 }
 
 static inline void insert_into_queues(struct buffer_head * bh)
 {
 /* put at end of free list */
-       bh->b_next_free = free_list;
-       bh->b_prev_free = free_list->b_prev_free;
-       free_list->b_prev_free->b_next_free = bh;
-       free_list->b_prev_free = bh;
+
+        if(bh->b_dev == 0xffff) {
+               put_last_free(bh);
+               return;
+       };
+       if(!lru_list[bh->b_list]) {
+               lru_list[bh->b_list] = bh;
+               bh->b_prev_free = bh;
+       };
+       if (bh->b_next_free) panic("VFS: buffer LRU pointers corrupted");
+       bh->b_next_free = lru_list[bh->b_list];
+       bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
+       lru_list[bh->b_list]->b_prev_free->b_next_free = bh;
+       lru_list[bh->b_list]->b_prev_free = bh;
+       nr_buffers_type[bh->b_list]++;
+       nr_buffers_st[BUFSIZE_INDEX(bh->b_size)][bh->b_list]++;
 /* put the buffer in new hash-queue if it has a device */
        bh->b_prev = NULL;
        bh->b_next = NULL;
@@ -398,7 +537,7 @@ struct buffer_head * get_hash_table(dev_t dev, int block, int size)
 
 void set_blocksize(dev_t dev, int size)
 {
-       int i;
+       int i, nlist;
        struct buffer_head * bh, *bhnext;
 
        if (!blksize_size[MAJOR(dev)])
@@ -421,20 +560,206 @@ void set_blocksize(dev_t dev, int size)
   /* We need to be quite careful how we do this - we are moving entries
      around on the free list, and we can get in a loop if we are not careful.*/
 
-       bh = free_list;
-       for (i = nr_buffers*2 ; --i > 0 ; bh = bhnext) {
-               bhnext = bh->b_next_free; 
-               if (bh->b_dev != dev)
-                       continue;
-               if (bh->b_size == size)
-                       continue;
+       for(nlist = 0; nlist < NR_LIST; nlist++) {
+               bh = lru_list[nlist];
+               for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bhnext) {
+                       if(!bh) break;
+                       bhnext = bh->b_next_free; 
+                       if (bh->b_dev != dev)
+                                continue;
+                       if (bh->b_size == size)
+                                continue;
+                       
+                       wait_on_buffer(bh);
+                       if (bh->b_dev == dev && bh->b_size != size) {
+                               bh->b_uptodate = bh->b_dirt = 
+                                        bh->b_flushtime = 0;
+                       };
+                       remove_from_hash_queue(bh);
+               }
+       }
+}
 
-               wait_on_buffer(bh);
-               if (bh->b_dev == dev && bh->b_size != size)
-                       bh->b_uptodate = bh->b_dirt = 0;
-               remove_from_hash_queue(bh);
-/*    put_first_free(bh); */
+#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
+
+void refill_freelist(int size)
+{
+       struct buffer_head * bh, * tmp;
+       struct buffer_head * candidate[NR_LIST];
+       unsigned int best_time, winner;
+        int isize = BUFSIZE_INDEX(size);
+       int buffers[NR_LIST];
+       int i;
+       int needed;
+
+       /* First see if we even need this.  Sometimes it is advantageous
+        to request some blocks in a filesystem that we know that we will
+        be needing ahead of time. */
+
+       if(nr_free[isize] > 100) return 0;
+
+       /* If there are too many dirty buffers, we wake up the update process
+          now so as to ensure that there are still clean buffers available
+          for user processes to use (and dirty) */
+       
+       /* We are going to try and locate this much memory */
+       needed =bdf_prm.b_un.nrefill * size;  
+
+       while (nr_free_pages > min_free_pages && needed > 0 &&
+              grow_buffers(GFP_BUFFER, size)) {
+               needed -= PAGE_SIZE;
+       }
+
+       if(needed <= 0) return;
+
+       /* See if there are too many buffers of a different size.
+          If so, victimize them */
+
+       while(maybe_shrink_lav_buffers(size))
+        {
+                if(!grow_buffers(GFP_BUFFER, size)) break;
+                needed -= PAGE_SIZE;
+                if(needed <= 0) return;
+        };
+
+       /* OK, we cannot grow the buffer cache, now try and get some
+          from the lru list */
+
+       /* First set the candidate pointers to usable buffers.  This
+          should be quick nearly all of the time. */
+
+repeat0:
+       for(i=0; i<NR_LIST; i++){
+               if(i == BUF_DIRTY || i == BUF_SHARED || 
+                  nr_buffers_type[i] == 0) {
+                       candidate[i] = NULL;
+                       buffers[i] = 0;
+                       continue;
+               }
+               buffers[i] = nr_buffers_type[i];
+               for (bh = lru_list[i]; buffers[i] > 0; bh = tmp, buffers[i]--)
+                {
+                        if(buffers[i] < 0) panic("Here is the problem");
+                        tmp = bh->b_next_free;
+                        if (!bh) break;
+                        
+                        if (mem_map[MAP_NR((unsigned long) bh->b_data)] != 1 ||
+                            bh->b_dirt) {
+                                refile_buffer(bh);
+                                continue;
+                        };
+                        
+                        if (bh->b_count || bh->b_size != size)
+                                 continue;
+                        
+                        /* Buffers are written in the order they are placed 
+                           on the locked list. If we encounter a locked
+                           buffer here, this means that the rest of them
+                           are also locked */
+                        if(bh->b_lock && (i == BUF_LOCKED || i == BUF_LOCKED1)) {
+                                buffers[i] = 0;
+                                break;
+                        }
+                        
+                        if (BADNESS(bh)) continue;
+                        break;
+                };
+               if(!buffers[i]) candidate[i] = NULL; /* Nothing on this list */
+               else candidate[i] = bh;
+               if(candidate[i] && candidate[i]->b_count) panic("Here is the problem");
+       }
+       
+ repeat:
+       if(needed <= 0) return;
+       
+       /* Now see which candidate wins the election */
+       
+       winner = best_time = UINT_MAX;  
+       for(i=0; i<NR_LIST; i++){
+               if(!candidate[i]) continue;
+               if(candidate[i]->b_lru_time < best_time){
+                       best_time = candidate[i]->b_lru_time;
+                       winner = i;
+               }
+       }
+       
+       /* If we have a winner, use it, and then get a new candidate from that list */
+       if(winner != UINT_MAX) {
+               i = winner;
+               bh = candidate[i];
+               candidate[i] = bh->b_next_free;
+               if(candidate[i] == bh) candidate[i] = NULL;  /* Got last one */
+               if (bh->b_count || bh->b_size != size)
+                        panic("Busy buffer in candidate list\n");
+               if (mem_map[MAP_NR((unsigned long) bh->b_data)] != 1)
+                        panic("Shared buffer in candidate list\n");
+               if (BADNESS(bh)) panic("Buffer in candidate list with BADNESS != 0\n");
+               
+               if(bh->b_dev == 0xffff) panic("Wrong list");
+               remove_from_queues(bh);
+               bh->b_dev = 0xffff;
+               put_last_free(bh);
+               needed -= bh->b_size;
+               buffers[i]--;
+               if(buffers[i] < 0) panic("Here is the problem");
+               
+               if(buffers[i] == 0) candidate[i] = NULL;
+               
+               /* Now all we need to do is advance the candidate pointer
+                  from the winner list to the next usable buffer */
+               if(candidate[i] && buffers[i] > 0){
+                       if(buffers[i] <= 0) panic("Here is another problem");
+                       for (bh = candidate[i]; buffers[i] > 0; bh = tmp, buffers[i]--) {
+                               if(buffers[i] < 0) panic("Here is the problem");
+                               tmp = bh->b_next_free;
+                               if (!bh) break;
+                               
+                               if (mem_map[MAP_NR((unsigned long) bh->b_data)] != 1 ||
+                                   bh->b_dirt) {
+                                       refile_buffer(bh);
+                                       continue;
+                               };
+                               
+                               if (bh->b_count || bh->b_size != size)
+                                        continue;
+                               
+                               /* Buffers are written in the order they are
+                                  placed on the locked list.  If we encounter
+                                  a locked buffer here, this means that the
+                                  rest of them are also locked */
+                               if(bh->b_lock && (i == BUF_LOCKED || i == BUF_LOCKED1)) {
+                                       buffers[i] = 0;
+                                       break;
+                               }
+             
+                               if (BADNESS(bh)) continue;
+                               break;
+                       };
+                       if(!buffers[i]) candidate[i] = NULL; /* Nothing here */
+                       else candidate[i] = bh;
+                       if(candidate[i] && candidate[i]->b_count) 
+                                panic("Here is the problem");
+               }
+               
+               goto repeat;
+       }
+       
+       if(needed <= 0) return;
+       
+       /* Too bad, that was not enough. Try a little harder to grow some. */
+       
+       if (nr_free_pages > 5) {
+               if (grow_buffers(GFP_BUFFER, size)) {
+                       needed -= PAGE_SIZE;
+                       goto repeat0;
+               };
        }
+       
+       /* and repeat until we find something good */
+       if (!grow_buffers(GFP_ATOMIC, size))
+               wakeup_bdflush(1);
+       needed -= PAGE_SIZE;
+       goto repeat0;
 }
 
 /*
@@ -447,85 +772,105 @@ void set_blocksize(dev_t dev, int size)
  * 14.02.92: changed it to sync dirty buffers a bit: better performance
  * when the filesystem starts to get full of dirty blocks (I hope).
  */
-#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
 struct buffer_head * getblk(dev_t dev, int block, int size)
 {
-       struct buffer_head * bh, * tmp;
-       int buffers;
-       static int grow_size = 0;
+       struct buffer_head * bh;
+        int isize = BUFSIZE_INDEX(size);
 
+       /* Update this for the buffer size lav. */
+       buffer_usage[isize]++;
+
+       /* If there are too many dirty buffers, we wake up the update process
+          now so as to ensure that there are still clean buffers available
+          for user processes to use (and dirty) */
 repeat:
        bh = get_hash_table(dev, block, size);
        if (bh) {
                if (bh->b_uptodate && !bh->b_dirt)
-                       put_last_free(bh);
+                        put_last_lru(bh);
+               if(!bh->b_dirt) bh->b_flushtime = 0;
                return bh;
        }
-       grow_size -= size;
-       if (nr_free_pages > min_free_pages && grow_size <= 0) {
-               if (grow_buffers(GFP_BUFFER, size))
-                       grow_size = PAGE_SIZE;
-       }
-       buffers = nr_buffers;
-       bh = NULL;
 
-       for (tmp = free_list; buffers-- > 0 ; tmp = tmp->b_next_free) {
-               if (tmp->b_count || tmp->b_size != size)
-                       continue;
-               if (mem_map[MAP_NR((unsigned long) tmp->b_data)] != 1)
-                       continue;
-               if (!bh || BADNESS(tmp)<BADNESS(bh)) {
-                       bh = tmp;
-                       if (!BADNESS(tmp))
-                               break;
-               }
-#if 0
-               if (tmp->b_dirt) {
-                       tmp->b_count++;
-                       ll_rw_block(WRITEA, 1, &tmp);
-                       tmp->b_count--;
-               }
-#endif
-       }
+       while(!free_list[isize]) refill_freelist(size);
+       
+       if (find_buffer(dev,block,size))
+                goto repeat;
 
-       if (!bh) {
-               if (nr_free_pages > 5)
-                       if (grow_buffers(GFP_BUFFER, size))
-                               goto repeat;
-               if (!grow_buffers(GFP_ATOMIC, size))
-                       sleep_on(&buffer_wait);
-               goto repeat;
-       }
+       bh = free_list[isize];
+       remove_from_free_list(bh);
 
-       wait_on_buffer(bh);
-       if (bh->b_count || bh->b_size != size)
-               goto repeat;
-       if (bh->b_dirt) {
-               sync_buffers(0,0);
-               goto repeat;
-       }
-/* NOTE!! While we slept waiting for this block, somebody else might */
-/* already have added "this" block to the cache. check it */
-       if (find_buffer(dev,block,size))
-               goto repeat;
-/* OK, FINALLY we know that this buffer is the only one of its kind, */
+/* OK, FINALLY we know that this buffer is the only one of it's kind, */
 /* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
        bh->b_count=1;
        bh->b_dirt=0;
+       bh->b_lock=0;
        bh->b_uptodate=0;
+       bh->b_flushtime = 0;
        bh->b_req=0;
-       remove_from_queues(bh);
        bh->b_dev=dev;
        bh->b_blocknr=block;
        insert_into_queues(bh);
        return bh;
 }
 
+void set_writetime(struct buffer_head * buf, int flag)
+{
+        int newtime;
+
+       if (buf->b_dirt){
+               /* Move buffer to dirty list if jiffies is clear */
+               newtime = jiffies + (flag ? bdf_prm.b_un.age_super : 
+                                    bdf_prm.b_un.age_buffer);
+               if(!buf->b_flushtime || buf->b_flushtime > newtime)
+                        buf->b_flushtime = newtime;
+       } else {
+               buf->b_flushtime = 0;
+       }
+}
+
+
+static char buffer_disposition[] = {BUF_CLEAN, BUF_SHARED, BUF_LOCKED, BUF_SHARED, 
+                                     BUF_DIRTY, BUF_DIRTY, BUF_DIRTY, BUF_DIRTY};
+
+void refile_buffer(struct buffer_head * buf){
+       int i, dispose;
+       i = 0;
+       if(buf->b_dev == 0xffff) panic("Attempt to refile free buffer\n");
+       if(mem_map[MAP_NR((unsigned long) buf->b_data)] != 1) i = 1;
+       if(buf->b_lock) i |= 2;
+       if(buf->b_dirt) i |= 4;
+       dispose = buffer_disposition[i];
+       if(buf->b_list == BUF_SHARED && dispose == BUF_CLEAN)
+                dispose = BUF_UNSHARED;
+       if(dispose == -1) panic("Bad buffer settings (%d)\n", i);
+       if(dispose == BUF_CLEAN) buf->b_lru_time = jiffies;
+       if(dispose != buf->b_list)  {
+               if(dispose == BUF_DIRTY || dispose == BUF_UNSHARED)
+                        buf->b_lru_time = jiffies;
+               if(dispose == BUF_LOCKED && 
+                  (buf->b_flushtime - buf->b_lru_time) <= bdf_prm.b_un.age_super)
+                        dispose = BUF_LOCKED1;
+               remove_from_queues(buf);
+               buf->b_list = dispose;
+               insert_into_queues(buf);
+               if(dispose == BUF_DIRTY && nr_buffers_type[BUF_DIRTY] > 
+                  (nr_buffers - nr_buffers_type[BUF_SHARED]) *
+                  bdf_prm.b_un.nfract/100)
+                        wakeup_bdflush(0);
+       }
+}
+
 void brelse(struct buffer_head * buf)
 {
        if (!buf)
                return;
        wait_on_buffer(buf);
+
+       /* If dirty, mark the time this buffer should be written back */
+       set_writetime(buf, 0);
+       refile_buffer(buf);
+
        if (buf->b_count) {
                if (--buf->b_count)
                        return;
@@ -560,7 +905,8 @@ struct buffer_head * bread(dev_t dev, int block, int size)
 
 /*
  * Ok, breada can be used as bread, but additionally to mark other
- * blocks for reading as well.
+ * blocks for reading as well. End the argument list with a negative
+ * number.
  */
 
 #define NBUF 16
@@ -686,6 +1032,7 @@ static struct buffer_head * create_buffers(unsigned long page, unsigned long siz
                head = bh;
                bh->b_data = (char *) (page+offset);
                bh->b_size = size;
+               bh->b_dev = 0xffff;  /* Flag as unused */
        }
        return head;
 /*
@@ -766,6 +1113,7 @@ static unsigned long try_to_load_aligned(unsigned long address,
 {
        struct buffer_head * bh, * tmp, * arr[8];
        unsigned long offset;
+        int isize = BUFSIZE_INDEX(size);
        int * p;
        int block;
 
@@ -788,10 +1136,14 @@ static unsigned long try_to_load_aligned(unsigned long address,
                arr[block++] = bh;
                bh->b_count = 1;
                bh->b_dirt = 0;
+               bh->b_flushtime = 0;
                bh->b_uptodate = 0;
+               bh->b_req = 0;
                bh->b_dev = dev;
                bh->b_blocknr = *(p++);
+               bh->b_list = BUF_CLEAN;
                nr_buffers++;
+               nr_buffers_size[isize]++;
                insert_into_queues(bh);
                if (bh->b_this_page)
                        bh = bh->b_this_page;
@@ -801,6 +1153,7 @@ static unsigned long try_to_load_aligned(unsigned long address,
        buffermem += PAGE_SIZE;
        bh->b_this_page = tmp;
        mem_map[MAP_NR(address)]++;
+       buffer_pages[address >> PAGE_SHIFT] = bh;
        read_buffers(arr,block);
        while (block-- > 0)
                brelse(arr[block]);
@@ -889,11 +1242,16 @@ static int grow_buffers(int pri, int size)
 {
        unsigned long page;
        struct buffer_head *bh, *tmp;
+       struct buffer_head * insert_point;
+       int isize;
 
        if ((size & 511) || (size > PAGE_SIZE)) {
                printk("VFS: grow_buffers: size = %d\n",size);
                return 0;
        }
+
+       isize = BUFSIZE_INDEX(size);
+
        if (!(page = __get_free_page(pri)))
                return 0;
        bh = create_buffers(page, size);
@@ -901,25 +1259,32 @@ static int grow_buffers(int pri, int size)
                free_page(page);
                return 0;
        }
+
+       insert_point = free_list[isize];
+
        tmp = bh;
        while (1) {
-               if (free_list) {
-                       tmp->b_next_free = free_list;
-                       tmp->b_prev_free = free_list->b_prev_free;
-                       free_list->b_prev_free->b_next_free = tmp;
-                       free_list->b_prev_free = tmp;
+               nr_free[isize]++;
+               if (insert_point) {
+                       tmp->b_next_free = insert_point->b_next_free;
+                       tmp->b_prev_free = insert_point;
+                       insert_point->b_next_free->b_prev_free = tmp;
+                       insert_point->b_next_free = tmp;
                } else {
                        tmp->b_prev_free = tmp;
                        tmp->b_next_free = tmp;
                }
-               free_list = tmp;
+               insert_point = tmp;
                ++nr_buffers;
                if (tmp->b_this_page)
                        tmp = tmp->b_this_page;
                else
                        break;
        }
+       free_list[isize] = bh;
+       buffer_pages[page >> PAGE_SHIFT] = bh;
        tmp->b_this_page = bh;
+       wake_up(&buffer_wait);
        buffermem += PAGE_SIZE;
        return 1;
 }
@@ -932,6 +1297,7 @@ static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp)
 {
        unsigned long page;
        struct buffer_head * tmp, * p;
+        int isize = BUFSIZE_INDEX(bh->b_size);
 
        *bhp = bh;
        page = (unsigned long) bh->b_data;
@@ -949,16 +1315,72 @@ static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp)
                p = tmp;
                tmp = tmp->b_this_page;
                nr_buffers--;
+               nr_buffers_size[isize]--;
                if (p == *bhp)
-                       *bhp = p->b_prev_free;
+                 {
+                   *bhp = p->b_prev_free;
+                   if (p == *bhp) /* Was this the last in the list? */
+                     *bhp = NULL;
+                 }
                remove_from_queues(p);
                put_unused_buffer_head(p);
        } while (tmp != bh);
        buffermem -= PAGE_SIZE;
+       buffer_pages[page >> PAGE_SHIFT] = NULL;
        free_page(page);
        return !mem_map[MAP_NR(page)];
 }
 
+
+/*
+ * Consult the load average for buffers and decide whether or not
+ * we should shrink the buffers of one size or not.  If we decide yes,
+ * do it and return 1.  Else return 0.  Do not attempt to shrink size
+ * that is specified.
+ *
+ * I would prefer not to use a load average, but the way things are now it
+ * seems unavoidable.  The way to get rid of it would be to force clustering
+ * universally, so that when we reclaim buffers we always reclaim an entire
+ * page.  Doing this would mean that we all need to move towards QMAGIC.
+ */
+
+static int maybe_shrink_lav_buffers(int size)
+{         
+       int nlist;
+       int isize;
+       int total_lav, total_n_buffers, n_sizes;
+       
+       /* Do not consider the shared buffers since they would not tend
+          to have getblk called very often, and this would throw off
+          the lav.  They are not easily reclaimable anyway (let the swapper
+          make the first move). */
+  
+       total_lav = total_n_buffers = n_sizes = 0;
+       for(nlist = 0; nlist < NR_SIZES; nlist++)
+        {
+                total_lav += buffers_lav[nlist];
+                if(nr_buffers_size[nlist]) n_sizes++;
+                total_n_buffers += nr_buffers_size[nlist];
+                total_n_buffers -= nr_buffers_st[nlist][BUF_SHARED]; 
+        }
+       
+       /* See if we have an excessive number of buffers of a particular
+          size - if so, victimize that bunch. */
+  
+       isize = (size ? BUFSIZE_INDEX(size) : -1);
+       
+       if (n_sizes > 1)
+                for(nlist = 0; nlist < NR_SIZES; nlist++)
+                 {
+                         if(nlist == isize) continue;
+                         if(nr_buffers_size[nlist] &&
+                            bdf_prm.b_un.lav_const * buffers_lav[nlist]*total_n_buffers < 
+                            total_lav * (nr_buffers_size[nlist] - nr_buffers_st[nlist][BUF_SHARED]))
+                                  if(shrink_specific_buffers(6, bufferindex_size[nlist])) 
+                                           return 1;
+                 }
+       return 0;
+}
 /*
  * Try to free up some pages by shrinking the buffer-cache
  *
@@ -967,65 +1389,289 @@ static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp)
  * of 0 means "we'd better get some free pages now".
  */
 int shrink_buffers(unsigned int priority)
+{
+       if (priority < 2) {
+               sync_buffers(0,0);
+       }
+
+       if(priority == 2) wakeup_bdflush(1);
+
+       if(maybe_shrink_lav_buffers(0)) return 1;
+
+       /* No good candidate size - take any size we can find */
+        return shrink_specific_buffers(priority, 0);
+}
+
+static int shrink_specific_buffers(unsigned int priority, int size)
 {
        struct buffer_head *bh;
-       int i;
+       int nlist;
+       int i, isize, isize1;
 
-       if (priority < 2)
-               sync_buffers(0,0);
-       bh = free_list;
-       i = nr_buffers >> priority;
-       for ( ; i-- > 0 ; bh = bh->b_next_free) {
-               if (bh->b_count ||
-                   (priority >= 5 &&
-                    mem_map[MAP_NR((unsigned long) bh->b_data)] > 1)) {
-                       put_last_free(bh);
-                       continue;
+#ifdef DEBUG
+       if(size) printk("Shrinking buffers of size %d\n", size);
+#endif
+       /* First try the free lists, and see if we can get a complete page
+          from here */
+       isize1 = (size ? BUFSIZE_INDEX(size) : -1);
+
+       for(isize = 0; isize<NR_SIZES; isize++){
+               if(isize1 != -1 && isize1 != isize) continue;
+               bh = free_list[isize];
+               if(!bh) continue;
+               for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) {
+                       if (bh->b_count || !bh->b_this_page)
+                                continue;
+                       if (try_to_free(bh, &bh))
+                                return 1;
+                       if(!bh) break; /* Some interrupt must have used it after we
+                                         freed the page.  No big deal - keep looking */
                }
-               if (!bh->b_this_page)
-                       continue;
-               if (bh->b_lock)
-                       if (priority)
+       }
+       
+       /* Not enough in the free lists, now try the lru list */
+       
+       for(nlist = 0; nlist < NR_LIST; nlist++) {
+       repeat1:
+               if(priority > 3 && nlist == BUF_SHARED) continue;
+               bh = lru_list[nlist];
+               if(!bh) continue;
+               i = nr_buffers_type[nlist] >> priority;
+               for ( ; i-- > 0 ; bh = bh->b_next_free) {
+                       /* We may have stalled while waiting for I/O to complete. */
+                       if(bh->b_list != nlist) goto repeat1;
+                       if (bh->b_count || !bh->b_this_page)
+                                continue;
+                       if(size && bh->b_size != size) continue;
+                       if (bh->b_lock)
+                                if (priority)
+                                         continue;
+                                else
+                                         wait_on_buffer(bh);
+                       if (bh->b_dirt) {
+                               bh->b_count++;
+                               bh->b_flushtime = 0;
+                               ll_rw_block(WRITEA, 1, &bh);
+                               bh->b_count--;
                                continue;
-                       else
-                               wait_on_buffer(bh);
-               if (bh->b_dirt) {
-                       bh->b_count++;
-                       ll_rw_block(WRITEA, 1, &bh);
-                       bh->b_count--;
-                       continue;
+                       }
+                       if (try_to_free(bh, &bh))
+                                return 1;
+                       if(!bh) break;
                }
-               if (try_to_free(bh, &bh))
-                       return 1;
        }
        return 0;
 }
 
+
 void show_buffers(void)
 {
        struct buffer_head * bh;
        int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
+       int shared;
+       int nlist, isize;
 
        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 {
+
+       for(nlist = 0; nlist < NR_LIST; nlist++) {
+         shared = found = locked = dirty = used = lastused = 0;
+         bh = lru_list[nlist];
+         if(!bh) continue;
+         do {
                found++;
                if (bh->b_lock)
                        locked++;
                if (bh->b_dirt)
                        dirty++;
+               if(mem_map[MAP_NR(((unsigned long) bh->b_data))] !=1) shared++;
                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);
+             } while (bh != lru_list[nlist]);
+       printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d dirty %d shrd\n",
+               nlist, found, used, lastused, locked, dirty, shared);
+       };
+       printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared\n");
+       for(isize = 0; isize<NR_SIZES; isize++){
+               printk("%5d [%5d]: %7d ", bufferindex_size[isize],
+                      buffers_lav[isize], nr_free[isize]);
+               for(nlist = 0; nlist < NR_LIST; nlist++)
+                        printk("%7d ", nr_buffers_st[isize][nlist]);
+               printk("\n");
+       }
+}
+
+/*
+ * try_to_reassign() checks if all the buffers on this particular page
+ * are unused, and reassign to a new cluster them if this is true.
+ */
+static inline int try_to_reassign(struct buffer_head * bh, struct buffer_head ** bhp,
+                          dev_t dev, unsigned int starting_block)
+{
+       unsigned long page;
+       struct buffer_head * tmp, * p;
+
+       *bhp = bh;
+       page = (unsigned long) bh->b_data;
+       page &= PAGE_MASK;
+       if(mem_map[MAP_NR(page)] != 1) return 0;
+       tmp = bh;
+       do {
+               if (!tmp)
+                        return 0;
+               
+               if (tmp->b_count || tmp->b_dirt || tmp->b_lock)
+                        return 0;
+               tmp = tmp->b_this_page;
+       } while (tmp != bh);
+       tmp = bh;
+       
+       while((unsigned int) tmp->b_data & (PAGE_SIZE - 1)) 
+                tmp = tmp->b_this_page;
+       
+       /* This is the buffer at the head of the page */
+       bh = tmp;
+       do {
+               p = tmp;
+               tmp = tmp->b_this_page;
+               remove_from_queues(p);
+               p->b_dev=dev;
+               p->b_uptodate = 0;
+               p->b_req = 0;
+               p->b_blocknr=starting_block++;
+               insert_into_queues(p);
+       } while (tmp != bh);
+       return 1;
+}
+
+/*
+ * Try to find a free cluster by locating a page where
+ * all of the buffers are unused.  We would like this function
+ * to be atomic, so we do not call anything that might cause
+ * the process to sleep.  The priority is somewhat similar to
+ * the priority used in shrink_buffers.
+ * 
+ * My thinking is that the kernel should end up using whole
+ * pages for the buffer cache as much of the time as possible.
+ * This way the other buffers on a particular page are likely
+ * to be very near each other on the free list, and we will not
+ * be expiring data prematurely.  For now we only canibalize buffers
+ * of the same size to keep the code simpler.
+ */
+static int reassign_cluster(dev_t dev, 
+                    unsigned int starting_block, int size)
+{
+       struct buffer_head *bh;
+        int isize = BUFSIZE_INDEX(size);
+       int i;
+
+       /* We want to give ourselves a really good shot at generating
+          a cluster, and since we only take buffers from the free
+          list, we "overfill" it a little. */
+
+       while(nr_free[isize] < 32) refill_freelist(size);
+
+       bh = free_list[isize];
+       if(bh)
+                for (i=0 ; !i || bh != free_list[isize] ; bh = bh->b_next_free, i++) {
+                        if (!bh->b_this_page)  continue;
+                        if (try_to_reassign(bh, &bh, dev, starting_block))
+                                return 4;
+                }
+       return 0;
+}
+
+/* This function tries to generate a new cluster of buffers
+ * from a new page in memory.  We should only do this if we have
+ * not expanded the buffer cache to the maximum size that we allow.
+ */
+static unsigned long try_to_generate_cluster(dev_t dev, int block, int size)
+{
+       struct buffer_head * bh, * tmp, * arr[8];
+        int isize = BUFSIZE_INDEX(size);
+       unsigned long offset;
+       unsigned long page;
+       int nblock;
+
+       page = get_free_page(GFP_NOBUFFER);
+       if(!page) return 0;
+
+       bh = create_buffers(page, size);
+       if (!bh) {
+               free_page(page);
+               return 0;
+       };
+       nblock = block;
+       for (offset = 0 ; offset < PAGE_SIZE ; offset += size) {
+               if (find_buffer(dev, nblock++, size))
+                        goto not_aligned;
+       }
+       tmp = bh;
+       nblock = 0;
+       while (1) {
+               arr[nblock++] = bh;
+               bh->b_count = 1;
+               bh->b_dirt = 0;
+               bh->b_flushtime = 0;
+               bh->b_lock = 0;
+               bh->b_uptodate = 0;
+               bh->b_req = 0;
+               bh->b_dev = dev;
+               bh->b_list = BUF_CLEAN;
+               bh->b_blocknr = block++;
+               nr_buffers++;
+               nr_buffers_size[isize]++;
+               insert_into_queues(bh);
+               if (bh->b_this_page)
+                       bh = bh->b_this_page;
+               else
+                       break;
+       }
+       buffermem += PAGE_SIZE;
+       buffer_pages[page >> PAGE_SHIFT] = bh;
+       bh->b_this_page = tmp;
+       while (nblock-- > 0)
+               brelse(arr[nblock]);
+       return 4;
+not_aligned:
+       while ((tmp = bh) != NULL) {
+               bh = bh->b_this_page;
+               put_unused_buffer_head(tmp);
+       }
+       free_page(page);
+       return 0;
+}
+
+unsigned long generate_cluster(dev_t dev, int b[], int size)
+{
+       int i, offset;
+       
+       for (i = 0, offset = 0 ; offset < PAGE_SIZE ; i++, offset += size) {
+               if(i && b[i]-1 != b[i-1]) return 0;  /* No need to cluster */
+               if(find_buffer(dev, b[i], size)) return 0;
+       };
+
+       /* OK, we have a candidate for a new cluster */
+       
+       /* See if one size of buffer is over-represented in the buffer cache,
+          if so reduce the numbers of buffers */
+       if(maybe_shrink_lav_buffers(size))
+        {
+                int retval;
+                retval = try_to_generate_cluster(dev, b[0], size);
+                if(retval) return retval;
+        };
+       
+       if (nr_free_pages > min_free_pages) 
+                return try_to_generate_cluster(dev, b[0], size);
+       else
+                return reassign_cluster(dev, b[0], size);
 }
 
 /*
- * This initializes the initial buffer free list.  nr_buffers is set
+ * This initializes the initial buffer free list.  nr_buffers_type is set
  * to one less the actual number of buffers, as a sop to backwards
  * compatibility --- the old code did this (I think unintentionally,
  * but I'm not sure), and programs in the ps package expect it.
@@ -1034,16 +1680,254 @@ void show_buffers(void)
 void buffer_init(void)
 {
        int i;
+        int isize = BUFSIZE_INDEX(BLOCK_SIZE);
 
-       if (high_memory >= 4*1024*1024)
+       if (high_memory >= 4*1024*1024) {
                min_free_pages = 200;
-       else
+               if(high_memory >= 16*1024*1024)
+                        nr_hash = 16381;
+               else
+                        nr_hash = 4093;
+       } else {
                min_free_pages = 20;
-       for (i = 0 ; i < NR_HASH ; i++)
+               nr_hash = 997;
+       };
+       
+       hash_table = (struct buffer_head **) vmalloc(nr_hash * 
+                                                    sizeof(struct buffer_head *));
+
+
+       buffer_pages = (struct buffer_head **) vmalloc((high_memory >>PAGE_SHIFT) * 
+                                                    sizeof(struct buffer_head *));
+       for (i = 0 ; i < high_memory >> PAGE_SHIFT ; i++)
+               buffer_pages[i] = NULL;
+
+       for (i = 0 ; i < nr_hash ; i++)
                hash_table[i] = NULL;
-       free_list = 0;
+       lru_list[BUF_CLEAN] = 0;
        grow_buffers(GFP_KERNEL, BLOCK_SIZE);
-       if (!free_list)
+       if (!free_list[isize])
                panic("VFS: Unable to initialize buffer free list!");
        return;
 }
+
+/* This is a simple kernel daemon, whose job it is to provide a dynamicly
+ * response to dirty buffers.  Once this process is activated, we write back
+ * a limited number of buffers to the disks and then go back to sleep again.
+ * In effect this is a process which never leaves kernel mode, and does not have
+ * any user memory associated with it except for the stack.  There is also
+ * a kernel stack page, which obviously must be separate from the user stack.
+ */
+struct wait_queue * bdflush_wait = NULL;
+struct wait_queue * bdflush_done = NULL;
+
+static int bdflush_running = 0;
+
+static void wakeup_bdflush(int wait)
+{
+       if(!bdflush_running){
+               printk("Warning - bdflush not running\n");
+               sync_buffers(0,0);
+               return;
+       };
+       wake_up(&bdflush_wait);
+       if(wait) sleep_on(&bdflush_done);
+}
+
+
+
+/* 
+ * Here we attempt to write back old buffers.  We also try and flush indoes 
+ * and supers as well, since this function is essentially "update", and 
+ * otherwise there would be no way of ensuring that these quantities ever 
+ * get written back.  Ideally, we would have a timestamp on the inodes
+ * and superblocks so that we could write back only the old ones as well
+ */
+
+asmlinkage int sync_old_buffers(void)
+{
+       int i, isize;
+       int ndirty, nwritten;
+       int nlist;
+       int ncount;
+       struct buffer_head * bh, *next;
+
+       sync_supers(0);
+       sync_inodes(0);
+
+       ncount = 0;
+#ifdef DEBUG
+       for(nlist = 0; nlist < NR_LIST; nlist++)
+#else
+       for(nlist = BUF_DIRTY; nlist <= BUF_DIRTY; nlist++)
+#endif
+       {
+               ndirty = 0;
+               nwritten = 0;
+       repeat:
+               bh = lru_list[nlist];
+               if(bh) 
+                        for (i = nr_buffers_type[nlist]; --i > 0; bh = next) {
+                                /* We may have stalled while waiting for I/O to complete. */
+                                if(bh->b_list != nlist) goto repeat;
+                                next = bh->b_next_free;
+                                if(!lru_list[nlist]) {
+                                        printk("Dirty list empty %d\n", i);
+                                        break;
+                                }
+                                
+                                /* Clean buffer on dirty list?  Refile it */
+                                if (nlist == BUF_DIRTY && !bh->b_dirt && !bh->b_lock)
+                                 {
+                                         refile_buffer(bh);
+                                         continue;
+                                 }
+                                
+                                if (bh->b_lock || !bh->b_dirt)
+                                         continue;
+                                ndirty++;
+                                if(bh->b_flushtime > jiffies) continue;
+                                nwritten++;
+                                bh->b_count++;
+                                bh->b_flushtime = 0;
+#ifdef DEBUG
+                                if(nlist != BUF_DIRTY) ncount++;
+#endif
+                                ll_rw_block(WRITE, 1, &bh);
+                                bh->b_count--;
+                        }
+       }
+#ifdef DEBUG
+       if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount);
+       printk("Wrote %d/%d buffers\n", nwritten, ndirty);
+#endif
+       
+       /* We assume that we only come through here on a regular
+          schedule, like every 5 seconds.  Now update load averages.  
+          Shift usage counts to prevent overflow. */
+       for(isize = 0; isize<NR_SIZES; isize++){
+               CALC_LOAD(buffers_lav[isize], bdf_prm.b_un.lav_const, buffer_usage[isize]);
+               buffer_usage[isize] = 0;
+       };
+       return 0;
+}
+
+
+/* This is the interface to bdflush.  As we get more sophisticated, we can
+ * pass tuning parameters to this "process", to adjust how it behaves.  If you
+ * invoke this again after you have done this once, you would simply modify 
+ * the tuning parameters.  We would want to verify each parameter, however,
+ * to make sure that it is reasonable. */
+
+asmlinkage int sys_bdflush(int func, int data)
+{
+       int i, error;
+       int ndirty;
+       int nlist;
+       int ncount;
+       struct buffer_head * bh, *next;
+
+       if(!suser()) return -EPERM;
+
+       if(func == 1)
+                return sync_old_buffers();
+
+       /* Basically func 0 means start, 1 means read param 1, 2 means write param 1, etc */
+       if(func >= 2){
+               i = (func-2) >> 1;
+               if (i < 0 || i >= N_PARAM) return -EINVAL;
+               if((func & 1) == 0) {
+                       error = verify_area(VERIFY_WRITE, (void *) data, sizeof(int));
+                       if(error) return error;
+                       put_fs_long(bdf_prm.data[i], data);
+                       return 0;
+               };
+               if(data < bdflush_min[i] || data > bdflush_max[i]) return -EINVAL;
+               bdf_prm.data[i] = data;
+               return 0;
+       };
+       
+       if(bdflush_running++) return -EBUSY; /* Only one copy of this running at one time */
+       
+       /* OK, from here on is the daemon */
+       
+       while(1==1){
+#ifdef DEBUG
+               printk("bdflush() activated...");
+#endif
+               
+               ncount = 0;
+#ifdef DEBUG
+               for(nlist = 0; nlist < NR_LIST; nlist++)
+#else
+               for(nlist = BUF_DIRTY; nlist <= BUF_DIRTY; nlist++)
+#endif
+                {
+                        ndirty = 0;
+                repeat:
+                        bh = lru_list[nlist];
+                        if(bh) 
+                                 for (i = nr_buffers_type[nlist]; --i > 0 && ndirty < bdf_prm.b_un.ndirty; 
+                                      bh = next) {
+                                         /* We may have stalled while waiting for I/O to complete. */
+                                         if(bh->b_list != nlist) goto repeat;
+                                         next = bh->b_next_free;
+                                         if(!lru_list[nlist]) {
+                                                 printk("Dirty list empty %d\n", i);
+                                                 break;
+                                         }
+                                         
+                                         /* Clean buffer on dirty list?  Refile it */
+                                         if (nlist == BUF_DIRTY && !bh->b_dirt && !bh->b_lock)
+                                          {
+                                                  refile_buffer(bh);
+                                                  continue;
+                                          }
+                                         
+                                         if (bh->b_lock || !bh->b_dirt)
+                                                  continue;
+                                         /* Should we write back buffers that are shared or not??
+                                            currently dirty buffers are not shared, so it does not matter */
+                                         bh->b_count++;
+                                         ndirty++;
+                                         bh->b_flushtime = 0;
+                                         ll_rw_block(WRITE, 1, &bh);
+#ifdef DEBUG
+                                         if(nlist != BUF_DIRTY) ncount++;
+#endif
+                                         bh->b_count--;
+                                 }
+                }
+#ifdef DEBUG
+               if (ncount) printk("sys_bdflush: %d dirty buffers not on dirty list\n", ncount);
+               printk("sleeping again.\n");
+#endif
+               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 - nr_buffers_type[BUF_SHARED]) * 
+                  bdf_prm.b_un.nfract/100) {
+                       interruptible_sleep_on(&bdflush_wait);
+               }
+       }
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
index fb6e2c7b49c3683860819619cd8f167d00c43b28..ebe388c2d712056a698f32401a55686796075fdc 100644 (file)
@@ -28,6 +28,26 @@ static struct device_struct blkdevs[MAX_BLKDEV] = {
        { NULL, NULL },
 };
 
+int get_device_list(char * page)
+{
+       int i;
+       int len;
+
+       len = sprintf(page, "Character devices:\n");
+       for (i = 0; i < MAX_CHRDEV ; i++) {
+               if (chrdevs[i].fops) {
+                       len += sprintf(page+len, "%2d %s\n", i, chrdevs[i].name);
+               }
+       }
+       len += sprintf(page+len, "\nBlock devices:\n");
+       for (i = 0; i < MAX_BLKDEV ; i++) {
+               if (blkdevs[i].fops) {
+                       len += sprintf(page+len, "%2d %s\n", i, blkdevs[i].name);
+               }
+       }
+       return len;
+}
+
 struct file_operations * get_blkfops(unsigned int major)
 {
        if (major >= MAX_BLKDEV)
index 16fe1ffb448faaea760823a9da1ef0d5b38635fb..f32cdd8982ecd62b8928d91ba8a59f532ca3c151 100644 (file)
@@ -248,7 +248,7 @@ static int ext_file_write(struct inode * inode, struct file * filp, char * buf,
                memcpy_fromfs(p,buf,c);
                buf += c;
                bh->b_uptodate = 1;
-               dirtify_buffer(bh, 0);
+               mark_buffer_dirty(bh, 0);
                brelse(bh);
        }
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
index e46bb9e99a1abceae4e3f7c7bdbc8a1b6e1f646b..8d9fe7acf2802947a48ec43436a43483d02dfb67 100644 (file)
@@ -83,7 +83,7 @@ printk("ext_free_block: block full, skipping to %d\n", block);
        }
        sb->u.ext_sb.s_freeblockscount ++;
        sb->s_dirt = 1;
-       dirtify_buffer(sb->u.ext_sb.s_firstfreeblock, 1);
+       mark_buffer_dirty(sb->u.ext_sb.s_firstfreeblock, 1);
        unlock_super (sb);
        return;
 }
@@ -104,7 +104,7 @@ int ext_new_block(struct super_block * sb)
        efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
        if (efb->count) {
                j = efb->free[--efb->count];
-               dirtify_buffer(sb->u.ext_sb.s_firstfreeblock, 1);
+               mark_buffer_dirty(sb->u.ext_sb.s_firstfreeblock, 1);
        } else {
 #ifdef EXTFS_DEBUG
 printk("ext_new_block: block empty, skipping to %d\n", efb->next);
@@ -135,7 +135,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
        }
        clear_block(bh->b_data);
        bh->b_uptodate = 1;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
 #ifdef EXTFS_DEBUG
 printk("ext_new_block: allocating block %d\n", j);
@@ -239,7 +239,7 @@ printk("ext_free_inode: inode full, skipping to %d\n", ino);
        }
        sb->u.ext_sb.s_freeinodescount ++;
        sb->s_dirt = 1;
-       dirtify_buffer(sb->u.ext_sb.s_firstfreeinodeblock, 1);
+       mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
        unlock_super (sb);
 }
 
@@ -263,7 +263,7 @@ struct inode * ext_new_inode(const struct inode * dir)
                (sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
        if (efi->count) {
                j = efi->free[--efi->count];
-               dirtify_buffer(sb->u.ext_sb.s_firstfreeinodeblock, 1);
+               mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
        } else {
 #ifdef EXTFS_DEBUG
 printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
index eff68fcb525c8cd5b98eb131e03b15bd645c2d3a..891e1d567656ef3796f9fe345d3dedad5b4e349f 100644 (file)
@@ -139,7 +139,7 @@ void ext_write_super (struct super_block *sb)
        es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
        es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
        es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse (bh);
        sb->s_dirt = 0;
 }
@@ -296,7 +296,7 @@ repeat:
                goto repeat;
        }
        *p = tmp;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        return result;
 }
@@ -407,7 +407,7 @@ static struct buffer_head * ext_update_inode(struct inode * inode)
                raw_inode->i_zone[0] = inode->i_rdev;
        else for (block = 0; block < 12; block++)
                raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        inode->i_dirt=0;
        return bh;
 }
index 5a1ac36c681cbb6989b1ce263322c9fb4ad04aae..79ae157cf68cb111fbe3c386cb7ecad7287a5536 100644 (file)
@@ -249,7 +249,7 @@ printk ("ext_add_entry: skipping to next block\n");
 #if 0
                                        dir->i_ctime = CURRENT_TIME;
 #endif
-                                       dirtify_buffer(bh, 1);
+                                       mark_buffer_dirty(bh, 1);
                                }
                                brelse (bh);
                                bh = NULL;
@@ -296,7 +296,7 @@ printk ("ext_add_entry : creating next block\n");
                        de->name_len = namelen;
                        for (i=0; i < namelen ; i++)
                                de->name[i] = name[i];
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        return bh;
                }
@@ -334,7 +334,7 @@ int ext_create(struct inode * dir,const char * name, int len, int mode,
                return -ENOSPC;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        *result = inode;
@@ -393,7 +393,7 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
                return -ENOSPC;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        iput(inode);
@@ -445,7 +445,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
        de->name_len=2;
        strcpy(de->name,"..");
        inode->i_nlink = 2;
-       dirtify_buffer(dir_block, 1);
+       mark_buffer_dirty(dir_block, 1);
        brelse(dir_block);
        inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
        if (dir->i_mode & S_ISGID)
@@ -459,7 +459,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
                return -ENOSPC;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        dir->i_nlink++;
        dir->i_dirt = 1;
        iput(dir);
@@ -567,7 +567,7 @@ int ext_rmdir(struct inode * dir, const char * name, int len)
        de->inode = 0;
        de->name_len = 0;
        ext_merge_entries (de, pde, nde);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        inode->i_nlink=0;
        inode->i_dirt=1;
        dir->i_nlink--;
@@ -610,7 +610,7 @@ int ext_unlink(struct inode * dir, const char * name, int len)
        de->inode = 0;
        de->name_len = 0;
        ext_merge_entries (de, pde, nde);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        inode->i_nlink--;
        inode->i_dirt = 1;
        inode->i_ctime = CURRENT_TIME;
@@ -650,7 +650,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym
        while (i < 1023 && (c = *(symname++)))
                name_block->b_data[i++] = c;
        name_block->b_data[i] = 0;
-       dirtify_buffer(name_block, 1);
+       mark_buffer_dirty(name_block, 1);
        brelse(name_block);
        inode->i_size = i;
        inode->i_dirt = 1;
@@ -672,7 +672,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym
                return -ENOSPC;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        iput(inode);
@@ -708,7 +708,7 @@ int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int
                return -ENOSPC;
        }
        de->inode = oldinode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        oldinode->i_nlink++;
@@ -851,11 +851,11 @@ start_up:
                new_inode->i_nlink--;
                new_inode->i_dirt = 1;
        }
-       dirtify_buffer(old_bh, 1);
-       dirtify_buffer(new_bh, 1);
+       mark_buffer_dirty(old_bh, 1);
+       mark_buffer_dirty(new_bh, 1);
        if (dir_bh) {
                PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-               dirtify_buffer(dir_bh, 1);
+               mark_buffer_dirty(dir_bh, 1);
                old_dir->i_nlink--;
                new_dir->i_nlink++;
                old_dir->i_dirt = 1;
index 21f85bef3393ee8d0e1a3a4b3002e4bb6f20f85a..a2b4858216f7d459e551618938adf1e5c0f8eae0 100644 (file)
@@ -102,7 +102,7 @@ repeat:
                        continue;
                }
                *ind = 0;
-               dirtify_buffer(ind_bh, 1);
+               mark_buffer_dirty(ind_bh, 1);
                brelse(bh);
                ext_free_block(inode->i_sb,tmp);
        }
@@ -154,7 +154,7 @@ repeat:
                if (!tmp)
                        continue;
                retry |= trunc_indirect(inode,offset+(i<<8),dind);
-               dirtify_buffer(dind_bh, 1);
+               mark_buffer_dirty(dind_bh, 1);
        }
        dind = (unsigned long *) dind_bh->b_data;
        for (i = 0; i < 256; i++)
@@ -201,7 +201,7 @@ repeat:
                        goto repeat;
                tind = i+(unsigned long *) tind_bh->b_data;
                retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
-               dirtify_buffer(tind_bh, 1);
+               mark_buffer_dirty(tind_bh, 1);
        }
        tind = (unsigned long *) tind_bh->b_data;
        for (i = 0; i < 256; i++)
index 82e4019a422f0c25644d967bc591baad492d43fd..156cb734d11f6503855bb52e7f1fcd014ae06442 100644 (file)
@@ -310,10 +310,10 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block,
                }
        }
        
-       dirtify_buffer(bh2, 1);
-       dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+       mark_buffer_dirty(bh2, 1);
+       mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
 
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (sb->s_flags & MS_SYNC) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -524,7 +524,7 @@ got_block:
 
        j = tmp;
 
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (sb->s_flags & MS_SYNC) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -544,16 +544,16 @@ got_block:
        }
        clear_block (bh->b_data, sb->s_blocksize);
        bh->b_uptodate = 1;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse (bh);
 
        ext2_debug ("allocating block %d. "
                    "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
 
        gdp->bg_free_blocks_count--;
-       dirtify_buffer(bh2, 1);
+       mark_buffer_dirty(bh2, 1);
        es->s_free_blocks_count--;
-       dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+       mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        sb->s_dirt = 1;
        unlock_super (sb);
        return j;
index 806165f470210e5766e5fb31b10f7bdd6dfc1858..3e9e14e9b196f1ae6c298f7188db105f8bf410f3 100644 (file)
@@ -78,6 +78,7 @@ static int ext2_file_read (struct inode * inode, struct file * filp,
        int read, left, chars;
        int block, blocks, offset;
        int bhrequest, uptodate;
+       int clusterblocks;
        struct buffer_head ** bhb, ** bhe;
        struct buffer_head * bhreq[NBUF];
        struct buffer_head * buflist[NBUF];
@@ -130,11 +131,18 @@ static int ext2_file_read (struct inode * inode, struct file * filp,
         * buffers and caches.
         */
 
+       clusterblocks = 0;
+
        do {
                bhrequest = 0;
                uptodate = 1;
                while (blocks) {
                        --blocks;
+#if 1
+                       if(!clusterblocks) clusterblocks = ext2_getcluster(inode, block);
+                       if(clusterblocks) clusterblocks--;
+#endif
+
                        *bhb = ext2_getblk (inode, block++, 0, &err);
                        if (*bhb && !(*bhb)->b_uptodate) {
                                uptodate = 0;
@@ -277,7 +285,7 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
                memcpy_fromfs (p, buf, c);
                buf += c;
                bh->b_uptodate = 1;
-               dirtify_buffer(bh, 0);
+               mark_buffer_dirty(bh, 0);
                brelse (bh);
        }
        up(&inode->i_sem);
index d3ba1df81cf86ecb531bd4a5d962c76673326681..561a7b5465bc233ebe16b2287c051e5b7d6a3282 100644 (file)
@@ -202,7 +202,7 @@ static void set_inode_dtime (struct inode * inode,
                        EXT2_INODES_PER_BLOCK(inode->i_sb));
        raw_inode->i_links_count = 0;
        raw_inode->i_dtime = CURRENT_TIME;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(inode)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -266,12 +266,12 @@ void ext2_free_inode (struct inode * inode)
                gdp->bg_free_inodes_count++;
                if (S_ISDIR(inode->i_mode))
                        gdp->bg_used_dirs_count--;
-               dirtify_buffer(bh2, 1);
+               mark_buffer_dirty(bh2, 1);
                es->s_free_inodes_count++;
-               dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                set_inode_dtime (inode, gdp);
        }
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (sb->s_flags & MS_SYNC) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -313,7 +313,7 @@ static void inc_inode_version (struct inode * inode,
                        EXT2_INODES_PER_BLOCK(inode->i_sb));
        raw_inode->i_version++;
        inode->u.ext2_i.i_version = raw_inode->i_version;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse (bh);
 }
 
@@ -438,7 +438,7 @@ repeat:
                                      "bit already set for inode %d", j);
                        goto repeat;
                }
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                if (sb->s_flags & MS_SYNC) {
                        ll_rw_block (WRITE, 1, &bh);
                        wait_on_buffer (bh);
@@ -466,9 +466,9 @@ repeat:
        gdp->bg_free_inodes_count--;
        if (S_ISDIR(mode))
                gdp->bg_used_dirs_count++;
-       dirtify_buffer(bh2, 1);
+       mark_buffer_dirty(bh2, 1);
        es->s_free_inodes_count--;
-       dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+       mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        sb->s_dirt = 1;
        inode->i_mode = mode;
        inode->i_sb = sb;
index 409846553c2553b6ff39352c87b08a02ddcb4451..4aacbaa227317df7b34c878c9ad406653dacd686 100644 (file)
@@ -109,7 +109,7 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal)
                }
                clear_block (bh->b_data, inode->i_sb->s_blocksize);
                bh->b_uptodate = 1;
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                brelse (bh);
        } else {
                ext2_discard_prealloc (inode);
@@ -314,7 +314,7 @@ repeat:
                goto repeat;
        }
        *p = tmp;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(inode)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -328,6 +328,41 @@ repeat:
        return result;
 }
 
+static int block_getcluster (struct inode * inode, struct buffer_head * bh,
+                                         int nr,
+                                         int blocksize)
+{
+       unsigned long * p;
+       int firstblock = 0;
+       int result = 0;
+       int i;
+
+       /* Check to see if clustering possible here. */
+
+       if(!bh) return 0;
+
+       if(nr % (PAGE_SIZE / inode->i_sb->s_blocksize) != 0) goto out;
+       if(nr + 3 > EXT2_ADDR_PER_BLOCK(inode->i_sb)) goto out;
+
+       for(i=0; i< (PAGE_SIZE / inode->i_sb->s_blocksize); i++) {
+         p = (unsigned long *) bh->b_data + nr + i;
+         
+         /* All blocks in cluster must already be allocated */
+         if(*p == 0) goto out;
+         
+         /* See if aligned correctly */
+         if(i==0) firstblock = *p;
+         else if(*p != firstblock + i) goto out;
+       };
+       
+       p = (unsigned long *) bh->b_data + nr;
+       result = generate_cluster(bh->b_dev, (int *) p, blocksize);
+
+      out:
+       brelse(bh);
+       return result;
+}
+
 struct buffer_head * ext2_getblk (struct inode * inode, long block,
                                  int create, int * err)
 {
@@ -389,6 +424,55 @@ struct buffer_head * ext2_getblk (struct inode * inode, long block,
                             inode->i_sb->s_blocksize, b, err);
 }
 
+int ext2_getcluster (struct inode * inode, long block)
+{
+       struct buffer_head * bh;
+       int err, create;
+       unsigned long b;
+       unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+
+       create = 0;
+       err = -EIO;
+       if (block < 0) {
+               ext2_warning (inode->i_sb, "ext2_getblk", "block < 0");
+               return 0;
+       }
+       if (block > EXT2_NDIR_BLOCKS + addr_per_block  +
+                   addr_per_block * addr_per_block +
+                   addr_per_block * addr_per_block * addr_per_block) {
+               ext2_warning (inode->i_sb, "ext2_getblk", "block > big");
+               return 0;
+       }
+
+       err = -ENOSPC;
+       b = block;
+       if (block < EXT2_NDIR_BLOCKS) return 0;
+
+       block -= EXT2_NDIR_BLOCKS;
+
+       if (block < addr_per_block) {
+               bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, &err);
+               return block_getcluster (inode, bh, block, 
+                                        inode->i_sb->s_blocksize);
+       }
+       block -= addr_per_block;
+       if (block < addr_per_block * addr_per_block) {
+               bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, &err);
+               bh = block_getblk (inode, bh, block / addr_per_block, create,
+                                  inode->i_sb->s_blocksize, b, &err);
+               return block_getcluster (inode, bh, block & (addr_per_block - 1),
+                                    inode->i_sb->s_blocksize);
+       }
+       block -= addr_per_block * addr_per_block;
+       bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, &err);
+       bh = block_getblk (inode, bh, block/(addr_per_block * addr_per_block),
+                          create, inode->i_sb->s_blocksize, b, &err);
+       bh = block_getblk (inode, bh, (block/addr_per_block) & (addr_per_block - 1),
+                          create, inode->i_sb->s_blocksize, b, &err);
+       return block_getcluster (inode, bh, block & (addr_per_block - 1),
+                                inode->i_sb->s_blocksize);
+}
+
 struct buffer_head * ext2_bread (struct inode * inode, int block, 
                                 int create, int *err)
 {
@@ -549,7 +633,7 @@ static struct buffer_head * ext2_update_inode (struct inode * inode)
                raw_inode->i_block[0] = inode->i_rdev;
        else for (block = 0; block < EXT2_N_BLOCKS; block++)
                raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        inode->i_dirt = 0;
        return bh;
 }
index 6a92d13e2f61361c5efab386f373123446b24274..bae03a5cf8db67caea17fa2e4d97f8af14bae3f7 100644 (file)
@@ -320,7 +320,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                         */
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
                        dir->i_dirt = 1;
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        *err = 0;
                        return bh;
@@ -394,7 +394,7 @@ int ext2_create (struct inode * dir,const char * name, int len, int mode,
        ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
                         de->inode);
 #endif
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -460,7 +460,7 @@ int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
        ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
                         de->inode);
 #endif
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -517,7 +517,7 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
        de->name_len = 2;
        strcpy (de->name, "..");
        inode->i_nlink = 2;
-       dirtify_buffer(dir_block, 1);
+       mark_buffer_dirty(dir_block, 1);
        brelse (dir_block);
        inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->umask);
        if (dir->i_mode & S_ISGID)
@@ -536,7 +536,7 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
        ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
                         de->inode);
 #endif
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -660,7 +660,7 @@ repeat:
        up(&inode->i_sem);
        if (retval)
                goto end_rmdir;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -728,7 +728,7 @@ repeat:
        retval = ext2_delete_entry (de, bh);
        if (retval)
                goto end_unlink;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -793,7 +793,7 @@ int ext2_symlink (struct inode * dir, const char * name, int len,
                link[i++] = c;
        link[i] = 0;
        if (name_block) {
-               dirtify_buffer(name_block, 1);
+               mark_buffer_dirty(name_block, 1);
                brelse (name_block);
        }
        inode->i_size = i;
@@ -820,7 +820,7 @@ int ext2_symlink (struct inode * dir, const char * name, int len,
        ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
                         de->inode);
 #endif
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -866,7 +866,7 @@ int ext2_link (struct inode * oldinode, struct inode * dir,
        ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
                         de->inode);
 #endif
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
@@ -1042,19 +1042,19 @@ start_up:
        }
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
        old_dir->i_dirt = 1;
-       dirtify_buffer(old_bh,  1);
+       mark_buffer_dirty(old_bh,  1);
        if (IS_SYNC(old_dir)) {
                ll_rw_block (WRITE, 1, &old_bh);
                wait_on_buffer (old_bh);
        }
-       dirtify_buffer(new_bh, 1);
+       mark_buffer_dirty(new_bh, 1);
        if (IS_SYNC(new_dir)) {
                ll_rw_block (WRITE, 1, &new_bh);
                wait_on_buffer (new_bh);
        }
        if (dir_bh) {
                PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-               dirtify_buffer(dir_bh, 1);
+               mark_buffer_dirty(dir_bh, 1);
                old_dir->i_nlink--;
                old_dir->i_dirt = 1;
                if (new_inode) {
index 4cfa9ff017dded8df74d2d533ace429ca6ea4260..88a46d7d53f70ede74d09d700e4561b13cb416db 100644 (file)
@@ -36,7 +36,7 @@ void ext2_error (struct super_block * sb, const char * function,
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
                sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
-               dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
        }
        va_start (args, fmt);
@@ -66,7 +66,7 @@ NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
                sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
-               dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
        }
        va_start (args, fmt);
@@ -96,7 +96,7 @@ void ext2_put_super (struct super_block * sb)
        lock_super (sb);
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
-               dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        }
 #ifndef DONT_USE_DCACHE
        ext2_dcache_invalidate (sb->s_dev);
@@ -159,10 +159,10 @@ static int convert_pre_02b_fs (struct super_block * sb,
                gdp[i].bg_free_blocks_count = old_group_desc[i].bg_free_blocks_count;
                gdp[i].bg_free_inodes_count = old_group_desc[i].bg_free_inodes_count;
        }
-       dirtify_buffer(bh2, 1);
+       mark_buffer_dirty(bh2, 1);
        brelse (bh2);
        es->s_magic = EXT2_SUPER_MAGIC;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        sb->s_magic = EXT2_SUPER_MAGIC;
        return 1;
 }
@@ -287,7 +287,7 @@ static void ext2_setup_super (struct super_block * sb,
                        es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
                es->s_mnt_count++;
                es->s_mtime = CURRENT_TIME;
-               dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
                if (test_opt (sb, DEBUG))
                        printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
@@ -570,7 +570,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
 #ifdef EXT2FS_PRE_02B_COMPAT
        if (fs_converted) {
                for (i = 0; i < bh_count; i++)
-                       dirtify_buffer(sb->u.ext2_sb.s_group_desc[i], 1);
+                       mark_buffer_dirty(sb->u.ext2_sb.s_group_desc[i], 1);
                sb->s_dirt = 1;
        }
 #endif
@@ -582,7 +582,7 @@ static void ext2_commit_super (struct super_block * sb,
                               struct ext2_super_block * es)
 {
        es->s_wtime = CURRENT_TIME;
-       dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+       mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        sb->s_dirt = 0;
 }
 
@@ -639,7 +639,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
                 */
                es->s_state = sb->u.ext2_sb.s_mount_state;
                es->s_mtime = CURRENT_TIME;
-               dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
                ext2_commit_super (sb, es);
        }
index 589e3650fd57fff5613eee3d6a1acb8f954e1100..b4cddb696fdab31cd2734cda8e1186db0d6d8c9b 100644 (file)
@@ -90,7 +90,7 @@ repeat:
                if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
                        clear_block (bh->b_data, inode->i_sb->s_blocksize,
                                     RANDOM_INT);
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                }
                brelse (bh);
                if (free_count == 0) {
@@ -162,11 +162,11 @@ repeat:
                        continue;
                }
                *ind = 0;
-               dirtify_buffer(ind_bh, 1);
+               mark_buffer_dirty(ind_bh, 1);
                if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
                        clear_block (bh->b_data, inode->i_sb->s_blocksize,
                                     RANDOM_INT);
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                }
                brelse (bh);
                if (free_count == 0) {
@@ -243,7 +243,7 @@ repeat:
                        continue;
                retry |= trunc_indirect (inode, offset + (i * addr_per_block),
                                          dind);
-               dirtify_buffer(dind_bh, 1);
+               mark_buffer_dirty(dind_bh, 1);
        }
        dind = (unsigned long *) dind_bh->b_data;
        for (i = 0; i < addr_per_block; i++)
@@ -302,7 +302,7 @@ repeat:
                retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
                        addr_per_block + (i + 1) * addr_per_block * addr_per_block,
                        tind);
-               dirtify_buffer(tind_bh, 1);
+               mark_buffer_dirty(tind_bh, 1);
        }
        tind = (unsigned long *) tind_bh->b_data;
        for (i = 0; i < addr_per_block; i++)
index 4d8cf173897f4b7644ffd666773455a540979e0e..1502e1bc06b57c98de8a99c7cfa6217a18d85bf7 100644 (file)
@@ -93,7 +93,7 @@ void minix_free_block(struct super_block * sb, int block)
        }
        if (!clear_bit(bit,bh->b_data))
                printk("free_block (%04x:%d): bit already cleared\n",sb->s_dev,block);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        return;
 }
 
@@ -118,7 +118,7 @@ repeat:
                printk("new_block: bit already set");
                goto repeat;
        }
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
        if (j < sb->u.minix_sb.s_firstdatazone ||
            j >= sb->u.minix_sb.s_nzones)
@@ -129,7 +129,7 @@ repeat:
        }
        clear_block(bh->b_data);
        bh->b_uptodate = 1;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        return j;
 }
@@ -175,7 +175,7 @@ void minix_free_inode(struct inode * inode)
        clear_inode(inode);
        if (!clear_bit(ino & 8191, bh->b_data))
                printk("free_inode: bit %lu already cleared.\n",ino);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
 }
 
 struct inode * minix_new_inode(const struct inode * dir)
@@ -204,7 +204,7 @@ struct inode * minix_new_inode(const struct inode * dir)
                iput(inode);
                return NULL;
        }
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        j += i*8192;
        if (!j || j >= inode->i_sb->u.minix_sb.s_ninodes) {
                iput(inode);
index 73088e0e95e777e05e1e86e043dc7aed3c376ff3..17e161fd3cb7a6ea148ff6946e6c21d9aef1cba2 100644 (file)
@@ -240,7 +240,7 @@ static int minix_file_write(struct inode * inode, struct file * filp, char * buf
                memcpy_fromfs(p,buf,c);
                buf += c;
                bh->b_uptodate = 1;
-               dirtify_buffer(bh, 0);
+               mark_buffer_dirty(bh, 0);
                brelse(bh);
        }
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
index b4226db4a9049a64d9a5c47b825dbd098c819a65..da27827b8a68196de5b21f087b15020103f25868 100644 (file)
@@ -28,7 +28,7 @@ void minix_put_inode(struct inode *inode)
 static void minix_commit_super (struct super_block * sb,
                               struct minix_super_block * ms)
 {
-       dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
+       mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
        sb->s_dirt = 0;
 }
 
@@ -54,7 +54,7 @@ void minix_put_super(struct super_block *sb)
        lock_super(sb);
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
-               dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
        }
        sb->s_dev = 0;
        for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
@@ -90,7 +90,7 @@ int minix_remount (struct super_block * sb, int * flags, char * data)
                        return 0;
                /* Mounting a rw partition read-only. */
                ms->s_state = sb->u.minix_sb.s_mount_state;
-               dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
                sb->s_dirt = 1;
                minix_commit_super (sb, ms);
        }
@@ -98,7 +98,7 @@ int minix_remount (struct super_block * sb, int * flags, char * data)
                /* Mount a partition which is read-only, read-write. */
                sb->u.minix_sb.s_mount_state = ms->s_state;
                ms->s_state &= ~MINIX_VALID_FS;
-               dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
+               mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
                sb->s_dirt = 1;
 
                if (!(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -197,7 +197,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
        }
        if (!(s->s_flags & MS_RDONLY)) {
                ms->s_state &= ~MINIX_VALID_FS;
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                s->s_dirt = 1;
        }
        if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -349,7 +349,7 @@ repeat:
                goto repeat;
        }
        *p = tmp;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        return result;
 }
@@ -477,7 +477,7 @@ static struct buffer_head * minix_update_inode(struct inode * inode)
        else for (block = 0; block < 9; block++)
                raw_inode->i_zone[block] = inode->u.minix_i.i_data[block];
        inode->i_dirt=0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        return bh;
 }
 
index 68d7cedd48427b2bd62e63f3f4b6c54a08046ef8..93f79450b64673d8a52d2251a7444e16089ab4f2 100644 (file)
@@ -195,7 +195,7 @@ static int minix_add_entry(struct inode * dir,
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
                        for (i = 0; i < info->s_namelen ; i++)
                                de->name[i] = (i < namelen) ? name[i] : 0;
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        break;
                }
@@ -238,7 +238,7 @@ int minix_create(struct inode * dir,const char * name, int len, int mode,
                return error;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        *result = inode;
@@ -295,7 +295,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
                return error;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        iput(inode);
@@ -347,7 +347,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
        de->inode = dir->i_ino;
        strcpy(de->name,"..");
        inode->i_nlink = 2;
-       dirtify_buffer(dir_block, 1);
+       mark_buffer_dirty(dir_block, 1);
        brelse(dir_block);
        inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
        if (dir->i_mode & S_ISGID)
@@ -361,7 +361,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
                return error;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        dir->i_nlink++;
        dir->i_dirt = 1;
        iput(dir);
@@ -469,7 +469,7 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
        if (inode->i_nlink != 2)
                printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
        de->inode = 0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        inode->i_nlink=0;
        inode->i_dirt=1;
        dir->i_nlink--;
@@ -522,7 +522,7 @@ repeat:
                inode->i_nlink=1;
        }
        de->inode = 0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        dir->i_dirt = 1;
        inode->i_nlink--;
@@ -562,7 +562,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
        while (i < 1023 && (c=*(symname++)))
                name_block->b_data[i++] = c;
        name_block->b_data[i] = 0;
-       dirtify_buffer(name_block, 1);
+       mark_buffer_dirty(name_block, 1);
        brelse(name_block);
        inode->i_size = i;
        inode->i_dirt = 1;
@@ -584,7 +584,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
                return i;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        iput(inode);
@@ -621,7 +621,7 @@ int minix_link(struct inode * oldinode, struct inode * dir, const char * name, i
                return error;
        }
        de->inode = oldinode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        oldinode->i_nlink++;
@@ -774,11 +774,11 @@ start_up:
                new_inode->i_ctime = CURRENT_TIME;
                new_inode->i_dirt = 1;
        }
-       dirtify_buffer(old_bh, 1);
-       dirtify_buffer(new_bh, 1);
+       mark_buffer_dirty(old_bh, 1);
+       mark_buffer_dirty(new_bh, 1);
        if (dir_bh) {
                PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-               dirtify_buffer(dir_bh, 1);
+               mark_buffer_dirty(dir_bh, 1);
                old_dir->i_nlink--;
                old_dir->i_dirt = 1;
                if (new_inode) {
index bd5445367e09a142ae430fc87900a3f8a56a2d78..0b127b9b840f5c90dd4297005eeccad845151a93 100644 (file)
@@ -96,7 +96,7 @@ repeat:
                        continue;
                }
                *ind = 0;
-               dirtify_buffer(ind_bh, 1);
+               mark_buffer_dirty(ind_bh, 1);
                brelse(bh);
                minix_free_block(inode->i_sb,tmp);
        }
@@ -144,7 +144,7 @@ repeat:
                        goto repeat;
                dind = i+(unsigned short *) dind_bh->b_data;
                retry |= trunc_indirect(inode,7+512+(i<<9),dind);
-               dirtify_buffer(dind_bh, 1);
+               mark_buffer_dirty(dind_bh, 1);
        }
        dind = (unsigned short *) dind_bh->b_data;
        for (i = 0; i < 512; i++)
index 8576a81d419bcd8e718efec1a50849d0803bacbf..fe0c1ff428505d790b55ae37fa9f3fcb93fca1fc 100644 (file)
@@ -72,15 +72,15 @@ int fat_access(struct super_block *sb,int nr,int new_value)
                                *p_first = new_value & 0xff;
                                *p_last = (*p_last & 0xf0) | (new_value >> 8);
                        }
-                       dirtify_buffer(bh2, 1);
+                       mark_buffer_dirty(bh2, 1);
                }
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
                        if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
                            fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
                            fat_length*copy,&c_data))) break;
                        memcpy(c_data,data,SECTOR_SIZE);
-                       dirtify_buffer(c_bh, 1);
+                       mark_buffer_dirty(c_bh, 1);
                        if (data != data2 || bh != bh2) {
                                if (!(c_bh2 = msdos_sread(sb->s_dev,
                                    MSDOS_SB(sb)->fat_start+(first >>
index ba1d623184df5fee317260ce356ce39ac7298247..3a49ebad74c325eedf5796dcc1ff9eb8f51f21fc 100644 (file)
@@ -200,7 +200,7 @@ static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
                        inode->i_size = filp->f_pos;
                        inode->i_dirt = 1;
                }
-               dirtify_buffer(bh, 0);
+               mark_buffer_dirty(bh, 0);
                brelse(bh);
        }
        if (start == buf)
index 7d028fd4a614f66f0a7affc98707da87b66f75ee..8c6d3b2afe063d584a9939bd055386a4a157114a 100644 (file)
@@ -415,7 +415,7 @@ void msdos_write_inode(struct inode *inode)
        date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
        raw_entry->time = CT_LE_W(raw_entry->time);
        raw_entry->date = CT_LE_W(raw_entry->date);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
 }
 
index 7b23886c03e850cba8991659d652baa41787db85..022c59779227f7330de3977eff0ad3021ac0e2ae 100644 (file)
@@ -185,7 +185,7 @@ printk("zeroing sector %d\n",sector);
                        else memset(data,0,SECTOR_SIZE);
                }
                if (bh) {
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                        brelse(bh);
                }
        }
index 2ed3ee94cc792d2b1ff9941b161afa99a397a374..70fbfa1d2cf6a47a07f5f10533c4ed12db0f2343 100644 (file)
@@ -181,7 +181,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
        de->start = 0;
        date_unix2dos(dir->i_mtime,&de->time,&de->date);
        de->size = 0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        if ((*result = iget(dir->i_sb,ino)) != NULL)
                msdos_read_inode(*result);
        brelse(bh);
@@ -350,7 +350,7 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
        dir->i_nlink--;
        inode->i_dirt = dir->i_dirt = 1;
        de->name[0] = DELETED_FLAG;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        res = 0;
 rmdir_done:
        brelse(bh);
@@ -384,7 +384,7 @@ int msdos_unlink(struct inode *dir,const char *name,int len)
        MSDOS_I(inode)->i_busy = 1;
        inode->i_dirt = dir->i_dirt = 1;
        de->name[0] = DELETED_FLAG;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
 unlink_done:
        brelse(bh);
        iput(inode);
@@ -429,12 +429,12 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,
                MSDOS_I(new_inode)->i_busy = 1;
                new_inode->i_dirt = 1;
                new_de->name[0] = DELETED_FLAG;
-               dirtify_buffer(new_bh, 1);
+               mark_buffer_dirty(new_bh, 1);
                iput(new_inode);
                brelse(new_bh);
        }
        memcpy(old_de->name,new_name,MSDOS_NAME);
-       dirtify_buffer(old_bh, 1);
+       mark_buffer_dirty(old_bh, 1);
        if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
                if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
                        msdos_read_inode(old_inode);
@@ -503,7 +503,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
                MSDOS_I(new_inode)->i_busy = 1;
                new_inode->i_dirt = 1;
                new_de->name[0] = DELETED_FLAG;
-               dirtify_buffer(new_bh, 1);
+               mark_buffer_dirty(new_bh, 1);
        }
        memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
        memcpy(free_de->name,new_name,MSDOS_NAME);
@@ -526,8 +526,8 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
        cache_inval_inode(old_inode);
        old_inode->i_dirt = 1;
        old_de->name[0] = DELETED_FLAG;
-       dirtify_buffer(old_bh, 1);
-       dirtify_buffer(free_bh, 1);
+       mark_buffer_dirty(old_bh, 1);
+       mark_buffer_dirty(free_bh, 1);
        if (!exists) iput(free_inode);
        else {
                MSDOS_I(new_inode)->i_depend = free_inode;
@@ -547,7 +547,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
                dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
                    MSDOS_I(new_dir)->i_start;
                dotdot_inode->i_dirt = 1;
-               dirtify_buffer(dotdot_bh, 1);
+               mark_buffer_dirty(dotdot_bh, 1);
                old_dir->i_nlink--;
                new_dir->i_nlink++;
                /* no need to mark them dirty */
index fca6f07ebf97a4ac474348322b7e089b4233370e..8d7e46e1801831358cde29537afcdcdf2ce5e9f0 100644 (file)
@@ -465,6 +465,7 @@ static int get_maps(int pid, char *buf)
 }
 
 extern int get_module_list(char *);
+extern int get_device_list(char *);
 
 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
 {
@@ -522,6 +523,9 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c
                case 17:
                        length = get_kstat(page);
                        break;
+               case 18:
+                       length = get_device_list(page);
+                       break;
                default:
                        free_page((unsigned long) page);
                        return -EBADF;
index 1690b431fa9243966180e0dc4b568fd90d5d8bcf..07c9a9e93f2ada4f285dc4ef34e4617fedfc442c 100644 (file)
@@ -67,6 +67,7 @@ static struct proc_dir_entry root_dir[] = {
        {14,5,"kcore" },
        {16,7,"modules" },
        {17,4,"stat" },
+       {18,7,"devices" },
 };
 
 #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
index 6707267b40a9e04b8fb3026c15970b9eff6b84fe..e8d5e3d87e886c6efc24c0e976f1df749de43ed6 100644 (file)
@@ -96,7 +96,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
                }
                *flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */
                memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                bh->b_uptodate = 1;
                brelse(bh);
                *sb->sv_sb_flc_count = 0;
@@ -117,7 +117,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
                bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
                memzero(bh_data, sb->sv_block_size);
                /* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                bh->b_uptodate = 1;
                brelse(bh);
                /* still *sb->sv_sb_flc_count = 0 */
@@ -138,7 +138,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
                  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
        else
                *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
-       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
+       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
        sb->s_dirt = 1; /* and needs time stamp */
        unlock_super(sb);
 }
@@ -229,7 +229,7 @@ int sysv_new_block(struct super_block * sb)
                        return 0;
                }
        memzero(bh_data,sb->sv_block_size);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        bh->b_uptodate = 1;
        brelse(bh);
        if (sb->sv_convert)
@@ -237,7 +237,7 @@ int sysv_new_block(struct super_block * sb)
                  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
        else
                *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
-       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
+       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
        sb->s_dirt = 1; /* and needs time stamp */
        unlock_super(sb);
        return block;
@@ -331,7 +331,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
                printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
                if (!(sb->s_flags & MS_RDONLY)) {
                        *sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
-                       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
+                       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
                        sb->s_dirt = 1; /* and needs time stamp */
                }
        }
index df61c0d2b014c3565179add71a6c185c3102453a..e578ddddaaf8d58cae0ad04a990dc10eb4440e4a 100644 (file)
@@ -301,7 +301,7 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf,
                memcpy_fromfs(p,buf,c);
                buf += c;
                bh->b_uptodate = 1;
-               dirtify_buffer(bh, 0);
+               mark_buffer_dirty(bh, 0);
                brelse(bh);
        }
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
index 4aa79035823e7aa3d37a1bb355b33e7493a3502c..b0e3894415663884c20b2b57fde1b7e7b05eeb7c 100644 (file)
@@ -74,10 +74,10 @@ void sysv_free_inode(struct inode * inode)
        if (*sb->sv_sb_fic_count < sb->sv_fic_size)
                sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)++] = ino;
        (*sb->sv_sb_total_free_inodes)++;
-       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
+       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
        sb->s_dirt = 1; /* and needs time stamp */
        memset(raw_inode, 0, sizeof(struct sysv_inode));
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        unlock_super(sb);
        brelse(bh);
        clear_inode(inode);
@@ -130,7 +130,7 @@ struct inode * sysv_new_inode(const struct inode * dir)
        }
        /* Now *sb->sv_sb_fic_count > 0. */
        ino = sb->sv_sb_fic_inodes[--(*sb->sv_sb_fic_count)];
-       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
+       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
        sb->s_dirt = 1; /* and needs time stamp */
        inode->i_count = 1;
        inode->i_nlink = 1;
@@ -152,7 +152,7 @@ struct inode * sysv_new_inode(const struct inode * dir)
        inode->i_dirt = 1;              /* cleared by sysv_write_inode() */
        /* That's it. */
        (*sb->sv_sb_total_free_inodes)--;
-       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified again */
+       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified again */
        sb->s_dirt = 1; /* and needs time stamp again */
        unlock_super(sb);
        return inode;
@@ -191,7 +191,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
                printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
                if (!(sb->s_flags & MS_RDONLY)) {
                        *sb->sv_sb_total_free_inodes = count;
-                       dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
+                       mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
                        sb->s_dirt = 1; /* and needs time stamp */
                }
        }
index 4c1d94bdece2ae75911a83ab08ee62461ce30e0d..d4f56a8271b8d6a0ce50967015da90868347c712 100644 (file)
@@ -557,7 +557,7 @@ repeat:
                goto repeat;
        }
        *p = (sb->sv_convert ? to_coh_ulong(block) : block);
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        *start = result->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
        return result;
@@ -773,7 +773,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
                for (block = 0; block < 10+1+1+1; block++)
                        write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]);
        inode->i_dirt=0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        return bh;
 }
 
index a08d2943b8c2e0843a8d0d9c777057b5c000e6c3..83ef0d536eb90397a4bf50c58d83fdee4a9dcf43 100644 (file)
@@ -193,7 +193,7 @@ static int sysv_add_entry(struct inode * dir,
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
                        for (i = 0; i < SYSV_NAMELEN ; i++)
                                de->name[i] = (i < namelen) ? name[i] : 0;
-                       dirtify_buffer(bh, 1);
+                       mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        break;
                }
@@ -238,7 +238,7 @@ int sysv_create(struct inode * dir,const char * name, int len, int mode,
                return error;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        *result = inode;
@@ -298,7 +298,7 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde
                return error;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        iput(inode);
@@ -349,7 +349,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
        de->inode = dir->i_ino;
        strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */
        inode->i_nlink = 2;
-       dirtify_buffer(dir_block, 1);
+       mark_buffer_dirty(dir_block, 1);
        brelse(dir_block);
        inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
        if (dir->i_mode & S_ISGID)
@@ -363,7 +363,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
                return error;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        dir->i_nlink++;
        dir->i_dirt = 1;
        iput(dir);
@@ -473,7 +473,7 @@ int sysv_rmdir(struct inode * dir, const char * name, int len)
        if (inode->i_nlink != 2)
                printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
        de->inode = 0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        inode->i_nlink=0;
        inode->i_dirt=1;
        dir->i_nlink--;
@@ -526,7 +526,7 @@ repeat:
                inode->i_nlink=1;
        }
        de->inode = 0;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        dir->i_dirt = 1;
        inode->i_nlink--;
@@ -570,7 +570,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
        while (i < sb->sv_block_size_1 && (c = *(symname++)))
                name_block_data[i++] = c;
        name_block_data[i] = 0;
-       dirtify_buffer(name_block, 1);
+       mark_buffer_dirty(name_block, 1);
        brelse(name_block);
        inode->i_size = i;
        inode->i_dirt = 1;
@@ -592,7 +592,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
                return i;
        }
        de->inode = inode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        iput(inode);
@@ -629,7 +629,7 @@ int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, in
                return error;
        }
        de->inode = oldinode->i_ino;
-       dirtify_buffer(bh, 1);
+       mark_buffer_dirty(bh, 1);
        brelse(bh);
        iput(dir);
        oldinode->i_nlink++;
@@ -782,11 +782,11 @@ start_up:
                new_inode->i_ctime = CURRENT_TIME;
                new_inode->i_dirt = 1;
        }
-       dirtify_buffer(old_bh, 1);
-       dirtify_buffer(new_bh, 1);
+       mark_buffer_dirty(old_bh, 1);
+       mark_buffer_dirty(new_bh, 1);
        if (dir_bh) {
                PARENT_INO(dir_bh_data) = new_dir->i_ino;
-               dirtify_buffer(dir_bh, 1);
+               mark_buffer_dirty(dir_bh, 1);
                old_dir->i_nlink--;
                old_dir->i_dirt = 1;
                if (new_inode) {
index e8b5ddee13202ace3df81f498a4fb23b6fe1916a..b8f802af8277f8a58e2c90b7c0218f2975e9c63a 100644 (file)
@@ -84,7 +84,7 @@ static int coh_trunc_indirect (struct inode * inode, unsigned long blocks, unsig
                if (!indblock)
                        continue;
                *ind = 0;
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                sysv_free_block(sb,indblock);
        }
        for (i = 0; i < sb->sv_ind_per_block; i++)
@@ -338,7 +338,7 @@ repeat:
                        continue;
                }
                *ind = 0;
-               dirtify_buffer(indbh, 1);
+               mark_buffer_dirty(indbh, 1);
                brelse(bh);
                sysv_free_block(sb,block);
        }
index c191d64f41a6623add560a8f5429a0f3eba5a2e7..d3735621f2ee7ee1a0d1fc5e16d99c5e842bb394 100644 (file)
@@ -65,7 +65,7 @@ zone_found:
         start_bit=j + (i << 5) + 1;
        goto repeat;
     }
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     return j + (i << 5);
 }
 
@@ -245,7 +245,7 @@ void xiafs_free_zone(struct super_block * sb, int d_addr)
         printk("XIA-FS: dev %04x"
               " block bit %u (0x%x) already cleared (%s %d)\n",
               sb->s_dev, bit, bit, WHERE_ERR);
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
 }
 
@@ -277,7 +277,7 @@ int xiafs_new_zone(struct super_block * sb, u_long prev_addr)
     }
     clear_buf(bh);
     bh->b_uptodate = 1;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     brelse(bh);
     return tmp;
 }
@@ -305,7 +305,7 @@ void xiafs_free_inode(struct inode * inode)
         printk("XIA-FS: dev %04x"
               "inode bit %ld (0x%lx) already cleared (%s %d)\n",
               inode->i_dev, ino, ino, WHERE_ERR);
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
 }
 
index 92075b5f3a76f447291324ad19617ae9faca92d9..5678ffd0bcb3675b9d26d611145cb7b599b9430f 100644 (file)
@@ -241,7 +241,7 @@ xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count
        memcpy_fromfs(cp,buf,c);
        buf += c;
        bh->b_uptodate = 1;
-       dirtify_buffer(bh, 0);
+       mark_buffer_dirty(bh, 0);
        brelse(bh);
     }
     inode->i_mtime = inode->i_ctime = CURRENT_TIME;
index 8af15c3a413a714b96c30dcb5c04dcde5551ba8b..171499a95cabe81665f361a5f02955683b34225c 100644 (file)
@@ -306,7 +306,7 @@ repeat:
     }
     *lp = tmp;
     inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     brelse(bh);
     return result;
 }
@@ -466,7 +466,7 @@ static struct buffer_head *  xiafs_update_inode(struct inode * inode)
                                     | (inode->u.xiafs_i.i_dind_zone  & 0xffffff);
     }
     inode->i_dirt=0;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     return bh;
 }
 
index 13d49d6b52c823ee885b5fde1434176a2e394faa..da0d3d2378d594e04b1a5fa0e1ef219ce1ad5cdd 100644 (file)
@@ -221,7 +221,7 @@ static struct buffer_head * xiafs_add_entry(struct inode * dir,
                memcpy(de->d_name, name, namelen);
                de->d_name[namelen]=0;
                de->d_name_len=namelen;
-               dirtify_buffer(bh, 1);
+               mark_buffer_dirty(bh, 1);
                *res_dir = de;
                if (res_pre)
                    *res_pre = de_pre;
@@ -268,7 +268,7 @@ int xiafs_create(struct inode * dir, const char * name, int len, int mode,
        return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     brelse(bh);
     iput(dir);
     *result = inode;
@@ -325,7 +325,7 @@ int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev
        return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     brelse(bh);
     iput(dir);
     iput(inode);
@@ -375,7 +375,7 @@ int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
     de->d_name_len=2;
     de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
     inode->i_nlink = 2;
-    dirtify_buffer(dir_block, 1);
+    mark_buffer_dirty(dir_block, 1);
     brelse(dir_block);
     inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->umask);
     if (dir->i_mode & S_ISGID)
@@ -389,7 +389,7 @@ int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
        return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     dir->i_nlink++;
     dir->i_dirt = 1;
     iput(dir);
@@ -518,7 +518,7 @@ int xiafs_rmdir(struct inode * dir, const char * name, int len)
     if (inode->i_nlink != 2)
         printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
     xiafs_rm_entry(de, de_pre);
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     inode->i_nlink=0;
     inode->i_dirt=1;
     dir->i_nlink--;
@@ -566,7 +566,7 @@ repeat:
        inode->i_nlink=1;
     }
     xiafs_rm_entry(de, de_pre);
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
     dir->i_dirt = 1;
     inode->i_nlink--;
@@ -611,7 +611,7 @@ int xiafs_symlink(struct inode * dir, const char * name,
     for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
         name_block->b_data[i] = c;
     name_block->b_data[i] = 0;
-    dirtify_buffer(name_block, 1);
+    mark_buffer_dirty(name_block, 1);
     brelse(name_block);
     inode->i_size = i;
     inode->i_dirt = 1;
@@ -624,7 +624,7 @@ int xiafs_symlink(struct inode * dir, const char * name,
        return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     brelse(bh);
     iput(dir);
     iput(inode);
@@ -661,7 +661,7 @@ int xiafs_link(struct inode * oldinode, struct inode * dir,
        return -ENOSPC;
     }
     de->d_ino = oldinode->i_ino;
-    dirtify_buffer(bh, 1);
+    mark_buffer_dirty(bh, 1);
     brelse(bh);
     iput(dir);
     oldinode->i_nlink++;
@@ -798,11 +798,11 @@ try_again:
         new_inode->i_nlink--;
        new_inode->i_dirt = 1;
     }
-    dirtify_buffer(old_bh, 1);
-    dirtify_buffer(new_bh, 1);
+    mark_buffer_dirty(old_bh, 1);
+    mark_buffer_dirty(new_bh, 1);
     if (dir_bh) {
         PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-       dirtify_buffer(dir_bh, 1);
+       mark_buffer_dirty(dir_bh, 1);
        old_dir->i_nlink--;
        new_dir->i_nlink++;
        old_dir->i_dirt = 1;
index 6cae2507eb0c11a4e2e76bb8cd8a1d3e7c62b458..bdb9d39be059b494e6e92d9698f9630db30d2551 100644 (file)
@@ -104,7 +104,7 @@ repeat:
            retry = 1;
        else {
            *indp = 0;
-           dirtify_buffer(ind_bh, 1);
+           mark_buffer_dirty(ind_bh, 1);
            inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
            xiafs_free_zone(inode->i_sb, tmp);
        }
@@ -157,7 +157,7 @@ repeat:
        retry |= trunc_indirect(inode, 
                                8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)), 
                                dindp);
-       dirtify_buffer(dind_bh, 1);
+       mark_buffer_dirty(dind_bh, 1);
     }
     dindp = (u_long *) dind_bh->b_data;
     for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++);
index b73aa4fd58e3c75060eb956023a0337b6999be37..4068c00200a6c55b0c82f276f060d97b34270436 100644 (file)
@@ -390,6 +390,7 @@ extern int ext2_bmap (struct inode *, int);
 extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
 extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
 
+extern int ext2_getcluster (struct inode * inode, long block);
 extern void ext2_read_inode (struct inode *);
 extern void ext2_write_inode (struct inode *);
 extern void ext2_put_inode (struct inode *);
index 16ebab99ade0b4cf5367c77c5724b58561f4b893..846dbe9560355c11004f397947397093d1a46771 100644 (file)
@@ -28,7 +28,6 @@
 #define NR_INODE 2048  /* this should be bigger than NR_FILE */
 #define NR_FILE 1024   /* this can well be larger on a larger system */
 #define NR_SUPER 32
-#define NR_HASH 997
 #define NR_IHASH 131
 #define NR_FILE_LOCKS 64
 #define BLOCK_SIZE 1024
@@ -138,6 +137,11 @@ struct buffer_head {
        unsigned char b_dirt;           /* 0-clean,1-dirty */
        unsigned char b_lock;           /* 0 - ok, 1 -locked */
        unsigned char b_req;            /* 0 if the buffer has been invalidated */
+       unsigned char b_list;           /* List that this buffer appears */
+       unsigned char b_retain;         /* Expected number of times this will
+                                          be used.  Put on freelist when 0 */
+       unsigned long b_flushtime;      /* Time when this (dirty) buffer should be written */
+       unsigned long b_lru_time;       /* Time when this buffer was last used. */
        struct wait_queue * b_wait;
        struct buffer_head * b_prev;            /* doubly linked list of hash-queue */
        struct buffer_head * b_next;
@@ -356,16 +360,41 @@ extern struct super_block super_blocks[NR_SUPER];
 
 extern int shrink_buffers(unsigned int priority);
 
+extern void refile_buffer(struct buffer_head * buf);
+void set_writetime(struct buffer_head * buf, int flag);
+
+struct buffer_head ** buffer_pages;
+
 extern int nr_buffers;
 extern int buffermem;
 extern int nr_buffer_heads;
 
-/* Once the full cluster diffs are in place, this will be filled out a bit. */
-extern inline void dirtify_buffer(struct buffer_head * bh, int flag)
+#define BUF_CLEAN 0
+#define BUF_UNSHARED 1 /* Buffers that were shared but are not any more */
+#define BUF_LOCKED 2   /* Buffers scheduled for write */
+#define BUF_LOCKED1 3  /* Supers, inodes */
+#define BUF_DIRTY 4    /* Dirty buffers, not yet scheduled for write */
+#define BUF_SHARED 5   /* Buffers shared */
+#define NR_LIST 6
+
+extern inline void mark_buffer_clean(struct buffer_head * bh)
 {
-  bh->b_dirt = 1;
+  if(bh->b_dirt) {
+    bh->b_dirt = 0;
+    if(bh->b_list == BUF_DIRTY) refile_buffer(bh);
+  }
 }
 
+extern inline void mark_buffer_dirty(struct buffer_head * bh, int flag)
+{
+  if(!bh->b_dirt) {
+    bh->b_dirt = 1;
+    set_writetime(bh, flag);
+    if(bh->b_list != BUF_DIRTY) refile_buffer(bh);
+  }
+}
+
+
 extern void check_disk_change(dev_t dev);
 extern void invalidate_inodes(dev_t dev);
 extern void invalidate_buffers(dev_t dev);
@@ -402,6 +431,7 @@ extern unsigned long bread_page(unsigned long addr,dev_t dev,int b[],int size,in
 extern struct buffer_head * breada(dev_t dev,int block, int size, 
                                   unsigned int pos, unsigned int filesize);
 extern void put_super(dev_t dev);
+unsigned long generate_cluster(dev_t dev, int b[], int size);
 extern dev_t ROOT_DEV;
 
 extern void show_buffers(void);
index f1934b83efb5ad45d674cb2cd2a94dbef9e23d0b..1ae2ce7e25a1ac3d06bd428a036d4ed9b1a091f6 100644 (file)
@@ -217,6 +217,7 @@ extern unsigned short * mem_map;
 #define GFP_ATOMIC     0x01
 #define GFP_USER       0x02
 #define GFP_KERNEL     0x03
+#define GFP_NOBUFFER   0x04
 
 
 /* vm_ops not present page codes */
index a7ee1cf243ab2f88e7b84b8fe2d850251b82ffd8..6ec269dde68ffbd02717eca4a92394447568b089 100644 (file)
@@ -14,6 +14,7 @@
 /*
  * These are system calls that will be removed at some time
  * due to newer versions existing..
+ * (please be careful - ibcs2 may need some of these).
  */
 #ifdef notdef
 #define _sys_waitpid   _sys_old_syscall        /* _sys_wait4 */
@@ -32,6 +33,5 @@
  * but have an entry in the table for future expansion..
  */
 #define _sys_quotactl  _sys_ni_syscall
-#define _sys_bdflush   _sys_ni_syscall
 
 #endif
index a9a64df90aa38f2fc65faee0a1df65c93fc8c369..a81cdd146be25535701b39b0e4a84c982bee50ef 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -470,12 +470,12 @@ check_table:
 
 #endif
 
-static int try_to_free_page(void)
+static int try_to_free_page(int priority)
 {
        int i=6;
 
        while (i--) {
-               if (shrink_buffers(i))
+               if (priority != GFP_NOBUFFER && shrink_buffers(i))
                        return 1;
                if (shm_swap(i))
                        return 1;
@@ -545,6 +545,17 @@ void free_pages(unsigned long addr, unsigned long order)
                                if (!--*map)
                                        free_pages_ok(addr, order);
                                restore_flags(flag);
+                               if(*map == 1) {
+                                 int j;
+                                 struct buffer_head * bh, *tmp;
+
+                                 bh = buffer_pages[MAP_NR(addr)];
+                                 if(bh)
+                                   for(j = 0, tmp = bh; tmp && (!j || tmp != bh); 
+                                       tmp = tmp->b_this_page, j++)
+                                     if(tmp->b_list == BUF_SHARED && tmp->b_dev != 0xffff)
+                                       refile_buffer(tmp);
+                               }
                        }
                        return;
                }
@@ -610,7 +621,7 @@ repeat:
                return 0;
        }
        restore_flags(flags);
-        if (priority != GFP_BUFFER && try_to_free_page())
+        if (priority != GFP_BUFFER && try_to_free_page(priority))
                goto repeat;
        return 0;
 }