diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 213399551097..d363d0db816d 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -3762,11 +3762,11 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep, ndp->ni_dvp != ndp->ni_vp && (newvp->v_type != VDIR || dctime.tv_sec != 0)) { - cache_enter_time(ndp->ni_dvp, + cache_enter_time_flags(ndp->ni_dvp, ndp->ni_vp, cnp, &nfsva.na_ctime, newvp->v_type != VDIR ? NULL : - &dctime); + &dctime, VFS_CE_DROPOLD); } if (unlocknewvp) vput(newvp); diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 5b978511db17..40c5f4f198d0 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -2582,6 +2582,23 @@ cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp, return; } +/* + * A variant of the above accepting flags. + * + * - VFS_CE_DROPOLD -- if a conflicting entry is found, drop it. + */ +void +cache_enter_time_flags(struct vnode *dvp, struct vnode *vp, struct componentname *cnp, + struct timespec *tsp, struct timespec *dtsp, int flags) +{ + + MPASS((flags & ~(VFS_CE_DROPOLD)) == 0); + + if (flags & VFS_CE_DROPOLD) + cache_remove_cnp(dvp, cnp); + cache_enter_time(dvp, vp, cnp, tsp, dtsp); +} + static u_int cache_roundup_2(u_int val) { diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index ed5867b80754..710311c78ece 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -641,6 +641,12 @@ int bnoreuselist(struct bufv *bufv, struct bufobj *bo, daddr_t startn, daddr_t endn); /* cache_* may belong in namei.h. */ void cache_changesize(u_long newhashsize); + +#define VFS_CE_DROPOLD 0x1 + +void cache_enter_time_flags(struct vnode *dvp, struct vnode *vp, + struct componentname *cnp, struct timespec *tsp, + struct timespec *dtsp, int flags); #define cache_enter(dvp, vp, cnp) \ cache_enter_time(dvp, vp, cnp, NULL, NULL) void cache_enter_time(struct vnode *dvp, struct vnode *vp,