Index: cpukit/libblock/src/bdbuf.c
===================================================================
--- cpukit/libblock/src/bdbuf.c	(revision 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb)
+++ cpukit/libblock/src/bdbuf.c	(revision 945884fe9fc662bcce68f5ed61127c3e6ddef467)
@@ -135,20 +135,28 @@
   (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF))
 
-#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY  RTEMS_BLKDEV_FATAL_ERROR(1)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT      RTEMS_BLKDEV_FATAL_ERROR(2)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK    RTEMS_BLKDEV_FATAL_ERROR(3)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK  RTEMS_BLKDEV_FATAL_ERROR(4)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_LOCK   RTEMS_BLKDEV_FATAL_ERROR(5)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(6)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1 RTEMS_BLKDEV_FATAL_ERROR(7)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2 RTEMS_BLKDEV_FATAL_ERROR(8)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3 RTEMS_BLKDEV_FATAL_ERROR(9)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE   RTEMS_BLKDEV_FATAL_ERROR(10)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE      RTEMS_BLKDEV_FATAL_ERROR(11)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM     RTEMS_BLKDEV_FATAL_ERROR(12)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE RTEMS_BLKDEV_FATAL_ERROR(13)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START  RTEMS_BLKDEV_FATAL_ERROR(14)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE         RTEMS_BLKDEV_FATAL_ERROR(15)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS         RTEMS_BLKDEV_FATAL_ERROR(16)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_1 RTEMS_BLKDEV_FATAL_ERROR(1)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2 RTEMS_BLKDEV_FATAL_ERROR(2)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_3 RTEMS_BLKDEV_FATAL_ERROR(3)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_4 RTEMS_BLKDEV_FATAL_ERROR(4)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_5 RTEMS_BLKDEV_FATAL_ERROR(5)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_6 RTEMS_BLKDEV_FATAL_ERROR(6)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_7 RTEMS_BLKDEV_FATAL_ERROR(7)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_8 RTEMS_BLKDEV_FATAL_ERROR(8)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_9 RTEMS_BLKDEV_FATAL_ERROR(9)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT       RTEMS_BLKDEV_FATAL_ERROR(10)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK     RTEMS_BLKDEV_FATAL_ERROR(11)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK   RTEMS_BLKDEV_FATAL_ERROR(12)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_LOCK    RTEMS_BLKDEV_FATAL_ERROR(13)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_UNLOCK  RTEMS_BLKDEV_FATAL_ERROR(14)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1  RTEMS_BLKDEV_FATAL_ERROR(15)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2  RTEMS_BLKDEV_FATAL_ERROR(16)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3  RTEMS_BLKDEV_FATAL_ERROR(17)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE    RTEMS_BLKDEV_FATAL_ERROR(18)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE       RTEMS_BLKDEV_FATAL_ERROR(19)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM      RTEMS_BLKDEV_FATAL_ERROR(20)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE  RTEMS_BLKDEV_FATAL_ERROR(21)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START   RTEMS_BLKDEV_FATAL_ERROR(22)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE          RTEMS_BLKDEV_FATAL_ERROR(23)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS          RTEMS_BLKDEV_FATAL_ERROR(24)
 
 /**
@@ -877,7 +885,6 @@
  * time.
  *
- * and you must
- * hold the sync lock. The sync lock is used to block writes while a sync is
- * active.
+ * @note Do not lower the group user count as the modified list is a user of
+ * the buffer.
  *
  * @param bd The bd to queue to the cache's modified list.
@@ -962,12 +969,21 @@
        b++, bd += bufs_per_bd)
   {
+    if ((bd->state == RTEMS_BDBUF_STATE_MODIFIED) ||
+        (bd->state == RTEMS_BDBUF_STATE_ACCESS) ||
+        (bd->state == RTEMS_BDBUF_STATE_ACCESS_MODIFIED) ||
+        (bd->state == RTEMS_BDBUF_STATE_SYNC) ||
+        (bd->state == RTEMS_BDBUF_STATE_TRANSFER))
+      rtems_fatal_error_occurred ((bd->state << 16) |
+                                  RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_8);
+    
     if ((bd->state == RTEMS_BDBUF_STATE_CACHED) ||
-        (bd->state == RTEMS_BDBUF_STATE_MODIFIED) ||
         (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD))
     {
       if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
-        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
-      rtems_chain_extract (&bd->link);
-    }
+        rtems_fatal_error_occurred ((bd->state << 16) |
+                                    RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_1);
+    }
+    
+    rtems_chain_extract (&bd->link);
   }
   
@@ -978,5 +994,8 @@
        b < group->bds_per_group;
        b++, bd += bufs_per_bd)
+  {
+    bd->state = RTEMS_BDBUF_STATE_EMPTY;
     rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
+  }
 }
 
@@ -1005,5 +1024,4 @@
     {
       rtems_chain_extract (node);
-      bd->group->users++;
       return bd;
     }
@@ -1430,5 +1448,5 @@
            */
           if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
-            rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+            rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2);
         }
         else
@@ -1472,10 +1490,10 @@
         if ((bd->state != RTEMS_BDBUF_STATE_EMPTY) &&
             (bd->state != RTEMS_BDBUF_STATE_READ_AHEAD))
-          rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+          rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_3);
 
         if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
         {
           if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
-            rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+            rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_4);
         }
       }
@@ -1492,5 +1510,5 @@
 
         if (rtems_bdbuf_avl_insert (&bdbuf_cache.tree, bd) != 0)
-          rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+          rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_5);
 
         return bd;
@@ -1553,5 +1571,5 @@
 
       default:
-        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_6);
     }
   }
@@ -1611,4 +1629,9 @@
     bd->state = RTEMS_BDBUF_STATE_ACCESS;
 
+  /*
+   * Indicate a buffer in this group is being used.
+   */
+  bd->group->users++;
+  
   rtems_bdbuf_unlock_cache ();
 
@@ -1735,4 +1758,9 @@
     bd->error = 0;
 
+    /*
+     * The buffer will be passed to the driver so this buffer has a user.
+     */
+    bd->group->users++;
+    
     /*
      * @todo The use of these req blocks is not a great design. The req is a
@@ -1817,8 +1845,36 @@
       bd->error = req->error;
       bd->state = RTEMS_BDBUF_STATE_READ_AHEAD;
-      rtems_bdbuf_release (bd);
+      bd->group->users--;
+      rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
+
+      /*
+       * If there is an error remove the BD from the AVL tree as it does is
+       * invalid, then wake any threads that may be waiting. A thread may have
+       * been waiting for this block and assumed it was in the tree.
+       */
+      if (bd->error)
+      {
+        bd->state = RTEMS_BDBUF_STATE_EMPTY;
+        if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
+          rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_9);
+      }
+
+      if (bd->waiters)
+        rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters);
+      else
+      {
+        if (rtems_chain_has_only_one_node (&bdbuf_cache.ready))
+          rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
+      }
     }
 
     bd = req->bufs[0].user;
+
+    /*
+     * One less user. We do this here then increment again so the case of the
+     * buffer in the the cache and no read leaves the user counts at the
+     * correct level.
+     */
+    bd->group->users--;
   }
 
@@ -1829,5 +1885,11 @@
     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;
+  }
 
   rtems_bdbuf_unlock_cache ();
@@ -1970,10 +2032,11 @@
       case RTEMS_BDBUF_STATE_TRANSFER:
         bd->waiters++;
-        rtems_bdbuf_wait (&bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
+        rtems_bdbuf_wait (&bdbuf_cache.transfer,
+                          &bdbuf_cache.transfer_waiters);
         bd->waiters--;
         break;
 
       default:
-        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY);
+        rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_7);
     }
   }
@@ -2212,4 +2275,8 @@
               bd->state = RTEMS_BDBUF_STATE_CACHED;
               bd->error = 0;
+
+              /*
+               * The buffer is now not modified so lower the user count for the group.
+               */
               bd->group->users--;
               
