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>variabletypes/<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:::tick1sec{ i++; }<br />
profile:::tick1sec/i==10/{ printf("sample collection total time %i sec, total_cnt=%<br />
Checking a function's latency<br />
<strong>dtrace</strong> n '<br />
profile:::tick1sec{ i++; }<br />
profile:::tick1sec/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:::tick1sec{ 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 nextlevel 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 nextlevel 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:::tick1sec{ 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:zfsunlinkeddrainbreak{<br />
printf("zfsvfs=%p\n", arg0);<br />
}<br />
::zfs_unlinked_drain:zfsunlinkeddrainqfull{<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:zfsunlinkedprocessreason<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:zfsunlinkedprocesschkrele<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:zfszinactivermnode{<br />
printf("zfsvfs=%p obj_num=%d\n", arg0, arg1);<br />
}<br />
:::dmufreelongrangebreak<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 />
:::zfsunlinkedtaskremovechk<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:dmutxcountfree/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:dmutxholdfree/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:txgquiescing{<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:txgsyncing{<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:txgopeneddirty{<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(), iteratetoconvergence 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_sync1setup/self>txg/<br />
{<br />
self>ds_sync_zio_delta = timestamp;<br />
}<br />
::dsl_pool_sync:pool_sync2rootzio/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:::tick1sec<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 />
:::rfs4compoundargop/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 />
:::rfs4compoundargop/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