+/*
+ * Definitions for the buffer hash lists.
+ */
+#define BUFHASH(dvp, lbn) \
+ (&bufhashtbl[((int)(dvp) / sizeof(*(dvp)) + (int)(lbn)) & bufhash])
+LIST_HEAD(bufhashhdr, buf) *bufhashtbl, invalhash;
+u_long bufhash;
+
+/*
+ * Insq/Remq for the buffer hash lists.
+ */
+#define binshash(bp, dp) LIST_INSERT_HEAD(dp, bp, b_hash)
+#define bremhash(bp) LIST_REMOVE(bp, b_hash)
+
+/*
+ * Definitions for the buffer free lists.
+ */
+#define BQUEUES 4 /* number of free buffer queues */
+
+#define BQ_LOCKED 0 /* super-blocks &c */
+#define BQ_LRU 1 /* lru, useful buffers */
+#define BQ_AGE 2 /* rubbish */
+#define BQ_EMPTY 3 /* buffer headers with no memory */
+
+TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES];
+int needbuffer;
+
+/*
+ * Insq/Remq for the buffer free lists.
+ */
+#define binsheadfree(bp, dp) TAILQ_INSERT_HEAD(dp, bp, b_freelist)
+#define binstailfree(bp, dp) TAILQ_INSERT_TAIL(dp, bp, b_freelist)
+
+void
+bremfree(bp)
+ struct buf *bp;
+{
+ struct bqueues *dp = NULL;
+
+ /*
+ * We only calculate the head of the freelist when removing
+ * the last element of the list as that is the only time that
+ * it is needed (e.g. to reset the tail pointer).
+ *
+ * NB: This makes an assumption about how tailq's are implemented.
+ */
+ if (bp->b_freelist.tqe_next == NULL) {
+ for (dp = bufqueues; dp < &bufqueues[BQUEUES]; dp++)
+ if (dp->tqh_last == &bp->b_freelist.tqe_next)
+ break;
+ if (dp == &bufqueues[BQUEUES])
+ panic("bremfree: lost tail");
+ }
+ TAILQ_REMOVE(dp, bp, b_freelist);
+}
+