| 3699 | #endif |
| 3700 | |
| 3701 | int |
| 3702 | vflush(struct mount *mp, int rootrefs, int flags, struct thread *td) |
| 3703 | { |
| 3704 | struct vnode *vp, *mvp, *rootvp = NULL; |
| 3705 | struct vattr vattr; |
| 3706 | int busy = 0, error; |
| 3707 | |
| 3708 | CTR4(KTR_VFS, "%s: mp %p with rootrefs %d and flags %d", __func__, mp, |
| 3709 | rootrefs, flags); |
| 3710 | if (rootrefs > 0) { |
| 3711 | KASSERT((flags & (SKIPSYSTEM | WRITECLOSE)) == 0, |
| 3712 | ("vflush: bad args")); |
| 3713 | /* |
| 3714 | * Get the filesystem root vnode. We can vput() it |
| 3715 | * immediately, since with rootrefs > 0, it won't go away. |
| 3716 | */ |
| 3717 | if ((error = VFS_ROOT(mp, LK_EXCLUSIVE, &rootvp)) != 0) { |
| 3718 | CTR2(KTR_VFS, "%s: vfs_root lookup failed with %d", |
| 3719 | __func__, error); |
| 3720 | return (error); |
| 3721 | } |
| 3722 | vput(rootvp); |
| 3723 | } |
| 3724 | loop: |
| 3725 | MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { |
| 3726 | vholdl(vp); |
| 3727 | error = vn_lock(vp, LK_INTERLOCK | LK_EXCLUSIVE); |
| 3728 | if (error) { |
| 3729 | vdrop(vp); |
| 3730 | MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); |
| 3731 | goto loop; |
| 3732 | } |
| 3733 | /* |
| 3734 | * Skip over a vnodes marked VV_SYSTEM. |
| 3735 | */ |
| 3736 | if ((flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM)) { |
| 3737 | VOP_UNLOCK(vp); |
| 3738 | vdrop(vp); |
| 3739 | continue; |
| 3740 | } |
| 3741 | /* |
| 3742 | * If WRITECLOSE is set, flush out unlinked but still open |
| 3743 | * files (even if open only for reading) and regular file |
| 3744 | * vnodes open for writing. |
| 3745 | */ |
| 3746 | if (flags & WRITECLOSE) { |
| 3747 | if (vp->v_object != NULL) { |
| 3748 | VM_OBJECT_WLOCK(vp->v_object); |
| 3749 | vm_object_page_clean(vp->v_object, 0, 0, 0); |
| 3750 | VM_OBJECT_WUNLOCK(vp->v_object); |
| 3751 | } |
| 3752 | do { |
| 3753 | error = VOP_FSYNC(vp, MNT_WAIT, td); |
| 3754 | } while (error == ERELOOKUP); |
| 3755 | if (error != 0) { |
| 3756 | VOP_UNLOCK(vp); |
| 3757 | vdrop(vp); |
| 3758 | MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); |
no test coverage detected