A lot of misc adjustments, pretty broken now.
authorshort <>
Tue, 12 Aug 2003 17:41:01 +0000 (17:41 +0000)
committershort <>
Tue, 12 Aug 2003 17:41:01 +0000 (17:41 +0000)
src/TraceFS/checktrace.pl

index 077a9cd..1869469 100755 (executable)
@@ -52,6 +52,7 @@ my $ntfs_blocksize=0x200;
 # $SharedCacheMap{$SharedCacheMap}{"LogHandle"}="0x12345678" optional;
 # $SharedCacheMap{$SharedCacheMap}{"AcquireForLazyWrite"}=0;   # count
 # $SharedCacheMap{$SharedCacheMap}{"in_memory"}{"0x4000"}=1;   # mapped page?
+# $SharedCacheMap{$SharedCacheMap}{"Buffer"}="0x12345678";
 # $LogHandle{$LogHandle}{"LogHandle"}="0x12345678";
 # $Bcb{$Bcb}{"Bcb"}="0x12345678";
 # $Bcb{$Bcb}{"SharedCacheMap"}="0x12345678";
@@ -150,6 +151,8 @@ my($CObject)=@_;
                        if !(my $LObject=$LogHandle{$LogHandle});
                # Do not delete $LogHandle as it may be used by many SharedCacheMap-s
                }
+       warn "ref_count=".$CObject->{"ref_count"}." of SharedCacheMap $SharedCacheMap during its deletion"
+                       if $CObject->{"ref_count"};
        delete $SharedCacheMap{$SharedCacheMap};
 }
 
@@ -212,7 +215,12 @@ my($data)=@_;
                }
        return if !$FileObject{$data->{"FileObject"}};
        return if !(my $FObject=FObject $data->{"FileObject"});
-       return if !(my $SObject=SObject $FObject->{"SectionObjectPointer"});
+       $SectionObjectPointer=$FObject->{"SectionObjectPointer"};
+       return if !(my $SObject=SObject $SectionObjectPointer);
+       warn "FileObject ".$FObject->{"FileObject"}
+                                       ." expected SectionObjectPointer $SectionObjectPointer"
+                                       ." but found SectionObjectPointer ".$data->{"SectionObjectPointer"}
+                       if $SectionObjectPointer ne $data->{"SectionObjectPointer"};
        my $SharedCacheMap=$SObject->{"SharedCacheMap"};
        warn "FileObject ".$FObject->{"FileObject"}." SectionObjectPointer ".$SObject->{"SectionObjectPointer"}
                                        ." expected SharedCacheMap $SharedCacheMap"
@@ -245,8 +253,11 @@ sub CcInitializeCacheMap_leave()
        if (!SharedCacheMap_valid $Object->{"data"}[0]{"SharedCacheMap"} && $old) {
                # SharedCacheMap got deleted in the meantime
                delete_CObject CObject $SharedCacheMap;
-               my $SObject=SObject $Object->{"data"}[0]{"SectionObjectPointer"};
-               $SObject->{"SharedCacheMap"}=tohex(0);
+               # Either it got deleted of some foreign SectionObjectPointer
+               # or of the current one:
+               if (my $SObject=$SectionObjectPointer{$Object->{"data"}[0]{"SectionObjectPointer"}}) {
+                       $SObject->{"SharedCacheMap"}=tohex(0);
+                       }
                $old=undef();
                }
        if (!$old != !SharedCacheMap_valid $Object->{"data"}[0]{"SharedCacheMap"}) {
@@ -371,8 +382,11 @@ my($FileObject,$AllocationSize,$FileSize,$ValidDataLength)=@_;
                do { warn "Existing pin $_ of FileObject $FileObject SharedCacheMap $SharedCacheMap during CcSetAllocationSizes(),"
                                                ." AllocationSize=".$CObject->{"AllocationSize"} if $_; }
                                for (values(%{$CObject->{"pin"}}));
-               # Is it valid? It does not change our output in any way:
-               delete $CObject->{"in_memory"};
+               # Do not: delete $CObject->{"in_memory"};
+               # as its keep is required by W32. Squeeze it instead:
+               $CObject->{"in_memory"}={ map({
+                               (eval($_)<$AllocationSize ? ($_=>1) : ());
+                               } keys(%{$CObject->{"in_memory"}})) };
                }
        # $ValidDataLength can be > $CObject->{"FileSize"};
        warn "ValidDataLength ".tohex($ValidDataLength)." > FileSize ".tohex($FileSize)
@@ -384,6 +398,7 @@ my($FileObject,$AllocationSize,$FileSize,$ValidDataLength)=@_;
                        if $FileSize>$AllocationSize;
        $CObject->{"FileSize"}=tohex($FileSize);
        $CObject->{"AllocationSize"}=tohex($AllocationSize);
+       delete $CObject->{"Buffer"} if !eval $AllocationSize;
 }
 
 sub IRP_MJ_CREATE_leave()
@@ -419,7 +434,10 @@ my($Bcb)=@_;
 
        cluck if !defined $Bcb;
        my $BObject=$Bcb{$Bcb};
-       warn "Non-existent Bcb $Bcb" if !$BObject;
+       if (!$BObject) {
+               my($package,$filename,$line,$subroutine)=caller 0;
+               warn "Non-existent Bcb $Bcb by line $line"
+               }
        return $BObject;
 }
 
@@ -428,6 +446,7 @@ sub delete_BObject($)
 my($BObject)=@_;
 
        my $Bcb=$BObject->{"Bcb"};
+#      warn "XXX delete_BObject 0x811799B8 line $. BObject=".Dumper $BObject if $Bcb eq "0x811799B8";
        warn "Deleting ref_count=".$BObject->{"ref_count"}." Bcb $Bcb" if $BObject->{"ref_count"};
        # Do not: warn "Deleting dirty Bcb $Bcb" if $BObject->{"dirty"};
        # as it is valid to allow sanity check below.
@@ -460,6 +479,8 @@ my($BObject)=@_;
                        }
                }
        delete $Bcb{$Bcb};
+#      warn "XXX delete_BObject 0x811799B8 line $. CObject=".Dumper $CObject if $Bcb eq "0x811799B8";
+       CObject_Buffer_check($CObject);
 }
 
 sub MObject($)
@@ -472,6 +493,23 @@ my($MdlChain)=@_;
        return $MObject;
 }
 
+sub CObject_Buffer_check($)
+{
+my($CObject)=@_;
+
+       my $any;
+       for my $BObject ($CObject->{"map"},values(%{$CObject->{"pin"}})) {
+               # There may exist OwnerPointer-ed or dirty&unreffed standalone Bcbs bound to this SharedCacheMap
+               # but these are not important for Buffer reset.
+               next if !$BObject;
+               $any=1;
+               last;
+               }
+       if (!$any) {
+               delete $CObject->{"Buffer"};
+               }
+}
+
 sub Bcb_conflict($;@)
 {
 my($CObject,@Bcb_list)=@_;
@@ -485,17 +523,29 @@ my($CObject,@Bcb_list)=@_;
        my %reversed;
        my $BufferBase; # relativized to FileOffset 0
        my $BufferBase_val;
+       if ($CObject->{"Buffer"}) {
+               $BufferBase=eval $CObject->{"Buffer"};
+               $BufferBase_val="SharedCacheMap Buffer";
+               }
        while (my($key,$val)=each(%check)) {
                next if !defined $val;
                warn "Conflicting Bcb $val of keys $key and ".$reversed{$val}." of SharedCacheMap ".$CObject->{"SharedCacheMap"}
                                if $reversed{$val};
                # Buffer base should match even between 'map's and 'pin's
                # as the data are always mapped only once.
-               if (my $BObject=BObject $val) {
+               my $BObject=$Bcb{$val};
+               warn "Non-existent key=$key Bcb $val"
+#                                              ." XXX line $. CObject=".Dumper $CObject
+                               if !$BObject;
+               if ($BObject) {
                        my $Buffer=eval $BObject->{"Buffer"};
                        $Buffer-=eval($BObject->{"FileOffset"}) if exists $BObject->{"FileOffset"};
+                       warn "INTERNAL: Non page aligned Buffer ".tohex($Buffer)." of Bcb $val"
+                                       if $Buffer & 0xFFF;
                        warn "Non-matching Bcb ".$BObject->{"type"}." $val Buffer base ".tohex($Buffer)
-                                                       ." with Bcb ".$Bcb{$BufferBase_val}->{"type"}." $BufferBase_val BufferBase ".tohex($BufferBase)
+                                                       ." with".($BufferBase_val=~/^SharedCacheMap / ? "" : " Bcb ".$Bcb{$BufferBase_val}->{"type"})
+                                                       ." $BufferBase_val BufferBase ".tohex($BufferBase)."; SharedCacheMap=".$CObject->{"SharedCacheMap"}
+#                                                      ." XXX line $. ".Dumper($CObject,\%Bcb)
                                        if defined($BufferBase) && $Buffer!=$BufferBase;
                        $BufferBase=$Buffer;
                        $BufferBase_val=$val;
@@ -516,21 +566,23 @@ my($BObject,$ref)=@_;
                my $BObject2=$Bcb{$$ref};
                warn "new $type Bcb $Bcb != old ".$BObject2->{"type"}." Bcb $$ref";
                delete_BObject $BObject2;
-               warn "INTERNAL: Trailing ref to Bcb $$ref" if $$ref;
                }
-       if ($$ref) {
-               my $BObject2=$Bcb{$$ref};
-               warn "new $type $Bcb type ".$BObject->{"type"}." != old type $type $$ref type ".$BObject2->{"type"}
+       if ($Bcb{$Bcb}) {
+               my $BObject2=$Bcb{$Bcb};
+               warn "new $type $Bcb type ".$BObject->{"type"}." != old type $type $Bcb type ".$BObject2->{"type"}
                                if $BObject->{"type"} ne $BObject2->{"type"};
-               warn "new $type $Bcb Buffer ".$BObject->{"Buffer"}." != old $type $$ref Buffer ".$BObject2->{"Buffer"}
+               warn "new $type $Bcb Buffer ".($BObject->{"Buffer"} || "<undef>")
+                                               ." != old $type $Bcb Buffer ".($BObject2->{"Buffer"} || "<undef>")
+#                                              ." XXX line $. ".Dumper($BObject,$BObject2)
                                if $BObject->{"Buffer"} ne $BObject2->{"Buffer"};
                }
-       if ($$ref && $$ref eq $Bcb) {
-               $BObject->{"ref_count"}+=$Bcb{$$ref}->{"ref_count"};
-               $$ref=undef();
+       if ($Bcb{$Bcb}) {
+               warn "Equal Bcb?" if $Bcb{$Bcb} eq $BObject;
+               $Bcb{$Bcb}->{"ref_count"}+=$BObject->{"ref_count"};
+               $BObject=$Bcb{$Bcb};
                }
        $Bcb{$Bcb}=$BObject;    # &Bcb_conflict needs this reference
-       Bcb_conflict $CObject,$Bcb;
+       Bcb_conflict $CObject,($$ref && $$ref eq $Bcb ? () : ($Bcb));
        $$ref=$Bcb;
 }
 
@@ -570,6 +622,8 @@ my($Bcb,$Buffer)=@_;
                $Object->{"Buffer"}=tohex(eval($Buffer)-(eval($Object->{"FileOffset"}) || 0));
                }
        delete $Object->{"FileOffset"};
+       $CObject->{"Buffer"}=$Object->{"Buffer"} if !$CObject->{"Buffer"};
+       warn "Unknown Buffer during map_new_leave" if !$Object->{"Buffer"};
 
        my $ref=\$CObject->{"map"};
        # There may exist some pin bcbs even if we are creating the new map bcb.
@@ -618,6 +672,9 @@ my($Bcb,$Buffer)=@_;
        $Object->{"FileOffset"}=tohex(eval($Object->{"FileOffset"})-$shift);
        $Object->{"Buffer"}=tohex(eval($Buffer)-$shift);
 
+       my $Buffer_base=tohex(eval($Object->{"Buffer"})-eval($Object->{"FileOffset"}));
+       $CObject->{"Buffer"}=$Buffer_base if !$CObject->{"Buffer"};
+
        warn "pin_new_leave() while FileOffset ".$Object->{"FileOffset"}." not in_memory"
                                        ." of SharedCacheMap ".$CObject->{"SharedCacheMap"}
                        if !$CObject->{"in_memory"}{$Object->{"FileOffset"}};
@@ -625,6 +682,7 @@ my($Bcb,$Buffer)=@_;
        my $ref=\$CObject->{"pin"}{$Object->{"FileOffset"}};
        # There may not exist map bcb even if we are creating the new pin bcb.
        Bcb_checkref $Object,$ref;
+#      warn "XXX pin_new_leave line $. BObject=".Dumper $Object if $Bcb eq "0x811799B8";
 }
 
 sub CcPinRead($$$)
@@ -675,13 +733,16 @@ sub CcPinMappedData_leave($)
 my($Bcb)=@_;
 
        return if !(my $CObject=CObject $Object->{"SharedCacheMap"});
-       do { warn "CcPinMappedData() with Bcb $Bcb on non-CcMapData()ed SharedCacheMap ".$CObject->{"SharedCacheMap"}; return; }
-                       if !(my $mapBcb=$CObject->{"map"});
-       return if !(my $BmapObject=BObject $mapBcb);
-       my $Buffer=tohex(eval($BmapObject->{"Buffer"})+eval($Object->{"FileOffset"}));
+       # Do not: do { warn "CcPinMappedData() with Bcb $Bcb on non-CcMapData()ed SharedCacheMap ".$CObject->{"SharedCacheMap"}; return; }
+       #             if !$CObject->{"map"};
+       # as the only requirement of CcPinMappedData() is to have all the pages already 'in_memory'.
+       my $Buffer=$CObject->{"Buffer"};
+       warn "SharedCacheMap ".$CObject->{"SharedCacheMap"}." Buffer not known during CcPinMappedData()"
+                       if !$Buffer;
+       $Buffer=tohex(eval($Buffer)+eval($Object->{"FileOffset"})) if $Buffer;
 
-       my $Bcb2=$CObject->{"pin"}{tohex(eval($Object->{"FileOffset"})&~0xFFF)};
-       my $BObject2=BObject $Bcb2 if $Bcb2;
+#      my $Bcb2=$CObject->{"pin"}{tohex(eval($Object->{"FileOffset"})&~0xFFF)};
+#      my $BObject2=BObject $Bcb2 if $Bcb2;
 
        pin_new_leave $Bcb,$Buffer;
 }
@@ -755,7 +816,7 @@ my($ByteOffset,$Lsn_check)=@_;
                                # Direct IRP_MJ_WRITE can be from callbacked 'FlushToLsnRoutine'.
                                # It can occur even from other callbacks ('DirtyPageRoutine' etc.)
                                # but it was not needed here yet.
-                               } if @$EnterLeave && !(${$EnterLeave}[$#$EnterLeave]->{"by"} eq "FlushToLsnRoutine");
+                               } if @$EnterLeave && !(${$EnterLeave}[$#$EnterLeave]->{"by"}=~/^(?:FlushToLsnRoutine\b|IRP_MJ_)/);
                warn "Non-Bcb IRP_MJ_WRITE ByteOffset=$ByteOffset but FlushToLsnRoutine was preceding"
                                if $FlushToLsnRoutine;
                return;
@@ -777,13 +838,16 @@ my($ByteOffset,$Lsn_check)=@_;
                warn "Missing preceding FlushToLsnRoutine during IRP_MJ_WRITE of Bcb $Bcb with Lsn ".$BObject->{"Lsn"}
                                if $BObject->{"Lsn"};
                }
-       warn "IRP_MJ_WRITE with FlushToLsnRoutine although not in AcquireForLazyWrite"
-                       if $FlushToLsnRoutine && !($CObject->{"AcquireForLazyWrite"}>=1);
+       warn "IRP_MJ_WRITE with FlushToLsnRoutine although not in AcquireForLazyWrite or CcFlushCache"
+                       if $FlushToLsnRoutine && !((1==@$EnterLeave && ${$EnterLeave}[0]->{"by"} eq "CcFlushCache")
+                                               || (2==@$EnterLeave && ${$EnterLeave}[0]->{"by"}=~/^IRP_MJ_/
+                                                                   && ${$EnterLeave}[1]->{"by"} eq "CcFlushCache"))
+                                             && !($CObject->{"AcquireForLazyWrite"}>=1);
        warn "IRP_MJ_WRITE not the toplevel function"
                                                ." (".join(",",map({ $_->{"line_enter"}.":".$_->{"by"}; } @$EnterLeave)).")"
                        if !(0==@$EnterLeave
                         || (1==@$EnterLeave && ${$EnterLeave}[0]->{"by"} eq "CcFlushCache")
-                        || (2==@$EnterLeave && ${$EnterLeave}[0]->{"by"} eq "IRP_MJ_FILE_SYSTEM_CONTROL"
+                        || (2==@$EnterLeave && ${$EnterLeave}[0]->{"by"}=~/^IRP_MJ_/
                                             && ${$EnterLeave}[1]->{"by"} eq "CcFlushCache"));
        my $CcFlushCache=${$EnterLeave}[$#$EnterLeave];
        if ($CcFlushCache && $CcFlushCache->{"by"} eq "CcFlushCache") {
@@ -800,6 +864,12 @@ my($ByteOffset,$Lsn_check)=@_;
 
 sub IRP_MJ_WRITE_leave()
 {
+       return if !(my $CObject=CObject $Object->{"data"}[0]{"SharedCacheMap"});
+       # toplevel IRP_MJ_WRITE has no requirements
+       return if 0==@$EnterLeave
+                       # We do not need any outer function, just 'AcquireForLazyWrite' is enough
+                       # for flushing Cache Manager buffers by some its LazyWriter task.
+                       && !$CObject->{"AcquireForLazyWrite"};
        do { warn "Length $_ not divisible by 0x1000" if eval($_)%0x1000; } for ($Object->{"WRITE"}{"Length"});
        my @Lsn_check;
        for my $reloffs (0..(eval($Object->{"WRITE"}{"Length"})/0x1000)-1) {
@@ -822,7 +892,7 @@ sub IRP_MJ_WRITE_leave()
 sub IRP_MJ_READ_leave()
 {
        # toplevel IRP_MJ_READ has no requirements
-       return if (0==@$EnterLeave);
+       return if 0==@$EnterLeave;
        my @stack=map({ $_->{"by"}=~/^IRP_MJ_/ ? () : $_ } @$EnterLeave);
        my $opObject=$stack[0] if 1==@stack;
        warn "IRP_MJ_READ not the expected function stack"
@@ -859,7 +929,10 @@ my($SectionObjectPointer,$SharedCacheMap,$FileOffset,$Length,$UninitializeCacheM
        warn "Not yet implemented ranged CcPurgeCacheSection()" if !$all;
        do { warn "Existing map Bcb $_ during CcPurgeCacheSection()" if $_; } for ($CObject->{"map"});
        do { warn "Existing pin Bcb $_ during CcPurgeCacheSection()" if $_; } for (values(%{$CObject->{"pin"}}));
+       # Primary goal of this function:
        delete $CObject->{"in_memory"};
+       # Really needed:
+       delete $CObject->{"Buffer"};
 }
 
 sub CcFlushCache($$$$)
@@ -878,7 +951,7 @@ my($Status,$Information)=@_;
        warn "CcFlushCache() not the toplevel function"
                                                ." (".join(",",map({ $_->{"line_enter"}.":".$_->{"by"}; } @$EnterLeave)).")"
                        if !(0==@$EnterLeave
-                        || (1==@$EnterLeave && ${$EnterLeave}[0]->{"by"} eq "IRP_MJ_FILE_SYSTEM_CONTROL"));
+                        || (1==@$EnterLeave && ${$EnterLeave}[0]->{"by"}=~/^IRP_MJ_/));
        if ($Status ne "0x".("F"x8) || $Information ne "0x".("F"x8)) {
                warn "Unexpected Status $Status" if eval $Status;
                warn "Unexpected Information $Information while CcFlushCached=".$Object->{"CcFlushCached"}
@@ -992,6 +1065,7 @@ my($Bcb)=@_;
                                                && !$BObject->{"OwnerPointer"};
                delete $CObject->{"pin"}{$BObject->{"FileOffset"}}
                                if $CObject->{"pin"}{$BObject->{"FileOffset"}} && ($CObject->{"pin"}{$BObject->{"FileOffset"}} eq $Bcb);
+               CObject_Buffer_check $CObject;
                return;
                }
        delete_BObject $BObject;
@@ -1023,6 +1097,7 @@ my($Bcb,$OwnerPointer)=@_;
        warn "CcSetBcbOwnerPointer() on unregistered pin Bcb $Bcb" if !$val || $val ne $Bcb;
        delete $CObject->{"pin"}{$BObject->{"FileOffset"}} if $val && $val eq $Bcb;
        $BObject->{"OwnerPointer"}=$OwnerPointer;
+       CObject_Buffer_check $CObject;
 }
 
 sub IRP_MJ_CLOSE_leave()