Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F112521089
D49372.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D49372.diff
View Options
diff --git a/lib/libprocstat/core.h b/lib/libprocstat/core.h
--- a/lib/libprocstat/core.h
+++ b/lib/libprocstat/core.h
@@ -31,7 +31,7 @@
#define _CORE_H
enum psc_type {
- PSC_TYPE_PROC,
+ PSC_TYPE_PROC = 0,
PSC_TYPE_FILES,
PSC_TYPE_VMMAP,
PSC_TYPE_GROUPS,
@@ -43,6 +43,7 @@
PSC_TYPE_ENVV,
PSC_TYPE_AUXV,
PSC_TYPE_PTLWPINFO,
+ PSC_TYPE_KQUEUES,
PSC_TYPE_MAX
};
diff --git a/lib/libprocstat/core.c b/lib/libprocstat/core.c
--- a/lib/libprocstat/core.c
+++ b/lib/libprocstat/core.c
@@ -57,22 +57,62 @@
GElf_Phdr pc_phdr;
};
-static struct psc_type_info {
+static const struct psc_type_info {
unsigned int n_type;
int structsize;
} psc_type_info[PSC_TYPE_MAX] = {
- { .n_type = NT_PROCSTAT_PROC, .structsize = sizeof(struct kinfo_proc) },
- { .n_type = NT_PROCSTAT_FILES, .structsize = sizeof(struct kinfo_file) },
- { .n_type = NT_PROCSTAT_VMMAP, .structsize = sizeof(struct kinfo_vmentry) },
- { .n_type = NT_PROCSTAT_GROUPS, .structsize = sizeof(gid_t) },
- { .n_type = NT_PROCSTAT_UMASK, .structsize = sizeof(u_short) },
- { .n_type = NT_PROCSTAT_RLIMIT, .structsize = sizeof(struct rlimit) * RLIM_NLIMITS },
- { .n_type = NT_PROCSTAT_OSREL, .structsize = sizeof(int) },
- { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
- { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
- { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
- { .n_type = NT_PROCSTAT_AUXV, .structsize = sizeof(Elf_Auxinfo) },
- { .n_type = NT_PTLWPINFO, .structsize = sizeof(struct ptrace_lwpinfo) },
+ [PSC_TYPE_PROC] = {
+ .n_type = NT_PROCSTAT_PROC,
+ .structsize = sizeof(struct kinfo_proc)
+ },
+ [PSC_TYPE_FILES] = {
+ .n_type = NT_PROCSTAT_FILES,
+ .structsize = sizeof(struct kinfo_file)
+ },
+ [PSC_TYPE_VMMAP] = {
+ .n_type = NT_PROCSTAT_VMMAP,
+ .structsize = sizeof(struct kinfo_vmentry)
+ },
+ [PSC_TYPE_GROUPS] = {
+ .n_type = NT_PROCSTAT_GROUPS,
+ .structsize = sizeof(gid_t)
+ },
+ [PSC_TYPE_UMASK] = {
+ .n_type = NT_PROCSTAT_UMASK,
+ .structsize = sizeof(u_short)
+ },
+ [PSC_TYPE_RLIMIT] = {
+ .n_type = NT_PROCSTAT_RLIMIT,
+ .structsize = sizeof(struct rlimit) * RLIM_NLIMITS
+ },
+ [PSC_TYPE_OSREL] = {
+ .n_type = NT_PROCSTAT_OSREL,
+ .structsize = sizeof(int)
+ },
+ [PSC_TYPE_PSSTRINGS] = {
+ .n_type = NT_PROCSTAT_PSSTRINGS,
+ .structsize = sizeof(vm_offset_t)
+ },
+ [PSC_TYPE_ARGV] = {
+ .n_type = NT_PROCSTAT_PSSTRINGS,
+ .structsize = sizeof(vm_offset_t)
+ },
+ [PSC_TYPE_ENVV] = {
+ .n_type = NT_PROCSTAT_PSSTRINGS,
+ .structsize = sizeof(vm_offset_t)
+ },
+ [PSC_TYPE_AUXV] = {
+ .n_type = NT_PROCSTAT_AUXV,
+ .structsize = sizeof(Elf_Auxinfo)
+ },
+ [PSC_TYPE_PTLWPINFO] = {
+ .n_type = NT_PTLWPINFO,
+ .structsize = sizeof(struct ptrace_lwpinfo)
+ },
+ [PSC_TYPE_KQUEUES] = {
+ .n_type = NT_PROCSTAT_KQUEUES,
+ .structsize = sizeof(struct kinfo_knote)
+ },
};
static bool core_offset(struct procstat_core *core, off_t offset);
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -2862,6 +2862,9 @@
procstat_get_kqueue_info(struct procstat *procstat,
struct kinfo_proc *kp, int kqfd, unsigned int *count, char *errbuf)
{
+ struct kinfo_knote *kn, *k, *res, *rn;
+ size_t len, kqn;
+
switch (procstat->type) {
case PROCSTAT_KVM:
warnx("kvm method is not supported");
@@ -2870,8 +2873,34 @@
return (procstat_get_kqueue_info_sysctl(kp->ki_pid, kqfd,
count, errbuf));
case PROCSTAT_CORE:
- warnx("core method is not supported");
- return (NULL);
+ k = procstat_core_get(procstat->core, PSC_TYPE_KQUEUES,
+ NULL, &len);
+ if (k == NULL) {
+ snprintf(errbuf, _POSIX2_LINE_MAX,
+ "getting NT_PROCSTAT_KQUEUES note failed");
+ *count = 0;
+ return (NULL);
+ }
+ for (kqn = 0, kn = k; kn < k + len / sizeof(*kn); kn++) {
+ if (kn->knt_kq_fd == kqfd)
+ kqn++;
+ }
+ res = calloc(kqn, sizeof(*res));
+ if (res == NULL) {
+ free(k);
+ snprintf(errbuf, _POSIX2_LINE_MAX,
+ "no memory");
+ return (NULL);
+ }
+ for (kn = k, rn = res; kn < k + len / sizeof(*kn); kn++) {
+ if (kn->knt_kq_fd != kqfd)
+ continue;
+ *rn = *kn;
+ rn++;
+ }
+ *count = kqn;
+ free(k);
+ return (res);
default:
warnx("unknown access method: %d", procstat->type);
return (NULL);
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -446,6 +446,25 @@
uint32_t kvm_spare[12];
};
+struct kinfo_knote32 {
+ int knt_kq_fd;
+ struct kevent32 knt_event;
+ int knt_status;
+ int knt_extdata;
+ uint32_t knt_spare0[8];
+ union {
+ struct {
+ int knt_vnode_type;
+ uint32_t knt_vnode_fsid[2];
+ uint32_t knt_vnode_fileid[2];
+ char knt_vnode_fullpath[PATH_MAX];
+ } knt_vnode;
+ struct {
+ uint32_t knt_pipe_ino[2];
+ } knt_pipe;
+ };
+};
+
struct kld_file_stat_1_32 {
int version; /* set to sizeof(struct kld_file_stat_1) */
char name[MAXPATHLEN];
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -679,6 +679,86 @@
return (error);
}
+static void
+freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)
+{
+ uint64_t e;
+ int j;
+
+ CP(*kevp, *ks32, ident);
+ CP(*kevp, *ks32, filter);
+ CP(*kevp, *ks32, flags);
+ CP(*kevp, *ks32, fflags);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ks32->data1 = kevp->data;
+ ks32->data2 = kevp->data >> 32;
+#else
+ ks32->data1 = kevp->data >> 32;
+ ks32->data2 = kevp->data;
+#endif
+ PTROUT_CP(*kevp, *ks32, udata);
+ for (j = 0; j < nitems(kevp->ext); j++) {
+ e = kevp->ext[j];
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ks32->ext64[2 * j] = e;
+ ks32->ext64[2 * j + 1] = e >> 32;
+#else
+ ks32->ext64[2 * j] = e >> 32;
+ ks32->ext64[2 * j + 1] = e;
+#endif
+ }
+}
+
+void
+freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
+ struct kinfo_knote32 *kin32)
+{
+ memset(kin32, 0, sizeof(*kin32));
+ CP(*kin, *kin32, knt_kq_fd);
+ freebsd32_kevent_to_kevent32(&kin->knt_event, &kin32->knt_event);
+ CP(*kin, *kin32, knt_status);
+ CP(*kin, *kin32, knt_extdata);
+ switch (kin->knt_extdata) {
+ case KNOTE_EXTDATA_NONE:
+ break;
+ case KNOTE_EXTDATA_VNODE:
+ CP(*kin, *kin32, knt_vnode.knt_vnode_type);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
+ knt_vnode_fsid;
+ kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
+ knt_vnode_fsid >> 32;
+ kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
+ knt_vnode_fileid;
+ kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
+ knt_vnode_fileid >> 32;
+#else
+ kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
+ knt_vnode_fsid;
+ kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
+ knt_vnode_fsid >> 32;
+ kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
+ knt_vnode_fileid;
+ kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
+ knt_vnode_fileid >> 32;
+#endif
+ memcpy(kin32->knt_vnode.knt_vnode_fullpath,
+ kin->knt_vnode.knt_vnode_fullpath, PATH_MAX);
+ break;
+ case KNOTE_EXTDATA_PIPE:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.knt_pipe_ino;
+ kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.
+ knt_pipe_ino >> 32;
+#else
+ kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.knt_pipe_ino;
+ kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.
+ knt_pipe_ino >> 32;
+#endif
+ break;
+ }
+}
+
/*
* Copy 'count' items into the destination list pointed to by uap->eventlist.
*/
@@ -687,36 +767,13 @@
{
struct freebsd32_kevent_args *uap;
struct kevent32 ks32[KQ_NEVENTS];
- uint64_t e;
- int i, j, error;
+ int i, error;
KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
uap = (struct freebsd32_kevent_args *)arg;
- for (i = 0; i < count; i++) {
- CP(kevp[i], ks32[i], ident);
- CP(kevp[i], ks32[i], filter);
- CP(kevp[i], ks32[i], flags);
- CP(kevp[i], ks32[i], fflags);
-#if BYTE_ORDER == LITTLE_ENDIAN
- ks32[i].data1 = kevp[i].data;
- ks32[i].data2 = kevp[i].data >> 32;
-#else
- ks32[i].data1 = kevp[i].data >> 32;
- ks32[i].data2 = kevp[i].data;
-#endif
- PTROUT_CP(kevp[i], ks32[i], udata);
- for (j = 0; j < nitems(kevp->ext); j++) {
- e = kevp[i].ext[j];
-#if BYTE_ORDER == LITTLE_ENDIAN
- ks32[i].ext64[2 * j] = e;
- ks32[i].ext64[2 * j + 1] = e >> 32;
-#else
- ks32[i].ext64[2 * j] = e >> 32;
- ks32[i].ext64[2 * j + 1] = e;
-#endif
- }
- }
+ for (i = 0; i < count; i++)
+ freebsd32_kevent_to_kevent32(&kevp[i], &ks32[i]);
error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
if (error == 0)
uap->eventlist += count;
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
--- a/sys/compat/freebsd32/freebsd32_util.h
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -122,6 +122,11 @@
int freebsd32_exec_copyin_args(struct image_args *args, const char *fname,
enum uio_seg segflg, uint32_t *argv, uint32_t *envv);
+struct kinfo_knote;
+struct kinfo_knote32;
+void freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
+ struct kinfo_knote32 *kin32);
+
extern int compat_freebsd_32bit;
#endif /* !_COMPAT_FREEBSD32_FREEBSD32_UTIL_H_ */
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1574,6 +1574,7 @@
static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_proc)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
+static void __elfN(note_procstat_kqueues)(void *, struct sbuf *, size_t *);
static void note_procstat_files(void *, struct sbuf *, size_t *);
static void note_procstat_groups(void *, struct sbuf *, size_t *);
static void note_procstat_osrel(void *, struct sbuf *, size_t *);
@@ -1899,6 +1900,8 @@
__elfN(note_procstat_psstrings), p);
size += __elfN(register_note)(td, list, NT_PROCSTAT_AUXV,
__elfN(note_procstat_auxv), p);
+ size += __elfN(register_note)(td, list, NT_PROCSTAT_KQUEUES,
+ __elfN(note_procstat_kqueues), p);
*sizep = size;
}
@@ -2719,6 +2722,54 @@
}
}
+static void
+__elfN(note_procstat_kqueues)(void *arg, struct sbuf *sb, size_t *sizep)
+{
+ struct proc *p;
+ size_t size, sect_sz, i;
+ ssize_t start_len, sect_len;
+ int structsize;
+ bool compat32;
+
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+ compat32 = true;
+ structsize = sizeof(struct kinfo_knote32);
+#else
+ compat32 = false;
+ structsize = sizeof(struct kinfo_knote);
+#endif
+ p = arg;
+ if (sb == NULL) {
+ size = 0;
+ sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
+ sbuf_set_drain(sb, sbuf_count_drain, &size);
+ sbuf_bcat(sb, &structsize, sizeof(structsize));
+ kern_proc_kqueues_out(p, sb, -1, compat32);
+ sbuf_finish(sb);
+ sbuf_delete(sb);
+ *sizep = size;
+ } else {
+ sbuf_start_section(sb, &start_len);
+
+ sbuf_bcat(sb, &structsize, sizeof(structsize));
+ kern_proc_kqueues_out(p, sb, *sizep - sizeof(structsize),
+ compat32);
+
+ sect_len = sbuf_end_section(sb, start_len, 0, 0);
+ if (sect_len < 0)
+ return;
+ sect_sz = sect_len;
+
+ KASSERT(sect_sz <= *sizep,
+ ("kern_proc_kqueue_out did not respect maxlen; "
+ "requested %zu, got %zu", *sizep - sizeof(structsize),
+ sect_sz - sizeof(structsize)));
+
+ for (i = 0; i < *sizep - sect_sz && sb->s_error == 0; i++)
+ sbuf_putc(sb, 0);
+ }
+}
+
#define MAX_NOTES_LOOP 4096
bool
__elfN(parse_notes)(const struct image_params *imgp, const Elf_Note *checknote,
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -34,14 +34,11 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include "opt_capsicum.h"
#include "opt_ddb.h"
#include "opt_ktrace.h"
-#include <sys/param.h>
#include <sys/systm.h>
-
#include <sys/capsicum.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -2996,6 +2993,47 @@
return (error);
}
+int
+fget_remote_foreach(struct thread *td, struct proc *p,
+ int (*fn)(struct proc *, int, struct file *, void *), void *arg)
+{
+ struct filedesc *fdp;
+ struct fdescenttbl *fdt;
+ struct file *fp;
+ int error, error1, fd, highfd;
+
+ error = 0;
+ PROC_LOCK(p);
+ fdp = fdhold(p);
+ PROC_UNLOCK(p);
+ if (fdp == NULL)
+ return (ENOENT);
+
+ FILEDESC_SLOCK(fdp);
+ if (refcount_load(&fdp->fd_refcnt) != 0) {
+ fdt = atomic_load_ptr(&fdp->fd_files);
+ highfd = fdt->fdt_nfiles - 1;
+ FILEDESC_SUNLOCK(fdp);
+ } else {
+ error = ENOENT;
+ FILEDESC_SUNLOCK(fdp);
+ goto out;
+ }
+
+ for (fd = 0; fd <= highfd; fd++) {
+ error1 = fget_remote(td, p, fd, &fp);
+ if (error1 != 0)
+ continue;
+ error = fn(p, fd, fp, arg);
+ fdrop(fp, td);
+ if (error != 0)
+ break;
+ }
+out:
+ fddrop(fdp);
+ return (error);
+}
+
#ifdef CAPABILITIES
int
fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch)
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -58,6 +58,7 @@
#include <sys/poll.h>
#include <sys/protosw.h>
#include <sys/resourcevar.h>
+#include <sys/sbuf.h>
#include <sys/sigio.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@@ -74,6 +75,10 @@
#include <sys/ktrace.h>
#endif
#include <machine/atomic.h>
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_util.h>
+#endif
#include <vm/uma.h>
@@ -2871,94 +2876,181 @@
}
static int
-sysctl_kern_proc_kqueue_report_one(struct proc *p, struct sysctl_req *req,
- struct kqueue *kq, struct knote *kn)
+kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
+ int kq_fd, struct kqueue *kq, struct knote *kn, bool compat32 __unused)
{
struct kinfo_knote kin;
+#ifdef COMPAT_FREEBSD32
+ struct kinfo_knote32 kin32;
+#endif
int error;
if (kn->kn_status == KN_MARKER)
return (0);
memset(&kin, 0, sizeof(kin));
+ kin.knt_kq_fd = kq_fd;
memcpy(&kin.knt_event, &kn->kn_kevent, sizeof(struct kevent));
kin.knt_status = knote_status_export(kn->kn_status);
kn_enter_flux(kn);
KQ_UNLOCK_FLUX(kq);
if (kn->kn_fop->f_userdump != NULL)
(void)kn->kn_fop->f_userdump(p, kn, &kin);
- error = SYSCTL_OUT(req, &kin, sizeof(kin));
- maybe_yield();
+#ifdef COMPAT_FREEBSD32
+ if (compat32) {
+ freebsd32_kinfo_knote_to_32(&kin, &kin32);
+ error = sbuf_bcat(s, &kin32, sizeof(kin32));
+ } else
+#endif
+ error = sbuf_bcat(s, &kin, sizeof(kin));
KQ_LOCK(kq);
kn_leave_flux(kn);
return (error);
}
+static int
+kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
+ struct kqueue *kq, bool compat32)
+{
+ struct knote *kn;
+ int error, i;
+
+ error = 0;
+ KQ_LOCK(kq);
+ for (i = 0; i < kq->kq_knlistsize; i++) {
+ SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
+ error = kern_proc_kqueue_report_one(s, p, kq_fd,
+ kq, kn, compat32);
+ if (error != 0)
+ goto out;
+ }
+ }
+ if (kq->kq_knhashmask == 0)
+ goto out;
+ for (i = 0; i <= kq->kq_knhashmask; i++) {
+ SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
+ error = kern_proc_kqueue_report_one(s, p, kq_fd,
+ kq, kn, compat32);
+ if (error != 0)
+ goto out;
+ }
+ }
+out:
+ KQ_UNLOCK_FLUX(kq);
+ return (error);
+}
+
+struct kern_proc_kqueues_out1_cb_args {
+ struct sbuf *s;
+ bool compat32;
+};
+
+static int
+kern_proc_kqueues_out1_cb(struct proc *p, int fd, struct file *fp, void *arg)
+{
+ struct kqueue *kq;
+ struct kern_proc_kqueues_out1_cb_args *a;
+
+ if (fp->f_type != DTYPE_KQUEUE)
+ return (0);
+ a = arg;
+ kq = fp->f_data;
+ return (kern_proc_kqueue_report(a->s, p, fd, kq, a->compat32));
+}
+
+static int
+kern_proc_kqueues_out1(struct thread *td, struct proc *p, struct sbuf *s,
+ bool compat32)
+{
+ struct kern_proc_kqueues_out1_cb_args a;
+
+ a.s = s;
+ a.compat32 = compat32;
+ return (fget_remote_foreach(td, p, kern_proc_kqueues_out1_cb, &a));
+}
+
+int
+kern_proc_kqueues_out(struct proc *p, struct sbuf *sb, size_t maxlen,
+ bool compat32)
+{
+ struct sbuf *s, sm;
+ int error;
+
+ s = sbuf_new(&sm, NULL, maxlen, SBUF_FIXEDLEN);
+ error = kern_proc_kqueues_out1(curthread, p, s, compat32);
+ sbuf_finish(s);
+ if (error == 0)
+ sbuf_bcat(sb, sbuf_data(s), MIN(sbuf_len(s), maxlen));
+ sbuf_delete(s);
+ return (error);
+}
+
+static int
+sysctl_kern_proc_kqueue_one(struct thread *td, struct sbuf *s, struct proc *p,
+ int kq_fd, bool compat32)
+{
+ struct file *fp;
+ struct kqueue *kq;
+ int error;
+
+ error = fget_remote(td, p, kq_fd, &fp);
+ if (error == 0) {
+ if (fp->f_type != DTYPE_KQUEUE) {
+ error = EINVAL;
+ } else {
+ kq = fp->f_data;
+ error = kern_proc_kqueue_report(s, p, kq_fd, kq,
+ compat32);
+ }
+ fdrop(fp, td);
+ }
+ return (error);
+}
+
static int
sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
{
struct thread *td;
struct proc *p;
- struct file *fp;
- struct kqueue *kq;
- struct knote *kn;
- int error, i, *name;
+ struct sbuf *s, sm;
+ int error, error1, *name;
+ bool compat32;
name = (int *)arg1;
- if ((u_int)arg2 != 2)
+ if ((u_int)arg2 > 2 || (u_int)arg2 == 0)
return (EINVAL);
error = pget((pid_t)name[0], PGET_HOLD | PGET_CANDEBUG, &p);
if (error != 0)
return (error);
-#ifdef COMPAT_FREEBSD32
- if (SV_CURPROC_FLAG(SV_ILP32)) {
- /* XXXKIB */
- error = EOPNOTSUPP;
- goto out1;
- }
-#endif
td = curthread;
- error = fget_remote(td, p, name[1] /* kqfd */, &fp);
- if (error != 0)
- goto out1;
- if (fp->f_type != DTYPE_KQUEUE) {
- error = EINVAL;
- goto out2;
+#ifdef FREEBSD_COMPAT32
+ compat32 = SV_CURPROC_FLAG(SV_ILP32);
+#else
+ compat32 = false;
+#endif
+
+ s = sbuf_new_for_sysctl(&sm, NULL, 0, req);
+ if (s == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ sbuf_clear_flags(s, SBUF_INCLUDENUL);
+
+ if ((u_int)arg2 == 1) {
+ error = kern_proc_kqueues_out1(td, p, s, compat32);
+ } else {
+ error = sysctl_kern_proc_kqueue_one(td, s, p,
+ name[1] /* kq_fd */, compat32);
}
- kq = fp->f_data;
- if (req->oldptr == NULL) {
- error = SYSCTL_OUT(req, NULL, sizeof(struct kinfo_knote) *
- kq->kq_knlistsize * 11 / 10);
- goto out2;
- }
+ error1 = sbuf_finish(s);
+ if (error == 0)
+ error = error1;
+ sbuf_delete(s);
- KQ_LOCK(kq);
- for (i = 0; i < kq->kq_knlistsize; i++) {
- SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
- error = sysctl_kern_proc_kqueue_report_one(p, req,
- kq, kn);
- if (error != 0)
- goto out3;
- }
- }
- if (kq->kq_knhashmask == 0)
- goto out3;
- for (i = 0; i <= kq->kq_knhashmask; i++) {
- SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
- error = sysctl_kern_proc_kqueue_report_one(p, req,
- kq, kn);
- if (error != 0)
- goto out3;
- }
- }
-out3:
- KQ_UNLOCK_FLUX(kq);
-out2:
- fdrop(fp, td);
-out1:
+out:
PRELE(p);
return (error);
}
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -840,6 +840,7 @@
#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */
#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */
#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */
+#define NT_PROCSTAT_KQUEUES 18 /* Procstat kqueues events. */
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
#define NT_X86_SEGBASES 0x200 /* x86 FS/GS base addresses. */
diff --git a/sys/sys/file.h b/sys/sys/file.h
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -267,6 +267,8 @@
int needfcntl, struct file **fpp);
int _fdrop(struct file *fp, struct thread *td);
int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp);
+int fget_remote_foreach(struct thread *td, struct proc *p,
+ int (*fn)(struct proc *, int, struct file *, void *), void *arg);
fo_rdwr_t invfo_rdwr;
fo_truncate_t invfo_truncate;
diff --git a/sys/sys/user.h b/sys/sys/user.h
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -677,9 +677,11 @@
#define KNOTE_EXTDATA_PIPE 2
struct kinfo_knote {
+ int knt_kq_fd;
struct kevent knt_event;
int knt_status;
int knt_extdata;
+ uint64_t knt_spare0[4];
union {
struct {
int knt_vnode_type;
@@ -720,6 +722,8 @@
int kern_proc_out(struct proc *p, struct sbuf *sb, int flags);
int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
int flags);
+int kern_proc_kqueues_out(struct proc *p, struct sbuf *s, size_t maxlen,
+ bool compat32);
int vntype_to_kinfo(int vtype);
void pack_kinfo(struct kinfo_file *kif);
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
--- a/usr.bin/gcore/elfcore.c
+++ b/usr.bin/gcore/elfcore.c
@@ -105,6 +105,7 @@
static void *elf_note_procstat_auxv(void *, size_t *);
static void *elf_note_procstat_files(void *, size_t *);
static void *elf_note_procstat_groups(void *, size_t *);
+static void *elf_note_procstat_kqueues(void *, size_t *);
static void *elf_note_procstat_osrel(void *, size_t *);
static void *elf_note_procstat_proc(void *, size_t *);
static void *elf_note_procstat_psstrings(void *, size_t *);
@@ -388,6 +389,7 @@
elf_putnote(NT_PROCSTAT_PSSTRINGS, elf_note_procstat_psstrings, &pid,
sb);
elf_putnote(NT_PROCSTAT_AUXV, elf_note_procstat_auxv, &pid, sb);
+ elf_putnote(NT_PROCSTAT_KQUEUES, elf_note_procstat_kqueues, &pid, sb);
#endif
size = sbuf_end_section(sb, old_len, 1, 0);
@@ -756,7 +758,7 @@
{
size_t len;
pid_t pid;
- int name[4], structsize;
+ int name[5], structsize;
void *buf, *p;
pid = *(pid_t *)arg;
@@ -841,6 +843,14 @@
sizeof(Elf_Auxinfo), sizep));
}
+static void *
+elf_note_procstat_kqueues(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_KQUEUE,
+ sizeof(struct kinfo_knote), sizep));
+}
+
static void *
elf_note_procstat_rlimit(void *arg, size_t *sizep)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 20, 6:43 AM (21 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17227549
Default Alt Text
D49372.diff (21 KB)
Attached To
Mode
D49372: More work on kq introspection: NT_PROCSTAT_KQUEUE and compat32
Attached
Detach File
Event Timeline
Log In to Comment