/* * Do some digging to get a reasonable pathname for this vnode. 'path' * should point at a buffer of MAXPATHLEN in size. */ static int pfiles_dig_pathname(uintptr_t vp, char *path) { vnode_t v; bzero(path, MAXPATHLEN); if (mdb_vread(&v, sizeof (v), vp) == -1) { mdb_warn("failed to read vnode"); return (-1); } if (v.v_path == NULL) { /* * 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. */ if (v.v_type == VFIFO || v.v_type == VDOOR || v.v_type == VPORT) return (0); /* * For sockets, we won't find a path unless we print the path * associated with the accessvp. */ if (v.v_type == VSOCK) { struct sonode sonode; if (pfiles_get_sonode(vp, &sonode) == -1) { return (-1); } vp = (uintptr_t)sonode.so_accessvp; } } /* * mdb_vnode2path will print an error for us as needed, but not * finding a pathname is not really an error, so we plow on. */ (void) mdb_vnode2path(vp, path, MAXPATHLEN); /* * A common problem is that device pathnames are prefixed with * /dev/../devices/. We just clean those up slightly: * /dev/../devices/<mumble> --> /devices/<mumble> * /dev/pts/../../devices/<mumble> --> /devices/<mumble> */ if (strncmp("/dev/../devices/", path, strlen("/dev/../devices/")) == 0) strcpy(path, path + 7); if (strncmp("/dev/pts/../../devices/", path, strlen("/dev/pts/../../devices/")) == 0) strcpy(path, path + 14); return (0); }
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); }
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); }