ruby-dtrace 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/Manifest.txt +11 -1
- data/README.txt +10 -11
- data/examples/scsi.rb +442 -0
- data/ext/dtrace_aggdata.c +4 -1
- data/ext/dtrace_api.c +18 -7
- data/ext/dtrace_api.h +48 -9
- data/ext/dtrace_bufdata.c +52 -4
- data/ext/dtrace_hdl.c +137 -86
- data/ext/dtrace_probedata.c +188 -50
- data/ext/dtrace_process.c +37 -0
- data/ext/dtrace_recdesc.c +31 -0
- data/lib/dtrace.rb +53 -1
- data/lib/dtraceaggregate.rb +25 -1
- data/lib/dtraceaggregateset.rb +17 -0
- data/lib/dtraceconsumer.rb +91 -67
- data/lib/dtracedata.rb +73 -0
- data/lib/dtraceprintfrecord.rb +8 -0
- data/lib/dtraceprobedata.rb +5 -0
- data/lib/dtracerecord.rb +2 -1
- data/lib/dtracestackrecord.rb +29 -0
- data/plugin/dtrace/lib/dtracer.rb +42 -2
- data/plugin/dtrace/views/dtrace/_report.rhtml +48 -3
- data/test/test_dtrace.rb +2 -0
- data/test/test_dtrace_aggregates.rb +56 -0
- data/test/test_dtrace_processes.rb +83 -0
- data/test/test_dtrace_profile.rb +232 -0
- data/test/test_dtrace_repeat.rb +51 -0
- data/test/test_dtrace_rubyprobe.rb +52 -0
- metadata +19 -5
- data/test/test_dtrace_workapi.rb +0 -142
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.0.3 / 2008-01-06
|
2
|
+
|
3
|
+
* Add a DtraceData class which consumers return, containing
|
4
|
+
the data returned from each probe firing, rather than
|
5
|
+
returning the raw records directly from DTrace.
|
6
|
+
* Provide access to probe, CPU and flow information.
|
7
|
+
* Allow creation and grabbing of processes.
|
8
|
+
* Add an example script: a port of scsi.d.
|
9
|
+
|
1
10
|
== 0.0.2 / 2007-12-07
|
2
11
|
|
3
12
|
* Implement the dtrace_work-based API
|
data/Manifest.txt
CHANGED
@@ -2,6 +2,7 @@ History.txt
|
|
2
2
|
Manifest.txt
|
3
3
|
README.txt
|
4
4
|
Rakefile
|
5
|
+
examples/scsi.rb
|
5
6
|
ext/dtrace_aggdata.c
|
6
7
|
ext/dtrace_api.c
|
7
8
|
ext/dtrace_api.h
|
@@ -9,6 +10,7 @@ ext/dtrace_bufdata.c
|
|
9
10
|
ext/dtrace_hdl.c
|
10
11
|
ext/dtrace_probe.c
|
11
12
|
ext/dtrace_probedata.c
|
13
|
+
ext/dtrace_process.c
|
12
14
|
ext/dtrace_program.c
|
13
15
|
ext/dtrace_programinfo.c
|
14
16
|
ext/dtrace_recdesc.c
|
@@ -16,10 +18,14 @@ ext/dtrace_util.c
|
|
16
18
|
ext/extconf.rb
|
17
19
|
lib/dtrace.rb
|
18
20
|
lib/dtraceaggregate.rb
|
21
|
+
lib/dtraceaggregateset.rb
|
19
22
|
lib/dtraceconsumer.rb
|
23
|
+
lib/dtracedata.rb
|
24
|
+
lib/dtraceprintfrecord.rb
|
20
25
|
lib/dtraceprobe.rb
|
21
26
|
lib/dtraceprobedata.rb
|
22
27
|
lib/dtracerecord.rb
|
28
|
+
lib/dtracestackrecord.rb
|
23
29
|
plugin/dtrace/README
|
24
30
|
plugin/dtrace/Rakefile
|
25
31
|
plugin/dtrace/bin/dtracer.rb
|
@@ -34,4 +40,8 @@ plugin/dtrace/tasks/dtrace.rake
|
|
34
40
|
plugin/dtrace/test/dtrace_test.rb
|
35
41
|
plugin/dtrace/views/dtrace/_report.rhtml
|
36
42
|
test/test_dtrace.rb
|
37
|
-
test/
|
43
|
+
test/test_dtrace_aggregates.rb
|
44
|
+
test/test_dtrace_processes.rb
|
45
|
+
test/test_dtrace_profile.rb
|
46
|
+
test/test_dtrace_repeat.rb
|
47
|
+
test/test_dtrace_rubyprobe.rb
|
data/README.txt
CHANGED
@@ -8,24 +8,23 @@ use it with the probes found in the Joyent and Apple builds of Ruby.
|
|
8
8
|
* Probe metadata
|
9
9
|
* Run D programs
|
10
10
|
* Access aggregates
|
11
|
+
* Consume output from D programs
|
11
12
|
|
12
13
|
== SYNOPSIS
|
13
14
|
|
14
|
-
t = Dtrace.new
|
15
|
-
|
16
|
-
prog = t.compile
|
15
|
+
t = Dtrace.new
|
16
|
+
progtext = 'ruby$1:::function-entry{ @a[strjoin(strjoin(copyinstr(arg0),"."),copyinstr(arg1))] = count(); } END { printa(@a); }'
|
17
|
+
prog = t.compile progtext
|
17
18
|
prog.execute
|
19
|
+
|
18
20
|
t.go
|
19
21
|
|
20
22
|
[...]
|
21
|
-
|
22
|
-
t
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
rec = agg[i]
|
27
|
-
end
|
28
|
-
end
|
23
|
+
|
24
|
+
c = DtraceConsumer.new(t)
|
25
|
+
c.consume_once do |rec|
|
26
|
+
# handle records
|
27
|
+
end
|
29
28
|
|
30
29
|
== REQUIREMENTS
|
31
30
|
|
data/examples/scsi.rb
ADDED
@@ -0,0 +1,442 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'dtrace'
|
4
|
+
require 'getoptlong'
|
5
|
+
|
6
|
+
# scsi.rb: part of ruby-dtrace, (c) Chris Andrews, 2007
|
7
|
+
#
|
8
|
+
# This is a ruby reimplementation of Chris Gerhard's "scsi.d" script,
|
9
|
+
# obtained from here:
|
10
|
+
# http://blogs.sun.com/chrisg/resource/scsi_d/scsi.d-1.12
|
11
|
+
#
|
12
|
+
# It's meant as an example of how you might use ruby to keep the D
|
13
|
+
# script simple. For actually debugging SCSI, scsi.d is probably a
|
14
|
+
# better bet!
|
15
|
+
|
16
|
+
class ScsiCdb
|
17
|
+
attr_reader :op, :len, :control, :lba, :cdblen
|
18
|
+
|
19
|
+
def initialize(group, cdb_bytes)
|
20
|
+
@bytes = cdb_bytes
|
21
|
+
@group = group
|
22
|
+
parse
|
23
|
+
end
|
24
|
+
|
25
|
+
def raw
|
26
|
+
@bytes.slice(0, @cdblen).inject('') {|string, b| string + sprintf('%2.2x', b) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse
|
30
|
+
|
31
|
+
case @group
|
32
|
+
when 0
|
33
|
+
@lba = int32([0, @bytes[1] & 0x1f, @bytes[2], @bytes[3]])
|
34
|
+
@lbalen = 6;
|
35
|
+
@len = int8(@bytes[4])
|
36
|
+
@control = @bytes[5]
|
37
|
+
@sa = 0
|
38
|
+
@cdblen = 6
|
39
|
+
|
40
|
+
when 1
|
41
|
+
@lba = int32(@bytes[2..5])
|
42
|
+
@lbalen = 8
|
43
|
+
@len = int16(@bytes[7..8])
|
44
|
+
@control = @bytes[9]
|
45
|
+
@sa = 0
|
46
|
+
@cdblen = 10
|
47
|
+
|
48
|
+
when 2
|
49
|
+
@lba = int32(@bytes[2..5])
|
50
|
+
@lbalen = 8
|
51
|
+
@len = int16(@bytes[7..8])
|
52
|
+
@control = @bytes[9]
|
53
|
+
@sa = 0
|
54
|
+
@cdblen = 10
|
55
|
+
|
56
|
+
when 3
|
57
|
+
@lba = int64(@bytes[12..19])
|
58
|
+
@lbalen = 16;
|
59
|
+
@len = int32(@bytes[28..31])
|
60
|
+
@control = @bytes[1]
|
61
|
+
@sa = int16(@bytes[8..9])
|
62
|
+
@cdblen = 32
|
63
|
+
|
64
|
+
when 4
|
65
|
+
@lba = int64(@bytes[2..9])
|
66
|
+
@lbalen = 16
|
67
|
+
@len = int32(@bytes[10.13])
|
68
|
+
@control = @bytes[15]
|
69
|
+
@sa = 0
|
70
|
+
@cdblen = 16
|
71
|
+
|
72
|
+
when 5
|
73
|
+
@lba = int32(@bytes[2..5])
|
74
|
+
@lbalen = 8;
|
75
|
+
@len = int32(@bytes[6..9])
|
76
|
+
@control = @bytes[11]
|
77
|
+
@sa = 0
|
78
|
+
@cdblen = 12
|
79
|
+
|
80
|
+
when 6 .. 7
|
81
|
+
@lba = 0
|
82
|
+
@lbalen = 0
|
83
|
+
@len = 0
|
84
|
+
@control = 0
|
85
|
+
@sa = 0
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
@op = scsi_op(@bytes[0], @sa)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def int8(byte)
|
94
|
+
return byte & 0x0ff;
|
95
|
+
end
|
96
|
+
|
97
|
+
def int16(bytes)
|
98
|
+
return (int8(bytes[0]) << 8) + int8(bytes[1])
|
99
|
+
end
|
100
|
+
|
101
|
+
def int32(bytes)
|
102
|
+
return (int16(bytes[0..1]) << 16) + int16(bytes[2..3])
|
103
|
+
end
|
104
|
+
|
105
|
+
def int64(bytes)
|
106
|
+
return (int32(bytes[0..3]) << 32) + int32(bytes[4..7])
|
107
|
+
end
|
108
|
+
|
109
|
+
def scsi_op(code, code2)
|
110
|
+
scsi_ops = {
|
111
|
+
0x000 => "TEST_UNIT_READY",
|
112
|
+
0x001 => "REZERO_UNIT_or_REWIND",
|
113
|
+
0x003 => "REQUEST_SENSE",
|
114
|
+
0x004 => "FORMAT_UNIT",
|
115
|
+
0x007 => "REASSIGN_BLOCKS",
|
116
|
+
0x008 => "READ(6)",
|
117
|
+
0x00a => "WRITE(6)",
|
118
|
+
0x00b => "SEEK(6)",
|
119
|
+
0x012 => "INQUIRY",
|
120
|
+
0x015 => "MODE_SELECT(6)",
|
121
|
+
0x016 => "RESERVE(6)",
|
122
|
+
0x017 => "RELEASE(6)",
|
123
|
+
0x018 => "COPY",
|
124
|
+
0x019 => "ERASE(6)",
|
125
|
+
0x01a => "MODE_SENSE(6)",
|
126
|
+
0x01b => "START_STOP_UNIT",
|
127
|
+
0x01c => "RECIEVE_DIAGNOSTIC_RESULTS",
|
128
|
+
0x01d => "SEND_DIAGNOSTIC",
|
129
|
+
0x01e => "PREVENT_ALLOW_MEDIUM_REMOVAL",
|
130
|
+
0x025 => "READ_CAPACITY(10)",
|
131
|
+
0x028 => "READ(10)",
|
132
|
+
0x02a => "WRITE(10)",
|
133
|
+
0x02b => "SEEK(10)_or_LOCATE(10)",
|
134
|
+
0x02e => "WRITE_AND_VERIFY(10)",
|
135
|
+
0x02f => "VERIFY(10)",
|
136
|
+
0x030 => "SEARCH_DATA_HIGH",
|
137
|
+
0x031 => "SEARCH_DATA_EQUAL",
|
138
|
+
0x032 => "SEARCH_DATA_LOW",
|
139
|
+
0x033 => "SET_LIMITS(10)",
|
140
|
+
0x034 => "PRE-FETCH(10)",
|
141
|
+
0x035 => "SYNCHRONIZE_CACHE(10)",
|
142
|
+
0x036 => "LOCK_UNLOCK_CACHE(10)",
|
143
|
+
0x037 => "READ_DEFECT_DATA(10)",
|
144
|
+
0x039 => "COMPARE",
|
145
|
+
0x03a => "COPY_AND_WRITE",
|
146
|
+
0x03b => "WRITE_BUFFER",
|
147
|
+
0x03c => "READ_BUFFER",
|
148
|
+
0x03e => "READ_LONG",
|
149
|
+
0x03f => "WRITE_LONG",
|
150
|
+
0x040 => "CHANGE_DEFINITION",
|
151
|
+
0x041 => "WRITE_SAME(10)",
|
152
|
+
0x04c => "LOG_SELECT",
|
153
|
+
0x04d => "LOG_SENSE",
|
154
|
+
0x050 => "XDWRITE(10)",
|
155
|
+
0x051 => "XPWRITE(10)",
|
156
|
+
0x052 => "XDREAD(10)",
|
157
|
+
0x053 => "XDWRITEREAD(10)",
|
158
|
+
0x055 => "MODE_SELECT(10)",
|
159
|
+
0x056 => "RESERVE(10)",
|
160
|
+
0x057 => "RELEASE(10)",
|
161
|
+
0x05a => "MODE_SENSE(10)",
|
162
|
+
0x05e => "PERSISTENT_RESERVE_IN",
|
163
|
+
0x05f => "PERSISTENT_RESERVE_OUT",
|
164
|
+
0x07f => "Variable_Length_CDB",
|
165
|
+
0x080 => "XDWRITE_EXTENDED(16)",
|
166
|
+
0x081 => "REBUILD(16)",
|
167
|
+
0x082 => "REGENERATE(16)",
|
168
|
+
0x083 => "EXTENDED_COPY",
|
169
|
+
0x086 => "ACCESS_CONTROL_IN",
|
170
|
+
0x087 => "ACCESS_CONTROL_OUT",
|
171
|
+
0x088 => "READ(16)",
|
172
|
+
0x08a => "WRITE(16)",
|
173
|
+
0x08c => "READ_ATTRIBUTES",
|
174
|
+
0x08d => "WRITE_ATTRIBUTES",
|
175
|
+
0x08e => "WRITE_AND_VERIFY(16)",
|
176
|
+
0x08f => "VERIFY(16)",
|
177
|
+
0x090 => "PRE-FETCH(16)",
|
178
|
+
0x091 => "SYNCHRONIZE_CACHE(16)",
|
179
|
+
0x092 => "LOCK_UNLOCK_CACHE(16)_or_LOCATE(16)",
|
180
|
+
0x093 => "WRITE_SAME(16)_or_ERASE(16)",
|
181
|
+
0x09e => "SERVICE_IN_or_READ_CAPACITY(16)",
|
182
|
+
0x0a0 => "REPORT_LUNS",
|
183
|
+
0x0a3 => "MAINTENANCE_IN_or_REPORT_TARGET_PORT_GROUPS",
|
184
|
+
0x0a4 => "MAINTENANCE_OUT_or_SET_TARGET_PORT_GROUPS",
|
185
|
+
0x0a7 => "MOVE_MEDIUM",
|
186
|
+
0x0a8 => "READ(12)",
|
187
|
+
0x0aa => "WRITE(12)",
|
188
|
+
0x0ae => "WRITE_AND_VERIFY(12)",
|
189
|
+
0x0af => "VERIFY(12)",
|
190
|
+
0x0b3 => "SET_LIMITS(12)",
|
191
|
+
0x0b4 => "READ_ELEMENT_STATUS",
|
192
|
+
0x0b7 => "READ_DEFECT_DATA(12)",
|
193
|
+
0x0ba => "REDUNDANCY_GROUP_IN",
|
194
|
+
0x0bb => "REDUNDANCY_GROUP_OUT",
|
195
|
+
0x0bc => "SPARE_IN",
|
196
|
+
0x0bd => "SPARE_OUT",
|
197
|
+
0x0be => "VOLUME_SET_IN",
|
198
|
+
0x0bf => "VOLUME_SET_OUT",
|
199
|
+
0x0d0 => "EXPLICIT_LUN_FAILOVER",
|
200
|
+
0x0f1 => "STOREDGE_CONTROLLER"
|
201
|
+
}
|
202
|
+
|
203
|
+
variable_length_ops = {
|
204
|
+
0x3 => "XDREAD(32)",
|
205
|
+
0x4 => "XDWRITE(32)",
|
206
|
+
0x6 => "XPWRITE(32)",
|
207
|
+
0x7 => "XDWRITEREAD(32)",
|
208
|
+
0x9 => "READ(32)",
|
209
|
+
0xb => "WRITE(32)",
|
210
|
+
0xa => "VERIFY(32)",
|
211
|
+
0xc => "WRITE_AND_VERIFY(32)"
|
212
|
+
}
|
213
|
+
|
214
|
+
op = scsi_ops[code]
|
215
|
+
if op == 'Variable_Length_CDB'
|
216
|
+
return variable_length_ops[code2]
|
217
|
+
else
|
218
|
+
return op
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
def scsi_reason(code)
|
225
|
+
scsi_reasons = {
|
226
|
+
0 => "COMPLETED",
|
227
|
+
1 => "INCOMPLETE",
|
228
|
+
2 => "DMA_ERR",
|
229
|
+
3 => "TRAN_ERR",
|
230
|
+
4 => "RESET",
|
231
|
+
5 => "ABORTED",
|
232
|
+
6 => "TIMEOUT",
|
233
|
+
7 => "DATA_OVERRUN",
|
234
|
+
8 => "COMMAND_OVERRUN",
|
235
|
+
9 => "STATUS_OVERRUN",
|
236
|
+
10 => "Bad_Message",
|
237
|
+
11 => "No_Message_Out",
|
238
|
+
12 => "XID_Failed",
|
239
|
+
13 => "IDE_Failed",
|
240
|
+
14 => "Abort_Failed",
|
241
|
+
15 => "Reject_Failed",
|
242
|
+
16 => "Nop_Failed",
|
243
|
+
17 => "Message_Parity_Error_Failed",
|
244
|
+
18 => "Bus_Device_Reset_Failed",
|
245
|
+
19 => "Identify_Message_Rejected",
|
246
|
+
20 => "Unexpected_Bus_free",
|
247
|
+
21 => "Tag_Rejected",
|
248
|
+
22 => "TERMINATED",
|
249
|
+
24 => "Device_Gone"
|
250
|
+
}
|
251
|
+
return scsi_reasons[code]
|
252
|
+
end
|
253
|
+
|
254
|
+
timeout = 0
|
255
|
+
opts = GetoptLong.new([ '-T', GetoptLong::REQUIRED_ARGUMENT ])
|
256
|
+
opts.each do |opt, arg|
|
257
|
+
if opt == '-T'
|
258
|
+
timeout = arg
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
devname = ARGV.shift
|
263
|
+
devinst = ARGV.shift
|
264
|
+
|
265
|
+
if devname && devinst
|
266
|
+
matchdev = "/this->devname == \"#{devname}\" && this->devinst == #{devinst}/"
|
267
|
+
elsif devname
|
268
|
+
matchdev = "/this->devname == \"#{devname}\"/"
|
269
|
+
else
|
270
|
+
matchdev = ""
|
271
|
+
end
|
272
|
+
|
273
|
+
progtext =<<"EOD"
|
274
|
+
|
275
|
+
struct scsi_cdb {
|
276
|
+
uint8_t bytes[32];
|
277
|
+
};
|
278
|
+
|
279
|
+
BEGIN
|
280
|
+
{
|
281
|
+
script_start_time = timestamp;
|
282
|
+
timeout = #{timeout};
|
283
|
+
end_time = timestamp + (timeout * 1000000000);
|
284
|
+
}
|
285
|
+
|
286
|
+
fbt:scsi:scsi_transport:entry,
|
287
|
+
fbt:scsi:scsi_destroy_pkt:entry
|
288
|
+
/timeout != 0 && end_time < timestamp/
|
289
|
+
{
|
290
|
+
exit(0);
|
291
|
+
}
|
292
|
+
|
293
|
+
fbt:scsi:scsi_transport:entry,
|
294
|
+
fbt:scsi:scsi_destroy_pkt:entry
|
295
|
+
{
|
296
|
+
this->pkt = (struct scsi_pkt *)arg0;
|
297
|
+
this->scb = (uchar_t *)this->pkt->pkt_scbp;
|
298
|
+
|
299
|
+
this->devinfo = ((struct dev_info *)((this->pkt->pkt_address.a_hba_tran)->tran_hba_dip));
|
300
|
+
this->devname = stringof(`devnamesp[this->devinfo->devi_major].dn_name);
|
301
|
+
this->devinst = this->devinfo->devi_instance;
|
302
|
+
|
303
|
+
relevant[this->scb] = 0;
|
304
|
+
}
|
305
|
+
|
306
|
+
fbt:scsi:scsi_transport:entry,
|
307
|
+
fbt:scsi:scsi_destroy_pkt:entry
|
308
|
+
#{matchdev}
|
309
|
+
{
|
310
|
+
relevant[this->scb] = 1;
|
311
|
+
}
|
312
|
+
|
313
|
+
fbt:scsi:scsi_transport:entry
|
314
|
+
/relevant[this->scb] == 1/
|
315
|
+
{
|
316
|
+
start_time[this->scb] = timestamp;
|
317
|
+
this->dir = 1;
|
318
|
+
}
|
319
|
+
|
320
|
+
fbt:scsi:scsi_destroy_pkt:entry
|
321
|
+
/relevant[this->scb] == 1/
|
322
|
+
{
|
323
|
+
req_time[this->scb] = start_time[this->scb] != 0 ?
|
324
|
+
(timestamp - start_time[this->scb])/1000 : 0;
|
325
|
+
start_time[this->scb] = 0;
|
326
|
+
this->dir = 0;
|
327
|
+
}
|
328
|
+
|
329
|
+
fbt:scsi:scsi_transport:entry,
|
330
|
+
fbt:scsi:scsi_destroy_pkt:entry
|
331
|
+
/relevant[this->scb] == 1/
|
332
|
+
{
|
333
|
+
this->cdb = (uchar_t *)this->pkt->pkt_cdbp;
|
334
|
+
this->group = ((this->cdb[0] & 0xe0) >> 5);
|
335
|
+
|
336
|
+
/* timestamp */
|
337
|
+
trace((timestamp - script_start_time)/1000000000);
|
338
|
+
trace((timestamp - script_start_time)%1000000000);
|
339
|
+
|
340
|
+
/* devname, devinst */
|
341
|
+
trace(this->devname);
|
342
|
+
trace(this->devinst);
|
343
|
+
|
344
|
+
/* scsi cdb */
|
345
|
+
trace(this->cdb);
|
346
|
+
trace(this->group);
|
347
|
+
trace(*(struct scsi_cdb *)(this->cdb));
|
348
|
+
|
349
|
+
/* command or response? */
|
350
|
+
trace(this->dir);
|
351
|
+
|
352
|
+
/* target and LUN */
|
353
|
+
trace(this->pkt->pkt_address.a_target);
|
354
|
+
trace(this->pkt->pkt_address.a_lun);
|
355
|
+
|
356
|
+
/* timeout */
|
357
|
+
trace(this->pkt->pkt_time);
|
358
|
+
|
359
|
+
/* executable and pid, for commands */
|
360
|
+
trace(execname);
|
361
|
+
trace(pid);
|
362
|
+
|
363
|
+
/* reason and state, for responses */
|
364
|
+
trace(this->pkt->pkt_reason);
|
365
|
+
trace(this->pkt->pkt_state);
|
366
|
+
|
367
|
+
/* elapsed time for this command/response */
|
368
|
+
trace(req_time[this->scb]);
|
369
|
+
req_time[this->scb] = 0;
|
370
|
+
|
371
|
+
relevant[this->scb] = 0;
|
372
|
+
}
|
373
|
+
|
374
|
+
EOD
|
375
|
+
#`
|
376
|
+
|
377
|
+
t = Dtrace.new
|
378
|
+
t.setopt("bufsize", "4m")
|
379
|
+
prog = t.compile progtext
|
380
|
+
prog.execute
|
381
|
+
t.go
|
382
|
+
|
383
|
+
begin
|
384
|
+
c = DtraceConsumer.new(t)
|
385
|
+
|
386
|
+
c.consume do |d|
|
387
|
+
records = d.data
|
388
|
+
|
389
|
+
# D exit at timeout
|
390
|
+
if records.length == 1 && records[0].value == 0
|
391
|
+
exit 0
|
392
|
+
end
|
393
|
+
|
394
|
+
# first two elements are timestamp
|
395
|
+
t = sprintf("%05.5d.%09.9d", records.shift.value, records.shift.value)
|
396
|
+
|
397
|
+
# next two elements are devname/devinst
|
398
|
+
dev = sprintf('%s%d', records.shift.value, records.shift.value)
|
399
|
+
|
400
|
+
# next is CBDP, group, then 32 bytes of CDB
|
401
|
+
cdbp = records.shift.value
|
402
|
+
group = records.shift.value
|
403
|
+
cdb_bytes = records.shift.value
|
404
|
+
|
405
|
+
# then dir flag
|
406
|
+
dir = (records.shift.value == 1) ? '->' : '<-'
|
407
|
+
|
408
|
+
# address
|
409
|
+
address_target = records.shift.value
|
410
|
+
address_lun = records.shift.value
|
411
|
+
|
412
|
+
# timeout
|
413
|
+
timeout = records.shift.value
|
414
|
+
|
415
|
+
# execname and pid
|
416
|
+
execname = records.shift.value
|
417
|
+
pid = records.shift.value
|
418
|
+
|
419
|
+
# reason, state, request time
|
420
|
+
reason = records.shift.value
|
421
|
+
state = records.shift.value
|
422
|
+
req_time = records.shift.value
|
423
|
+
|
424
|
+
# parse the CDB
|
425
|
+
cdb = ScsiCdb.new(group, cdb_bytes)
|
426
|
+
|
427
|
+
printf "%s %s:%s 0x%2.2x %9s address %2.2d:%2.2d, lba 0x%08x, len 0x%6.6x, control 0x%2.2x timeout %d CDBP 0x%x",
|
428
|
+
t, dev, dir, cdb_bytes[0], cdb.op, address_target, address_lun,
|
429
|
+
cdb.lba, cdb.len, cdb.control, timeout, cdbp, execname, pid
|
430
|
+
|
431
|
+
case dir
|
432
|
+
when '->'
|
433
|
+
printf " %s(%d) cdb(%d) %s\n", execname, pid, cdb.cdblen, cdb.raw
|
434
|
+
when '<-'
|
435
|
+
printf ", reason 0x%x (%s) state 0x%x Time %dus\n", reason, scsi_reason(reason), state, req_time
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
rescue Interrupt => e
|
440
|
+
exit
|
441
|
+
end
|
442
|
+
|