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>