git: e7cf562a40fc - main - cache: change ->v_cache_dd synchronisation rules
Mateusz Guzik
mjg at FreeBSD.org
Mon Jan 25 22:42:49 UTC 2021
The branch main has been updated by mjg:
URL: https://cgit.FreeBSD.org/src/commit/?id=e7cf562a40fc093df054bd7fa6f34746069a984a
commit e7cf562a40fc093df054bd7fa6f34746069a984a
Author: Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-01-25 20:49:09 +0000
Commit: Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-01-25 22:41:13 +0000
cache: change ->v_cache_dd synchronisation rules
Instead of resorting to seqc modification take advantage of immutability
of entries and check if the entry still matches after everything got
prepared.
---
sys/kern/vfs_cache.c | 46 ++++++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index fad7ce91ef44..a73e4843b5f3 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -1440,9 +1440,7 @@ cache_zap_locked(struct namecache *ncp)
SDT_PROBE3(vfs, namecache, zap, done, dvp, ncp->nc_name, vp);
TAILQ_REMOVE(&vp->v_cache_dst, ncp, nc_dst);
if (ncp == vp->v_cache_dd) {
- vn_seqc_write_begin_unheld(vp);
atomic_store_ptr(&vp->v_cache_dd, NULL);
- vn_seqc_write_end(vp);
}
} else {
SDT_PROBE2(vfs, namecache, zap_negative, done, dvp, ncp->nc_name);
@@ -1450,9 +1448,7 @@ cache_zap_locked(struct namecache *ncp)
}
if (ncp->nc_flag & NCF_ISDOTDOT) {
if (ncp == dvp->v_cache_dd) {
- vn_seqc_write_begin_unheld(dvp);
atomic_store_ptr(&dvp->v_cache_dd, NULL);
- vn_seqc_write_end(dvp);
}
} else {
LIST_REMOVE(ncp, nc_src);
@@ -1627,9 +1623,7 @@ retry_dotdot:
mtx_unlock(dvlp2);
cache_free(ncp);
} else {
- vn_seqc_write_begin(dvp);
atomic_store_ptr(&dvp->v_cache_dd, NULL);
- vn_seqc_write_end(dvp);
mtx_unlock(dvlp);
if (dvlp2 != NULL)
mtx_unlock(dvlp2);
@@ -2246,7 +2240,6 @@ cache_enter_dotdot_prep(struct vnode *dvp, struct vnode *vp,
cache_celockstate_init(&cel);
hash = cache_get_hash(cnp->cn_nameptr, len, dvp);
cache_enter_lock_dd(&cel, dvp, vp, hash);
- vn_seqc_write_begin(dvp);
ncp = dvp->v_cache_dd;
if (ncp != NULL && (ncp->nc_flag & NCF_ISDOTDOT)) {
KASSERT(ncp->nc_dvp == dvp, ("wrong isdotdot parent"));
@@ -2255,7 +2248,6 @@ cache_enter_dotdot_prep(struct vnode *dvp, struct vnode *vp,
ncp = NULL;
}
atomic_store_ptr(&dvp->v_cache_dd, NULL);
- vn_seqc_write_end(dvp);
cache_enter_unlock(&cel);
if (ncp != NULL)
cache_free(ncp);
@@ -2392,9 +2384,8 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
goto out_unlock_free;
KASSERT(vp == NULL || vp->v_type == VDIR,
("wrong vnode type %p", vp));
- vn_seqc_write_begin(dvp);
+ atomic_thread_fence_rel();
atomic_store_ptr(&dvp->v_cache_dd, ncp);
- vn_seqc_write_end(dvp);
}
if (vp != NULL) {
@@ -2404,20 +2395,17 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
* directory name in it and the name ".." for the
* directory's parent.
*/
- vn_seqc_write_begin(vp);
if ((ndd = vp->v_cache_dd) != NULL) {
if ((ndd->nc_flag & NCF_ISDOTDOT) != 0)
cache_zap_locked(ndd);
else
ndd = NULL;
}
+ atomic_thread_fence_rel();
atomic_store_ptr(&vp->v_cache_dd, ncp);
- vn_seqc_write_end(vp);
} else if (vp->v_type != VDIR) {
if (vp->v_cache_dd != NULL) {
- vn_seqc_write_begin(vp);
atomic_store_ptr(&vp->v_cache_dd, NULL);
- vn_seqc_write_end(vp);
}
}
}
@@ -3301,10 +3289,6 @@ vn_fullpath_any_smr(struct vnode *vp, struct vnode *rdir, char *buf,
cache_rev_failed(&reason);
goto out_abort;
}
- if (!cache_ncp_canuse(ncp)) {
- cache_rev_failed(&reason);
- goto out_abort;
- }
if (ncp->nc_nlen >= *buflen) {
cache_rev_failed(&reason);
error = ENOMEM;
@@ -3324,6 +3308,17 @@ vn_fullpath_any_smr(struct vnode *vp, struct vnode *rdir, char *buf,
cache_rev_failed(&reason);
goto out_abort;
}
+ /*
+ * Acquire fence provided by vn_seqc_read_any above.
+ */
+ if (__predict_false(atomic_load_ptr(&vp->v_cache_dd) != ncp)) {
+ cache_rev_failed(&reason);
+ goto out_abort;
+ }
+ if (!cache_ncp_canuse(ncp)) {
+ cache_rev_failed(&reason);
+ goto out_abort;
+ }
vp = tvp;
vp_seqc = tvp_seqc;
if (vp == rdir || vp == rootvnode)
@@ -4719,15 +4714,22 @@ cache_fplookup_dotdot(struct cache_fpl *fpl)
fpl->tvp = ncp->nc_dvp;
}
- if (!cache_ncp_canuse(ncp)) {
- return (cache_fpl_aborted(fpl));
- }
-
fpl->tvp_seqc = vn_seqc_read_any(fpl->tvp);
if (seqc_in_modify(fpl->tvp_seqc)) {
return (cache_fpl_partial(fpl));
}
+ /*
+ * Acquire fence provided by vn_seqc_read_any above.
+ */
+ if (__predict_false(atomic_load_ptr(&dvp->v_cache_dd) != ncp)) {
+ return (cache_fpl_aborted(fpl));
+ }
+
+ if (!cache_ncp_canuse(ncp)) {
+ return (cache_fpl_aborted(fpl));
+ }
+
counter_u64_add(dotdothits, 1);
return (0);
}
More information about the dev-commits-src-all
mailing list