vfs.c revision 150d2c5288c645a1c1a7d2bee61199a3729406c7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <mdb/mdb_modapi.h>
#include <sys/socketvar.h>
int
{
mdb_warn("failed to read 'rootvfs'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
}
return (WALK_DONE);
return (status);
}
/*
* Utility routine to read in a filesystem name given a vfs pointer. If
* no vfssw entry for the vfs is available (as is the case with some pseudo-
* filesystems), we check against some known problem fs's: doorfs and
* portfs. If that fails, we try to guess the filesystem name using
* symbol names. fsname should be a buffer of size _ST_FSTYPSZ.
*/
static int
{
struct vfssw vfssw_entry;
char testname[MDB_SYM_NAMLEN];
return (-1);
}
mdb_warn("failed to find vfssw");
return (-1);
}
/*
* vfssw is an array; we need vfssw[vfs.vfs_fstype].
*/
== -1) {
return (-1);
}
if (vfs.vfs_fstype != 0) {
mdb_warn("failed to find fs name %p",
return (-1);
}
return (0);
}
/*
* Do precise detection for certain filesystem types that we
* know do not appear in vfssw[], and that we depend upon in other
* parts of the code: doorfs and portfs.
*/
return (0);
}
}
return (0);
}
}
/*
* Heuristic detection for other filesystems that don't have a
* vfssw[] entry. These tend to be named <fsname>_vfs, so we do a
* lookup_by_addr and see if we find a symbol of that name.
*/
&test_sym) != -1) {
return (0);
}
}
return (-1);
}
/*
* Column widths for mount point display in ::fsinfo output.
*/
#ifdef _LP64
#define FSINFO_MNTLEN 48
#else
#define FSINFO_MNTLEN 56
#endif
/*ARGSUSED*/
int
{
int len;
int opt_v = 0;
char buf[MAXPATHLEN];
char fsname[_ST_FSTYPSZ];
int i;
int first = 1;
char opt[MAX_MNTOPT_STR];
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk file system list");
return (DCMD_ERR);
}
return (DCMD_OK);
}
return (DCMD_USAGE);
if (DCMD_HDRSPEC(flags))
mdb_printf("%<u>%?s %-15s %s%</u>\n",
"VFSP", "FS", "MOUNT");
return (DCMD_ERR);
}
sizeof (buf))) <= 0)
/*
* In normal mode, we truncate the path to keep the output
* clean. In -v mode, we just print the full path.
*/
return (DCMD_ERR);
if (!opt_v)
return (DCMD_OK);
/*
* Print 'resource' string; this shows what we're mounted upon.
*/
MAXPATHLEN) <= 0)
/*
* Print mount options array; it sucks to be a mimic, but we copy
* the same logic as in mntvnops.c for adding zone= tags, and we
* don't bother with the obsolete dev= option.
*/
return (DCMD_ERR);
}
mdb_warn("failed to read mntopt name %p",
return (DCMD_ERR);
}
if (first) {
first = 0;
} else {
mdb_printf(",");
}
mdb_warn("failed to read mntopt "
return (DCMD_ERR);
}
}
}
}
mdb_warn("failed to locate global_zone");
return (DCMD_ERR);
}
zone_t z;
mdb_warn("failed to read zone");
return (DCMD_ERR);
}
/*
* zone names are much shorter than MAX_MNTOPT_STR
*/
mdb_warn("failed to read zone name");
return (DCMD_ERR);
}
if (first) {
} else {
mdb_printf(",");
}
}
return (DCMD_OK);
}
#define REALVP_DONE 0
#define REALVP_ERR 1
#define REALVP_CONTINUE 2
static int
{
char fsname[_ST_FSTYPSZ];
return (REALVP_ERR);
}
return (REALVP_ERR);
/*
* We know how to do 'realvp' for as many filesystems as possible;
* for all other filesystems, we assume that the vp we are given
* is the realvp. In the kernel, a realvp operation will sometimes
* dig through multiple layers. Here, we only fetch the pointer
* to the next layer down. This allows dcmds to print out the
* various layers.
*/
mdb_warn("failed to read fifonode");
return (REALVP_ERR);
}
mdb_warn("failed to read namenode");
return (REALVP_ERR);
}
/*
* Sockets have a strange and different layering scheme; we
* hop over into the sockfs vnode (accessible via the stream
* head) if possible.
*/
mdb_warn("failed to read stream data");
return (REALVP_ERR);
}
}
return (REALVP_DONE);
return (REALVP_CONTINUE);
}
static void
{
struct sockaddr_in *s_in;
struct sockaddr_un *s_un;
struct sockaddr_in6 *s_in6;
case AF_INET:
/*LINTED: alignment*/
break;
case AF_INET6:
/*LINTED: alignment*/
break;
case AF_UNIX:
break;
default:
break;
}
}
static int
{
vnode_t v;
mdb_warn("failed to read socket vnode");
return (-1);
}
mdb_warn("failed to read stream data");
return (-1);
}
mdb_warn("failed to read stream vnode");
return (-1);
}
mdb_warn("failed to read sonode");
return (-1);
}
return (0);
}
/*
* Do some digging to get a reasonable pathname for this vnode. 'path'
* should point at a buffer of MAXPATHLEN in size.
*/
static int
{
vnode_t v;
mdb_warn("failed to read vnode");
return (-1);
}
/*
* fifo's and doors are special. Some have pathnames, and
* some do not. And for these, it is pointless to go off to
* mdb_vnode2path, which is very slow.
*
* Event ports never have a pathname.
*/
return (0);
/*
* For sockets, we won't find a path unless we print the path
* associated with the accessvp.
*/
return (-1);
}
}
}
/*
* mdb_vnode2path will print an error for us as needed, but not
* finding a pathname is not really an error, so we plow on.
*/
/*
* A common problem is that device pathnames are prefixed with
* /dev/../devices/. We just clean those up slightly:
* /dev/../devices/<mumble> --> /devices/<mumble>
*/
return (0);
}
const struct fs_type {
int type;
const char *name;
} fs_types[] = {
{ VNON, "NON" },
{ VREG, "REG" },
{ VDIR, "DIR" },
{ VBLK, "BLK" },
{ VCHR, "CHR" },
{ VLNK, "LNK" },
{ VFIFO, "FIFO" },
{ VDOOR, "DOOR" },
{ VPROC, "PROC" },
{ VSOCK, "SOCK" },
{ VPORT, "PORT" },
{ VBAD, "BAD" }
};
struct pfiles_cbdata {
int opt_p;
int fd;
};
static int
{
const char *type;
char path[MAXPATHLEN];
char fsname[_ST_FSTYPSZ];
int err, i;
return (WALK_NEXT);
}
mdb_warn("failed to read vnode");
return (DCMD_ERR);
}
type = "?";
for (i = 0; i <= NUM_FS_TYPES; i++) {
}
do {
if (next_realvpp != NULL)
} while (err == REALVP_CONTINUE);
if (err == REALVP_ERR) {
return (DCMD_ERR);
}
return (DCMD_ERR);
return (DCMD_ERR);
return (DCMD_OK);
}
/*
* Sockets generally don't have interesting pathnames; we only
* show those in the '-p' view.
*/
path[0] = '\0';
return (DCMD_ERR);
}
switch (v.v_type) {
case VDOOR:
{
mdb_warn("failed to read door_node");
return (DCMD_ERR);
}
mdb_warn("failed to read door server process %p",
return (DCMD_ERR);
}
break;
}
case VSOCK:
{
return (DCMD_ERR);
/*
* If the address is cached in the sonode, use it; otherwise,
* we print nothing.
*/
mdb_warn("failed to read sonode socket addr");
return (DCMD_ERR);
}
mdb_printf("socket: ");
}
mdb_warn("failed to read sonode remote addr");
return (DCMD_ERR);
}
mdb_printf("remote: ");
}
break;
}
case VPORT:
break;
case VPROC:
{
mdb_warn("failed to read prnode");
return (DCMD_ERR);
}
mdb_warn("failed to read prcommon %p",
return (DCMD_ERR);
}
break;
}
default:
break;
}
mdb_printf("\n");
return (WALK_NEXT);
}
static int
{
return (WALK_NEXT);
}
/*
* We really need 20 digits to print a 64-bit offset_t, but this
* is exceedingly rare, so we cheat and assume a column width of 10
* digits, in order to fit everything cleanly into 80 columns.
*/
mdb_printf("%?0p %4d %8x %?0p %10lld %?0p %4d\n",
f->f_count);
return (WALK_NEXT);
}
int
{
int opt_f = 0;
struct pfiles_cbdata cb;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_USAGE);
if (opt_f) {
"FD", "FLAG", "VNODE", "OFFSET", "CRED", "CNT");
addr) == -1) {
mdb_warn("failed to walk 'allfile'");
return (DCMD_ERR);
}
} else {
mdb_printf("PATH");
else
mdb_printf("INFO");
mdb_printf("%</u>\n");
addr) == -1) {
mdb_warn("failed to walk 'allfile'");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
void
pfiles_help(void)
{
"Given the address of a process, print information about files\n"
"which the process has open. By default, this includes decoded\n"
"information about the file depending on file and filesystem type\n"
"\n"
"\t-p\tPathnames; omit decoded information. Only display "
"pathnames\n"
"\t-f\tfile_t view; show the file_t structure corresponding to "
"the fd\n");
}