예제 #1
0
파일: vfs.c 프로젝트: andreiw/polaris
static int
pfile_callback(uintptr_t addr, const struct file *f, struct pfiles_cbdata *cb)
{
	vnode_t v, layer_vn;
	int myfd = cb->fd;
	const char *type;
	char path[MAXPATHLEN];
	uintptr_t top_vnodep, realvpp;
	char fsname[_ST_FSTYPSZ];
	int err, i;

	cb->fd++;

	if (addr == NULL) {
		return (WALK_NEXT);
	}

	top_vnodep = realvpp = (uintptr_t)f->f_vnode;

	if (mdb_vread(&v, sizeof (v), realvpp) == -1) {
		mdb_warn("failed to read vnode");
		return (DCMD_ERR);
	}

	type = "?";
	for (i = 0; i <= NUM_FS_TYPES; i++) {
		if (fs_types[i].type == v.v_type)
			type = fs_types[i].name;
	}

	do {
		uintptr_t next_realvpp;

		err = next_realvp(realvpp, &layer_vn, &next_realvpp);
		if (next_realvpp != NULL)
			realvpp = next_realvpp;

	} while (err == REALVP_CONTINUE);

	if (err == REALVP_ERR) {
		mdb_warn("failed to do realvp() for %p", realvpp);
		return (DCMD_ERR);
	}

	if (read_fsname((uintptr_t)layer_vn.v_vfsp, fsname) == -1)
		return (DCMD_ERR);

	mdb_printf("%4d %4s %?0p ", myfd, type, top_vnodep);

	if (cb->opt_p) {
		if (pfiles_dig_pathname(top_vnodep, path) == -1)
			return (DCMD_ERR);

		mdb_printf("%s\n", path);
		return (DCMD_OK);
	}

	/*
	 * Sockets generally don't have interesting pathnames; we only
	 * show those in the '-p' view.
	 */
	path[0] = '\0';
	if (v.v_type != VSOCK) {
		if (pfiles_dig_pathname(top_vnodep, path) == -1)
			return (DCMD_ERR);
	}
	mdb_printf("%s%s", path, path[0] == '\0' ? "" : " ");

	switch (v.v_type) {
	case VDOOR:
	{
		door_node_t doornode;
		proc_t pr;

		if (mdb_vread(&doornode, sizeof (doornode),
		    (uintptr_t)layer_vn.v_data) == -1) {
			mdb_warn("failed to read door_node");
			return (DCMD_ERR);
		}

		if (mdb_vread(&pr, sizeof (pr),
		    (uintptr_t)doornode.door_target) == -1) {
			mdb_warn("failed to read door server process %p",
			    doornode.door_target);
			return (DCMD_ERR);
		}
		mdb_printf("[door to '%s' (proc=%p)]", pr.p_user.u_comm,
		    doornode.door_target);
		break;
	}

	case VSOCK:
	{
		struct sonode sonode;

		if (pfiles_get_sonode(realvpp, &sonode) == -1)
			return (DCMD_ERR);

		/*
		 * If the address is cached in the sonode, use it; otherwise,
		 * we print nothing.
		 */
		if (sonode.so_state & SS_LADDR_VALID) {
			struct sockaddr *laddr =
			    mdb_alloc(sonode.so_laddr_len, UM_SLEEP);
			if (mdb_vread(laddr, sonode.so_laddr_len,
			    (uintptr_t)sonode.so_laddr_sa) == -1) {
				mdb_warn("failed to read sonode socket addr");
				return (DCMD_ERR);
			}

			mdb_printf("socket: ");
			pfiles_print_addr(laddr);
		}

		if (sonode.so_state & SS_FADDR_VALID) {
			struct sockaddr *faddr =
			    mdb_alloc(sonode.so_faddr_len, UM_SLEEP);
			if (mdb_vread(faddr, sonode.so_faddr_len,
			    (uintptr_t)sonode.so_faddr_sa) == -1) {
				mdb_warn("failed to read sonode remote addr");
				return (DCMD_ERR);
			}

			mdb_printf("remote: ");
			pfiles_print_addr(faddr);
		}
		break;
	}

	case VPORT:
		mdb_printf("[event port (port=%p)]", v.v_data);
		break;

	case VPROC:
	{
		prnode_t prnode;
		prcommon_t prcommon;

		if (mdb_vread(&prnode, sizeof (prnode),
		    (uintptr_t)layer_vn.v_data) == -1) {
			mdb_warn("failed to read prnode");
			return (DCMD_ERR);
		}

		if (mdb_vread(&prcommon, sizeof (prcommon),
		    (uintptr_t)prnode.pr_common) == -1) {
			mdb_warn("failed to read prcommon %p",
			    prnode.pr_common);
			return (DCMD_ERR);
		}

		mdb_printf("(proc=%p)", prcommon.prc_proc);
		break;
	}

	default:
		break;
	}


	mdb_printf("\n");

	return (WALK_NEXT);
}
예제 #2
0
파일: vfs.c 프로젝트: andreiw/polaris
/*ARGSUSED*/
int
fsinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	vfs_t vfs;
	int len;
	int opt_v = 0;
	char buf[MAXPATHLEN];
	char fsname[_ST_FSTYPSZ];
	mntopt_t *mntopts;
	size_t size;
	int i;
	int first = 1;
	char opt[MAX_MNTOPT_STR];
	uintptr_t global_zone;

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk_dcmd("vfs", "fsinfo", argc, argv) == -1) {
			mdb_warn("failed to walk file system list");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_getopts(argc, argv,
	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
		return (DCMD_USAGE);

	if (DCMD_HDRSPEC(flags))
		mdb_printf("%<u>%?s %-15s %s%</u>\n",
		    "VFSP", "FS", "MOUNT");

	if (mdb_vread(&vfs, sizeof (vfs), addr) == -1) {
		mdb_warn("failed to read vfs_t %p", addr);
		return (DCMD_ERR);
	}

	if ((len = mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf,
	    sizeof (buf))) <= 0)
		strcpy(buf, "??");

	else if (!opt_v && (len >= FSINFO_MNTLEN))
		/*
		 * In normal mode, we truncate the path to keep the output
		 * clean.  In -v mode, we just print the full path.
		 */
		strcpy(&buf[FSINFO_MNTLEN - 4], "...");

	if (read_fsname(addr, fsname) == -1)
		return (DCMD_ERR);

	mdb_printf("%0?p %-15s %s\n", addr, fsname, buf);

	if (!opt_v)
		return (DCMD_OK);

	/*
	 * Print 'resource' string; this shows what we're mounted upon.
	 */
	if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf,
	    MAXPATHLEN) <= 0)
		strcpy(buf, "??");

	mdb_printf("%?s %s\n", "R:", buf);

	/*
	 * 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.
	 */
	size = vfs.vfs_mntopts.mo_count * sizeof (mntopt_t);
	mntopts = mdb_alloc(size, UM_SLEEP | UM_GC);

	if (mdb_vread(mntopts, size,
	    (uintptr_t)vfs.vfs_mntopts.mo_list) == -1) {
		mdb_warn("failed to read mntopts %p", vfs.vfs_mntopts.mo_list);
		return (DCMD_ERR);
	}

	for (i = 0; i < vfs.vfs_mntopts.mo_count; i++) {
		if (mntopts[i].mo_flags & MO_SET) {
			if (mdb_readstr(opt, sizeof (opt),
			    (uintptr_t)mntopts[i].mo_name) == -1) {
				mdb_warn("failed to read mntopt name %p",
				    mntopts[i].mo_name);
				return (DCMD_ERR);
			}
			if (first) {
				mdb_printf("%?s ", "O:");
				first = 0;
			} else {
				mdb_printf(",");
			}
			mdb_printf("%s", opt);
			if (mntopts[i].mo_flags & MO_HASVALUE) {
				if (mdb_readstr(opt, sizeof (opt),
				    (uintptr_t)mntopts[i].mo_arg) == -1) {
					mdb_warn("failed to read mntopt "
					    "value %p", mntopts[i].mo_arg);
					return (DCMD_ERR);
				}
				mdb_printf("=%s", opt);
			}
		}
	}

	if (mdb_readvar(&global_zone, "global_zone") == -1) {
		mdb_warn("failed to locate global_zone");
		return (DCMD_ERR);
	}

	if ((vfs.vfs_zone != NULL) &&
	    ((uintptr_t)vfs.vfs_zone != global_zone)) {
		zone_t z;

		if (mdb_vread(&z, sizeof (z), (uintptr_t)vfs.vfs_zone) == -1) {
			mdb_warn("failed to read zone");
			return (DCMD_ERR);
		}
		/*
		 * zone names are much shorter than MAX_MNTOPT_STR
		 */
		if (mdb_readstr(opt, sizeof (opt),
		    (uintptr_t)z.zone_name) == -1) {
			mdb_warn("failed to read zone name");
			return (DCMD_ERR);
		}
		if (first) {
			mdb_printf("%?s ", "O:");
		} else {
			mdb_printf(",");
		}
		mdb_printf("zone=%s", opt);
	}
	return (DCMD_OK);
}
예제 #3
0
파일: vfs.c 프로젝트: andreiw/polaris
static int
next_realvp(uintptr_t invp, struct vnode *outvn, uintptr_t *outvp)
{
	char fsname[_ST_FSTYPSZ];

	*outvp = invp;
	if (mdb_vread(outvn, sizeof (struct vnode), invp) == -1) {
		mdb_warn("failed to read vnode at %p", invp);
		return (REALVP_ERR);
	}

	if (read_fsname((uintptr_t)outvn->v_vfsp, fsname) == -1)
		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.
	 */
	if (strcmp(fsname, "fifofs") == 0) {
		fifonode_t fn;
		if (mdb_vread(&fn, sizeof (fn),
		    (uintptr_t)outvn->v_data) == -1) {
			mdb_warn("failed to read fifonode");
			return (REALVP_ERR);
		}
		*outvp = (uintptr_t)fn.fn_realvp;

	} else if (strcmp(fsname, "namefs") == 0) {
		struct namenode nn;
		if (mdb_vread(&nn, sizeof (nn),
		    (uintptr_t)outvn->v_data) == -1) {
			mdb_warn("failed to read namenode");
			return (REALVP_ERR);
		}
		*outvp = (uintptr_t)nn.nm_filevp;

	} else if (outvn->v_type == VSOCK && outvn->v_stream != NULL) {
		struct stdata stream;

		/*
		 * Sockets have a strange and different layering scheme; we
		 * hop over into the sockfs vnode (accessible via the stream
		 * head) if possible.
		 */
		if (mdb_vread(&stream, sizeof (stream),
		    (uintptr_t)outvn->v_stream) == -1) {
			mdb_warn("failed to read stream data");
			return (REALVP_ERR);
		}
		*outvp = (uintptr_t)stream.sd_vnode;
	}

	if (*outvp == invp || *outvp == NULL)
		return (REALVP_DONE);

	return (REALVP_CONTINUE);
}
예제 #4
0
파일: vfs.c 프로젝트: bahamas10/openzfs
static int
pfile_callback(uintptr_t addr, const struct file *f, struct pfiles_cbdata *cb)
{
	vnode_t v, layer_vn;
	int myfd = cb->fd;
	const char *type;
	char path[MAXPATHLEN];
	uintptr_t top_vnodep, realvpp;
	char fsname[_ST_FSTYPSZ];
	int err, i;

	cb->fd++;

	if (addr == NULL) {
		return (WALK_NEXT);
	}

	top_vnodep = realvpp = (uintptr_t)f->f_vnode;

	if (mdb_vread(&v, sizeof (v), realvpp) == -1) {
		mdb_warn("failed to read vnode");
		return (DCMD_ERR);
	}

	type = "?";
	for (i = 0; i < NUM_FS_TYPES; i++) {
		if (fs_types[i].type == v.v_type) {
			type = fs_types[i].name;
			break;
		}
	}

	do {
		uintptr_t next_realvpp;

		err = next_realvp(realvpp, &layer_vn, &next_realvpp);
		if (next_realvpp != NULL)
			realvpp = next_realvpp;

	} while (err == REALVP_CONTINUE);

	if (err == REALVP_ERR) {
		mdb_warn("failed to do realvp() for %p", realvpp);
		return (DCMD_ERR);
	}

	if (read_fsname((uintptr_t)layer_vn.v_vfsp, fsname) == -1)
		return (DCMD_ERR);

	mdb_printf("%4d %4s %?0p ", myfd, type, top_vnodep);

	if (cb->opt_p) {
		if (pfiles_dig_pathname(top_vnodep, path) == -1)
			return (DCMD_ERR);

		mdb_printf("%s\n", path);
		return (DCMD_OK);
	}

	/*
	 * Sockets generally don't have interesting pathnames; we only
	 * show those in the '-p' view.
	 */
	path[0] = '\0';
	if (v.v_type != VSOCK) {
		if (pfiles_dig_pathname(top_vnodep, path) == -1)
			return (DCMD_ERR);
	}
	mdb_printf("%s%s", path, path[0] == '\0' ? "" : " ");

	switch (v.v_type) {
	case VDOOR:
	{
		door_node_t doornode;
		proc_t pr;

		if (mdb_vread(&doornode, sizeof (doornode),
		    (uintptr_t)layer_vn.v_data) == -1) {
			mdb_warn("failed to read door_node");
			return (DCMD_ERR);
		}

		if (mdb_vread(&pr, sizeof (pr),
		    (uintptr_t)doornode.door_target) == -1) {
			mdb_warn("failed to read door server process %p",
			    doornode.door_target);
			return (DCMD_ERR);
		}
		mdb_printf("[door to '%s' (proc=%p)]", pr.p_user.u_comm,
		    doornode.door_target);
		break;
	}

	case VSOCK:
	{
		vnode_t v_sock;
		struct sonode so;

		if (mdb_vread(&v_sock, sizeof (v_sock), realvpp) == -1) {
			mdb_warn("failed to read socket vnode");
			return (DCMD_ERR);
		}

		/*
		 * Sockets can be non-stream or stream, they have to be dealed
		 * with differently.
		 */
		if (v_sock.v_stream == NULL) {
			if (pfiles_get_sonode(&v_sock, &so) == -1)
				return (DCMD_ERR);

			/* Pick the proper methods. */
			for (i = 0; i <= NUM_SOCK_PRINTS; i++) {
				if ((sock_prints[i].family == so.so_family &&
				    sock_prints[i].type == so.so_type &&
				    sock_prints[i].pro == so.so_protocol) ||
				    (sock_prints[i].family == so.so_family &&
				    sock_prints[i].type == so.so_type &&
				    so.so_type == SOCK_RAW)) {
					if ((*sock_prints[i].print)(&so) == -1)
						return (DCMD_ERR);
				}
			}
		} else {
			sotpi_sonode_t sotpi_sonode;

			if (pfiles_get_sonode(&v_sock, &so) == -1)
				return (DCMD_ERR);

			/*
			 * If the socket is a fallback socket, read its related
			 * information separately; otherwise, read it as a whole
			 * tpi socket.
			 */
			if (so.so_state & SS_FALLBACK_COMP) {
				sotpi_sonode.st_sonode = so;

				if (mdb_vread(&(sotpi_sonode.st_info),
				    sizeof (sotpi_info_t),
				    (uintptr_t)so.so_priv) == -1)
					return (DCMD_ERR);
			} else {
				if (pfiles_get_tpi_sonode(&v_sock,
				    &sotpi_sonode) == -1)
					return (DCMD_ERR);
			}

			if (tpi_sock_print(&sotpi_sonode) == -1)
				return (DCMD_ERR);
		}

		break;
	}

	case VPORT:
		mdb_printf("[event port (port=%p)]", v.v_data);
		break;

	case VPROC:
	{
		prnode_t prnode;
		prcommon_t prcommon;

		if (mdb_vread(&prnode, sizeof (prnode),
		    (uintptr_t)layer_vn.v_data) == -1) {
			mdb_warn("failed to read prnode");
			return (DCMD_ERR);
		}

		if (mdb_vread(&prcommon, sizeof (prcommon),
		    (uintptr_t)prnode.pr_common) == -1) {
			mdb_warn("failed to read prcommon %p",
			    prnode.pr_common);
			return (DCMD_ERR);
		}

		mdb_printf("(proc=%p)", prcommon.prc_proc);
		break;
	}

	default:
		break;
	}

	mdb_printf("\n");

	return (WALK_NEXT);
}