* Do the actual filesystem unmount. */
| 1728 | * Do the actual filesystem unmount. |
| 1729 | */ |
| 1730 | int |
| 1731 | dounmount(struct mount *mp, int flags, struct thread *td) |
| 1732 | { |
| 1733 | struct vnode *coveredvp, *rootvp; |
| 1734 | int error; |
| 1735 | uint64_t async_flag; |
| 1736 | int mnt_gen_r; |
| 1737 | |
| 1738 | if ((coveredvp = mp->mnt_vnodecovered) != NULL) { |
| 1739 | mnt_gen_r = mp->mnt_gen; |
| 1740 | VI_LOCK(coveredvp); |
| 1741 | vholdl(coveredvp); |
| 1742 | vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY); |
| 1743 | /* |
| 1744 | * Check for mp being unmounted while waiting for the |
| 1745 | * covered vnode lock. |
| 1746 | */ |
| 1747 | if (coveredvp->v_mountedhere != mp || |
| 1748 | coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) { |
| 1749 | VOP_UNLOCK(coveredvp); |
| 1750 | vdrop(coveredvp); |
| 1751 | vfs_rel(mp); |
| 1752 | return (EBUSY); |
| 1753 | } |
| 1754 | } |
| 1755 | |
| 1756 | /* |
| 1757 | * Only privileged root, or (if MNT_USER is set) the user that did the |
| 1758 | * original mount is permitted to unmount this filesystem. |
| 1759 | */ |
| 1760 | error = vfs_suser(mp, td); |
| 1761 | if (error != 0) { |
| 1762 | if (coveredvp != NULL) { |
| 1763 | VOP_UNLOCK(coveredvp); |
| 1764 | vdrop(coveredvp); |
| 1765 | } |
| 1766 | vfs_rel(mp); |
| 1767 | return (error); |
| 1768 | } |
| 1769 | |
| 1770 | vfs_op_enter(mp); |
| 1771 | |
| 1772 | vn_start_write(NULL, &mp, V_WAIT | V_MNTREF); |
| 1773 | MNT_ILOCK(mp); |
| 1774 | if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 || |
| 1775 | (mp->mnt_flag & MNT_UPDATE) != 0 || |
| 1776 | !TAILQ_EMPTY(&mp->mnt_uppers)) { |
| 1777 | dounmount_cleanup(mp, coveredvp, 0); |
| 1778 | return (EBUSY); |
| 1779 | } |
| 1780 | mp->mnt_kern_flag |= MNTK_UNMOUNT; |
| 1781 | rootvp = vfs_cache_root_clear(mp); |
| 1782 | if (coveredvp != NULL) |
| 1783 | vn_seqc_write_begin(coveredvp); |
| 1784 | if (flags & MNT_NONBUSY) { |
| 1785 | MNT_IUNLOCK(mp); |
| 1786 | error = vfs_check_usecounts(mp); |
| 1787 | MNT_ILOCK(mp); |
no test coverage detected