* buf_recycle: * * Free a buffer from the given bufqueue. kva controls whether the * freed buf must own some kva resources. This is used for * defragmenting. */
| 1720 | * defragmenting. |
| 1721 | */ |
| 1722 | static int |
| 1723 | buf_recycle(struct bufdomain *bd, bool kva) |
| 1724 | { |
| 1725 | struct bufqueue *bq; |
| 1726 | struct buf *bp, *nbp; |
| 1727 | |
| 1728 | if (kva) |
| 1729 | counter_u64_add(bufdefragcnt, 1); |
| 1730 | nbp = NULL; |
| 1731 | bq = bd->bd_cleanq; |
| 1732 | BQ_LOCK(bq); |
| 1733 | KASSERT(BQ_LOCKPTR(bq) == BD_LOCKPTR(bd), |
| 1734 | ("buf_recycle: Locks don't match")); |
| 1735 | nbp = TAILQ_FIRST(&bq->bq_queue); |
| 1736 | |
| 1737 | /* |
| 1738 | * Run scan, possibly freeing data and/or kva mappings on the fly |
| 1739 | * depending. |
| 1740 | */ |
| 1741 | while ((bp = nbp) != NULL) { |
| 1742 | /* |
| 1743 | * Calculate next bp (we can only use it if we do not |
| 1744 | * release the bqlock). |
| 1745 | */ |
| 1746 | nbp = TAILQ_NEXT(bp, b_freelist); |
| 1747 | |
| 1748 | /* |
| 1749 | * If we are defragging then we need a buffer with |
| 1750 | * some kva to reclaim. |
| 1751 | */ |
| 1752 | if (kva && bp->b_kvasize == 0) |
| 1753 | continue; |
| 1754 | |
| 1755 | if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) != 0) |
| 1756 | continue; |
| 1757 | |
| 1758 | /* |
| 1759 | * Implement a second chance algorithm for frequently |
| 1760 | * accessed buffers. |
| 1761 | */ |
| 1762 | if ((bp->b_flags & B_REUSE) != 0) { |
| 1763 | TAILQ_REMOVE(&bq->bq_queue, bp, b_freelist); |
| 1764 | TAILQ_INSERT_TAIL(&bq->bq_queue, bp, b_freelist); |
| 1765 | bp->b_flags &= ~B_REUSE; |
| 1766 | BUF_UNLOCK(bp); |
| 1767 | continue; |
| 1768 | } |
| 1769 | |
| 1770 | /* |
| 1771 | * Skip buffers with background writes in progress. |
| 1772 | */ |
| 1773 | if ((bp->b_vflags & BV_BKGRDINPROG) != 0) { |
| 1774 | BUF_UNLOCK(bp); |
| 1775 | continue; |
| 1776 | } |
| 1777 | |
| 1778 | KASSERT(bp->b_qindex == QUEUE_CLEAN, |
| 1779 | ("buf_recycle: inconsistent queue %d bp %p", |
no test coverage detected