| 2705 | } |
| 2706 | |
| 2707 | int |
| 2708 | vn_fsync_buf(struct vnode *vp, int waitfor) |
| 2709 | { |
| 2710 | struct buf *bp, *nbp; |
| 2711 | struct bufobj *bo; |
| 2712 | struct mount *mp; |
| 2713 | int error, maxretry; |
| 2714 | |
| 2715 | error = 0; |
| 2716 | maxretry = 10000; /* large, arbitrarily chosen */ |
| 2717 | mp = NULL; |
| 2718 | if (vp->v_type == VCHR) { |
| 2719 | VI_LOCK(vp); |
| 2720 | mp = vp->v_rdev->si_mountpt; |
| 2721 | VI_UNLOCK(vp); |
| 2722 | } |
| 2723 | bo = &vp->v_bufobj; |
| 2724 | BO_LOCK(bo); |
| 2725 | loop1: |
| 2726 | /* |
| 2727 | * MARK/SCAN initialization to avoid infinite loops. |
| 2728 | */ |
| 2729 | TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) { |
| 2730 | bp->b_vflags &= ~BV_SCANNED; |
| 2731 | bp->b_error = 0; |
| 2732 | } |
| 2733 | |
| 2734 | /* |
| 2735 | * Flush all dirty buffers associated with a vnode. |
| 2736 | */ |
| 2737 | loop2: |
| 2738 | TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { |
| 2739 | if ((bp->b_vflags & BV_SCANNED) != 0) |
| 2740 | continue; |
| 2741 | bp->b_vflags |= BV_SCANNED; |
| 2742 | if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { |
| 2743 | if (waitfor != MNT_WAIT) |
| 2744 | continue; |
| 2745 | if (BUF_LOCK(bp, |
| 2746 | LK_EXCLUSIVE | LK_INTERLOCK | LK_SLEEPFAIL, |
| 2747 | BO_LOCKPTR(bo)) != 0) { |
| 2748 | BO_LOCK(bo); |
| 2749 | goto loop1; |
| 2750 | } |
| 2751 | BO_LOCK(bo); |
| 2752 | } |
| 2753 | BO_UNLOCK(bo); |
| 2754 | KASSERT(bp->b_bufobj == bo, |
| 2755 | ("bp %p wrong b_bufobj %p should be %p", |
| 2756 | bp, bp->b_bufobj, bo)); |
| 2757 | if ((bp->b_flags & B_DELWRI) == 0) |
| 2758 | panic("fsync: not dirty"); |
| 2759 | if ((vp->v_object != NULL) && (bp->b_flags & B_CLUSTEROK)) { |
| 2760 | vfs_bio_awrite(bp); |
| 2761 | } else { |
| 2762 | bremfree(bp); |
| 2763 | bawrite(bp); |
| 2764 | } |
no test coverage detected