4 # Checks assumptions on Cc* (Cache Manager) behaviour by reading TraceFS log
5 # Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; exactly version 2 of June 1991 is required
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 use Carp qw(cluck confess);
28 $Data::Dumper::Sortkeys=1;
29 my $ntfs_blocksize=0x200;
31 # $Object->{"by"}="CcSomeFunction";
32 # $Object->{"line_enter"}=123;
33 # $Object->{"line_leave"}=124;
34 # $Object->{"process_thread"}="0x12345678/0x12345678";
35 # $Object->{"data"}[dataline]{"FileObject"}="0x12345678";
36 # $Object->{"data"}[dataline]{"FileName"}="\filename" or undef() if NULL;
37 # $Object->{"data"}[dataline]{"Flags"}="0x40100";
38 # $Object->{"data"}[dataline]{"SectionObjectPointer"}="0x12345678";
39 # $Object->{"data"}[dataline]{"SharedCacheMap"}="0x12345678";
40 # $FileObject{$FileObject}{"FileObject"}="0x12345678";
41 # $FileObject{$FileObject}{"SectionObjectPointer"}="0x12345678";
42 # $SectionObjectPointer{$SectionObjectPointer}{"SectionObjectPointer"}="0x12345678";
43 # $SectionObjectPointer{$SectionObjectPointer}{"SharedCacheMap"}="0x12345678";
44 # $SharedCacheMap{$SharedCacheMap}{"SharedCacheMap"}="0x12345678";
45 # $SharedCacheMap{$SharedCacheMap}{"SectionObjectPointer"}="0x12345678";
46 # $SharedCacheMap{$SharedCacheMap}{"Allocation"}="0x12345";
47 # $SharedCacheMap{$SharedCacheMap}{"FileSize"}="0x12345";
48 # $SharedCacheMap{$SharedCacheMap}{"ref_count"}=1;
49 # $SharedCacheMap{$SharedCacheMap}{"map"}="0x12345678" (Bcb);
50 # $SharedCacheMap{$SharedCacheMap}{"pin"}{"0x1000"}="0x12345678" (Bcb);
51 # $SharedCacheMap{$SharedCacheMap}{"PinAccess"}=0 or 1;
52 # $Bcb{$Bcb}{"Bcb"}="0x12345678";
53 # $Bcb{$Bcb}{"SharedCacheMap"}="0x12345678";
54 # $Bcb{$Bcb}{"type"}="pin" or "map";
55 # $Bcb{$Bcb}{"ref_count"}=1;
56 # $Bcb{$Bcb}{"FileOffset"}="0x1000" if {"type"} eq "pin";
57 # $Bcb{$Bcb}{"Buffer"}="0x12345678"; # PAGE_SIZE-aligned for "pin", FileOffset_0-aligned for "map"
60 my %SectionObjectPointer;
65 print Data::Dumper->Dump([\%FileObject,\%SectionObjectPointer,\%SharedCacheMap,\%Bcb],
66 [qw(%FileObject %SectionObjectPointer %SharedCacheMap %Bcb)]) if !$filter;
75 return sprintf("0x%X",$num);
82 my $FObject=$FileObject{$FileObject};
84 my($package,$filename,$line,$subroutine)=caller 0;
85 warn "Non-existent FileObject $FileObject by line $line";
92 my($SectionObjectPointer)=@_;
94 my $SObject=$SectionObjectPointer{$SectionObjectPointer};
96 my($package,$filename,$line,$subroutine)=caller 0;
97 warn "Non-existent SectionObjectPointer $SectionObjectPointer by line $line"
102 sub SObject_from_FileObject($)
106 return if !(my $FObject=FObject $FileObject);
107 my $SObject=SObject $FObject->{"SectionObjectPointer"};
109 my($package,$filename,$line,$subroutine)=caller 0;
110 warn "by line $line";
115 sub delete_CObject($)
119 my $SharedCacheMap=$CObject->{"SharedCacheMap"};
120 do { warn "Trailing map $_ of SharedCacheMap $SharedCacheMap during its deletion" if $_; } for ($CObject->{"map"});
121 do { warn "Trailing pin $_ of SharedCacheMap $SharedCacheMap during its deletion" if $_; } for (values(%{$CObject->{"pin"}}));
122 delete $SharedCacheMap{$SharedCacheMap};
127 my($SharedCacheMap)=@_;
129 my $CObject=$SharedCacheMap{$SharedCacheMap};
131 my($package,$filename,$line,$subroutine)=caller 0;
132 warn "Non-existent SharedCacheMap $SharedCacheMap by line $line";
137 sub CObject_from_FileObject($)
141 return if !(my $SObject=SObject_from_FileObject $FileObject);
142 return if !(my $CObject=CObject $SObject->{"SharedCacheMap"});
146 sub SharedCacheMap_valid($)
148 my($SharedCacheMap)=@_;
150 cluck if !defined $SharedCacheMap;
151 return 0 if "0x".("F"x8) eq $SharedCacheMap;
152 return 0 if !eval $SharedCacheMap;
160 if (!eval $data->{"SectionObjectPointer"}) {
161 return if $Object->{"by"} eq "IRP_MJ_CREATE"; # SectionObjectPointer is not yet initialized
162 warn "Existing FileObject ".$data->{"FileObject"}." but no SectionObjectPointer found"
163 if $FileObject{$data->{"FileObject"}} && eval($FileObject{$data->{"FileObject"}}{"SectionObjectPointer"});
166 my $SectionObjectPointer=$data->{"SectionObjectPointer"};
167 if (!SharedCacheMap_valid $data->{"SharedCacheMap"} && $SectionObjectPointer{$SectionObjectPointer}) {
168 return if !(my $SObject=SObject $SectionObjectPointer);
169 my $SharedCacheMap=$SObject->{"SharedCacheMap"};
170 return if !eval $SharedCacheMap;
171 my $CObject=CObject $SharedCacheMap;
172 warn "Existing SectionObjectPointer ".$data->{"SectionObjectPointer"}." but no SharedCacheMap found,"
173 ." ref_count of SharedCacheMap is ".$CObject->{"ref_count"}
174 if $CObject->{"ref_count"};
175 # if $SectionObjectPointer{$data->{"SectionObjectPointer"}};
176 # SharedCacheMap was droppped by async task as it had ref_count==0.
177 delete_CObject $CObject;
178 $SObject->{"SharedCacheMap"}=tohex(0);
179 # FileObject is still valid!
182 return if !$FileObject{$data->{"FileObject"}};
183 return if !(my $FObject=FObject $data->{"FileObject"});
184 return if !(my $SObject=SObject $FObject->{"SectionObjectPointer"});
185 my $SharedCacheMap=$SObject->{"SharedCacheMap"};
186 warn "FileObject ".$FObject->{"FileObject"}." SectionObjectPointer ".$SObject->{"SectionObjectPointer"}
187 ." expected SharedCacheMap $SharedCacheMap"
188 ." but found SharedCacheMap ".$data->{"SharedCacheMap"}
189 if $SharedCacheMap ne $data->{"SharedCacheMap"};
190 warn "INTERNAL: SharedCacheMap $SharedCacheMap of FileObject ".$FObject->{"FileObject"}." got destroyed"
191 if !$SharedCacheMap{$SharedCacheMap};
194 sub CcInitializeCacheMap($$$$$)
196 my($FileObject,$AllocationSize,$FileSize,$ValidDataLength,$PinAccess)=@_;
198 $ValidDataLength=$FileSize if $ValidDataLength==eval("0x".("F"x8));
199 $Object->{"ref_count"}=1;
200 $Object->{"AllocationSize"}=tohex($AllocationSize);
201 $Object->{"FileSize"}=tohex($FileSize);
202 $Object->{"ValidDataLength"}=tohex($ValidDataLength);
203 $Object->{"map"}=undef();
205 $Object->{"PinAccess"}=$PinAccess;
206 $Object->{"FileObject"}=$FileObject;
209 sub CcInitializeCacheMap_leave()
211 my $SharedCacheMap=$Object->{"data"}[1]{"SharedCacheMap"};
212 $Object->{"SharedCacheMap"}=$SharedCacheMap;
213 my $old=$SharedCacheMap{$SharedCacheMap};
214 if (!SharedCacheMap_valid $Object->{"data"}[0]{"SharedCacheMap"} && $old) {
215 # SharedCacheMap got deleted in the meantime
216 delete_CObject CObject $SharedCacheMap;
217 my $SObject=SObject $Object->{"data"}[0]{"SectionObjectPointer"};
218 $SObject->{"SharedCacheMap"}=tohex(0);
221 if (!$old != !SharedCacheMap_valid $Object->{"data"}[0]{"SharedCacheMap"}) {
222 warn "Expecting old SharedCacheMap validity ".(!!$old)
223 ." but found old SharedCacheMap ".$Object->{"data"}[0]{"SharedCacheMap"};
225 warn "New SharedCacheMap ".$Object->{"data"}[1]{"SharedCacheMap"}." is not valid"
226 if !SharedCacheMap_valid $Object->{"data"}[1]{"SharedCacheMap"};
227 if (SharedCacheMap_valid $Object->{"data"}[0]{"SharedCacheMap"}) {
228 warn "Existing SharedCacheMap changed"
229 ." from ".$Object->{"data"}[0]{"SharedCacheMap"}." to ".$Object->{"data"}[1]{"SharedCacheMap"}
230 if $Object->{"data"}[0]{"SharedCacheMap"} ne $Object->{"data"}[1]{"SharedCacheMap"};
233 for my $field (qw(AllocationSize FileSize PinAccess)) {
234 warn "SharedCacheMap $SharedCacheMap old instance $field ".$old->{$field}
235 ." != new instance $field ".$Object->{$field}
236 if $old->{$field} ne $Object->{$field};
238 do { warn "Existing map Bcb $_ during CcInitializeCacheMap()" if $_; } for ($old->{"map"});
239 do { warn "Existing pin Bcb $_ during CcInitializeCacheMap()" if $_; } for (values(%{$old->{"pin"}}));
240 $Object->{"ref_count"}+=$old->{"ref_count"};
242 $SharedCacheMap{$SharedCacheMap}=$Object;
244 warn "Changed SectionObjectPointer inside CcInitializeCacheMap()"
245 ." from ".$Object->{"data"}[0]{"SectionObjectPointer"}." to ".$Object->{"data"}[1]{"SectionObjectPointer"}
246 if $Object->{"data"}[0]{"SectionObjectPointer"} ne $Object->{"data"}[1]{"SectionObjectPointer"};
247 my $SectionObjectPointer=$Object->{"data"}[1]{"SectionObjectPointer"};
249 my $FileObject=$Object->{"FileObject"};
250 if (my $FObject=$FileObject{$FileObject}) {
251 if (my $SObject=$SectionObjectPointer{$FObject->{"SectionObjectPointer"}}) {
252 warn "Changed SectionObjectPointer of FileObject $FileObject"
253 ." from ".$FObject->{"SectionObjectPointer"}." to ".$SectionObjectPointer
254 if $FObject->{"SectionObjectPointer"} ne $SectionObjectPointer;
256 # Otherwise SectionObjectPointer could be deleted and rebuilt async in the meantime.
258 $FileObject{$FileObject}={
259 "FileObject"=>$FileObject,
260 "SectionObjectPointer"=>$SectionObjectPointer,
263 if (my $SObject=$SectionObjectPointer{$SectionObjectPointer}) {
264 warn "Changed SharedCacheMap of SectionObjectPointer $SectionObjectPointer"
265 ." from ".$SObject->{"SharedCacheMap"}." to ".$SharedCacheMap
266 if $SObject->{"SharedCacheMap"} ne $SharedCacheMap && eval($SObject->{"SharedCacheMap"});
268 $SectionObjectPointer{$SectionObjectPointer}={
269 "SectionObjectPointer"=>$SectionObjectPointer,
270 "SharedCacheMap"=>$SharedCacheMap,
273 CcSetFileSizes($FileObject,map({ eval($Object->{$_}); } qw(AllocationSize FileSize ValidDataLength)));
274 delete $Object->{$_} for (qw(FileObject ValidDataLength));
277 sub CcUninitializeCacheMap($$)
279 my($FileObject,$TruncateSize)=@_;
281 $Object->{"FileObject"}=$FileObject;
284 sub CcUninitializeCacheMap_leave($)
288 my $FileObject=$Object->{"FileObject"};
289 # 'r' means function success.
290 # r=0 either if no CcInitializeCacheMap() was called at all
291 # or if Cc was unable to detach SharedCacheMap and it remains valid
292 # (FIXME: Do we SharedCacheMap->ref_count-- on in such case?).
293 my $SectionObjectPointer=$FileObject{$FileObject}->{"SectionObjectPointer"} if $FileObject{$FileObject};
294 my $SharedCacheMap=$SectionObjectPointer{$SectionObjectPointer}->{"SharedCacheMap"}
295 if $SectionObjectPointer && $SectionObjectPointer{$SectionObjectPointer};
296 warn "Unexpected 'r' result $r for CcUninitializeCacheMap of FileObject $FileObject"
297 if !(eval($SharedCacheMap) && !SharedCacheMap_valid($Object->{"data"}[1]{"SharedCacheMap"})) != !$r;
298 if (!eval $SharedCacheMap) {
299 for my $SharedCacheMap ($Object->{"data"}[0]{"SharedCacheMap"},$Object->{"data"}[1]{"SharedCacheMap"}) {
300 warn "Not expecting valid SharedCacheMap $SharedCacheMap"
301 if SharedCacheMap_valid $SharedCacheMap;
305 for my $SharedCacheMap ($Object->{"data"}[0]{"SharedCacheMap"}) {
306 warn "Expecting valid SharedCacheMap $SharedCacheMap"
307 if !SharedCacheMap_valid $SharedCacheMap;
309 return if !(my $FObject=FObject $FileObject);
310 return if !(my $SObject=SObject $FObject->{"SectionObjectPointer"});
311 return if !(my $CObject=CObject $SObject->{"SharedCacheMap"});
312 if (--$CObject->{"ref_count"}) {
313 for my $SharedCacheMap ($Object->{"data"}[1]{"SharedCacheMap"}) {
314 warn "Expecting still valid SharedCacheMap $SharedCacheMap after CcUninitializeCacheMap()"
315 ." with ref_count=".$CObject->{"ref_count"}
316 if !SharedCacheMap_valid $SharedCacheMap;
320 if (!SharedCacheMap_valid $Object->{"data"}[1]{"SharedCacheMap"}) {
321 delete_CObject $CObject;
322 $SObject->{"SharedCacheMap"}=tohex(0);
323 # FileObject is still valid!
326 # FIXME: Do we SharedCacheMap->ref_count-- on in such case?
330 sub CcSetFileSizes($$$$)
332 my($FileObject,$AllocationSize,$FileSize,$ValidDataLength)=@_;
334 return if !(my $CObject=CObject_from_FileObject $FileObject);
335 my $SharedCacheMap=$CObject->{"SharedCacheMap"};
336 if ($AllocationSize!=eval($CObject->{"AllocationSize"})) {
337 do { warn "Existing map $_ of FileObject $FileObject SharedCacheMap $SharedCacheMap during CcSetAllocationSizes(),"
338 ." AllocationSize=".$CObject->{"AllocationSize"} if $_; }
339 for ($CObject->{"map"});
340 do { warn "Existing pin $_ of FileObject $FileObject SharedCacheMap $SharedCacheMap during CcSetAllocationSizes(),"
341 ." AllocationSize=".$CObject->{"AllocationSize"} if $_; }
342 for (values(%{$CObject->{"pin"}}));
344 # $ValidDataLength can be > $CObject->{"FileSize"};
345 warn "ValidDataLength ".tohex($ValidDataLength)." > FileSize ".tohex($FileSize)
346 if $ValidDataLength>$FileSize;
347 warn "0 != AllocationSize ".tohex($AllocationSize)." % ntfs_blocksize ".tohex($ntfs_blocksize)
348 if 0!=($AllocationSize%$ntfs_blocksize);
349 # $AllocationSize can be higher
350 warn "FileSize ".tohex($FileSize)." > AllocationSize ".tohex($AllocationSize)
351 if $FileSize>$AllocationSize;
352 $CObject->{"FileSize"}=tohex($FileSize);
353 $CObject->{"AllocationSize"}=tohex($AllocationSize);
356 sub IRP_MJ_CREATE_leave()
358 do { warn "Non-NULL SectionObjectPointer $_ not expected" if eval($_); } for ($Object->{"data"}[0]{"SectionObjectPointer"});
359 my $FileObject=$Object->{"data"}[0]{"FileObject"};
360 warn "Existing FileObject $FileObject not expected" if $FileObject{$FileObject};
361 my $SectionObjectPointer=$Object->{"data"}[1]{"SectionObjectPointer"};
362 # We want to track even FileObject without SectionObjectPointer yet.
363 # if ($SectionObjectPointer && $SectionObjectPointer{$SectionObjectPointer})
365 $FileObject{$FileObject}={
366 "FileObject"=>$FileObject,
367 "SectionObjectPointer"=>$SectionObjectPointer,
370 if (eval $SectionObjectPointer) {
371 my $SharedCacheMap=$Object->{"data"}[1]{"SharedCacheMap"};
372 if (my $SObject=$SectionObjectPointer{$SectionObjectPointer}) {
373 warn "Changed SharedCacheMap from stored ".$SObject->{"SharedCacheMap"}." to ".$SharedCacheMap
374 if $SObject->{"SharedCacheMap"} ne $SharedCacheMap && $Object->{"by"} ne "IRP_MJ_CREATE";
376 $SectionObjectPointer{$SectionObjectPointer}={
377 "SectionObjectPointer"=>$SectionObjectPointer,
378 "SharedCacheMap"=>$SharedCacheMap,
387 my $BObject=$Bcb{$Bcb};
388 warn "Non-existent Bcb $Bcb" if !$BObject;
392 sub Bcb_conflict($;@)
394 my($CObject,@Bcb_list)=@_;
398 "map"=>$CObject->{"map"},
399 map(("arg".($arg++)=>$_),@Bcb_list),
400 %{$CObject->{"pin"}},
403 my $BufferBase; # relativized to FileOffset 0
405 while (my($key,$val)=each(%check)) {
406 next if !defined $val;
407 warn "Conflicting Bcb $val of keys $key and ".$reversed{$val}." of SharedCacheMap ".$CObject->{"SharedCacheMap"}
409 # Buffer base should match even between 'map's and 'pin's
410 # as the data are always mapped only once.
411 if (my $BObject=BObject $val) {
412 my $Buffer=eval $BObject->{"Buffer"};
413 $Buffer-=eval($BObject->{"FileOffset"}) if exists $BObject->{"FileOffset"};
414 warn "Non-matching Bcb ".$BObject->{"type"}." $val Buffer base ".tohex($Buffer)
415 ." with Bcb ".$Bcb{$BufferBase_val}->{"type"}." $BufferBase_val BufferBase ".tohex($BufferBase)
416 if defined($BufferBase) && $Buffer!=$BufferBase;
418 $BufferBase_val=$val;
420 $reversed{$val}=$key;
424 # New $BObject will always be forced as the last stored reference.
427 my($BObject,$ref)=@_;
429 return if !(my $CObject=CObject $BObject->{"SharedCacheMap"});
430 my $type=$BObject->{"type"};
431 my $Bcb=$BObject->{"Bcb"};
433 my $BObject2=$Bcb{$$ref};
434 warn "new $type Bcb $Bcb != old $type Bcb $$ref"
436 warn "new $type $Bcb type ".$BObject->{"type"}." != old $type $$ref type ".$BObject2->{"type"}
437 if $BObject->{"type"} ne $BObject2->{"type"};
438 warn "new $type $Bcb Buffer ".$BObject->{"Buffer"}." != old $type $$ref Buffer ".$BObject2->{"Buffer"}
439 if $BObject->{"Buffer"} ne $BObject2->{"Buffer"};
441 if ($$ref && $$ref eq $Bcb) {
442 $BObject->{"ref_count"}+=$Bcb{$$ref}->{"ref_count"};
445 $Bcb{$Bcb}=$BObject; # &Bcb_conflict needs this reference
446 Bcb_conflict $CObject,$Bcb;
452 my($SharedCacheMap,$FileOffset,$Length)=@_;
454 return if !(my $CObject=CObject $SharedCacheMap);
455 if (defined($FileOffset) && defined($Length)) {
456 warn "Mapping data (end ".tohex($FileOffset+$Length).") out of FileSize ".$CObject->{"FileSize"}
457 if $FileOffset+$Length>eval($CObject->{"FileSize"});
459 $Object->{"SharedCacheMap"}=$CObject->{"SharedCacheMap"};
460 if (defined $FileOffset) {
461 $Object->{"FileOffset"}=tohex($FileOffset);
463 $Object->{"type"}="map";
464 $Object->{"ref_count"}=1;
467 sub map_new_from_FileObject($;$$)
469 my($FileObject,$FileOffset,$Length)=@_;
471 return if !(my $CObject=CObject_from_FileObject $FileObject);
472 map_new $CObject->{"SharedCacheMap"},$FileOffset,$Length;
475 sub map_new_leave($;$)
479 $Object->{"Bcb"}=$Bcb;
480 return if !(my $CObject=CObject $Object->{"SharedCacheMap"});
482 if (defined $Buffer) {
483 $Object->{"Buffer"}=tohex(eval($Buffer)-(eval($Object->{"FileOffset"}) || 0));
485 delete $Object->{"FileOffset"};
487 my $ref=\$CObject->{"map"};
488 # There may exist some pin bcbs even if we are creating the new map bcb.
489 Bcb_checkref $Object,$ref;
494 my($FileObject,$FileOffset,$Length)=@_;
496 map_new_from_FileObject $FileObject,$FileOffset,$Length;
499 sub CcMapData_leave($$)
503 map_new_leave $Bcb,$Buffer;
508 my($FileObject,$FileOffset,$Length)=@_;
510 return if !(my $CObject=CObject_from_FileObject $FileObject);
511 warn "Pinning of non-PinAccess FileObject $FileObject" if !$CObject->{"PinAccess"};
512 warn "Mapping data (end ".tohex($FileOffset+$Length).") out of FileSize ".$CObject->{"FileSize"}
513 if $FileOffset+$Length>eval($CObject->{"FileSize"});
514 warn "Pinning Length ".tohex($Length)." > 0x1000" if $Length>0x1000;
515 warn "Pinning across file page (start=".tohex($FileOffset).",end-1=".tohex($FileOffset+$Length-1).")"
516 if ($FileOffset&~0xFFF)!=(($FileOffset+$Length-1)&~0xFFF);
517 $Object->{"SharedCacheMap"}=$CObject->{"SharedCacheMap"};
518 $Object->{"FileOffset"}=tohex($FileOffset);
519 $Object->{"type"}="pin";
520 $Object->{"ref_count"}=1;
523 sub pin_new_leave($$)
527 $Object->{"Bcb"}=$Bcb;
528 return if !(my $CObject=CObject $Object->{"SharedCacheMap"});
529 $Object->{"Buffer"}=tohex(eval($Buffer)-(eval($Object->{"FileOffset"})&0xFFF));
530 my $shift=eval($Object->{"FileOffset"})&0xFFF;
531 $Object->{"FileOffset"}=tohex(eval($Object->{"FileOffset"})-$shift);
532 $Object->{"Buffer"}=tohex(eval($Buffer)-$shift);
534 my $ref=\$CObject->{"pin"}{$Object->{"FileOffset"}};
535 # There may not exist map bcb even if we are creating the new pin bcb.
536 Bcb_checkref $Object,$ref;
541 my($FileObject,$FileOffset,$Length)=@_;
543 pin_new $FileObject,$FileOffset,$Length;
546 sub CcPinRead_leave($$)
550 pin_new_leave $Bcb,$Buffer;
553 sub CcPreparePinWrite($$$)
555 my($FileObject,$FileOffset,$Length)=@_;
557 pin_new $FileObject,$FileOffset,$Length;
560 sub CcPreparePinWrite_leave($$)
564 pin_new_leave $Bcb,$Buffer;
567 sub CcPinMappedData($$$)
569 my($FileObject,$FileOffset,$Length)=@_;
571 pin_new $FileObject,$FileOffset,$Length;
574 sub CcPinMappedData_leave($)
578 return if !(my $CObject=CObject $Object->{"SharedCacheMap"});
579 do { warn "CcPinMappedData() with Bcb $Bcb on non-CcMapData()ed SharedCacheMap ".$CObject->{"SharedCacheMap"}; return; }
580 if !(my $mapBcb=$CObject->{"map"});
581 return if !(my $BmapObject=BObject $mapBcb);
582 my $Buffer=tohex(eval($BmapObject->{"Buffer"})+eval($Object->{"FileOffset"}));
584 my $Bcb2=$CObject->{"pin"}{tohex(eval($Object->{"FileOffset"})&~0xFFF)};
585 my $BObject2=BObject $Bcb2 if $Bcb2;
586 if ($BObject2 && $BObject2->{"CcPinMappedData_double"}
587 && eval($BObject2->{"CcPinMappedData_double"})==eval($Object->{"FileOffset"})) { # unaligned yet
588 my $BmapBuffer=eval($BmapObject->{"Buffer"})+(eval($Object->{"FileOffset"})&~0xFFF);
589 warn "CcPinMappedData-double cludge non-matching new Bcb $Bcb != old Bcb ".$BObject2->{"Bcb"}
590 if $Bcb ne $BObject2->{"Bcb"};
591 warn "CcPinMappedData-double cludge non-matching Buffer new Bcb $Bcb Buffer $BmapBuffer"
592 ." != old Bcb ".$BObject2->{"Bcb"}." Buffer ".$BObject2->{"Buffer"}
593 if eval($BmapBuffer)!=eval($BObject2->{"Buffer"});
597 # It appears as this cludge is not needed:
598 # $Object->{"CcPinMappedData_double"}=$Object->{"FileOffset"}; # unaligned yet
600 pin_new_leave $Bcb,$Buffer;
601 # print STDERR "$.:".Dumper($Object);
604 sub CcSetDirtyPinnedData($$)
608 return if !(my $BObject=BObject $Bcb);
609 delete $BObject->{"CcPinMappedData_double"};
616 return if !(my $BObject=BObject $Bcb);
617 map_new $BObject->{"SharedCacheMap"};
618 $Object->{"Buffer"}=tohex(eval($BObject->{"Buffer"})-eval($BObject->{"FileOffset"} || 0));
621 sub CcRemapBcb_leave($)
632 return if !(my $BObject=BObject $Bcb);
633 delete $BObject->{"CcPinMappedData_double"};
634 return if --$BObject->{"ref_count"};
635 return if !(my $CObject=CObject $BObject->{"SharedCacheMap"});
636 if ($BObject->{"type"} eq "map") {
637 for my $pin (values(%{$CObject->{"pin"}})) {
638 warn "unpin map but CcPinMappedData pin $pin still exists"
639 if $Bcb{$pin}->{"by"} eq "CcPinMappedData";
642 for my $ref ($BObject->{"type"} eq "map" ? \$CObject->{"map"} : \$CObject->{"pin"}{$BObject->{"FileOffset"}}) {
643 warn "Final unpin but ".$BObject->{"type"}." Bcb $Bcb not registered"
644 ." in SharedCacheMap ".$CObject->{"SharedCacheMap"}." ref ".($$ref || "<undef>")
645 if !defined($BObject->{"OwnerPointer"}) && !($$ref && $$ref eq $Bcb);
646 if ($$ref && $$ref eq $Bcb) {
648 delete $CObject->{"pin"}{$BObject->{"FileOffset"}} if $BObject->{"type"} eq "pin";
661 sub CcUnpinDataForThread($)
668 sub CcSetBcbOwnerPointer($$)
670 my($Bcb,$OwnerPointer)=@_;
672 return if !(my $BObject=BObject $Bcb);
673 warn "CcSetBcbOwnerPointer() on map Bcb $Bcb" if $BObject->{"type"} ne "pin";
674 return if !(my $CObject=CObject $BObject->{"SharedCacheMap"});
675 warn "Double CcSetBcbOwnerPointer() on Bcb $Bcb" if defined $BObject->{"OwnerPointer"};
676 my $val=$CObject->{"pin"}{$BObject->{"FileOffset"}};
677 warn "CcSetBcbOwnerPointer() on unregistered pin Bcb $Bcb" if !$val || $val ne $Bcb;
678 delete $CObject->{"pin"}{$BObject->{"FileOffset"}} if $val && $val eq $Bcb;
679 $BObject->{"OwnerPointer"}=$OwnerPointer;
682 sub IRP_MJ_CLOSE_leave()
684 my $FileObject=$Object->{"data"}[0]{"FileObject"};
685 # # IRP_MJ_CLOSE of FileObject w/o CcInitializeCacheMap()?
686 # return if !$FileObject{$FileObject};
687 return if !(my $FObject=FObject $FileObject);
688 if (eval(my $SectionObjectPointer=$FObject->{"SectionObjectPointer"})) {
689 return if !(my $SObject=SObject $SectionObjectPointer);
690 my $SharedCacheMap=$SObject->{"SharedCacheMap"};
691 if (eval $SharedCacheMap) {
692 return if !(my $CObject=CObject $SObject->{"SharedCacheMap"});
693 # SharedCacheMap may still exist for FCB although this FileObject gets destroyed now.
694 # warn "SectionObjectPointer $SectionObjectPointer still exists during IRP_MJ_CLOSE"
695 # ." while SharedCacheMap ".$CObject->{"SharedCacheMap"}." ref_count ".$CObject->{"ref_count"}
696 # if $SectionObjectPointer && $CObject->{"ref_count"};
699 delete $FileObject{$FileObject};
704 my $hex='0x[\dA-F]+';
710 # We may get some foreign garbage without '\n' before our debug data line:
711 # Do not use '\bTraceFS' as there really can be precediny _any_ data.
712 s#^.*?TraceFS[(]($hex/$hex)[)]: ## or do { print "$_\n" if $filter; next; };
713 my($process_thread)=($1);
716 if (/^enter: (\w+)/) {
719 $Object->{"line_enter"}=$.;
720 $Object->{"process_thread"}=$process_thread;
721 push @{$enter_leave{$process_thread}},$Object;
723 elsif (/^leave: (\w+)/) {
724 warn "Empty pop stack during 'leave' of $1" if !($Object=pop @{$enter_leave{$process_thread}});
725 warn "Non-matching popped 'by' ".$Object->{"by"}." ne current 'leave' $1"
726 if $Object->{"by"} ne $1;
727 $Object->{"line_leave"}=$.;
729 elsif (my($FileObject,$FileName,$Flags,$SectionObjectPointer,$SharedCacheMap)=
730 /^FileObject=($hex): FileName=(?:NULL|'(.*)'),Flags=($hex),SectionObjectPointer=($hex),->SharedCacheMap=($hex)/) {
731 my $aref=$enter_leave{$process_thread};
732 warn "Empty stack during 'data' line" if !($Object=${$aref}[$#$aref]);
734 "FileObject"=>$FileObject,
735 "FileName"=>$FileName,
737 "SectionObjectPointer"=>$SectionObjectPointer,
738 "SharedCacheMap"=>$SharedCacheMap,
741 push @{$Object->{"data"}},$data;
742 my $isinit={ map(($_=>1),qw(
744 CcUninitializeCacheMap
746 )) }->{$Object->{"by"}};
748 if 1==@{$Object->{"data"}} || !$isinit;
750 # Prevent 'SharedCacheMap' 0->N change by CcInitializeCacheMap() called inside.
751 for my $ref (@$aref[0..$#$aref-1]) {
752 $ref->{"data"}[0]->{"SharedCacheMap"}=$SharedCacheMap;
755 if (2<=@{$Object->{"data"}}) {
756 my $data_prev=$Object->{"data"}[$#{$Object->{"data"}}-1];
757 for my $field (qw(FileObject FileName Flags),($isinit ? () : qw(SharedCacheMap))) {
758 next if !defined(my $prev=$data_prev->{$field});
759 next if !defined(my $now=$data->{$field});
760 my $by=$Object->{"by"};
761 if ($field eq "Flags") {
762 next if $by eq "IRP_MJ_CREATE" && $field eq "Flags";
763 my $FO_CLEANUP_COMPLETE=0x4000;
764 $now=tohex(eval($now)&~$FO_CLEANUP_COMPLETE) if $by eq "IRP_MJ_CLEANUP";
765 my $FO_FILE_FAST_IO_READ=0x80000;
766 $prev=tohex(eval($prev)&~$FO_FILE_FAST_IO_READ) if $by eq "IRP_MJ_CLEANUP";
767 $now=tohex(eval($now)&~$FO_FILE_FAST_IO_READ) if $by eq "IRP_MJ_READ" && !(eval($prev)&$FO_FILE_FAST_IO_READ);
768 my $FO_FILE_MODIFIED=0x1000;
769 $now=tohex(eval($now)&~$FO_FILE_MODIFIED) if $by eq "IRP_MJ_WRITE" && !(eval($prev)&$FO_FILE_MODIFIED);
770 my $FO_FILE_SIZE_CHANGED=0x2000;
771 $prev=tohex(eval($prev)&~$FO_FILE_MODIFIED)
772 if $by eq "IRP_MJ_SET_INFORMATION" && !(eval($now)&$FO_FILE_MODIFIED);
773 $prev=tohex(eval($prev)&~$FO_FILE_SIZE_CHANGED)
774 if $by eq "IRP_MJ_SET_INFORMATION" && !(eval($now)&$FO_FILE_SIZE_CHANGED);
776 next if $by eq "IRP_MJ_CLOSE" && $field eq "FileName";
777 $prev=~s#\\$## if $by eq "IRP_MJ_CREATE";
778 $prev="\\" if $by eq "IRP_MJ_CREATE" && $prev eq "";
779 $prev=~s#:.*## if $by eq "IRP_MJ_CREATE" && $prev ne $now;
780 next if $field eq "SharedCacheMap" && !SharedCacheMap_valid $prev && !SharedCacheMap_valid $now;
781 do { warn "Changed data field $field, prev=".$data_prev->{$field}.", now=".$data->{$field}." by $by";
782 # print STDERR Dumper $data_prev,$data;
790 /^leave: IRP_MJ_\w+: r=($hex)/) {
791 # Failed requests should make no consequences.
795 if (my($FileObject,$AllocationSize,$FileSize,$ValidDataLength,$PinAccess)=
796 /^enter: CcInitializeCacheMap: FileObject=($hex),FileSizes,->AllocationSize=($hex),->FileSize=($hex),->ValidDataLength=($hex),PinAccess=([01]),/) {
797 CcInitializeCacheMap $FileObject,eval($AllocationSize),eval($FileSize),eval($ValidDataLength),eval($PinAccess);
800 if (/^leave: CcInitializeCacheMap\b/) {
801 CcInitializeCacheMap_leave;
805 if (my($FileObject,$TruncateSize)=
806 /^enter: CcUninitializeCacheMap: FileObject=($hex),TruncateSize=($hex),/) {
807 CcUninitializeCacheMap $FileObject,eval($TruncateSize);
811 /^leave: CcUninitializeCacheMap: r=([01])/) {
812 CcUninitializeCacheMap_leave $r;
816 if (my($FileObject,$AllocationSize,$FileSize,$ValidDataLength)=
817 /^enter: CcSetFileSizes: FileObject=($hex),FileSizes,->AllocationSize=($hex),->FileSize=($hex),->ValidDataLength=($hex)/) {
818 CcSetFileSizes $FileObject,eval($AllocationSize),eval($FileSize),eval($ValidDataLength);
822 if (/^leave: IRP_MJ_CREATE\b/) {
827 if (/^leave: IRP_MJ_CLOSE\b/) {
832 if (my($FileObject,$FileOffset,$Length)=
833 /^enter: CcMapData: FileObject=($hex),FileOffset=($hex),Length=($hex),Flags=0x1/) {
834 CcMapData $FileObject,eval($FileOffset),eval($Length);
837 if (my($Bcb,$Buffer)=
838 /^leave: CcMapData: r=1,Bcb=($hex),Buffer=($hex)/) {
839 CcMapData_leave $Bcb,$Buffer;
843 if (my($FileObject,$FileOffset,$Length)=
844 /^enter: CcPinRead: FileObject=($hex),FileOffset=($hex),Length=($hex),Flags=0x1/) {
845 CcPinRead $FileObject,eval($FileOffset),eval($Length);
848 if (my($Bcb,$Buffer)=
849 /^leave: CcPinRead: r=1,Bcb=($hex),Buffer=($hex)/) {
850 CcPinRead_leave $Bcb,$Buffer;
854 if (my($FileObject,$FileOffset,$Length)=
855 /^enter: CcPreparePinWrite: FileObject=($hex),FileOffset=($hex),Length=($hex),Zero=([01]),Flags=0x1/) {
856 CcPreparePinWrite $FileObject,eval($FileOffset),eval($Length);
859 if (my($Bcb,$Buffer)=
860 /^leave: CcPreparePinWrite: r=1,Bcb=($hex),Buffer=($hex)/) {
861 CcPreparePinWrite_leave $Bcb,$Buffer;
865 if (my($FileObject,$FileOffset,$Length)=
866 /^enter: CcPinMappedData: FileObject=($hex),FileOffset=($hex),Length=($hex),Flags=0x1/) {
867 CcPinMappedData $FileObject,eval($FileOffset),eval($Length);
871 /^leave: CcPinMappedData: r=1,Bcb=($hex)/) {
872 CcPinMappedData_leave $Bcb;
876 if (my($BcbVoid,$Lsn)=
877 /^enter: CcSetDirtyPinnedData: BcbVoid=($hex),Lsn=($hex)/) {
878 CcSetDirtyPinnedData $BcbVoid,$Lsn;
883 /^enter: CcRemapBcb: Bcb=($hex)/) {
888 /^leave: CcRemapBcb: r=($hex)/) {
894 /^enter: CcUnpinData: Bcb=($hex)/) {
899 /^enter: CcUnpinDataForThread: Bcb=($hex)/) {
900 CcUnpinDataForThread $Bcb;
904 if (my($Bcb,$OwnerPointer)=
905 /^enter: CcSetBcbOwnerPointer: Bcb=($hex),OwnerPointer=($hex)/) {
906 CcSetBcbOwnerPointer $Bcb,$OwnerPointer;
910 print "$_\n" if $filter;
912 for my $FileObject (keys(%FileObject)) {
913 warn "EXIT: still CcInitializeCacheMap FileObject $FileObject";
914 next if !(my $FObject=FObject $FileObject);