svn commit: r195877 - in projects/libprocstat: sys/kern sys/sys usr.bin/fstat

Stanislav Sedov stas at FreeBSD.org
Sat Jul 25 20:26:55 UTC 2009


Author: stas
Date: Sat Jul 25 20:26:54 2009
New Revision: 195877
URL: http://svn.freebsd.org/changeset/base/195877

Log:
  - Locking bugfixes.
  - Organize new kinfo_file fields into the union to save space.  Also
    use kf_path field for textual representation of sockets domain name.
    This allows to fit all new kinfo_fields into spare space thus keeping
    the sysctl compatible with 7x world.
  - Use uint64_t to store pointers to allow i386 fstat to be used with amd64
    kernels and vice versa.
  - Correctly initialize kf_vnode_type field.
  - Implement missing sysctl-mode access routines in libprocstat.  Now sysctl
    version of fstat should be fully functional.

Modified:
  projects/libprocstat/sys/kern/kern_descrip.c
  projects/libprocstat/sys/sys/user.h
  projects/libprocstat/usr.bin/fstat/libprocstat.c
  projects/libprocstat/usr.bin/fstat/libprocstat.h

Modified: projects/libprocstat/sys/kern/kern_descrip.c
==============================================================================
--- projects/libprocstat/sys/kern/kern_descrip.c	Sat Jul 25 19:43:46 2009	(r195876)
+++ projects/libprocstat/sys/kern/kern_descrip.c	Sat Jul 25 20:26:54 2009	(r195877)
@@ -2968,6 +2968,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 	struct filedesc *fdp;
 	struct kinfo_file *kif;
 	struct proc *p;
+	struct vnode *tracevp, *textvp;
 	size_t oldidx;
 	int64_t offset;
 	void *data;
@@ -2981,27 +2982,23 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 		PROC_UNLOCK(p);
 		return (error);
 	}
+	/* ktrace vnode */
+	tracevp = p->p_tracevp;
+	if (tracevp != NULL)
+		vref(tracevp);
+	/* text vnode */
+	textvp = p->p_textvp;
+	if (textvp != NULL)
+		vref(textvp);
 	fdp = fdhold(p);
+	PROC_UNLOCK(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,
+	if (tracevp != NULL)
+		export_fd_for_sysctl(tracevp, 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,
+	if (textvp != NULL)
+		export_fd_for_sysctl(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
 		    FREAD, -1, -1, kif, req);
-		PROC_LOCK(p);
-	}
-	PROC_UNLOCK(p);
 	if (fdp == NULL)
 		goto fail;
 	FILEDESC_SLOCK(fdp);
@@ -3133,20 +3130,20 @@ fill_vnode_info(struct vnode *vp, struct
 		int	vtype;
 		int	kf_vtype;
 	} vtypes_table[] = {
-		{ VNON,  },
-		{ VREG,  },
-		{ VDIR,  },
-		{ VBLK,  },
-		{ VCHR,  },
-		{ VLNK,  },
-		{ VSOCK,  },
-		{ VFIFO, },
-		{ VBAD,  },
+		{ VNON, KF_VTYPE_VNON },
+		{ VREG, KF_VTYPE_VREG },
+		{ VDIR, KF_VTYPE_VDIR },
+		{ VBLK, KF_VTYPE_VBLK },
+		{ VCHR, KF_VTYPE_VCHR },
+		{ VLNK, KF_VTYPE_VLNK },
+		{ VSOCK, KF_VTYPE_VSOCK },
+		{ VFIFO, KF_VTYPE_VFIFO },
+		{ VBAD, KF_VTYPE_VBAD }
 	};
 #define	NVTYPES	(sizeof(vtypes_table) / sizeof(*vtypes_table))
 	struct vattr va;
 	char *fullpath, *freepath;
-	int error;
+	int error, vfslocked;
 	unsigned int i;
 
 	if (vp == NULL)
@@ -3158,7 +3155,6 @@ fill_vnode_info(struct vnode *vp, struct
 	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
@@ -3175,14 +3171,18 @@ fill_vnode_info(struct vnode *vp, struct
 	/*
 	 * Retrieve vnode attributes.
 	 */
-	error = VOP_GETATTR(vp, &va, NULL);
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+	vn_lock(vp, LK_SHARED | LK_RETRY);
+	error = VOP_GETATTR(vp, &va, curthread->td_ucred);
+	VOP_UNLOCK(vp, 0);
+	VFS_UNLOCK_GIANT(vfslocked);
 	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;
+	kif->kf_un.file.kf_file_fsid = va.va_fsid;
+	kif->kf_un.file.kf_file_fileid = va.va_fileid;
+	kif->kf_un.file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
+	kif->kf_un.file.kf_file_size = va.va_size;
+	kif->kf_un.file.kf_file_rdev = va.va_rdev;
 	return (0);
 }
 
@@ -3199,14 +3199,15 @@ fill_socket_info(struct socket *so, stru
 	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;
+	kif->kf_un.sock.kf_sock_pcb = (uintptr_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;
+				kif->kf_un.sock.kf_sock_inpcb =
+				    (uintptr_t)inpcb->inp_ppcb;
 			}
 		}
 		break;
@@ -3214,11 +3215,11 @@ fill_socket_info(struct socket *so, stru
 		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 =
+				kif->kf_un.sock.kf_sock_unpconn =
+				    (uintptr_t)unpcb->unp_conn;
+				kif->kf_un.sock.kf_sock_rcv_sb_state =
 				    so->so_rcv.sb_state;
-				kif->kf_sock_snd_sb_state =
+				kif->kf_un.sock.kf_sock_snd_sb_state =
 				    so->so_snd.sb_state;
 			}
 		}
@@ -3234,8 +3235,8 @@ fill_socket_info(struct socket *so, stru
 		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));
+	strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
+	    sizeof(kif->kf_path));
 	return (0);
 }
 
@@ -3245,6 +3246,7 @@ fill_pts_info(struct tty *tp, struct kin
 
 	if (tp == NULL)
 		return (1);
+	kif->kf_un.pts.pts_dev = tty_udev(tp);
 	strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
 	return (0);
 }
@@ -3255,9 +3257,9 @@ fill_pipe_info(struct pipe *pi, struct k
 
 	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;
+	kif->kf_un.pipe.pipe_addr = (uintptr_t)pi;
+	kif->kf_un.pipe.pipe_peer = (uintptr_t)pi->pipe_peer;
+	kif->kf_un.pipe.pipe_buffer_cnt = pi->pipe_buffer.cnt;
 	return (0);
 }
 

Modified: projects/libprocstat/sys/sys/user.h
==============================================================================
--- projects/libprocstat/sys/sys/user.h	Sat Jul 25 19:43:46 2009	(r195876)
+++ projects/libprocstat/sys/sys/user.h	Sat Jul 25 20:26:54 2009	(r195877)
@@ -317,7 +317,7 @@ struct kinfo_ofile {
 };
 
 #if defined(__amd64__) || defined(__i386__)
-#define	KINFO_FILE_SIZE	1496
+#define	KINFO_FILE_SIZE	1392
 #endif
 
 struct kinfo_file {
@@ -326,29 +326,53 @@ struct kinfo_file {
 	int		kf_fd;			/* Array index. */
 	int		kf_ref_count;		/* Reference count. */
 	int		kf_flags;		/* Flags. */
-	int		kf_vnode_type;		/* Vnode type. */
+	int		kf_pad0;		/* Round to 64 bit alignment. */
 	int64_t		kf_offset;		/* Seek location. */
-	char		kf_sock_domname[32];	/* Address domain name. */
+	int		kf_vnode_type;		/* Vnode type. */
 	int		kf_sock_domain;		/* Socket domain. */
-	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. */
+	int		kf_sock_protocol;	/* Socket protocol. */
 	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. */
+	union {
+		struct {
+			/* Send buffer state. */
+			uint16_t	kf_sock_snd_sb_state;
+			/* Receive buffer state. */
+			uint16_t	kf_sock_rcv_sb_state;
+			/* Address of so_pcb. */
+			uint64_t	kf_sock_pcb;
+			/* Address of inp_ppcb. */
+			uint64_t	kf_sock_inpcb;
+			/* Address of unp_conn. */
+			uint64_t	kf_sock_unpconn;
+			/* Round to 64-bit alignment. */
+			int		kf_sock_pad;
+		} sock;
+		struct {
+			/* Vnode filesystem id. */
+			dev_t		kf_file_fsid;
+			/* File device. */
+			dev_t		kf_file_rdev;
+			/* Global file id. */
+			uint64_t	kf_file_fileid;
+			/* File size. */
+			off_t		kf_file_size;
+			/* File mode. */
+			mode_t		kf_file_mode;
+		} file;
+		struct {
+			uint32_t	pipe_buffer_cnt;
+			uint64_t	pipe_addr;
+			uint64_t	pipe_peer;
+		} pipe;
+		struct {
+			dev_t		pts_dev;
+		} pts;
+	} kf_un;
 	uint16_t	kf_status;		/* Status flags. */
-	uint32_t	pipe_buffer_cnt;
-	uint64_t	pipe_addr;
-	uint64_t	pipe_peer;
-	int		_kf_ispare[16];		/* Space for more stuff. */
+	uint16_t	kf_pad1;		/* Round to 32 bit alignment. */
+	int		_kf_ispare[7];		/* Space for more stuff. */
 	/* Truncated before copyout in sysctl */
 	char		kf_path[PATH_MAX];	/* Path to file, if any. */
 };

Modified: projects/libprocstat/usr.bin/fstat/libprocstat.c
==============================================================================
--- projects/libprocstat/usr.bin/fstat/libprocstat.c	Sat Jul 25 19:43:46 2009	(r195876)
+++ projects/libprocstat/usr.bin/fstat/libprocstat.c	Sat Jul 25 20:26:54 2009	(r195877)
@@ -610,12 +610,10 @@ kinfo_uflags2fst(int fd)
 		return (PS_FST_UFLAG_RDIR);
 	case KF_FD_TYPE_JAIL:
 		return (PS_FST_UFLAG_JAIL);
-#if 0
 	case KF_FD_TYPE_TRACE:
 		return (PS_FST_UFLAG_TRACE);
 	case KF_FD_TYPE_TEXT:
 		return (PS_FST_UFLAG_TEXT);
-#endif
 	}
 	return (0);
 }
@@ -701,8 +699,8 @@ procstat_get_pipe_info_kvm(kvm_t *kd, st
 		warnx("can't read pipe at %p", (void *)pipep);
 		goto fail;
 	}
-	ps->addr = (caddr_t)pipep;
-	ps->peer = (caddr_t)pi.pipe_peer;
+	ps->addr = (uintptr_t)pipep;
+	ps->peer = (uintptr_t)pi.pipe_peer;
 	ps->buffer_cnt = pi.pipe_buffer.cnt;
 	return (0);
 
@@ -712,13 +710,21 @@ fail:
 }
 
 static int
-procstat_get_pipe_info_sysctl(struct filestat *fst __unused, struct pipestat *ps __unused,
+procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps,
     char *errbuf __unused)
 {
+	struct kinfo_file *kif;
 
-	warnx("not implemented: %s:%d", __FUNCTION__, __LINE__);
-	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
-	return (1);
+	assert(ps);
+	assert(fst);
+	bzero(ps, sizeof(*ps));
+	kif = fst->fs_typedep;
+	if (kif == NULL)
+		return (1);
+	ps->addr = kif->kf_un.pipe.pipe_addr;
+	ps->peer = kif->kf_un.pipe.pipe_peer;
+	ps->buffer_cnt = kif->kf_un.pipe.pipe_buffer_cnt;
+	return (0);
 }
 
 int
@@ -767,13 +773,20 @@ fail:
 }
 
 static int
-procstat_get_pts_info_sysctl(struct filestat *fst __unused, struct ptsstat *pts __unused,
+procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
     char *errbuf __unused)
 {
+	struct kinfo_file *kif;
 
-	warnx("not implemented: %s:%d", __FUNCTION__, __LINE__);
-	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
-	return (1);
+	assert(pts);
+	assert(fst);
+	bzero(pts, sizeof(*pts));
+	kif = fst->fs_typedep;
+	if (kif == NULL)
+		return (0);
+	pts->dev = kif->kf_un.pts.pts_dev;
+	strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname));
+	return (0);
 }
 
 int
@@ -893,7 +906,7 @@ procstat_get_vnode_info_sysctl(struct fi
 		statfs(kif->kf_path, &stbuf);
 		vn->mntdir = strdup(stbuf.f_mntonname);
 	}
-	vn->vn_dev = kif->kf_file_rdev;
+	vn->vn_dev = kif->kf_un.file.kf_file_rdev;
 	if (kif->kf_vnode_type == KF_VTYPE_VBLK) {
 		name = devname(vn->vn_dev, S_IFBLK);
 		if (name != NULL)
@@ -903,10 +916,10 @@ procstat_get_vnode_info_sysctl(struct fi
 		if (name != NULL)
 			strlcpy(vn->vn_devname, name, sizeof(vn->vn_devname));
 	}
-	vn->vn_fsid = kif->kf_file_fsid;
-	vn->vn_fileid = kif->kf_file_fileid;
-	vn->vn_size = kif->kf_file_size;
-	vn->vn_mode = kif->kf_file_mode;
+	vn->vn_fsid = kif->kf_un.file.kf_file_fsid;
+	vn->vn_fileid = kif->kf_un.file.kf_file_fileid;
+	vn->vn_size = kif->kf_un.file.kf_file_size;
+	vn->vn_mode = kif->kf_un.file.kf_file_mode;
 	return (0);
 }
 
@@ -947,7 +960,7 @@ procstat_get_socket_info_kvm(kvm_t *kd, 
 	so = fst->fs_typedep;
 	if (so == NULL)
 		goto fail;
-	sock->so_addr = (caddr_t)so;
+	sock->so_addr = (uintptr_t)so;
 	/* fill in socket */
 	if (!kvm_read_all(kd, (unsigned long)so, &s,
 	    sizeof(struct socket))) {
@@ -981,7 +994,7 @@ procstat_get_socket_info_kvm(kvm_t *kd, 
 	sock->type = s.so_type;
 	sock->proto = proto.pr_protocol;
 	sock->dom_family = dom.dom_family;
-	sock->so_pcb = s.so_pcb;
+	sock->so_pcb = (uintptr_t)s.so_pcb;
 
 	/*
 	 * Protocol specific data.
@@ -998,7 +1011,7 @@ procstat_get_socket_info_kvm(kvm_t *kd, 
 					    (void *)s.so_pcb);
 				} else
 					sock->inp_ppcb =
-					    (caddr_t)inpcb.inp_ppcb;
+					    (uintptr_t)inpcb.inp_ppcb;
 			}
 		}
 		break;
@@ -1011,7 +1024,7 @@ procstat_get_socket_info_kvm(kvm_t *kd, 
 			} else if (unpcb.unp_conn) {
 				sock->so_rcv_sb_state = s.so_rcv.sb_state;
 				sock->so_snd_sb_state = s.so_snd.sb_state;
-				sock->unp_conn = (caddr_t)unpcb.unp_conn;
+				sock->unp_conn = (uintptr_t)unpcb.unp_conn;
 			}
 		}
 		break;
@@ -1026,13 +1039,50 @@ fail:
 }
 
 static int
-procstat_get_socket_info_sysctl(struct filestat *fst __unused, struct sockstat *sock __unused,
+procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock,
     char *errbuf __unused)
 {
+	struct kinfo_file *kif;
 
-	warnx("not implemented: %s:%d", __FUNCTION__, __LINE__);
-	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
-	return (1);
+	assert(sock);
+	assert(fst);
+	bzero(sock, sizeof(*sock));
+	kif = fst->fs_typedep;
+	if (kif == NULL)
+		return (0);
+
+	/*
+	 * Fill in known data.
+	 */
+	sock->type = kif->kf_sock_type;
+	sock->proto = kif->kf_sock_protocol;
+	sock->dom_family = kif->kf_sock_domain;
+	sock->so_pcb = kif->kf_un.sock.kf_sock_pcb;
+	strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname));
+
+	/*
+	 * Protocol specific data.
+	 */
+	switch(sock->dom_family) {
+	case AF_INET:
+	case AF_INET6:
+		if (sock->proto == IPPROTO_TCP)
+			sock->inp_ppcb = kif->kf_un.sock.kf_sock_inpcb;
+		break;
+	case AF_UNIX:
+		if (kif->kf_un.sock.kf_sock_unpconn != 0) {
+				sock->so_rcv_sb_state =
+				    kif->kf_un.sock.kf_sock_rcv_sb_state;
+				sock->so_snd_sb_state =
+				    kif->kf_un.sock.kf_sock_snd_sb_state;
+				sock->unp_conn =
+				    kif->kf_un.sock.kf_sock_unpconn;
+		}
+		break;
+	default:
+		break;
+	}
+	return (0);
 }
 
 static int

Modified: projects/libprocstat/usr.bin/fstat/libprocstat.h
==============================================================================
--- projects/libprocstat/usr.bin/fstat/libprocstat.h	Sat Jul 25 19:43:46 2009	(r195876)
+++ projects/libprocstat/usr.bin/fstat/libprocstat.h	Sat Jul 25 20:26:54 2009	(r195877)
@@ -115,21 +115,21 @@ struct ptsstat {
 	char	devname[SPECNAMELEN + 1];
 };
 struct pipestat {
-	caddr_t	addr;
-	caddr_t	peer;
-	size_t	buffer_cnt;
+	uint64_t	addr;
+	uint64_t	peer;
+	size_t		buffer_cnt;
 };
 struct sockstat {
-	int	type;
-	int	proto;
-	int	dom_family;
-	caddr_t	so_addr;
-	caddr_t	so_pcb;
-	caddr_t	inp_ppcb;
-	caddr_t	unp_conn;
-	int	so_snd_sb_state;
-	int	so_rcv_sb_state;
-	char	dname[32];
+	int		type;
+	int		proto;
+	int		dom_family;
+	uint64_t	so_addr;
+	uint64_t	so_pcb;
+	uint64_t	inp_ppcb;
+	uint64_t	unp_conn;
+	int		so_snd_sb_state;
+	int		so_rcv_sb_state;
+	char		dname[32];
 };
 
 /* XXX: sort structs. */


More information about the svn-src-projects mailing list