Why my DTrace script does not work after installing a new kernel without reboot
Andreas Longwitz
longwitz at incore.de
Sun Oct 28 10:56:15 UTC 2018
Thans very much for quick answer !
>> I have a simple, probably stupid question. I run FreeBSD 10.4 Stable
>> r338093 and use the script
>>
>> #!/usr/sbin/dtrace -s
>>
>> dtrace:::BEGIN
>> {
>> printf("pf_default_rule.timeout[2/16/17]=%d/%d/%d\n",
>> kernel`pf_default_rule.timeout[2], kernel`pf_default_rule.timeout[16],
>> kernel`pf_default_rule.timeout[17]);
>> }
>>
>> The output normally is
>> pf_default_rule.timeout[2/16/17]=86400/6000/12000
>>
>> But when I change the sourcefile /sys/netpfil/pf/pf.c trying a patch and
>> build and install the new kernel but without reboot, then the output of
>> the script is wrong:
>>
>> pf_default_rule.timeout[2/16/17]=3237216124/0/0
>>
>> After reboot everything works again.
>
> Does your patch change the layout of the timeout structure? If so, the
> problem is that dtrace(1) is using the CTF from kern.bootfile, but that
> doesn't match the layout of the structures used by the running kernel.
My patch does not change data structures, I have added a debug statement
for an actual pf problem:
--- pf.c.orig 2018-08-14 10:17:41.000000000 +0200
+++ pf.c 2018-10-28 00:04:45.441327000 +0200
@@ -1543,6 +1543,12 @@
if (start) {
end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
states = counter_u64_fetch(state->rule.ptr->states_cur);
+ if (bootverbose > 5) {
+ if (states > 10000) {
+ bootverbose--;
+ printf("%s: counter value %u too big ",
__func__, states);
+ }
+ }
} else {
start = V_pf_default_rule.timeout[PFTM_ADAPTIVE_START];
end = V_pf_default_rule.timeout[PFTM_ADAPTIVE_END];
If dtrace(1) uses the CTF of kern.bootfile, then everything should work
as expected. Normally I have
-> sysctl kern.bootfile
kern.bootfile: /boot/kernel/kernel
and after building and installing the patched kernel I have
-> sysctl kern.bootfile
kern.bootfile: /boot/kernel.old/kernel
and that is correct the file of the actual running kernel.
I do not understand the logic of dtrace(1) in handling the kern.bootfile
variable. This is done in sourcefile dt_open.c:
/*
* On FreeBSD the kernel module name can't be hard-coded. The
* 'kern.bootfile' sysctl value tells us exactly which file is being
* used as the kernel.
*/
#ifndef illumos
{
char bootfile[MAXPATHLEN];
char *p;
int i;
size_t len = sizeof(bootfile);
/* This call shouldn't fail, but use a default just in case. */
if (sysctlbyname("kern.bootfile", bootfile, &len, NULL, 0) != 0)
strlcpy(bootfile, "kernel", sizeof(bootfile));
if ((p = strrchr(bootfile, '/')) != NULL)
p++;
else
p = bootfile;
If I am not comletely wrong this code snippet does not do what can be
read in the comment. The function strrchr() returns a pointer to the
last occurrence of '/' in bootfile, so we always end with *p="kernel".
After
cd /boot; mv kernel kernel.new; mv kernel.old kernel
my DTrace script works correct again, that means dtrace(1) always uses
/boot/kernel/kernel.
So there may be a bug in handling the kern.bootfile variable in dtrace.
Best regards,
Andreas
More information about the freebsd-dtrace
mailing list