From owner-svn-src-projects@FreeBSD.ORG Wed Oct 23 17:18:55 2013 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 6D3ACCC6; Wed, 23 Oct 2013 17:18:55 +0000 (UTC) (envelope-from will@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4A8D82ED5; Wed, 23 Oct 2013 17:18:55 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9NHItqS065435; Wed, 23 Oct 2013 17:18:55 GMT (envelope-from will@svn.freebsd.org) Received: (from will@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9NHIso4065429; Wed, 23 Oct 2013 17:18:54 GMT (envelope-from will@svn.freebsd.org) Message-Id: <201310231718.r9NHIso4065429@svn.freebsd.org> From: Will Andrews Date: Wed, 23 Oct 2013 17:18:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r256993 - in projects/vps/sys: fs/vpsfs kern sys vps X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Oct 2013 17:18:55 -0000 Author: will Date: Wed Oct 23 17:18:53 2013 New Revision: 256993 URL: http://svnweb.freebsd.org/changeset/base/256993 Log: Sync with svn.7he.at/vps/trunk r194. r194 | klaus | 2013-07-26 13:49:49 -0600 (Fri, 26 Jul 2013) | 4 lines Added a failsafe vn_fullpath1() version, that still needs a little bit of work. Submitted by: Klaus P. Ohrhallinger Modified: projects/vps/sys/fs/vpsfs/vpsfs_quota.c projects/vps/sys/kern/vfs_cache.c projects/vps/sys/kern/vfs_default.c projects/vps/sys/sys/vnode.h projects/vps/sys/vps/vps_snapst.c projects/vps/sys/vps/vps_suspend.c Modified: projects/vps/sys/fs/vpsfs/vpsfs_quota.c ============================================================================== --- projects/vps/sys/fs/vpsfs/vpsfs_quota.c Wed Oct 23 17:17:57 2013 (r256992) +++ projects/vps/sys/fs/vpsfs/vpsfs_quota.c Wed Oct 23 17:18:53 2013 (r256993) @@ -67,10 +67,6 @@ static int vpsfs_readdir(struct thread * int dirbuflen, struct vpsfs_limits *, void (*cbfunc)(struct vnode *, struct vpsfs_limits *, struct thread *)); -static int get_next_dirent(struct vnode *vp, struct dirent **dpp, - char *dirbuf, int dirbuflen, off_t *off, char **cpos, int *len, - int *eofflag, struct thread *td); - static void vpsfs_calcvnode(struct vnode *vp, struct vpsfs_limits *limits, struct thread *td); @@ -610,63 +606,6 @@ vpsfs_readdir(struct thread *td, struct return (error); } -/* copied from kern/vfs_default.c */ -static int -get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, - int dirbuflen, off_t *off, char **cpos, int *len, - int *eofflag, struct thread *td) -{ - int error, reclen; - struct uio uio; - struct iovec iov; - struct dirent *dp; - - KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); - KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); - - if (*len == 0) { - iov.iov_base = dirbuf; - iov.iov_len = dirbuflen; - - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = *off; - uio.uio_resid = dirbuflen; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_td = td; - - *eofflag = 0; - -#ifdef MAC - error = mac_vnode_check_readdir(td->td_ucred, vp); - if (error == 0) -#endif - error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag, - NULL, NULL); - if (error) - return (error); - - *off = uio.uio_offset; - - *cpos = dirbuf; - *len = (dirbuflen - uio.uio_resid); - } - - dp = (struct dirent *)(*cpos); - reclen = dp->d_reclen; - *dpp = dp; - - /* check for malformed directory.. */ - if (reclen < DIRENT_MINSIZE) - return (EINVAL); - - *cpos += reclen; - *len -= reclen; - - return (0); -} - #endif /* VPS */ /* EOF */ Modified: projects/vps/sys/kern/vfs_cache.c ============================================================================== --- projects/vps/sys/kern/vfs_cache.c Wed Oct 23 17:17:57 2013 (r256992) +++ projects/vps/sys/kern/vfs_cache.c Wed Oct 23 17:18:53 2013 (r256993) @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -309,13 +310,8 @@ SYSCTL_OPAQUE(_vfs_cache, OID_AUTO, nchs static void cache_zap(struct namecache *ncp); static int vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, char *buf, u_int *buflen); -#ifdef VPS -int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, - char *buf, char **retbuf, u_int buflen); -#else static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, u_int buflen); -#endif static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries"); @@ -1269,11 +1265,7 @@ vn_vptocnp_locked(struct vnode **vp, str /* * The magic behind kern___getcwd() and vn_fullpath(). */ -#ifdef VPS -int -#else static int -#endif vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, u_int buflen) { @@ -1368,6 +1360,357 @@ vn_fullpath1(struct thread *td, struct v return (0); } + +/* ----------------------------------------------------------- */ + +/* + XXX lookup for /dev/console doesn't work, altough td->td_vps and + td->td_ucred->cr_vps are right. + XXX for this failure no error is returned + XXX limit recursion depth !!! + */ + +/* + * Search a directory for a given inode number, recursing into + * subdirectories. + */ +static int +vn_fullpath1_findparentdir_recurse(struct vnode *dvp, struct ucred *cred, + int inodenum, struct vnode **retvp) +{ + struct componentname cnp; + struct dirent *dp; + struct vnode *vp; + char *dirbuf; + char *cpos; + off_t off; + int dirbuflen; + int eofflag; + int error; + int len; + + dirbuflen = PATH_MAX; + dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK); + + cpos = NULL; + off = 0; + len = 0; + + do { + error = get_next_dirent(dvp, &dp, dirbuf, dirbuflen, + &off, &cpos, &len, &eofflag, curthread); + if (error != 0) + goto out; + + if (!strcmp(dp->d_name, ".") || + !strcmp(dp->d_name, "..") || + dp->d_fileno == 0) + continue; + + cnp.cn_pnbuf = NULL; + cnp.cn_consume = 0; + cnp.cn_nameptr = dp->d_name; + cnp.cn_namelen = strlen(dp->d_name); + cnp.cn_lkflags = LK_SHARED | LK_RETRY; + cnp.cn_thread = curthread; + cnp.cn_cred = cred; + error = VOP_LOOKUP(dvp, &vp, &cnp); + if (error != 0) + goto out; + + if (dp->d_fileno == inodenum) { + *retvp = dvp; + vunref(vp); + VOP_UNLOCK(vp, 0); + error = 0; + goto out; + } + + if (vp->v_type == VDIR) { + error = vn_fullpath1_findparentdir_recurse(vp, cred, + inodenum, retvp); + if (error != ENOENT) { + vunref(vp); + VOP_UNLOCK(vp, 0); + error = 0; + goto out; + } + } + + vunref(vp); + VOP_UNLOCK(vp, 0); + + } while (len > 0 || !eofflag); + + error = ENOENT; + + out: + free(dirbuf, M_TEMP); + + return (error); +} + +/* + * Search through the filesystem that owns 'vp' for (one of) its + * parent directories. + */ +static int +vn_fullpath1_findparentdir(struct vnode *vp, struct ucred *cred, + struct vnode **outvp) +{ + struct vattr vattr; + struct vnode *rootvp; + struct vnode *dvp; + int error; + + if (VOP_ISLOCKED(vp) == 0) + vn_lock(vp, LK_SHARED | LK_RETRY); + + /* Get inode number of file. */ + error = VOP_GETATTR(vp, &vattr, cred); + VOP_UNLOCK(vp, 0); + if (error != 0) + return (error); + + error = VFS_ROOT(vp->v_mount, LK_EXCLUSIVE | LK_RETRY, &rootvp); + if (error != 0) + return (error); + + error = vn_fullpath1_findparentdir_recurse(rootvp, cred, + vattr.va_fileid, &dvp); + if (error == 0) + *outvp = dvp; + + vunref(rootvp); + VOP_UNLOCK(rootvp, 0); + + return (error); +} + +static int +vn_fullpath1_fallback(struct thread *td, struct vnode *vp, + struct vnode *rdir, char *buf, char **retbuf, u_int buflen) +{ + struct componentname cnp; + struct vattr vattr; + struct vnode *dvp2; + struct vnode *dvp; + struct dirent *dp; + char *dirbuf; + char *cpos; + off_t off; + int dirbuflen; + int inodenum; + int eofflag; + int error; + int len; + + dirbuflen = PATH_MAX; + dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK); + + buflen -= 1; + buf[buflen] = 0; + + if (vp->v_type == VDIR) { + dvp = vp; + + if (VOP_ISLOCKED(dvp) == 0) + vn_lock(dvp, LK_SHARED | LK_RETRY); + + } else { + char buf2[MAXPATHLEN]; + int buflen2; + + /* Get the parent directory. */ + + buflen2 = sizeof(buf2); + memset(buf2, 0, sizeof(buf2)); + + /* + * Since this step is the most expensive one, + * try the namecache for this one. + */ + vref(vp); + CACHE_RLOCK(); + error = vn_vptocnp_locked(&vp, td->td_ucred, buf2, &buflen2); + if (error == 0) + CACHE_RUNLOCK(); + vrele(vp); + dvp = vp; + /* + // debugging + dvp = NULL; + error = ENOENT; + */ + + if (error == 0) { + buflen -= sizeof(buf2)-buflen2; + memcpy(buf+buflen, buf2+buflen2, sizeof(buf2)-buflen2); + + } else { + /* Do it the *expensive* way. */ + + printf("%s: WARNING: looking up by " + "vn_fullpath1_findparentdir(vp=%p, ...)\n", + __func__, vp); + error = vn_fullpath1_findparentdir(vp, td->td_ucred, &dvp); + if (error != 0) + goto out; + + vn_lock(dvp, LK_SHARED | LK_RETRY); + + /* Get inode number of file. */ + if (VOP_ISLOCKED(vp) == 0) + vn_lock(vp, LK_SHARED | LK_RETRY); + error = VOP_GETATTR(vp, &vattr, td->td_ucred); + VOP_UNLOCK(vp, 0); + if (error != 0) { + VOP_UNLOCK(dvp, 0); + goto out; + } + inodenum = vattr.va_fileid; + + /* Now we know the parent directory so search it for the file. */ + cpos = NULL; + off = 0; + len = 0; + error = ENOENT; + + do { + error = get_next_dirent(dvp, &dp, dirbuf, dirbuflen, + &off, &cpos, &len, &eofflag, td); + if (error != 0) { + VOP_UNLOCK(dvp, 0); + goto out; + } + + if (dp->d_fileno == inodenum) { + /* Found it ! */ + if (buflen < strlen(dp->d_name)) { + error = ENOMEM; + VOP_UNLOCK(dvp, 0); + goto out; + } + buflen -= strlen(dp->d_name); + memcpy(buf+buflen, dp->d_name, strlen(dp->d_name)); + error = 0; + break; + } + error = ENOENT; + } while (len > 0 || !eofflag); + + if (error != 0) { + printf("%s: line %d\n", __func__, __LINE__); + VOP_UNLOCK(dvp, 0); + goto out; + } + } + + } + + for (;;) { + + /* Separate component names with '/'. */ + if (buflen < 1) { + error = ENOMEM; + VOP_UNLOCK(dvp, 0); + goto out; + } + buflen -= 1; + memcpy(buf+buflen, "/", 1); + *retbuf = buf+buflen; + + if (dvp == rdir) { + /* Reached (relative) root directory. */ + VOP_UNLOCK(dvp, 0); + break; + } + + if (dvp->v_vflag & VV_ROOT) { + /* Crossing filesystems. */ + dvp2 = dvp->v_mount->mnt_vnodecovered; + VOP_UNLOCK(dvp, 0); + vn_lock(dvp2, LK_SHARED | LK_RETRY); + dvp = dvp2; + } + + /* Get inode number of directory. */ + error = VOP_GETATTR(dvp, &vattr, td->td_ucred); + if (error != 0) { + VOP_UNLOCK(dvp, 0); + goto out; + } + inodenum = vattr.va_fileid; + + /* Lookup "..". */ + cnp.cn_pnbuf = NULL; + cnp.cn_consume = 0; + cnp.cn_nameptr = ".."; + cnp.cn_namelen = 2; + cnp.cn_lkflags = LK_SHARED; + cnp.cn_thread = curthread; + cnp.cn_cred = td->td_ucred; + error = VOP_LOOKUP(dvp, &dvp2, &cnp); + if (error != 0) { + VOP_UNLOCK(dvp, 0); + goto out; + } + + vunref(dvp2); + VOP_UNLOCK(dvp, 0); + dvp = dvp2; + + cpos = NULL; + off = 0; + len = 0; + error = ENOENT; + + do { + error = get_next_dirent(dvp2, &dp, dirbuf, dirbuflen, + &off, &cpos, &len, &eofflag, td); + if (error != 0) { + VOP_UNLOCK(dvp2, 0); + goto out; + } + + if (dp->d_fileno == inodenum) { + /* Found it ! */ + if (buflen < strlen(dp->d_name)) { + error = ENOMEM; + VOP_UNLOCK(dvp2, 0); + goto out; + } + buflen -= strlen(dp->d_name); + memcpy(buf+buflen, dp->d_name, strlen(dp->d_name)); + break; + } + error = ENOENT; + } while (len > 0 || !eofflag); + } + + out: + free(dirbuf, M_TEMP); + + return (error); +} + +int +vn_fullpath1_failsafe(struct thread *td, struct vnode *vp, + struct vnode *rdir, char *buf, char **retbuf, u_int buflen) +{ + int error; + + error = vn_fullpath1(td, vp, rdir, buf, retbuf, buflen); + if (error != ENOENT) + return (error); + + error = vn_fullpath1_fallback(td, vp, rdir, buf, retbuf, buflen); + + return (error); +} + +/* ----------------------------------------------------------- */ + struct vnode * vn_dir_dd_ino(struct vnode *vp) { Modified: projects/vps/sys/kern/vfs_default.c ============================================================================== --- projects/vps/sys/kern/vfs_default.c Wed Oct 23 17:17:57 2013 (r256992) +++ projects/vps/sys/kern/vfs_default.c Wed Oct 23 17:18:53 2013 (r256993) @@ -69,10 +69,6 @@ __FBSDID("$FreeBSD$"); static int vop_nolookup(struct vop_lookup_args *); static int vop_norename(struct vop_rename_args *); static int vop_nostrategy(struct vop_strategy_args *); -static int get_next_dirent(struct vnode *vp, struct dirent **dpp, - char *dirbuf, int dirbuflen, off_t *off, - char **cpos, int *len, int *eofflag, - struct thread *td); static int dirent_exists(struct vnode *vp, const char *dirname, struct thread *td); @@ -261,7 +257,7 @@ vop_nostrategy (struct vop_strategy_args return (EOPNOTSUPP); } -static int +int get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, int dirbuflen, off_t *off, char **cpos, int *len, int *eofflag, struct thread *td) Modified: projects/vps/sys/sys/vnode.h ============================================================================== --- projects/vps/sys/sys/vnode.h Wed Oct 23 17:17:57 2013 (r256992) +++ projects/vps/sys/sys/vnode.h Wed Oct 23 17:18:53 2013 (r256993) @@ -577,6 +577,7 @@ vn_canvmio(struct vnode *vp) * Public vnode manipulation functions. */ struct componentname; +struct dirent; struct file; struct mount; struct nameidata; @@ -609,6 +610,10 @@ int getnewvnode(const char *tag, struct struct vnode **vpp); void getnewvnode_reserve(u_int count); void getnewvnode_drop_reserve(void); +int get_next_dirent(struct vnode *vp, struct dirent **dpp, + char *dirbuf, int dirbuflen, off_t *off, + char **cpos, int *len, int *eofflag, + struct thread *td); int insmntque1(struct vnode *vp, struct mount *mp, void (*dtr)(struct vnode *, void *), void *dtr_arg); int insmntque(struct vnode *vp, struct mount *mp); @@ -659,6 +664,8 @@ int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td); void vn_finished_write(struct mount *mp); void vn_finished_secondary_write(struct mount *mp); +int vn_fullpath1_failsafe(struct thread *td, struct vnode *vp, + struct vnode *rdir, char *buf, char **retbuf, u_int buflen); int vn_isdisk(struct vnode *vp, int *errp); int _vn_lock(struct vnode *vp, int flags, char *file, int line); #define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__) Modified: projects/vps/sys/vps/vps_snapst.c ============================================================================== --- projects/vps/sys/vps/vps_snapst.c Wed Oct 23 17:17:57 2013 (r256992) +++ projects/vps/sys/vps/vps_snapst.c Wed Oct 23 17:18:53 2013 (r256993) @@ -656,6 +656,11 @@ vps_snapshot_vnodepath(struct vps_snapst { struct vps_dumpobj *o1; struct vps_dump_filepath *vdfp; + /* + struct ucred *save_ucred; + struct vps *save_vps; + struct thread *td; + */ char *retbuf, *buf; int error; @@ -671,9 +676,29 @@ vps_snapshot_vnodepath(struct vps_snapst vrele(vp); return (ENOMEM); } + +#if 0 +// not yet ... for devfs lookups + td = curthread; + save_ucred = td->td_ucred; + save_vps = td->td_vps; + td->td_ucred = crdup(save_ucred); + vps_deref(td->td_ucred->cr_vps, td->td_ucred); + td->td_ucred->cr_vps = vps; + vps_ref(td->td_ucred->cr_vps, td->td_ucred); + td->td_vps = vps; +#endif + retbuf = "-"; - error = vn_fullpath1(curthread, vp, vps->_rootvnode, + error = vn_fullpath1_failsafe(curthread, vp, vps->_rootvnode, buf, &retbuf, MAXPATHLEN); + +#if 0 + crfree(td->td_ucred); + td->td_ucred = save_ucred; + td->td_vps = save_vps; +#endif + if (error != 0) { free(buf, M_TEMP); vrele(vp); Modified: projects/vps/sys/vps/vps_suspend.c ============================================================================== --- projects/vps/sys/vps/vps_suspend.c Wed Oct 23 17:17:57 2013 (r256992) +++ projects/vps/sys/vps/vps_suspend.c Wed Oct 23 17:18:53 2013 (r256993) @@ -118,9 +118,6 @@ static int vps_access_vmspace(struct vms size_t len, void *buf, int prot); static int vps_resume_relinkvnodes(struct vps *vps); -static int get_next_dirent(struct vnode *vp, struct dirent **dpp, - char *dirbuf, int dirbuflen, off_t *off, char **cpos, - int *len, int *eofflag, struct thread *td); static int vps_suspend_relink_delete(struct vnode *vp); static int vps_suspend_mod_refcnt; @@ -981,65 +978,6 @@ vps_suspend_relink_delete(struct vnode * return (error); } -#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) - -/* copied from kern/vfs_default.c */ -static int -get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, - int dirbuflen, off_t *off, char **cpos, int *len, - int *eofflag, struct thread *td) -{ - int error, reclen; - struct uio uio; - struct iovec iov; - struct dirent *dp; - - KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); - KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); - - if (*len == 0) { - iov.iov_base = dirbuf; - iov.iov_len = dirbuflen; - - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = *off; - uio.uio_resid = dirbuflen; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_td = td; - - *eofflag = 0; - -#ifdef MAC - error = mac_vnode_check_readdir(td->td_ucred, vp); - if (error == 0) -#endif - error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag, - NULL, NULL); - if (error) - return (error); - - *off = uio.uio_offset; - - *cpos = dirbuf; - *len = (dirbuflen - uio.uio_resid); - } - - dp = (struct dirent *)(*cpos); - reclen = dp->d_reclen; - *dpp = dp; - - /* check for malformed directory.. */ - if (reclen < DIRENT_MINSIZE) - return (EINVAL); - - *cpos += reclen; - *len -= reclen; - - return (0); -} - static int vps_suspend_modevent(module_t mod, int type, void *data) {