From owner-svn-src-head@FreeBSD.ORG Fri Dec 12 00:57:39 2008 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 5A1251065670; Fri, 12 Dec 2008 00:57:39 +0000 (UTC) (envelope-from marcus@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 490378FC12; Fri, 12 Dec 2008 00:57:39 +0000 (UTC) (envelope-from marcus@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 mBC0vd0C081653; Fri, 12 Dec 2008 00:57:39 GMT (envelope-from marcus@svn.freebsd.org) Received: (from marcus@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mBC0vdX7081650; Fri, 12 Dec 2008 00:57:39 GMT (envelope-from marcus@svn.freebsd.org) Message-Id: <200812120057.mBC0vdX7081650@svn.freebsd.org> From: Joe Marcus Clarke Date: Fri, 12 Dec 2008 00:57:39 +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: r185956 - head/sys/kern 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: Fri, 12 Dec 2008 00:57:39 -0000 Author: marcus (doc,ports committer) Date: Fri Dec 12 00:57:38 2008 New Revision: 185956 URL: http://svn.freebsd.org/changeset/base/185956 Log: Add a new VOP, VOP_VPTOCNP, which translates a vnode to its component name on a best-effort basis. Teach vn_fullpath to use this new VOP if a regular VFS cache lookup fails. This VOP is designed to supplement the VFS cache to provide a better chance that a vnode-to-name lookup will succeed. Currently, an implementation for devfs is being committed. The default implementation is to return ENOENT. A big thanks to kib for the mentorship on this, and to pho for running it through his stress test suite. Reviewed by: arch Approved by: kib Modified: head/sys/kern/vfs_cache.c head/sys/kern/vfs_default.c head/sys/kern/vnode_if.src Modified: head/sys/kern/vfs_cache.c ============================================================================== --- head/sys/kern/vfs_cache.c Fri Dec 12 00:56:00 2008 (r185955) +++ head/sys/kern/vfs_cache.c Fri Dec 12 00:57:38 2008 (r185956) @@ -169,6 +169,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_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, u_int buflen); @@ -840,6 +841,38 @@ vn_fullpath_global(struct thread *td, st return (error); } +static int +vn_vptocnp(struct vnode **vp, char **bp, char *buf, u_int *buflen) +{ + struct vnode *dvp; + int error, vfslocked; + + vhold(*vp); + CACHE_UNLOCK(); + vfslocked = VFS_LOCK_GIANT((*vp)->v_mount); + vn_lock(*vp, LK_SHARED | LK_RETRY); + vdrop(*vp); + error = VOP_VPTOCNP(*vp, &dvp, buf, buflen); + VOP_UNLOCK(*vp, 0); + VFS_UNLOCK_GIANT(vfslocked); + if (error) { + numfullpathfail2++; + return (error); + } + *bp = buf + *buflen; + *vp = dvp; + CACHE_LOCK(); + if ((*vp)->v_iflag & VI_DOOMED) { + /* forced unmount */ + CACHE_UNLOCK(); + vdrop(*vp); + return (ENOENT); + } + vdrop(*vp); + + return (0); +} + /* * The magic behind kern___getcwd() and vn_fullpath(). */ @@ -851,7 +884,8 @@ vn_fullpath1(struct thread *td, struct v int error, i, slash_prefixed; struct namecache *ncp; - bp = buf + buflen - 1; + buflen--; + bp = buf + buflen; *bp = '\0'; error = 0; slash_prefixed = 0; @@ -860,58 +894,77 @@ vn_fullpath1(struct thread *td, struct v numfullpathcalls++; if (vp->v_type != VDIR) { ncp = TAILQ_FIRST(&vp->v_cache_dst); - if (!ncp) { - numfullpathfail2++; - CACHE_UNLOCK(); - return (ENOENT); + if (ncp != NULL) { + for (i = ncp->nc_nlen - 1; i >= 0 && bp > buf; i--) + *--bp = ncp->nc_name[i]; + if (bp == buf) { + numfullpathfail4++; + CACHE_UNLOCK(); + return (ENOMEM); + } + vp = ncp->nc_dvp; + } else { + error = vn_vptocnp(&vp, &bp, buf, &buflen); + if (error) { + return (error); + } } - for (i = ncp->nc_nlen - 1; i >= 0 && bp > buf; i--) - *--bp = ncp->nc_name[i]; - if (bp == buf) { + *--bp = '/'; + buflen--; + if (buflen < 0) { numfullpathfail4++; CACHE_UNLOCK(); return (ENOMEM); } - *--bp = '/'; slash_prefixed = 1; - vp = ncp->nc_dvp; } while (vp != rdir && vp != rootvnode) { if (vp->v_vflag & VV_ROOT) { if (vp->v_iflag & VI_DOOMED) { /* forced unmount */ + CACHE_UNLOCK(); error = EBADF; break; } vp = vp->v_mount->mnt_vnodecovered; continue; } - if (vp->v_dd == NULL) { + if (vp->v_type != VDIR) { numfullpathfail1++; + CACHE_UNLOCK(); error = ENOTDIR; break; } ncp = TAILQ_FIRST(&vp->v_cache_dst); - if (!ncp) { - numfullpathfail2++; - error = ENOENT; - break; + if (ncp != NULL) { + MPASS(ncp->nc_dvp == vp->v_dd); + buflen -= ncp->nc_nlen - 1; + for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--) + *--bp = ncp->nc_name[i]; + if (bp == buf) { + numfullpathfail4++; + CACHE_UNLOCK(); + error = ENOMEM; + break; + } + vp = ncp->nc_dvp; + } else { + error = vn_vptocnp(&vp, &bp, buf, &buflen); + if (error) { + break; + } } - MPASS(ncp->nc_dvp == vp->v_dd); - for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--) - *--bp = ncp->nc_name[i]; - if (bp == buf) { + *--bp = '/'; + buflen--; + if (buflen < 0) { numfullpathfail4++; + CACHE_UNLOCK(); error = ENOMEM; break; } - *--bp = '/'; slash_prefixed = 1; - vp = ncp->nc_dvp; } - if (error) { - CACHE_UNLOCK(); + if (error) return (error); - } if (!slash_prefixed) { if (bp == buf) { numfullpathfail4++; Modified: head/sys/kern/vfs_default.c ============================================================================== --- head/sys/kern/vfs_default.c Fri Dec 12 00:56:00 2008 (r185955) +++ head/sys/kern/vfs_default.c Fri Dec 12 00:57:38 2008 (r185956) @@ -98,6 +98,7 @@ struct vop_vector default_vnodeops = { .vop_revoke = VOP_PANIC, .vop_strategy = vop_nostrategy, .vop_unlock = vop_stdunlock, + .vop_vptocnp = VOP_ENOENT, .vop_vptofh = vop_stdvptofh, }; @@ -138,6 +139,13 @@ vop_einval(struct vop_generic_args *ap) } int +vop_enoent(struct vop_generic_args *ap) +{ + + return (ENOENT); +} + +int vop_null(struct vop_generic_args *ap) { Modified: head/sys/kern/vnode_if.src ============================================================================== --- head/sys/kern/vnode_if.src Fri Dec 12 00:56:00 2008 (r185955) +++ head/sys/kern/vnode_if.src Fri Dec 12 00:57:38 2008 (r185956) @@ -595,3 +595,13 @@ vop_vptofh { IN struct vnode *vp; IN struct fid *fhp; }; + +%% vptocnp vp L L L +%% vptocnp vpp - U - + +vop_vptocnp { + IN struct vnode *vp; + OUT struct vnode **vpp; + INOUT char *buf; + INOUT int *buflen; +};