# This patch adds the bitmap hinting code that substantially speeds up write
# performance, and lowers fragmentation.

diff -ruN linux-2.4.11-pre6/fs/reiserfs/bitmap.c linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/bitmap.c
--- linux-2.4.11-pre6/fs/reiserfs/bitmap.c	Wed Oct 10 14:42:40 2001
+++ linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/bitmap.c	Wed Oct 10 14:47:35 2001
@@ -29,7 +29,7 @@
 
     /* it can't be one of the bitmap blocks */
     for (i = 0; i < SB_BMAP_NR (s); i ++)
-	if (block == SB_AP_BITMAP (s)[i]->b_blocknr) {
+	if (block == SB_AP_BITMAP (s)[i].bh->b_blocknr) {
 	    reiserfs_warning ("vs: 4020: is_reusable: "
 			      "bitmap block %lu(%u) can't be freed or reused\n",
 			      block, SB_BMAP_NR (s));
@@ -45,12 +45,12 @@
 
     j = block % (s->s_blocksize << 3);
     if ((bit_value == 0 && 
-         reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i]->b_data)) ||
+         reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) ||
 	(bit_value == 1 && 
-	 reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i]->b_data) == 0)) {
+	 reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i].bh->b_data) == 0)) {
 	reiserfs_warning ("vs-4040: is_reusable: corresponding bit of block %lu does not "
 			  "match required value (i==%d, j==%d) test_bit==%d\n",
-		block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i]->b_data));
+		block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i].bh->b_data));
 	return 0;
     }
 
@@ -89,7 +89,7 @@
     struct super_block * s = th->t_super;
     struct reiserfs_super_block * rs;
     struct buffer_head * sbh;
-    struct buffer_head ** apbh;
+    struct reiserfs_bitmap_info *apbi;
     int nr, offset;
 
   RFALSE(!s, "vs-4060: trying to free block on nonexistent device");
@@ -97,22 +97,27 @@
 
   rs = SB_DISK_SUPER_BLOCK (s);
   sbh = SB_BUFFER_WITH_SB (s);
-  apbh = SB_AP_BITMAP (s);
+  apbi = SB_AP_BITMAP (s);
 
   get_bit_address (s, block, &nr, &offset);
 
   /* mark it before we clear it, just in case */
   journal_mark_freed(th, s, block) ;
 
-  reiserfs_prepare_for_journal(s, apbh[nr], 1 ) ;
+  reiserfs_prepare_for_journal(s, apbi[nr].bh, 1 ) ;
 
   /* clear bit for the given block in bit map */
-  if (!reiserfs_test_and_clear_le_bit (offset, apbh[nr]->b_data)) {
+  if (!reiserfs_test_and_clear_le_bit (offset, apbi[nr].bh->b_data)) {
       reiserfs_warning ("vs-4080: reiserfs_free_block: "
 			"free_block (%04x:%lu)[dev:blocknr]: bit already cleared\n", 
 	    s->s_dev, block);
   }
-  journal_mark_dirty (th, s, apbh[nr]);
+
+  if (offset < apbi[nr].first_zero_hint) {
+      apbi[nr].first_zero_hint = offset;
+  }
+  apbi[nr].free_count ++;
+  journal_mark_dirty (th, s, apbi[nr].bh);
 
   reiserfs_prepare_for_journal(s, sbh, 1) ;
   /* update super block */
@@ -122,28 +127,21 @@
   s->s_dirt = 1;
 }
 
-
-
-/* beginning from offset-th bit in bmap_nr-th bitmap block,
-   find_forward finds the closest zero bit. It returns 1 and zero
-   bit address (bitmap, offset) if zero bit found or 0 if there is no
-   zero bit in the forward direction */
-/* The function is NOT SCHEDULE-SAFE! */
-static int find_forward (struct super_block * s, int * bmap_nr, int * offset, int for_unformatted)
+static int find_free_in_bitmap (struct super_block *s, int *bmap_nr, int *offset,
+                                int for_unformatted)
 {
-  int i, j;
-  struct buffer_head * bh;
+
+    int j;
   unsigned long block_to_try = 0;
   unsigned long next_block_to_try = 0 ;
+    struct reiserfs_bitmap_info *bi = SB_AP_BITMAP(s) + *bmap_nr;
 
-  for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0) {
-    /* get corresponding bitmap block */
-    bh = SB_AP_BITMAP (s)[i];
-    if (buffer_locked (bh)) {
-        __wait_on_buffer (bh);
+    if (buffer_locked (bi->bh)) {
+        __wait_on_buffer (bi->bh);
     }
+
 retry:
-    j = reiserfs_find_next_zero_le_bit ((unsigned long *)bh->b_data, 
+    j = reiserfs_find_next_zero_le_bit ((unsigned long *)bi->bh->b_data, 
                                          s->s_blocksize << 3, *offset);
 
     /* wow, this really needs to be redone.  We can't allocate a block if
@@ -159,11 +157,11 @@
     ** it goes.  TODO.
     */
     if (j < (s->s_blocksize << 3)) {
-      block_to_try = (i * (s->s_blocksize << 3)) + j; 
+      block_to_try = (*bmap_nr * (s->s_blocksize << 3)) + j; 
 
       /* the block is not in the journal, we can proceed */
-      if (!(reiserfs_in_journal(s, s->s_dev, block_to_try, s->s_blocksize, for_unformatted, &next_block_to_try))) {
-	*bmap_nr = i;
+      if (!(reiserfs_in_journal(s, s->s_dev, block_to_try, s->s_blocksize,
+                                for_unformatted, &next_block_to_try))) {
 	*offset = j;
 	return 1;
       } 
@@ -171,15 +169,18 @@
       else if ((j+1) < (s->s_blocksize << 3)) { /* try again */
 	/* reiserfs_in_journal suggested a new block to try */
 	if (next_block_to_try > 0) {
-	  int new_i ;
-	  get_bit_address (s, next_block_to_try, &new_i, offset);
+	  int suggested_bmap ;
+	  get_bit_address (s, next_block_to_try, &suggested_bmap, offset);
 
 	  /* block is not in this bitmap. reset i and continue
 	  ** we only reset i if new_i is in a later bitmap.
 	  */
-	  if (new_i > i) {
-	    i = (new_i - 1 ); /* i gets incremented by the for loop */
-	    continue ;
+
+          /* send the suggestion to caller,
+           * if it's in a later bitmap, so we can skip */
+	  if (suggested_bmap > *bmap_nr) {
+	    *bmap_nr = suggested_bmap;
+	    return 1 ;
 	  }
 	} else {
 	  /* no suggestion was made, just try the next block */
@@ -188,11 +189,102 @@
 	goto retry ;
       }
     }
-  }
     /* zero bit not found */
     return 0;
 }
 
+
+/* beginning from offset-th bit in bmap_nr-th bitmap block,
+   find_forward finds the closest zero bit. It returns 1 and zero
+   bit address (bitmap, offset) if zero bit found or 0 if there is no
+   zero bit in the forward direction */
+/* The function is NOT SCHEDULE-SAFE! */
+static int find_forward (struct super_block * s, int * bmap_nr, int * offset, int for_unformatted)
+{
+  int i;
+  struct reiserfs_bitmap_info *bi;
+  int block_to_try = 0;
+  int nbmap;
+
+  if (!reiserfs_no_bitmap_hinting (s)) {
+    /* Block must be at least 10% free to be a candidate for first cycle */
+    int threshold = (s->s_blocksize << 3) / 10;
+
+    /* Start off by ignoring the threshold value to find the suggested
+     * optimal position for this block. This cuts down on fragmentation and
+     * honors the suggested block more closely. */
+    bi = SB_AP_BITMAP (s) + *bmap_nr;
+    if (bi->free_count > 0) {
+        nbmap = *bmap_nr;
+        block_to_try = (*offset > bi->first_zero_hint) ?
+                                                *offset : bi->first_zero_hint;
+        if (find_free_in_bitmap (s, &nbmap, &block_to_try, for_unformatted) > 0) {
+            if (nbmap == *bmap_nr) {
+                *offset = block_to_try;
+                return 1;
+            }
+        }
+    }
+
+    /* By keeping a certain percentage of blocks free per bitmap-controlled
+     * area, we can cut down on fragmentation by leaving space available for
+     * a suggested block (see code above). If we didn't find a free block
+     * in the suggested bitmap, we can assume _some_ fragmentation will
+     * already occur. By using this threshold method, we can try to cut
+     * down on fragmentation of the "suggested" blocks. */
+    while (threshold >= 1) {
+
+      /* Just tried bmap_nr. If we're here, we didn't get anything. */
+      for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++) {
+
+        /* get corresponding bitmap block */
+        bi = SB_AP_BITMAP (s) + i;
+
+        if (bi->free_count > threshold) {
+              nbmap = i;
+              block_to_try = bi->first_zero_hint;
+              if (find_free_in_bitmap (s, &nbmap, &block_to_try,
+                                                    for_unformatted) > 0) {
+                /* If the bitmap number changed, a suggestion was made by
+                 * reiserfs_in_journal(). Yes, it's ugly. */
+                if (nbmap > i) {
+                    i = (nbmap - 1);
+                    continue;
+                }
+                *offset = block_to_try;
+                *bmap_nr = i;
+
+                return 1;
+              }
+        }
+      }
+      threshold >>= 1;
+    }
+  } else {
+      /* This is the original reiserfs bitmap allocation algorithm. */
+      for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0) {
+          /* get corresponding bitmap block */
+          bi = SB_AP_BITMAP (s) + i;
+
+          nbmap = i;
+          if (find_free_in_bitmap (s, &nbmap, offset, for_unformatted) > 0) {
+            /* If the bitmap number changed, a suggestion was made by
+             * reiserfs_in_journal(). Yes, it's ugly. */
+            if (nbmap > i) {
+                i = (nbmap - 1);
+                continue;
+            }
+            *bmap_nr = i;
+
+            return 1;
+          }
+      }
+  }
+
+  /* No bits found */
+  return 0;
+}
+
 /* return 0 if no free blocks, else return 1 */
 /* The function is NOT SCHEDULE-SAFE!  
 ** because the bitmap block we want to change could be locked, and on its
@@ -382,22 +474,26 @@
     }
        
 
-    reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[i], 1) ;
+    reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[i].bh, 1) ;
 
-    RFALSE( buffer_locked (SB_AP_BITMAP (s)[i]) || 
+    RFALSE( buffer_locked (SB_AP_BITMAP (s)[i].bh) ||
 	    is_reusable (s, search_start, 0) == 0,
 	    "vs-4140: bitmap block is locked or bad block number found");
 
     /* if this bit was already set, we've scheduled, and someone else
     ** has allocated it.  loop around and try again
     */
-    if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i]->b_data)) {
+    if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i].bh->b_data)) {
 	reiserfs_warning("vs-4150: reiserfs_new_blocknrs, block not free");
-	reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i]) ;
+	reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i].bh) ;
 	amount_needed++ ;
 	continue ;
     }    
-    journal_mark_dirty (th, s, SB_AP_BITMAP (s)[i]); 
+    SB_AP_BITMAP (s)[i].free_count --;
+    if (j == SB_AP_BITMAP (s)[i].first_zero_hint) {
+        SB_AP_BITMAP (s)[i].first_zero_hint ++;
+    }
+    journal_mark_dirty (th, s, SB_AP_BITMAP (s)[i].bh); 
     *free_blocknrs = search_start ;
     free_blocknrs ++;
   }
diff -ruN linux-2.4.11-pre6/fs/reiserfs/prints.c linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/prints.c
--- linux-2.4.11-pre6/fs/reiserfs/prints.c	Wed Oct 10 14:42:40 2001
+++ linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/prints.c	Wed Oct 10 14:47:35 2001
@@ -495,19 +495,6 @@
     return 0;
 }
 
-static char * reiserfs_version (char * buf)
-{
-    __u16 * pversion;
-
-    pversion = (__u16 *)(buf) + 36;
-    if (*pversion == 0)
-	return "0";
-    if (*pversion == 2)
-	return "2";
-    return "Unknown";
-}
-
-
 /* return 1 if this is not super block */
 static int print_super_block (struct buffer_head * bh)
 {
diff -ruN linux-2.4.11-pre6/fs/reiserfs/resize.c linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/resize.c
--- linux-2.4.11-pre6/fs/reiserfs/resize.c	Wed Oct 10 14:40:49 2001
+++ linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/resize.c	Wed Oct 10 14:47:35 2001
@@ -19,7 +19,8 @@
 int reiserfs_resize (struct super_block * s, unsigned long block_count_new)
 {
 	struct reiserfs_super_block * sb;
-	struct buffer_head ** bitmap, * bh;
+        struct reiserfs_bitmap_info *bitmap;
+	struct buffer_head * bh;
 	struct reiserfs_transaction_handle th;
 	unsigned int bmap_nr_new, bmap_nr;
 	unsigned int block_r_new, block_r;
@@ -103,26 +104,26 @@
 	
 	    /* allocate additional bitmap blocks, reallocate array of bitmap
 	     * block pointers */
-	    bitmap = reiserfs_kmalloc(sizeof(struct buffer_head *) * bmap_nr_new, GFP_KERNEL, s);
+	    bitmap = reiserfs_kmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new, GFP_KERNEL, s);
 	    if (!bitmap) {
 		printk("reiserfs_resize: unable to allocate memory.\n");
 		return -ENOMEM;
 	    }
 	    for (i = 0; i < bmap_nr; i++)
-		bitmap[i] = SB_AP_BITMAP(s)[i];
+		bitmap[i].bh = SB_AP_BITMAP(s)[i].bh;
 	    for (i = bmap_nr; i < bmap_nr_new; i++) {
-		bitmap[i] = reiserfs_getblk(s->s_dev, i * s->s_blocksize * 8, s->s_blocksize);
-		memset(bitmap[i]->b_data, 0, sb->s_blocksize);
-		reiserfs_test_and_set_le_bit(0, bitmap[i]->b_data);
-
-		mark_buffer_dirty(bitmap[i]) ;
-		mark_buffer_uptodate(bitmap[i], 1);
-		ll_rw_block(WRITE, 1, bitmap + i);
-		wait_on_buffer(bitmap[i]);
+		bitmap[i].bh = reiserfs_getblk(s->s_dev, i * s->s_blocksize * 8, s->s_blocksize);
+		memset(bitmap[i].bh->b_data, 0, sb->s_blocksize);
+		reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data);
+
+		mark_buffer_dirty(bitmap[i].bh) ;
+		mark_buffer_uptodate(bitmap[i].bh, 1);
+		ll_rw_block(WRITE, 1, &bitmap[i].bh);
+		wait_on_buffer(bitmap[i].bh);
 	    }	
 	    /* free old bitmap blocks array */
 	    reiserfs_kfree(SB_AP_BITMAP(s), 
-			   sizeof(struct buffer_head *) * bmap_nr, s);
+			   sizeof(struct reiserfs_bitmap_info) * bmap_nr, s);
 	    SB_AP_BITMAP(s) = bitmap;
 	}
 	
@@ -130,17 +131,17 @@
 	journal_begin(&th, s, 10);
 
 	/* correct last bitmap blocks in old and new disk layout */
-	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1], 1);
+	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1);
 	for (i = block_r; i < s->s_blocksize * 8; i++)
 	    reiserfs_test_and_clear_le_bit(i, 
-					   SB_AP_BITMAP(s)[bmap_nr - 1]->b_data);
-	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1]);
+					   SB_AP_BITMAP(s)[bmap_nr - 1].bh->b_data);
+	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh);
 
-	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1], 1);
+	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1);
 	for (i = block_r_new; i < s->s_blocksize * 8; i++)
 	    reiserfs_test_and_set_le_bit(i,
-					 SB_AP_BITMAP(s)[bmap_nr_new - 1]->b_data);
-	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1]);
+					 SB_AP_BITMAP(s)[bmap_nr_new - 1].bh->b_data);
+	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh);
  
  	/* update super */
 	reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
diff -ruN linux-2.4.11-pre6/fs/reiserfs/super.c linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/super.c
--- linux-2.4.11-pre6/fs/reiserfs/super.c	Wed Oct 10 14:42:40 2001
+++ linux-2.4.11-pre6-bmap-hinting/fs/reiserfs/super.c	Wed Oct 10 14:47:35 2001
@@ -98,9 +98,9 @@
   journal_release(&th, s) ;
 
   for (i = 0; i < SB_BMAP_NR (s); i ++)
-    brelse (SB_AP_BITMAP (s)[i]);
+    brelse (SB_AP_BITMAP (s)[i].bh);
 
-  reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s);
+  reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR (s), s);
 
   brelse (SB_BUFFER_WITH_SB (s));
 
@@ -164,6 +164,8 @@
 	    set_bit (REISERFS_NO_UNHASHED_RELOCATION, mount_options);
 	} else if (!strcmp (this_char, "hashed_relocation")) {
 	    set_bit (REISERFS_HASHED_RELOCATION, mount_options);
+        } else if (!strcmp (this_char, "no_bitmap_hinting")) {
+            set_bit (REISERFS_NO_BITMAP_HINTING, mount_options);
 	} else if (!strcmp (this_char, "test4")) {
 	    set_bit (REISERFS_TEST4, mount_options);
 	} else if (!strcmp (this_char, "nolog")) {
@@ -278,28 +280,73 @@
   return 0;
 }
 
+/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
+ * @sb - superblock for this filesystem
+ * @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
+ *
+ * This routine counts how many free bits there are, finding the first zero
+ * as a side effect. Could also be implemented as a loop of test_bit() calls, or
+ * a loop of find_first_zero_bit() calls. This implementation is similar to 
+ * find_first_zero_bit(), but doesn't return after it finds the first bit.
+ * Should only be called on fs mount, but should be fairly efficient anyways.
+ *
+ * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
+ * will * invariably occupt block 0 represented in the bitmap. The only
+ * exception to this is when free_count also == 0, since there will be no
+ * free blocks at all.
+ */
+static void load_bitmap_info_data (struct super_block *sb,
+                                   struct reiserfs_bitmap_info *bi)
+{
+    __u32 *cur = (__u32 *)bi->bh->b_data;
+
+    while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
+
+        /* No need to scan if all 0's or all 1's.
+          * Since we're only counting 0's, we can simply ignore all 1's */
+        if (*cur == 0) {
+            if (bi->first_zero_hint == 0) {
+                bi->first_zero_hint = ((char *)cur - bi->bh->b_data) << 3;
+            }
+            bi->free_count += 32;
+        } else if (*cur != ~0L) {
+            int b;
+            for (b = 0; b < 32; b++) {
+                if (!test_bit (b, cur)) {
+                    bi->free_count ++;
+                    if (bi->first_zero_hint == 0)
+                        bi->first_zero_hint =
+                                        (((char *)cur - bi->bh->b_data) << 3) + b;
+                }
+            }
+        }
+        cur ++;
+    }
+}
 
 static int read_bitmaps (struct super_block * s)
 {
     int i, bmp, dl ;
     struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK(s);
 
-    SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * sb_bmap_nr(rs), GFP_NOFS, s);
+    SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct reiserfs_bitmap_info) * sb_bmap_nr(rs), GFP_NOFS, s);
     if (SB_AP_BITMAP (s) == 0)
 	return 1;
-    memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * sb_bmap_nr(rs));
+    memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_bitmap_info) * sb_bmap_nr(rs));
 
     /* reiserfs leaves the first 64k unused so that any partition
        labeling scheme currently used will have enough space. Then we
        need one block for the super.  -Hans */
     bmp = (REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1;	/* first of bitmap blocks */
-    SB_AP_BITMAP (s)[0] = reiserfs_bread (s->s_dev, bmp, s->s_blocksize);
-    if(!SB_AP_BITMAP(s)[0])
+    SB_AP_BITMAP (s)[0].bh = reiserfs_bread (s->s_dev, bmp, s->s_blocksize);
+    if(!SB_AP_BITMAP(s)[0].bh)
 	return 1;
+    load_bitmap_info_data (s, SB_AP_BITMAP (s));
     for (i = 1, bmp = dl = s->s_blocksize * 8; i < sb_bmap_nr(rs); i ++) {
-	SB_AP_BITMAP (s)[i] = reiserfs_bread (s->s_dev, bmp, s->s_blocksize);
-	if (!SB_AP_BITMAP (s)[i])
+	SB_AP_BITMAP (s)[i].bh = reiserfs_bread (s->s_dev, bmp, s->s_blocksize);
+	if (!SB_AP_BITMAP (s)[i].bh)
 	    return 1;
+        load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
 	bmp += dl;
     }
 
@@ -313,16 +360,17 @@
   int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1;  /* first of bitmap blocks */
 
   /* read true bitmap */
-  SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * sb_bmap_nr(rs), GFP_NOFS, s);
+  SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct reiserfs_buffer_info *) * sb_bmap_nr(rs), GFP_NOFS, s);
   if (SB_AP_BITMAP (s) == 0)
     return 1;
 
-  memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * sb_bmap_nr(rs));
+  memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
 
   for (i = 0; i < sb_bmap_nr(rs); i ++) {
-    SB_AP_BITMAP (s)[i] = reiserfs_bread (s->s_dev, bmp1 + i, s->s_blocksize);
-    if (!SB_AP_BITMAP (s)[i])
+    SB_AP_BITMAP (s)[i].bh = reiserfs_bread (s->s_dev, bmp1 + i, s->s_blocksize);
+    if (!SB_AP_BITMAP (s)[i].bh)
       return 1;
+    load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
   }
 
   return 0;
@@ -335,7 +383,7 @@
   char * buf;
 
   while (i < SB_BLOCK_COUNT (s)) {
-    buf = SB_AP_BITMAP (s)[i / (s->s_blocksize * 8)]->b_data;
+    buf = SB_AP_BITMAP (s)[i / (s->s_blocksize * 8)].bh->b_data;
     if (!reiserfs_test_le_bit (i % (s->s_blocksize * 8), buf))
       free ++;
     i ++;
@@ -437,10 +485,11 @@
   }
 
   for (i = 0; i < SB_BMAP_NR(s) ; i++) {
-    ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i])) ;
-    wait_on_buffer(SB_AP_BITMAP(s)[i]) ;
-    if (!buffer_uptodate(SB_AP_BITMAP(s)[i])) {
-      printk("reread_meta_blocks, error reading bitmap block number %d at %ld\n", i, SB_AP_BITMAP(s)[i]->b_blocknr) ;
+    ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh)) ;
+    wait_on_buffer(SB_AP_BITMAP(s)[i].bh) ;
+    if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
+      printk("reread_meta_blocks, error reading bitmap block number %d at
+      %ld\n", i, SB_AP_BITMAP(s)[i].bh->b_blocknr) ;
       return 1 ;
     }
   }
@@ -757,10 +806,10 @@
     if (SB_DISK_SUPER_BLOCK (s)) {
 	for (j = 0; j < SB_BMAP_NR (s); j ++) {
 	    if (SB_AP_BITMAP (s))
-		brelse (SB_AP_BITMAP (s)[j]);
+		brelse (SB_AP_BITMAP (s)[j].bh);
 	}
 	if (SB_AP_BITMAP (s))
-	    reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s);
+	    reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR (s), s);
     }
     if (SB_BUFFER_WITH_SB (s))
 	brelse(SB_BUFFER_WITH_SB (s));
diff -ruN linux-2.4.11-pre6/include/linux/reiserfs_fs_sb.h linux-2.4.11-pre6-bmap-hinting/include/linux/reiserfs_fs_sb.h
--- linux-2.4.11-pre6/include/linux/reiserfs_fs_sb.h	Wed Oct 10 14:42:40 2001
+++ linux-2.4.11-pre6-bmap-hinting/include/linux/reiserfs_fs_sb.h	Wed Oct 10 14:47:35 2001
@@ -314,6 +314,14 @@
 
 typedef __u32 (*hashf_t) (const signed char *, int);
 
+struct reiserfs_bitmap_info
+{
+    // FIXME: Won't work with block sizes > 8K
+    __u16  first_zero_hint;
+    __u16  free_count;
+    struct buffer_head *bh; /* the actual bitmap */
+};
+
 /* reiserfs union of in-core super block data */
 struct reiserfs_sb_info
 {
@@ -321,7 +329,7 @@
 				/* both the comment and the choice of
                                    name are unclear for s_rs -Hans */
     struct reiserfs_super_block * s_rs;           /* Pointer to the super block in the buffer */
-    struct buffer_head ** s_ap_bitmap;       /* array of buffers, holding block bitmap */
+    struct reiserfs_bitmap_info * s_ap_bitmap;
     struct reiserfs_journal *s_journal ;		/* pointer to journal information */
     unsigned short s_mount_state;                 /* reiserfs state (valid, invalid) */
   
@@ -386,6 +394,7 @@
 #define REISERFS_NO_UNHASHED_RELOCATION 12
 #define REISERFS_HASHED_RELOCATION 13
 #define REISERFS_TEST4 14 
+#define REISERFS_NO_BITMAP_HINTING 15
 
 #define REISERFS_TEST1 11
 #define REISERFS_TEST2 12
@@ -400,6 +409,7 @@
 #define reiserfs_no_unhashed_relocation(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NO_UNHASHED_RELOCATION))
 #define reiserfs_hashed_relocation(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_HASHED_RELOCATION))
 #define reiserfs_test4(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_TEST4))
+#define reiserfs_no_bitmap_hinting(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NO_BITMAP_HINTING))
 
 #define dont_have_tails(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << NOTAIL))
 #define replay_only(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REPLAYONLY))
