cache: fix a race between entry removal and demotion
The negative list shrinker can demote an entry with only hotlist + neglist locks held. On the other hand entry removal possibly sets the NCF_DVDROP without aformentioned locks held prior to detaching it from the respective netlist., which can lose the update made by the shrinker. Reported and tested by: truckman
This commit is contained in:
parent
cf8bc16b1e
commit
87bcad2bfb
@ -868,6 +868,13 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked)
|
||||
nc_get_name(ncp), ncp->nc_neghits);
|
||||
}
|
||||
LIST_REMOVE(ncp, nc_hash);
|
||||
if (!(ncp->nc_flag & NCF_NEGATIVE)) {
|
||||
TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
|
||||
if (ncp == ncp->nc_vp->v_cache_dd)
|
||||
ncp->nc_vp->v_cache_dd = NULL;
|
||||
} else {
|
||||
cache_negative_remove(ncp, neg_locked);
|
||||
}
|
||||
if (ncp->nc_flag & NCF_ISDOTDOT) {
|
||||
if (ncp == ncp->nc_dvp->v_cache_dd)
|
||||
ncp->nc_dvp->v_cache_dd = NULL;
|
||||
@ -878,13 +885,6 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked)
|
||||
atomic_subtract_rel_long(&numcachehv, 1);
|
||||
}
|
||||
}
|
||||
if (!(ncp->nc_flag & NCF_NEGATIVE)) {
|
||||
TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
|
||||
if (ncp == ncp->nc_vp->v_cache_dd)
|
||||
ncp->nc_vp->v_cache_dd = NULL;
|
||||
} else {
|
||||
cache_negative_remove(ncp, neg_locked);
|
||||
}
|
||||
atomic_subtract_rel_long(&numcache, 1);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user