From owner-svn-src-projects@FreeBSD.ORG Fri Jul 24 14:48:59 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CDFDB106567D; Fri, 24 Jul 2009 14:48:59 +0000 (UTC) (envelope-from stas@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id BAA0F8FC19; Fri, 24 Jul 2009 14:48:59 +0000 (UTC) (envelope-from stas@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6OEmxJU012811; Fri, 24 Jul 2009 14:48:59 GMT (envelope-from stas@svn.freebsd.org) Received: (from stas@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6OEmxEm012808; Fri, 24 Jul 2009 14:48:59 GMT (envelope-from stas@svn.freebsd.org) Message-Id: <200907241448.n6OEmxEm012808@svn.freebsd.org> From: Stanislav Sedov Date: Fri, 24 Jul 2009 14:48:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195841 - in projects/libprocstat/sys: kern sys X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Jul 2009 14:49:00 -0000 Author: stas Date: Fri Jul 24 14:48:59 2009 New Revision: 195841 URL: http://svn.freebsd.org/changeset/base/195841 Log: - Add fields required for fstat to kinfo_file structure and code to initialize them. It appears that the size of spare memory in the end of struct isn't enough so I expanded it for now. Modified: projects/libprocstat/sys/kern/kern_descrip.c projects/libprocstat/sys/sys/user.h Modified: projects/libprocstat/sys/kern/kern_descrip.c ============================================================================== --- projects/libprocstat/sys/kern/kern_descrip.c Fri Jul 24 13:50:29 2009 (r195840) +++ projects/libprocstat/sys/kern/kern_descrip.c Fri Jul 24 14:48:59 2009 (r195841) @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -72,12 +74,17 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #ifdef KTRACE #include #endif +#include +#include + #include #include @@ -103,6 +110,10 @@ static int fd_last_used(struct filedesc static void fdgrowtable(struct filedesc *, int); static void fdunused(struct filedesc *fdp, int fd); static void fdused(struct filedesc *fdp, int fd); +static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif); +static int fill_socket_info(struct socket *so, struct kinfo_file *kif); +static int fill_pts_info(struct tty *tp, struct kinfo_file *kif); +static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif); /* * A process is initially started out with NDFILE descriptors stored within @@ -2882,103 +2893,69 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE); #endif -static void -prepare_kinfo_file(struct vnode *vp, struct kinfo_file *kif) +static int +export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt, + int64_t offset, struct kinfo_file *kif, struct sysctl_req *req) { - struct vattr va; - char *fullpath, *freepath; - int error, vfslocked; + struct { + int fflag; + int kf_fflag; + } fflags_table[] = { + { FREAD, KF_FLAG_READ }, + { FWRITE , KF_FLAG_WRITE }, + { FAPPEND , KF_FLAG_APPEND }, + { FASYNC , KF_FLAG_ASYNC }, + { FFSYNC , KF_FLAG_FSYNC }, + { FNONBLOCK , KF_FLAG_NONBLOCK }, + { O_DIRECT , KF_FLAG_DIRECT }, + { FHASLOCK , KF_FLAG_HASLOCK } + }; +#define NFFLAGS (sizeof(fflags_table) / sizeof(*fflags_table)) + int error; + int vfslocked; + struct vnode *vp; + int i; - vref(vp); - switch (vp->v_type) { - case VNON: - kif->kf_vnode_type = KF_VTYPE_VNON; - break; - case VREG: - kif->kf_vnode_type = KF_VTYPE_VREG; - break; - case VDIR: - kif->kf_vnode_type = KF_VTYPE_VDIR; - break; - case VBLK: - kif->kf_vnode_type = KF_VTYPE_VBLK; - break; - case VCHR: - kif->kf_vnode_type = KF_VTYPE_VCHR; - break; - case VLNK: - kif->kf_vnode_type = KF_VTYPE_VLNK; + bzero(kif, sizeof(*kif)); + switch (type) { + case KF_TYPE_FIFO: + case KF_TYPE_VNODE: + vp = (struct vnode *)data; + error = fill_vnode_info(vp, kif); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vrele(vp); + VFS_UNLOCK_GIANT(vfslocked); break; - case VSOCK: - kif->kf_vnode_type = KF_VTYPE_VSOCK; + case KF_TYPE_SOCKET: + error = fill_socket_info((struct socket *)data, kif); break; - case VFIFO: - kif->kf_vnode_type = KF_VTYPE_VFIFO; + case KF_TYPE_PIPE: + error = fill_pipe_info((struct pipe *)data, kif); break; - case VBAD: - kif->kf_vnode_type = KF_VTYPE_VBAD; + case KF_TYPE_PTS: + error = fill_pts_info((struct tty *)data, kif); break; default: - kif->kf_vnode_type = KF_VTYPE_UNKNOWN; - break; + error = 0; } - - freepath = NULL; - fullpath = "-"; - do { - error = VOP_GETATTR(vp, &va, NULL); - if (error) - break; + if (error == 0) kif->kf_status |= KF_ATTR_VALID; - kif->kf_file_fsid = va.va_fsid; - kif->kf_file_fileid = va.va_fileid; - kif->kf_file_mode = MAKEIMODE(va.va_type, va.va_mode); - kif->kf_file_size = va.va_size; - kif->kf_file_rdev = va.va_rdev; - } while (0); - vn_fullpath(curthread, vp, &fullpath, &freepath); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vrele(vp); - VFS_UNLOCK_GIANT(vfslocked); - strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); - if (freepath != NULL) - free(freepath, M_TEMP); -} - -static int -export_vnode_for_sysctl(struct vnode *vp, int type, - struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req) -{ - int error; - - bzero(kif, sizeof(*kif)); - - vref(vp); - kif->kf_fd = type; - kif->kf_type = KF_TYPE_VNODE; - /* This function only handles directories. */ - if (vp->v_type != VDIR) { - vrele(vp); - return (ENOTDIR); - } - FILEDESC_SUNLOCK(fdp); - prepare_kinfo_file(vp, kif); - kif->kf_vnode_type = KF_VTYPE_VDIR; - vrele(vp); /* - * This is not a true file descriptor, so we set a bogus refcount - * and offset to indicate these fields should be ignored. + * Translate file access flags. */ - kif->kf_ref_count = -1; - kif->kf_offset = -1; - + for (i = 0; i < NFFLAGS; i++) + if (fflags & fflags_table[i].fflag) + kif->kf_flags |= fflags_table[i].kf_fflag; + kif->kf_fd = fd; + kif->kf_type = type; + kif->kf_ref_count = refcnt; + kif->kf_offset = offset; /* Pack record size down */ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + strlen(kif->kf_path) + 1; kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t)); error = SYSCTL_OUT(req, kif, kif->kf_structsize); - FILEDESC_SLOCK(fdp); return (error); } @@ -2991,12 +2968,14 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER struct kinfo_file *kif; struct filedesc *fdp; int error, i, *name; - struct socket *so; - struct vnode *vp; struct file *fp; struct proc *p; - struct tty *tp; size_t oldidx; + void *data; + int type; + int refcnt; + int64_t offset; + int fflags; name = (int *)arg1; if ((p = pfind((pid_t)name[0])) == NULL) @@ -3006,134 +2985,129 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER return (error); } fdp = fdhold(p); + kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK); + /* ktrace vnode */ + if (p->p_tracevp != NULL) { + vref(p->p_tracevp); + data = p->p_tracevp; + PROC_UNLOCK(p); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_TRACE, + FREAD | FWRITE, -1, -1, kif, req); + PROC_LOCK(p); + } + /* text vnode */ + if (p->p_textvp != NULL) { + vref(p->p_textvp); + data = p->p_textvp; + PROC_UNLOCK(p); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_TEXT, + FREAD, -1, -1, kif, req); + PROC_LOCK(p); + } PROC_UNLOCK(p); if (fdp == NULL) - return (ENOENT); - kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK); + goto fail; FILEDESC_SLOCK(fdp); - if (fdp->fd_cdir != NULL) - export_vnode_for_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif, - fdp, req); - if (fdp->fd_rdir != NULL) - export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif, - fdp, req); - if (fdp->fd_jdir != NULL) - export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif, - fdp, req); + /* working directory */ + if (fdp->fd_cdir != NULL) { + vref(fdp->fd_cdir); + data = fdp->fd_cdir; + FILEDESC_SUNLOCK(fdp); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD, + FREAD, -1, -1, kif, req); + FILEDESC_SLOCK(fdp); + } + /* root directory */ + if (fdp->fd_rdir != NULL) { + vref(fdp->fd_rdir); + data = fdp->fd_rdir; + FILEDESC_SUNLOCK(fdp); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT, + FREAD, -1, -1, kif, req); + FILEDESC_SLOCK(fdp); + } + /* jail directory */ + if (fdp->fd_jdir != NULL) { + vref(fdp->fd_jdir); + data = fdp->fd_jdir; + FILEDESC_SUNLOCK(fdp); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL, + FREAD, -1, -1, kif, req); + FILEDESC_SLOCK(fdp); + } for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fdp->fd_ofiles[i]) == NULL) continue; - bzero(kif, sizeof(*kif)); - vp = NULL; - so = NULL; - tp = NULL; - kif->kf_fd = i; + data = NULL; switch (fp->f_type) { case DTYPE_VNODE: - kif->kf_type = KF_TYPE_VNODE; - vp = fp->f_vnode; + type = KF_TYPE_VNODE; + vref(fp->f_vnode); + data = fp->f_vnode; break; case DTYPE_SOCKET: - kif->kf_type = KF_TYPE_SOCKET; - so = fp->f_data; + type = KF_TYPE_SOCKET; + data = fp->f_data; break; case DTYPE_PIPE: - kif->kf_type = KF_TYPE_PIPE; + type = KF_TYPE_PIPE; + data = fp->f_data; break; case DTYPE_FIFO: - kif->kf_type = KF_TYPE_FIFO; - vp = fp->f_vnode; + type = KF_TYPE_FIFO; + vref(fp->f_vnode); + data = fp->f_vnode; break; case DTYPE_KQUEUE: - kif->kf_type = KF_TYPE_KQUEUE; + type = KF_TYPE_KQUEUE; break; case DTYPE_CRYPTO: - kif->kf_type = KF_TYPE_CRYPTO; + type = KF_TYPE_CRYPTO; break; case DTYPE_MQUEUE: - kif->kf_type = KF_TYPE_MQUEUE; + type = KF_TYPE_MQUEUE; break; case DTYPE_SHM: - kif->kf_type = KF_TYPE_SHM; + type = KF_TYPE_SHM; break; case DTYPE_SEM: - kif->kf_type = KF_TYPE_SEM; + type = KF_TYPE_SEM; break; case DTYPE_PTS: - kif->kf_type = KF_TYPE_PTS; - tp = fp->f_data; + type = KF_TYPE_PTS; + data = fp->f_data; break; default: - kif->kf_type = KF_TYPE_UNKNOWN; + type = KF_TYPE_UNKNOWN; break; } - kif->kf_ref_count = fp->f_count; - if (fp->f_flag & FREAD) - kif->kf_flags |= KF_FLAG_READ; - if (fp->f_flag & FWRITE) - kif->kf_flags |= KF_FLAG_WRITE; - if (fp->f_flag & FAPPEND) - kif->kf_flags |= KF_FLAG_APPEND; - if (fp->f_flag & FASYNC) - kif->kf_flags |= KF_FLAG_ASYNC; - if (fp->f_flag & FFSYNC) - kif->kf_flags |= KF_FLAG_FSYNC; - if (fp->f_flag & FNONBLOCK) - kif->kf_flags |= KF_FLAG_NONBLOCK; - if (fp->f_flag & O_DIRECT) - kif->kf_flags |= KF_FLAG_DIRECT; - if (fp->f_flag & FHASLOCK) - kif->kf_flags |= KF_FLAG_HASLOCK; - kif->kf_offset = fp->f_offset; - if (vp != NULL) { - /* - * It is OK to drop the filedesc lock here as we will - * re-validate and re-evaluate its properties when - * the loop continues. - */ - FILEDESC_SUNLOCK(fdp); - prepare_kinfo_file(vp, kif); - FILEDESC_SLOCK(fdp); - } - if (so != NULL) { - struct sockaddr *sa; + refcnt = fp->f_count; + fflags = fp->f_flag; + offset = fp->f_offset; - if (so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa) - == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) { - bcopy(sa, &kif->kf_sa_local, sa->sa_len); - free(sa, M_SONAME); - } - if (so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa) - == 00 && sa->sa_len <= sizeof(kif->kf_sa_peer)) { - bcopy(sa, &kif->kf_sa_peer, sa->sa_len); - free(sa, M_SONAME); - } - kif->kf_sock_domain = - so->so_proto->pr_domain->dom_family; - kif->kf_sock_type = so->so_type; - kif->kf_sock_protocol = so->so_proto->pr_protocol; - } - if (tp != NULL) { - strlcpy(kif->kf_path, tty_devname(tp), - sizeof(kif->kf_path)); - } - /* Pack record size down */ - kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + - strlen(kif->kf_path) + 1; - kif->kf_structsize = roundup(kif->kf_structsize, - sizeof(uint64_t)); + /* + * Create sysctl entry. + * It is OK to drop the filedesc lock here as we will + * re-validate and re-evaluate its properties when + * the loop continues. + */ oldidx = req->oldidx; - error = SYSCTL_OUT(req, kif, kif->kf_structsize); + if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO) + FILEDESC_SUNLOCK(fdp); + error = export_fd_for_sysctl(data, type, i, + fflags, refcnt, offset, kif, req); + if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO) + FILEDESC_SLOCK(fdp); if (error) { if (error == ENOMEM) { /* @@ -3149,11 +3123,148 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER } } FILEDESC_SUNLOCK(fdp); +fail: fddrop(fdp); free(kif, M_TEMP); return (error); } +static int +fill_vnode_info(struct vnode *vp, struct kinfo_file *kif) +{ + struct { + int vtype; + int kf_vtype; + } vtypes_table[] = { + { VNON, }, + { VREG, }, + { VDIR, }, + { VBLK, }, + { VCHR, }, + { VLNK, }, + { VSOCK, }, + { VFIFO, }, + { VBAD, }, + }; + char *fullpath, *freepath; + struct vattr va; +#define NVTYPES (sizeof(vtypes_table) / sizeof(*vtypes_table)) + unsigned int i; + int error; + + if (vp == NULL) + return (1); + + /* + * Perform vtype translation. + */ + for (i = 0; i < NVTYPES; i++) + if (vtypes_table[i].vtype == vp->v_type) + break; + + if (i < NVTYPES) + kif->kf_vnode_type = vtypes_table[i].kf_vtype; + else + kif->kf_vnode_type = KF_VTYPE_UNKNOWN; + + freepath = NULL; + fullpath = "-"; + error = vn_fullpath(curthread, vp, &fullpath, &freepath); + if (error != 0) + return (error); + strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); + free(freepath, M_TEMP); + + /* + * Retrieve vnode attributes. + */ + error = VOP_GETATTR(vp, &va, NULL); + if (error != 0) + return (error); + kif->kf_file_fsid = va.va_fsid; + kif->kf_file_fileid = va.va_fileid; + kif->kf_file_mode = MAKEIMODE(va.va_type, va.va_mode); + kif->kf_file_size = va.va_size; + kif->kf_file_rdev = va.va_rdev; + return (0); +} + +static int +fill_socket_info(struct socket *so, struct kinfo_file *kif) +{ + struct sockaddr *sa; + struct inpcb *inpcb; + struct unpcb *unpcb; + int error; + + if (so == NULL) + return (1); + + kif->kf_sock_domain = so->so_proto->pr_domain->dom_family; + kif->kf_sock_type = so->so_type; + kif->kf_sock_protocol = so->so_proto->pr_protocol; + kif->kf_sock_pcb = (uint64_t)so->so_pcb; + switch(kif->kf_sock_domain) { + case AF_INET: + case AF_INET6: + if (kif->kf_sock_protocol == IPPROTO_TCP) { + if (so->so_pcb != NULL) { + inpcb = (struct inpcb *)(so->so_pcb); + kif->kf_sock_inpcb = (uint64_t)inpcb->inp_ppcb; + } + } + break; + case AF_UNIX: + if (so->so_pcb != NULL) { + unpcb = (struct unpcb *)(so->so_pcb); + if (unpcb->unp_conn) { + kif->kf_sock_unpconn = + (uint64_t)unpcb->unp_conn; + kif->kf_sock_rcv_sb_state = + so->so_rcv.sb_state; + kif->kf_sock_snd_sb_state = + so->so_snd.sb_state; + } + } + break; + } + error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); + if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) { + bcopy(sa, &kif->kf_sa_local, sa->sa_len); + free(sa, M_SONAME); + } + error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa); + if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) { + bcopy(sa, &kif->kf_sa_peer, sa->sa_len); + free(sa, M_SONAME); + } + strncpy(kif->kf_sock_domname, so->so_proto->pr_domain->dom_name, + sizeof(kif->kf_sock_domname)); + return (0); +} + +static int +fill_pts_info(struct tty *tp, struct kinfo_file *kif) +{ + + if (tp == NULL) + return (1); + strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path)); + return (0); +} + +static int +fill_pipe_info(struct pipe *pi, struct kinfo_file *kif) +{ + + if (pi == NULL) + return (1); + kif->pipe_addr = (uint64_t)pi; + kif->pipe_peer = (uint64_t)pi->pipe_peer; + kif->pipe_buffer_cnt = pi->pipe_buffer.cnt; + return (0); +} + static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD, sysctl_kern_proc_filedesc, "Process filedesc entries"); Modified: projects/libprocstat/sys/sys/user.h ============================================================================== --- projects/libprocstat/sys/sys/user.h Fri Jul 24 13:50:29 2009 (r195840) +++ projects/libprocstat/sys/sys/user.h Fri Jul 24 14:48:59 2009 (r195841) @@ -270,6 +270,8 @@ struct user { #define KF_FD_TYPE_CWD -1 /* Current working directory */ #define KF_FD_TYPE_ROOT -2 /* Root directory */ #define KF_FD_TYPE_JAIL -3 /* Jail directory */ +#define KF_FD_TYPE_TRACE -4 /* ptrace vnode */ +#define KF_FD_TYPE_TEXT -5 /* Text vnode */ #define KF_FLAG_READ 0x00000001 #define KF_FLAG_WRITE 0x00000002 @@ -309,7 +311,7 @@ struct kinfo_ofile { }; #if defined(__amd64__) || defined(__i386__) -#define KINFO_FILE_SIZE 1392 +#define KINFO_FILE_SIZE 1496 #endif struct kinfo_file { @@ -318,21 +320,29 @@ struct kinfo_file { int kf_fd; /* Array index. */ int kf_ref_count; /* Reference count. */ int kf_flags; /* Flags. */ - int _kf_pad0; /* Round to 64 bit alignment */ - int64_t kf_offset; /* Seek location. */ int kf_vnode_type; /* Vnode type. */ + int64_t kf_offset; /* Seek location. */ + char kf_sock_domname[32]; /* Address domain name. */ int kf_sock_domain; /* Socket domain. */ - int kf_sock_type; /* Socket type. */ int kf_sock_protocol; /* Socket protocol. */ + int kf_sock_type; /* Socket type. */ + uint16_t kf_sock_snd_sb_state; /* Send buffer state. */ + uint16_t kf_sock_rcv_sb_state; /* Receive buffer state. */ + uint64_t kf_sock_pcb; /* Address of so_pcb. */ + uint64_t kf_sock_inpcb; /* Address of inp_ppcb. */ + uint64_t kf_sock_unpconn; /* Address of unp_conn. */ struct sockaddr_storage kf_sa_local; /* Socket address. */ struct sockaddr_storage kf_sa_peer; /* Peer address. */ dev_t kf_file_fsid; /* Vnode filesystem id. */ + dev_t kf_file_rdev; /* File device. */ uint64_t kf_file_fileid; /* Global file id. */ + off_t kf_file_size; /* File size. */ mode_t kf_file_mode; /* File mode. */ uint16_t kf_status; /* Status flags. */ - off_t kf_file_size; /* File size. */ - dev_t kf_file_rdev; /* File device. */ - int _kf_ispare[9]; /* Space for more stuff. */ + uint32_t pipe_buffer_cnt; + uint64_t pipe_addr; + uint64_t pipe_peer; + int _kf_ispare[16]; /* Space for more stuff. */ /* Truncated before copyout in sysctl */ char kf_path[PATH_MAX]; /* Path to file, if any. */ };