Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Sep 2014 16:20:47 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r271976 - in head/sys: fs/devfs kern ofed/include/linux opencrypto sys
Message-ID:  <201409221620.s8MGKl08079806@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon Sep 22 16:20:47 2014
New Revision: 271976
URL: http://svnweb.freebsd.org/changeset/base/271976

Log:
  Add a new fo_fill_kinfo fileops method to add type-specific information to
  struct kinfo_file.
  - Move the various fill_*_info() methods out of kern_descrip.c and into the
    various file type implementations.
  - Rework the support for kinfo_ofile to generate a suitable kinfo_file object
    for each file and then convert that to a kinfo_ofile structure rather than
    keeping a second, different set of code that directly manipulates
    type-specific file information.
  - Remove the shm_path() and ksem_info() layering violations.
  
  Differential Revision:	https://reviews.freebsd.org/D775
  Reviewed by:	kib, glebius (earlier version)

Modified:
  head/sys/fs/devfs/devfs_vnops.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_event.c
  head/sys/kern/sys_pipe.c
  head/sys/kern/sys_procdesc.c
  head/sys/kern/sys_socket.c
  head/sys/kern/tty_pts.c
  head/sys/kern/uipc_mqueue.c
  head/sys/kern/uipc_sem.c
  head/sys/kern/uipc_shm.c
  head/sys/kern/vfs_vnops.c
  head/sys/ofed/include/linux/linux_compat.c
  head/sys/opencrypto/cryptodev.c
  head/sys/sys/file.h
  head/sys/sys/ksem.h
  head/sys/sys/mman.h

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c	Mon Sep 22 16:20:38 2014	(r271975)
+++ head/sys/fs/devfs/devfs_vnops.c	Mon Sep 22 16:20:47 2014	(r271976)
@@ -1700,6 +1700,7 @@ static struct fileops devfs_ops_f = {
 	.fo_chown =	vn_chown,
 	.fo_sendfile =	vn_sendfile,
 	.fo_seek =	vn_seek,
+	.fo_fill_kinfo = vn_fill_kinfo,
 	.fo_flags =	DFLAG_PASSABLE | DFLAG_SEEKABLE
 };
 

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Mon Sep 22 16:20:38 2014	(r271975)
+++ head/sys/kern/kern_descrip.c	Mon Sep 22 16:20:47 2014	(r271976)
@@ -47,27 +47,21 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/capsicum.h>
 #include <sys/conf.h>
-#include <sys/domain.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
 #include <sys/filio.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
-#include <sys/ksem.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/mman.h>
 #include <sys/mount.h>
-#include <sys/mqueue.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
 #include <sys/selinfo.h>
-#include <sys/pipe.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
-#include <sys/procdesc.h>
 #include <sys/protosw.h>
 #include <sys/racct.h>
 #include <sys/resourcevar.h>
@@ -79,10 +73,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 #include <sys/sysproto.h>
-#include <sys/tty.h>
 #include <sys/unistd.h>
-#include <sys/un.h>
-#include <sys/unpcb.h>
 #include <sys/user.h>
 #include <sys/vnode.h>
 #ifdef KTRACE
@@ -91,9 +82,6 @@ __FBSDID("$FreeBSD$");
 
 #include <net/vnet.h>
 
-#include <netinet/in.h>
-#include <netinet/in_pcb.h>
-
 #include <security/audit/audit.h>
 
 #include <vm/uma.h>
@@ -111,8 +99,6 @@ MALLOC_DECLARE(M_FADVISE);
 
 static uma_zone_t file_zone;
 
-void	(*ksem_info)(struct ksem *ks, char *path, size_t size, uint32_t *value);
-
 static int	closefp(struct filedesc *fdp, int fd, struct file *fp,
 		    struct thread *td, int holdleaders);
 static int	fd_first_free(struct filedesc *fdp, int low, int size);
@@ -121,14 +107,6 @@ static void	fdgrowtable(struct filedesc 
 static void	fdgrowtable_exp(struct filedesc *fdp, int nfd);
 static void	fdunused(struct filedesc *fdp, int fd);
 static void	fdused(struct filedesc *fdp, int fd);
-static int	fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
-static int	fill_procdesc_info(struct procdesc *pdp,
-		    struct kinfo_file *kif);
-static int	fill_pts_info(struct tty *tp, struct kinfo_file *kif);
-static int	fill_sem_info(struct file *fp, struct kinfo_file *kif);
-static int	fill_shm_info(struct file *fp, struct kinfo_file *kif);
-static int	fill_socket_info(struct socket *so, struct kinfo_file *kif);
-static int	fill_vnode_info(struct vnode *vp, struct kinfo_file *kif);
 static int	getmaxfd(struct proc *p);
 
 /*
@@ -2945,280 +2923,14 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,
     0, 0, sysctl_kern_file, "S,xfile", "Entire file table");
 
-#ifdef KINFO_OFILE_SIZE
-CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
-#endif
-
-#ifdef COMPAT_FREEBSD7
-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;
-
-	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. */
-	if (vp->v_type != VDIR) {
-		vrele(vp);
-		return (ENOTDIR);
-	}
-	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);
-	vrele(vp);
-	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 shmfd *shmfd;
-	struct socket *so;
-	struct vnode *vp;
-	struct ksem *ks;
-	struct file *fp;
-	struct proc *p;
-	struct tty *tp;
-
-	name = (int *)arg1;
-	error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
-	if (error != 0)
-		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; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
-		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
-			continue;
-		bzero(kif, sizeof(*kif));
-		kif->kf_structsize = sizeof(*kif);
-		ks = NULL;
-		vp = NULL;
-		so = NULL;
-		tp = NULL;
-		shmfd = 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;
-			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;
-			shmfd = fp->f_data;
-			break;
-
-		case DTYPE_SEM:
-			kif->kf_type = KF_TYPE_SEM;
-			ks = fp->f_data;
-			break;
-
-		case DTYPE_PTS:
-			kif->kf_type = KF_TYPE_PTS;
-			tp = fp->f_data;
-			break;
-
-		case DTYPE_PROCDESC:
-			kif->kf_type = KF_TYPE_PROCDESC;
-			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 = foffset_get(fp);
-		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);
-			vrele(vp);
-			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)
-			    == 0 && 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));
-		}
-		if (shmfd != NULL)
-			shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path));
-		if (ks != NULL && ksem_info != NULL)
-			ksem_info(ks, kif->kf_path, sizeof(kif->kf_path), NULL);
-		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||CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
-    "Process ofiledesc entries");
-#endif	/* COMPAT_FREEBSD7 */
-
 #ifdef KINFO_FILE_SIZE
 CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
 #endif
 
-struct export_fd_buf {
-	struct filedesc		*fdp;
-	struct sbuf 		*sb;
-	ssize_t			remainder;
-	struct kinfo_file	kif;
-};
-
 static int
-export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
-    int64_t offset, cap_rights_t *rightsp, struct export_fd_buf *efbuf)
+xlate_fflags(int fflags)
 {
-	struct {
+	static const struct {
 		int	fflag;
 		int	kf_fflag;
 	} fflags_table[] = {
@@ -3238,83 +2950,126 @@ export_fd_to_sb(void *data, int type, in
 		{ O_SHLOCK, KF_FLAG_SHLOCK },
 		{ O_TRUNC, KF_FLAG_TRUNC }
 	};
-#define	NFFLAGS	(sizeof(fflags_table) / sizeof(*fflags_table))
-	struct kinfo_file *kif;
-	struct vnode *vp;
-	int error, locked;
 	unsigned int i;
+	int kflags;
+
+	kflags = 0;
+	for (i = 0; i < nitems(fflags_table); i++)
+		if (fflags & fflags_table[i].fflag)
+			kflags |=  fflags_table[i].kf_fflag;
+	return (kflags);
+}
+
+/* Trim unused data from kf_path by truncating the structure size. */
+static void
+pack_kinfo(struct kinfo_file *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));
+}
+
+static void
+export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp,
+    struct kinfo_file *kif, struct filedesc *fdp)
+{
+	int error;
 
-	if (efbuf->remainder == 0)
-		return (0);
-	kif = &efbuf->kif;
 	bzero(kif, sizeof(*kif));
-	locked = efbuf->fdp != NULL;
-	switch (type) {
-	case KF_TYPE_FIFO:
-	case KF_TYPE_VNODE:
-		if (locked) {
-			FILEDESC_SUNLOCK(efbuf->fdp);
-			locked = 0;
-		}
-		vp = (struct vnode *)data;
-		error = fill_vnode_info(vp, kif);
-		vrele(vp);
-		break;
-	case KF_TYPE_SOCKET:
-		error = fill_socket_info((struct socket *)data, kif);
-		break;
-	case KF_TYPE_PIPE:
-		error = fill_pipe_info((struct pipe *)data, kif);
-		break;
-	case KF_TYPE_PTS:
-		error = fill_pts_info((struct tty *)data, kif);
-		break;
-	case KF_TYPE_PROCDESC:
-		error = fill_procdesc_info((struct procdesc *)data, kif);
-		break;
-	case KF_TYPE_SEM:
-		error = fill_sem_info((struct file *)data, kif);
-		break;
-	case KF_TYPE_SHM:
-		error = fill_shm_info((struct file *)data, kif);
-		break;
-	default:
-		error = 0;
-	}
-	if (error == 0)
-		kif->kf_status |= KF_ATTR_VALID;
 
-	/*
-	 * Translate file access flags.
-	 */
-	for (i = 0; i < NFFLAGS; i++)
-		if (fflags & fflags_table[i].fflag)
-			kif->kf_flags |=  fflags_table[i].kf_fflag;
+	/* Set a default type to allow for empty fill_kinfo() methods. */
+	kif->kf_type = KF_TYPE_UNKNOWN;
+	kif->kf_flags = xlate_fflags(fp->f_flag);
 	if (rightsp != NULL)
 		kif->kf_cap_rights = *rightsp;
 	else
 		cap_rights_init(&kif->kf_cap_rights);
 	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));
+	kif->kf_ref_count = fp->f_count;
+	kif->kf_offset = foffset_get(fp);
+
+	/*
+	 * This may drop the filedesc lock, so the 'fp' cannot be
+	 * accessed after this call.
+	 */
+	error = fo_fill_kinfo(fp, kif, fdp);
+	if (error == 0)
+		kif->kf_status |= KF_ATTR_VALID;
+	pack_kinfo(kif);
+}
+
+static void
+export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags,
+    struct kinfo_file *kif)
+{
+	int error;
+
+	bzero(kif, sizeof(*kif));
+
+	kif->kf_type = KF_TYPE_VNODE;
+	error = vn_fill_kinfo_vnode(vp, kif);
+	if (error == 0)
+		kif->kf_status |= KF_ATTR_VALID;
+	kif->kf_flags = xlate_fflags(fflags);
+	kif->kf_fd = fd;
+	kif->kf_ref_count = -1;
+	kif->kf_offset = -1;
+	pack_kinfo(kif);
+	vrele(vp);
+}
+
+struct export_fd_buf {
+	struct filedesc		*fdp;
+	struct sbuf 		*sb;
+	ssize_t			remainder;
+	struct kinfo_file	kif;
+};
+
+static int
+export_kinfo_to_sb(struct export_fd_buf *efbuf)
+{
+	struct kinfo_file *kif;
+
+	kif = &efbuf->kif;
 	if (efbuf->remainder != -1) {
 		if (efbuf->remainder < kif->kf_structsize) {
 			/* Terminate export. */
 			efbuf->remainder = 0;
-			if (efbuf->fdp != NULL && !locked)
-				FILEDESC_SLOCK(efbuf->fdp);
 			return (0);
 		}
 		efbuf->remainder -= kif->kf_structsize;
 	}
-	if (locked)
+	return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize));
+}
+
+static int
+export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp,
+    struct export_fd_buf *efbuf)
+{
+	int error;
+
+	if (efbuf->remainder == 0)
+		return (0);
+	export_file_to_kinfo(fp, fd, rightsp, &efbuf->kif, efbuf->fdp);
+	FILEDESC_SUNLOCK(efbuf->fdp);
+	error = export_kinfo_to_sb(efbuf);
+	FILEDESC_SLOCK(efbuf->fdp);
+	return (error);
+}
+
+static int
+export_vnode_to_sb(struct vnode *vp, int fd, int fflags,
+    struct export_fd_buf *efbuf)
+{
+	int error;
+
+	if (efbuf->remainder == 0)
+		return (0);
+	if (efbuf->fdp != NULL)
 		FILEDESC_SUNLOCK(efbuf->fdp);
-	error = sbuf_bcat(efbuf->sb, kif, kif->kf_structsize);
+	export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif);
+	error = export_kinfo_to_sb(efbuf);
 	if (efbuf->fdp != NULL)
 		FILEDESC_SLOCK(efbuf->fdp);
 	return (error);
@@ -3328,16 +3083,15 @@ export_fd_to_sb(void *data, int type, in
 int
 kern_proc_filedesc_out(struct proc *p,  struct sbuf *sb, ssize_t maxlen)
 {
+	struct thread *td;
 	struct file *fp;
 	struct filedesc *fdp;
 	struct export_fd_buf *efbuf;
 	struct vnode *cttyvp, *textvp, *tracevp;
-	int64_t offset;
-	void *data;
 	int error, i;
-	int type, refcnt, fflags;
 	cap_rights_t rights;
 
+	td = curthread;
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 
 	/* ktrace vnode */
@@ -3362,14 +3116,13 @@ kern_proc_filedesc_out(struct proc *p,  
 	efbuf->sb = sb;
 	efbuf->remainder = maxlen;
 	if (tracevp != NULL)
-		export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
-		    FREAD | FWRITE, -1, -1, NULL, efbuf);
+		export_vnode_to_sb(tracevp, KF_FD_TYPE_TRACE, FREAD | FWRITE,
+		    efbuf);
 	if (textvp != NULL)
-		export_fd_to_sb(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
-		    FREAD, -1, -1, NULL, efbuf);
+		export_vnode_to_sb(textvp, KF_FD_TYPE_TEXT, FREAD, efbuf);
 	if (cttyvp != NULL)
-		export_fd_to_sb(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
-		    FREAD | FWRITE, -1, -1, NULL, efbuf);
+		export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE,
+		    efbuf);
 	error = 0;
 	if (fdp == NULL)
 		goto fail;
@@ -3378,105 +3131,34 @@ kern_proc_filedesc_out(struct proc *p,  
 	/* working directory */
 	if (fdp->fd_cdir != NULL) {
 		vref(fdp->fd_cdir);
-		data = fdp->fd_cdir;
-		export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
-		    FREAD, -1, -1, NULL, efbuf);
+		export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
 	}
 	/* root directory */
 	if (fdp->fd_rdir != NULL) {
 		vref(fdp->fd_rdir);
-		data = fdp->fd_rdir;
-		export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
-		    FREAD, -1, -1, NULL, efbuf);
+		export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf);
 	}
 	/* jail directory */
 	if (fdp->fd_jdir != NULL) {
 		vref(fdp->fd_jdir);
-		data = fdp->fd_jdir;
-		export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
-		    FREAD, -1, -1, NULL, efbuf);
+		export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
 	}
 	for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
 		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
 			continue;
-		data = NULL;
 #ifdef CAPABILITIES
 		rights = *cap_rights(fdp, i);
 #else /* !CAPABILITIES */
 		cap_rights_init(&rights);
 #endif
-		switch (fp->f_type) {
-		case DTYPE_VNODE:
-			type = KF_TYPE_VNODE;
-			vref(fp->f_vnode);
-			data = fp->f_vnode;
-			break;
-
-		case DTYPE_SOCKET:
-			type = KF_TYPE_SOCKET;
-			data = fp->f_data;
-			break;
-
-		case DTYPE_PIPE:
-			type = KF_TYPE_PIPE;
-			data = fp->f_data;
-			break;
-
-		case DTYPE_FIFO:
-			type = KF_TYPE_FIFO;
-			vref(fp->f_vnode);
-			data = fp->f_vnode;
-			break;
-
-		case DTYPE_KQUEUE:
-			type = KF_TYPE_KQUEUE;
-			break;
-
-		case DTYPE_CRYPTO:
-			type = KF_TYPE_CRYPTO;
-			break;
-
-		case DTYPE_MQUEUE:
-			type = KF_TYPE_MQUEUE;
-			break;
-
-		case DTYPE_SHM:
-			type = KF_TYPE_SHM;
-			data = fp;
-			break;
-
-		case DTYPE_SEM:
-			type = KF_TYPE_SEM;
-			data = fp;
-			break;
-
-		case DTYPE_PTS:
-			type = KF_TYPE_PTS;
-			data = fp->f_data;
-			break;
-
-		case DTYPE_PROCDESC:
-			type = KF_TYPE_PROCDESC;
-			data = fp->f_data;
-			break;
-
-		default:
-			type = KF_TYPE_UNKNOWN;
-			break;
-		}
-		refcnt = fp->f_count;
-		fflags = fp->f_flag;
-		offset = foffset_get(fp);
-
 		/*
-		 * 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.
+		 * Create sysctl entry.  It is OK to drop the filedesc
+		 * lock inside of export_file_to_sb() as we will
+		 * re-validate and re-evaluate its properties when the
+		 * loop continues.
 		 */
-		error = export_fd_to_sb(data, type, i, fflags, refcnt,
-		    offset, &rights, efbuf);
-		if (error != 0)
+		error = export_file_to_sb(fp, i, &rights, efbuf);
+		if (error != 0 || efbuf->remainder == 0)
 			break;
 	}
 	FILEDESC_SUNLOCK(fdp);
@@ -3514,6 +3196,105 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 	return (error != 0 ? error : error2);
 }
 
+#ifdef KINFO_OFILE_SIZE
+CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
+#endif
+
+#ifdef COMPAT_FREEBSD7
+static void
+kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_ofile *okif)
+{
+
+	okif->kf_structsize = sizeof(*okif);
+	okif->kf_type = kif->kf_type;
+	okif->kf_fd = kif->kf_fd;
+	okif->kf_ref_count = kif->kf_ref_count;
+	okif->kf_flags = kif->kf_flags & (KF_FLAG_READ | KF_FLAG_WRITE |
+	    KF_FLAG_APPEND | KF_FLAG_ASYNC | KF_FLAG_FSYNC | KF_FLAG_NONBLOCK |
+	    KF_FLAG_DIRECT | KF_FLAG_HASLOCK);
+	okif->kf_offset = kif->kf_offset;
+	okif->kf_vnode_type = kif->kf_vnode_type;
+	okif->kf_sock_domain = kif->kf_sock_domain;
+	okif->kf_sock_type = kif->kf_sock_type;
+	okif->kf_sock_protocol = kif->kf_sock_protocol;
+	strlcpy(okif->kf_path, kif->kf_path, sizeof(okif->kf_path));
+	okif->kf_sa_local = kif->kf_sa_local;
+	okif->kf_sa_peer = kif->kf_sa_peer;
+}
+
+static int
+export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
+    struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req)
+{
+	int error;
+
+	vref(vp);
+	FILEDESC_SUNLOCK(fdp);
+	export_vnode_to_kinfo(vp, type, 0, kif);
+	kinfo_to_okinfo(kif, okif);
+	error = SYSCTL_OUT(req, okif, sizeof(*okif));
+	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)
+{
+	struct kinfo_ofile *okif;
+	struct kinfo_file *kif;
+	struct filedesc *fdp;
+	struct thread *td;
+	int error, i, *name;
+	struct file *fp;
+	struct proc *p;
+
+	td = curthread;
+	name = (int *)arg1;
+	error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+	if (error != 0)
+		return (error);
+	fdp = fdhold(p);
+	PROC_UNLOCK(p);
+	if (fdp == NULL)
+		return (ENOENT);
+	kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
+	okif = malloc(sizeof(*okif), M_TEMP, M_WAITOK);
+	FILEDESC_SLOCK(fdp);
+	if (fdp->fd_cdir != NULL)
+		export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
+		    okif, fdp, req);
+	if (fdp->fd_rdir != NULL)
+		export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
+		    okif, fdp, req);
+	if (fdp->fd_jdir != NULL)
+		export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
+		    okif, fdp, req);
+	for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
+		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
+			continue;
+		export_file_to_kinfo(fp, i, NULL, kif, fdp);
+		FILEDESC_SUNLOCK(fdp);
+		kinfo_to_okinfo(kif, okif);
+		error = SYSCTL_OUT(req, okif, sizeof(*okif));
+		FILEDESC_SLOCK(fdp);
+		if (error)
+			break;
+	}
+	FILEDESC_SUNLOCK(fdp);
+	fddrop(fdp);
+	free(kif, M_TEMP);
+	free(okif, M_TEMP);
+	return (0);
+}
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,
+    CTLFLAG_RD||CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
+    "Process ofiledesc entries");
+#endif	/* COMPAT_FREEBSD7 */
+
 int
 vntype_to_kinfo(int vtype)
 {
@@ -3543,170 +3324,6 @@ vntype_to_kinfo(int vtype)
 	return (KF_VTYPE_UNKNOWN);
 }
 
-static int
-fill_vnode_info(struct vnode *vp, struct kinfo_file *kif)
-{
-	struct vattr va;
-	char *fullpath, *freepath;
-	int error;
-
-	if (vp == NULL)
-		return (1);
-	kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
-	freepath = NULL;
-	fullpath = "-";
-	error = vn_fullpath(curthread, vp, &fullpath, &freepath);
-	if (error == 0) {
-		strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
-	}
-	if (freepath != NULL)
-		free(freepath, M_TEMP);
-
-	/*
-	 * Retrieve vnode attributes.
-	 */
-	va.va_fsid = VNOVAL;
-	va.va_rdev = NODEV;
-	vn_lock(vp, LK_SHARED | LK_RETRY);
-	error = VOP_GETATTR(vp, &va, curthread->td_ucred);
-	VOP_UNLOCK(vp, 0);
-	if (error != 0)
-		return (error);
-	if (va.va_fsid != VNOVAL)
-		kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
-	else
-		kif->kf_un.kf_file.kf_file_fsid =
-		    vp->v_mount->mnt_stat.f_fsid.val[0];
-	kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
-	kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
-	kif->kf_un.kf_file.kf_file_size = va.va_size;
-	kif->kf_un.kf_file.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_un.kf_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_un.kf_sock.kf_sock_inpcb =
-				    (uintptr_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_un.kf_sock.kf_sock_unpconn =
-				    (uintptr_t)unpcb->unp_conn;
-				kif->kf_un.kf_sock.kf_sock_rcv_sb_state =
-				    so->so_rcv.sb_state;
-				kif->kf_un.kf_sock.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_path, so->so_proto->pr_domain->dom_name,
-	    sizeof(kif->kf_path));
-	return (0);
-}
-
-static int
-fill_pts_info(struct tty *tp, struct kinfo_file *kif)
-{
-
-	if (tp == NULL)
-		return (1);
-	kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
-	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->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi;
-	kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer;
-	kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt;
-	return (0);
-}
-
-static int
-fill_procdesc_info(struct procdesc *pdp, struct kinfo_file *kif)
-{
-
-	if (pdp == NULL)
-		return (1);
-	kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
-	return (0);
-}
-
-static int
-fill_sem_info(struct file *fp, struct kinfo_file *kif)
-{
-	struct thread *td;
-	struct stat sb;
-
-	td = curthread;
-	if (fp->f_data == NULL)
-		return (1);
-	if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
-		return (1);
-	if (ksem_info == NULL)
-		return (1);
-	ksem_info(fp->f_data, kif->kf_path, sizeof(kif->kf_path),
-	    &kif->kf_un.kf_sem.kf_sem_value);
-	kif->kf_un.kf_sem.kf_sem_mode = sb.st_mode;
-	return (0);
-}
-
-static int
-fill_shm_info(struct file *fp, struct kinfo_file *kif)
-{
-	struct thread *td;
-	struct stat sb;
-
-	td = curthread;
-	if (fp->f_data == NULL)
-		return (1);
-	if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
-		return (1);
-	shm_path(fp->f_data, kif->kf_path, sizeof(kif->kf_path));
-	kif->kf_un.kf_file.kf_file_mode = sb.st_mode;
-	kif->kf_un.kf_file.kf_file_size = sb.st_size;
-	return (0);
-}
-
 static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc,
     CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_filedesc,
     "Process filedesc entries");
@@ -3926,6 +3543,13 @@ badfo_sendfile(struct file *fp, int sock
 	return (EBADF);
 }
 
+static int
+badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+	return (0);
+}
+
 struct fileops badfileops = {
 	.fo_read = badfo_readwrite,
 	.fo_write = badfo_readwrite,
@@ -3938,6 +3562,7 @@ struct fileops badfileops = {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409221620.s8MGKl08079806>