| 1750 | }; |
| 1751 | #endif |
| 1752 | int |
| 1753 | sys_undelete(struct thread *td, struct undelete_args *uap) |
| 1754 | { |
| 1755 | struct mount *mp; |
| 1756 | struct nameidata nd; |
| 1757 | int error; |
| 1758 | |
| 1759 | restart: |
| 1760 | bwillwrite(); |
| 1761 | NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | AUDITVNODE1, |
| 1762 | UIO_USERSPACE, uap->path, td); |
| 1763 | error = namei(&nd); |
| 1764 | if (error != 0) |
| 1765 | return (error); |
| 1766 | |
| 1767 | if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { |
| 1768 | NDFREE(&nd, NDF_ONLY_PNBUF); |
| 1769 | if (nd.ni_vp == nd.ni_dvp) |
| 1770 | vrele(nd.ni_dvp); |
| 1771 | else |
| 1772 | vput(nd.ni_dvp); |
| 1773 | if (nd.ni_vp) |
| 1774 | vrele(nd.ni_vp); |
| 1775 | return (EEXIST); |
| 1776 | } |
| 1777 | if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { |
| 1778 | NDFREE(&nd, NDF_ONLY_PNBUF); |
| 1779 | vput(nd.ni_dvp); |
| 1780 | if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) |
| 1781 | return (error); |
| 1782 | goto restart; |
| 1783 | } |
| 1784 | error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); |
| 1785 | NDFREE(&nd, NDF_ONLY_PNBUF); |
| 1786 | vput(nd.ni_dvp); |
| 1787 | vn_finished_write(mp); |
| 1788 | if (error == ERELOOKUP) |
| 1789 | goto restart; |
| 1790 | return (error); |
| 1791 | } |
| 1792 | |
| 1793 | /* |
| 1794 | * Delete a name from the filesystem. |
nothing calls this directly
no test coverage detected