Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Oct 2018 11:56:11 +0100
From:      Andreas Longwitz <longwitz@incore.de>
To:        Mark Johnston <markj@freebsd.org>
Cc:        "freebsd-dtrace@freebsd.org" <freebsd-dtrace@freebsd.org>
Subject:   Re: Why my DTrace script does not work after installing a new kernel without reboot
Message-ID:  <5BD595CB.5030800@incore.de>
In-Reply-To: <20181027225339.GA4191@spy>
References:  <5BD4E965.9040006@incore.de> <20181027225339.GA4191@spy>

next in thread | previous in thread | raw e-mail | index | archive | help
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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5BD595CB.5030800>