public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* dereferencing pointer to incomplete type ‘struct workqueue_struct’
@ 2017-04-26 15:20 John Busch
  2017-04-27  7:07 ` Arkady
  0 siblings, 1 reply; 6+ messages in thread
From: John Busch @ 2017-04-26 15:20 UTC (permalink / raw)
  To: systemtap

Hello,

I’m new to SystemTap, and trying to print information about kernel
work queues.  I’ve used the example code in section 4.3 [1] of the
tutorial as my starting point, and I’m working on an up-to-date Fedora
25 system.

The example code in the tutorial works just fine.  However, when I
essentially swap out variable and struct names to modify the example
to walk through workqueue_structs (instead of task_structs), I get a
“dereferencing pointer to incomplete type ‘struct workqueue_struct’”
compilation error on the line containing list_for_each_safe.  Code
sample below.

workqueue_struct is defined in workqueue.h [2] and workqueue.c [4],
and I’m trying to access the global variable system_wq [3, 5].  How
would I gain access to these objects in systemtap?  I must be doing
something wrong, but can't figure out what it is.

Thanks!

[1] https://sourceware.org/systemtap/tutorial/Tapsets.html
[2] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L16
[3] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L365
[4] http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
[5] http://lxr.free-electrons.com/source/kernel/workqueue.c#L338

%{
#include <linux/workqueue.h>
#include <linux/list.h>
%}

function read_wq_list:long ()
%{
   int ret = 0;
   struct workqueue_struct *wq;
   struct list_head *p, *n;

   list_for_each_safe(p, n, system_wq->list) {
       wq = list_entry(p, struct workqueue_struct, list);
       _stp_printf("workqueue struct %s\n", wq->name);
   }

   STAP_RETURN(ret);
%}

probe begin
{
printf("reading list of workqueues\n")
read_wq_list()
exit()
}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: dereferencing pointer to incomplete type ‘struct workqueue_struct’
  2017-04-26 15:20 dereferencing pointer to incomplete type ‘struct workqueue_struct’ John Busch
@ 2017-04-27  7:07 ` Arkady
  2017-04-27 13:02   ` John Busch
  0 siblings, 1 reply; 6+ messages in thread
From: Arkady @ 2017-04-27  7:07 UTC (permalink / raw)
  To: John Busch; +Cc: systemtap

The simplest way to resolve the problem is top copy the struct to the
inline C code

http://lxr.free-electrons.com/source/kernel/workqueue.c#L239

On Wed, Apr 26, 2017 at 6:20 PM, John Busch <jbusch175@gmail.com> wrote:
> Hello,
>
> I’m new to SystemTap, and trying to print information about kernel
> work queues.  I’ve used the example code in section 4.3 [1] of the
> tutorial as my starting point, and I’m working on an up-to-date Fedora
> 25 system.
>
> The example code in the tutorial works just fine.  However, when I
> essentially swap out variable and struct names to modify the example
> to walk through workqueue_structs (instead of task_structs), I get a
> “dereferencing pointer to incomplete type ‘struct workqueue_struct’”
> compilation error on the line containing list_for_each_safe.  Code
> sample below.
>
> workqueue_struct is defined in workqueue.h [2] and workqueue.c [4],
> and I’m trying to access the global variable system_wq [3, 5].  How
> would I gain access to these objects in systemtap?  I must be doing
> something wrong, but can't figure out what it is.
>
> Thanks!
>
> [1] https://sourceware.org/systemtap/tutorial/Tapsets.html
> [2] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L16
> [3] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L365
> [4] http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
> [5] http://lxr.free-electrons.com/source/kernel/workqueue.c#L338
>
> %{
> #include <linux/workqueue.h>
> #include <linux/list.h>
> %}
>
> function read_wq_list:long ()
> %{
>    int ret = 0;
>    struct workqueue_struct *wq;
>    struct list_head *p, *n;
>
>    list_for_each_safe(p, n, system_wq->list) {
>        wq = list_entry(p, struct workqueue_struct, list);
>        _stp_printf("workqueue struct %s\n", wq->name);
>    }
>
>    STAP_RETURN(ret);
> %}
>
> probe begin
> {
> printf("reading list of workqueues\n")
> read_wq_list()
> exit()
> }

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: dereferencing pointer to incomplete type ‘struct workqueue_struct’
  2017-04-27  7:07 ` Arkady
@ 2017-04-27 13:02   ` John Busch
  2017-04-27 14:43     ` David Smith
  0 siblings, 1 reply; 6+ messages in thread
From: John Busch @ 2017-04-27 13:02 UTC (permalink / raw)
  To: Arkady; +Cc: systemtap

This worked for me.  Thank you Arkady!

On Thu, Apr 27, 2017 at 3:07 AM, Arkady <arkady.miasnikov@gmail.com> wrote:
> The simplest way to resolve the problem is top copy the struct to the
> inline C code
>
> http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
>
> On Wed, Apr 26, 2017 at 6:20 PM, John Busch <jbusch175@gmail.com> wrote:
>> Hello,
>>
>> I’m new to SystemTap, and trying to print information about kernel
>> work queues.  I’ve used the example code in section 4.3 [1] of the
>> tutorial as my starting point, and I’m working on an up-to-date Fedora
>> 25 system.
>>
>> The example code in the tutorial works just fine.  However, when I
>> essentially swap out variable and struct names to modify the example
>> to walk through workqueue_structs (instead of task_structs), I get a
>> “dereferencing pointer to incomplete type ‘struct workqueue_struct’”
>> compilation error on the line containing list_for_each_safe.  Code
>> sample below.
>>
>> workqueue_struct is defined in workqueue.h [2] and workqueue.c [4],
>> and I’m trying to access the global variable system_wq [3, 5].  How
>> would I gain access to these objects in systemtap?  I must be doing
>> something wrong, but can't figure out what it is.
>>
>> Thanks!
>>
>> [1] https://sourceware.org/systemtap/tutorial/Tapsets.html
>> [2] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L16
>> [3] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L365
>> [4] http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
>> [5] http://lxr.free-electrons.com/source/kernel/workqueue.c#L338
>>
>> %{
>> #include <linux/workqueue.h>
>> #include <linux/list.h>
>> %}
>>
>> function read_wq_list:long ()
>> %{
>>    int ret = 0;
>>    struct workqueue_struct *wq;
>>    struct list_head *p, *n;
>>
>>    list_for_each_safe(p, n, system_wq->list) {
>>        wq = list_entry(p, struct workqueue_struct, list);
>>        _stp_printf("workqueue struct %s\n", wq->name);
>>    }
>>
>>    STAP_RETURN(ret);
>> %}
>>
>> probe begin
>> {
>> printf("reading list of workqueues\n")
>> read_wq_list()
>> exit()
>> }

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: dereferencing pointer to incomplete type ‘struct workqueue_struct’
  2017-04-27 13:02   ` John Busch
@ 2017-04-27 14:43     ` David Smith
  2017-04-27 19:08       ` John Busch
  0 siblings, 1 reply; 6+ messages in thread
From: David Smith @ 2017-04-27 14:43 UTC (permalink / raw)
  To: John Busch; +Cc: Arkady, systemtap

If you look carefully, workqueue_struct isn't defined in
include/linux/workqueue.h. It is declared ("struct
workqueue_struct;"), but never fully defined ("struct workqueue_struct
{ char *name, ... }") in that file. So, that's why the compiler is
giving you that error. It has nothing to do with systemtap, if you
tried to compile a kernel module without systemtap, you'd get the same
error. The workqueue_struct definition is private to the workqueue.c
file.

Strangely enough, systemtap use of debuginfo would give it a
definition of that structure. So, you could write something like the
following in script language:

====
function display_wq_name:long(wq:long)
{
    printf("workqueue struct %s\n", @cast(wq, "workqueue_struct")->name)
}
====

However, the problem is iterating through that list in script
language. To do that correctly, you'd need embedded-C as you've got
here.

To solve your problem, unfortunately copying the workqueue_struct
definition into your module is the only way to go to make the compiler
happy. Of course if you plan to use this long term, you'll have to
keep an eye on that private structure and be on the lookout for
changes.

Also note that if this is just a one-off exercise, your code is fine.
If you planned to use this long term or on a system you really cared
about, you'd need to change it to use systemtap's kderef_* functions
to ensure that memory is safe to read.


On Thu, Apr 27, 2017 at 8:02 AM, John Busch <jbusch175@gmail.com> wrote:
> This worked for me.  Thank you Arkady!
>
> On Thu, Apr 27, 2017 at 3:07 AM, Arkady <arkady.miasnikov@gmail.com> wrote:
>> The simplest way to resolve the problem is top copy the struct to the
>> inline C code
>>
>> http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
>>
>> On Wed, Apr 26, 2017 at 6:20 PM, John Busch <jbusch175@gmail.com> wrote:
>>> Hello,
>>>
>>> I’m new to SystemTap, and trying to print information about kernel
>>> work queues.  I’ve used the example code in section 4.3 [1] of the
>>> tutorial as my starting point, and I’m working on an up-to-date Fedora
>>> 25 system.
>>>
>>> The example code in the tutorial works just fine.  However, when I
>>> essentially swap out variable and struct names to modify the example
>>> to walk through workqueue_structs (instead of task_structs), I get a
>>> “dereferencing pointer to incomplete type ‘struct workqueue_struct’”
>>> compilation error on the line containing list_for_each_safe.  Code
>>> sample below.
>>>
>>> workqueue_struct is defined in workqueue.h [2] and workqueue.c [4],
>>> and I’m trying to access the global variable system_wq [3, 5].  How
>>> would I gain access to these objects in systemtap?  I must be doing
>>> something wrong, but can't figure out what it is.
>>>
>>> Thanks!
>>>
>>> [1] https://sourceware.org/systemtap/tutorial/Tapsets.html
>>> [2] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L16
>>> [3] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L365
>>> [4] http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
>>> [5] http://lxr.free-electrons.com/source/kernel/workqueue.c#L338
>>>
>>> %{
>>> #include <linux/workqueue.h>
>>> #include <linux/list.h>
>>> %}
>>>
>>> function read_wq_list:long ()
>>> %{
>>>    int ret = 0;
>>>    struct workqueue_struct *wq;
>>>    struct list_head *p, *n;
>>>
>>>    list_for_each_safe(p, n, system_wq->list) {
>>>        wq = list_entry(p, struct workqueue_struct, list);
>>>        _stp_printf("workqueue struct %s\n", wq->name);
>>>    }
>>>
>>>    STAP_RETURN(ret);
>>> %}
>>>
>>> probe begin
>>> {
>>> printf("reading list of workqueues\n")
>>> read_wq_list()
>>> exit()
>>> }



-- 
David Smith
Principal Software Engineer
Red Hat

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: dereferencing pointer to incomplete type ‘struct workqueue_struct’
  2017-04-27 14:43     ` David Smith
@ 2017-04-27 19:08       ` John Busch
  2017-04-28 14:36         ` Frank Ch. Eigler
  0 siblings, 1 reply; 6+ messages in thread
From: John Busch @ 2017-04-27 19:08 UTC (permalink / raw)
  To: David Smith; +Cc: Arkady, systemtap

Thanks David, this is helpful.  Struct definitions in .c files is new
to me.  I'll also check out using kderef_* as well.  Thanks!

On Thu, Apr 27, 2017 at 10:43 AM, David Smith <dsmith@redhat.com> wrote:
> If you look carefully, workqueue_struct isn't defined in
> include/linux/workqueue.h. It is declared ("struct
> workqueue_struct;"), but never fully defined ("struct workqueue_struct
> { char *name, ... }") in that file. So, that's why the compiler is
> giving you that error. It has nothing to do with systemtap, if you
> tried to compile a kernel module without systemtap, you'd get the same
> error. The workqueue_struct definition is private to the workqueue.c
> file.
>
> Strangely enough, systemtap use of debuginfo would give it a
> definition of that structure. So, you could write something like the
> following in script language:
>
> ====
> function display_wq_name:long(wq:long)
> {
>     printf("workqueue struct %s\n", @cast(wq, "workqueue_struct")->name)
> }
> ====
>
> However, the problem is iterating through that list in script
> language. To do that correctly, you'd need embedded-C as you've got
> here.
>
> To solve your problem, unfortunately copying the workqueue_struct
> definition into your module is the only way to go to make the compiler
> happy. Of course if you plan to use this long term, you'll have to
> keep an eye on that private structure and be on the lookout for
> changes.
>
> Also note that if this is just a one-off exercise, your code is fine.
> If you planned to use this long term or on a system you really cared
> about, you'd need to change it to use systemtap's kderef_* functions
> to ensure that memory is safe to read.
>
>
> On Thu, Apr 27, 2017 at 8:02 AM, John Busch <jbusch175@gmail.com> wrote:
>> This worked for me.  Thank you Arkady!
>>
>> On Thu, Apr 27, 2017 at 3:07 AM, Arkady <arkady.miasnikov@gmail.com> wrote:
>>> The simplest way to resolve the problem is top copy the struct to the
>>> inline C code
>>>
>>> http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
>>>
>>> On Wed, Apr 26, 2017 at 6:20 PM, John Busch <jbusch175@gmail.com> wrote:
>>>> Hello,
>>>>
>>>> I’m new to SystemTap, and trying to print information about kernel
>>>> work queues.  I’ve used the example code in section 4.3 [1] of the
>>>> tutorial as my starting point, and I’m working on an up-to-date Fedora
>>>> 25 system.
>>>>
>>>> The example code in the tutorial works just fine.  However, when I
>>>> essentially swap out variable and struct names to modify the example
>>>> to walk through workqueue_structs (instead of task_structs), I get a
>>>> “dereferencing pointer to incomplete type ‘struct workqueue_struct’”
>>>> compilation error on the line containing list_for_each_safe.  Code
>>>> sample below.
>>>>
>>>> workqueue_struct is defined in workqueue.h [2] and workqueue.c [4],
>>>> and I’m trying to access the global variable system_wq [3, 5].  How
>>>> would I gain access to these objects in systemtap?  I must be doing
>>>> something wrong, but can't figure out what it is.
>>>>
>>>> Thanks!
>>>>
>>>> [1] https://sourceware.org/systemtap/tutorial/Tapsets.html
>>>> [2] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L16
>>>> [3] http://lxr.free-electrons.com/source/include/linux/workqueue.h#L365
>>>> [4] http://lxr.free-electrons.com/source/kernel/workqueue.c#L239
>>>> [5] http://lxr.free-electrons.com/source/kernel/workqueue.c#L338
>>>>
>>>> %{
>>>> #include <linux/workqueue.h>
>>>> #include <linux/list.h>
>>>> %}
>>>>
>>>> function read_wq_list:long ()
>>>> %{
>>>>    int ret = 0;
>>>>    struct workqueue_struct *wq;
>>>>    struct list_head *p, *n;
>>>>
>>>>    list_for_each_safe(p, n, system_wq->list) {
>>>>        wq = list_entry(p, struct workqueue_struct, list);
>>>>        _stp_printf("workqueue struct %s\n", wq->name);
>>>>    }
>>>>
>>>>    STAP_RETURN(ret);
>>>> %}
>>>>
>>>> probe begin
>>>> {
>>>> printf("reading list of workqueues\n")
>>>> read_wq_list()
>>>> exit()
>>>> }
>
>
>
> --
> David Smith
> Principal Software Engineer
> Red Hat

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: dereferencing pointer to incomplete type ‘struct workqueue_struct’
  2017-04-27 19:08       ` John Busch
@ 2017-04-28 14:36         ` Frank Ch. Eigler
  0 siblings, 0 replies; 6+ messages in thread
From: Frank Ch. Eigler @ 2017-04-28 14:36 UTC (permalink / raw)
  To: John Busch; +Cc: David Smith, Arkady, systemtap


jbusch175 / dsmith wrote:

>> [...]  However, the problem is iterating through that list in script
>> language. To do that correctly, you'd need embedded-C as you've got
>> here.  [...]

Iterating through the list in script language is possible though.
The workqueue structure is available via 
   p = @var("system_wq")
Its list_head field is accessible via
   n = @cast(p, "workqueue_struct")->list->next
One can get back to the workqueue_struct from a list pointer via
   p = & @container_of(n, "workqueue_struct", list)

So putting it together:

# stap -DMAXACTION=50000  -e '
probe oneshot { 
  p=@var("system_wq")
  while (max++ < 5000) {
    printf("p=%p name=%s\n", p, @cast(p,"workqueue_struct")->name$);
    n = @cast(p, "workqueue_struct")->list->next;
    ne = & @cast(p, "workqueue_struct")->list;
    if (n == ne) break;
    p = & @container_of(n, "workqueue_struct", list);
  }
}
'

- FChE

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-04-28 14:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-26 15:20 dereferencing pointer to incomplete type ‘struct workqueue_struct’ John Busch
2017-04-27  7:07 ` Arkady
2017-04-27 13:02   ` John Busch
2017-04-27 14:43     ` David Smith
2017-04-27 19:08       ` John Busch
2017-04-28 14:36         ` Frank Ch. Eigler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).