Post r230394, the Lookup RPC counts for both NFS clients increased
significantly. Upon investigation this was caused by name cache misses for lookups of "..". For name cache entries for non-".." directories, the cache entry serves double duty. It maps both the named directory plus ".." for the parent of the directory. As such, two ctime values (one for each of the directory and its parent) need to be saved in the name cache entry. This patch adds an entry for ctime of the parent directory to the name cache. It also adds an additional uma zone for large entries with this time value, in order to minimize memory wastage. As well, it fixes a couple of cases where the mtime of the parent directory was being saved instead of ctime for positive name cache entries. With this patch, Lookup RPC counts return to values similar to pre-r230394 kernels. Reported by: bde Discussed with: kib Reviewed by: jhb MFC after: 2 weeks
This commit is contained in:
parent
62953748f5
commit
5e99212d36
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232420
@ -2951,10 +2951,12 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
|||||||
nfsattrbit_t attrbits, dattrbits;
|
nfsattrbit_t attrbits, dattrbits;
|
||||||
size_t tresid;
|
size_t tresid;
|
||||||
u_int32_t *tl2 = NULL, fakefileno = 0xffffffff, rderr;
|
u_int32_t *tl2 = NULL, fakefileno = 0xffffffff, rderr;
|
||||||
|
struct timespec dctime;
|
||||||
|
|
||||||
KASSERT(uiop->uio_iovcnt == 1 &&
|
KASSERT(uiop->uio_iovcnt == 1 &&
|
||||||
(uio_uio_resid(uiop) & (DIRBLKSIZ - 1)) == 0,
|
(uio_uio_resid(uiop) & (DIRBLKSIZ - 1)) == 0,
|
||||||
("nfs readdirplusrpc bad uio"));
|
("nfs readdirplusrpc bad uio"));
|
||||||
|
timespecclear(&dctime);
|
||||||
*attrflagp = 0;
|
*attrflagp = 0;
|
||||||
if (eofp != NULL)
|
if (eofp != NULL)
|
||||||
*eofp = 0;
|
*eofp = 0;
|
||||||
@ -2997,6 +2999,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
|||||||
#endif
|
#endif
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
dctime = nfsva.na_ctime;
|
||||||
dotfileid = nfsva.na_fileid;
|
dotfileid = nfsva.na_fileid;
|
||||||
NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, vp);
|
NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, vp);
|
||||||
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
||||||
@ -3134,6 +3137,8 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
|||||||
error = nd->nd_repstat;
|
error = nd->nd_repstat;
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
}
|
||||||
|
if ((nd->nd_flag & ND_NFSV3) != 0 && *attrflagp != 0)
|
||||||
|
dctime = nap->na_ctime;
|
||||||
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
|
||||||
NFSLOCKNODE(dnp);
|
NFSLOCKNODE(dnp);
|
||||||
dnp->n_cookieverf.nfsuquad[0] = *tl++;
|
dnp->n_cookieverf.nfsuquad[0] = *tl++;
|
||||||
@ -3316,10 +3321,14 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
|||||||
vtonfs_dtype(np->n_vattr.na_type);
|
vtonfs_dtype(np->n_vattr.na_type);
|
||||||
ndp->ni_vp = newvp;
|
ndp->ni_vp = newvp;
|
||||||
NFSCNHASH(cnp, HASHINIT);
|
NFSCNHASH(cnp, HASHINIT);
|
||||||
if (cnp->cn_namelen <= NCHNAMLEN) {
|
if (cnp->cn_namelen <= NCHNAMLEN &&
|
||||||
|
(newvp->v_type != VDIR ||
|
||||||
|
dctime.tv_sec != 0)) {
|
||||||
cache_enter_time(ndp->ni_dvp,
|
cache_enter_time(ndp->ni_dvp,
|
||||||
ndp->ni_vp, cnp,
|
ndp->ni_vp, cnp,
|
||||||
&nfsva.na_ctime);
|
&nfsva.na_ctime,
|
||||||
|
newvp->v_type != VDIR ? NULL :
|
||||||
|
&dctime);
|
||||||
}
|
}
|
||||||
if (unlocknewvp)
|
if (unlocknewvp)
|
||||||
vput(newvp);
|
vput(newvp);
|
||||||
|
@ -1172,7 +1172,7 @@ nfs_lookup(struct vop_lookup_args *ap)
|
|||||||
&dnfsva.na_mtime, ==)) {
|
&dnfsva.na_mtime, ==)) {
|
||||||
mtx_unlock(&np->n_mtx);
|
mtx_unlock(&np->n_mtx);
|
||||||
cache_enter_time(dvp, NULL, cnp,
|
cache_enter_time(dvp, NULL, cnp,
|
||||||
&dnfsva.na_mtime);
|
&dnfsva.na_mtime, NULL);
|
||||||
} else
|
} else
|
||||||
mtx_unlock(&np->n_mtx);
|
mtx_unlock(&np->n_mtx);
|
||||||
}
|
}
|
||||||
@ -1271,9 +1271,10 @@ nfs_lookup(struct vop_lookup_args *ap)
|
|||||||
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
|
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
|
||||||
cnp->cn_flags |= SAVENAME;
|
cnp->cn_flags |= SAVENAME;
|
||||||
if ((cnp->cn_flags & MAKEENTRY) &&
|
if ((cnp->cn_flags & MAKEENTRY) &&
|
||||||
(cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) && attrflag) {
|
(cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) &&
|
||||||
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime);
|
attrflag != 0 && (newvp->v_type != VDIR || dattrflag != 0))
|
||||||
}
|
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
|
||||||
|
newvp->v_type != VDIR ? NULL : &dnfsva.na_ctime);
|
||||||
*vpp = newvp;
|
*vpp = newvp;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -1591,7 +1592,8 @@ nfs_create(struct vop_create_args *ap)
|
|||||||
}
|
}
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if ((cnp->cn_flags & MAKEENTRY) && attrflag)
|
if ((cnp->cn_flags & MAKEENTRY) && attrflag)
|
||||||
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime);
|
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
|
||||||
|
NULL);
|
||||||
*ap->a_vpp = newvp;
|
*ap->a_vpp = newvp;
|
||||||
} else if (NFS_ISV4(dvp)) {
|
} else if (NFS_ISV4(dvp)) {
|
||||||
error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid,
|
error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid,
|
||||||
@ -1966,8 +1968,8 @@ nfs_link(struct vop_link_args *ap)
|
|||||||
* must care about lookup caching hit rate, so...
|
* must care about lookup caching hit rate, so...
|
||||||
*/
|
*/
|
||||||
if (VFSTONFS(vp->v_mount)->nm_negnametimeo != 0 &&
|
if (VFSTONFS(vp->v_mount)->nm_negnametimeo != 0 &&
|
||||||
(cnp->cn_flags & MAKEENTRY) && dattrflag) {
|
(cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) {
|
||||||
cache_enter_time(tdvp, vp, cnp, &dnfsva.na_mtime);
|
cache_enter_time(tdvp, vp, cnp, &nfsva.na_ctime, NULL);
|
||||||
}
|
}
|
||||||
if (error && NFS_ISV4(vp))
|
if (error && NFS_ISV4(vp))
|
||||||
error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0,
|
error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0,
|
||||||
@ -2033,21 +2035,21 @@ nfs_symlink(struct vop_symlink_args *ap)
|
|||||||
if (dattrflag != 0) {
|
if (dattrflag != 0) {
|
||||||
mtx_unlock(&dnp->n_mtx);
|
mtx_unlock(&dnp->n_mtx);
|
||||||
(void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
|
(void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
|
||||||
/*
|
|
||||||
* If negative lookup caching is enabled, I might as well
|
|
||||||
* add an entry for this node. Not necessary for correctness,
|
|
||||||
* but if negative caching is enabled, then the system
|
|
||||||
* must care about lookup caching hit rate, so...
|
|
||||||
*/
|
|
||||||
if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
|
|
||||||
(cnp->cn_flags & MAKEENTRY)) {
|
|
||||||
cache_enter_time(dvp, newvp, cnp, &dnfsva.na_mtime);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dnp->n_attrstamp = 0;
|
dnp->n_attrstamp = 0;
|
||||||
mtx_unlock(&dnp->n_mtx);
|
mtx_unlock(&dnp->n_mtx);
|
||||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
|
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* If negative lookup caching is enabled, I might as well
|
||||||
|
* add an entry for this node. Not necessary for correctness,
|
||||||
|
* but if negative caching is enabled, then the system
|
||||||
|
* must care about lookup caching hit rate, so...
|
||||||
|
*/
|
||||||
|
if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
|
||||||
|
(cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) {
|
||||||
|
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, NULL);
|
||||||
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2118,9 +2120,10 @@ nfs_mkdir(struct vop_mkdir_args *ap)
|
|||||||
* must care about lookup caching hit rate, so...
|
* must care about lookup caching hit rate, so...
|
||||||
*/
|
*/
|
||||||
if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
|
if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
|
||||||
(cnp->cn_flags & MAKEENTRY) && dattrflag) {
|
(cnp->cn_flags & MAKEENTRY) &&
|
||||||
cache_enter_time(dvp, newvp, cnp, &dnfsva.na_mtime);
|
attrflag != 0 && dattrflag != 0)
|
||||||
}
|
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
|
||||||
|
&dnfsva.na_ctime);
|
||||||
*ap->a_vpp = newvp;
|
*ap->a_vpp = newvp;
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -105,6 +105,10 @@ struct namecache {
|
|||||||
/*
|
/*
|
||||||
* struct namecache_ts repeats struct namecache layout up to the
|
* struct namecache_ts repeats struct namecache layout up to the
|
||||||
* nc_nlen member.
|
* nc_nlen member.
|
||||||
|
* struct namecache_ts is used in place of struct namecache when time(s) need
|
||||||
|
* to be stored. The nc_dotdottime field is used when a cache entry is mapping
|
||||||
|
* both a non-dotdot directory name plus dotdot for the directory's
|
||||||
|
* parent.
|
||||||
*/
|
*/
|
||||||
struct namecache_ts {
|
struct namecache_ts {
|
||||||
LIST_ENTRY(namecache) nc_hash; /* hash chain */
|
LIST_ENTRY(namecache) nc_hash; /* hash chain */
|
||||||
@ -115,6 +119,7 @@ struct namecache_ts {
|
|||||||
u_char nc_flag; /* flag bits */
|
u_char nc_flag; /* flag bits */
|
||||||
u_char nc_nlen; /* length of name */
|
u_char nc_nlen; /* length of name */
|
||||||
struct timespec nc_time; /* timespec provided by fs */
|
struct timespec nc_time; /* timespec provided by fs */
|
||||||
|
struct timespec nc_dotdottime; /* dotdot timespec provided by fs */
|
||||||
int nc_ticks; /* ticks value when entry was added */
|
int nc_ticks; /* ticks value when entry was added */
|
||||||
char nc_name[0]; /* segment name + nul */
|
char nc_name[0]; /* segment name + nul */
|
||||||
};
|
};
|
||||||
@ -125,6 +130,7 @@ struct namecache_ts {
|
|||||||
#define NCF_WHITE 0x01
|
#define NCF_WHITE 0x01
|
||||||
#define NCF_ISDOTDOT 0x02
|
#define NCF_ISDOTDOT 0x02
|
||||||
#define NCF_TS 0x04
|
#define NCF_TS 0x04
|
||||||
|
#define NCF_DTS 0x08
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name caching works as follows:
|
* Name caching works as follows:
|
||||||
@ -190,6 +196,7 @@ RW_SYSINIT(vfscache, &cache_lock, "Name Cache");
|
|||||||
static uma_zone_t cache_zone_small;
|
static uma_zone_t cache_zone_small;
|
||||||
static uma_zone_t cache_zone_small_ts;
|
static uma_zone_t cache_zone_small_ts;
|
||||||
static uma_zone_t cache_zone_large;
|
static uma_zone_t cache_zone_large;
|
||||||
|
static uma_zone_t cache_zone_large_ts;
|
||||||
|
|
||||||
#define CACHE_PATH_CUTOFF 35
|
#define CACHE_PATH_CUTOFF 35
|
||||||
|
|
||||||
@ -197,8 +204,12 @@ static struct namecache *
|
|||||||
cache_alloc(int len, int ts)
|
cache_alloc(int len, int ts)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (len > CACHE_PATH_CUTOFF)
|
if (len > CACHE_PATH_CUTOFF) {
|
||||||
return (uma_zalloc(cache_zone_large, M_WAITOK));
|
if (ts)
|
||||||
|
return (uma_zalloc(cache_zone_large_ts, M_WAITOK));
|
||||||
|
else
|
||||||
|
return (uma_zalloc(cache_zone_large, M_WAITOK));
|
||||||
|
}
|
||||||
if (ts)
|
if (ts)
|
||||||
return (uma_zalloc(cache_zone_small_ts, M_WAITOK));
|
return (uma_zalloc(cache_zone_small_ts, M_WAITOK));
|
||||||
else
|
else
|
||||||
@ -218,7 +229,9 @@ cache_free(struct namecache *ncp)
|
|||||||
uma_zfree(cache_zone_small_ts, ncp);
|
uma_zfree(cache_zone_small_ts, ncp);
|
||||||
else
|
else
|
||||||
uma_zfree(cache_zone_small, ncp);
|
uma_zfree(cache_zone_small, ncp);
|
||||||
} else
|
} else if (ts)
|
||||||
|
uma_zfree(cache_zone_large_ts, ncp);
|
||||||
|
else
|
||||||
uma_zfree(cache_zone_large, ncp);
|
uma_zfree(cache_zone_large, ncp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,6 +534,10 @@ cache_lookup(dvp, vpp, cnp, tsp, ticksp)
|
|||||||
SDT_PROBE(vfs, namecache, lookup, hit, dvp, "..",
|
SDT_PROBE(vfs, namecache, lookup, hit, dvp, "..",
|
||||||
*vpp, 0, 0);
|
*vpp, 0, 0);
|
||||||
cache_out_ts(ncp, tsp, ticksp);
|
cache_out_ts(ncp, tsp, ticksp);
|
||||||
|
if ((ncp->nc_flag & (NCF_ISDOTDOT | NCF_DTS)) ==
|
||||||
|
NCF_DTS && tsp != NULL)
|
||||||
|
*tsp = ((struct namecache_ts *)ncp)->
|
||||||
|
nc_dotdottime;
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -686,11 +703,12 @@ cache_lookup(dvp, vpp, cnp, tsp, ticksp)
|
|||||||
* Add an entry to the cache.
|
* Add an entry to the cache.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
cache_enter_time(dvp, vp, cnp, tsp)
|
cache_enter_time(dvp, vp, cnp, tsp, dtsp)
|
||||||
struct vnode *dvp;
|
struct vnode *dvp;
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
struct componentname *cnp;
|
struct componentname *cnp;
|
||||||
struct timespec *tsp;
|
struct timespec *tsp;
|
||||||
|
struct timespec *dtsp;
|
||||||
{
|
{
|
||||||
struct namecache *ncp, *n2;
|
struct namecache *ncp, *n2;
|
||||||
struct namecache_ts *n3;
|
struct namecache_ts *n3;
|
||||||
@ -769,6 +787,10 @@ cache_enter_time(dvp, vp, cnp, tsp)
|
|||||||
n3->nc_time = *tsp;
|
n3->nc_time = *tsp;
|
||||||
n3->nc_ticks = ticks;
|
n3->nc_ticks = ticks;
|
||||||
n3->nc_flag |= NCF_TS;
|
n3->nc_flag |= NCF_TS;
|
||||||
|
if (dtsp != NULL) {
|
||||||
|
n3->nc_dotdottime = *dtsp;
|
||||||
|
n3->nc_flag |= NCF_DTS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
len = ncp->nc_nlen = cnp->cn_namelen;
|
len = ncp->nc_nlen = cnp->cn_namelen;
|
||||||
hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
|
hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
|
||||||
@ -794,6 +816,12 @@ cache_enter_time(dvp, vp, cnp, tsp)
|
|||||||
((struct namecache_ts *)ncp)->nc_time;
|
((struct namecache_ts *)ncp)->nc_time;
|
||||||
n3->nc_ticks =
|
n3->nc_ticks =
|
||||||
((struct namecache_ts *)ncp)->nc_ticks;
|
((struct namecache_ts *)ncp)->nc_ticks;
|
||||||
|
if (dtsp != NULL) {
|
||||||
|
n3->nc_dotdottime =
|
||||||
|
((struct namecache_ts *)ncp)->
|
||||||
|
nc_dotdottime;
|
||||||
|
n3->nc_flag |= NCF_DTS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CACHE_WUNLOCK();
|
CACHE_WUNLOCK();
|
||||||
cache_free(ncp);
|
cache_free(ncp);
|
||||||
@ -823,6 +851,11 @@ cache_enter_time(dvp, vp, cnp, tsp)
|
|||||||
ncp->nc_flag |= NCF_WHITE;
|
ncp->nc_flag |= NCF_WHITE;
|
||||||
} else if (vp->v_type == VDIR) {
|
} else if (vp->v_type == VDIR) {
|
||||||
if (flag != NCF_ISDOTDOT) {
|
if (flag != NCF_ISDOTDOT) {
|
||||||
|
/*
|
||||||
|
* For this case, the cache entry maps both the
|
||||||
|
* directory name in it and the name ".." for the
|
||||||
|
* directory's parent.
|
||||||
|
*/
|
||||||
if ((n2 = vp->v_cache_dd) != NULL &&
|
if ((n2 = vp->v_cache_dd) != NULL &&
|
||||||
(n2->nc_flag & NCF_ISDOTDOT) != 0)
|
(n2->nc_flag & NCF_ISDOTDOT) != 0)
|
||||||
cache_zap(n2);
|
cache_zap(n2);
|
||||||
@ -886,6 +919,9 @@ nchinit(void *dummy __unused)
|
|||||||
sizeof(struct namecache_ts) + CACHE_PATH_CUTOFF + 1,
|
sizeof(struct namecache_ts) + CACHE_PATH_CUTOFF + 1,
|
||||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
|
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
|
||||||
cache_zone_large = uma_zcreate("L VFS Cache",
|
cache_zone_large = uma_zcreate("L VFS Cache",
|
||||||
|
sizeof(struct namecache) + NAME_MAX + 1,
|
||||||
|
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
|
||||||
|
cache_zone_large_ts = uma_zcreate("LTS VFS Cache",
|
||||||
sizeof(struct namecache_ts) + NAME_MAX + 1,
|
sizeof(struct namecache_ts) + NAME_MAX + 1,
|
||||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
|
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
|
||||||
|
|
||||||
@ -1382,7 +1418,7 @@ void
|
|||||||
cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
|
cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
|
||||||
{
|
{
|
||||||
|
|
||||||
cache_enter_time(dvp, vp, cnp, NULL);
|
cache_enter_time(dvp, vp, cnp, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -912,7 +912,7 @@ nfs_lookup(struct vop_lookup_args *ap)
|
|||||||
struct vnode *dvp = ap->a_dvp;
|
struct vnode *dvp = ap->a_dvp;
|
||||||
struct vnode **vpp = ap->a_vpp;
|
struct vnode **vpp = ap->a_vpp;
|
||||||
struct mount *mp = dvp->v_mount;
|
struct mount *mp = dvp->v_mount;
|
||||||
struct vattr vattr;
|
struct vattr dvattr, vattr;
|
||||||
struct timespec nctime;
|
struct timespec nctime;
|
||||||
int flags = cnp->cn_flags;
|
int flags = cnp->cn_flags;
|
||||||
struct vnode *newvp;
|
struct vnode *newvp;
|
||||||
@ -1129,7 +1129,7 @@ nfs_lookup(struct vop_lookup_args *ap)
|
|||||||
}
|
}
|
||||||
if (v3) {
|
if (v3) {
|
||||||
nfsm_postop_attr_va(newvp, attrflag, &vattr);
|
nfsm_postop_attr_va(newvp, attrflag, &vattr);
|
||||||
nfsm_postop_attr(dvp, dattrflag);
|
nfsm_postop_attr_va(dvp, dattrflag, &dvattr);
|
||||||
} else {
|
} else {
|
||||||
nfsm_loadattr(newvp, &vattr);
|
nfsm_loadattr(newvp, &vattr);
|
||||||
attrflag = 1;
|
attrflag = 1;
|
||||||
@ -1137,9 +1137,10 @@ nfs_lookup(struct vop_lookup_args *ap)
|
|||||||
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
|
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
|
||||||
cnp->cn_flags |= SAVENAME;
|
cnp->cn_flags |= SAVENAME;
|
||||||
if ((cnp->cn_flags & MAKEENTRY) &&
|
if ((cnp->cn_flags & MAKEENTRY) &&
|
||||||
(cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) && attrflag) {
|
(cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) &&
|
||||||
cache_enter_time(dvp, newvp, cnp, &vattr.va_ctime);
|
attrflag != 0 && (newvp->v_type != VDIR || dattrflag != 0))
|
||||||
}
|
cache_enter_time(dvp, newvp, cnp, &vattr.va_ctime,
|
||||||
|
newvp->v_type != VDIR ? NULL : &dvattr.va_ctime);
|
||||||
*vpp = newvp;
|
*vpp = newvp;
|
||||||
m_freem(mrep);
|
m_freem(mrep);
|
||||||
nfsmout:
|
nfsmout:
|
||||||
@ -1181,7 +1182,7 @@ nfs_lookup(struct vop_lookup_args *ap)
|
|||||||
&vattr.va_mtime, ==)) {
|
&vattr.va_mtime, ==)) {
|
||||||
mtx_unlock(&np->n_mtx);
|
mtx_unlock(&np->n_mtx);
|
||||||
cache_enter_time(dvp, NULL, cnp,
|
cache_enter_time(dvp, NULL, cnp,
|
||||||
&vattr.va_mtime);
|
&vattr.va_mtime, NULL);
|
||||||
} else
|
} else
|
||||||
mtx_unlock(&np->n_mtx);
|
mtx_unlock(&np->n_mtx);
|
||||||
}
|
}
|
||||||
@ -2463,11 +2464,11 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
|
|||||||
nfsuint64 cookie;
|
nfsuint64 cookie;
|
||||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||||
struct nfsnode *dnp = VTONFS(vp), *np;
|
struct nfsnode *dnp = VTONFS(vp), *np;
|
||||||
struct vattr vattr;
|
struct vattr vattr, dvattr;
|
||||||
nfsfh_t *fhp;
|
nfsfh_t *fhp;
|
||||||
u_quad_t fileno;
|
u_quad_t fileno;
|
||||||
int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
|
int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
|
||||||
int attrflag, fhsize;
|
int attrflag, dattrflag, fhsize;
|
||||||
|
|
||||||
#ifndef nolint
|
#ifndef nolint
|
||||||
dp = NULL;
|
dp = NULL;
|
||||||
@ -2513,7 +2514,7 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
|
|||||||
*tl++ = txdr_unsigned(nmp->nm_readdirsize);
|
*tl++ = txdr_unsigned(nmp->nm_readdirsize);
|
||||||
*tl = txdr_unsigned(nmp->nm_rsize);
|
*tl = txdr_unsigned(nmp->nm_rsize);
|
||||||
nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, cred);
|
nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, cred);
|
||||||
nfsm_postop_attr(vp, attrflag);
|
nfsm_postop_attr_va(vp, dattrflag, &dvattr);
|
||||||
if (error) {
|
if (error) {
|
||||||
m_freem(mrep);
|
m_freem(mrep);
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
@ -2649,8 +2650,11 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
|
|||||||
md = mdsav2;
|
md = mdsav2;
|
||||||
dp->d_type = IFTODT(VTTOIF(vattr.va_type));
|
dp->d_type = IFTODT(VTTOIF(vattr.va_type));
|
||||||
ndp->ni_vp = newvp;
|
ndp->ni_vp = newvp;
|
||||||
cache_enter_time(ndp->ni_dvp, ndp->ni_vp, cnp,
|
if (newvp->v_type != VDIR || dattrflag != 0)
|
||||||
&vattr.va_ctime);
|
cache_enter_time(ndp->ni_dvp, ndp->ni_vp,
|
||||||
|
cnp, &vattr.va_ctime,
|
||||||
|
newvp->v_type != VDIR ? NULL :
|
||||||
|
&dvattr.va_ctime);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Just skip over the file handle */
|
/* Just skip over the file handle */
|
||||||
|
@ -583,9 +583,10 @@ struct vnode;
|
|||||||
|
|
||||||
/* cache_* may belong in namei.h. */
|
/* cache_* may belong in namei.h. */
|
||||||
#define cache_enter(dvp, vp, cnp) \
|
#define cache_enter(dvp, vp, cnp) \
|
||||||
cache_enter_time(dvp, vp, cnp, NULL)
|
cache_enter_time(dvp, vp, cnp, NULL, NULL)
|
||||||
void cache_enter_time(struct vnode *dvp, struct vnode *vp,
|
void cache_enter_time(struct vnode *dvp, struct vnode *vp,
|
||||||
struct componentname *cnp, struct timespec *tsp);
|
struct componentname *cnp, struct timespec *tsp,
|
||||||
|
struct timespec *dtsp);
|
||||||
int cache_lookup(struct vnode *dvp, struct vnode **vpp,
|
int cache_lookup(struct vnode *dvp, struct vnode **vpp,
|
||||||
struct componentname *cnp, struct timespec *tsp, int *ticksp);
|
struct componentname *cnp, struct timespec *tsp, int *ticksp);
|
||||||
void cache_purge(struct vnode *vp);
|
void cache_purge(struct vnode *vp);
|
||||||
|
Loading…
Reference in New Issue
Block a user