mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
vfs cache: plug a hypothetical corner case when freeing
cache_zap_unlocked_bucket is called with a bunch of addresses and without any locks held, forcing it to revalidate everything from scratch. It did not account for a case where the entry is reallocated with everything the same except for the target vnode. Should the target use a different lock than the one expected, freeing would proceed without being properly synchronized. Note this is almost impossible to happen in practice.
This commit is contained in:
parent
2749c222da
commit
0f15054f79
1 changed files with 18 additions and 7 deletions
|
|
@ -1720,6 +1720,7 @@ cache_zap_unlocked_bucket(struct namecache *ncp, struct componentname *cnp,
|
|||
struct mtx *blp)
|
||||
{
|
||||
struct namecache *rncp;
|
||||
struct mtx *rvlp;
|
||||
|
||||
cache_assert_bucket_unlocked(ncp);
|
||||
|
||||
|
|
@ -1732,14 +1733,24 @@ cache_zap_unlocked_bucket(struct namecache *ncp, struct componentname *cnp,
|
|||
!bcmp(rncp->nc_name, cnp->cn_nameptr, rncp->nc_nlen))
|
||||
break;
|
||||
}
|
||||
if (rncp != NULL) {
|
||||
cache_zap_locked(rncp);
|
||||
mtx_unlock(blp);
|
||||
cache_unlock_vnodes(dvlp, vlp);
|
||||
atomic_add_long(&zap_bucket_relock_success, 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (rncp == NULL)
|
||||
goto out_mismatch;
|
||||
|
||||
if (!(ncp->nc_flag & NCF_NEGATIVE))
|
||||
rvlp = VP2VNODELOCK(rncp->nc_vp);
|
||||
else
|
||||
rvlp = NULL;
|
||||
if (rvlp != vlp)
|
||||
goto out_mismatch;
|
||||
|
||||
cache_zap_locked(rncp);
|
||||
mtx_unlock(blp);
|
||||
cache_unlock_vnodes(dvlp, vlp);
|
||||
atomic_add_long(&zap_bucket_relock_success, 1);
|
||||
return (0);
|
||||
|
||||
out_mismatch:
|
||||
mtx_unlock(blp);
|
||||
cache_unlock_vnodes(dvlp, vlp);
|
||||
return (EAGAIN);
|
||||
|
|
|
|||
Loading…
Reference in a new issue