From 4fd339b41fbee5bb5f458d759bb38738acc2cbb3 Mon Sep 17 00:00:00 2001 From: short <> Date: Sat, 1 Feb 2003 00:25:04 +0000 Subject: [PATCH] Support of PIN_IF_BCB is now non-fatal-reporting. CcUnpinData() flushing isolated -> captive_privbcb_flush(). CcPurgeCacheSection(): NULL input is no longer fatal (NOP now). CcPurgeCacheSection(): Implemented real purging. +CcFlushCache() --- src/libcaptive/cc/map.c | 187 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 133 insertions(+), 54 deletions(-) diff --git a/src/libcaptive/cc/map.c b/src/libcaptive/cc/map.c index fe2a0a1..75f1db7 100644 --- a/src/libcaptive/cc/map.c +++ b/src/libcaptive/cc/map.c @@ -490,6 +490,8 @@ ULONG got; pagepos_local.privbcb_list=NULL; pagepos_local.shmid=-1; pagepos=g_hash_table_lookup(page_position_hash,&pagepos_local); + if (!pagepos && (Flags & PIN_IF_BCB)) /* BCB does not exist */ + return FALSE; g_assert(validate_page_position(pagepos)); g_assert(pagepos->privbcb_list!=NULL); @@ -503,6 +505,8 @@ ULONG got; privbcb=privbcb_listitem; } } + if (!privbcb && (Flags & PIN_IF_BCB)) /* BCB does not exist */ + return FALSE; g_return_val_if_fail(privbcb!=NULL,FALSE); /* appropriate privbcb not found */ /* Sanity check 'privbcb': */ @@ -591,6 +595,63 @@ gboolean errbool; } +static void captive_privbcb_flush(struct private_bcb *privbcb) +{ +MDL *Mdl; +KEVENT Event; +IO_STATUS_BLOCK IoStatus; +NTSTATUS err; +gpointer base_sectoraligned; +gsize length_sectoraligned; +LARGE_INTEGER FileOffset_sectoraligned; + + if (!privbcb->dirty) + return; + + g_assert(privbcb->FileObject->DeviceObject!=NULL); + /* Is PAGE_SIZE aligned with 'privbcb->FileObject->DeviceObject->SectorSize'? */ + g_assert(privbcb->FileObject->DeviceObject->SectorSize>0); + g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(PAGE_SIZE,privbcb->FileObject->DeviceObject->SectorSize)); + /* We align here directly the 'privbcb->base' which is not correct. + * We should rather aligned according to 'privbcb->MappedOffset' but + * as 'privbcb->base' with PAGE_SIZE alignment is just a possibly + * better alignment than 'privbcb->FileObject->DeviceObject->SectorSize' it must the same operation. + */ + g_assert(CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize) + ==CAPTIVE_ROUND_DOWN_EXCEEDING64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize)); + base_sectoraligned =CAPTIVE_ROUND_DOWN(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize); + length_sectoraligned=CAPTIVE_ROUND_UP(((char *)privbcb->base)+privbcb->MappedLength,privbcb->FileObject->DeviceObject->SectorSize) + -((char *)base_sectoraligned); + g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(length_sectoraligned,privbcb->FileObject->DeviceObject->SectorSize)); + FileOffset_sectoraligned.QuadPart=CAPTIVE_ROUND_DOWN64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize); + + Mdl=MmCreateMdl(NULL,base_sectoraligned,length_sectoraligned); + g_assert(Mdl!=NULL); + + KeInitializeEvent(&Event,NotificationEvent,FALSE); + + /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */ + /* Use rather IoSynchronousPageWrite() than IoPageWrite() to prevent STATUS_PENDING. */ + err=IoSynchronousPageWrite(privbcb->FileObject,Mdl,&FileOffset_sectoraligned,&Event,&IoStatus); + g_assert(NT_SUCCESS(err)); + g_assert(NT_SUCCESS(IoStatus.Status)); + /* We should write at least the unaligned mapped data although we + * do not need to successfuly write the whole aligned amount. + */ + g_assert(IoStatus.Information>=CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize) + +privbcb->MappedLength); + g_assert(IoStatus.Information<=length_sectoraligned); + + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: 'dirty' flush: FileObject=%p,MappedFileOffset=0x%llX,MappedLength=0x%lX,base=%p" + "; base_sectoraligned=%p,FileOffset_sectoraligned=0x%llX,length_sectoraligned=0x%lX; ->Information=0x%lX",G_STRLOC, + privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(gulong)privbcb->MappedLength,privbcb->base, + base_sectoraligned,(guint64)FileOffset_sectoraligned.QuadPart,(gulong)length_sectoraligned, + (gulong)IoStatus.Information); + + privbcb->dirty=FALSE; +} + + /** * CcUnpinData: * @Bcb: Initialized #PUBLIC_BCB structure. @@ -626,57 +687,7 @@ gboolean errbool; if (--privbcb->ref_count) return; - if (privbcb->dirty) { -MDL *Mdl; -KEVENT Event; -IO_STATUS_BLOCK IoStatus; -NTSTATUS err; -gpointer base_sectoraligned; -gsize length_sectoraligned; -LARGE_INTEGER FileOffset_sectoraligned; - - g_assert(privbcb->FileObject->DeviceObject!=NULL); - /* Is PAGE_SIZE aligned with 'privbcb->FileObject->DeviceObject->SectorSize'? */ - g_assert(privbcb->FileObject->DeviceObject->SectorSize>0); - g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(PAGE_SIZE,privbcb->FileObject->DeviceObject->SectorSize)); - /* We align here directly the 'privbcb->base' which is not correct. - * We should rather aligned according to 'privbcb->MappedOffset' but - * as 'privbcb->base' with PAGE_SIZE alignment is just a possibly - * better alignment than 'privbcb->FileObject->DeviceObject->SectorSize' it must the same operation. - */ - g_assert(CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize) - ==CAPTIVE_ROUND_DOWN_EXCEEDING64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize)); - base_sectoraligned =CAPTIVE_ROUND_DOWN(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize); - length_sectoraligned=CAPTIVE_ROUND_UP(((char *)privbcb->base)+privbcb->MappedLength,privbcb->FileObject->DeviceObject->SectorSize) - -((char *)base_sectoraligned); - g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING(length_sectoraligned,privbcb->FileObject->DeviceObject->SectorSize)); - FileOffset_sectoraligned.QuadPart=CAPTIVE_ROUND_DOWN64(privbcb->MappedFileOffset.QuadPart,privbcb->FileObject->DeviceObject->SectorSize); - - Mdl=MmCreateMdl(NULL,base_sectoraligned,length_sectoraligned); - g_assert(Mdl!=NULL); - - KeInitializeEvent(&Event,NotificationEvent,FALSE); - - /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */ - /* Use rather IoSynchronousPageWrite() than IoPageWrite() to prevent STATUS_PENDING. */ - err=IoSynchronousPageWrite(privbcb->FileObject,Mdl,&FileOffset_sectoraligned,&Event,&IoStatus); - g_assert(NT_SUCCESS(err)); - g_assert(NT_SUCCESS(IoStatus.Status)); - /* We should write at least the unaligned mapped data although we - * do not need to successfuly write the whole aligned amount. - */ - g_assert(IoStatus.Information>=CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize) - +privbcb->MappedLength); - g_assert(IoStatus.Information<=length_sectoraligned); - - g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: 'dirty' flush: FileObject=%p,MappedFileOffset=0x%llX,MappedLength=0x%lX,base=%p" - "; base_sectoraligned=%p,FileOffset_sectoraligned=0x%llX,length_sectoraligned=0x%lX; ->Information=0x%lX",G_STRLOC, - privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(gulong)privbcb->MappedLength,privbcb->base, - base_sectoraligned,(guint64)FileOffset_sectoraligned.QuadPart,(gulong)length_sectoraligned, - (gulong)IoStatus.Information); - - privbcb->dirty=FALSE; - } + captive_privbcb_flush(privbcb); g_assert(privbcb->FileObject->SectionObjectPointers!=NULL); g_assert(privbcb->FileObject->SectionObjectPointers->SharedCacheMap==PublicBcb); @@ -781,14 +792,18 @@ VOID CcSetFileSizes(IN PFILE_OBJECT FileObject,IN PCC_FILE_SIZES FileSizes) /** * CcPurgeCacheSection: - * @SectionObjectPointer: FIXME: ???. + * @SectionObjectPointer: Pointer specifying file to purge; + * %NULL value is forbidden. + * libcaptive interprets only #SharedCacheMap field as #PUBLIC_BCB pointer. + * Field #SharedCacheMap value %NULL is permitted; libcaptive does a NOP with %FALSE return code in such case. * @FileOffset: Starting offset of the ranger to purge. * %NULL pointer is permitted and it means to purge the whole whole. + * FIXME: Non %NULL pointer is NOT IMPLEMENTED YET by libcaptive. * @Length: Length of the range to purge. Ignored if @FileOffset==NULL. * @UninitializeCacheMaps: Purge also private cache maps (FIXME: ???). * * Drop any caching for shrunken file which is not being deleted. - * libcaptive implements this function as NOP as it does not cache anything. + * libcaptive will no longer consider such #BCB as dirty. * * Returns: %TRUE if the range was purged successfuly. */ @@ -799,7 +814,9 @@ PUBLIC_BCB *PublicBcb; struct private_bcb *privbcb; g_return_val_if_fail(SectionObjectPointer!=NULL,FALSE); - g_return_val_if_fail(SectionObjectPointer->SharedCacheMap!=NULL,FALSE); + if (SectionObjectPointer->SharedCacheMap==NULL) + return FALSE; /* failed - nothing to purge */ + g_return_val_if_fail(FileOffset==NULL,FALSE); /* NOT IMPLEMENTED YET */ PublicBcb=SectionObjectPointer->SharedCacheMap; g_return_val_if_fail(validate_Bcb(PublicBcb),FALSE); @@ -814,6 +831,8 @@ struct private_bcb *privbcb; SectionObjectPointer,PublicBcb,privbcb,privbcb->FileObject, (guint64)(!FileOffset ? -1 : FileOffset->QuadPart),(gulong)Length,(gint)UninitializeCacheMaps); + privbcb->dirty=FALSE; /* purge it */ + return TRUE; } @@ -982,3 +1001,63 @@ VOID CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject,IN ULONG Granularity) /* NOP; no caching by libcaptive */ } + + +/** + * CcFlushCache: + * @SectionObjectPointer: Pointer specifying file to flush; + * %NULL value is forbidden. + * libcaptive interprets only #SharedCacheMap field as #PUBLIC_BCB pointer. + * Field #SharedCacheMap value %NULL is permitted; libcaptive does a NOP in such case. + * @FileOffset: Optional starting point of the range to flush. + * %NULL value is permitted. + * @Length: Length of the range to flush. Ignored if @FileOffset is %NULL. + * @IoStatus: Optionally returns the resulting operation status. + * #Information field will contain the number of bytes flushed. + * %NULL value is permitted. + * + * Flushes out any pending dirty data in cache manager BCB mapping. + * FIXME: libcaptive currently always flushes the full file ignoring any @FileOffset or @Length. + */ +VOID CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER FileOffset OPTIONAL,IN ULONG Length,OUT PIO_STATUS_BLOCK IoStatus OPTIONAL) +{ +PUBLIC_BCB *PublicBcb; +struct private_bcb *privbcb; + + g_return_if_fail(SectionObjectPointer!=NULL); + + if (SectionObjectPointer->SharedCacheMap==NULL) { + if (IoStatus) { + IoStatus->Status=STATUS_SUCCESS; + IoStatus->Information=0; + } + return; + } + + PublicBcb=SectionObjectPointer->SharedCacheMap; + g_return_if_fail(validate_Bcb(PublicBcb)); + + private_bcb_hash_init(); + + privbcb=g_hash_table_lookup(private_bcb_hash,PublicBcb); + g_return_if_fail(privbcb!=NULL); + + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: SectionObjectPointer=%p(Bcb=%p,privbcb=%p,privbcb->FileObject=%p)," + "FileOffset=0x%llX,Length=0x%lX,IoStatus=%p",G_STRLOC, + SectionObjectPointer,PublicBcb,privbcb,privbcb->FileObject, + (guint64)(!FileOffset ? -1 : FileOffset->QuadPart),(gulong)Length,IoStatus); + + if (FileOffset) { + g_assert(FileOffset->QuadPart >=privbcb->MappedFileOffset.QuadPart); + g_assert(FileOffset->QuadPart+Length<=privbcb->MappedFileOffset.QuadPart+privbcb->MappedLength); + } + + /* FIXME: Flush just FileOffset..FileOfset+Length part */ + captive_privbcb_flush(privbcb); + + if (IoStatus) { + IoStatus->Status=STATUS_SUCCESS; + IoStatus->Information=(FileOffset && Length ? MIN(privbcb->MappedLength,Length) : privbcb->MappedLength); + } +} -- 1.8.3.1