05.10.2017 Views

dtrace_scripts

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

Last modified 5 months ago<br />

Dtrace references<br />

Intro to Dtrace. https://wikis.oracle.com/display/DTrace/Introduction<br />

Overview of different type of Dtrace script variables.<br />

http://<strong>dtrace</strong>.org/blogs/brendan/2011/11/25/<strong>dtrace</strong>­variable­types/<br />

Dtrace cheatsheets.<br />

http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_Cheatsheets_Checklists<br />

Dtrace tunables (e.g. pragma to increase memory allowed for <strong>dtrace</strong>).<br />

https://wikis.oracle.com/display/DTrace/Options+and+Tunables<br />

Checking return value of a function<br />

<strong>dtrace</strong> ­n 'fbt:zfs:arc_reclaim_needed:return{ printf("%i\n",arg1); }'<br />

<strong>dtrace</strong> ­n 'fbt:zfs:arc_evict_needed:return{ printf("%i\n",arg1); }'<br />

Tracing specific arcstats field<br />

<strong>dtrace</strong> ­n 'BEGIN{ trace(`arc_stats.arcstat_l2_size.value.ui64); }'<br />

<strong>dtrace</strong> ­n 'BEGIN{ printf("l2_write_bytes=%llu\n", (unsigned long long)`arc_stats.arc<br />

<strong>dtrace</strong> ­qn 'fbt:zfs:arcstat_l2_size_incr:return<br />

{<br />

printf("\nl2_size=%llu\n", (unsigned long long)`arc_stats.arcstat_l2_size.value.u<br />

printf("l2_write_bytes=%llu\n", (unsigned long long)`arc_stats.arcstat_l2_write_b<br />

stack();<br />

printf("\n");<br />

}<br />

'<br />

Counting and checking where a function is called from<br />

<strong>dtrace</strong> ­qn '<br />

fbt:zfs:arc_buf_destroy:entry{ @count_stack[stack(), arg1, arg2] = count(); j++; }<br />

profile:::tick­1sec{ i++; }<br />

profile:::tick­1sec/i==10/{ printf("sample collection total time %i sec, total_cnt=%<br />

Checking a function's latency<br />

<strong>dtrace</strong> ­n '<br />

profile:::tick­1sec{ i++; }<br />

profile:::tick­1sec/i==10/{ exit(0); }<br />

arc_buf_add_ref:entry { self­>s = timestamp; }<br />

arc_buf_add_ref:return /self­>s/ { @["ns"] = quantize(timestamp ­ self­>s); self­>s<br />

Count next level function calls and time taken within function<br />

Note that when calculating time spent in a function, we are excluding the time spent in nextlevel<br />

function calls.<br />

<strong>dtrace</strong> ­q ­n '<br />

BEGIN<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 1/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

{<br />

}<br />

i = 0;<br />

profile:::tick­1sec{ i++; printf("trace time=%i sec\n", i); }<br />

fbt:zfs:spa_unload:entry<br />

{<br />

self­>entered = 1;<br />

}<br />

fbt:zfs::entry<br />

/ self­>entered /<br />

{<br />

self­>ts[stackdepth]=timestamp;<br />

self­>time_in_depth[stackdepth + 1] = 0;<br />

}<br />

fbt:zfs::return<br />

/ self­>entered && self­>ts[stackdepth] /<br />

{<br />

this­>time_delta = timestamp ­ self­>ts[stackdepth];<br />

self­>time_in_depth[stackdepth] += this­>time_delta;<br />

this­>base_time = this­>time_delta ­ self­>time_in_depth[stackdepth + 1];<br />

@call_count[execname, probefunc] = count();<br />

@call_time[execname, probefunc] = sum( this­>base_time );<br />

}<br />

self­>time_in_depth[stackdepth + 1] = 0;<br />

self­>ts[stackdepth] = 0;<br />

fbt:zfs:spa_unload:return<br />

{<br />

self­>entered = 0;<br />

self­>time_in_depth[stackdepth] = 0;<br />

printf("\n");<br />

printf("Function calls as a result of calling %s().\n", probefunc );<br />

printf("Count of function calls.\n");<br />

printa(@call_count);<br />

printf("\n");<br />

printf("Sum of all time spent within the same function, but excluding\n" );<br />

printf("time taken within next level of function calls. (In nanosec).\n" );<br />

printa(@call_time);<br />

}<br />

exit(0);<br />

END<br />

{<br />

}'<br />

Combination of code flow tracking and counting next­level function calls<br />

If max_stack_depth is set too high, <strong>dtrace</strong> will try to trace many "enter" and "return" probes<br />

and starts dropping.<br />

In the below, it is set to trace "spa_unload".<br />

In this script, we generate our own indent instead of using <strong>dtrace</strong> ­F option to show indentation<br />

of different stack depth, since the <strong>dtrace</strong> auto indent seems to get messed up if "return" probe<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 2/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

is dropped.<br />

The base_time field is time spent in a function excluding the time spent in next­level function<br />

calls.<br />

We use pragma D here to increase the <strong>dtrace</strong> dynamic variable usage size to 256MB, else <strong>dtrace</strong><br />

will start dropping dynamic variables when there is not enough memory in the pool.<br />

#!/usr/sbin/<strong>dtrace</strong> ­s<br />

#pragma D option dynvarsize=256m<br />

#pragma D option quiet<br />

BEGIN<br />

{<br />

i = 0;<br />

max_stack_depth = 4;<br />

}<br />

profile:::tick­1sec{ i++; printf("trace time=%i sec\n", i); }<br />

fbt:zfs:spa_unload:entry<br />

{<br />

printf( "\n execname=%s probefunc=%s (cpu=%i pid=%i tid=%i depth=%i)\n",<br />

execname, probefunc,<br />

cpu, pid, tid, stackdepth );<br />

self­>base_depth = stackdepth;<br />

self­>my_indent[stackdepth] = " ";<br />

self­>entered = 1;<br />

}<br />

fbt:zfs::entry<br />

/ self­>entered && (stackdepth ­ self­>base_depth < max_stack_depth) && self­>my_ind<br />

{<br />

self­>my_indent[stackdepth + 1] = strjoin( self­>my_indent[stackdepth], " " );<br />

}<br />

fbt:zfs::entry<br />

/ self­>entered /<br />

{<br />

self­>ts[stackdepth] = timestamp;<br />

self­>time_in_depth[stackdepth + 1] = 0;<br />

}<br />

fbt:zfs::entry<br />

/ self­>entered && (stackdepth ­ self­>base_depth < max_stack_depth) /<br />

{<br />

printf("cpu=%i pid=%i tid=%i depth=%i, %s ­> %­30s\n",<br />

cpu, pid, tid, stackdepth, self­>my_indent[stackdepth], probefunc );<br />

}<br />

fbt:zfs::return<br />

/ self­>entered && self­>ts[stackdepth] /<br />

{<br />

self­>time_delta = timestamp ­ self­>ts[stackdepth];<br />

self­>time_in_depth[stackdepth] += self­>time_delta;<br />

self­>base_time = self­>time_delta ­ self­>time_in_depth[stackdepth + 1];<br />

}<br />

@call_count[execname, probefunc] = count();<br />

@call_time[execname, probefunc] = sum( self­>base_time );<br />

fbt:zfs::return<br />

/ self­>entered && (stackdepth ­ self­>base_depth < max_stack_depth) && self­>ts[sta<br />

{<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 3/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

printf("cpu=%i pid=%i tid=%i depth=%i, %s my_indent[stackdepth],<br />

probefunc, self­>time_delta, self­>base_time );<br />

fbt:zfs::return<br />

/ self­>entered && self­>ts[stackdepth] /<br />

{<br />

self­>my_indent[stackdepth + 1] = 0;<br />

self­>time_in_depth[stackdepth + 1] = 0;<br />

self­>ts[stackdepth] = 0;<br />

self­>time_delta = 0;<br />

self­>base_time = 0;<br />

}<br />

fbt:zfs:spa_unload:return<br />

{<br />

self­>entered = 0;<br />

self­>base_depth = 0;<br />

self­>my_indent[stackdepth] = 0;<br />

}<br />

END{<br />

printf("\n");<br />

printf("Count of function calls.\n");<br />

printa(@call_count);<br />

printf("\n");<br />

printf("Sum of all time spent within the same function, but excluding\n" );<br />

printf("time taken within next level of function calls. (In nanosec).\n" );<br />

printa(@call_time);<br />

}<br />

printf("\n\n");<br />

Below are example output, when we replace the "spa_unload" in the above script to<br />

"arc_buf_destroy". (There are two places where the function name have to be replaced).<br />

...<br />

...<br />

...<br />

execname=svc.configd probefunc=arc_buf_destroy (cpu=0 pid=11 tid=27 depth=11)<br />

cpu=0 pid=11 tid=27 depth=11, ­> arc_buf_destroy<br />

cpu=0 pid=11 tid=27 depth=12, ­> arc_cksum_verify<br />

cpu=0 pid=11 tid=27 depth=12, arc_buf_data_free<br />

cpu=0 pid=11 tid=27 depth=13,<br />

­> zio_data_buf_free<br />

cpu=0 pid=11 tid=27 depth=13, zio_data_buf_free<br />

cpu=0 pid=11 tid=27 depth=15,


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

trace time=2 sec<br />

trace time=3 sec<br />

^C<br />

trace time=4 sec<br />

Function calls as a result of calling ().<br />

Count of function calls.<br />

svc.configd<br />

svc.configd<br />

svc.configd<br />

svc.configd<br />

arc_buf_data_free<br />

arc_buf_destroy<br />

arc_cksum_verify<br />

zio_data_buf_free<br />

Sum of all time spent within the same function, but excluding<br />

time taken within next level of function calls. (In nanosec).<br />

svc.configd<br />

svc.configd<br />

svc.configd<br />

svc.configd<br />

zio_data_buf_free<br />

arc_cksum_verify<br />

arc_buf_data_free<br />

arc_buf_destroy<br />

Check return value of arc_evict_needed()<br />

fbt:zfs:arc_evict_needed:entry<br />

{<br />

self­>data_type = arg0;<br />

}<br />

fbt:zfs:arc_evict_needed:return<br />

{<br />

printf("data_type=%i evict_needed() returns %i\n",self­>data_type, arg1);<br />

self­>data_type = 0;<br />

}<br />

Dtrace async unlinked drain handling<br />

#!/usr/sbin/<strong>dtrace</strong> ­s<br />

::zfs_unlinked_drain:entry{<br />

self­>myvfs=arg0;<br />

}<br />

::zfs_unlinked_drain:zfs­unlinked­drain­break{<br />

printf("zfsvfs=%p\n", arg0);<br />

}<br />

::zfs_unlinked_drain:zfs­unlinked­drain­qfull{<br />

printf("zfsvfs=%p task_cnt=%d\n", arg0, arg1);<br />

}<br />

::zfs_unlinked_drain:return/arg1/{<br />

printf("zfsvfs=%p work_done_cnt=%d\n", self­>myvfs, arg1);<br />

self­>myvfs=0;<br />

}<br />

::zfs_znode_unlinked_process:zfs­unlinked­process­reason<br />

{<br />

self­>my_znode = (znode_t *)arg2;<br />

self­>my_vnode = (vnode_t *)self­>my_znode­>z_vnode;<br />

printf("zfsvfs=%p reason=%i zp=%p vp=%p obj_num=%d rele=%i rmnode=%i v_count<br />

arg0, arg1, arg2, self­>my_znode­>z_vnode, arg3, arg4, arg5,<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 5/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

self­>my_vnode­>v_count_dnlc,<br />

self­>my_vnode­>v_count,<br />

self­>my_vnode­>v_path? stringof(self­>my_vnode­>v_path) : "na");<br />

self­>my_znode = 0;<br />

self­>my_vnode = 0;<br />

::zfs_znode_unlinked_process:zfs­unlinked­process­chk­rele<br />

/self­>myvfs/<br />

{<br />

self­>my_znode = (znode_t *)arg2;<br />

printf("zfsvfs=%p zp=%p vp=%p zp_v_count=%d zp_rmnode=%i\n",<br />

self­>myvfs,<br />

arg0, arg1, arg2, arg3);<br />

self­>my_znode = 0;<br />

}<br />

::zfs_rmnode:entry<br />

{<br />

self­>myrmnodezp = (znode_t *)arg0;<br />

self­>myrmnodezptime = timestamp;<br />

self­>myvnode = (vnode_t *)self­>myrmnodezp­>z_vnode;<br />

printf("zfsvfs=%p zp=%p obj_num=%d z_pflags=0x%x vp=%p v_type=%d v_count=%d\<br />

self­>myvfs, arg0,<br />

self­>myrmnodezp­>z_id,<br />

self­>myrmnodezp­>z_pflags,<br />

self­>myvnode,<br />

self­>myvnode­>v_type,<br />

self­>myvnode­>v_count);<br />

}<br />

::zfs_rmnode:return<br />

/self­>myrmnodezptime && ((unsigned long)self­>myvnode­>v_path != 0)/<br />

{<br />

printf("zfsvfs=%p zp=%p obj_num=%d delta=%d nsec vpath=%s\n",<br />

self­>myvfs, self­>myrmnodezp, self­>myrmnodezp­>z_id,<br />

timestamp ­ self­>myrmnodezptime, stringof(self­>myvnode­>v_path));<br />

self­>myrmnodezp = 0;<br />

self­>myrmnodezptime = 0;<br />

self­>myvnode = 0;<br />

}<br />

::zfs_rmnode:return<br />

/self­>myrmnodezptime && ((unsigned long)self­>myvnode­>v_path == 0)/<br />

{<br />

printf("zfsvfs=%p zp=%p obj_num=%d delta=%d nsec vpath=NULL\n",<br />

self­>myvfs, self­>myrmnodezp, self­>myrmnodezp­>z_id,<br />

timestamp ­ self­>myrmnodezptime);<br />

self­>myrmnodezp = 0;<br />

self­>myrmnodezptime = 0;<br />

self­>myvnode = 0;<br />

}<br />

::zfs_zinactive:zfs­zinactive­rmnode{<br />

printf("zfsvfs=%p obj_num=%d\n", arg0, arg1);<br />

}<br />

:::dmu­free­long­range­break<br />

{<br />

printf("dnode=%p\n", arg0);<br />

}<br />

::zfs_unlinked_add:entry{<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 6/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

self­>myunlinkedaddzp = (znode_t *)arg0;<br />

self­>myunlinkedaddvp = (vnode_t *)self­>myunlinkedaddzp­>z_vnode;<br />

printf("enter zp=%p, obj_num=%d vp=%p v_count=%d\n",<br />

self­>myunlinkedaddzp, self­>myunlinkedaddzp­>z_id,<br />

self­>myunlinkedaddvp, self­>myunlinkedaddvp­>v_count);<br />

::zfs_unlinked_add:return/(unsigned long)(self­>myunlinkedaddvp­>v_path) != 0/<br />

{<br />

printf("enter zp=%p, obj_num=%d vp=%p v_count=%d path=%s\n",<br />

self­>myunlinkedaddzp, self­>myunlinkedaddzp­>z_id,<br />

self­>myunlinkedaddvp,<br />

self­>myunlinkedaddvp­>v_count,<br />

stringof(self­>myunlinkedaddvp­>v_path));<br />

stack();<br />

}<br />

::zfs_unlinked_add:return/(unsigned long)(self­>myunlinkedaddvp­>v_path) == 0/<br />

{<br />

printf("enter zp=%p, obj_num=%d vp=%p v_count=%d path=NULL\n",<br />

self­>myunlinkedaddzp, self­>myunlinkedaddzp­>z_id,<br />

self­>myunlinkedaddvp,<br />

self­>myunlinkedaddvp­>v_count);<br />

stack();<br />

}<br />

::taskq_remove_task:entry{<br />

printf("zfsvfs=%p\n", arg2);<br />

}<br />

::taskq_remove_task:return{<br />

printf("remove_cnt=%d\n", arg1);<br />

}<br />

::zfs_unlinked_task_remove_filter:entry{<br />

self­>myremovezp = (znode_t *)arg1;<br />

printf("zfsvfs=%p obj_num=%d\n", arg0, self­>myremovezp­>z_id);<br />

self­>myremovezp = 0;<br />

}<br />

:::zfs­unlinked­task­remove­chk<br />

{<br />

printf("zfsvfs=%p zp=%p obj_num=%d\n", arg0, arg1, arg2);<br />

}<br />

::zfs_unlinked_task_remove_filter:return{<br />

printf("remove_cnt=%d\n", arg1);<br />

}<br />

spa_sync() side free related work<br />

<strong>dtrace</strong> ­n '<br />

::spa_sync:entry{<br />

self­>spa = (spa_t *)arg0;<br />

}<br />

::dnode_sync_free_range:entry/self­>spa/{<br />

printf("spa=%s dnode=%p dn_type=%i beginning blkid=%d num_blocks=%d (0x%x)\n",<br />

stringof(self­>spa­>spa_name),<br />

arg0,<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 7/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

((dnode_t *)arg0)­>dn_type,<br />

arg1, arg2, arg2);<br />

::free_blocks:return{<br />

printf("spa=%s freed_blocks=%d\n",<br />

stringof(self­>spa­>spa_name), arg1);<br />

}<br />

::spa_sync:return{<br />

self­>spa = 0;<br />

}'<br />

Check zfsvfs teardown sequence<br />

<strong>dtrace</strong> ­n '<br />

::zfs_umount:entry{<br />

self­>umounttime = timestamp;<br />

printf("enter\n");<br />

}<br />

::zfs_umount:return{<br />

printf("return, delta=%d\n", timestamp ­ self­>umounttime);<br />

self­>umounttime = 0;<br />

}<br />

::zfsvfs_teardown:entry<br />

{<br />

self­>myvfs=arg0;<br />

printf("zfsvfs=%p\n", arg0);<br />

}<br />

::zfsvfs_teardown:return<br />

{<br />

printf("zfsvfs=%p\n", self­>myvfs);<br />

self­>myvfs=0;<br />

}<br />

::zfs_unlinked_drain_vfs_remove:entry<br />

/self­>myvfs/<br />

{<br />

printf("zfsvfs=%p\n", self­>myvfs);<br />

}<br />

::zfs_unlinked_drain_vfs_remove:return<br />

/self­>myvfs/<br />

{<br />

printf("zfsvfs=%p\n", self­>myvfs);<br />

}<br />

::zfs_unlinked_drain_task_wait:entry<br />

/self­>myvfs/<br />

{<br />

printf("zfsvfs=%p\n", self­>myvfs);<br />

}<br />

::zfs_unlinked_drain_task_wait:return<br />

/self­>myvfs/<br />

{<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 8/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

'<br />

printf("zfsvfs=%p\n", self­>myvfs);<br />

Check async delete workers thread dmu_tx_hold_free() throttling<br />

<strong>dtrace</strong> ­n '<br />

BEGIN<br />

{<br />

MB=1024 * 1024;<br />

KB=1024;<br />

MIL=1000000<br />

}<br />

::dmu_free_long_range_impl:entry<br />

{<br />

self­>spa_name=stringof(((objset_t *)arg0)­>os_spa­>spa_name);<br />

self­>start0 = timestamp;<br />

printf("spa=%s offset=%d length=%d\n",<br />

self­>spa_name, arg2, arg3);<br />

}<br />

::dmu_tx_hold_free:entry/self­>start0/<br />

{<br />

printf("spa=%s start=%d len=%d\n", self­>spa_name, arg2, arg3);<br />

}<br />

::dmu_tx_count_free:dmu­tx­count­free/self­>start0/<br />

{<br />

printf("spa=%s txg=%d dn_nlevels=%d dn_maxblkdid=%d off=%d len=%d\n",<br />

self­>spa_name,<br />

arg2, arg3, arg4, arg5, arg6);<br />

}<br />

::dmu_tx_hold_free:dmu­tx­hold­free/self­>start0/<br />

{<br />

printf("spa=%s txh_type=%i towrite=%d tofree=%d tooverwrite=%d tounref=%d memtoh<br />

self­>spa_name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);<br />

}<br />

::dmu_tx_assign:entry/self­>start0/<br />

{<br />

self­>start1 = timestamp;<br />

printf("spa=%s start\n", self­>spa_name);<br />

}<br />

::dmu_tx_try_assign:entry/self­>start0/<br />

{<br />

self­>start2 = timestamp;<br />

printf("spa=%s start\n", self­>spa_name);<br />

}<br />

::dmu_tx_try_assign:return/self­>start0/<br />

{<br />

printf("spa=%s end return=%i time_taken=%d ns\n",<br />

self­>spa_name, arg1,<br />

(timestamp ­ self­>start2));<br />

}<br />

::dmu_tx_wait:entry/self­>start0/<br />

{<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 9/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

self­>start3 = timestamp;<br />

printf("spa=%s start\n", self­>spa_name);<br />

::dmu_tx_wait:return/self­>start0/<br />

{<br />

printf("spa=%s end return=%i time_taken=%d ns\n",<br />

self­>spa_name, arg1,<br />

(timestamp ­ self­>start3));<br />

}<br />

::dmu_tx_assign:return/self­>start0/<br />

{<br />

printf("spa=%s end return=%i time_taken=%d ns\n",<br />

self­>spa_name, arg1,<br />

(timestamp ­ self­>start1));<br />

}<br />

::dnode_clear_range:entry/self­>start0/<br />

{<br />

self­>spa_name = stringof(((dmu_tx_t *)arg3)­>tx_pool­>dp_spa­>spa_name);<br />

printf("spa=%s txg=%d dn=%p blkid=%d nblks=%d\n",<br />

self­>spa_name,<br />

((dmu_tx_t *)arg3)­>tx_txg,<br />

arg0, arg1, arg2);<br />

}<br />

::dmu_free_long_range_impl:return/self­>start0/<br />

{<br />

printf("spa=%s return=%i time_taken=%d ms\n",<br />

self­>spa_name,<br />

arg1, (timestamp ­ self­>start0)/MIL);<br />

self­>spa_name = 0;<br />

self­>start0 = 0;<br />

}<br />

'<br />

Trace dsl_scan_sync() bp traverse pause checking code<br />

<strong>dtrace</strong> ­n '<br />

::dsl_scan_sync:entry{<br />

self­>time0 = timestamp;<br />

}<br />

::dsl_scan_check_pause:entry/self­>time0/{<br />

self­>curr = timestamp;<br />

self­>scn = (dsl_scan_t *)arg0;<br />

printf("scan_start=%9d elapsed=%9d delta=%9d ns\n",<br />

self­>scn­>scn_sync_start_time,<br />

self­>curr ­ self­>scn­>scn_sync_start_time,<br />

self­>curr ­ self­>time0);<br />

self­>time0 = self­>curr;<br />

}<br />

::dsl_scan_check_waiting:entry{<br />

self­>elapsed = arg1;<br />

}<br />

::dsl_scan_check_waiting:return{<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 10/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

printf("elapsed=%9d ns, return=%i\n",<br />

self­>elapsed, arg1);<br />

::dsl_scan_check_pause:return/self­>time0/{<br />

printf("return=%d\n", arg1);<br />

}<br />

'<br />

Trace txg open, quiesce, sync group dirty data<br />

<strong>dtrace</strong> ­qn '<br />

::txg_quiesce:txg­quiescing{<br />

MB=1024 *1024;<br />

printf("spa=%s quiese txg=%9d dirty=%4d\n",<br />

stringof(((dsl_pool_t *)arg0)­>dp_spa­>spa_name),<br />

arg1,<br />

arg2/MB);<br />

}<br />

::txg_sync_thread:txg­syncing{<br />

MB=1024 *1024;<br />

printf("spa=%s syncing txg=%9d dirty=%4d\n",<br />

stringof(((dsl_pool_t *)arg0)­>dp_spa­>spa_name),<br />

arg1,<br />

arg2/MB);<br />

}<br />

::txg_sync_thread:txg­opened­dirty{<br />

MB=1024 *1024;<br />

printf("spa=%s opened txg=%9d dirty=%4d\n",<br />

stringof(((spa_t *)arg0)­>spa_name),<br />

arg1,<br />

arg2/MB);<br />

}'<br />

Trace zfs_zget()<br />

<strong>dtrace</strong> ­n '<br />

::zfs_zget:entry{<br />

self­>obj = arg1;<br />

self­>zpp = (znode_t **)arg2;<br />

}<br />

::zfs_zget:return/self­>obj/{<br />

self­>vnode = (vnode_t *)(*(self­>zpp))­>z_vnode;<br />

}'<br />

printf("obj=%d path=%s\n",<br />

self­>obj,<br />

stringof(self­>vnode­>v_path));<br />

spa_sync(), iterate­to­convergence section of the code, breakdown of time taken<br />

<strong>dtrace</strong> ­n '<br />

BEGIN{<br />

MIL=1000000;<br />

}<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 11/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

::spa_sync:entry{<br />

self­>txg = arg1;<br />

self­>spa = (spa_t *)arg0;<br />

self­>spa_name = stringof(((spa_t *)arg0)­>spa_name);<br />

}<br />

::spa_sync_config_object:entry/self­>txg/{<br />

self­>time0 = timestamp;<br />

}<br />

::spa_sync_config_object:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time0)/MIL);<br />

}<br />

::spa_sync_aux_dev:entry/self­>txg/{<br />

self­>time1 = timestamp;<br />

}<br />

::spa_sync_aux_dev:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time1)/MIL);<br />

}<br />

::spa_errlog_sync:entry/self­>txg/{<br />

self­>time2 = timestamp;<br />

}<br />

::spa_errlog_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time2)/MIL);<br />

}<br />

::dsl_pool_sync:entry/self­>txg/{<br />

self­>time3 = timestamp;<br />

}<br />

::dsl_pool_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time3)/MIL);<br />

}<br />

::spa_sync_frees:entry/self­>txg/{<br />

self­>time4 = timestamp;<br />

}<br />

::spa_sync_frees:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time4)/MIL);<br />

}<br />

::bplist_iterate:entry/self­>txg/{<br />

self­>time5 = timestamp;<br />

}<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 12/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

::bplist_iterate:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time5)/MIL);<br />

}<br />

::ddt_sync:entry/self­>txg/{<br />

self­>time6 = timestamp;<br />

}<br />

::ddt_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time6)/MIL);<br />

}<br />

::dsl_scan_sync:entry/self­>txg/{<br />

self­>time7 = timestamp;<br />

}<br />

::dsl_scan_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time7)/MIL);<br />

}<br />

::vdev_sync:entry/self­>txg/{<br />

self­>time8 = timestamp;<br />

}<br />

::vdev_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time8)/MIL);<br />

}<br />

::spa_sync_upgrades:entry/self­>txg/{<br />

self­>time9 = timestamp;<br />

}<br />

::spa_sync_upgrades:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time9)/MIL);<br />

}<br />

::dmu_objset_is_dirty:entry/self­>txg/{<br />

self­>time10 = timestamp;<br />

}<br />

::dmu_objset_is_dirty:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

(timestamp ­ self­>time10)/MIL);<br />

}<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 13/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

::spa_sync:return{<br />

self­>txg = 0;<br />

self­>spa_name = 0;<br />

}'<br />

dsl_pool_sync()<br />

<strong>dtrace</strong> ­n '<br />

BEGIN{<br />

MIL=1000000;<br />

}<br />

::spa_sync:entry{<br />

self­>txg = arg1;<br />

self­>spa = (spa_t *)arg0;<br />

self­>spa_name = stringof(((spa_t *)arg0)­>spa_name);<br />

}<br />

::dsl_pool_sync:entry/self­>txg/{<br />

self­>time3 = timestamp;<br />

}<br />

::dsl_dataset_sync:entry/self­>txg/{<br />

self­>ds_time1 = timestamp;<br />

self­>ds = (dsl_dataset_t *)arg0;<br />

}<br />

::dsl_dataset_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d ds=%p delta=%d ms\n",<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass,<br />

self­>ds,<br />

(timestamp ­ self­>ds_time1)/MIL);<br />

}<br />

::dsl_pool_sync:pool_sync­1setup/self­>txg/<br />

{<br />

self­>ds_sync_zio_delta = timestamp;<br />

}<br />

::dsl_pool_sync:pool_sync­2rootzio/self­>txg/<br />

{<br />

self­>ds_sync_zio_delta = timestamp ­ self­>ds_sync_zio_delta;<br />

}<br />

::dsl_pool_sync_mos:entry/self­>txg/<br />

{<br />

self­>mostime = timestamp;<br />

}<br />

::dsl_pool_sync_mos:return/self­>txg/<br />

{<br />

self­>mostime = timestamp ­ self­>mostime;<br />

}<br />

::dsl_pool_sync:return/self­>txg/{<br />

printf("spa=%s txg=%d pass=%d ds_sync_zio_wait_time=%d ms mos_sync=%d ms delta=%d<br />

self­>spa_name, self­>txg, self­>spa­>spa_sync_pass, self­>mostime,<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 14/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

self­>ds_sync_zio_delta/MIL,<br />

(timestamp ­ self­>time3)/MIL);<br />

::spa_sync:return{<br />

self­>txg = 0;<br />

self­>spa_name = 0;<br />

}<br />

'<br />

dsl_scan free and scrub traversal time limit<br />

<strong>dtrace</strong> ­n '<br />

::dsl_scan_sync:entry{<br />

self­>time0 = timestamp;<br />

self­>dp = (dsl_pool_t *)arg0;<br />

self­>spa = (spa_t *)self­>dp­>dp_spa;<br />

self­>spa_name = stringof( self­>spa­>spa_name );<br />

}<br />

::dsl_scan_check_pause:entry/self­>time0/{<br />

self­>curr = timestamp;<br />

self­>scn = (dsl_scan_t *)arg0;<br />

}<br />

::dsl_scan_check_pause:return/self­>time0 && arg1/{<br />

printf("spa=%s scan_start=%9d elapsed=%9d ns return=%d\n",<br />

self­>spa_name,<br />

self­>scn­>scn_sync_start_time,<br />

self­>curr ­ self­>scn­>scn_sync_start_time,<br />

arg1);<br />

}<br />

::dsl_scan_check_waiting:entry/self­>time0/{<br />

self­>scrub_elapsed=arg1;<br />

}<br />

::dsl_scan_check_waiting:return/arg1 == 2/<br />

{<br />

printf("elapsed=%d ns return=%d\n", self­>scrub_elapsed, arg1);<br />

}<br />

::dsl_scan_sync:return{<br />

self­>time0=0;<br />

}<br />

'<br />

<strong>dtrace</strong> ­n '<br />

::dsl_scan_sync:entry{<br />

self­>time0 = timestamp;<br />

self­>dp = (dsl_pool_t *)arg0;<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 15/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

self­>spa = (spa_t *)self­>dp­>dp_spa;<br />

self­>spa_name = stringof( self­>spa­>spa_name );<br />

::dsl_scan_free_should_pause:entry/self­>time0/{<br />

self­>curr = timestamp;<br />

self­>scn = (dsl_scan_t *)arg0;<br />

}<br />

::dsl_scan_free_should_pause:return/self­>time0 && arg1/{<br />

printf("spa=%s scan_start=%9d elapsed=%9d ns return=%d\n",<br />

self­>spa_name,<br />

self­>scn­>scn_sync_start_time,<br />

self­>curr ­ self­>scn­>scn_sync_start_time,<br />

arg1);<br />

}<br />

::dsl_scan_check_waiting:entry/self­>time0/{<br />

self­>scrub_elapsed=arg1;<br />

}<br />

::dsl_scan_check_waiting:return/arg1 == 2/<br />

{<br />

printf("elapsed=%d ns return=%d\n", self­>scrub_elapsed, arg1);<br />

}<br />

::dsl_scan_sync:return{<br />

self­>time0=0;<br />

}<br />

'<br />

Tracking NFS op time taken<br />

#!/usr/sbin/<strong>dtrace</strong> ­qs<br />

#pragma D option dynvarsize=256m<br />

profile:::tick­1sec<br />

{<br />

mytime++;<br />

printf("timestamp=%12d sec elapsed, %Y\n", mytime, walltimestamp);<br />

}<br />

nfssrv:common_dispatch:entry{<br />

}<br />

self­>opstart = timestamp;<br />

self­>req = arg0;<br />

self­>opdelta = 0;<br />

self­>op = ­1;<br />

:::rfs4­compound­argop/self­>req && (arg0 == 0)/{<br />

self­>opstart = timestamp;<br />

self­>idx = arg0;<br />

self­>op = arg1;<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 16/17


1/28/2016 enyew/<strong>dtrace</strong>_<strong>scripts</strong> – Zebi<br />

}<br />

:::rfs4­compound­argop/self­>req && (arg0 > 0)/{<br />

self­>prev_delta = (timestamp ­ self­>opstart)/1000000;<br />

self­>prev_idx = self­>idx;<br />

self­>prev_op = self­>op;<br />

printf("END nfs req=%p i=%d op=%d delta=%d ms\n",<br />

self­>req,<br />

self­>prev_idx,<br />

self­>prev_op,<br />

self­>prev_delta<br />

);<br />

}<br />

self­>opstart = timestamp;<br />

self­>idx = arg0;<br />

self­>op = arg1;<br />

nfssrv:common_dispatch:return/self­>req/{<br />

self­>prev_delta = (timestamp ­ self­>opstart)/1000000;<br />

self­>prev_idx = self­>idx;<br />

self­>prev_op = self­>op;<br />

printf("END nfs req=%p i=%d op=%d delta=%d ms\n",<br />

self­>req,<br />

self­>prev_idx,<br />

self­>prev_op,<br />

self­>prev_delta<br />

);<br />

}<br />

self­>prev_delta = 0;<br />

self­>prev_idx = 0;<br />

self­>prev_op = 0;<br />

self­>op = 0;<br />

self­>idx = 0;<br />

self­>opstart = 0;<br />

self­>req = 0;<br />

https://nimbus.eng.tegile.com/trac/wiki/enyew/<strong>dtrace</strong>_<strong>scripts</strong> 17/17

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!