Sang-Thong.Chang
2009-May-22  09:40 UTC
[dtrace-discuss] Anomaly in Dtrace copyin() observed through DTT''s zvmstat
Hi all,
Not sure if this is an anomaly in dtrace''s copyin() or just
the way that the hacks in DTT''s zvmstat created this observation.
I am seeing this anomaly where copyin() from syscall::write:entry/return
probe is getting trailing data from the previous calls.
This can be observed from the zvmstat script bundled in DTT,
running on system where there are zones which the zonenames
are of various string length.
For example, on a system with the following zones configured:
bash-3.00# zoneadm list
global
bravo
alpha88
alps
apple
alibaba
allscp
cvsserv
lego1
situationroom
cookbook
fire99
pooh
prodapps
rdrv
redzone
bash-3.00# ./zvmstat
      ZONE   re    mf   fr    sr  epi  epo  epf  api  apo  apf  fpi fpo  fpf
    global   76   324    0     0    0    0    0    0    0    0    0 0    0
    bravol    0     0    0     0    0    0    0    0    0    0    0 0    0
   alpha88    0     0    0     0    0    0    0    0    0    0    0 0    0
   alpsa88    0     0    0     0    0    0    0    0    0    0    0 0    0
   apple88    0     0    0     0    0    0    0    0    0    0    0 0    0
   alibaba    0     0    0     0    0    0    0    0    0    0    0 0    0
   allscpa    0     0    0     0    0    0    0    0    0    0    0 0    0
   cvsserv    0     0    0     0    0    0    0    0    0    0    0 0    0
   lego1rv    0     0    0     0    0    0    0    0    0    0    0 0    0
situationroom    0     0    0     0    0    0    0    0    0    0    0   0    0
cookbooknroom    0     0    0     0    0    0    0    0    0    0    0   0    0
fire99oknroom    0     0    0     0    0    0    0    0    0    0    0   0    0
pooh99oknroom    0     0    0     0    0    0    0    0    0    0    0   0    0
prodappsnroom    0     0    0     0    0    0    0    0    0    0    0   0    0
rdrvappsnroom    0     0    0     0    0    0    0    0    0    0    0   0    0
redzonesnroom    0     0    0     0    0    0    0    0    0    0    0   0    0
Notice that any subsequent zonename string that is shorter
than it''s prev. neighbours will have it''s neighbour trailing
string.
Having suspecting arg2 (length) returned by the
syscall::write:entry, I stripped down zvmstat further,
to print the string length as well. Well, the string
lengths all appeared to be correct.
bash-3.00# ./zv.d
ZONE
----
arg2 - 1 = 6 [global]
arg2 - 1 = 5 [bravol]
arg2 - 1 = 7 [alpha88]
arg2 - 1 = 4 [alpsa88]
arg2 - 1 = 5 [apple88]
arg2 - 1 = 7 [alibaba]
arg2 - 1 = 6 [allscpa]
arg2 - 1 = 7 [cvsserv]
arg2 - 1 = 5 [lego1rv]
arg2 - 1 = 13 [situationroom]
arg2 - 1 = 8 [cookbooknroom]
arg2 - 1 = 6 [fire99oknroom]
arg2 - 1 = 4 [pooh99oknroom]
arg2 - 1 = 8 [prodappsnroom]
arg2 - 1 = 4 [rdrvappsnroom]
arg2 - 1 = 7 [redzonesnroom]
If I add in a print(" \b") as below to trigger additional
syscall::write: probes, I''ve got the correct values.
*BUT* this firing of probe triggered an neccessary cosmetic
issue with an additional printout, not an ideal workaround,
and the observation is still a puzzle to me.
   156   /*
   157    * Scrape zone listing
   158    */
   159   syscall::write:entry
   160   /listing && (execname == "zoneadm") &&
   161   (curthread->t_procp->p_parent->p_ppid == $pid)/
   162   {
   163          printf(" \b");      ### Triggers another probe.
   164          /* read zoneadm output */
   165          zonelist[zonemax] = stringof(copyin(arg1, arg2 - 1));
   166          zone_len[zonemax] = arg2 - 1;
   167          /* increment max number of zones */
   168          zonemax++;
   169   }
bash-3.00# ./zv.d
arg2 - 1 = 6 [global]
arg2 - 1 = 5 [bravo]
arg2 - 1 = 7 [alpha88]
arg2 - 1 = 4 [alps]
arg2 - 1 = 5 [apple]
arg2 - 1 = 7 [alibaba]
arg2 - 1 = 6 [allscp]
arg2 - 1 = 7 [cvsserv]
arg2 - 1 = 5 [lego1]
arg2 - 1 = 13 [situationroom]
arg2 - 1 = 8 [cookbook]
arg2 - 1 = 6 [fire99]
arg2 - 1 = 4 [pooh]
arg2 - 1 = 8 [prodapps]
arg2 - 1 = 4 [rdrv]
arg2 - 1 = 7 [redzone]
ZONE
----
arg2 - 1 = 6 [global]
arg2 - 1 = 5 [bravo]
arg2 - 1 = 7 [alpha88]
arg2 - 1 = 4 [alps]
arg2 - 1 = 5 [apple]
arg2 - 1 = 7 [alibaba]
arg2 - 1 = 6 [allscp]
arg2 - 1 = 7 [cvsserv]
arg2 - 1 = 5 [lego1]
arg2 - 1 = 13 [situationroom]
arg2 - 1 = 8 [cookbook]
arg2 - 1 = 6 [fire99]
arg2 - 1 = 4 [pooh]
arg2 - 1 = 8 [prodapps]
arg2 - 1 = 4 [rdrv]
arg2 - 1 = 7 [redzone]
My ultimate question here is, is this a bug in
Dtrace copyin()/copyinstr() here, or I am missing
something here?
TIA
Regards
ST
-- 
This message posted from opensolaris.org
S.T.Chang
2009-May-23  18:01 UTC
[dtrace-discuss] Anomaly in Dtrace copyin() observed through DTT''s zvmstat
Ok. I have came up with a more simplified demonstration of the issue
at hand. Comments prefixed with "!!!".
!!! Using the following very simple "hello_print" program: 
# cat hello_print.c
/* hello_print.c */
#include <stdio.h>
main()
{
        printf("ss20\n");
	printf("sparcstation\n");
	printf("suni386\n");
	printf("itanium\n");
	printf("austinpower\n");
	printf("u27\n");
	printf("u24\n");
	printf("galaxy\n");
	printf("sunfire240\n");
        printf("v890\n");
	printf("sunfire15000\n");
	printf("x4120\n");
	printf("u\n");
	printf("deadman\n");
	printf("snooping\n");
	printf("0xdeadbeef\n");
	printf("null\n");
	printf("trap0x31\n");
	printf("u10\n");
}
!!! And running the following dtrace script, "c.d" in 
!!! one terminal, and then start up the "hello_print" 
!!! in another terminal.
# cat c.d
#!/usr/sbin/dtrace -qs
BEGIN
{
	namemax = 0;
	namei = 0;
	rolling = 0;
	printf("\n");
	printf("Please run ''hello_print'' in another
terminal.\n");
	printf("-----------------------------------------------\n");
}
syscall::write:entry
/(execname == "hello_print")/
{
	namelist[namemax] = stringof(copyin(arg1, arg2 - 1));
	namelen[namemax] = arg2 - 1;  /* not including terminal NUL */
	namemax++;
}
/* When hello_print exit(), let''s get printing going by
   triggering the write probe */
fbt::exit:entry
/(execname == "hello_print")/
{
	rolling = 1;
	printf(" \b");
}
syscall::write:return
/(execname == "dtrace") && (pid == $pid) &&
 (namei < namemax) /
{
	printf("len = %2.2d [%s]\n", namelen[namei], namelist[namei]);
	namei++;
}
syscall::write:return
/(execname == "dtrace") && (pid == $pid) && (namei
>= namemax) && rolling/
{
	exit(0);
}
END
{
	printf("---------------\n");
}
!!! Below is what I got. Notice that any string that
!!! is 3 characters in length ( well, 4 chars counting
!!! the terminating null) will have the copyin() done
!!! correctly. Anything longer, will inherit it''s neighbour
!!! trailing strings.
# ./hello_print     
ss20
sparcstation
suni386
itanium
austinpower
u27
u24
galaxy
sunfire240
v890
sunfire15000
x4120
u
deadman
snooping
0xdeadbeef
null
trap0x31
u10
# ./c.d             
Please run ''hello_print'' in another terminal.
-----------------------------------------------
len = 04 [ss20]
len = 12 [sparcstation]
len = 07 [suni386ation]
len = 07 [itaniumation]
len = 11 [austinpowern]
len = 03 [u27]
len = 03 [u24]
len = 06 [galaxypowern]
len = 10 [sunfire240rn]
len = 04 [v890ire240rn]
len = 12 [sunfire15000]
len = 05 [x4120re15000]
len = 01 [u]
len = 07 [deadman15000]
len = 08 [snooping5000]
len = 10 [0xdeadbeef00]
len = 04 [nulladbeef00]
len = 08 [trap0x31ef00]
len = 03 [u10]
---------------
!!! I am sure this is not the right(or consistent) behaviour 
!!! here. Or I really have gone off tangent on this?
!!! Appreciate if anyone can shed some light on the 
!!! observation here.
TIA
Regards
S.T.
-- 
This message posted from opensolaris.org
Adam Leventhal
2009-May-23  20:02 UTC
[dtrace-discuss] Anomaly in Dtrace copyin() observed through DTT''s zvmstat
Hi S.T. The memory that''s used to store the string is reused from the previous iteration. If you either null-terminal the string yourself or change the copyin() to include the trailing null your script should work as predicted. Adam On May 23, 2009, at 11:01 AM, S.T.Chang wrote:> Ok. I have came up with a more simplified demonstration of the issue > at hand. Comments prefixed with "!!!". > > > !!! Using the following very simple "hello_print" program: > > > # cat hello_print.c > /* hello_print.c */ > > #include <stdio.h> > > main() > { > printf("ss20\n"); > printf("sparcstation\n"); > printf("suni386\n"); > printf("itanium\n"); > printf("austinpower\n"); > printf("u27\n"); > printf("u24\n"); > printf("galaxy\n"); > printf("sunfire240\n"); > printf("v890\n"); > printf("sunfire15000\n"); > printf("x4120\n"); > printf("u\n"); > printf("deadman\n"); > printf("snooping\n"); > printf("0xdeadbeef\n"); > printf("null\n"); > printf("trap0x31\n"); > printf("u10\n"); > > } > > > !!! And running the following dtrace script, "c.d" in > !!! one terminal, and then start up the "hello_print" > !!! in another terminal. > > > # cat c.d > #!/usr/sbin/dtrace -qs > > > BEGIN > { > namemax = 0; > namei = 0; > rolling = 0; > printf("\n"); > printf("Please run ''hello_print'' in another terminal.\n"); > printf("-----------------------------------------------\n"); > } > > > syscall::write:entry > /(execname == "hello_print")/ > { > namelist[namemax] = stringof(copyin(arg1, arg2 - 1)); > namelen[namemax] = arg2 - 1; /* not including terminal NUL */ > namemax++; > } > > /* When hello_print exit(), let''s get printing going by > triggering the write probe */ > fbt::exit:entry > /(execname == "hello_print")/ > { > rolling = 1; > printf(" \b"); > } > > syscall::write:return > /(execname == "dtrace") && (pid == $pid) && > (namei < namemax) / > { > printf("len = %2.2d [%s]\n", namelen[namei], namelist[namei]); > namei++; > } > > syscall::write:return > /(execname == "dtrace") && (pid == $pid) && (namei >= namemax) && > rolling/ > { > exit(0); > } > > END > { > printf("---------------\n"); > } > > > !!! Below is what I got. Notice that any string that > !!! is 3 characters in length ( well, 4 chars counting > !!! the terminating null) will have the copyin() done > !!! correctly. Anything longer, will inherit it''s neighbour > !!! trailing strings. > > > # ./hello_print > ss20 > sparcstation > suni386 > itanium > austinpower > u27 > u24 > galaxy > sunfire240 > v890 > sunfire15000 > x4120 > u > deadman > snooping > 0xdeadbeef > null > trap0x31 > u10 > > > # ./c.d > > Please run ''hello_print'' in another terminal. > ----------------------------------------------- > len = 04 [ss20] > len = 12 [sparcstation] > len = 07 [suni386ation] > len = 07 [itaniumation] > len = 11 [austinpowern] > len = 03 [u27] > len = 03 [u24] > len = 06 [galaxypowern] > len = 10 [sunfire240rn] > len = 04 [v890ire240rn] > len = 12 [sunfire15000] > len = 05 [x4120re15000] > len = 01 [u] > len = 07 [deadman15000] > len = 08 [snooping5000] > len = 10 [0xdeadbeef00] > len = 04 [nulladbeef00] > len = 08 [trap0x31ef00] > len = 03 [u10] > --------------- > > > !!! I am sure this is not the right(or consistent) behaviour > !!! here. Or I really have gone off tangent on this? > !!! Appreciate if anyone can shed some light on the > !!! observation here. > > TIA > > Regards > S.T. > -- > This message posted from opensolaris.org > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org-- Adam Leventhal, Fishworks http://blogs.sun.com/ahl
S.T.Chang
2009-May-24  04:13 UTC
[dtrace-discuss] Anomaly in Dtrace copyin() observed through DTT''s zvmstat
Hi Adam, Thanks for the reply.> If you either null-terminal the string yourselfYes, inserting a trailing null works.> or change the copyin() to include the trailing > null your script should work as predicted.Using copyin(arg1, arg2) or copyinstr(arg1) shown that there is no terminating null in arg1 :-) My fault... I should have thought of this. I will advise the CU to modify their script to insert a trailing NULL. Thanks. Regards S.T. -- This message posted from opensolaris.org