Page MenuHomeFreeBSD

D32635.diff
No OneTemporary

D32635.diff

diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -3630,7 +3630,8 @@
nfsattrbit_t attrbits, dattrbits;
size_t tresid;
u_int32_t *tl2 = NULL, rderr;
- struct timespec dctime;
+ struct timespec dctime, ts;
+ bool attr_ok;
KASSERT(uiop->uio_iovcnt == 1 &&
(uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
@@ -3815,6 +3816,7 @@
*tl = txdr_unsigned(NFSV4OP_GETATTR);
(void) nfsrv_putattrbit(nd, &dattrbits);
}
+ nanouptime(&ts);
error = nfscl_request(nd, vp, p, cred, stuff);
if (error)
return (error);
@@ -3972,6 +3974,7 @@
ncookie.lval[1];
if (nfhp != NULL) {
+ attr_ok = true;
if (NFSRV_CMPFH(nfhp->nfh_fh, nfhp->nfh_len,
dnp->n_fhp->nfh_fh, dnp->n_fhp->nfh_len)) {
VREF(vp);
@@ -4001,12 +4004,32 @@
if (!error) {
newvp = NFSTOV(np);
unlocknewvp = 1;
+ /*
+ * If n_localmodtime >= time before RPC,
+ * then a file modification operation,
+ * such as VOP_SETATTR() of size, has
+ * occurred while the Lookup RPC and
+ * acquisition of the vnode happened. As
+ * such, the attributes might be stale,
+ * with possibly an incorrect size.
+ */
+ NFSLOCKNODE(np);
+ if (timespecisset(
+ &np->n_localmodtime) &&
+ timespeccmp(&np->n_localmodtime,
+ &ts, >=)) {
+ NFSCL_DEBUG(4, "nfsrpc_readdirplus:"
+ " localmod stale attributes\n");
+ attr_ok = false;
+ }
+ NFSUNLOCKNODE(np);
}
}
nfhp = NULL;
if (newvp != NULLVP) {
- error = nfscl_loadattrcache(&newvp,
- &nfsva, NULL, NULL, 0, 0);
+ if (attr_ok)
+ error = nfscl_loadattrcache(&newvp,
+ &nfsva, NULL, NULL, 0, 0);
if (error) {
if (unlocknewvp)
vput(newvp);
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1014,6 +1014,7 @@
struct vattr *vap = ap->a_vap;
int error = 0;
u_quad_t tsize;
+ struct timespec ts;
#ifndef nolint
tsize = (u_quad_t)0;
@@ -1108,11 +1109,18 @@
NFSUNLOCKNODE(np);
}
error = nfs_setattrrpc(vp, vap, ap->a_cred, td);
- if (error && vap->va_size != VNOVAL) {
- NFSLOCKNODE(np);
- np->n_size = np->n_vattr.na_size = tsize;
- vnode_pager_setsize(vp, tsize);
- NFSUNLOCKNODE(np);
+ if (vap->va_size != VNOVAL) {
+ if (error == 0) {
+ nanouptime(&ts);
+ NFSLOCKNODE(np);
+ np->n_localmodtime = ts;
+ NFSUNLOCKNODE(np);
+ } else {
+ NFSLOCKNODE(np);
+ np->n_size = np->n_vattr.na_size = tsize;
+ vnode_pager_setsize(vp, tsize);
+ NFSUNLOCKNODE(np);
+ }
}
return (error);
}
@@ -1169,7 +1177,7 @@
struct nfsfh *nfhp;
struct nfsvattr dnfsva, nfsva;
struct vattr vattr;
- struct timespec nctime;
+ struct timespec nctime, ts;
uint32_t openmode;
*vpp = NULLVP;
@@ -1293,6 +1301,7 @@
newvp = NULLVP;
NFSINCRGLOBAL(nfsstatsv1.lookupcache_misses);
+ nanouptime(&ts);
error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag,
NULL, openmode);
@@ -1359,6 +1368,22 @@
if (error)
return (error);
newvp = NFSTOV(np);
+ /*
+ * If n_localmodtime >= time before RPC, then
+ * a file modification operation, such as
+ * VOP_SETATTR() of size, has occurred while
+ * the Lookup RPC and acquisition of the vnode
+ * happened. As such, the attributes might
+ * be stale, with possibly an incorrect size.
+ */
+ NFSLOCKNODE(np);
+ if (timespecisset(&np->n_localmodtime) &&
+ timespeccmp(&np->n_localmodtime, &ts, >=)) {
+ NFSCL_DEBUG(4, "nfs_lookup: rename localmod "
+ "stale attributes\n");
+ attrflag = 0;
+ }
+ NFSUNLOCKNODE(np);
if (attrflag)
(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
0, 1);
@@ -1418,6 +1443,22 @@
if (error)
return (error);
newvp = NFSTOV(np);
+ /*
+ * If n_localmodtime >= time before RPC, then
+ * a file modification operation, such as
+ * VOP_SETATTR() of size, has occurred while
+ * the Lookup RPC and acquisition of the vnode
+ * happened. As such, the attributes might
+ * be stale, with possibly an incorrect size.
+ */
+ NFSLOCKNODE(np);
+ if (timespecisset(&np->n_localmodtime) &&
+ timespeccmp(&np->n_localmodtime, &ts, >=)) {
+ NFSCL_DEBUG(4, "nfs_lookup: localmod "
+ "stale attributes\n");
+ attrflag = 0;
+ }
+ NFSUNLOCKNODE(np);
if (attrflag)
(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
0, 1);
@@ -2635,7 +2676,9 @@
struct componentname cn;
int error = 0, attrflag, dattrflag;
u_int hash;
+ struct timespec ts;
+ nanouptime(&ts);
error = nfsrpc_lookup(dvp, name, len, cred, td, &dnfsva, &nfsva,
&nfhp, &attrflag, &dattrflag, NULL, 0);
if (dattrflag)
@@ -2696,6 +2739,22 @@
if (error)
return (error);
newvp = NFSTOV(np);
+ /*
+ * If n_localmodtime >= time before RPC, then
+ * a file modification operation, such as
+ * VOP_SETATTR() of size, has occurred while
+ * the Lookup RPC and acquisition of the vnode
+ * happened. As such, the attributes might
+ * be stale, with possibly an incorrect size.
+ */
+ NFSLOCKNODE(np);
+ if (timespecisset(&np->n_localmodtime) &&
+ timespeccmp(&np->n_localmodtime, &ts, >=)) {
+ NFSCL_DEBUG(4, "nfs_lookitup: localmod "
+ "stale attributes\n");
+ attrflag = 0;
+ }
+ NFSUNLOCKNODE(np);
}
if (!attrflag && *npp == NULL) {
if (newvp == dvp)
@@ -3643,11 +3702,14 @@
struct thread *td = curthread;
struct nfsvattr nfsva;
struct nfsmount *nmp;
+ struct nfsnode *np;
off_t alen;
int attrflag, error, ret;
+ struct timespec ts;
attrflag = 0;
nmp = VFSTONFS(vp->v_mount);
+ np = VTONFS(vp);
mtx_lock(&nmp->nm_mtx);
if (NFSHASNFSV4(nmp) && nmp->nm_minorvers >= NFSV42_MINORVERSION &&
(nmp->nm_privflag & NFSMNTP_NOALLOCATE) == 0) {
@@ -3667,6 +3729,10 @@
if (error == 0) {
*ap->a_offset += alen;
*ap->a_len -= alen;
+ nanouptime(&ts);
+ NFSLOCKNODE(np);
+ np->n_localmodtime = ts;
+ NFSUNLOCKNODE(np);
} else if (error == NFSERR_NOTSUPP) {
mtx_lock(&nmp->nm_mtx);
nmp->nm_privflag |= NFSMNTP_NOALLOCATE;
diff --git a/sys/fs/nfsclient/nfsnode.h b/sys/fs/nfsclient/nfsnode.h
--- a/sys/fs/nfsclient/nfsnode.h
+++ b/sys/fs/nfsclient/nfsnode.h
@@ -129,6 +129,7 @@
struct nfsv4node *n_v4; /* extra V4 stuff */
struct ucred *n_writecred; /* Cred. for putpages */
struct nfsclopen *n_openstateid; /* Cached open stateid */
+ struct timespec n_localmodtime; /* Last local modify */
};
#define n_atim n_un1.nf_atim

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 21, 1:07 PM (18 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15541634
Default Alt Text
D32635.diff (6 KB)

Event Timeline