cache_fullpath - Guess mountpoints if requested
authorAlex Hornung <ahornung@gmail.com>
Wed, 24 Mar 2010 20:24:05 +0000 (20:24 +0000)
committerAlex Hornung <ahornung@gmail.com>
Wed, 24 Mar 2010 20:30:26 +0000 (20:30 +0000)
* cache_fullpath (and vn_fullpath) now take an extra parameter, guess,
  which, if != 0, makes cache_fullpath look for a matching mp if an ncp
  flagged as a mountpoint is found while traversing upwards.
  This fixes uses of *_fullpath when no nch is provided, but only a vp.

* Change all consumers of cache_fullpath and vn_fullpath to accomodate
  for the extra parameter.

Suggested-by: Matthew Dillon
13 files changed:
sys/dev/disk/vn/vn.c
sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c
sys/kern/imgact_elf.c
sys/kern/imgact_resident.c
sys/kern/kern_jail.c
sys/kern/vfs_cache.c
sys/kern/vfs_mount.c
sys/kern/vfs_syscalls.c
sys/sys/mount.h
sys/sys/namecache.h
sys/sys/vnode.h
sys/vfs/isofs/cd9660/cd9660_rrip.c
sys/vfs/procfs/procfs_vnops.c

index 9c3f50e..95bcf44 100644 (file)
@@ -792,7 +792,7 @@ vnget(cdev_t dev, struct vn_softc *vn, struct vn_user *vnu)
                        }
 
                        error = vn_fullpath(curproc, vn->sc_vp,
-                                               &fullpath, &freepath);
+                                               &fullpath, &freepath, 0);
 
                        if (error) {
                                kprintf("vnget: unable to resolve vp %p\n",
index 8f06b90..0314698 100644 (file)
@@ -509,7 +509,7 @@ linprocfs_getattr(struct vop_getattr_args *ap)
 
        case Pexe: {
                char *fullpath, *freepath;
-               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath);
+               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0);
                /* error = vn_fullpath(procp, NULL, &fullpath, &freepath); */
                if (error == 0) {
                        vap->va_size = strlen(fullpath);
@@ -523,7 +523,7 @@ linprocfs_getattr(struct vop_getattr_args *ap)
        }
        case Pcwd: {
                char *fullpath, *freepath;
-               error = cache_fullpath(procp, &procp->p_fd->fd_ncdir, &fullpath, &freepath);
+               error = cache_fullpath(procp, &procp->p_fd->fd_ncdir, &fullpath, &freepath, 0);
                if (error == 0) {
                        vap->va_size = strlen(fullpath);
                        kfree(freepath, M_TEMP);
@@ -538,7 +538,7 @@ linprocfs_getattr(struct vop_getattr_args *ap)
                struct nchandle *nchp;
                char *fullpath, *freepath;
                nchp = jailed(procp->p_ucred) ? &procp->p_fd->fd_njdir : &procp->p_fd->fd_nrdir;
-               error = cache_fullpath(procp, nchp, &fullpath, &freepath);
+               error = cache_fullpath(procp, nchp, &fullpath, &freepath, 0);
                if (error == 0) {
                        vap->va_size = strlen(fullpath);
                        kfree(freepath, M_TEMP);
@@ -1492,7 +1492,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));
                }
-               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath);
+               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0);
                if (error != 0)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));
@@ -1507,7 +1507,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));
                }
-               error = cache_fullpath(procp, &procp->p_fd->fd_ncdir, &fullpath, &freepath);
+               error = cache_fullpath(procp, &procp->p_fd->fd_ncdir, &fullpath, &freepath, 0);
                if (error != 0)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));
@@ -1523,7 +1523,7 @@ linprocfs_readlink(struct vop_readlink_args *ap)
                            ap->a_uio));
                }
                nchp = jailed(procp->p_ucred) ? &procp->p_fd->fd_njdir : &procp->p_fd->fd_nrdir;
-               error = cache_fullpath(procp, nchp, &fullpath, &freepath);
+               error = cache_fullpath(procp, nchp, &fullpath, &freepath, 0);
                if (error != 0)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));
index c51f034..9a20056 100644 (file)
@@ -1177,7 +1177,7 @@ cb_put_fp(vm_map_entry_t entry, void *closure)
                if (error) {
                        char *freepath, *fullpath;
 
-                       if (vn_fullpath(curproc, vp, &fullpath, &freepath)) {
+                       if (vn_fullpath(curproc, vp, &fullpath, &freepath, 0)) {
                                kprintf("Warning: coredump, error %d: cannot store file handle for vnode %p\n", error, vp);
                        } else {
                                kprintf("Warning: coredump, error %d: cannot store file handle for %s\n", error, fullpath);
index a1c27d1..f08259f 100644 (file)
@@ -94,7 +94,7 @@ fill_xresident(struct vmresident *vr, struct xresident *in, struct thread *td)
        in->res_id = vr->vr_id;
        if (vrtmp) {
                char *freepath, *fullpath;
-               error = vn_fullpath(td->td_proc, vrtmp, &fullpath, &freepath);
+               error = vn_fullpath(td->td_proc, vrtmp, &fullpath, &freepath, 0);
                if (error != 0) {
                        /* could not retrieve cached path, return zero'ed string */
                        bzero(in->res_file, MAXPATHLEN);
index 6c61867..cfe2641 100644 (file)
@@ -586,7 +586,7 @@ retry:
 
        LIST_FOREACH(pr, &allprison, pr_list) {
                error = cache_fullpath(lp->lwp_proc, &pr->pr_root,
-                                       &fullpath, &freepath);
+                                       &fullpath, &freepath, 0);
                if (error)
                        continue;
                if (jlsused && jlsused < jlssize)
index 08b58df..e700ce2 100644 (file)
@@ -3098,12 +3098,12 @@ STATNODE(numfullpathfound);
 
 int
 cache_fullpath(struct proc *p, struct nchandle *nchp,
-              char **retbuf, char **freebuf)
+              char **retbuf, char **freebuf, int guess)
 {
        struct nchandle fd_nrdir;
        struct nchandle nch;
        struct namecache *ncp;
-       struct mount *mp;
+       struct mount *mp, *new_mp;
        char *bp, *buf;
        int slash_prefixed;
        int error = 0;
@@ -3129,12 +3129,26 @@ cache_fullpath(struct proc *p, struct nchandle *nchp,
        mp = nch.mount;
 
        while (ncp && (ncp != fd_nrdir.ncp || mp != fd_nrdir.mount)) {
+               new_mp = NULL;
+
+               /*
+                * If we are asked to guess the upwards path, we do so whenever
+                * we encounter an ncp marked as a mountpoint. We try to find
+                * the actual mountpoint by finding the mountpoint with this ncp.
+                */
+               if (guess && (ncp->nc_flag & NCF_ISMOUNTPT)) {
+                       new_mp = mount_get_by_nc(ncp);
+               }
                /*
                 * While traversing upwards if we encounter the root
                 * of the current mount we have to skip to the mount point.
                 */
                if (ncp == mp->mnt_ncmountpt.ncp) {
-                       nch = mp->mnt_ncmounton;
+                       new_mp = mp;
+               }
+               if (new_mp) {
+                       kprintf("bump. switch mountpoint.\n");
+                       nch = new_mp->mnt_ncmounton;
                        _cache_drop(ncp);
                        ncp = nch.ncp;
                        if (ncp)
@@ -3210,7 +3224,7 @@ done:
 }
 
 int
-vn_fullpath(struct proc *p, struct vnode *vn, char **retbuf, char **freebuf) 
+vn_fullpath(struct proc *p, struct vnode *vn, char **retbuf, char **freebuf, int guess
 {
        struct namecache *ncp;
        struct nchandle nch;
@@ -3243,7 +3257,7 @@ vn_fullpath(struct proc *p, struct vnode *vn, char **retbuf, char **freebuf)
        atomic_add_int(&numfullpathcalls, -1);
        nch.ncp = ncp;;
        nch.mount = vn->v_mount;
-       error = cache_fullpath(p, &nch, retbuf, freebuf);
+       error = cache_fullpath(p, &nch, retbuf, freebuf, guess);
        _cache_drop(ncp);
        return (error);
 }
index 99d6e99..3e1dd00 100644 (file)
@@ -1316,3 +1316,21 @@ bio_ops_sync(struct mount *mp)
        }
 }
 
+/*
+ * Lookup a mount point by nch
+ */
+struct mount *
+mount_get_by_nc(struct namecache *ncp)
+{
+       struct mount *mp = NULL;
+       lwkt_tokref ilock;
+
+       lwkt_gettoken(&ilock, &mountlist_token);
+       TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+               if (ncp == mp->mnt_ncmountpt.ncp)
+                       break;
+       }
+       lwkt_reltoken(&ilock);
+       return (mp);
+}
+
index 56dc082..1243999 100644 (file)
@@ -798,7 +798,7 @@ mount_warning(struct mount *mp, const char *ctl, ...)
        __va_list va;
 
        __va_start(va, ctl);
-       if (cache_fullpath(NULL, &mp->mnt_ncmounton, &ptr, &buf) == 0) {
+       if (cache_fullpath(NULL, &mp->mnt_ncmounton, &ptr, &buf, 0) == 0) {
                kprintf("unmount(%s): ", ptr);
                kvprintf(ctl, va);
                kprintf("\n");
@@ -831,7 +831,7 @@ mount_path(struct proc *p, struct mount *mp, char **rb, char **fb)
                nch = &p->p_fd->fd_nrdir;
        else
                nch = &mp->mnt_ncmountpt;
-       return(cache_fullpath(p, nch, rb, fb));
+       return(cache_fullpath(p, nch, rb, fb, 0));
 }
 
 /*
index 1a41e16..b9339af 100644 (file)
@@ -689,7 +689,7 @@ int mountlist_interlock(int (*callback)(struct mount *), struct mount *);
 struct mount *mountlist_boot_getfirst(void);
 void   mountlist_remove(struct mount *mp);
 int    mountlist_scan(int (*callback)(struct mount *, void *), void *, int);
-
+struct mount *mount_get_by_nc(struct namecache *ncp);
 #else /* !_KERNEL */
 
 #include <sys/cdefs.h>
index c50e924..4df15f9 100644 (file)
@@ -255,7 +255,7 @@ void        cache_rename(struct nchandle *fnch, struct nchandle *tnch);
 int    cache_vget(struct nchandle *, struct ucred *, int, struct vnode **);
 int    cache_vref(struct nchandle *, struct ucred *, struct vnode **);
 int    cache_fromdvp(struct vnode *, struct ucred *, int, struct nchandle *);
-int    cache_fullpath(struct proc *, struct nchandle *, char **, char **);
+int    cache_fullpath(struct proc *, struct nchandle *, char **, char **, int);
 
 #endif
 
index 87615dd..c3ac1dc 100644 (file)
@@ -534,7 +534,7 @@ int debug_vn_lock (struct vnode *vp, int flags,
 
 int    vn_get_namelen(struct vnode *, int *);
 void   vn_setspecops (struct file *fp);
-int    vn_fullpath (struct proc *p, struct vnode *vn, char **retbuf, char **freebuf);
+int    vn_fullpath (struct proc *p, struct vnode *vn, char **retbuf, char **freebuf, int guess);
 int    vn_open (struct nlookupdata *ndp, struct file *fp, int fmode, int cmode);
 int    vn_opendisk (const char *devname, int fmode, struct vnode **vpp);
 void   vn_pollevent (struct vnode *vp, int events);
index 2f850ef..d3b9f13 100644 (file)
@@ -175,7 +175,7 @@ cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana)
                        outbuf -= len;
                        len = 0;
                        error = cache_fullpath(NULL, &ana->imp->im_mountp->mnt_ncmountpt,
-                                              &inbuf, &freebuf);
+                                              &inbuf, &freebuf, 0);
                        if (error)
                                goto bad;
                        wlen = strlen(inbuf);
index ad8eb3a..581f489 100644 (file)
@@ -579,7 +579,7 @@ procfs_getattr(struct vop_getattr_args *ap)
 
        case Pfile: {
                char *fullpath, *freepath;
-               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath);
+               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0);
                if (error == 0) {
                        vap->va_size = strlen(fullpath);
                        kfree(freepath, M_TEMP);
@@ -1040,7 +1040,7 @@ procfs_readlink(struct vop_readlink_args *ap)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));
                }
-               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath);
+               error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0);
                if (error != 0)
                        return (uiomove("unknown", sizeof("unknown") - 1,
                            ap->a_uio));