From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10493 invoked by alias); 25 Nov 2009 09:31:13 -0000 Received: (qmail 10451 invoked by uid 22791); 25 Nov 2009 09:31:09 -0000 X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=BAYES_00 X-Spam-Check-By: sourceware.org Received: from e23smtp09.au.ibm.com (HELO e23smtp09.au.ibm.com) (202.81.31.142) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 25 Nov 2009 09:31:02 +0000 Received: from d23relay04.au.ibm.com (d23relay04.au.ibm.com [202.81.31.246]) by e23smtp09.au.ibm.com (8.14.3/8.13.1) with ESMTP id nAPKUx91016094 for ; Thu, 26 Nov 2009 07:30:59 +1100 Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id nAP9RTBG1576978 for ; Wed, 25 Nov 2009 20:27:32 +1100 Received: from d23av02.au.ibm.com (loopback [127.0.0.1]) by d23av02.au.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id nAP9Utwl007657 for ; Wed, 25 Nov 2009 20:30:55 +1100 Received: from localhost (rajduddu.in.ibm.com [9.124.33.100]) by d23av02.au.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id nAP9Urh5007610 for ; Wed, 25 Nov 2009 20:30:54 +1100 Date: Wed, 25 Nov 2009 09:31:00 -0000 From: Rajasekhar Duddu To: systemtap@sources.redhat.com Subject: [PATCH V4] Tracepoint Tapset for Memory Subsystem Message-ID: <20091125093051.GA13363@rajduddu> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) X-IsSubscribed: yes Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2009-q4/txt/msg00694.txt.bz2 Hi all, here I am sending the updated patch along with the example script. Please review it and let me know if it needs any more improvements. Changelog 1: Removed the Hardcoded constants in converting GFPFLAGS. Added a kprobe based fallback probe to kfree. Changelog 2: Removed the unreliable code which was used in fetching the call_site in kprobe based probe for kfree.(__builtin_return_address(0)) Changelog 3: Defined two macros for converting the GFP_FLAGS into string formats. Added k(ret)probe based fallback probes for all the Functions. Changelog 4: Added an example script and a corresponding meta file for kmem_cache_alloc probe point at testsuite/systemtap.examples/memory/vm.tracepoints.(stp/meta) Sample O/P: stap -v testsuite/systemtap.examples/memory/vm.tracepoints.stp Pass 1: parsed user script and 63 library script(s) in 170usr/10sys/189real ms. Pass 2: analyzed script: 2 probe(s), 2 function(s), 5 embed(s), 1 global(s) in 20usr/0sys/24real ms. Pass 3: using cached /root/.systemtap/cache/97/stap_97935f61947942cab7e7143435bd6ee7_3084.c Pass 4: using cached /root/.systemtap/cache/97/stap_97935f61947942cab7e7143435bd6ee7_3084.ko Pass 5: starting run. Process:swapper Slab_size:256 Count:3 Process:sendmail Slab_size:4096 Count:4 Slab_size:256 Count:2 Slab_size:16 Count:2 Slab_size:192 Count:2 Slab_size:640 Count:2 Slab_size:72 Count:2 Slab_size:64 Count:2 Slab_size:32 Count:2 Slab_size:128 Count:2 Process:kjournald Slab_size:104 Count:11 Slab_size:112 Count:11 Slab_size:256 Count:11 Slab_size:336 Count:2 ------------------------------------------------------- Process:sshd Slab_size:512 Count:1 Slab_size:256 Count:1 Process:swapper Slab_size:256 Count:1 Process:sendmail Slab_size:4096 Count:4 Slab_size:256 Count:2 Slab_size:16 Count:2 Slab_size:192 Count:2 Slab_size:640 Count:2 Slab_size:72 Count:2 Slab_size:64 Count:2 Slab_size:32 Count:2 Slab_size:128 Count:2 Process:crond Slab_size:4096 Count:2 ------------------------------------------------------- Patch: Signed-off-by: Rajasekhar Duddu diff -rupaN a/tapset/memory.stp b/tapset/memory.stp --- a/tapset/memory.stp 2009-11-25 01:18:29.000000000 -0500 +++ b/tapset/memory.stp 2009-11-25 01:21:16.000000000 -0500 @@ -195,3 +195,269 @@ probe vm.brk = kernel.function("do_brk") probe vm.oom_kill = kernel.function("__oom_kill_task") { task = $p } +/* Macro for GFP Bitmasks. */ +/* The resulted GFP_FLAGS may be either single or concatenation of the multiple bitmasks. */ + +%{ +#define __GFP_BITMASKS(FLAG) if(gfp_flag & FLAG) { if(THIS->__retvalue[0] != '\0') \ + strlcat(THIS->__retvalue, " | "#FLAG, MAXSTRINGLEN); \ + else strlcat(THIS->__retvalue, #FLAG, MAXSTRINGLEN); } +%} + + +/* Macro for Composite Flags. */ +/* Each Composite GFP_FLAG is the combination of multiple bitmasks. */ + +%{ +#define __GFP_COMPOSITE_FLAG(FLAG) if(gfp_flag == FLAG) { \ + strlcat(THIS->__retvalue, #FLAG, MAXSTRINGLEN); return; } +%} + + +/* Function to convert the GFP_FLAGS into corresponding STRING formats. */ + +function __gfp_flag_str:string(gfp_flag:long) %{ + long gfp_flag = THIS->gfp_flag; + THIS->__retvalue[0] = '\0'; + + +/* Composite GFP FLAGS of the BitMasks. */ + + __GFP_COMPOSITE_FLAG(GFP_ZONEMASK) + __GFP_COMPOSITE_FLAG(GFP_ATOMIC) + __GFP_COMPOSITE_FLAG(GFP_NOIO) + __GFP_COMPOSITE_FLAG(GFP_NOFS) + __GFP_COMPOSITE_FLAG(GFP_KERNEL) + __GFP_COMPOSITE_FLAG(GFP_TEMPORARY) + __GFP_COMPOSITE_FLAG(GFP_USER) + __GFP_COMPOSITE_FLAG(GFP_HIGHUSER) + __GFP_COMPOSITE_FLAG(GFP_HIGHUSER_MOVABLE) + __GFP_COMPOSITE_FLAG(GFP_THISNODE) + __GFP_COMPOSITE_FLAG(GFP_DMA) + __GFP_COMPOSITE_FLAG(GFP_DMA32) + +/* GFP BitMasks */ + + __GFP_BITMASKS(__GFP_DMA) + __GFP_BITMASKS(__GFP_HIGHMEM) + __GFP_BITMASKS(__GFP_MOVABLE) + __GFP_BITMASKS(__GFP_WAIT) + __GFP_BITMASKS(__GFP_HIGH) + __GFP_BITMASKS(__GFP_IO) + __GFP_BITMASKS(__GFP_FS) + __GFP_BITMASKS(__GFP_COLD) + __GFP_BITMASKS(__GFP_NOWARN) + __GFP_BITMASKS(__GFP_REPEAT) + __GFP_BITMASKS(__GFP_NOFAIL) + __GFP_BITMASKS(__GFP_COMP) + __GFP_BITMASKS(__GFP_ZERO) + __GFP_BITMASKS(__GFP_NOMEMALLOC) + __GFP_BITMASKS(__GFP_HARDWALL) + __GFP_BITMASKS(__GFP_THISNODE) + __GFP_BITMASKS(__GFP_RECLAIMABLE) + __GFP_BITMASKS(__GFP_NOTRACK) + +%} + +/* The Formal Parameters will be displayed if available, otherwise \ + "0" or "unknown" will be displayed */ + +probe __vm.kmalloc.tp = kernel.trace("kmalloc") { + name = "kmalloc" + call_site = $call_site + caller_function = symname(call_site) + bytes_req = $bytes_req + bytes_alloc = $bytes_alloc + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $ptr +} + +/* It is unsafe to invoke __builtin_return_address() \ +presently(to get call_site for kporbe based probes) \ +and that it can be improved later when fix for bugs bz#6961 and bz#6580 is available. */ + +probe __vm.kmalloc.kp = kernel.function("kmalloc").return { + name = "kmalloc" + call_site = 0 + caller_function = "unknown" + bytes_req = $size + bytes_alloc = "unknown" + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $return +} + +/** + * probe vm.kmalloc - Fires when kmalloc is requested. + * @call_site: Address of the kmemory function. + * @caller_function: Name of the caller function. + * @bytes_req: Requested Bytes + * @bytes_alloc: Allocated Bytes + * @gfp_flags: type of kmemory to allocate + * @gfp_flag_name: type of kmemory to allocate (in String format) + * @ptr: Pointer to the kmemory allocated + */ +probe vm.kmalloc = __vm.kmalloc.tp !, + __vm.kmalloc.kp +{} + + +probe __vm.kmem_cache_alloc.tp = kernel.trace("kmem_cache_alloc") { + name = "kmem_cache_alloc" + call_site = $call_site + caller_function = symname(call_site) + bytes_req = $bytes_req + bytes_alloc = $bytes_alloc + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $ptr +} + +probe __vm.kmem_cache_alloc.kp = kernel.function("kmem_cache_alloc").return { + name = "kmem_cache_alloc" + call_site = 0 + caller_function = "unknown" + bytes_req = $size + bytes_alloc = "unknown" + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $return +} + +/** + * probe vm.kmem_cache_alloc - Fires when \ + * kmem_cache_alloc is requested. + * @call_site: Address of the function calling this kmemory function. + * @caller_function: Name of the caller function. + * @bytes_req: Requested Bytes + * @bytes_alloc: Allocated Bytes + * @gfp_flags: type of kmemory to allocate + * @gfp_flag_name: Type of kmemory to allocate(in string format) + * @ptr: Pointer to the kmemory allocated + */ + +probe vm.kmem_cache_alloc = __vm.kmem_cache_alloc.tp !, + __vm.kmem_cache_alloc.kp +{} + +probe __vm.kmalloc_node.tp = kernel.trace("kmalloc_node")? { + name = "kmalloc_node" + call_site = $call_site + caller_function = symname(call_site) + bytes_req = $bytes_req + bytes_alloc = $bytes_alloc + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $ptr +} + +probe __vm.kmalloc_node.kp = kernel.function("kmalloc_node").return? { + name = "kmalloc_node" + call_site = 0 + caller_function = "unknown" + bytes_req = $size + bytes_alloc = "unknown" + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $return +} + +/** + * probe vm.kmalloc_node - Fires when kmalloc_node is requested. + * @call_site: Address of the function caling this kmemory function. + * @caller_function: Name of the caller function. + * @bytes_req: Requested Bytes + * @bytes_alloc: Allocated Bytes + * @gfp_flags: type of kmemory to allocate + * @gfp_flag_name: Type of kmemory to allocate(in string format) + * @ptr: Pointer to the kmemory allocated + */ +probe vm.kmalloc_node = __vm.kmalloc_node.tp !, + __vm.kmalloc_node.kp +{} + +probe __vm.kmem_cache_alloc_node.tp = kernel.trace("kmem_cache_alloc_node")? { + name = "kmem_cache_alloc_node" + call_site = $call_site + caller_function = symname(call_site) + bytes_req = $bytes_req + bytes_alloc = $bytes_alloc + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $ptr +} + +probe __vm.kmem_cache_alloc_node.kp = kernel.function("kmem_cache_alloc_node").return? { + name = "kmem_cache_alloc_node" + call_site = 0 + caller_function = "unknown" + bytes_req = $size + bytes_alloc = "unknown" + gfp_flags = $gfp_flags + gfp_flag_name = __gfp_flag_str($gfp_flags) + ptr = $return +} + +/** + * probe vm.kmem_cache_alloc_node - Fires when \ + * kmem_cache_alloc_node is requested. + * @call_site: Address of the function calling this kmemory function. + * @caller_function: Name of the caller function. + * @bytes_req: Requested Bytes + * @bytes_alloc: Allocated Bytes + * @gfp_flags: type of kmemory to allocate + * @gfp_flag_name: Type of kmemory to allocate(in string format) + * @ptr: Pointer to the kmemory allocated + */ +probe vm.kmem_cache_alloc_node = __vm.kmem_cache_alloc_node.tp !, + __vm.kmem_cache_alloc_node.kp +{} + + +probe __vm.kfree.tp = kernel.trace("kfree") { + name = "kfree" + call_site = $call_site + caller_function = symname(call_site) + ptr = $ptr +} + +probe __vm.kfree.kp = kernel.function("kfree").return { + name = "kfree" + call_site = 0 + caller_function = "unknown" + ptr = $return +} + +/** + * probe vm.kfree - Fires when kfree is requested. + * @call_site: Address of the function calling this kmemory function. + * @caller_function: Name of the caller function. + * @ptr: Pointer to the kmemory allocated which is returned by kmalloc + */ +probe vm.kfree = __vm.kfree.tp !, + __vm.kfree.kp +{} + +probe __vm.kmem_cache_free.tp = kernel.trace("kmem_cache_free") { + name = "kmem_cache_free" + call_site = $call_site + caller_function = symname(call_site) + ptr = $ptr +} +probe __vm.kmem_cache_free.kp = kernel.function("kmem_cache_free").return { + name = "kmem_cache_free" + call_site = 0 + caller_function = "unknown" + ptr = $return +} +/** + * probe vm.kmem_cache_free - Fires when \ + * kmem_cache_free is requested. + * @call_site: Address of the function calling this kmemory function. + * @caller_function: Name of the caller function. + * @ptr: Pointer to the kmemory allocated which is returned by kmem_cache + */ +probe vm.kmem_cache_free = __vm.kmem_cache_free.tp !, + __vm.kmem_cache_free.kp +{} diff -rupaN a/testsuite/buildok/vm.tracepoints.stp b/testsuite/buildok/vm.tracepoints.stp --- a/testsuite/buildok/vm.tracepoints.stp 1969-12-31 19:00:00.000000000 -0500 +++ b/testsuite/buildok/vm.tracepoints.stp 2009-11-25 04:05:23.000000000 -0500 @@ -0,0 +1,31 @@ +#! stap -up4 + +probe vm.kfree { + println(name) + printf("%-15s %-15p %-15s %-15p \n", execname(), call_site, caller_function, ptr) +} + +probe vm.kmalloc { + println(name) + printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) +} + +probe vm.kmem_cache_alloc { + println(name) + printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) +} + +probe vm.kmalloc_node { + println(name) + printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) +} + +probe vm.kmem_cache_alloc_node { + println(name) + printf("%-15s %-15p %-15s %-15p %-15d %-15d %-15d %-15s \n", execname(), call_site, caller_function, ptr, bytes_req, bytes_alloc, gfp_flags, gfp_flag_name) +} + +probe vm.kmem_cache_free { + println(name) + printf("%-15s %-15p %-15s %-15p \n", execname(), call_site, caller_function, ptr) +} diff -rupaN a/testsuite/systemtap.examples/memory/vm.tracepoints.meta b/testsuite/systemtap.examples/memory/vm.tracepoints.meta --- a/testsuite/systemtap.examples/memory/vm.tracepoints.meta 1969-12-31 19:00:00.000000000 -0500 +++ b/testsuite/systemtap.examples/memory/vm.tracepoints.meta 2009-11-25 03:58:25.000000000 -0500 @@ -0,0 +1,13 @@ +title: Collect slab allocation statistics +name: vm.tracepoints.stp +version: 1.0 +author: Rajasekhar +keywords: memory slab allocator +subsystem: memory +status: production +exit: user-controlled +output: sorted-list +scope: system-wide +description: The script will probe all memory slab/slub allocations and collects information about the size of the object (bytes requested) and user-space process in execution. When run over a period of time, it helps to correlate kernel-space memory consumption owing to user-space processes. +test_check: stap -p4 vm.tracepoints.stp +test_installcheck: stap vm.tracepoints.stp -c "sleep 10" diff -rupaN a/testsuite/systemtap.examples/memory/vm.tracepoints.stp b/testsuite/systemtap.examples/memory/vm.tracepoints.stp --- a/testsuite/systemtap.examples/memory/vm.tracepoints.stp 1969-12-31 19:00:00.000000000 -0500 +++ b/testsuite/systemtap.examples/memory/vm.tracepoints.stp 2009-11-25 04:06:21.000000000 -0500 @@ -0,0 +1,18 @@ +global slabs + +probe vm.kmem_cache_alloc { + slabs [execname(), bytes_req]++ +} + +probe timer.ms(10000) +{ + dummy = ""; + foreach ([name, bytes] in slabs) { + if (dummy != name) + printf("\nProcess:%s\n", name); + printf("Slab_size:%d\tCount:%d\n", bytes, slabs[name, bytes]); + dummy = name; + } + delete slabs + printf("\n-------------------------------------------------------\n\n") +} Thanks -- Rajasekhar Duddu (rajduddu@linux.vnet.ibm.com), Linux on System z - CSVT, IBM LTC, Bangalore.