[ltt-dev] [PATCH] LTTNG: Make marker enabled in advance
Gui Jianfeng
guijianfeng at cn.fujitsu.com
Fri Mar 6 01:40:56 EST 2009
Mathieu Desnoyers wrote:
> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>> Mathieu Desnoyers wrote:
>>> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>>>> Mathieu Desnoyers wrote:
>>>>> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>>>>>> Hi Mathieu,
>>>>>>
>>>>>> This patch makes marker enabled in advance.
>>>>>> IOW, even if the marker isn't present for the moment,
>>>>>> you can still enable it for future use.
>>>>>> As soon as the marker is inserted into kernel, tracing
>>>>>> work can be started immediately.
>>>>>>
>>>>>> Here is an example for using the user interface:
>>>>>> This patch assumes the marker control patch is applied.
>>>>>>
>>>>>> [root at localhost markers]# cd /mnt/debugfs/ltt/markers
>>>>>> [root at localhost markers]# mkdir fs
>>>>>> [root at localhost markers]# cd fs
>>>>>> [root at localhost fs]# mkdir close
>>>>>> [root at localhost fs]# cd close/
>>>>>> [root at localhost close]# ls
>>>>>> enable info
>>>>>> [root at localhost close]# echo 1 > enable
>>>>>> [root at localhost close]# cat enable
>>>>>> 2
>>>>>> [root at localhost close]# cat info
>>>>>> marker is not present now!
>>>>>> [root at localhost close]# modprobe fs_trace
>>>>>> [root at localhost close]# cat enable
>>>>>> 1
>>>>>> [root at localhost close]# cat info
>>>>>> format: "fd %u"
>>>>>> state: 1
>>>>>> event_id: 1
>>>>>> call: 0xc0468167
>>>>>> probe single : 0xc0520cdc
>>>>>>
>>>>>> Signed-off-by: Gui Jianfeng <guijianfeng at cn.fujitsu.com>
>>>>>> ---
>>>>>> ltt/ltt-trace-control.c | 357 ++++++++++++++++++++++++++++++++---------------
>>>>>> 1 files changed, 247 insertions(+), 110 deletions(-)
>>>>>>
>>>>>> diff --git a/ltt/ltt-trace-control.c b/ltt/ltt-trace-control.c
>>>>>> index 128db4e..7e1c32e 100644
>>>>>> --- a/ltt/ltt-trace-control.c
>>>>>> +++ b/ltt/ltt-trace-control.c
>>>>>> @@ -19,6 +19,7 @@
>>>>>> #include <linux/debugfs.h>
>>>>>> #include <linux/ltt-tracer.h>
>>>>>> #include <linux/notifier.h>
>>>>>> +#include <linux/mutex.h>
>>>>>>
>>>>>> #define LTT_CONTROL_DIR "control"
>>>>>> #define MARKERS_CONTROL_DIR "markers"
>>>>>> @@ -27,9 +28,240 @@
>>>>>>
>>>>>> #define LTT_WRITE_MAXLEN (128)
>>>>>>
>>>>>> +#define MARKER_ENABLE_MASK 0x7UL
>>>>> What is this doing ?
>>>> marker is 8 bytes aligned, the last 3 bit must 0.
>>>> I use these bits to identify whether the marker is enabled in advance.
>>>>
>>> Is there a clear gain to encode such information in the pointer bits ?
>>> Can we simply add a "char" somewhere which would be easier for the code
>>> reviewers ? I rarely found out that this addition of complexity was
>>> worth it, except when some updates need to be done atomically.
>> Hi Mathieu,
>>
>> I make use of inode->i_private of the file "enable" to store the corresponding
>> marker address. If marker isn't present in kernel, but someone want to enable
>> it in advance, inode->i_private will be 0x00000001. We don't need additional
>> space to store *Pre-enable* status.
>> If you have a better solution, could you give me some suggestions?
>>
>
> Oh ! I see, you keep a pointer to struct marker as i_private of the
> marker files in the debugfs tree. This is buggy, here is why :
>
> If the follow happens :
>
> module A has marker1
> module B has marker1 (too)
>
> We have :
>
> insmod module A
> -> marker1 debugfs files created, pointing to module A marker1
> insmod module B
> -> marker1 already exists, no update done, but "marker1" i_private
> still points to module A's marker1
> rmmod module A
> -> removing marker1, but module B still has one which should show up
> in the directory tree.
marker1 will not show up any more, it will gone when removing module A.
So this won't cause serious problem. but this is a problem for sure,
beacuse current implementation can't handle same name marker....
>
> How to fix this ? Simply by _not_ keeping a direct reference to
> struct marker within ltt-trace-control.c.
>
> We have a hash table in kernel/marker.c which takes care of exactly
> this: it keeps a reference could of each marker loaded. Therefore, if
> you need to get information about the state of such marker, you should
> really use primitives like include/linux/marker.h:is_marker_enabled(),
> and create your own primitives to export the information you need from
> marker.c.
>
> This will solve you "is enabled" problem, because this hash table keeps
> track of _activated_ markers. Therefore, for each marker you encounter
> in the marker section (what you are iterating on upon module load
> notification), you just have to query the is_marker_enabled() state for
> the channel and marker name to get its state.
>
> You will however need to be called also when the marker state changes.
> One way to do this would be to add a marker update notifier chain to
> kernel/marker.c which would call your notifier callback.
>
> Looking at the register_module_notifier() use you are doing in
> ltt_trace_control makes think of the following : kernel/marker.c should
> use register_module_notifier(), but your module should not be called by
> module.c. It should rather be called by marker.c, which is the module
> which modifies the data structures your are interested to follow.
>
> Therefore, once you do that, keeping track of the marker state changes
> will become _much_ easier, and you won't need any of these weird pointer
> handling stuff.
buffering a marker pointer can save search-time. IOW, when read "info" or "enable"
to query information for a given marker, it has to iterate all the marker section
in kernel and each modules to find out the marker. and this also save the time for
calling is_marker_enabled() to search the hash table.
My solution to solve the "same name marker" problem is that buffering the marker
pointer in i_private if a marker doesn't have another same name marker. If there are
two same name markers available, the 2nd lowest bit of i_private will indicate this situation
and we need to iterate all the markers in kernel and modules to find out the corresponding
markers.
>
>>>>>> +
>>>>>> +static DEFINE_MUTEX(unload_mutex);
>>>>> Can you tell me exactly what this protects, where it is nested ?
>>>> when doing mkdir to create a new dir by debugfs_create_dir(), I have to drop
>>>> the parent's i_mutex, because debugfs_create_dir() need it. To prevent the
>>>> parent to be removed, this mutex is introduced.
>>>>
>>> So you want to protect against racy removal ? Which module is
>>> responsible for such removal, and which mutex protects addition/removal?
>>> I really doubt that anything near this unload_mutex is the right
>>> solution.
>> Suppose we are creating a new channel dir, meanwhile we remove the ltt-trace-control
>> module, all debugfs file will be removed. but debugfs_create_dir() is still in
>> processing, but the ltt/marker is gone. Will this scenario happen?
>>
>
> Hrm, upon entry in
>
> fs/namei.c: mkdirat, we have :
>
> dentry = lookup_create(&nd, 1);
>
> Which looks up for the parent path. This will hold the dentry counter on
> the parent. It will execute the vfs_mkdir with this reference count
> held. Therefore, the mkdir functions you created are called with the
> parent's dentry refcount held, is that enough to insure the kind of
> protection you want ?
Is it possible that all other files are remove except the one we protects
and new created files. If this can happen, i don't think it's ok.
The goal of unload_mutex is protecting the whole tree.
>
> Mathieu
>
>
>>> Mathieu
>>>
>>>>> Mathieu
>>>>>
>>>>>> +
>>>> --
>>>> Regards
>>>> Gui Jianfeng
>>>>
>> --
>> Regards
>> Gui Jianfeng
>>
>
--
Regards
Gui Jianfeng
More information about the lttng-dev
mailing list