Index: cpukit/libblock/src/bdbuf.c
===================================================================
--- cpukit/libblock/src/bdbuf.c	(revision b5b07cad7d223ffa61db5aefa47db5f4f3ee8265)
+++ cpukit/libblock/src/bdbuf.c	(revision 2960c42fabc77838e74699060a2f1eb42df5a1a6)
@@ -1386,4 +1386,16 @@
 }
 
+static inline void
+rtems_bdbuf_group_obtain (rtems_bdbuf_buffer *bd)
+{
+  ++bd->group->users;
+}
+
+static inline void
+rtems_bdbuf_group_release (rtems_bdbuf_buffer *bd)
+{
+  --bd->group->users;
+}
+
 /**
  * Get a buffer for this device and block. This function returns a buffer once
@@ -1433,4 +1445,6 @@
  * different the buffer size for the block has changed. The buffer needs to be
  * invalidated.
+ *
+ * The returned buffer will be a user its group.
  *
  * @param dd The disk device. Has the configured block size.
@@ -1588,4 +1602,6 @@
           rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_5);
 
+        rtems_bdbuf_group_obtain (bd);
+
         return bd;
       }
@@ -1622,4 +1638,10 @@
 
   /*
+   * Before we wait for the buffer, we have to obtain its group.  This prevents
+   * a reallocation.
+   */
+  rtems_bdbuf_group_obtain (bd);
+
+  /*
    * Loop waiting for the buffer to enter the cached state. If the buffer is in
    * the access or transfer state then wait until it is not.
@@ -1660,4 +1682,10 @@
   rtems_chain_extract (&bd->link);
 
+  /*
+   * The modified list is no longer a user of the buffers group.
+   */
+  if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
+    rtems_bdbuf_group_release (bd);
+
   return bd;
 }
@@ -1718,19 +1746,14 @@
 
   /*
-   * This could be considered a bug in the caller because you should not be
-   * getting an already modified buffer but user may have modified a byte in a
-   * block then decided to seek the start and write the whole block and the
-   * file system will have no record of this so just gets the block to fill.
-   */
-  if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
+   * To get a modified buffer could be considered a bug in the caller because
+   * you should not be getting an already modified buffer but user may have
+   * modified a byte in a block then decided to seek the start and write the
+   * whole block and the file system will have no record of this so just gets
+   * the block to fill.
+   */
+  if (bd->state != RTEMS_BDBUF_STATE_MODIFIED)
+    bd->state = RTEMS_BDBUF_STATE_ACCESS;
+  else
     bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED;
-  else
-  {
-    bd->state = RTEMS_BDBUF_STATE_ACCESS;
-    /*
-     * Indicate a buffer in this group is being used.
-     */
-    bd->group->users++;
-  }
   
   if (rtems_bdbuf_tracer)
@@ -1782,4 +1805,5 @@
   rtems_blkdev_bnum     media_block;
   rtems_blkdev_bnum     media_block_count;
+  bool                  read_ahead = false;
   
   if (!bdbuf_cache.initialised)
@@ -1860,5 +1884,5 @@
      */
     bd = rtems_bdbuf_get_buffer (dd, bds_per_group, media_block + dd->start,
-                                 req->bufnum == 0 ? false : true);
+                                 read_ahead);
 
     /*
@@ -1874,13 +1898,13 @@
     if ((bd->state == RTEMS_BDBUF_STATE_CACHED) ||
         (bd->state == RTEMS_BDBUF_STATE_MODIFIED))
+    {
+      if (read_ahead)
+        rtems_bdbuf_group_release (bd);
+
       break;
+    }
 
     bd->state = RTEMS_BDBUF_STATE_TRANSFER;
     bd->error = 0;
-
-    /*
-     * The buffer will be passed to the driver so this buffer has a user.
-     */
-    bd->group->users++;
 
     if (rtems_bdbuf_tracer)
@@ -1906,4 +1930,9 @@
      */
     media_block += media_block_count;
+
+    /*
+     * After the first buffer we have read ahead buffers.
+     */
+    read_ahead = true;
   }
 
@@ -1979,5 +2008,6 @@
         bd->error = req->error;
       bd->state = RTEMS_BDBUF_STATE_READ_AHEAD;
-      bd->group->users--;
+
+      rtems_bdbuf_group_release (bd);
 
       if (rtems_bdbuf_tracer)
@@ -2009,29 +2039,12 @@
     bd = req->bufs[0].user;
 
-    /*
-     * One less user for the BD we return. The loop above is only for the read
-     * head buffers. We do this here then increment again so the case of the
-     * buffer in the cache or modified and no read leaves the user counts at
-     * the correct level.
-     */
-    bd->group->users--;
-
     if (rtems_bdbuf_tracer)
       rtems_bdbuf_show_users ("read-done", bd);
   }
 
-  /*
-   * The data for this block is cached in the buffer.
-   */
-  if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
+  if (bd->state != RTEMS_BDBUF_STATE_MODIFIED)
+    bd->state = RTEMS_BDBUF_STATE_ACCESS;
+  else
     bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED;
-  else
-  {
-    /*
-     * The file system is a user of the buffer.
-     */
-    bd->group->users++;
-    bd->state = RTEMS_BDBUF_STATE_ACCESS;
-  }
 
   if (rtems_bdbuf_tracer)
@@ -2072,8 +2085,5 @@
     rtems_chain_append (&bdbuf_cache.lru, &bd->link);
 
-    /*
-     * One less user for the group of bds.
-     */
-    bd->group->users--;
+    rtems_bdbuf_group_release (bd);
   }
   
@@ -2412,8 +2422,5 @@
               bd->error = 0;
 
-              /*
-               * The buffer is now not modified so lower the user count for the group.
-               */
-              bd->group->users--;
+              rtems_bdbuf_group_release (bd);
 
               if (rtems_bdbuf_tracer)
