2 fixes that improve on the consistency of the NFS client cache.
- Change the cached mtime to a 'struct timespec' from a time_t. Improving the precision of the cached mtime tightens up NFS' "close-to-open" consistency considerably. - Always force an over-the-wire consistency check from nfs_open() (unless the file is marked modified). This further improves NFS' "close-to-open" consistency. Submitted by: Mohan Srinivasan mohans at yahoo-inc dot com
This commit is contained in:
parent
6a4b48f488
commit
ddc6c40075
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=138473
@ -98,10 +98,10 @@ nfs4_vnop_loadattrcache(struct vnode *vp, struct nfsv4_fattr *fap,
|
||||
*/
|
||||
np = VTONFS(vp);
|
||||
vap = &np->n_vattr;
|
||||
if (vp->v_type != vtyp || np->n_mtime == 0) {
|
||||
if (vp->v_type != vtyp || np->n_mtime.tv_sec == 0) {
|
||||
bzero(vap, sizeof *vap);
|
||||
vp->v_type = vtyp;
|
||||
np->n_mtime = mtime.tv_sec;
|
||||
np->n_mtime.tv_sec = mtime.tv_sec;
|
||||
}
|
||||
vap->va_type = vtyp;
|
||||
vap->va_mode = (vmode & 07777);
|
||||
|
@ -1412,7 +1412,7 @@ nfs4_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
|
||||
|
||||
/* XXX wccflag */
|
||||
if (wccflag)
|
||||
VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
|
||||
VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime;
|
||||
|
||||
error = nfs_v4postop(&cp, error);
|
||||
|
||||
@ -1994,7 +1994,7 @@ nfs4_readdir(struct vop_readdir_args *ap)
|
||||
if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
|
||||
(np->n_flag & NMODIFIED) == 0) {
|
||||
if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
|
||||
np->n_mtime == vattr.va_mtime.tv_sec) {
|
||||
np->n_mtime.tv_sec == vattr.va_mtime.tv_sec) {
|
||||
nfsstats.direofcache_hits++;
|
||||
return (0);
|
||||
}
|
||||
|
@ -396,19 +396,19 @@ nfs_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
|
||||
error = VOP_GETATTR(vp, &vattr, cred, td);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_mtime = vattr.va_mtime.tv_sec;
|
||||
np->n_mtime = vattr.va_mtime;
|
||||
} else {
|
||||
error = VOP_GETATTR(vp, &vattr, cred, td);
|
||||
if (error)
|
||||
return (error);
|
||||
if ((np->n_flag & NSIZECHANGED)
|
||||
|| (np->n_mtime != vattr.va_mtime.tv_sec)) {
|
||||
|| (NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime))) {
|
||||
if (vp->v_type == VDIR)
|
||||
(nmp->nm_rpcops->nr_invaldir)(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_mtime = vattr.va_mtime.tv_sec;
|
||||
np->n_mtime = vattr.va_mtime;
|
||||
np->n_flag &= ~NSIZECHANGED;
|
||||
}
|
||||
}
|
||||
@ -1318,7 +1318,7 @@ nfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td)
|
||||
}
|
||||
/* ASSERT_VOP_LOCKED(vp, "nfs_doio"); */
|
||||
if (p && (vp->v_vflag & VV_TEXT) &&
|
||||
(np->n_mtime != np->n_vattr.va_mtime.tv_sec)) {
|
||||
(NFS_TIMESPEC_COMPARE(&np->n_mtime, &np->n_vattr.va_mtime))) {
|
||||
PROC_LOCK(p);
|
||||
killproc(p, "text file modification");
|
||||
PROC_UNLOCK(p);
|
||||
|
@ -534,7 +534,7 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
|
||||
vp->v_type = vtyp;
|
||||
if (vp->v_type == VFIFO)
|
||||
vp->v_op = &nfs_fifoops;
|
||||
np->n_mtime = mtime.tv_sec;
|
||||
np->n_mtime = mtime;
|
||||
}
|
||||
vap = &np->n_vattr;
|
||||
vap->va_type = vtyp;
|
||||
@ -639,7 +639,7 @@ nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
|
||||
vap = &np->n_vattr;
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
/* XXX n_mtime doesn't seem to be updated on a miss-and-reload */
|
||||
timeo = (time_second - np->n_mtime) / 10;
|
||||
timeo = (time_second - np->n_mtime.tv_sec) / 10;
|
||||
|
||||
#ifdef NFS_ACDEBUG
|
||||
if (nfs_acdebug>1)
|
||||
@ -941,8 +941,8 @@ nfsm_wcc_data_xx(struct vnode **v, int *f, struct mbuf **md, caddr_t *dpos)
|
||||
if (tl == NULL)
|
||||
return EBADRPC;
|
||||
if (*f)
|
||||
ttretf = (VTONFS(*v)->n_mtime ==
|
||||
fxdr_unsigned(u_int32_t, *(tl + 2)));
|
||||
ttretf = (VTONFS(*v)->n_mtime.tv_sec == fxdr_unsigned(u_int32_t, *(tl + 2)) &&
|
||||
VTONFS(*v)->n_mtime.tv_nsec == fxdr_unsigned(u_int32_t, *(tl + 3)));
|
||||
}
|
||||
t1 = nfsm_postop_attr_xx(v, &ttattrf, md, dpos);
|
||||
if (t1)
|
||||
|
@ -417,22 +417,22 @@ nfs_open(struct vop_open_args *ap)
|
||||
error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_mtime = vattr.va_mtime.tv_sec;
|
||||
np->n_mtime = vattr.va_mtime;
|
||||
} else {
|
||||
np->n_attrstamp = 0;
|
||||
error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_mtime != vattr.va_mtime.tv_sec) {
|
||||
if (NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) {
|
||||
if (vp->v_type == VDIR)
|
||||
np->n_direofoffset = 0;
|
||||
error = nfs_vinvalbuf(vp, V_SAVE,
|
||||
ap->a_cred, ap->a_td, 1);
|
||||
if (error == EINTR || error == EIO)
|
||||
return (error);
|
||||
np->n_mtime = vattr.va_mtime.tv_sec;
|
||||
np->n_mtime = vattr.va_mtime;
|
||||
}
|
||||
}
|
||||
np->n_attrstamp = 0; /* For Open/Close consistency */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -484,7 +484,6 @@ nfs_close(struct vop_close_args *ap)
|
||||
vm_object_page_clean(vp->v_object, 0, 0, 0);
|
||||
VM_OBJECT_UNLOCK(vp->v_object);
|
||||
}
|
||||
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
if (NFS_ISV3(vp)) {
|
||||
/*
|
||||
@ -506,8 +505,14 @@ nfs_close(struct vop_close_args *ap)
|
||||
} else {
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_td, 1);
|
||||
}
|
||||
np->n_attrstamp = 0;
|
||||
}
|
||||
/*
|
||||
* Invalidate the attribute cache in all cases.
|
||||
* An open is going to fetch fresh attrs any way, other procs
|
||||
* on this node that have file open will be forced to do an
|
||||
* otw attr fetch, but this is safe.
|
||||
*/
|
||||
np->n_attrstamp = 0;
|
||||
if (np->n_flag & NWRITEERR) {
|
||||
np->n_flag &= ~NWRITEERR;
|
||||
error = np->n_error;
|
||||
@ -1153,7 +1158,7 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
|
||||
} else
|
||||
nfsm_loadattr(vp, NULL);
|
||||
if (wccflag)
|
||||
VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
|
||||
VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime;
|
||||
m_freem(mrep);
|
||||
if (error)
|
||||
break;
|
||||
@ -1912,7 +1917,7 @@ nfs_readdir(struct vop_readdir_args *ap)
|
||||
if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
|
||||
(np->n_flag & NMODIFIED) == 0) {
|
||||
if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
|
||||
np->n_mtime == vattr.va_mtime.tv_sec) {
|
||||
!NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) {
|
||||
nfsstats.direofcache_hits++;
|
||||
return (0);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ struct nfsnode {
|
||||
u_int32_t n_mode; /* ACCESS mode cache */
|
||||
uid_t n_modeuid; /* credentials having mode */
|
||||
time_t n_modestamp; /* mode cache timestamp */
|
||||
time_t n_mtime; /* Prev modify time. */
|
||||
struct timespec n_mtime; /* Prev modify time. */
|
||||
time_t n_ctime; /* Prev create time. */
|
||||
time_t n_expiry; /* Lease expiry time */
|
||||
nfsfh_t *n_fhp; /* NFS File Handle */
|
||||
@ -155,6 +155,8 @@ struct nfsnode {
|
||||
#define VTONFS(vp) ((struct nfsnode *)(vp)->v_data)
|
||||
#define NFSTOV(np) ((struct vnode *)(np)->n_vnode)
|
||||
|
||||
#define NFS_TIMESPEC_COMPARE(T1, T2) (((T1)->tv_sec != (T2)->tv_sec) || ((T1)->tv_nsec != (T2)->tv_nsec))
|
||||
|
||||
/*
|
||||
* Queue head for nfsiod's
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user