my %Bcb;
my %MdlChain;
my %LastLeave; # $ProcessThread=>[$Object,$Object,...]
-my $LastLeave; # ref copy for the current $ProcessThread
+my $LastLeave; # ref copy of the last item for the current $ProcessThread
my $ProcessThread;
my %EnterLeave;
+my $EnterLeave; # ref copy of the list for the current $ProcessThread
END {
print Data::Dumper->Dump([\%FileObject,\%SectionObjectPointer,\%SharedCacheMap,\%Bcb],
}
if (!@Bcbs) {
do {
- warn "Non-Bcb IRP_MJ_WRITE ByteOffset=$ByteOffset but some functions"
- ." (".join(",",map({ $_->{"line_enter"}.":".$_->{"by"}; } @{$EnterLeave{$ProcessThread}})).")"
- ." are nested:";
+ warn "Non-Bcb IRP_MJ_WRITE ByteOffset=$ByteOffset as non-toplevel function"
+ ." (".join(",",map({ $_->{"line_enter"}.":".$_->{"by"}; } @$EnterLeave)).")";
# warn Dumper $CObject;
# 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{$ProcessThread}}
- && !(${$EnterLeave{$ProcessThread}}[$#{$EnterLeave{$ProcessThread}}]->{"by"} eq "FlushToLsnRoutine");
+ } if @$EnterLeave && !(${$EnterLeave}[$#$EnterLeave]->{"by"} eq "FlushToLsnRoutine");
warn "Non-Bcb IRP_MJ_WRITE ByteOffset=$ByteOffset but FlushToLsnRoutine was preceding"
if $FlushToLsnRoutine;
return;
}
warn "IRP_MJ_WRITE with FlushToLsnRoutine although not in AcquireForLazyWrite"
if $FlushToLsnRoutine && !($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"
+ && ${$EnterLeave}[1]->{"by"} eq "CcFlushCache"));
+ my $CcFlushCache=${$EnterLeave}[$#$EnterLeave];
+ if ($CcFlushCache && $CcFlushCache->{"by"} eq "CcFlushCache") {
+ $CcFlushCache->{"CcFlushCached"}++;
+ if ($CcFlushCache->{"FileOffset"} ne "0x".("F"x8) || $CcFlushCache->{"Length"} ne "0x0") {
+ warn "IRP_MJ_WRITE outside of range of active CcFlushCache()"
+ if eval($ByteOffset)< eval($CcFlushCache->{"FileOffset"})
+ || eval($ByteOffset)>=eval($CcFlushCache->{"FileOffset"})+eval($CcFlushCache->{"Length"});
+ }
+ }
# Keep $BObject->{"dirty"} there for &delete_BObject sanity checks.
delete_BObject $BObject if $BObject->{"dirty"} && !$BObject->{"ref_count"};
}
}
}
+sub CcFlushCache($$$$)
+{
+my($SectionObjectPointer,$SharedCacheMap,$FileOffset,$Length)=@_;
+
+ $Object->{"CcFlushCached"}=0;
+ $Object->{"FileOffset"}=$FileOffset;
+ $Object->{"Length"}=$Length;
+}
+
+sub CcFlushCache_leave($$)
+{
+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"));
+ 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"}
+ if eval($Information)!=eval($Object->{"CcFlushCached"})*0x1000;
+ }
+}
+
sub CcPrepareMdlWrite($$$)
{
my($FileObject,$FileOffset,$Length)=@_;
my($r)=@_;
warn "Unexpected 'r' $r" if $r ne "1";
+ warn "AcquireForLazyWrite() not the toplevel function" if @$EnterLeave;
return if !(my $CObject=CObject $Object->{"data"}[0]{"SharedCacheMap"});
$CObject->{"AcquireForLazyWrite"}++;
}
sub ReleaseFromLazyWrite_leave()
{
+ warn "ReleaseFromLazyWrite() not the toplevel function" if @$EnterLeave;
return if !(my $CObject=CObject $Object->{"data"}[0]{"SharedCacheMap"});
warn "Invalid 'AcquireForLazyWrite' value ".$CObject->{"AcquireForLazyWrite"}
if !($CObject->{"AcquireForLazyWrite"}>=1);
}
$LastLeave=${$LastLeave{$ProcessThread}}[$#{$LastLeave{$ProcessThread}}-1];
+ $EnterLeave=$EnterLeave{$ProcessThread};
if (my($r)=
/^leave: IRP_MJ_\w+: r=($hex)/) {
next;
}
+ if (my($SectionObjectPointer,$SharedCacheMap,$FileOffset,$Length)=
+ /^enter: CcFlushCache: SectionObjectPointer=($hex),->SharedCacheMap=($hex),FileOffset=($hex),Length=($hex)/) {
+ CcFlushCache $SectionObjectPointer,$SharedCacheMap,$FileOffset,$Length;
+ next;
+ }
+
+ if (my($Status,$Information)=
+ /^leave: CcFlushCache: IoStatus->Status=($hex),IoStatus->Information=($hex)/) {
+ CcFlushCache_leave $Status,$Information;
+ next;
+ }
+
if (my($r)=
/^leave: AcquireForLazyWrite: r=([01])/) {
AcquireForLazyWrite_leave $r;