| 3471 | "Number of buffers flushed with dependecies that require rollbacks"); |
| 3472 | |
| 3473 | static int |
| 3474 | flushbufqueues(struct vnode *lvp, struct bufdomain *bd, int target, |
| 3475 | int flushdeps) |
| 3476 | { |
| 3477 | struct bufqueue *bq; |
| 3478 | struct buf *sentinel; |
| 3479 | struct vnode *vp; |
| 3480 | struct mount *mp; |
| 3481 | struct buf *bp; |
| 3482 | int hasdeps; |
| 3483 | int flushed; |
| 3484 | int error; |
| 3485 | bool unlock; |
| 3486 | |
| 3487 | flushed = 0; |
| 3488 | bq = &bd->bd_dirtyq; |
| 3489 | bp = NULL; |
| 3490 | sentinel = malloc(sizeof(struct buf), M_TEMP, M_WAITOK | M_ZERO); |
| 3491 | sentinel->b_qindex = QUEUE_SENTINEL; |
| 3492 | BQ_LOCK(bq); |
| 3493 | TAILQ_INSERT_HEAD(&bq->bq_queue, sentinel, b_freelist); |
| 3494 | BQ_UNLOCK(bq); |
| 3495 | while (flushed != target) { |
| 3496 | maybe_yield(); |
| 3497 | BQ_LOCK(bq); |
| 3498 | bp = TAILQ_NEXT(sentinel, b_freelist); |
| 3499 | if (bp != NULL) { |
| 3500 | TAILQ_REMOVE(&bq->bq_queue, sentinel, b_freelist); |
| 3501 | TAILQ_INSERT_AFTER(&bq->bq_queue, bp, sentinel, |
| 3502 | b_freelist); |
| 3503 | } else { |
| 3504 | BQ_UNLOCK(bq); |
| 3505 | break; |
| 3506 | } |
| 3507 | /* |
| 3508 | * Skip sentinels inserted by other invocations of the |
| 3509 | * flushbufqueues(), taking care to not reorder them. |
| 3510 | * |
| 3511 | * Only flush the buffers that belong to the |
| 3512 | * vnode locked by the curthread. |
| 3513 | */ |
| 3514 | if (bp->b_qindex == QUEUE_SENTINEL || (lvp != NULL && |
| 3515 | bp->b_vp != lvp)) { |
| 3516 | BQ_UNLOCK(bq); |
| 3517 | continue; |
| 3518 | } |
| 3519 | error = BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL); |
| 3520 | BQ_UNLOCK(bq); |
| 3521 | if (error != 0) |
| 3522 | continue; |
| 3523 | |
| 3524 | /* |
| 3525 | * BKGRDINPROG can only be set with the buf and bufobj |
| 3526 | * locks both held. We tolerate a race to clear it here. |
| 3527 | */ |
| 3528 | if ((bp->b_vflags & BV_BKGRDINPROG) != 0 || |
| 3529 | (bp->b_flags & B_DELWRI) == 0) { |
| 3530 | BUF_UNLOCK(bp); |
no test coverage detected