From owner-svn-src-all@FreeBSD.ORG Fri May 15 20:36:54 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B95FB106566B; Fri, 15 May 2009 20:36:54 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7555E8FC0C; Fri, 15 May 2009 20:36:54 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4FKasgA033838; Fri, 15 May 2009 20:36:54 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4FKashg033833; Fri, 15 May 2009 20:36:54 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200905152036.n4FKashg033833@svn.freebsd.org> From: John Baldwin Date: Fri, 15 May 2009 20:36:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r192156 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern nfsclient sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 May 2009 20:36:55 -0000 Author: jhb Date: Fri May 15 20:36:54 2009 New Revision: 192156 URL: http://svn.freebsd.org/changeset/base/192156 Log: MFC: Add caching of -ve lookups to the NFS client. To prevent clients from not noticing new files created by another client for a "long" time, reduce the default timeout for caching attributes of directories from 30 seconds to 3 seconds. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_cache.c stable/7/sys/nfsclient/nfs.h stable/7/sys/nfsclient/nfs_vnops.c stable/7/sys/nfsclient/nfsnode.h stable/7/sys/sys/vnode.h Modified: stable/7/sys/kern/vfs_cache.c ============================================================================== --- stable/7/sys/kern/vfs_cache.c Fri May 15 20:13:15 2009 (r192155) +++ stable/7/sys/kern/vfs_cache.c Fri May 15 20:36:54 2009 (r192156) @@ -700,6 +700,24 @@ cache_purge(vp) } /* + * Invalidate all negative entries for a particular directory vnode. + */ +void +cache_purge_negative(vp) + struct vnode *vp; +{ + struct namecache *cp, *ncp; + + CTR1(KTR_VFS, "cache_purge_negative(%p)", vp); + CACHE_LOCK(); + LIST_FOREACH_SAFE(cp, &vp->v_cache_src, nc_src, ncp) { + if (cp->nc_vp == NULL) + cache_zap(cp); + } + CACHE_UNLOCK(); +} + +/* * Flush all entries referencing a particular filesystem. */ void Modified: stable/7/sys/nfsclient/nfs.h ============================================================================== --- stable/7/sys/nfsclient/nfs.h Fri May 15 20:13:15 2009 (r192155) +++ stable/7/sys/nfsclient/nfs.h Fri May 15 20:36:54 2009 (r192156) @@ -63,7 +63,7 @@ #define NFS_MAXATTRTIMO 60 #endif #ifndef NFS_MINDIRATTRTIMO -#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */ +#define NFS_MINDIRATTRTIMO 3 /* VDIR attrib cache timeout in sec */ #endif #ifndef NFS_MAXDIRATTRTIMO #define NFS_MAXDIRATTRTIMO 60 Modified: stable/7/sys/nfsclient/nfs_vnops.c ============================================================================== --- stable/7/sys/nfsclient/nfs_vnops.c Fri May 15 20:13:15 2009 (r192155) +++ stable/7/sys/nfsclient/nfs_vnops.c Fri May 15 20:36:54 2009 (r192156) @@ -862,6 +862,7 @@ nfs_lookup(struct vop_lookup_args *ap) struct componentname *cnp = ap->a_cnp; struct vnode *dvp = ap->a_dvp; struct vnode **vpp = ap->a_vpp; + struct vattr vattr; int flags = cnp->cn_flags; struct vnode *newvp; struct nfsmount *nmp; @@ -890,16 +891,20 @@ nfs_lookup(struct vop_lookup_args *ap) if (error > 0 && error != ENOENT) return (error); if (error == -1) { - struct vattr vattr; - + /* + * We only accept a positive hit in the cache if the + * change time of the file matches our cached copy. + * Otherwise, we discard the cache entry and fallback + * to doing a lookup RPC. + */ newvp = *vpp; if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) - && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { - nfsstats.lookupcache_hits++; - if (cnp->cn_nameiop != LOOKUP && - (flags & ISLASTCN)) - cnp->cn_flags |= SAVENAME; - return (0); + && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { + nfsstats.lookupcache_hits++; + if (cnp->cn_nameiop != LOOKUP && + (flags & ISLASTCN)) + cnp->cn_flags |= SAVENAME; + return (0); } cache_purge(newvp); if (dvp != newvp) @@ -907,6 +912,22 @@ nfs_lookup(struct vop_lookup_args *ap) else vrele(newvp); *vpp = NULLVP; + } else if (error == ENOENT) { + /* + * We only accept a negative hit in the cache if the + * modification time of the parent directory matches + * our cached copy. Otherwise, we discard all of the + * negative cache entries for this directory. + */ + if (VOP_GETATTR(dvp, &vattr, cnp->cn_cred, td) == 0 && + vattr.va_mtime.tv_sec == np->n_dmtime) { + nfsstats.lookupcache_hits++; + return (ENOENT); + } + cache_purge_negative(dvp); + mtx_lock(&np->n_mtx); + np->n_dmtime = 0; + mtx_unlock(&np->n_mtx); } error = 0; newvp = NULLVP; @@ -992,16 +1013,40 @@ nfsmout: vput(newvp); *vpp = NULLVP; } + + if (error != ENOENT) + goto done; + + /* The requested file was not found. */ if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && - (flags & ISLASTCN) && error == ENOENT) { + (flags & ISLASTCN)) { + /* + * XXX: UFS does a full VOP_ACCESS(dvp, + * VWRITE) here instead of just checking + * MNT_RDONLY. + */ if (dvp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else - error = EJUSTRETURN; - } - if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) + return (EROFS); cnp->cn_flags |= SAVENAME; + return (EJUSTRETURN); + } + + if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) { + /* + * Maintain n_dmtime as the modification time + * of the parent directory when the oldest -ve + * name cache entry for this directory was + * added. + */ + mtx_lock(&np->n_mtx); + if (np->n_dmtime == 0) + np->n_dmtime = np->n_vattr.va_mtime.tv_sec; + mtx_unlock(&np->n_mtx); + cache_enter(dvp, NULL, cnp); + } + return (ENOENT); } +done: return (error); } Modified: stable/7/sys/nfsclient/nfsnode.h ============================================================================== --- stable/7/sys/nfsclient/nfsnode.h Fri May 15 20:13:15 2009 (r192155) +++ stable/7/sys/nfsclient/nfsnode.h Fri May 15 20:36:54 2009 (r192156) @@ -109,6 +109,7 @@ struct nfsnode { time_t n_modestamp; /* mode cache timestamp */ struct timespec n_mtime; /* Prev modify time. */ time_t n_ctime; /* Prev create time. */ + time_t n_dmtime; /* Prev dir modify time. */ time_t n_expiry; /* Lease expiry time */ nfsfh_t *n_fhp; /* NFS File Handle */ struct vnode *n_vnode; /* associated vnode */ Modified: stable/7/sys/sys/vnode.h ============================================================================== --- stable/7/sys/sys/vnode.h Fri May 15 20:13:15 2009 (r192155) +++ stable/7/sys/sys/vnode.h Fri May 15 20:36:54 2009 (r192156) @@ -564,6 +564,7 @@ void cache_enter(struct vnode *dvp, stru int cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp); void cache_purge(struct vnode *vp); +void cache_purge_negative(struct vnode *vp); void cache_purgevfs(struct mount *mp); int change_dir(struct vnode *vp, struct thread *td); int change_root(struct vnode *vp, struct thread *td);