* Lookup a name in the name cache * * # Arguments * * - dvp: Parent directory in which to search. * - vpp: Return argument. Will contain desired vnode on cache hit. * - cnp: Parameters of the name search. The most interesting bits of * the cn_flags field have the following meanings: * - MAKEENTRY: If clear, free an entry from the cache rather than look * it up. * - ISDOT
| 1846 | * lock is not recursively acquired. |
| 1847 | */ |
| 1848 | static int __noinline |
| 1849 | cache_lookup_fallback(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, |
| 1850 | struct timespec *tsp, int *ticksp) |
| 1851 | { |
| 1852 | struct namecache *ncp; |
| 1853 | struct mtx *blp; |
| 1854 | uint32_t hash; |
| 1855 | enum vgetstate vs; |
| 1856 | int error; |
| 1857 | bool whiteout; |
| 1858 | |
| 1859 | MPASS((cnp->cn_flags & ISDOTDOT) == 0); |
| 1860 | MPASS((cnp->cn_flags & (MAKEENTRY | NC_KEEPPOSENTRY)) != 0); |
| 1861 | |
| 1862 | retry: |
| 1863 | hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp); |
| 1864 | blp = HASH2BUCKETLOCK(hash); |
| 1865 | mtx_lock(blp); |
| 1866 | |
| 1867 | CK_SLIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { |
| 1868 | if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && |
| 1869 | !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) |
| 1870 | break; |
| 1871 | } |
| 1872 | |
| 1873 | if (__predict_false(ncp == NULL)) { |
| 1874 | mtx_unlock(blp); |
| 1875 | SDT_PROBE3(vfs, namecache, lookup, miss, dvp, cnp->cn_nameptr, |
| 1876 | NULL); |
| 1877 | counter_u64_add(nummiss, 1); |
| 1878 | return (0); |
| 1879 | } |
| 1880 | |
| 1881 | if (ncp->nc_flag & NCF_NEGATIVE) |
| 1882 | goto negative_success; |
| 1883 | |
| 1884 | counter_u64_add(numposhits, 1); |
| 1885 | *vpp = ncp->nc_vp; |
| 1886 | SDT_PROBE3(vfs, namecache, lookup, hit, dvp, ncp->nc_name, *vpp); |
| 1887 | cache_out_ts(ncp, tsp, ticksp); |
| 1888 | MPASS(dvp != *vpp); |
| 1889 | vs = vget_prep(*vpp); |
| 1890 | mtx_unlock(blp); |
| 1891 | error = vget_finish(*vpp, cnp->cn_lkflags, vs); |
| 1892 | if (error) { |
| 1893 | *vpp = NULL; |
| 1894 | goto retry; |
| 1895 | } |
| 1896 | return (-1); |
| 1897 | negative_success: |
| 1898 | /* |
| 1899 | * We don't get here with regular lookup apart from corner cases. |
| 1900 | */ |
| 1901 | if (__predict_true(cnp->cn_nameiop == CREATE)) { |
| 1902 | if (cnp->cn_flags & ISLASTCN) { |
| 1903 | counter_u64_add(numnegzaps, 1); |
| 1904 | error = cache_zap_locked_bucket(ncp, cnp, hash, blp); |
| 1905 | if (__predict_false(error != 0)) { |
no test coverage detected