diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4 index 07419894ccea..6c0d1c1cfdf8 100644 --- a/share/man/man4/ddb.4 +++ b/share/man/man4/ddb.4 @@ -60,7 +60,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 24, 2017 +.Dd June 20, 2018 .Dt DDB 4 .Os .Sh NAME @@ -1124,6 +1124,11 @@ Shows clean/dirty buffer lists of the vnode located at .Ar addr . .\" .Pp +.It Ic show Cm vpath Ar addr +Walk the namecache to lookup the pathname of the vnode located at +.Ar addr . +.\" +.Pp .It Ic show Cm watches Displays all watchpoints. Shows watchpoints set with "watch" command. diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 475ae0caa2e1..627e9d0c7a8d 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -37,6 +37,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ddb.h" #include "opt_ktrace.h" #include @@ -62,6 +63,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef DDB +#include +#endif + #include SDT_PROVIDER_DECLARE(vfs); @@ -2529,3 +2534,54 @@ vn_path_to_global_path(struct thread *td, struct vnode *vp, char *path, free(fbuf, M_TEMP); return (error); } + +#ifdef DDB +static void +db_print_vpath(struct vnode *vp) +{ + + while (vp != NULL) { + db_printf("%p: ", vp); + if (vp == rootvnode) { + db_printf("/"); + vp = NULL; + } else { + if (vp->v_vflag & VV_ROOT) { + db_printf(""); + vp = vp->v_mount->mnt_vnodecovered; + } else { + struct namecache *ncp; + char *ncn; + int i; + + ncp = TAILQ_FIRST(&vp->v_cache_dst); + if (ncp != NULL) { + ncn = ncp->nc_name; + for (i = 0; i < ncp->nc_nlen; i++) + db_printf("%c", *ncn++); + vp = ncp->nc_dvp; + } else { + vp = NULL; + } + } + } + db_printf("\n"); + } + + return; +} + +DB_SHOW_COMMAND(vpath, db_show_vpath) +{ + struct vnode *vp; + + if (!have_addr) { + db_printf("usage: show vpath \n"); + return; + } + + vp = (struct vnode *)addr; + db_print_vpath(vp); +} + +#endif