Support of PIN_IF_BCB is now non-fatal-reporting.
authorshort <>
Sat, 1 Feb 2003 00:25:04 +0000 (00:25 +0000)
committershort <>
Sat, 1 Feb 2003 00:25:04 +0000 (00:25 +0000)
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

index fe2a0a1..75f1db7 100644 (file)
@@ -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);
+               }
+}