svn commit: r185462 - in user/peter/kinfo/sys: kern sys

Peter Wemm peter at FreeBSD.org
Sat Nov 29 16:18:21 PST 2008


Author: peter
Date: Sun Nov 30 00:18:21 2008
New Revision: 185462
URL: http://svn.freebsd.org/changeset/base/185462

Log:
  Implement copyout packing more along the lines of what I had in mind.
  Create a temporary duplicate implementation of old filedesc struct for
  pre-7.1 libgtop package.
  Todo: specific fd or addr request

Modified:
  user/peter/kinfo/sys/kern/kern_descrip.c
  user/peter/kinfo/sys/sys/sysctl.h
  user/peter/kinfo/sys/sys/user.h

Modified: user/peter/kinfo/sys/kern/kern_descrip.c
==============================================================================
--- user/peter/kinfo/sys/kern/kern_descrip.c	Sun Nov 30 00:11:48 2008	(r185461)
+++ user/peter/kinfo/sys/kern/kern_descrip.c	Sun Nov 30 00:18:21 2008	(r185462)
@@ -2509,6 +2509,265 @@ 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");
 
+
+/*
+ * Sadly, the libgtop port has already been compiled for 7.1, but the code
+ * does not do enough error checking and bad things might happen.  Even
+ * though we've not made a release with this stuff in it, the packages have
+ * apparently been built.
+ *
+ * This should be deleted shortly after 7.1 is released and we go back to
+ * 7-stable again.  If the libgtop port can be rebuilt, then this can get
+ * deleted before release.
+ */
+#ifdef KINFO_OFILE_SIZE
+CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
+#endif
+
+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);
+	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);
+	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;
+	struct tty *tp;
+	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);
+		vp = NULL;
+		so = NULL;
+		tp = NULL;
+		kif->kf_fd = i;
+		switch (fp->f_type) {
+		case DTYPE_VNODE:
+			kif->kf_type = KF_TYPE_VNODE;
+			vp = fp->f_vnode;
+			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;
+
+		case DTYPE_SHM:
+			kif->kf_type = KF_TYPE_SHM;
+			break;
+
+		case DTYPE_SEM:
+			kif->kf_type = KF_TYPE_SEM;
+			break;
+
+		case DTYPE_PTS:
+			kif->kf_type = KF_TYPE_PTS;
+			tp = fp->f_data;
+			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;
+		if (vp != NULL) {
+			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;
+				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);
+			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);
+			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;
+		}
+		if (tp != NULL) {
+			strlcpy(kif->kf_path, tty_devname(tp),
+			    sizeof(kif->kf_path));
+		}
+		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
@@ -2522,7 +2781,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;
@@ -2548,7 +2806,10 @@ 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));
+	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);
 }
@@ -2596,7 +2857,6 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 		if ((fp = fdp->fd_ofiles[i]) == NULL)
 			continue;
 		bzero(kif, sizeof(*kif));
-		kif->kf_structsize = sizeof(*kif);
 		vp = NULL;
 		so = NULL;
 		tp = NULL;
@@ -2743,7 +3003,11 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 			strlcpy(kif->kf_path, tty_devname(tp),
 			    sizeof(kif->kf_path));
 		}
-		error = SYSCTL_OUT(req, kif, sizeof(*kif));
+		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: user/peter/kinfo/sys/sys/sysctl.h
==============================================================================
--- user/peter/kinfo/sys/sys/sysctl.h	Sun Nov 30 00:11:48 2008	(r185461)
+++ user/peter/kinfo/sys/sys/sysctl.h	Sun Nov 30 00:18:21 2008	(r185462)
@@ -541,12 +541,13 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e
 #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_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
 					 */
+#define	KERN_PROC_FILEDESC	32	/* File descriptors for process */
 
 /*
  * KERN_IPC identifiers

Modified: user/peter/kinfo/sys/sys/user.h
==============================================================================
--- user/peter/kinfo/sys/sys/user.h	Sun Nov 30 00:11:48 2008	(r185461)
+++ user/peter/kinfo/sys/sys/user.h	Sun Nov 30 00:18:21 2008	(r185462)
@@ -236,9 +236,6 @@ struct user {
 	struct	kinfo_proc u_kproc;	/* eproc */
 };
 
-/* When exporting paths via sysctl, give a short version */
-#define	KPROC_PATH_MAX	256
-
 /*
  * The KERN_PROC_FILE sysctl allows a process to dump the file descriptor
  * array of another process.
@@ -280,8 +277,36 @@ struct user {
 #define	KF_FLAG_DIRECT		0x00000040
 #define	KF_FLAG_HASLOCK		0x00000080
 
+/*
+ * 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. */
+	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	560
+#define	KINFO_FILE_SIZE	1392
 #endif
 
 struct kinfo_file {
@@ -290,7 +315,7 @@ struct kinfo_file {
 	int	kf_fd;				/* Array index. */
 	int	kf_ref_count;			/* Reference count. */
 	int	kf_flags;			/* Flags. */
-	int	_kf_pad0;			/* Alignment */
+	int	_kf_pad0;			/* Round to 64 bit alignment */
 	uint64_t kf_offset;			/* Seek location. */
 	int	kf_vnode_type;			/* Vnode type. */
 	int	kf_sock_domain;			/* Socket domain. */
@@ -298,7 +323,9 @@ struct kinfo_file {
 	int	kf_sock_protocol;		/* Socket protocol. */
 	struct sockaddr_storage kf_sa_local;	/* Socket address. */
 	struct sockaddr_storage	kf_sa_peer;	/* Peer address. */
-	char	kf_path[KPROC_PATH_MAX];	/* Path to file, if any. */
+	int	_kf_ispare[16];			/* Space for more stuff. */
+	/* Truncated before copyout in sysctl */
+	char	kf_path[PATH_MAX];		/* Path to file, if any. */
 };
 
 /*
@@ -322,7 +349,7 @@ struct kinfo_file {
 #define	KVME_FLAG_NEEDS_COPY	0x00000002
 
 #if defined(__amd64__) || defined(__i386__)
-#define	KINFO_VMENTRY_SIZE	384
+#define	KINFO_VMENTRY_SIZE	1160
 #endif
 
 struct kinfo_vmentry {
@@ -339,8 +366,10 @@ struct kinfo_vmentry {
 	int	 kve_protection;		/* Protection bitmask. */
 	int	 kve_ref_count;			/* VM obj ref count. */
 	int	 kve_shadow_count;		/* VM obj shadow count. */
-	int	 _kve_ispare[15];		/* Space for more stuff. */
-	char	 kve_path[KPROC_PATH_MAX];	/* Path to VM obj, if any. */
+	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. */
 };
 
 /*


More information about the svn-src-user mailing list