* Add the buffer to the sorted clean or dirty block list. * * NOTE: xflags is passed as a constant, optimizing this inline function! */
| 2375 | * NOTE: xflags is passed as a constant, optimizing this inline function! |
| 2376 | */ |
| 2377 | static void |
| 2378 | buf_vlist_add(struct buf *bp, struct bufobj *bo, b_xflags_t xflags) |
| 2379 | { |
| 2380 | struct bufv *bv; |
| 2381 | struct buf *n; |
| 2382 | int error; |
| 2383 | |
| 2384 | ASSERT_BO_WLOCKED(bo); |
| 2385 | KASSERT((bo->bo_flag & BO_NOBUFS) == 0, |
| 2386 | ("buf_vlist_add: bo %p does not allow bufs", bo)); |
| 2387 | KASSERT((xflags & BX_VNDIRTY) == 0 || (bo->bo_flag & BO_DEAD) == 0, |
| 2388 | ("dead bo %p", bo)); |
| 2389 | KASSERT((bp->b_xflags & (BX_VNDIRTY|BX_VNCLEAN)) == 0, |
| 2390 | ("buf_vlist_add: Buf %p has existing xflags %d", bp, bp->b_xflags)); |
| 2391 | bp->b_xflags |= xflags; |
| 2392 | if (xflags & BX_VNDIRTY) |
| 2393 | bv = &bo->bo_dirty; |
| 2394 | else |
| 2395 | bv = &bo->bo_clean; |
| 2396 | |
| 2397 | /* |
| 2398 | * Keep the list ordered. Optimize empty list insertion. Assume |
| 2399 | * we tend to grow at the tail so lookup_le should usually be cheaper |
| 2400 | * than _ge. |
| 2401 | */ |
| 2402 | if (bv->bv_cnt == 0 || |
| 2403 | bp->b_lblkno > TAILQ_LAST(&bv->bv_hd, buflists)->b_lblkno) |
| 2404 | TAILQ_INSERT_TAIL(&bv->bv_hd, bp, b_bobufs); |
| 2405 | else if ((n = BUF_PCTRIE_LOOKUP_LE(&bv->bv_root, bp->b_lblkno)) == NULL) |
| 2406 | TAILQ_INSERT_HEAD(&bv->bv_hd, bp, b_bobufs); |
| 2407 | else |
| 2408 | TAILQ_INSERT_AFTER(&bv->bv_hd, n, bp, b_bobufs); |
| 2409 | error = BUF_PCTRIE_INSERT(&bv->bv_root, bp); |
| 2410 | if (error) |
| 2411 | panic("buf_vlist_add: Preallocated nodes insufficient."); |
| 2412 | bv->bv_cnt++; |
| 2413 | } |
| 2414 | |
| 2415 | /* |
| 2416 | * Look up a buffer using the buffer tries. |
no test coverage detected