| 1613 | } |
| 1614 | |
| 1615 | static __noinline int |
| 1616 | cache_remove_cnp(struct vnode *dvp, struct componentname *cnp) |
| 1617 | { |
| 1618 | struct namecache *ncp; |
| 1619 | struct mtx *blp; |
| 1620 | struct mtx *dvlp, *dvlp2; |
| 1621 | uint32_t hash; |
| 1622 | int error; |
| 1623 | |
| 1624 | if (cnp->cn_namelen == 2 && |
| 1625 | cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.') { |
| 1626 | dvlp = VP2VNODELOCK(dvp); |
| 1627 | dvlp2 = NULL; |
| 1628 | mtx_lock(dvlp); |
| 1629 | retry_dotdot: |
| 1630 | ncp = dvp->v_cache_dd; |
| 1631 | if (ncp == NULL) { |
| 1632 | mtx_unlock(dvlp); |
| 1633 | if (dvlp2 != NULL) |
| 1634 | mtx_unlock(dvlp2); |
| 1635 | SDT_PROBE2(vfs, namecache, removecnp, miss, dvp, cnp); |
| 1636 | return (0); |
| 1637 | } |
| 1638 | if ((ncp->nc_flag & NCF_ISDOTDOT) != 0) { |
| 1639 | if (!cache_zap_locked_vnode_kl2(ncp, dvp, &dvlp2)) |
| 1640 | goto retry_dotdot; |
| 1641 | MPASS(dvp->v_cache_dd == NULL); |
| 1642 | mtx_unlock(dvlp); |
| 1643 | if (dvlp2 != NULL) |
| 1644 | mtx_unlock(dvlp2); |
| 1645 | cache_free(ncp); |
| 1646 | } else { |
| 1647 | atomic_store_ptr(&dvp->v_cache_dd, NULL); |
| 1648 | mtx_unlock(dvlp); |
| 1649 | if (dvlp2 != NULL) |
| 1650 | mtx_unlock(dvlp2); |
| 1651 | } |
| 1652 | SDT_PROBE2(vfs, namecache, removecnp, hit, dvp, cnp); |
| 1653 | return (1); |
| 1654 | } |
| 1655 | |
| 1656 | hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp); |
| 1657 | blp = HASH2BUCKETLOCK(hash); |
| 1658 | retry: |
| 1659 | if (CK_SLIST_EMPTY(NCHHASH(hash))) |
| 1660 | goto out_no_entry; |
| 1661 | |
| 1662 | mtx_lock(blp); |
| 1663 | |
| 1664 | CK_SLIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { |
| 1665 | if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && |
| 1666 | !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) |
| 1667 | break; |
| 1668 | } |
| 1669 | |
| 1670 | if (ncp == NULL) { |
| 1671 | mtx_unlock(blp); |
| 1672 | goto out_no_entry; |
no test coverage detected