summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
authormohans <mohans@FreeBSD.org>2007-03-09 04:02:38 +0000
committermohans <mohans@FreeBSD.org>2007-03-09 04:02:38 +0000
commita332cb00d57e6d307a6d08a69b4d5430b20c7850 (patch)
tree24b2e714c624eb1b06a4af38fe8eb04bc9f63660 /sys/nfsclient
parent088212ae5d87f38b2e7890e8e1a608a268db0add (diff)
downloadFreeBSD-src-a332cb00d57e6d307a6d08a69b4d5430b20c7850.zip
FreeBSD-src-a332cb00d57e6d307a6d08a69b4d5430b20c7850.tar.gz
Over NFS, an open() call could result in multiple over-the-wire
GETATTRs being generated - one from lookup()/namei() and the other from nfs_open() (for cto consistency). This change eliminates the GETATTR in nfs_open() if an otw GETATTR was done from the namei() path. Instead of extending the vop interface, we timestamp each attr load, and use this to detect whether a GETATTR was done from namei() for this syscall. Introduces a thread-local variable that counts the syscalls made by the thread and uses <pid, tid, thread syscalls> as the attrload timestamp. Thanks to jhb@ and peter@ for a discussion on thread state that could be used as the timestamp with minimal overhead.
Diffstat (limited to 'sys/nfsclient')
-rw-r--r--sys/nfsclient/nfs_socket.c2
-rw-r--r--sys/nfsclient/nfs_subs.c9
-rw-r--r--sys/nfsclient/nfs_vnops.c11
-rw-r--r--sys/nfsclient/nfsnode.h11
4 files changed, 31 insertions, 2 deletions
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index 6036050..a28d837 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -1412,7 +1412,7 @@ nfs_timer(void *arg)
}
if (rep->r_rtt >= 0) {
rep->r_rtt++;
- if (nmp->nm_flag & NFSMNT_DUMBTIMR)
+ if ((nmp->nm_flag & NFSMNT_DUMBTIMR) || (nmp->nm_sotype == SOCK_STREAM))
timeo = nmp->nm_timeo;
else
timeo = nfs_estimate_rto(nmp, rep->r_procnum);
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 92dd32e..61a82b8 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -548,6 +548,7 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
u_short vmode;
struct timespec mtime;
int v3 = NFS_ISV3(vp);
+ struct thread *td = curthread;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
@@ -647,6 +648,14 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
vap->va_filerev = 0;
}
np->n_attrstamp = time_second;
+ /* Timestamp the NFS otw getattr fetch */
+ if (td->td_proc) {
+ np->n_ac_ts_tid = td->td_tid;
+ np->n_ac_ts_pid = td->td_proc->p_pid;
+ np->n_ac_ts_syscalls = td->td_syscalls;
+ } else
+ bzero(&np->n_ac_ts, sizeof(struct nfs_attrcache_timestamp));
+
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (dontshrink && vap->va_size < np->n_size) {
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 761618b..55d7b3f 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -432,6 +432,8 @@ nfs_access(struct vop_access_args *ap)
}
}
+int nfs_otw_getattr_avoid = 0;
+
/*
* nfs open vnode op
* Check to see if the type is ok
@@ -471,7 +473,14 @@ nfs_open(struct vop_open_args *ap)
np->n_mtime = vattr.va_mtime;
mtx_unlock(&np->n_mtx);
} else {
- np->n_attrstamp = 0;
+ struct thread *td = curthread;
+
+ if (np->n_ac_ts_syscalls != td->td_syscalls ||
+ np->n_ac_ts_tid != td->td_tid ||
+ td->td_proc == NULL ||
+ np->n_ac_ts_pid != td->td_proc->p_pid) {
+ np->n_attrstamp = 0;
+ }
mtx_unlock(&np->n_mtx);
error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
if (error)
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 2287235..f6d898a 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -74,6 +74,16 @@ struct nfsdmap {
#define ndm_cookies ndm_un1.ndmu3_cookies
#define ndm4_cookies ndm_un1.ndmu4_cookies
+#define n_ac_ts_tid n_ac_ts.nfs_ac_ts_tid
+#define n_ac_ts_pid n_ac_ts.nfs_ac_ts_pid
+#define n_ac_ts_syscalls n_ac_ts.nfs_ac_ts_syscalls
+
+struct nfs_attrcache_timestamp {
+ lwpid_t nfs_ac_ts_tid;
+ pid_t nfs_ac_ts_pid;
+ unsigned long nfs_ac_ts_syscalls;
+};
+
/*
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
* is purely coincidental.
@@ -127,6 +137,7 @@ struct nfsnode {
uint32_t n_namelen;
int n_directio_opens;
int n_directio_asyncwr;
+ struct nfs_attrcache_timestamp n_ac_ts;
};
#define n_atim n_un1.nf_atim
OpenPOWER on IntegriCloud