From 83dc2280cebd626d5a4fda7c4268a94d329c4e78 Mon Sep 17 00:00:00 2001 From: peter Date: Sat, 29 Nov 2008 20:55:11 +0000 Subject: WIP kinfo_file/kinfo_vmmentry tweaks. The idea: 1) to get the 32 and 64 bit versions in sync so that no shims are needed, Valgrind in particular excercises this. and: 2) reduce the size of the copyout. On large processes this turns out to be a huge problem. Valgrind also suffers from this since it needs to do this in a context that can't malloc. I want to pack the records. 3) Add new types.. 'tell me about fd N' and 'tell me about addr N'. --- sys/kern/kern_descrip.c | 4 ++++ sys/kern/kern_proc.c | 10 +++++++--- sys/sys/user.h | 38 ++++++++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 15 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 833aa2c..848aa92 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2509,6 +2509,10 @@ 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_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) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index a331a42..e8e6e00 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1337,6 +1337,10 @@ sysctl_kern_proc_sv_name(SYSCTL_HANDLER_ARGS) return (sysctl_handle_string(oidp, sv_name, 0, req)); } +#ifdef KINFO_VMENTRY_SIZE +CTASSERT(sizeof(struct kinfo_vmentry) == KINFO_VMENTRY_SIZE); +#endif + static int sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) { @@ -1461,9 +1465,9 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) kve->kve_shadow_count = 0; } - kve->kve_start = (void*)entry->start; - kve->kve_end = (void*)entry->end; - kve->kve_offset = (off_t)entry->offset; + 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; diff --git a/sys/sys/user.h b/sys/sys/user.h index a12669f..2a7b36b 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -236,6 +236,9 @@ 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. @@ -277,20 +280,25 @@ struct user { #define KF_FLAG_DIRECT 0x00000040 #define KF_FLAG_HASLOCK 0x00000080 +#if defined(__amd64__) || defined(__i386__) +#define KINFO_FILE_SIZE 560 +#endif + struct kinfo_file { 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. */ - off_t kf_offset; /* Seek location. */ + int _kf_pad0; /* Alignment */ + uint64_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. */ + char kf_path[KPROC_PATH_MAX]; /* Path to file, if any. */ }; /* @@ -313,23 +321,26 @@ struct kinfo_file { #define KVME_FLAG_COW 0x00000001 #define KVME_FLAG_NEEDS_COPY 0x00000002 +#if defined(__amd64__) || defined(__i386__) +#define KINFO_VMENTRY_SIZE 384 +#endif + struct kinfo_vmentry { int kve_structsize; /* Size of kinfo_vmmapentry. */ int kve_type; /* Type of map entry. */ - void *kve_start; /* Starting pointer. */ - void *kve_end; /* Finishing pointer. */ + 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. */ - 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 */ - dev_t kve_fsid; /* dev_t of vnode location */ - int _kve_ispare[3]; /* Space for more stuff. */ + int _kve_ispare[15]; /* Space for more stuff. */ + char kve_path[KPROC_PATH_MAX]; /* Path to VM obj, if any. */ }; /* @@ -343,12 +354,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 -- cgit v1.1 From 343bde97065f4c35293558594e5b36627ef8ccb7 Mon Sep 17 00:00:00 2001 From: peter Date: Sun, 30 Nov 2008 00:18:21 +0000 Subject: 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 --- sys/kern/kern_descrip.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++- sys/sys/sysctl.h | 3 +- sys/sys/user.h | 47 +++++++-- 3 files changed, 308 insertions(+), 14 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 848aa92..d4d84e6 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -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 type, 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, int type, 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_ARGS) 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_ARGS) 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; } diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index e605e9f..e4e3040 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -541,12 +541,13 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); #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 diff --git a/sys/sys/user.h b/sys/sys/user.h index 2a7b36b..4f11765 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -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. */ }; /* -- cgit v1.1 From 2b1f03929a1b2aede23598bc1b54f8061c22fd69 Mon Sep 17 00:00:00 2001 From: peter Date: Sun, 30 Nov 2008 21:04:53 +0000 Subject: Properly wrap this giant block of duplicate code inside COMPAT_FREEBSD7 --- sys/kern/kern_descrip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index d4d84e6..11fa1c2 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2509,7 +2509,6 @@ 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 @@ -2524,6 +2523,7 @@ SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD, 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) @@ -2766,7 +2766,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc, CTLFLAG_RD, sysctl_kern_proc_ofiledesc, "Process ofiledesc entries"); - +#endif /* COMPAT_FREEBSD7 */ #ifdef KINFO_FILE_SIZE CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE); -- cgit v1.1 From cd7b78c33f9eb6fc2730afe6d09252f28cf9996e Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 1 Dec 2008 02:13:32 +0000 Subject: Duplicate another few hundred lines of code in order to be compatible with unreleased binaries. --- sys/kern/kern_descrip.c | 2 + sys/kern/kern_proc.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++- sys/sys/sysctl.h | 6 +- sys/sys/user.h | 26 +++++++ 4 files changed, 211 insertions(+), 4 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 11fa1c2..faac641 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2806,6 +2806,7 @@ export_vnode_for_sysctl(struct vnode *vp, int type, strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); if (freepath != NULL) free(freepath, M_TEMP); + /* 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)); @@ -3003,6 +3004,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path)); } + /* 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, diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index e8e6e00..bb66f04 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -32,6 +32,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_ddb.h" #include "opt_kdtrace.h" #include "opt_ktrace.h" @@ -1337,6 +1338,173 @@ sysctl_kern_proc_sv_name(SYSCTL_HANDLER_ARGS) return (sysctl_handle_string(oidp, sv_name, 0, req)); } +#ifdef KINFO_OVMENTRY_SIZE +CTASSERT(sizeof(struct kinfo_ovmentry) == KINFO_OVMENTRY_SIZE); +#endif + +#ifdef COMPAT_FREEBSD7 +static int +sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS) +{ + vm_map_entry_t entry, tmp_entry; + unsigned int last_timestamp; + char *fullpath, *freepath; + struct kinfo_ovmentry *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_structsize = 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) { + vn_fullpath(curthread, vp, &fullpath, + &freepath); + cred = curthread->td_ucred; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY); + if (VOP_GETATTR(vp, &va, cred) == 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 = (void *)entry->start; + kve->kve_end = (void *)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); + error = SYSCTL_OUT(req, kve, sizeof(*kve)); + 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); +} +#endif /* COMPAT_FREEBSD7 */ + #ifdef KINFO_VMENTRY_SIZE CTASSERT(sizeof(struct kinfo_vmentry) == KINFO_VMENTRY_SIZE); #endif @@ -1383,7 +1551,6 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) continue; bzero(kve, sizeof(*kve)); - kve->kve_structsize = sizeof(*kve); kve->kve_private_resident = 0; obj = entry->object.vm_object; @@ -1487,7 +1654,12 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) last_timestamp = map->timestamp; vm_map_unlock_read(map); - error = SYSCTL_OUT(req, kve, sizeof(*kve)); + /* 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; @@ -1673,6 +1845,11 @@ static SYSCTL_NODE(_kern_proc, (KERN_PROC_PID | KERN_PROC_INC_THREAD), pid_td, static SYSCTL_NODE(_kern_proc, (KERN_PROC_PROC | KERN_PROC_INC_THREAD), proc_td, CTLFLAG_RD, sysctl_kern_proc, "Return process table, no threads"); +#ifdef COMPAT_FREEBSD7 +static SYSCTL_NODE(_kern_proc, KERN_PROC_OVMMAP, ovmmap, CTLFLAG_RD, + sysctl_kern_proc_ovmmap, "Old Process vm map entries"); +#endif + static SYSCTL_NODE(_kern_proc, KERN_PROC_VMMAP, vmmap, CTLFLAG_RD, sysctl_kern_proc_vmmap, "Process vm map entries"); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index e4e3040..f1cb04a 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -540,14 +540,16 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); #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_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_FILEDESC 32 /* File descriptors for process */ +#define KERN_PROC_VMMAP 32 /* VM map entries for process */ +#define KERN_PROC_FILEDESC 33 /* File descriptors for process */ /* * KERN_IPC identifiers diff --git a/sys/sys/user.h b/sys/sys/user.h index 4f11765..73f7d76 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -348,6 +348,32 @@ struct kinfo_file { #define KVME_FLAG_COW 0x00000001 #define KVME_FLAG_NEEDS_COPY 0x00000002 +#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 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. */ + int kve_protection; /* Protection bitmask. */ + int kve_ref_count; /* VM obj ref count. */ + int kve_shadow_count; /* VM obj shadow count. */ + 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 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 -- cgit v1.1 From 0cd59a18e366e541876a23e59b53ce6246f0cec8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 2 Dec 2008 02:32:13 +0000 Subject: Prune some whining. --- sys/kern/kern_descrip.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index faac641..c981411 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2509,16 +2509,6 @@ 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 -- cgit v1.1