Add sysctl kern.proc.kqueue

(cherry picked from commit e60f608eb9cf3b38099948545934d699de9bbcea)
This commit is contained in:
Konstantin Belousov 2025-02-23 22:25:25 +02:00
parent ba224cec67
commit e2af76d470
7 changed files with 238 additions and 8 deletions

View file

@ -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");

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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);
};
/*

View file

@ -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

View file

@ -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

View file

@ -34,6 +34,7 @@
*/
#include <sys/param.h>
#include <sys/event.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>