Add a new type of KTRACE record for sysctl(3) invocations. It uses the

internal sysctl_sysctl_name() handler to map the MIB array to a string
name and logs this name in the trace log.  This can be useful to see
exactly which sysctls a thread is invoking.

MFC after:	1 month
This commit is contained in:
John Baldwin
2009-03-11 21:48:36 +00:00
parent a9d9537110
commit a56be37e68
8 changed files with 72 additions and 3 deletions
+39 -1
View File
@@ -111,6 +111,7 @@ static int data_lengths[] = {
sizeof(struct ktr_csw), /* KTR_CSW */
0, /* KTR_USER */
0, /* KTR_STRUCT */
0, /* KTR_SYSCTL */
};
static STAILQ_HEAD(, ktr_request) ktr_free;
@@ -319,7 +320,7 @@ ktr_enqueuerequest(struct thread *td, struct ktr_request *req)
* is used both internally before committing other records, and also on
* system call return. We drain all the ones we can find at the time when
* drain is requested, but don't keep draining after that as those events
* may me approximately "after" the current event.
* may be approximately "after" the current event.
*/
static void
ktr_drain(struct thread *td)
@@ -480,6 +481,40 @@ ktrnamei(path)
ktr_submitrequest(curthread, req);
}
void
ktrsysctl(name, namelen)
int *name;
u_int namelen;
{
struct ktr_request *req;
u_int mib[CTL_MAXNAME + 2];
char *mibname;
size_t mibnamelen;
int error;
/* Lookup name of mib. */
KASSERT(namelen <= CTL_MAXNAME, ("sysctl MIB too long"));
mib[0] = 0;
mib[1] = 1;
bcopy(name, mib + 2, namelen * sizeof(*name));
mibnamelen = 128;
mibname = malloc(mibnamelen, M_KTRACE, M_WAITOK);
error = kernel_sysctl(curthread, mib, namelen + 2, mibname, &mibnamelen,
NULL, 0, &mibnamelen, 0);
if (error) {
free(mibname, M_KTRACE);
return;
}
req = ktr_getrequest(KTR_SYSCTL);
if (req == NULL) {
free(mibname, M_KTRACE);
return;
}
req->ktr_header.ktr_len = mibnamelen;
req->ktr_buffer = mibname;
ktr_submitrequest(curthread, req);
}
void
ktrgenio(fd, rw, uio, error)
int fd;
@@ -925,6 +960,9 @@ ktr_writerequest(struct thread *td, struct ktr_request *req)
mtx_unlock(&ktrace_mtx);
kth = &req->ktr_header;
KASSERT(((u_short)kth->ktr_type & ~KTR_DROP) <
sizeof(data_lengths) / sizeof(data_lengths[0]),
("data_lengths array overflow"));
datalen = data_lengths[(u_short)kth->ktr_type & ~KTR_DROP];
buflen = kth->ktr_len;
auio.uio_iov = &aiov[0];
+10 -1
View File
@@ -39,6 +39,7 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
#include <sys/param.h>
@@ -54,6 +55,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sysproto.h>
#include <sys/uio.h>
#include <sys/vimage.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
#include <security/mac/mac_framework.h>
@@ -758,7 +762,7 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
static int
name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidpp)
name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
{
int i;
struct sysctl_oid *oidp;
@@ -1499,6 +1503,11 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
req.newfunc = sysctl_new_user;
req.lock = REQ_LOCKED;
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_SYSCTL))
ktrsysctl(name, namelen);
#endif
SYSCTL_XLOCK();
CURVNET_SET(TD_TO_VNET(curthread));
+9
View File
@@ -157,6 +157,12 @@ struct ktr_csw {
struct sockaddr;
struct stat;
/*
* KTR_SYSCTL - name of a sysctl MIB
*/
#define KTR_SYSCTL 9
/* record contains null-terminated MIB name */
/*
* KTR_DROP - If this bit is set in ktr_type, then at least one event
* between the previous record and this record was dropped.
@@ -175,6 +181,8 @@ struct stat;
#define KTRFAC_CSW (1<<KTR_CSW)
#define KTRFAC_USER (1<<KTR_USER)
#define KTRFAC_STRUCT (1<<KTR_STRUCT)
#define KTRFAC_SYSCTL (1<<KTR_SYSCTL)
/*
* trace flags (also in p_traceflags)
*/
@@ -190,6 +198,7 @@ void ktrcsw(int, int);
void ktrpsig(int, sig_t, sigset_t *, int);
void ktrgenio(int, enum uio_rw, struct uio *, int);
void ktrsyscall(int, int narg, register_t args[]);
void ktrsysctl(int *name, u_int namelen);
void ktrsysret(int, int, register_t);
void ktrprocexit(struct thread *);
void ktruserret(struct thread *);
+1
View File
@@ -172,6 +172,7 @@ The possible operations are:
.It Li CSW Ta context switch Ta stop/resume user/kernel
.It Li USER Ta data from user process Ta the data
.It Li STRU Ta various syscalls Ta structure
.It Li SCTL Ta Xr sysctl 3 requests Ta MIB name
.El
.Sh SEE ALSO
.Xr ktrace 1
+4
View File
@@ -217,6 +217,7 @@ main(int argc, char *argv[])
ktrsysret((struct ktr_sysret *)m);
break;
case KTR_NAMEI:
case KTR_SYSCTL:
ktrnamei(m, ktrlen);
break;
case KTR_GENIO:
@@ -288,6 +289,9 @@ dumpheader(struct ktr_header *kth)
case KTR_STRUCT:
type = "STRU";
break;
case KTR_SYSCTL:
type = "SCTL";
break;
default:
(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
type = unknown;
+4
View File
@@ -125,6 +125,10 @@ trace various structures
userland traces
.It Cm w
context switches
.It Cm y
trace
.Xr sysctl 3
requests
.It Cm +
trace the default set of trace points -
.Cm c , n , i , s , t , u
+2 -1
View File
@@ -35,7 +35,8 @@
*/
#define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | KTRFAC_STRUCT)
KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \
KTRFAC_STRUCT | KTRFAC_SYSCTL)
#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
+3
View File
@@ -83,6 +83,9 @@ getpoints(char *s)
case 'w':
facs |= KTRFAC_CSW;
break;
case 'y':
facs |= KTRFAC_SYSCTL;
break;
case '+':
facs |= DEF_POINTS;
break;