From owner-svn-src-head@FreeBSD.ORG Sun May 31 14:57:44 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 466661065674; Sun, 31 May 2009 14:57:44 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 32EF48FC14; Sun, 31 May 2009 14:57:44 +0000 (UTC) (envelope-from kib@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 n4VEviMA046933; Sun, 31 May 2009 14:57:44 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4VEvihD046931; Sun, 31 May 2009 14:57:44 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200905311457.n4VEvihD046931@svn.freebsd.org> From: Konstantin Belousov Date: Sun, 31 May 2009 14:57:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r193174 - in head/sys: kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 31 May 2009 14:57:45 -0000 Author: kib Date: Sun May 31 14:57:43 2009 New Revision: 193174 URL: http://svn.freebsd.org/changeset/base/193174 Log: Eliminate code duplication in vn_fullpath1() around the cache lookups and calls to vn_vptocnp() by moving more of the common code to vn_vptocnp(). Rename vn_vptocnp() to vn_vptocnp_locked() to signify that cache is locked around the call. Do not track buffer position by both the pointer and offset, use only buflen to record the start of the free space. Export vn_vptocnp() for external consumers as a wrapper around vn_vptocnp_locked() that locks the cache and handles hold counts. Tested by: pho Modified: head/sys/kern/vfs_cache.c head/sys/sys/vnode.h Modified: head/sys/kern/vfs_cache.c ============================================================================== --- head/sys/kern/vfs_cache.c Sun May 31 14:54:20 2009 (r193173) +++ head/sys/kern/vfs_cache.c Sun May 31 14:57:43 2009 (r193174) @@ -206,7 +206,7 @@ SYSCTL_OPAQUE(_vfs_cache, OID_AUTO, nchs static void cache_zap(struct namecache *ncp); -static int vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen); +static int vn_vptocnp_locked(struct vnode **vp, char *buf, u_int *buflen); static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, u_int buflen); @@ -1036,12 +1036,55 @@ vn_fullpath_global(struct thread *td, st return (error); } +int +vn_vptocnp(struct vnode **vp, char *buf, u_int *buflen) +{ + int error; + + CACHE_RLOCK(); + error = vn_vptocnp_locked(vp, buf, buflen); + if (error == 0) { + /* + * vn_vptocnp_locked() dropped hold acquired by + * VOP_VPTOCNP immediately after locking the + * cache. Since we are going to drop the cache rlock, + * re-hold the result. + */ + vhold(*vp); + CACHE_RUNLOCK(); + } + return (error); +} + static int -vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen) +vn_vptocnp_locked(struct vnode **vp, char *buf, u_int *buflen) { struct vnode *dvp; + struct namecache *ncp; int error, vfslocked; + TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) { + if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) + break; + } + if (ncp != NULL) { + if (*buflen < ncp->nc_nlen) { + CACHE_RUNLOCK(); + numfullpathfail4++; + error = ENOMEM; + SDT_PROBE(vfs, namecache, fullpath, return, error, + startvp, NULL, 0, 0); + return (error); + } + *buflen -= ncp->nc_nlen; + memcpy(buf + *buflen, ncp->nc_name, ncp->nc_nlen); + SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp, + ncp->nc_name, vp, 0, 0); + *vp = ncp->nc_dvp; + return (0); + } + SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0); + vhold(*vp); CACHE_RUNLOCK(); vfslocked = VFS_LOCK_GIANT((*vp)->v_mount); @@ -1052,16 +1095,21 @@ vn_vptocnp(struct vnode **vp, char **bp, VFS_UNLOCK_GIANT(vfslocked); if (error) { numfullpathfail2++; + SDT_PROBE(vfs, namecache, fullpath, return, error, startvp, + NULL, 0, 0); return (error); } - *bp = buf + *buflen; + *vp = dvp; CACHE_RLOCK(); if ((*vp)->v_iflag & VI_DOOMED) { /* forced unmount */ CACHE_RUNLOCK(); vdrop(*vp); - return (ENOENT); + error = ENOENT; + SDT_PROBE(vfs, namecache, fullpath, return, error, startvp, + NULL, 0, 0); + return (error); } vdrop(*vp); @@ -1075,59 +1123,26 @@ static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, u_int buflen) { - char *bp; - int error, i, slash_prefixed; - struct namecache *ncp; + int error, slash_prefixed; #ifdef KDTRACE_HOOKS struct vnode *startvp = vp; #endif buflen--; - bp = buf + buflen; - *bp = '\0'; + buf[buflen] = '\0'; error = 0; slash_prefixed = 0; SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0); - CACHE_RLOCK(); numfullpathcalls++; + CACHE_RLOCK(); if (vp->v_type != VDIR) { - ncp = TAILQ_FIRST(&vp->v_cache_dst); - if (ncp != NULL) { - buflen -= ncp->nc_nlen; - for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--) - *--bp = ncp->nc_name[i]; - if (bp == buf) { - numfullpathfail4++; - CACHE_RUNLOCK(); - error = ENOMEM; - SDT_PROBE(vfs, namecache, fullpath, return, - error, startvp, NULL, 0, 0); - return (error); - } - SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp, - ncp->nc_name, vp, 0, 0); - vp = ncp->nc_dvp; - } else { - SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, - 0, 0); - error = vn_vptocnp(&vp, &bp, buf, &buflen); - if (error) { - SDT_PROBE(vfs, namecache, fullpath, return, - error, startvp, NULL, 0, 0); - return (error); - } - } - if (buflen <= 0) { - numfullpathfail4++; - CACHE_RUNLOCK(); - error = ENOMEM; - SDT_PROBE(vfs, namecache, fullpath, return, error, - startvp, NULL, 0, 0); + error = vn_vptocnp_locked(&vp, buf, &buflen); + if (error) return (error); - } - *--bp = '/'; - buflen--; + if (buflen == 0) + return (ENOMEM); + buf[--buflen] = '/'; slash_prefixed = 1; } while (vp != rdir && vp != rootvnode) { @@ -1141,64 +1156,39 @@ vn_fullpath1(struct thread *td, struct v continue; } if (vp->v_type != VDIR) { - numfullpathfail1++; CACHE_RUNLOCK(); + numfullpathfail1++; error = ENOTDIR; break; } - TAILQ_FOREACH(ncp, &vp->v_cache_dst, nc_dst) - if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) - break; - if (ncp != NULL) { - buflen -= ncp->nc_nlen; - for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--) - *--bp = ncp->nc_name[i]; - if (bp == buf) { - numfullpathfail4++; - CACHE_RUNLOCK(); - error = ENOMEM; - break; - } - SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp, - ncp->nc_name, vp, 0, 0); - vp = ncp->nc_dvp; - } else { - SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, - 0, 0); - error = vn_vptocnp(&vp, &bp, buf, &buflen); - if (error) - break; - } - if (buflen <= 0) { - numfullpathfail4++; - CACHE_RUNLOCK(); + error = vn_vptocnp_locked(&vp, buf, &buflen); + if (error) + break; + if (buflen == 0) { error = ENOMEM; break; } - *--bp = '/'; - buflen--; + buf[--buflen] = '/'; slash_prefixed = 1; } - if (error) { - SDT_PROBE(vfs, namecache, fullpath, return, error, startvp, - NULL, 0, 0); + if (error) return (error); - } if (!slash_prefixed) { - if (bp == buf) { - numfullpathfail4++; + if (buflen == 0) { CACHE_RUNLOCK(); + numfullpathfail4++; SDT_PROBE(vfs, namecache, fullpath, return, 0, - startvp, bp, 0, 0); + startvp, fullpath, 0, 0); return (ENOMEM); - } else - *--bp = '/'; + } + buf[--buflen] = '/'; } numfullpathfound++; CACHE_RUNLOCK(); - SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, bp, 0, 0); - *retbuf = bp; + SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, buf + *buflen, + 0, 0); + *retbuf = buf + buflen; return (0); } Modified: head/sys/sys/vnode.h ============================================================================== --- head/sys/sys/vnode.h Sun May 31 14:54:20 2009 (r193173) +++ head/sys/sys/vnode.h Sun May 31 14:57:43 2009 (r193174) @@ -598,6 +598,7 @@ int insmntque1(struct vnode *vp, struct int insmntque(struct vnode *vp, struct mount *mp); u_quad_t init_va_filerev(void); int speedup_syncer(void); +int vn_vptocnp(struct vnode **vp, char *buf, u_int *buflen); #define textvp_fullpath(p, rb, rfb) \ vn_fullpath(FIRST_THREAD_IN_PROC(p), (p)->p_textvp, rb, rfb) int vn_fullpath(struct thread *td, struct vnode *vn,