diff options
author | mohans <mohans@FreeBSD.org> | 2007-03-09 04:02:38 +0000 |
---|---|---|
committer | mohans <mohans@FreeBSD.org> | 2007-03-09 04:02:38 +0000 |
commit | a332cb00d57e6d307a6d08a69b4d5430b20c7850 (patch) | |
tree | 24b2e714c624eb1b06a4af38fe8eb04bc9f63660 /sys/nfsclient | |
parent | 088212ae5d87f38b2e7890e8e1a608a268db0add (diff) | |
download | FreeBSD-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.c | 2 | ||||
-rw-r--r-- | sys/nfsclient/nfs_subs.c | 9 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vnops.c | 11 | ||||
-rw-r--r-- | sys/nfsclient/nfsnode.h | 11 |
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 |