svn commit: r363873 - head/sys/kern
Mateusz Guzik
mjg at FreeBSD.org
Tue Aug 4 23:07:01 UTC 2020
Author: mjg
Date: Tue Aug 4 23:07:00 2020
New Revision: 363873
URL: https://svnweb.freebsd.org/changeset/base/363873
Log:
cache: add NCF_WIP flag
This allows making half-constructed entries visible to the lockless lookup,
which now can check for either "not yet fully constructed" and "no longer valid"
state.
This will be used for .. lookup.
Modified:
head/sys/kern/vfs_cache.c
Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c Tue Aug 4 23:04:29 2020 (r363872)
+++ head/sys/kern/vfs_cache.c Tue Aug 4 23:07:00 2020 (r363873)
@@ -162,6 +162,7 @@ struct namecache_ts {
#define NCF_DVDROP 0x10
#define NCF_NEGATIVE 0x20
#define NCF_INVALID 0x40
+#define NCF_WIP 0x80
/*
* Flags in negstate.neg_flag
@@ -179,22 +180,22 @@ cache_ncp_invalidate(struct namecache *ncp)
KASSERT((ncp->nc_flag & NCF_INVALID) == 0,
("%s: entry %p already invalid", __func__, ncp));
- ncp->nc_flag |= NCF_INVALID;
+ atomic_store_char(&ncp->nc_flag, ncp->nc_flag | NCF_INVALID);
atomic_thread_fence_rel();
}
/*
- * Verify validity of an entry.
+ * Check whether the entry can be safely used.
*
* All places which elide locks are supposed to call this after they are
* done with reading from an entry.
*/
static bool
-cache_ncp_invalid(struct namecache *ncp)
+cache_ncp_canuse(struct namecache *ncp)
{
atomic_thread_fence_acq();
- return ((ncp->nc_flag & NCF_INVALID) != 0);
+ return ((atomic_load_char(&ncp->nc_flag) & (NCF_INVALID | NCF_WIP)) == 0);
}
/*
@@ -1506,7 +1507,7 @@ success:
VOP_UNLOCK(dvp);
}
if (doing_smr) {
- if (cache_ncp_invalid(ncp)) {
+ if (!cache_ncp_canuse(ncp)) {
vfs_smr_exit();
*vpp = NULL;
goto retry;
@@ -1560,7 +1561,7 @@ negative_success:
*/
negstate = NCP2NEGSTATE(ncp);
if ((negstate->neg_flag & NEG_HOT) == 0 ||
- cache_ncp_invalid(ncp)) {
+ !cache_ncp_canuse(ncp)) {
vfs_smr_exit();
doing_smr = false;
goto retry_hashed;
@@ -1884,7 +1885,7 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp,
* namecache entry as possible before acquiring the lock.
*/
ncp = cache_alloc(cnp->cn_namelen, tsp != NULL);
- ncp->nc_flag = flag;
+ ncp->nc_flag = flag | NCF_WIP;
ncp->nc_vp = vp;
if (vp == NULL)
cache_negative_init(ncp);
@@ -1987,13 +1988,19 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp,
ncp->nc_name);
}
- atomic_thread_fence_rel();
/*
* Insert the new namecache entry into the appropriate chain
* within the cache entries table.
*/
CK_LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
+ atomic_thread_fence_rel();
+ /*
+ * Mark the entry as fully constructed.
+ * It is immutable past this point until its removal.
+ */
+ atomic_store_char(&ncp->nc_flag, ncp->nc_flag & ~NCF_WIP);
+
cache_enter_unlock(&cel);
if (numneg * ncnegfactor > lnumcache)
cache_negative_zap_one();
@@ -3197,7 +3204,7 @@ cache_fplookup_negative_promote(struct cache_fpl *fpl,
goto out_abort;
}
- if (__predict_false(cache_ncp_invalid(ncp))) {
+ if (__predict_false(!cache_ncp_canuse(ncp))) {
goto out_abort;
}
@@ -3458,7 +3465,7 @@ cache_fplookup_next(struct cache_fpl *fpl)
if ((nc_flag & NCF_NEGATIVE) != 0) {
negstate = NCP2NEGSTATE(ncp);
neg_hot = ((negstate->neg_flag & NEG_HOT) != 0);
- if (__predict_false(cache_ncp_invalid(ncp))) {
+ if (__predict_false(!cache_ncp_canuse(ncp))) {
return (cache_fpl_partial(fpl));
}
if (__predict_false((nc_flag & NCF_WHITE) != 0)) {
@@ -3474,7 +3481,7 @@ cache_fplookup_next(struct cache_fpl *fpl)
return (cache_fpl_handled(fpl, ENOENT));
}
- if (__predict_false(cache_ncp_invalid(ncp))) {
+ if (__predict_false(!cache_ncp_canuse(ncp))) {
return (cache_fpl_partial(fpl));
}
More information about the svn-src-head
mailing list