Ok guys, here's another speedup patch.  This has the fix for the
segfault yura found, a few micro optimizations, and changes the
soft buffer limit to 500k.

Stats on the number of reads and writes are printed for each run,
to help tune the soft buffer limit.

This doesn't result in huge performance changes over the last patch,
but the CPU time consumed is a little less.

I'm also interested to hear how this does on slower disks.  It should
be more or less ready for inclusion, so if people object to parts of it,
please let me know.



-chris

# reiserfsprogs-speedup-5.diff
diff -ur diff/reiserfsprogs-3.x.1b-pre2/fsck/check_tree.c 
reiserfsprogs-3.x.1b-pre2/fsck/check_tree.c
--- diff/reiserfsprogs-3.x.1b-pre2/fsck/check_tree.c    Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/fsck/check_tree.c Wed Jan 30 11:58:39 2002
@@ -386,7 +386,7 @@
        return 0;
     }
 
-    mark_objectid_really_used (proper_id_map (fs), objectid);
+    __mark_objectid_really_used (proper_id_map (fs), objectid, pos);
     return 0;
 }
 
diff -ur diff/reiserfsprogs-3.x.1b-pre2/fsck/fsck.h 
reiserfsprogs-3.x.1b-pre2/fsck/fsck.h
--- diff/reiserfsprogs-3.x.1b-pre2/fsck/fsck.h  Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/fsck/fsck.h       Wed Jan 30 09:43:00 2002
@@ -243,6 +243,7 @@
 void free_id_map (struct id_map *);
 int is_objectid_really_used (struct id_map *, __u32 id, int * ppos);
 int mark_objectid_really_used (struct id_map *, __u32 id);
+int __mark_objectid_really_used (struct id_map *, __u32 id, int pos);
 void flush_objectid_map (struct id_map * map, reiserfs_filsys_t * fs);
 void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t * fs);
 
diff -ur diff/reiserfsprogs-3.x.1b-pre2/fsck/main.c 
reiserfsprogs-3.x.1b-pre2/fsck/main.c
--- diff/reiserfsprogs-3.x.1b-pre2/fsck/main.c  Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/fsck/main.c       Fri Feb  1 13:10:00 2002
@@ -552,7 +552,6 @@
     fsck_progress ("Syncing..");
     fs->fs_dirt = 1;
     reiserfs_close (fs);
-    sync ();
     fsck_progress ("done\n");
 }
 
@@ -766,7 +765,6 @@
     free_id_map (proper_id_map (fs));
     reiserfs_close (fs);
     close_rollback_file ();
-    sync();
     
     time (&t);
     fsck_progress ("###########\n"
@@ -870,8 +868,6 @@
     reiserfs_panic ("Fast rebuild is not ready");
 
 }
-
-
 
 int main (int argc, char * argv [])
 {
diff -ur diff/reiserfsprogs-3.x.1b-pre2/fsck/segments.c 
reiserfsprogs-3.x.1b-pre2/fsck/segments.c
--- diff/reiserfsprogs-3.x.1b-pre2/fsck/segments.c      Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/fsck/segments.c   Thu Jan 31 11:43:19 2002
@@ -30,7 +30,8 @@
 };
 
 struct overwritten_unfm ** g_overwritten_unfms;
-int g_overwritten_unfms_amount;        /* number of unformatted nodes, which contain 
direct items */
+int g_overwritten_unfms_amount;        /* allocated size of the array */ 
+int g_overwritten_unfms_len ; /* actual number used in the array */
 
 
 /* adds segment to the single linked list of segments sorted by begin
@@ -63,6 +64,67 @@
   return first;
 }
 
+static int comp_overwritten_unfm(const void *p1, const void *p2) {
+    const struct overwritten_unfm *o1 ;
+    unsigned long blocknum ;
+
+    o1 = *(const struct overwritten_unfm **)p1 ;
+    blocknum = *(unsigned long *)p2 ;
+
+    if (o1->ou_unfm_ptr < blocknum)
+        return -1 ;
+    if (o1->ou_unfm_ptr > blocknum)
+        return 1 ;
+
+  return 0 ;
+}
+
+static void print_g_unfm(void) {
+    int i; 
+    for(i = 0 ; i < g_overwritten_unfms_amount ; i++) {
+       if (g_overwritten_unfms[i] == NULL) {
+           printf("NULL ") ;
+           continue ;
+       }
+        printf("%d ", g_overwritten_unfms[i]->ou_unfm_ptr) ;
+    }
+    printf("\n%d entries\n", g_overwritten_unfms_amount) ;
+}
+static void check_g_unfm(int pos) {
+    int i; 
+
+    if (pos > 0) {
+        if (g_overwritten_unfms[pos-1]->ou_unfm_ptr >= 
+           g_overwritten_unfms[pos]->ou_unfm_ptr) {
+           print_g_unfm() ;
+           die("g_unfm list corrupted at %d\n", pos) ;
+       }
+    }
+    if (pos < (g_overwritten_unfms_len - 1)) {
+        if (g_overwritten_unfms[pos]->ou_unfm_ptr >= 
+           g_overwritten_unfms[pos+1]->ou_unfm_ptr) {
+           print_g_unfm() ;
+           die("g_unfm list corrupted at %d\n", pos) ;
+       }
+    }
+}
+
+static int check_unfm_search_result(int ret, unsigned long unfm, int pos) {
+    
+  if (ret == POSITION_FOUND) {
+      if (pos > g_overwritten_unfms_amount)
+          die("search gave %d, too big %d\n", pos, g_overwritten_unfms_amount);
+      if (pos < 0)
+          die("found pos less than zero %d\n", pos) ;
+      if (g_overwritten_unfms[pos]->ou_unfm_ptr != unfm) {
+          die("found %lu incorrect %lu\n", g_overwritten_unfms[pos],
+                                          unfm) ;
+      }
+      return 0 ;
+  }
+  return 0 ;
+}
+
 
 /* input parameter 
    `list_head` - first element of overlapping segments sorted by left edge
@@ -115,52 +177,76 @@
 /* this prepare list of segments to extracting of unoverwritten segments */
 struct overwritten_unfm_segment * find_overwritten_unfm (unsigned long unfm, int 
length, struct overwritten_unfm_segment * segment_to_init)
 {
-  int i;
+    struct overwritten_unfm *f ;
 
-  for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++)
-    if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm) {
-      if (g_overwritten_unfms[i]->ou_segments == 0)
-       die ("find_overwritten_unfm: no segment found");
-      g_overwritten_unfms[i]->ou_segments = add_segment 
(g_overwritten_unfms[i]->ou_segments, -1, -1);
-      add_segment (g_overwritten_unfms[i]->ou_segments, length, length);
-      segment_to_init->ous_begin = -2;
-      segment_to_init->ous_end = -2;
-      return g_overwritten_unfms[i]->ou_segments;
+    f = look_for_overwritten_unfm(unfm) ;
+    if (!f) {
+       return NULL ;
     }
-  return 0;
+    if (f->ou_segments == 0)
+       die ("find_overwritten_unfm: no segment found");
+    f->ou_segments = add_segment (f->ou_segments, -1, -1);
+    add_segment (f->ou_segments, length, length);
+    segment_to_init->ous_begin = -2;
+    segment_to_init->ous_end = -2;
+    return f->ou_segments;
 }
 
 struct overwritten_unfm * look_for_overwritten_unfm (__u32 unfm)
 {
-  int i;
-
-  for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++)
-    if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm)
-      return g_overwritten_unfms[i];
-    return 0;
+    int ret, pos ;
+    ret = reiserfs_bin_search(&unfm, g_overwritten_unfms, 
+                              g_overwritten_unfms_len, 
+                             sizeof(struct overwritten_unfm *),
+                             &pos, comp_overwritten_unfm) ;
+
+    check_unfm_search_result(ret, unfm, pos) ;
+    if (ret == POSITION_FOUND) {
+       return g_overwritten_unfms[pos];
+    }
+    return NULL ;
 }
 
-#define GROW_BY 10
+#define GROW_BY 64
 struct overwritten_unfm * add_overwritten_unfm (unsigned long unfm, struct item_head 
* direct_ih)
 {
-    int i;
+    int ret, pos ;
+
+    ret = reiserfs_bin_search(&unfm, g_overwritten_unfms, 
+                              g_overwritten_unfms_len, 
+                             sizeof(struct overwritten_unfm *),
+                             &pos, comp_overwritten_unfm) ;
     
-    for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++) {
-       if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm)
-           return g_overwritten_unfms[i];
+    check_unfm_search_result(ret, unfm, pos) ;
+    if (ret == POSITION_FOUND) {
+        return g_overwritten_unfms[pos] ;
     }
-    
-    if (i == g_overwritten_unfms_amount) {
-       g_overwritten_unfms = expandmem (g_overwritten_unfms, sizeof (struct 
overwritten_unfm *) * i, 
-                                        sizeof (struct overwritten_unfm *) * GROW_BY);
+
+    g_overwritten_unfms_len++ ;
+
+    /* do we need to expand the map? */
+    if (g_overwritten_unfms_len >= g_overwritten_unfms_amount) {
+       g_overwritten_unfms = expandmem(g_overwritten_unfms, 
+                                 sizeof (struct overwritten_unfm *) * 
+                                 g_overwritten_unfms_amount, 
+                                 sizeof (struct overwritten_unfm *) * GROW_BY);
        g_overwritten_unfms_amount += GROW_BY;
     }
-    g_overwritten_unfms[i] = getmem (sizeof (struct overwritten_unfm));
-    g_overwritten_unfms[i]->ou_unfm_ptr = unfm;
-    g_overwritten_unfms[i]->ou_dir_id = get_key_dirid (&direct_ih->ih_key);
-    g_overwritten_unfms[i]->ou_objectid = get_key_objectid (&direct_ih->ih_key);
-    g_overwritten_unfms[i]->ou_offset = get_offset(&direct_ih->ih_key) - 
(get_offset(&direct_ih->ih_key) - 1) % fs->fs_blocksize;
-    return g_overwritten_unfms[i];
+    /* does the list need to be shifted right? */
+    if (g_overwritten_unfms[pos]) {
+        memmove(g_overwritten_unfms + pos + 1, g_overwritten_unfms + pos,
+               (g_overwritten_unfms_amount - pos - 1) *
+               sizeof(struct overwritten_unfm *)) ;
+    }
+    g_overwritten_unfms[pos] = getmem (sizeof (struct overwritten_unfm));
+    g_overwritten_unfms[pos]->ou_unfm_ptr = unfm;
+    g_overwritten_unfms[pos]->ou_dir_id = get_key_dirid (&direct_ih->ih_key);
+    g_overwritten_unfms[pos]->ou_objectid=get_key_objectid(&direct_ih->ih_key);
+    g_overwritten_unfms[pos]->ou_offset = get_offset(&direct_ih->ih_key) - 
+                                         (get_offset(&direct_ih->ih_key) - 1) %
+                                        fs->fs_blocksize;
+    check_g_unfm(pos) ;
+    return g_overwritten_unfms[pos];
 }
 
 
diff -ur diff/reiserfsprogs-3.x.1b-pre2/fsck/semantic_rebuild.c 
reiserfsprogs-3.x.1b-pre2/fsck/semantic_rebuild.c
--- diff/reiserfsprogs-3.x.1b-pre2/fsck/semantic_rebuild.c      Mon Jan 28 06:39:54 
2002
+++ reiserfsprogs-3.x.1b-pre2/fsck/semantic_rebuild.c   Wed Jan 30 09:53:22 2002
@@ -619,7 +619,7 @@
                /* this works for files only */
                relocate = 1;
        } else
-           mark_objectid_really_used (semantic_id_map (fs), get_key_objectid 
(&ih->ih_key));
+           __mark_objectid_really_used (semantic_id_map (fs), get_key_objectid 
+(&ih->ih_key), pos_in_item);
 
        mark_item_reachable (ih, bh);
     }
diff -ur diff/reiserfsprogs-3.x.1b-pre2/fsck/uobjectid.c 
reiserfsprogs-3.x.1b-pre2/fsck/uobjectid.c
--- diff/reiserfsprogs-3.x.1b-pre2/fsck/uobjectid.c     Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/fsck/uobjectid.c  Wed Jan 30 12:49:59 2002
@@ -112,19 +112,10 @@
 
 static int comp_ids (const void * p1, const void * p2)
 {
-    const __u32 * id1, * id2;
 
-    id1 = p1;
-    id2 = p2;    
-
-    if ( le32_to_cpu(*id1) < le32_to_cpu(*id2) )
-        return -1;
-    if ( le32_to_cpu(*id1) > le32_to_cpu(*id2) )
-        return 1;
-    return 0;
+    return (le32_to_cpu(*(__u32 *)p1) - le32_to_cpu(*(__u32 *)p2)) ;
 }
 
-
 /* */
 struct id_map * init_id_map (void)
 {
@@ -198,16 +189,7 @@
            die ("check_objectid_map: map corrupted");
 }
 
-/* returns 1 objectid is marked used already, 0 otherwise */
-int mark_objectid_really_used (struct id_map * map, __u32 id)
-{
-    int pos;
-
-    
-    /* check whether id is used and get place if used or place to insert if not */
-    if (is_objectid_really_used (map, id, &pos) == 1)
-        return 1;
-
+int __mark_objectid_really_used(struct id_map *map, __u32 id, int pos) {
     map->objectids_marked ++;
     if (pos % 2 == 0){
         /* id not found in the map. why? is_id_used() knows */
@@ -258,6 +240,19 @@
     return 0;
 }
 
+/* returns 1 objectid is marked used already, 0 otherwise */
+int mark_objectid_really_used (struct id_map * map, __u32 id)
+{
+    int pos;
+
+    
+    /* check whether id is used and get place if used or place to insert if not */
+    if (is_objectid_really_used (map, id, &pos) == 1)
+        return 1;
+
+    return __mark_objectid_really_used(map, id, pos) ;
+}
+
 
 static __u32 get_free_id (reiserfs_filsys_t * fs)
 {
@@ -342,17 +337,16 @@
 #endif
 
 
-#if 0
 /* print the map of objectids */
-void print_objectid_list ()
+void print_objectid_list (__u32 *map, int count)
 {
     int i;
-    printf ("\n control id map: all %d, used:%d", id_map.m_page_count * MAP_SIZE, 
id_map.m_used_slots_count);
 
-    for (i = 0; i < id_map.m_used_slots_count; i += 2)
-           printf ("\n[%u-%u]", id_map.m_begin[i], id_map.m_begin[i + 1] - 1);
+    for (i = 0; i < count ; i += 2)
+           printf ("\n[%u-%u]", le32_to_cpu(map[i]),le32_to_cpu(map[i+1]));
 }
 
+#if 0
 /* print on-disk map of objectids */
 void print_disk_objectid_list (void)
 {
diff -ur diff/reiserfsprogs-3.x.1b-pre2/lib/io.c reiserfsprogs-3.x.1b-pre2/lib/io.c
--- diff/reiserfsprogs-3.x.1b-pre2/lib/io.c     Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/lib/io.c  Fri Feb  1 12:52:03 2002
@@ -45,24 +45,38 @@
 /* All buffers are in double linked cycled list.  If getblk found buffer with
    wanted block number in hash queue it moves buffer to the end of list. */
 
-#define MAX_NR_BUFFERS 16384
-
 static int g_nr_buffers;
 
 
-/* create buffers until we spend this fraction of system memory */
 static unsigned long buffers_memory;
+
+/* create buffers until we spend this fraction of system memory, this
+** is a hard limit on the amount of buffer ram used
+*/
 #define BUFFER_MEMORY_FRACTION 10
 
+/* number of bytes in local buffer cache before we start forcing syncs
+** of dirty data and reusing unused buffers instead of allocating new
+** ones.  If a flush doesn't find reusable buffers, new ones are
+** still allocated up to the BUFFER_MEMORY_FRACTION percentage
+**
+*/
+#define BUFFER_SOFT_LIMIT (500 * 1024) 
+
 
 #define NR_HASH_QUEUES 4096
 static struct buffer_head * g_a_hash_queues [NR_HASH_QUEUES];
 static struct buffer_head * Buffer_list_head;
+static struct buffer_head * g_free_buffers = NULL ;
 static struct buffer_head * g_buffer_heads;
+static int buffer_hits = 0 ;
+static int buffer_misses = 0 ;
+static int buffer_reads = 0 ;
+static int buffer_writes = 0 ;
 
 
 
-static void show_buffers (int dev, int size)
+static void _show_buffers(struct buffer_head **list, int dev, int size)
 {
     int all = 0;
     int dirty = 0;
@@ -70,11 +84,11 @@
     int free = 0;
     struct buffer_head * next;
 
-    next = Buffer_list_head;
+    next = *list;
+    if (!next)
+        return ;
 
     for (;;) {
-       if (!next)
-           die ("show_buffers: buffer list is corrupted");
        if (next->b_dev == dev && next->b_size == size) {
            all ++;
            if (next->b_count != 0) {
@@ -88,7 +102,7 @@
            }
        }
        next = next->b_next;
-       if (next == Buffer_list_head)
+       if (next == *list)
            break;
     }
 
@@ -96,6 +110,11 @@
            dev, size, free, in_use, dirty, all);
 }
 
+static void show_buffers (int dev, int size) {
+    _show_buffers(&Buffer_list_head, dev, size) ;
+    _show_buffers(&g_free_buffers, dev, size) ;
+}
+
 
 static void insert_into_hash_queue (struct buffer_head * bh)
 {
@@ -133,19 +152,20 @@
 }
 
 
-static void put_buffer_list_end (struct buffer_head * bh)
+static void put_buffer_list_end (struct buffer_head **list,
+                                 struct buffer_head * bh)
 {
     struct buffer_head * last = 0;
 
     if (bh->b_prev || bh->b_next)
        die ("put_buffer_list_end: buffer list corrupted");
 
-    if (Buffer_list_head == 0) {
+    if (*list == 0) {
        bh->b_next = bh;
        bh->b_prev = bh;
-       Buffer_list_head = bh;
+       *list = bh;
     } else {
-       last = Buffer_list_head->b_prev;
+       last = (*list)->b_prev;
     
        bh->b_next = last->b_next;
        bh->b_prev = last;
@@ -155,28 +175,31 @@
 }
 
 
-static void remove_from_buffer_list (struct buffer_head * bh)
+static void remove_from_buffer_list (struct buffer_head **list,
+                                     struct buffer_head * bh)
 {
     if (bh == bh->b_next) {
-       Buffer_list_head = 0;
+       *list = 0;
     } else {
        bh->b_prev->b_next = bh->b_next;
        bh->b_next->b_prev = bh->b_prev;
-       if (bh == Buffer_list_head)
-           Buffer_list_head = bh->b_next;
+       if (bh == *list)
+           *list = bh->b_next;
     }
 
     bh->b_next = bh->b_prev = 0;
 }
 
 
-static void put_buffer_list_head (struct buffer_head * bh)
+static void put_buffer_list_head (struct buffer_head **list, 
+                                  struct buffer_head * bh)
 {
-    put_buffer_list_end (bh);
-    Buffer_list_head = bh;
+    put_buffer_list_end (list, bh);
+    *list = bh;
 }
 
 #include <sys/mman.h>
+#define MEM_MAX 32000000
 
 static size_t estimate_memory_amount (void)
 {
@@ -234,8 +257,6 @@
 
     if (buffers_memory > buffer_memory_limit)
        return 0;
-
-
     /* get memory for array of buffer heads */
     bh = (struct buffer_head *)getmem (GROW_BUFFERS__NEW_BUFERS_PER_CALL * 
                                       sizeof (struct buffer_head) + sizeof (struct 
buffer_head *));
@@ -258,7 +279,7 @@
            die ("grow_buffers: no memory for new buffer data");
        tmp->b_dev = 0;
        tmp->b_size = size;
-       put_buffer_list_head (tmp);
+       put_buffer_list_head (&g_free_buffers, tmp);
 
     }
     buffers_memory += GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
@@ -286,11 +307,12 @@
 }
 
 
-static struct buffer_head * get_free_buffer (int size)
+static struct buffer_head * get_free_buffer (struct buffer_head **list, 
+                                             int size)
 {
     struct buffer_head * next;
 
-    next = Buffer_list_head;
+    next = *list;
     if (!next)
        return 0;
 
@@ -299,12 +321,11 @@
            die ("get_free_buffer: buffer list is corrupted");
        if (next->b_count == 0 && buffer_clean (next) && next->b_size == size) {
            remove_from_hash_queue (next);
-           remove_from_buffer_list (next);
-           put_buffer_list_end (next);
+           remove_from_buffer_list (list, next);
            return next;
        }
        next = next->b_next;
-       if (next == Buffer_list_head)
+       if (next == *list)
            break;
     }
     return 0;
@@ -313,28 +334,40 @@
 
 /* to_write == 0 when all blocks have to be flushed. Otherwise - write only
    buffers with b_count == 0 */
-static void sync_buffers (dev_t dev, int to_write)
+static void sync_buffers (struct buffer_head **list, dev_t dev, int to_write)
 {
     struct buffer_head * next;
     int written = 0;
 
-
-    next = Buffer_list_head;
+restart:
+    next = *list;
+    if (!next)
+        return ;
     for (;;) {
        if (!next)
            die ("sync_buffers: buffer list is corrupted");
- 
-       if (next->b_dev == dev && buffer_dirty (next) && buffer_uptodate (next)) {
+
+       if (next->b_dev == dev && buffer_dirty(next) && buffer_uptodate(next)) {
            if (to_write == 0 || next->b_count == 0) {
-               written ++;
                bwrite (next);
-               if (written == to_write)
-                   return;
            }
        }
     
+       /* if this buffer is reusable, put it onto the end of the free list */
+       if (next->b_count == 0 && buffer_clean(next)) {
+           remove_from_hash_queue (next);
+           remove_from_buffer_list (list, next);
+           put_buffer_list_end (&g_free_buffers, next);
+           written++ ;
+           if (written == to_write)
+               return ;
+           goto restart; 
+       }
+       if (to_write && written >= to_write)
+           return;
+ 
        next = next->b_next;
-       if (next == Buffer_list_head)
+       if (next == *list)
            break;
     }
 }
@@ -344,7 +377,7 @@
 {
     if (!dev)
        die ("flush_buffers: device is not specifed");
-    sync_buffers (dev, 0/*all*/);
+    sync_buffers (&Buffer_list_head, dev, 0/*all*/);
 }
 
 
@@ -358,21 +391,33 @@
 
        /*checkmem (bh->b_data, bh->b_size);*/
 
-       remove_from_buffer_list (bh);
-       put_buffer_list_end (bh);
+       remove_from_buffer_list (&Buffer_list_head, bh);
+       put_buffer_list_end (&Buffer_list_head, bh);
        bh->b_count ++;
+       buffer_hits++ ;
        return bh;
     }
+    buffer_misses++ ;
 
-    bh = get_free_buffer (size);
-    if (bh == 0) {
-       if (grow_buffers (size) == 0) {
-           sync_buffers (dev, 100);
+    bh = get_free_buffer (&g_free_buffers, size);
+    if (bh == NULL) {
+       if (buffers_memory >= BUFFER_SOFT_LIMIT) {
+           sync_buffers (&Buffer_list_head, dev, 32);
+       } else {
+           if (grow_buffers(size) == 0)
+               sync_buffers (&Buffer_list_head, dev, 32);
        }
-       bh = get_free_buffer (size);
-       if (bh == 0) {
-           show_buffers (dev, size);
-           die ("getblk: no free buffers after grow_buffers and refill (%d)", 
g_nr_buffers);
+
+       bh = get_free_buffer (&g_free_buffers, size);
+       if (bh == NULL) {
+           fprintf(stderr, "buffers at %d emergency growing\n",buffers_memory);
+           grow_buffers(size) ;
+           sync_buffers (&Buffer_list_head, dev, 32);
+           bh = get_free_buffer (&g_free_buffers, size);
+           if (bh == NULL) {
+               show_buffers (dev, size);
+               die ("getblk: no free buffers after grow_buffers and refill (%d)", 
+g_nr_buffers);
+           }
        }
     }
 
@@ -385,6 +430,7 @@
     clear_bit(BH_Dirty, &bh->b_state);
     clear_bit(BH_Uptodate, &bh->b_state);
 
+    put_buffer_list_end (&Buffer_list_head, bh);
     insert_into_hash_queue (bh);
     /*checkmem (bh->b_data, bh->b_size);*/
 
@@ -403,11 +449,6 @@
     /*checkmem (bh->b_data, get_mem_size (bh->b_data));*/
     
     bh->b_count --;
-    /* if this buffer is reusable, put it at the head of the list */
-    if (bh->b_count == 0 && buffer_clean(bh)) {
-       remove_from_buffer_list (bh);
-       put_buffer_list_head (bh);
-    }
 }
 
 
@@ -417,6 +458,11 @@
        bh->b_state = 0;
        brelse (bh);
        remove_from_hash_queue (bh);
+       remove_from_buffer_list(&Buffer_list_head, bh) ;
+       if (bh->b_count == 0)
+           put_buffer_list_head(&g_free_buffers, bh) ;
+        else
+           put_buffer_list_head(&Buffer_list_head, bh) ;
     }
 }
 
@@ -426,6 +472,8 @@
     loff_t offset;
     ssize_t bytes;
 
+    buffer_reads++ ;
+
     offset = (loff_t)bh->b_size * (loff_t)bh->b_blocknr;
     if (lseek64 (bh->b_dev, offset, SEEK_SET) == (loff_t)-1)
         return 0;
@@ -741,6 +789,7 @@
     if (!buffer_dirty (bh) || !buffer_uptodate (bh))
        return 0;
 
+    buffer_writes++ ;
     if (bh->b_start_io)
        /* this is used by undo feature of reiserfsck */
        bh->b_start_io (bh->b_blocknr);
@@ -812,16 +861,14 @@
     return 0;
 }
 
+static int _check_and_free_buffer_list(struct buffer_head *list) {
+    struct buffer_head *next = list ;
+    int count = 0 ;
 
-void check_and_free_buffer_mem (void)
-{
-    int i = 0;
-    struct buffer_head * next = Buffer_list_head;
+    if (!list)
+        return 0 ;
 
-    /*sync_buffers (0, 0);*/
-    for (;;) {
-       if (!next)
-           die ("check_and_free_buffer_mem: buffer list is corrupted");
+    for(;;) {
        if (next->b_count != 0)
            fprintf (stderr, "check_and_free_buffer_mem: not free buffer (%x, %ld, 
%ld, %d)\n",
                     next->b_dev, next->b_blocknr, next->b_size, next->b_count);
@@ -831,13 +878,27 @@
                     next->b_dev, next->b_blocknr);
 
        freemem (next->b_data);
-       i ++;
+       count++ ;
        next = next->b_next;
-       if (next == Buffer_list_head)
-           break;
+       if (next == list)
+           break ;
     }
-    if (i != g_nr_buffers)
-       die ("check_and_free_buffer_mem: found %d buffers, must be %d", i, 
g_nr_buffers);
+    return count ;
+}
+
+void check_and_free_buffer_mem (void)
+{
+    int count = 0;
+    struct buffer_head * next ;
+
+    printf("check and free buffer mem, hits %d misses %d reads %d writes %d\n", 
+buffer_hits, buffer_misses, buffer_reads, buffer_writes) ;
+    /*sync_buffers (0, 0);*/
+
+    count = _check_and_free_buffer_list(Buffer_list_head) ;
+    count += _check_and_free_buffer_list(g_free_buffers) ;
+
+    if (count != g_nr_buffers)
+       die ("check_and_free_buffer_mem: found %d buffers, must be %d", count, 
+g_nr_buffers);
 
     /* free buffer heads */
     while ((next = g_buffer_heads)) {
@@ -855,18 +916,16 @@
     check_and_free_buffer_mem ();
 }
 
-
-/* forget all buffers of the given device */
-void invalidate_buffers (dev_t dev)
-{
+static void _invalidate_buffer_list(struct buffer_head *list, dev_t dev) {
     struct buffer_head * next;
 
 
-    next = Buffer_list_head;
+    if (!list)
+        return ;
+
+    next = list;
 
     for (;;) {
-       if (!next)
-           die ("invalidate_buffers: buffer list is corrupted");
        if (next->b_dev == dev) {
            if (buffer_dirty (next) || next->b_count)
                fprintf (stderr, "invalidate_buffers: dirty buffer or used buffer (%d 
%lu) found\n",
@@ -875,9 +934,17 @@
            remove_from_hash_queue (next);
        }
        next = next->b_next;
-       if (next == Buffer_list_head)
+       if (next == list) {
            break;
+        }
     }
+}
+
+/* forget all buffers of the given device */
+void invalidate_buffers (dev_t dev)
+{
+    _invalidate_buffer_list(Buffer_list_head, dev) ;
+    _invalidate_buffer_list(g_free_buffers, dev) ;
 }
 
 
diff -ur diff/reiserfsprogs-3.x.1b-pre2/lib/misc.c reiserfsprogs-3.x.1b-pre2/lib/misc.c
--- diff/reiserfsprogs-3.x.1b-pre2/lib/misc.c   Fri Feb  1 13:18:04 2002
+++ reiserfsprogs-3.x.1b-pre2/lib/misc.c        Fri Feb  1 13:06:16 2002
@@ -671,6 +671,7 @@
                         int * ppos, comparison_fn_t comp_func)
 {
     int rbound, lbound, j;
+    int ret ;
 
     if (num == 0) {
        /* objectid map may be 0 elements long */
@@ -682,20 +683,20 @@
     rbound = num - 1;
 
     for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
-       switch (comp_func ((void *)((char *)base + j * width), key ) ) {
-       case -1:/* second is greater */
+       ret =  comp_func ((void *)((char *)base + j * width), key ) ;
+       if (ret < 0) { /* second is greater */
            lbound = j + 1;
            continue;
 
-       case 1: /* first is greater */
-           if (j == 0) {
-                *ppos = lbound;
-                return POSITION_NOT_FOUND;
-           }
+       } else if (ret > 0) { /* first is greater */
+           /* if j == 0, rbound is set to -1, which makes us break
+           ** from the loop, set ppos = lbound and return not found
+           ** micro optimization...avoid special test for j == 0 here
+           */
            rbound = j - 1;
            continue;
 
-       case 0:
+       } else { /* equal */
            *ppos = j;
            return POSITION_FOUND;
        }
diff -ur diff/reiserfsprogs-3.x.1b-pre2/reiserfscore/node_formats.c 
reiserfsprogs-3.x.1b-pre2/reiserfscore/node_formats.c
--- diff/reiserfsprogs-3.x.1b-pre2/reiserfscore/node_formats.c  Fri Feb  1 13:18:09 
2002
+++ reiserfsprogs-3.x.1b-pre2/reiserfscore/node_formats.c       Thu Jan 31 12:10:21 
+2002
@@ -1269,6 +1269,9 @@
     }
 }
 
+static int comp_disk_ids(const void *p1, const void *p2) {
+    return (le32_to_cpu(*(__u32 *)p1) - le32_to_cpu(*(__u32 *)p2)) ;
+}
 
 /* functions to manipulate with super block's objectid map */
 
@@ -1276,28 +1279,23 @@
 {
     __u32 * objectid_map;
     int i = 0;
+    int count = get_sb_oid_cursize(fs->fs_ondisk_sb) ;
+    int ret ;
+    int pos ;
+    __u32 le_id = cpu_to_le32(objectid) ;
     
 
     objectid_map = (__u32 *)((char *)fs->fs_ondisk_sb + reiserfs_super_block_size 
(fs->fs_ondisk_sb));
-    
-    while (i < get_sb_oid_cursize (fs->fs_ondisk_sb)) {
-       if (objectid == le32_to_cpu (objectid_map[i])) {
-           return 1;      /* objectid is used */
-       }
-       
-       if (objectid > le32_to_cpu (objectid_map[i]) &&
-           objectid < le32_to_cpu (objectid_map[i + 1])) {
-           return 1;   /* objectid is used */
-       }
-       
-       if (objectid < le32_to_cpu (objectid_map[i]))
-           break;
 
-       i += 2;
-    }
+    ret = reiserfs_bin_search(&le_id, objectid_map, count, sizeof(__u32),
+                              &pos, comp_disk_ids) ;
     
-    /* objectid is free */
-    return 0;
+    /* if the position returned is odd, the oid is in use */
+    if (ret == POSITION_NOT_FOUND)
+        return (pos & 1) ;
+
+    /* if the position returned is even, the oid is in use */
+    return !(pos & 1) ;
 }
 
 
diff -ur diff/reiserfsprogs-3.x.1b-pre2/reiserfscore/reiserfslib.c 
reiserfsprogs-3.x.1b-pre2/reiserfscore/reiserfslib.c
--- diff/reiserfsprogs-3.x.1b-pre2/reiserfscore/reiserfslib.c   Mon Jan 28 06:39:54 
2002
+++ reiserfsprogs-3.x.1b-pre2/reiserfscore/reiserfslib.c        Wed Jan 30 14:44:31 
+2002
@@ -360,6 +360,7 @@
 
     reiserfs_flush (fs);
     reiserfs_free (fs);
+    fsync(fs->fs_dev);
 }
 
 
diff -ur diff/reiserfsprogs-3.x.1b-pre2/reiserfscore/stree.c 
reiserfsprogs-3.x.1b-pre2/reiserfscore/stree.c
--- diff/reiserfsprogs-3.x.1b-pre2/reiserfscore/stree.c Mon Jan 28 06:39:54 2002
+++ reiserfsprogs-3.x.1b-pre2/reiserfscore/stree.c      Thu Jan 31 13:03:30 2002
@@ -55,14 +55,17 @@
 {
     __u32 * p_s_key1, * p_s_key2;
     int n_key_length = REISERFS_SHORT_KEY_LEN;
+    __u32 u1, u2 ;
 
     p_s_key1 = (__u32 *)k1;
     p_s_key2 = (__u32 *)k2;
 
     for( ; n_key_length--; ++p_s_key1, ++p_s_key2 ) {
-       if ( le32_to_cpu(*p_s_key1) < le32_to_cpu(*p_s_key2) )
+       u1 = le32_to_cpu(*p_s_key1) ;
+       u2 = le32_to_cpu(*p_s_key2) ;
+       if ( u1 < u2 )
            return -1;
-       if ( le32_to_cpu(*p_s_key1) > le32_to_cpu(*p_s_key2) )
+       if ( u1 > u2 )
            return 1;
     }
 
@@ -74,16 +77,19 @@
 {
     int retval;
     const struct key * k1, * k2;
+    loff_t off1, off2 ;
     
     k1 = p1;
     k2 = p2;
     retval = comp_short_keys (k1, k2);
     if (retval)
        return retval;
-    if (get_offset (k1) < get_offset (k2))
+    off1 = get_offset(k1) ;
+    off2 = get_offset(k2) ;
+    if (off1 < off2)
        return -1;
 
-    if (get_offset (k1) > get_offset (k2))
+    if (off1 > off2)
        return 1;
 
     return 0;

Reply via email to