svn commit: r185717 - in releng/7.1: lib/libutil sys sys/kern sys/sys usr.bin/procstat

Peter Wemm peter at FreeBSD.org
Sat Dec 6 12:36:48 PST 2008


Author: peter
Date: Sat Dec  6 20:36:46 2008
New Revision: 185717
URL: http://svn.freebsd.org/changeset/base/185717

Log:
  MF7: 185716 (head 185548 + followups).  KERN_PROC_* kinfo updates.
  
  Approved by:	re (kensmith)

Added:
  releng/7.1/lib/libutil/kinfo_getfile.c
     - copied unchanged from r185716, stable/7/lib/libutil/kinfo_getfile.c
  releng/7.1/lib/libutil/kinfo_getvmmap.c
     - copied unchanged from r185716, stable/7/lib/libutil/kinfo_getvmmap.c
Modified:
  releng/7.1/lib/libutil/   (props changed)
  releng/7.1/lib/libutil/Makefile
  releng/7.1/lib/libutil/libutil.h
  releng/7.1/sys/   (props changed)
  releng/7.1/sys/kern/kern_descrip.c
  releng/7.1/sys/kern/kern_proc.c
  releng/7.1/sys/sys/sysctl.h
  releng/7.1/sys/sys/user.h
  releng/7.1/usr.bin/procstat/   (props changed)
  releng/7.1/usr.bin/procstat/Makefile
  releng/7.1/usr.bin/procstat/procstat_files.c
  releng/7.1/usr.bin/procstat/procstat_vm.c

Modified: releng/7.1/lib/libutil/Makefile
==============================================================================
--- releng/7.1/lib/libutil/Makefile	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/lib/libutil/Makefile	Sat Dec  6 20:36:46 2008	(r185717)
@@ -9,7 +9,8 @@ LIB=	util
 SHLIB_MAJOR= 7
 
 SRCS=	_secure_path.c auth.c gr_util.c expand_number.c flopen.c fparseln.c \
-	humanize_number.c kld.c login.c login_auth.c login_cap.c login_class.c \
+	humanize_number.c kinfo_getfile.c kinfo_getvmmap.c kld.c \
+	login.c login_auth.c login_cap.c login_class.c \
 	login_crypt.c login_ok.c login_times.c login_tty.c logout.c \
 	logwtmp.c pidfile.c property.c pty.c pw_util.c realhostname.c \
 	stub.c trimdomain.c uucplock.c

Copied: releng/7.1/lib/libutil/kinfo_getfile.c (from r185716, stable/7/lib/libutil/kinfo_getfile.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ releng/7.1/lib/libutil/kinfo_getfile.c	Sat Dec  6 20:36:46 2008	(r185717, copy of r185716, stable/7/lib/libutil/kinfo_getfile.c)
@@ -0,0 +1,72 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libutil.h"
+
+struct kinfo_file *
+kinfo_getfile(pid_t pid, int *cntp)
+{
+	int mib[4];
+	int error;
+	int cnt;
+	size_t len;
+	char *buf, *bp, *eb;
+	struct kinfo_file *kif, *kp, *kf;
+
+	len = 0;
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	mib[2] = KERN_PROC_FILEDESC;
+	mib[3] = pid;
+
+	error = sysctl(mib, 4, NULL, &len, NULL, 0);
+	if (error)
+		return (0);
+	len = len * 4 / 3;
+	buf = malloc(len);
+	if (buf == NULL)
+		return (0);
+	error = sysctl(mib, 4, buf, &len, NULL, 0);
+	if (error) {
+		free(buf);
+		return (0);
+	}
+	/* Pass 1: count items */
+	cnt = 0;
+	bp = buf;
+	eb = buf + len;
+	while (bp < eb) {
+		kf = (struct kinfo_file *)(uintptr_t)bp;
+		bp += kf->kf_structsize;
+		cnt++;
+	}
+
+	kif = calloc(cnt, sizeof(*kif));
+	if (kif == NULL) {
+		free(buf);
+		return (0);
+	}
+	bp = buf;
+	eb = buf + len;
+	kp = kif;
+	/* Pass 2: unpack */
+	while (bp < eb) {
+		kf = (struct kinfo_file *)(uintptr_t)bp;
+		/* Copy/expand into pre-zeroed buffer */
+		memcpy(kp, kf, kf->kf_structsize);
+		/* Advance to next packed record */
+		bp += kf->kf_structsize;
+		/* Set field size to fixed length, advance */
+		kp->kf_structsize = sizeof(*kp);
+		kp++;
+	}
+	free(buf);
+	*cntp = cnt;
+	return (kif);	/* Caller must free() return value */
+}

Copied: releng/7.1/lib/libutil/kinfo_getvmmap.c (from r185716, stable/7/lib/libutil/kinfo_getvmmap.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ releng/7.1/lib/libutil/kinfo_getvmmap.c	Sat Dec  6 20:36:46 2008	(r185717, copy of r185716, stable/7/lib/libutil/kinfo_getvmmap.c)
@@ -0,0 +1,72 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libutil.h"
+
+struct kinfo_vmentry *
+kinfo_getvmmap(pid_t pid, int *cntp)
+{
+	int mib[4];
+	int error;
+	int cnt;
+	size_t len;
+	char *buf, *bp, *eb;
+	struct kinfo_vmentry *kiv, *kp, *kv;
+
+	len = 0;
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	mib[2] = KERN_PROC_VMMAP;
+	mib[3] = pid;
+
+	error = sysctl(mib, 4, NULL, &len, NULL, 0);
+	if (error)
+		return (0);
+	len = len * 4 / 3;
+	buf = malloc(len);
+	if (buf == NULL)
+		return (0);
+	error = sysctl(mib, 4, buf, &len, NULL, 0);
+	if (error) {
+		free(buf);
+		return (0);
+	}
+	/* Pass 1: count items */
+	cnt = 0;
+	bp = buf;
+	eb = buf + len;
+	while (bp < eb) {
+		kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+		bp += kv->kve_structsize;
+		cnt++;
+	}
+
+	kiv = calloc(cnt, sizeof(*kiv));
+	if (kiv == NULL) {
+		free(buf);
+		return (0);
+	}
+	bp = buf;
+	eb = buf + len;
+	kp = kiv;
+	/* Pass 2: unpack */
+	while (bp < eb) {
+		kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+		/* Copy/expand into pre-zeroed buffer */
+		memcpy(kp, kv, kv->kve_structsize);
+		/* Advance to next packed record */
+		bp += kv->kve_structsize;
+		/* Set field size to fixed length, advance */
+		kp->kve_structsize = sizeof(*kp);
+		kp++;
+	}
+	free(buf);
+	*cntp = cnt;
+	return (kiv);	/* Caller must free() return value */
+}

Modified: releng/7.1/lib/libutil/libutil.h
==============================================================================
--- releng/7.1/lib/libutil/libutil.h	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/lib/libutil/libutil.h	Sat Dec  6 20:36:46 2008	(r185717)
@@ -64,6 +64,8 @@ struct termios;
 struct winsize;
 struct utmp;
 struct in_addr;
+struct kinfo_file;
+struct kinfo_vmentry;
 
 __BEGIN_DECLS
 void	clean_environment(const char * const *_white,
@@ -99,6 +101,10 @@ int	realhostname_sa(char *host, size_t h
 
 int	kld_isloaded(const char *name);
 int	kld_load(const char *name);
+struct kinfo_file *
+	kinfo_getfile(pid_t _pid, int *_cntp);
+struct kinfo_vmentry *
+	kinfo_getvmmap(pid_t _pid, int *_cntp);
 
 #ifdef _STDIO_H_	/* avoid adding new includes */
 char   *fparseln(FILE *, size_t *, size_t *, const char[3], int);

Modified: releng/7.1/sys/kern/kern_descrip.c
==============================================================================
--- releng/7.1/sys/kern/kern_descrip.c	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/sys/kern/kern_descrip.c	Sat Dec  6 20:36:46 2008	(r185717)
@@ -2570,6 +2570,243 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD,
     0, 0, sysctl_kern_file, "S,xfile", "Entire file table");
 
+#ifdef KINFO_OFILE_SIZE
+CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
+#endif
+
+/* Compatability with early 7-stable */
+static int
+export_vnode_for_osysctl(struct vnode *vp, int type,
+    struct kinfo_ofile *kif, struct filedesc *fdp, struct sysctl_req *req)
+{
+	int error;
+	char *fullpath, *freepath;
+	int vfslocked;
+
+	bzero(kif, sizeof(*kif));
+	kif->kf_structsize = sizeof(*kif);
+
+	vref(vp);
+	kif->kf_fd = type;
+	kif->kf_type = KF_TYPE_VNODE;
+	/* This function only handles directories. */
+	KASSERT(vp->v_type == VDIR, ("export_vnode_for_osysctl: vnode not directory"));
+	kif->kf_vnode_type = KF_VTYPE_VDIR;
+
+	/*
+	 * This is not a true file descriptor, so we set a bogus refcount
+	 * and offset to indicate these fields should be ignored.
+	 */
+	kif->kf_ref_count = -1;
+	kif->kf_offset = -1;
+
+	freepath = NULL;
+	fullpath = "-";
+	FILEDESC_SUNLOCK(fdp);
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+	vn_fullpath(curthread, vp, &fullpath, &freepath);
+	vput(vp);
+	VFS_UNLOCK_GIANT(vfslocked);
+	strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
+	if (freepath != NULL)
+		free(freepath, M_TEMP);
+	error = SYSCTL_OUT(req, kif, sizeof(*kif));
+	FILEDESC_SLOCK(fdp);
+	return (error);
+}
+
+/*
+ * Get per-process file descriptors for use by procstat(1), et al.
+ */
+static int
+sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
+{
+	char *fullpath, *freepath;
+	struct kinfo_ofile *kif;
+	struct filedesc *fdp;
+	int error, i, *name;
+	struct socket *so;
+	struct vnode *vp;
+	struct file *fp;
+	struct proc *p;
+	int vfslocked;
+
+	name = (int *)arg1;
+	if ((p = pfind((pid_t)name[0])) == NULL)
+		return (ESRCH);
+	if ((error = p_candebug(curthread, p))) {
+		PROC_UNLOCK(p);
+		return (error);
+	}
+	fdp = fdhold(p);
+	PROC_UNLOCK(p);
+	if (fdp == NULL)
+		return (ENOENT);
+	kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
+	FILEDESC_SLOCK(fdp);
+	if (fdp->fd_cdir != NULL)
+		export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
+				fdp, req);
+	if (fdp->fd_rdir != NULL)
+		export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
+				fdp, req);
+	if (fdp->fd_jdir != NULL)
+		export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
+				fdp, req);
+	for (i = 0; i < fdp->fd_nfiles; i++) {
+		if ((fp = fdp->fd_ofiles[i]) == NULL)
+			continue;
+		bzero(kif, sizeof(*kif));
+		kif->kf_structsize = sizeof(*kif);
+		FILE_LOCK(fp);
+		vp = NULL;
+		so = NULL;
+		kif->kf_fd = i;
+		switch (fp->f_type) {
+		case DTYPE_VNODE:
+			kif->kf_type = KF_TYPE_VNODE;
+			vp = fp->f_vnode;
+			vref(vp);
+			break;
+
+		case DTYPE_SOCKET:
+			kif->kf_type = KF_TYPE_SOCKET;
+			so = fp->f_data;
+			break;
+
+		case DTYPE_PIPE:
+			kif->kf_type = KF_TYPE_PIPE;
+			break;
+
+		case DTYPE_FIFO:
+			kif->kf_type = KF_TYPE_FIFO;
+			vp = fp->f_vnode;
+			vref(vp);
+			break;
+
+		case DTYPE_KQUEUE:
+			kif->kf_type = KF_TYPE_KQUEUE;
+			break;
+
+		case DTYPE_CRYPTO:
+			kif->kf_type = KF_TYPE_CRYPTO;
+			break;
+
+		case DTYPE_MQUEUE:
+			kif->kf_type = KF_TYPE_MQUEUE;
+			break;
+
+		default:
+			kif->kf_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;
+		FILE_UNLOCK(fp);
+		if (vp != NULL) {
+			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;
+				break;
+			case VSOCK:
+				kif->kf_vnode_type = KF_VTYPE_VSOCK;
+				break;
+			case VFIFO:
+				kif->kf_vnode_type = KF_VTYPE_VFIFO;
+				break;
+			case VBAD:
+				kif->kf_vnode_type = KF_VTYPE_VBAD;
+				break;
+			default:
+				kif->kf_vnode_type = KF_VTYPE_UNKNOWN;
+				break;
+			}
+			/*
+			 * It is OK to drop the filedesc lock here as we will
+			 * re-validate and re-evaluate its properties when
+			 * the loop continues.
+			 */
+			freepath = NULL;
+			fullpath = "-";
+			FILEDESC_SUNLOCK(fdp);
+			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+			vn_fullpath(curthread, vp, &fullpath, &freepath);
+			vput(vp);
+			VFS_UNLOCK_GIANT(vfslocked);
+			strlcpy(kif->kf_path, fullpath,
+			    sizeof(kif->kf_path));
+			if (freepath != NULL)
+				free(freepath, M_TEMP);
+			FILEDESC_SLOCK(fdp);
+		}
+		if (so != NULL) {
+			struct sockaddr *sa;
+
+			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;
+		}
+		error = SYSCTL_OUT(req, kif, sizeof(*kif));
+		if (error)
+			break;
+	}
+	FILEDESC_SUNLOCK(fdp);
+	fddrop(fdp);
+	free(kif, M_TEMP);
+	return (0);
+}
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc, CTLFLAG_RD,
+    sysctl_kern_proc_ofiledesc, "Process ofiledesc entries");
+
+#ifdef KINFO_FILE_SIZE
+CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
+#endif
+
 static int
 export_vnode_for_sysctl(struct vnode *vp, int type,
     struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req)
@@ -2579,7 +2816,6 @@ export_vnode_for_sysctl(struct vnode *vp
 	int vfslocked;
 
 	bzero(kif, sizeof(*kif));
-	kif->kf_structsize = sizeof(*kif);
 
 	vref(vp);
 	kif->kf_fd = type;
@@ -2606,7 +2842,11 @@ export_vnode_for_sysctl(struct vnode *vp
 	strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
 	if (freepath != NULL)
 		free(freepath, M_TEMP);
-	error = SYSCTL_OUT(req, kif, sizeof(*kif));
+	/* 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);
 }
@@ -2653,7 +2893,6 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 		if ((fp = fdp->fd_ofiles[i]) == NULL)
 			continue;
 		bzero(kif, sizeof(*kif));
-		kif->kf_structsize = sizeof(*kif);
 		FILE_LOCK(fp);
 		vp = NULL;
 		so = NULL;
@@ -2785,7 +3024,12 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 			kif->kf_sock_type = so->so_type;
 			kif->kf_sock_protocol = so->so_proto->pr_protocol;
 		}
-		error = SYSCTL_OUT(req, kif, sizeof(*kif));
+		/* 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);
 		if (error)
 			break;
 	}

Modified: releng/7.1/sys/kern/kern_proc.c
==============================================================================
--- releng/7.1/sys/kern/kern_proc.c	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/sys/kern/kern_proc.c	Sat Dec  6 20:36:46 2008	(r185717)
@@ -32,6 +32,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_compat.h"
 #include "opt_ddb.h"
 #include "opt_kdtrace.h"
 #include "opt_ktrace.h"
@@ -1339,13 +1340,18 @@ sysctl_kern_proc_sv_name(SYSCTL_HANDLER_
 	return (sysctl_handle_string(oidp, sv_name, 0, req));
 }
 
+#ifdef KINFO_OVMENTRY_SIZE
+CTASSERT(sizeof(struct kinfo_ovmentry) == KINFO_OVMENTRY_SIZE);
+#endif
+
+/* Compatability with early 7-stable */
 static int
-sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS)
+sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS)
 {
 	vm_map_entry_t entry, tmp_entry;
 	unsigned int last_timestamp;
 	char *fullpath, *freepath;
-	struct kinfo_vmentry *kve;
+	struct kinfo_ovmentry *kve;
 	struct vattr va;
 	struct ucred *cred;
 	int error, *name;
@@ -1501,6 +1507,176 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_AR
 	return (error);
 }
 
+#ifdef KINFO_VMENTRY_SIZE
+CTASSERT(sizeof(struct kinfo_vmentry) == KINFO_VMENTRY_SIZE);
+#endif
+
+static int
+sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS)
+{
+	vm_map_entry_t entry, tmp_entry;
+	unsigned int last_timestamp;
+	char *fullpath, *freepath;
+	struct kinfo_vmentry *kve;
+	struct vattr va;
+	struct ucred *cred;
+	int error, *name;
+	struct vnode *vp;
+	struct proc *p;
+	vm_map_t map;
+
+	name = (int *)arg1;
+	if ((p = pfind((pid_t)name[0])) == NULL)
+		return (ESRCH);
+	if (p->p_flag & P_WEXIT) {
+		PROC_UNLOCK(p);
+		return (ESRCH);
+	}
+	if ((error = p_candebug(curthread, p))) {
+		PROC_UNLOCK(p);
+		return (error);
+	}
+	_PHOLD(p);
+	PROC_UNLOCK(p);
+
+	kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK);
+
+	map = &p->p_vmspace->vm_map;	/* XXXRW: More locking required? */
+	vm_map_lock_read(map);
+	for (entry = map->header.next; entry != &map->header;
+	    entry = entry->next) {
+		vm_object_t obj, tobj, lobj;
+		vm_offset_t addr;
+		int vfslocked;
+
+		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
+			continue;
+
+		bzero(kve, sizeof(*kve));
+
+		kve->kve_private_resident = 0;
+		obj = entry->object.vm_object;
+		if (obj != NULL) {
+			VM_OBJECT_LOCK(obj);
+			if (obj->shadow_count == 1)
+				kve->kve_private_resident =
+				    obj->resident_page_count;
+		}
+		kve->kve_resident = 0;
+		addr = entry->start;
+		while (addr < entry->end) {
+			if (pmap_extract(map->pmap, addr))
+				kve->kve_resident++;
+			addr += PAGE_SIZE;
+		}
+
+		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
+			if (tobj != obj)
+				VM_OBJECT_LOCK(tobj);
+			if (lobj != obj)
+				VM_OBJECT_UNLOCK(lobj);
+			lobj = tobj;
+		}
+
+		kve->kve_fileid = 0;
+		kve->kve_fsid = 0;
+		freepath = NULL;
+		fullpath = "";
+		if (lobj) {
+			vp = NULL;
+			switch(lobj->type) {
+			case OBJT_DEFAULT:
+				kve->kve_type = KVME_TYPE_DEFAULT;
+				break;
+			case OBJT_VNODE:
+				kve->kve_type = KVME_TYPE_VNODE;
+				vp = lobj->handle;
+				vref(vp);
+				break;
+			case OBJT_SWAP:
+				kve->kve_type = KVME_TYPE_SWAP;
+				break;
+			case OBJT_DEVICE:
+				kve->kve_type = KVME_TYPE_DEVICE;
+				break;
+			case OBJT_PHYS:
+				kve->kve_type = KVME_TYPE_PHYS;
+				break;
+			case OBJT_DEAD:
+				kve->kve_type = KVME_TYPE_DEAD;
+				break;
+			default:
+				kve->kve_type = KVME_TYPE_UNKNOWN;
+				break;
+			}
+			if (lobj != obj)
+				VM_OBJECT_UNLOCK(lobj);
+
+			kve->kve_ref_count = obj->ref_count;
+			kve->kve_shadow_count = obj->shadow_count;
+			VM_OBJECT_UNLOCK(obj);
+			if (vp != NULL) {
+				vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY,
+				    curthread);
+				vn_fullpath(curthread, vp, &fullpath,
+				    &freepath);
+				cred = curthread->td_ucred;
+				if (VOP_GETATTR(vp, &va, cred, curthread) == 0) {
+					kve->kve_fileid = va.va_fileid;
+					kve->kve_fsid = va.va_fsid;
+				}
+				vput(vp);
+				VFS_UNLOCK_GIANT(vfslocked);
+			}
+		} else {
+			kve->kve_type = KVME_TYPE_NONE;
+			kve->kve_ref_count = 0;
+			kve->kve_shadow_count = 0;
+		}
+
+		kve->kve_start = entry->start;
+		kve->kve_end = entry->end;
+		kve->kve_offset = entry->offset;
+
+		if (entry->protection & VM_PROT_READ)
+			kve->kve_protection |= KVME_PROT_READ;
+		if (entry->protection & VM_PROT_WRITE)
+			kve->kve_protection |= KVME_PROT_WRITE;
+		if (entry->protection & VM_PROT_EXECUTE)
+			kve->kve_protection |= KVME_PROT_EXEC;
+
+		if (entry->eflags & MAP_ENTRY_COW)
+			kve->kve_flags |= KVME_FLAG_COW;
+		if (entry->eflags & MAP_ENTRY_NEEDS_COPY)
+			kve->kve_flags |= KVME_FLAG_NEEDS_COPY;
+
+		strlcpy(kve->kve_path, fullpath, sizeof(kve->kve_path));
+		if (freepath != NULL)
+			free(freepath, M_TEMP);
+
+		last_timestamp = map->timestamp;
+		vm_map_unlock_read(map);
+		/* Pack record size down */
+		kve->kve_structsize = offsetof(struct kinfo_vmentry, kve_path) +
+		    strlen(kve->kve_path) + 1;
+		kve->kve_structsize = roundup(kve->kve_structsize,
+		    sizeof(uint64_t));
+		error = SYSCTL_OUT(req, kve, kve->kve_structsize);
+		vm_map_lock_read(map);
+		if (error)
+			break;
+		if (last_timestamp + 1 != map->timestamp) {
+			vm_map_lookup_entry(map, addr - 1, &tmp_entry);
+			entry = tmp_entry;
+		}
+	}
+	vm_map_unlock_read(map);
+	PRELE(p);
+	free(kve, M_TEMP);
+	return (error);
+}
+
 #if defined(STACK) || defined(DDB)
 static int
 sysctl_kern_proc_kstack(SYSCTL_HANDLER_ARGS)
@@ -1674,6 +1850,9 @@ static SYSCTL_NODE(_kern_proc, (KERN_PRO
 static SYSCTL_NODE(_kern_proc, (KERN_PROC_PROC | KERN_PROC_INC_THREAD), proc_td,
 	CTLFLAG_RD, sysctl_kern_proc, "Return process table, no threads");
 
+static SYSCTL_NODE(_kern_proc, KERN_PROC_OVMMAP, ovmmap, CTLFLAG_RD,
+	sysctl_kern_proc_ovmmap, "Old Process vm map entries");
+
 static SYSCTL_NODE(_kern_proc, KERN_PROC_VMMAP, vmmap, CTLFLAG_RD,
 	sysctl_kern_proc_vmmap, "Process vm map entries");
 

Modified: releng/7.1/sys/sys/sysctl.h
==============================================================================
--- releng/7.1/sys/sys/sysctl.h	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/sys/sys/sysctl.h	Sat Dec  6 20:36:46 2008	(r185717)
@@ -463,13 +463,16 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e
 #define	KERN_PROC_RGID		10	/* by real group id */
 #define	KERN_PROC_GID		11	/* by effective group id */
 #define	KERN_PROC_PATHNAME	12	/* path to executable */
-#define	KERN_PROC_VMMAP		13	/* VM map entries for process */
-#define	KERN_PROC_FILEDESC	14	/* File descriptors for process */
+#define	KERN_PROC_OVMMAP	13	/* Old VM map entries for process */
+#define	KERN_PROC_OFILEDESC	14	/* Old file descriptors for process */
 #define	KERN_PROC_KSTACK	15	/* Kernel stacks for process */
 #define	KERN_PROC_INC_THREAD	0x10	/*
 					 * modifier for pid, pgrp, tty,
 					 * uid, ruid, gid, rgid and proc
+					 * This effectively uses 16-31
 					 */
+#define	KERN_PROC_VMMAP		32	/* VM map entries for process */
+#define	KERN_PROC_FILEDESC	33	/* File descriptors for process */
 
 /*
  * KERN_IPC identifiers

Modified: releng/7.1/sys/sys/user.h
==============================================================================
--- releng/7.1/sys/sys/user.h	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/sys/sys/user.h	Sat Dec  6 20:36:46 2008	(r185717)
@@ -271,20 +271,55 @@ struct user {
 #define	KF_FLAG_DIRECT		0x00000040
 #define	KF_FLAG_HASLOCK		0x00000080
 
-struct kinfo_file {
+/*
+ * Old format.  Has variable hidden padding due to alignment.
+ * This is a compatability hack for pre-build 7.1 packages.
+ */
+#if defined(__amd64__)
+#define	KINFO_OFILE_SIZE	1328
+#endif
+#if defined(__i386__)
+#define	KINFO_OFILE_SIZE	1324
+#endif
+
+struct kinfo_ofile {
 	int	kf_structsize;			/* Size of kinfo_file. */
 	int	kf_type;			/* Descriptor type. */
 	int	kf_fd;				/* Array index. */
 	int	kf_ref_count;			/* Reference count. */
 	int	kf_flags;			/* Flags. */
+	/* XXX Hidden alignment padding here on amd64 */
 	off_t	kf_offset;			/* Seek location. */
 	int	kf_vnode_type;			/* Vnode type. */
 	int	kf_sock_domain;			/* Socket domain. */
 	int	kf_sock_type;			/* Socket type. */
 	int	kf_sock_protocol;		/* Socket protocol. */
-	char	kf_path[PATH_MAX];		/* Path to file, if any. */
+	char	kf_path[PATH_MAX];	/* Path to file, if any. */
+	struct sockaddr_storage kf_sa_local;	/* Socket address. */
+	struct sockaddr_storage	kf_sa_peer;	/* Peer address. */
+};
+
+#if defined(__amd64__) || defined(__i386__)
+#define	KINFO_FILE_SIZE	1392
+#endif
+
+struct kinfo_file {
+	int	kf_structsize;			/* Variable size of record. */
+	int	kf_type;			/* Descriptor type. */
+	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. */
+	int	kf_sock_domain;			/* Socket domain. */
+	int	kf_sock_type;			/* Socket type. */
+	int	kf_sock_protocol;		/* Socket protocol. */
 	struct sockaddr_storage kf_sa_local;	/* Socket address. */
 	struct sockaddr_storage	kf_sa_peer;	/* Peer address. */
+	int	_kf_ispare[16];			/* Space for more stuff. */
+	/* Truncated before copyout in sysctl */
+	char	kf_path[PATH_MAX];		/* Path to file, if any. */
 };
 
 /*
@@ -307,11 +342,18 @@ struct kinfo_file {
 #define	KVME_FLAG_COW		0x00000001
 #define	KVME_FLAG_NEEDS_COPY	0x00000002
 
-struct kinfo_vmentry {
+#if defined(__amd64__)
+#define	KINFO_OVMENTRY_SIZE	1168
+#endif
+#if defined(__i386__)
+#define	KINFO_OVMENTRY_SIZE	1128
+#endif
+
+struct kinfo_ovmentry {
 	int	 kve_structsize;		/* Size of kinfo_vmmapentry. */
 	int	 kve_type;			/* Type of map entry. */
-	void	*kve_start;			/* Starting pointer. */
-	void	*kve_end;			/* Finishing pointer. */
+	void	*kve_start;			/* Starting address. */
+	void	*kve_end;			/* Finishing address. */
 	int	 kve_flags;			/* Flags on map entry. */
 	int	 kve_resident;			/* Number of resident pages. */
 	int	 kve_private_resident;		/* Number of private pages. */
@@ -321,11 +363,35 @@ struct kinfo_vmentry {
 	char	 kve_path[PATH_MAX];		/* Path to VM obj, if any. */
 	void	*_kve_pspare[8];		/* Space for more stuff. */
 	off_t	 kve_offset;			/* Mapping offset in object */
-	uint64_t kve_fileid;			/* inode number of vnode */
+	uint64_t kve_fileid;			/* inode number if vnode */
 	dev_t	 kve_fsid;			/* dev_t of vnode location */
 	int	 _kve_ispare[3];		/* Space for more stuff. */
 };
 
+#if defined(__amd64__) || defined(__i386__)
+#define	KINFO_VMENTRY_SIZE	1160
+#endif
+
+struct kinfo_vmentry {
+	int	 kve_structsize;		/* Variable size of record. */
+	int	 kve_type;			/* Type of map entry. */
+	uint64_t kve_start;			/* Starting address. */
+	uint64_t kve_end;			/* Finishing address. */
+	uint64_t kve_offset;			/* Mapping offset in object */
+	uint64_t kve_fileid;			/* inode number if vnode */
+	uint32_t kve_fsid;			/* dev_t of vnode location */
+	int	 kve_flags;			/* Flags on map entry. */
+	int	 kve_resident;			/* Number of resident pages. */
+	int	 kve_private_resident;		/* Number of private pages. */
+	int	 kve_protection;		/* Protection bitmask. */
+	int	 kve_ref_count;			/* VM obj ref count. */
+	int	 kve_shadow_count;		/* VM obj shadow count. */
+	int	 _kve_pad0;			/* 64bit align next field */
+	int	 _kve_ispare[16];		/* Space for more stuff. */
+	/* Truncated before copyout in sysctl */
+	char	 kve_path[PATH_MAX];		/* Path to VM obj, if any. */
+};
+
 /*
  * The KERN_PROC_KSTACK sysctl allows a process to dump the kernel stacks of
  * another process as a series of entries.  Each stack is represented by a
@@ -337,12 +403,15 @@ struct kinfo_vmentry {
 #define	KKST_STATE_SWAPPED	1		/* Stack swapped out. */
 #define	KKST_STATE_RUNNING	2		/* Stack ephemeral. */
 
+#if defined(__amd64__) || defined(__i386__)
+#define	KINFO_KSTACK_SIZE	1096
+#endif
+
 struct kinfo_kstack {
 	lwpid_t	 kkst_tid;			/* ID of thread. */
 	int	 kkst_state;			/* Validity of stack. */
 	char	 kkst_trace[KKST_MAXLEN];	/* String representing stack. */
-	void	*_kkst_pspare[8];		/* Space for more stuff. */
-	int	 _kkst_ispare[8];		/* Space for more stuff. */
+	int	 _kkst_ispare[16];		/* Space for more stuff. */
 };
 
 #endif

Modified: releng/7.1/usr.bin/procstat/Makefile
==============================================================================
--- releng/7.1/usr.bin/procstat/Makefile	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/usr.bin/procstat/Makefile	Sat Dec  6 20:36:46 2008	(r185717)
@@ -12,4 +12,7 @@ SRCS=	procstat.c		\
 	procstat_threads.c	\
 	procstat_vm.c
 
+LDADD+=	-lutil
+DPADD+=	${LIBUTIL}
+
 .include <bsd.prog.mk>

Modified: releng/7.1/usr.bin/procstat/procstat_files.c
==============================================================================
--- releng/7.1/usr.bin/procstat/procstat_files.c	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/usr.bin/procstat/procstat_files.c	Sat Dec  6 20:36:46 2008	(r185717)
@@ -41,6 +41,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <libutil.h>
 
 #include "procstat.h"
 
@@ -134,42 +135,18 @@ void
 procstat_files(pid_t pid, struct kinfo_proc *kipp)
 {
 	struct kinfo_file *freep, *kif;
-	int error, name[4];
-	unsigned int i;
+	int i, cnt;
 	const char *str;
-	size_t len;
 
 	if (!hflag)
 		printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
 		    "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
 		    "PRO", "NAME");
 
-	name[0] = CTL_KERN;
-	name[1] = KERN_PROC;
-	name[2] = KERN_PROC_FILEDESC;
-	name[3] = pid;
-
-	error = sysctl(name, 4, NULL, &len, NULL, 0);
-	if (error < 0 && errno != ESRCH && errno != EPERM) {
-		warn("sysctl: kern.proc.filedesc: %d", pid);
-		return;
-	}
-	if (error < 0)
-		return;
-
-	freep = kif = malloc(len);
-	if (kif == NULL)
-		err(-1, "malloc");
-
-	if (sysctl(name, 4, kif, &len, NULL, 0) < 0) {
-		warn("sysctl: kern.proc.filedesc %d", pid);
-		free(freep);
-		return;
-	}
-
-	for (i = 0; i < len / sizeof(*kif); i++, kif++) {
-		if (kif->kf_structsize != sizeof(*kif))
-			errx(-1, "kinfo_file mismatch");
+	freep = kinfo_getfile(pid, &cnt);
+	for (i = 0; i < cnt; i++) {
+		kif = &freep[i];
+		
 		printf("%5d ", pid);
 		printf("%-16s ", kipp->ki_comm);
 		switch (kif->kf_fd) {

Modified: releng/7.1/usr.bin/procstat/procstat_vm.c
==============================================================================
--- releng/7.1/usr.bin/procstat/procstat_vm.c	Sat Dec  6 19:54:50 2008	(r185716)
+++ releng/7.1/usr.bin/procstat/procstat_vm.c	Sat Dec  6 20:36:46 2008	(r185717)
@@ -34,6 +34,8 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <libutil.h>
 
 #include "procstat.h"
 
@@ -41,10 +43,9 @@ void
 procstat_vm(pid_t pid, struct kinfo_proc *kipp __unused)
 {
 	struct kinfo_vmentry *freep, *kve;
-	int error, name[4], ptrwidth;
-	unsigned int i;
+	int ptrwidth;
+	int i, cnt;
 	const char *str;
-	size_t len;
 
 	ptrwidth = 2*sizeof(void *) + 2;
 	if (!hflag)
@@ -52,41 +53,12 @@ procstat_vm(pid_t pid, struct kinfo_proc
 		    "PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
 		    "PRES", "REF", "SHD", "FL", "TP", "PATH");
 
-	name[0] = CTL_KERN;
-	name[1] = KERN_PROC;
-	name[2] = KERN_PROC_VMMAP;
-	name[3] = pid;
-
-	len = 0;
-	error = sysctl(name, 4, NULL, &len, NULL, 0);
-	if (error < 0 && errno != ESRCH && errno != EPERM) {
-		warn("sysctl: kern.proc.vmmap: %d", pid);
-		return;
-	}
-	if (error < 0)
-		return;
-
-	/*
-	 * Especially if running procstat -sv, we may need room for more
-	 * mappings when printing than were present when we queried, so pad
-	 * out the allocation a bit.
-	 */
-	len += sizeof(*kve) * 3;
-	freep = kve = malloc(len);
-	if (kve == NULL)
-		err(-1, "malloc");
-	if (sysctl(name, 4, kve, &len, NULL, 0) < 0) {
-		warn("sysctl: kern.proc.vmmap: %d", pid);
-		free(freep);
-		return;
-	}
-
-	for (i = 0; i < (len / sizeof(*kve)); i++, kve++) {
-		if (kve->kve_structsize != sizeof(*kve))
-			errx(-1, "kinfo_vmentry structure mismatch");
+	freep = kinfo_getvmmap(pid, &cnt);
+	for (i = 0; i < cnt; i++) {
+		kve = &freep[i];
 		printf("%5d ", pid);
-		printf("%*p ", ptrwidth, kve->kve_start);
-		printf("%*p ", ptrwidth, kve->kve_end);
+		printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
+		printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
 		printf("%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
 		printf("%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
 		printf("%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");


More information about the svn-src-all mailing list