mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Add sysctl kern.proc.kqueue
(cherry picked from commit e60f608eb9cf3b38099948545934d699de9bbcea)
This commit is contained in:
parent
ba224cec67
commit
e2af76d470
7 changed files with 238 additions and 8 deletions
|
|
@ -64,6 +64,7 @@
|
|||
#include <sys/socketvar.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
|
@ -2730,8 +2731,15 @@ knote_drop_detached(struct knote *kn, struct thread *td)
|
|||
KQ_NOTOWNED(kq);
|
||||
|
||||
KQ_LOCK(kq);
|
||||
KASSERT(kn->kn_influx == 1,
|
||||
("knote_drop called on %p with influx %d", kn, kn->kn_influx));
|
||||
for (;;) {
|
||||
KASSERT(kn->kn_influx >= 1,
|
||||
("knote_drop called on %p with influx %d",
|
||||
kn, kn->kn_influx));
|
||||
if (kn->kn_influx == 1)
|
||||
break;
|
||||
kq->kq_state |= KQ_FLUXWAIT;
|
||||
msleep(kq, &kq->kq_lock, PSOCK, "kqflxwt", 0);
|
||||
}
|
||||
|
||||
if (kn->kn_fop->f_isfd)
|
||||
list = &kq->kq_knlist[kn->kn_id];
|
||||
|
|
@ -2829,3 +2837,132 @@ noacquire:
|
|||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
struct knote_status_export_bit {
|
||||
int kn_status_bit;
|
||||
int knt_status_bit;
|
||||
};
|
||||
|
||||
#define ST(name) \
|
||||
{ .kn_status_bit = KN_##name, .knt_status_bit = KNOTE_STATUS_##name }
|
||||
static const struct knote_status_export_bit knote_status_export_bits[] = {
|
||||
ST(ACTIVE),
|
||||
ST(QUEUED),
|
||||
ST(DISABLED),
|
||||
ST(DETACHED),
|
||||
ST(KQUEUE),
|
||||
};
|
||||
#undef ST
|
||||
|
||||
static int
|
||||
knote_status_export(int kn_status)
|
||||
{
|
||||
const struct knote_status_export_bit *b;
|
||||
unsigned i;
|
||||
int res;
|
||||
|
||||
res = 0;
|
||||
for (i = 0; i < nitems(knote_status_export_bits); i++) {
|
||||
b = &knote_status_export_bits[i];
|
||||
if ((kn_status & b->kn_status_bit) != 0)
|
||||
res |= b->knt_status_bit;
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_kern_proc_kqueue_report_one(struct proc *p, struct sysctl_req *req,
|
||||
struct kqueue *kq, struct knote *kn)
|
||||
{
|
||||
struct kinfo_knote kin;
|
||||
int error;
|
||||
|
||||
if (kn->kn_status == KN_MARKER)
|
||||
return (0);
|
||||
|
||||
memset(&kin, 0, sizeof(kin));
|
||||
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();
|
||||
KQ_LOCK(kq);
|
||||
kn_leave_flux(kn);
|
||||
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;
|
||||
|
||||
name = (int *)arg1;
|
||||
if ((u_int)arg2 != 2)
|
||||
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;
|
||||
}
|
||||
|
||||
kq = fp->f_data;
|
||||
if (req->oldptr == NULL) {
|
||||
error = SYSCTL_OUT(req, NULL, sizeof(struct kinfo_knote) *
|
||||
kq->kq_knlistsize * 11 / 10);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
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:
|
||||
PRELE(p);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static SYSCTL_NODE(_kern_proc, KERN_PROC_KQUEUE, kq,
|
||||
CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
sysctl_kern_proc_kqueue, "KQueue events");
|
||||
|
|
|
|||
|
|
@ -176,21 +176,26 @@ static void filt_pipedetach_notsup(struct knote *kn);
|
|||
static int filt_pipenotsup(struct knote *kn, long hint);
|
||||
static int filt_piperead(struct knote *kn, long hint);
|
||||
static int filt_pipewrite(struct knote *kn, long hint);
|
||||
static int filt_pipedump(struct proc *p, struct knote *kn,
|
||||
struct kinfo_knote *kin);
|
||||
|
||||
static const struct filterops pipe_nfiltops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_pipedetach_notsup,
|
||||
.f_event = filt_pipenotsup
|
||||
/* no userdump */
|
||||
};
|
||||
static const struct filterops pipe_rfiltops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_pipedetach,
|
||||
.f_event = filt_piperead
|
||||
.f_event = filt_piperead,
|
||||
.f_userdump = filt_pipedump,
|
||||
};
|
||||
static const struct filterops pipe_wfiltops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_pipedetach,
|
||||
.f_event = filt_pipewrite
|
||||
.f_event = filt_pipewrite,
|
||||
.f_userdump = filt_pipedump,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1901,3 +1906,14 @@ filt_pipenotsup(struct knote *kn, long hint)
|
|||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
filt_pipedump(struct proc *p, struct knote *kn,
|
||||
struct kinfo_knote *kin)
|
||||
{
|
||||
struct pipe *pipe = kn->kn_hook;
|
||||
|
||||
kin->knt_extdata = KNOTE_EXTDATA_PIPE;
|
||||
kin->knt_pipe.knt_pipe_ino = pipe->pipe_ino;
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/watchdog.h>
|
||||
|
|
@ -6416,7 +6417,7 @@ const struct filterops fs_filtops = {
|
|||
.f_isfd = 0,
|
||||
.f_attach = filt_fsattach,
|
||||
.f_detach = filt_fsdetach,
|
||||
.f_event = filt_fsevent
|
||||
.f_event = filt_fsevent,
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
@ -6494,20 +6495,26 @@ static int filt_vfsread(struct knote *kn, long hint);
|
|||
static int filt_vfswrite(struct knote *kn, long hint);
|
||||
static int filt_vfsvnode(struct knote *kn, long hint);
|
||||
static void filt_vfsdetach(struct knote *kn);
|
||||
static int filt_vfsdump(struct proc *p, struct knote *kn,
|
||||
struct kinfo_knote *kin);
|
||||
|
||||
static const struct filterops vfsread_filtops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_vfsdetach,
|
||||
.f_event = filt_vfsread
|
||||
.f_event = filt_vfsread,
|
||||
.f_userdump = filt_vfsdump,
|
||||
};
|
||||
static const struct filterops vfswrite_filtops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_vfsdetach,
|
||||
.f_event = filt_vfswrite
|
||||
.f_event = filt_vfswrite,
|
||||
.f_userdump = filt_vfsdump,
|
||||
};
|
||||
static const struct filterops vfsvnode_filtops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = filt_vfsdetach,
|
||||
.f_event = filt_vfsvnode
|
||||
.f_event = filt_vfsvnode,
|
||||
.f_userdump = filt_vfsdump,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -6656,6 +6663,41 @@ filt_vfsvnode(struct knote *kn, long hint)
|
|||
return (res);
|
||||
}
|
||||
|
||||
static int
|
||||
filt_vfsdump(struct proc *p, struct knote *kn, struct kinfo_knote *kin)
|
||||
{
|
||||
struct vattr va;
|
||||
struct vnode *vp;
|
||||
char *fullpath, *freepath;
|
||||
int error;
|
||||
|
||||
kin->knt_extdata = KNOTE_EXTDATA_VNODE;
|
||||
|
||||
vp = kn->kn_fp->f_vnode;
|
||||
kin->knt_vnode.knt_vnode_type = vntype_to_kinfo(vp->v_type);
|
||||
|
||||
va.va_fsid = VNOVAL;
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
error = VOP_GETATTR(vp, &va, curthread->td_ucred);
|
||||
VOP_UNLOCK(vp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
kin->knt_vnode.knt_vnode_fsid = va.va_fsid;
|
||||
kin->knt_vnode.knt_vnode_fileid = va.va_fileid;
|
||||
|
||||
freepath = NULL;
|
||||
fullpath = "-";
|
||||
error = vn_fullpath(vp, &fullpath, &freepath);
|
||||
if (error == 0) {
|
||||
strlcpy(kin->knt_vnode.knt_vnode_fullpath, fullpath,
|
||||
sizeof(kin->knt_vnode.knt_vnode_fullpath));
|
||||
}
|
||||
if (freepath != NULL)
|
||||
free(freepath, M_TEMP);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -262,12 +262,17 @@ struct knlist {
|
|||
#define EVENT_REGISTER 1
|
||||
#define EVENT_PROCESS 2
|
||||
|
||||
struct kinfo_knote;
|
||||
struct proc;
|
||||
|
||||
struct filterops {
|
||||
int f_isfd; /* true if ident == filedescriptor */
|
||||
int (*f_attach)(struct knote *kn);
|
||||
void (*f_detach)(struct knote *kn);
|
||||
int (*f_event)(struct knote *kn, long hint);
|
||||
void (*f_touch)(struct knote *kn, struct kevent *kev, u_long type);
|
||||
int (*f_userdump)(struct proc *p, struct knote *kn,
|
||||
struct kinfo_knote *kin);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1043,6 +1043,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
|
|||
#define KERN_PROC_SIGFASTBLK 44 /* address of fastsigblk magic word */
|
||||
#define KERN_PROC_VM_LAYOUT 45 /* virtual address space layout info */
|
||||
#define KERN_PROC_RLIMIT_USAGE 46 /* array of rlim_t */
|
||||
#define KERN_PROC_KQUEUE 47 /* array of struct kinfo_knote */
|
||||
|
||||
/*
|
||||
* KERN_IPC identifiers
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#ifndef _KERNEL
|
||||
/* stuff that *used* to be included by user.h, or is now needed */
|
||||
#include <sys/errno.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/ucred.h>
|
||||
|
|
@ -667,6 +668,33 @@ struct kinfo_vm_layout {
|
|||
uintptr_t kvm_spare[12];
|
||||
};
|
||||
|
||||
#define KNOTE_STATUS_ACTIVE 0x00000001
|
||||
#define KNOTE_STATUS_QUEUED 0x00000002
|
||||
#define KNOTE_STATUS_DISABLED 0x00000004
|
||||
#define KNOTE_STATUS_DETACHED 0x00000008
|
||||
#define KNOTE_STATUS_KQUEUE 0x00000010
|
||||
|
||||
#define KNOTE_EXTDATA_NONE 0
|
||||
#define KNOTE_EXTDATA_VNODE 1
|
||||
#define KNOTE_EXTDATA_PIPE 2
|
||||
|
||||
struct kinfo_knote {
|
||||
struct kevent knt_event;
|
||||
int knt_status;
|
||||
int knt_extdata;
|
||||
union {
|
||||
struct {
|
||||
int knt_vnode_type;
|
||||
uint64_t knt_vnode_fsid;
|
||||
uint64_t knt_vnode_fileid;
|
||||
char knt_vnode_fullpath[PATH_MAX];
|
||||
} knt_vnode;
|
||||
struct {
|
||||
ino_t knt_pipe_ino;
|
||||
} knt_pipe;
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* Flags for kern_proc_out function. */
|
||||
#define KERN_PROC_NOTHREADS 0x1
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rwlock.h>
|
||||
|
|
|
|||
Loading…
Reference in a new issue