+debug messages for Cc subsystem
authorshort <>
Fri, 31 Jan 2003 19:39:05 +0000 (19:39 +0000)
committershort <>
Fri, 31 Jan 2003 19:39:05 +0000 (19:39 +0000)
BCBs no longer need to be PAGE_SIZE-aligned
CcMapData(): We read only not-yet-cached pages; not the whole range
CcPinMappedData(): The whole range is reread once more; FIXME: is it needed?
CcUnpinData(): data is flushed only during the last unpin of BCB

src/libcaptive/cc/map.c

index 5a5b2bd..fe2a0a1 100644 (file)
@@ -55,7 +55,7 @@ static gboolean validate_Bcb(const PUBLIC_BCB *PublicBcb)
 /* position in file */
 struct page_position {
        FILE_OBJECT *FileObject;
-       LARGE_INTEGER FileOffset;
+       LARGE_INTEGER FileOffset;       /* always PAGE_SIZE aligned */
        int shmid;
        GList *privbcb_list;    /* each mapped page has its one private_bcb */
        };
@@ -71,6 +71,7 @@ struct shmid_ds shmid_ds;
        g_return_val_if_fail(pagepos!=NULL,FALSE);
        g_return_val_if_fail(pagepos->FileObject!=NULL,FALSE);
        g_return_val_if_fail(pagepos->FileOffset.QuadPart>=0,FALSE);
+       g_return_val_if_fail(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(pagepos->FileOffset.QuadPart,PAGE_SIZE),FALSE);
        /* 'pagepos->shmid' may be -1 */
        /* 'pagepos->privbcb_list' may be empty */
        g_return_val_if_fail((pagepos->shmid==-1)==(pagepos->privbcb_list==NULL),FALSE);        /* either deleted or alive */
@@ -137,10 +138,10 @@ struct private_bcb {
        FILE_OBJECT *FileObject;
        guint ref_count;
        /* we save it here as 'PublicBcb' may be already destroyed in private_bcb_hash_value_destroy_func(): */
-       ULONG MappedLength;
+       ULONG MappedLength;     /* It is the real requested size; it is not PAGE_SIZE aligned. */
        /* we save it here as 'PublicBcb' may be already destroyed in private_bcb_hash_value_destroy_func(): */
-       LARGE_INTEGER MappedFileOffset;
-       gpointer base;
+       LARGE_INTEGER MappedFileOffset; /* It is the real requested offset; it is not PAGE_SIZE aligned. */
+       gpointer base;  /* It is the pointer corresponding to MappedFileOffset; it is not PAGE_SIZE aligned. */
        gboolean dirty;
        };
 
@@ -160,6 +161,7 @@ struct page_position pagepos_local;
 gboolean errbool;
 int errint;
 size_t offset;
+gpointer base_aligned;
 
        g_return_if_fail(value!=NULL);
        /* We cannot do 'validate_Bcb(value->PublicBcb)' here as 'value->PublicBcb'
@@ -169,13 +171,14 @@ size_t offset;
        g_return_if_fail(value->FileObject!=NULL);
        g_return_if_fail(value->ref_count==0);
        g_return_if_fail(value->MappedLength>0);
-       g_return_if_fail((value->MappedLength&(PAGE_SIZE-1))==0);       /* PAGE_SIZE-aligned */
        g_return_if_fail(value->MappedFileOffset.QuadPart>=0);
        g_return_if_fail(value->base!=NULL);
        g_return_if_fail(value->dirty==FALSE);
 
        page_position_hash_init();
 
+       base_aligned=((char *)value->base)-CAPTIVE_ROUND_DOWN_EXCEEDING64(value->MappedFileOffset.QuadPart,PAGE_SIZE);
+
        pagepos_local.FileObject=value->FileObject;
        pagepos_local.privbcb_list=NULL;
        pagepos_local.shmid=-1;
@@ -185,11 +188,11 @@ size_t offset;
                        offset+=PAGE_SIZE) {
 struct page_position *pagepos;
 
-               pagepos_local.FileOffset.QuadPart=value->MappedFileOffset.QuadPart+offset;
+               pagepos_local.FileOffset.QuadPart=CAPTIVE_ROUND_DOWN64(value->MappedFileOffset.QuadPart+offset,PAGE_SIZE);
                pagepos=g_hash_table_lookup(page_position_hash,&pagepos_local);
                g_assert(validate_page_position(pagepos));
                g_assert(pagepos->privbcb_list!=NULL);
-               errint=shmdt(((char *)value->base)+offset);
+               errint=shmdt(((char *)base_aligned)+offset);
                g_assert(errint==0);
 
                g_assert(g_list_find(pagepos->privbcb_list,value)!=NULL);
@@ -221,6 +224,36 @@ static void private_bcb_hash_init(void)
 }
 
 
+static ULONG captive_Cc_IoPageRead(FILE_OBJECT *FileObject,gpointer address,ULONG length,LARGE_INTEGER *FileOffset)
+{
+MDL *Mdl;
+KEVENT Event;
+IO_STATUS_BLOCK IoStatus;
+NTSTATUS err;
+
+       g_return_val_if_fail(FileObject!=NULL,0);
+       g_return_val_if_fail(address!=0,0);
+       g_return_val_if_fail(length!=0,0);
+       g_return_val_if_fail(FileOffset!=NULL,0);
+
+       Mdl=MmCreateMdl(NULL,address,PAGE_SIZE);        /* FIXME: Depreacted in favor of IoAllocateMdl() */
+       g_assert(Mdl!=NULL);
+       KeInitializeEvent(&Event,NotificationEvent,FALSE);
+       /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
+       err=IoPageRead(FileObject,Mdl,FileOffset,&Event,&IoStatus);
+       g_assert(NT_SUCCESS(err));
+       g_assert(NT_SUCCESS(IoStatus.Status));
+       /* It is not == as the file may be shorter than requested */
+       g_assert(IoStatus.Information<=length);
+       IoFreeMdl(Mdl);
+
+       /* zero the rest of the buffer */
+       memset(((char *)address)+IoStatus.Information,0,(length-IoStatus.Information));
+
+       return IoStatus.Information;
+}
+
+
 /**
  * CcMapData:
  * @FileObject: Initialized open #FileObject to map.
@@ -255,20 +288,15 @@ BOOLEAN CcMapData(IN PFILE_OBJECT FileObject,
 PUBLIC_BCB **PublicBcbp,*PublicBcb;
 struct page_position pagepos_local,*pagepos;
 LARGE_INTEGER FileOffset_bottom,FileOffset_top;
-NTSTATUS err;
-KEVENT Event;
-IO_STATUS_BLOCK IoStatus;
-gpointer base;
-size_t offset,length;
-MDL *Mdl;
+gpointer base_aligned;
+size_t offset,length_mapped_aligned;
 int errint;
 gpointer errptr;
 struct private_bcb *privbcb;
-
-       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,FileOffset=0x%llX,Length=0x%X",G_STRLOC,
-                       FileObject,(guint64)FileOffset->QuadPart,(guint)Length);
+gboolean after_eof=FALSE;      /* Did we reached the end of file already? */
 
        g_return_val_if_fail(FileObject!=NULL,FALSE);
+       g_return_val_if_fail(FileOffset!=NULL,FALSE);
        g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
        g_return_val_if_fail(Length>0,FALSE);   /* FIXME: not handled below; 0 should be allowed */
        g_return_val_if_fail(Flags&MAP_WAIT,FALSE);     /* FIXME: on-demand loading not yet implemented */
@@ -276,35 +304,47 @@ struct private_bcb *privbcb;
        g_return_val_if_fail(Bcb!=NULL,FALSE);
        g_return_val_if_fail(Buffer!=NULL,FALSE);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,FileOffset=0x%llX,Length=0x%lX,Flags=0x%lX",G_STRLOC,
+                       FileObject,(guint64)FileOffset->QuadPart,(gulong)Length,(gulong)Flags);
+
+       g_return_val_if_fail(FileObject->SectionObjectPointers!=NULL,FALSE);
+       g_return_val_if_fail(FileObject->SectionObjectPointers->SharedCacheMap==NULL,FALSE);
+       g_return_val_if_fail(FileObject->DeviceObject!=NULL,FALSE);
+       /* Is PAGE_SIZE aligned with 'FileObject->DeviceObject->SectorSize'?
+        * 'SectorSize' may not yet be filled in.
+        */
+       g_return_val_if_fail(!FileObject->DeviceObject->SectorSize
+                       || 0==CAPTIVE_ROUND_DOWN_EXCEEDING(PAGE_SIZE,FileObject->DeviceObject->SectorSize),FALSE);
+
        page_position_hash_init();
        private_bcb_hash_init();
 
        PublicBcbp=(PUBLIC_BCB **)Bcb;
        /* extend 'FileOffset' and 'Length' to page boundaries */
-       FileOffset_bottom.QuadPart=FileOffset->QuadPart&~(PAGE_SIZE-1);
-       FileOffset_top.QuadPart=(FileOffset->QuadPart+Length+PAGE_SIZE-1)&~(PAGE_SIZE-1);
-       length=(FileOffset_top.QuadPart-FileOffset_bottom.QuadPart);
+       FileOffset_bottom.QuadPart=CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE);
+       FileOffset_top.QuadPart=CAPTIVE_ROUND_UP64(FileOffset->QuadPart+Length,PAGE_SIZE);
+       length_mapped_aligned=(FileOffset_top.QuadPart-FileOffset_bottom.QuadPart);
 
-       /* Create 'base'; referenced by 'privbcb'. */
+       /* Create 'base_aligned'; referenced as unaligned by 'privbcb'. */
        /* TODO: on-demand loading */
        /* Although we do zeroed-page mapping here we just reserve the linears
         * space by it - all the page will be overriden by shmat(2) afterwards anyway.
         */
-       base=mmap(
+       base_aligned=mmap(
                        NULL,   /* start */
-                       length, /* length */
+                       length_mapped_aligned,  /* length */
                        PROT_READ|PROT_WRITE,   /* prot; FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
                        MAP_PRIVATE|MAP_ANONYMOUS,      /* flags */
                        -1,     /* fd; ignored due to MAP_ANONYMOUS */
                        0);     /* offset; ignored due to MAP_ANONYMOUS */
-       g_assert(base!=NULL);
+       g_assert(base_aligned!=NULL);
 
        /* Create 'PublicBcb'; referenced by 'privbcb'. */
        captive_new(PublicBcb);
        PublicBcb->NodeTypeCode=CAPTIVE_PUBLIC_BCB_NODETYPECODE;
        PublicBcb->NodeByteSize=sizeof(*PublicBcb);     /* we have no extensions there */
-       PublicBcb->MappedLength=(FileOffset_top.QuadPart-FileOffset_bottom.QuadPart);
-       PublicBcb->MappedFileOffset=FileOffset_bottom;
+       PublicBcb->MappedLength=Length;
+       PublicBcb->MappedFileOffset=*FileOffset;
 
        /* Create 'privbcb'; referenced by created 'pagepos'es. */
        captive_new(privbcb);
@@ -313,7 +353,7 @@ struct private_bcb *privbcb;
        privbcb->ref_count=1;
        privbcb->MappedLength=PublicBcb->MappedLength;
        privbcb->MappedFileOffset=PublicBcb->MappedFileOffset;
-       privbcb->base=base;
+       privbcb->base=base_aligned+CAPTIVE_ROUND_DOWN_EXCEEDING64(FileOffset->QuadPart,PAGE_SIZE);
        privbcb->dirty=FALSE;
        g_hash_table_insert(private_bcb_hash,
                        PublicBcb,      /* key */
@@ -324,7 +364,7 @@ struct private_bcb *privbcb;
        pagepos_local.privbcb_list=NULL;
        for (
                        offset=0;
-                       offset<length;
+                       offset<length_mapped_aligned;
                        offset+=PAGE_SIZE) {
 gpointer pageaddr;
 
@@ -337,7 +377,7 @@ gpointer pageaddr;
                        g_assert(pagepos->shmid!=-1);
                        pagepos->privbcb_list=NULL;
                        }
-               pageaddr=(gpointer)(((char *)base)+offset);
+               pageaddr=(gpointer)(((char *)base_aligned)+offset);
                /* It appears as shmat(2) cannot override previously mmap(2)ed memory;
                 * mmap(2) is still needed to get linear block of memory assignment.
                 */
@@ -353,10 +393,21 @@ gpointer pageaddr;
                pagepos->privbcb_list=g_list_prepend(pagepos->privbcb_list,privbcb);    /* order not important */
                g_assert(g_list_find(pagepos->privbcb_list,privbcb)!=NULL);
                if (pagepos->privbcb_list->next==NULL) {        /* exactly one item (we just added it now) */
+ULONG got;
+
                        errint=shmctl(pagepos->shmid,
                                        IPC_RMID,       /* cmd */
                                        NULL);  /* buf */
                        g_assert(errint==0);
+
+                       /* Read the page content: */
+                       got=captive_Cc_IoPageRead(FileObject,pageaddr,PAGE_SIZE,&pagepos_local.FileOffset);
+                       if (after_eof)
+                               g_assert(got==0);
+                       else
+                               g_assert(got<=PAGE_SIZE);
+                       after_eof=(got<PAGE_SIZE);
+
                        g_hash_table_insert(page_position_hash,
                                        pagepos,        /* key */
                                        pagepos);       /* value */
@@ -364,55 +415,11 @@ gpointer pageaddr;
                g_assert(validate_page_position(pagepos));
                }
 
-       Mdl=MmCreateMdl(NULL,base,length);
-       g_assert(Mdl!=NULL);
-
-       KeInitializeEvent(&Event,NotificationEvent,FALSE);
-
-       /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
-       err=IoPageRead(FileObject,Mdl,&FileOffset_bottom,&Event,&IoStatus);
-       g_assert(NT_SUCCESS(err));
-       g_assert(NT_SUCCESS(IoStatus.Status));
-       /* It is not == as the file may be shorter than requested */
-       g_assert(IoStatus.Information<=length);
-
-       /* FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
-       for (
-                       offset=0;
-                       offset<length;
-                       offset+=PAGE_SIZE) {
-gpointer pageaddr,mapped_tmp;
-
-               pagepos_local.FileOffset.QuadPart=FileOffset_bottom.QuadPart+offset;
-               pagepos=g_hash_table_lookup(page_position_hash,&pagepos_local);
-               g_assert(validate_page_position(pagepos));
-               pageaddr=(gpointer)(((char *)base)+offset);
-               /* We need to temporarily map here the page also to 'mapped_tmp'
-                * as we need to unmap the page from 'pageaddr' before remapping it 'SHM_RDONLY'
-                * and theredore 'shmid_ds.shm_nattch' would fall to 0 and due to 'IPC_RMID'
-                * we would get 'shmid' destroyed at all.
-                */
-               mapped_tmp=shmat(pagepos->shmid,
-                               NULL,   /* shmaddr */
-                               SHM_RDONLY);    /* shmflg; just for temporary mapping of 'mapped_tmp' */
-               g_assert(mapped_tmp!=NULL);
-               errint=shmdt(pageaddr);
-               g_assert(errint==0);
-               g_assert(validate_page_position(pagepos));
-               errptr=shmat(pagepos->shmid,
-                               pageaddr,       /* shmaddr */
-                               0);     /* shmflg; !SHM_RDONLY==r/w FIXME: read/write should be possible after CcSetDirtyPinnedData() etc. */
-               g_assert(errptr==pageaddr);
-               errint=shmdt(mapped_tmp);
-               g_assert(errint==0);
-               /* re-validate 'pagepos' to ensure if still 'shmid_ds.shm_nattch==g_list_length(pagepos->privbcb_list)' */
-               g_assert(validate_page_position(pagepos));
-               }
-
        /* offset _into_ page, may not be PAGE_SIZE aligned: */
-       *Buffer=base+(FileOffset->QuadPart-FileOffset_bottom.QuadPart);
+       *Buffer=privbcb->base;
        *PublicBcbp=PublicBcb;
        g_assert(validate_Bcb(PublicBcb)==TRUE);
+       FileObject->SectionObjectPointers->SharedCacheMap=PublicBcb;
 
        return TRUE;
 }
@@ -453,22 +460,28 @@ BOOLEAN CcPinMappedData
                (IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb)
 {
 struct page_position pagepos_local,*pagepos;
-struct private_bcb *privbcb;
+struct private_bcb *privbcb,*privbcb_listitem;
 GList *privbcb_list;
 LARGE_INTEGER FileOffset_bottom,FileOffset_top;
-size_t length;
+size_t length_mapped_aligned;
+gpointer base_aligned;
+ULONG got;
 
        g_return_val_if_fail(FileObject!=NULL,FALSE);
+       g_return_val_if_fail(FileOffset!=NULL,FALSE);
        g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
        g_return_val_if_fail(Length>0,FALSE);   /* FIXME: not handled below; 0 should be allowed */
        /* 'Flags&PIN_WAIT' ignored as we already must have the data mapped */
        g_return_val_if_fail(!(Flags&~(PIN_WAIT|PIN_EXCLUSIVE|PIN_NO_READ|PIN_IF_BCB)),FALSE);  /* unknown flags? */
        g_return_val_if_fail(Bcb!=NULL,FALSE);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,FileOffset=0x%llX,Length=0x%lX,Flags=0x%lX",G_STRLOC,
+                       FileObject,(guint64)FileOffset->QuadPart,(gulong)Length,(gulong)Flags);
+
        /* extend 'FileOffset' and 'Length' to page boundaries */
-       FileOffset_bottom.QuadPart=FileOffset->QuadPart&~(PAGE_SIZE-1);
-       FileOffset_top.QuadPart=(FileOffset->QuadPart+Length+PAGE_SIZE-1)&~(PAGE_SIZE-1);
-       length=(FileOffset_top.QuadPart-FileOffset_bottom.QuadPart);
+       FileOffset_bottom.QuadPart=CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE);
+       FileOffset_top.QuadPart=CAPTIVE_ROUND_UP64(FileOffset->QuadPart+Length,PAGE_SIZE);
+       length_mapped_aligned=(FileOffset_top.QuadPart-FileOffset_bottom.QuadPart);
 
        page_position_hash_init();
 
@@ -482,16 +495,27 @@ size_t length;
 
        privbcb=NULL;
        for (privbcb_list=pagepos->privbcb_list;privbcb_list;privbcb_list=privbcb_list->next) {
-               privbcb=privbcb_list->data;
-               if (privbcb->MappedLength==length)
-                       break;
+               privbcb_listitem=privbcb_list->data;
+               if (1
+                               && privbcb_listitem->MappedFileOffset.QuadPart==FileOffset->QuadPart
+                               && privbcb_listitem->MappedLength==Length) {
+                       g_assert(privbcb==NULL);        /* appropriate privbcb found twice */
+                       privbcb=privbcb_listitem;
+                       }
                }
        g_return_val_if_fail(privbcb!=NULL,FALSE);      /* appropriate privbcb not found */
 
        /* Sanity check 'privbcb': */
        g_return_val_if_fail(FileObject==privbcb->FileObject,FALSE);
-       g_return_val_if_fail(FileOffset_bottom.QuadPart==privbcb->MappedFileOffset.QuadPart,FALSE);
-       g_return_val_if_fail(length==privbcb->MappedLength,FALSE);
+
+       base_aligned=CAPTIVE_ROUND_DOWN(privbcb->base,PAGE_SIZE);
+
+       got=captive_Cc_IoPageRead(
+                       privbcb->FileObject,    /* FILE_OBJECT */
+                       base_aligned,   /* address */
+                       PAGE_SIZE,      /* length */
+                       &pagepos_local.FileOffset);     /* FileOffset */
+       /* FIXME: sanitycheck 'got' agains CcMapData() state */
 
        /* Memory already mapped by CcMapData(). */
        *Bcb=privbcb->PublicBcb;
@@ -533,6 +557,7 @@ PVOID Bcb_CcPinMappedData;
 gboolean errbool;
 
        g_return_val_if_fail(FileObject!=NULL,FALSE);
+       g_return_val_if_fail(FileOffset!=NULL,FALSE);
        g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
        g_return_val_if_fail(Length>0,FALSE);   /* FIXME: not handled below; 0 should be allowed */
        /* 'Flags&PIN_WAIT' ignored as we already must have the data mapped */
@@ -540,6 +565,9 @@ gboolean errbool;
        g_return_val_if_fail(Bcb!=NULL,FALSE);
        g_return_val_if_fail(Buffer!=NULL,FALSE);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,FileOffset=0x%llX,Length=0x%lX,Flags=0x%lX",G_STRLOC,
+                       FileObject,(guint64)FileOffset->QuadPart,(gulong)Length,(gulong)Flags);
+
        if (!(Flags&PIN_IF_BCB)) {
                errbool=CcMapData(FileObject,FileOffset,Length,
                                0               /* Flags */
@@ -584,37 +612,78 @@ gboolean errbool;
        privbcb=g_hash_table_lookup(private_bcb_hash,PublicBcb);
        g_return_if_fail(privbcb!=NULL);
 
+       g_assert(privbcb->FileObject->SectionObjectPointers!=NULL);
+       g_assert(privbcb->FileObject->SectionObjectPointers->SharedCacheMap==PublicBcb);
+
        g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,
-                       "%s: privbcb->FileObject=%p,privbcb->MappedFileOffset=0x%llX,privbcb->MappedLength=0x%x",G_STRLOC,
-                       privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(guint)privbcb->MappedLength);
+                       "%s: privbcb->FileObject=%p,privbcb->MappedFileOffset=0x%llX,privbcb->MappedLength=0x%lX",G_STRLOC,
+                       privbcb->FileObject,(guint64)privbcb->MappedFileOffset.QuadPart,(gulong)privbcb->MappedLength);
+
+       g_assert(privbcb->ref_count>0);
+       /* Do not write back the contents if this is not the final unpin.
+        * FIXME: Is it correct?
+        */
+       if (--privbcb->ref_count)
+               return;
 
        if (privbcb->dirty) {
 MDL *Mdl;
 KEVENT Event;
 IO_STATUS_BLOCK IoStatus;
 NTSTATUS err;
-
-               Mdl=MmCreateMdl(NULL,privbcb->base,privbcb->MappedLength);
+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,&privbcb->MappedFileOffset,&Event,&IoStatus);
+               err=IoSynchronousPageWrite(privbcb->FileObject,Mdl,&FileOffset_sectoraligned,&Event,&IoStatus);
                g_assert(NT_SUCCESS(err));
                g_assert(NT_SUCCESS(IoStatus.Status));
-               /* It is not == as the file may be shorter than requested */
-               g_assert(IoStatus.Information==privbcb->MappedLength);
+               /* 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;
                }
 
-       g_assert(privbcb->ref_count>0);
-       if (!--privbcb->ref_count) {
-               errbool=g_hash_table_remove(private_bcb_hash,PublicBcb);
-               g_assert(errbool==TRUE);
-               }
+       g_assert(privbcb->FileObject->SectionObjectPointers!=NULL);
+       g_assert(privbcb->FileObject->SectionObjectPointers->SharedCacheMap==PublicBcb);
+       privbcb->FileObject->SectionObjectPointers->SharedCacheMap=NULL;
+
+       errbool=g_hash_table_remove(private_bcb_hash,PublicBcb);
+       g_assert(errbool==TRUE);
 }
 
 
@@ -631,6 +700,9 @@ struct private_bcb *privbcb;
        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: Bcb=%p; privbcb->FileObject=%p",G_STRLOC,
+                       Bcb,privbcb->FileObject);
+
        privbcb->ref_count++;
 }
 
@@ -649,6 +721,9 @@ struct private_bcb *privbcb;
        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: Bcb=%p,WriteThrough=%d,IoStatus=%p; privbcb->FileObject=%p",G_STRLOC,
+                       Bcb,(gint)WriteThrough,IoStatus,privbcb->FileObject);
+
        IoStatus->Status=STATUS_SUCCESS;
        IoStatus->Information=privbcb->MappedLength;
 
@@ -670,11 +745,13 @@ struct private_bcb *privbcb;
        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: Bcb=%p,Lsn=0x%llX; privbcb->FileObject=%p",G_STRLOC,
+                       Bcb,(guint64)(!Lsn ? -1 : Lsn->QuadPart),privbcb->FileObject);
+
        privbcb->dirty=TRUE;
 }
 
 
-
 /**
  * CcSetFileSizes:
  * @FileObject: Initialized open #FileObject to update file sizes of.
@@ -693,6 +770,11 @@ VOID CcSetFileSizes(IN PFILE_OBJECT FileObject,IN PCC_FILE_SIZES FileSizes)
        g_return_if_fail(FileObject!=NULL);
        g_return_if_fail(FileSizes!=NULL);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,"
+                       "FileSizes->AllocationSize=0x%llX,FileSizes->FileSize=0x%llX,FileSizes->ValidDataLength=0x%llX",G_STRLOC,
+                       FileObject,(guint64)FileSizes->AllocationSize.QuadPart,(guint64)FileSizes->FileSize.QuadPart,
+                       (guint64)FileSizes->ValidDataLength.QuadPart);
+
        /* FIXME: check BCB && 'struct page_position' invalidities */
 }
 
@@ -713,7 +795,24 @@ VOID CcSetFileSizes(IN PFILE_OBJECT FileObject,IN PCC_FILE_SIZES FileSizes)
 BOOLEAN CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
                IN PLARGE_INTEGER FileOffset OPTIONAL,IN ULONG Length,IN BOOLEAN UninitializeCacheMaps)
 {
+PUBLIC_BCB *PublicBcb;
+struct private_bcb *privbcb;
+
        g_return_val_if_fail(SectionObjectPointer!=NULL,FALSE);
+       g_return_val_if_fail(SectionObjectPointer->SharedCacheMap!=NULL,FALSE);
+
+       PublicBcb=SectionObjectPointer->SharedCacheMap;
+       g_return_val_if_fail(validate_Bcb(PublicBcb),FALSE);
+
+       private_bcb_hash_init();
+
+       privbcb=g_hash_table_lookup(private_bcb_hash,PublicBcb);
+       g_return_val_if_fail(privbcb!=NULL,FALSE);
+
+       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,UninitializeCacheMaps=%d",G_STRLOC,
+                       SectionObjectPointer,PublicBcb,privbcb,privbcb->FileObject,
+                       (guint64)(!FileOffset ? -1 : FileOffset->QuadPart),(gulong)Length,(gint)UninitializeCacheMaps);
 
        return TRUE;
 }
@@ -754,6 +853,9 @@ gboolean errbool;
        g_return_val_if_fail(Buffer!=NULL,FALSE);
        g_return_val_if_fail(IoStatus!=NULL,FALSE);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,FileOffset=0x%llX,Length=0x%lX,Wait=%d",G_STRLOC,
+                       FileObject,(guint64)FileOffset->QuadPart,(gulong)Length,(gint)Wait);
+
        IoStatus->Status=STATUS_UNSUCCESSFUL;
        IoStatus->Information=0;
 
@@ -808,6 +910,9 @@ gboolean errbool;
        g_return_val_if_fail(FileOffset!=NULL,FALSE);
        g_return_val_if_fail(Buffer!=NULL,FALSE);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,FileOffset=0x%llX,Length=0x%lX,Wait=%d",G_STRLOC,
+                       FileObject,(guint64)FileOffset->QuadPart,(gulong)Length,(gint)Wait);
+
        if (Length) {
                errbool=CcPinRead(
                                FileObject,     /* FileObject */
@@ -849,6 +954,9 @@ BOOLEAN CcCanIWrite(IN PFILE_OBJECT FileObject,IN ULONG BytesToWrite,IN BOOLEAN
 {
        g_return_val_if_fail(FileObject!=NULL,FALSE);
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,BytesToWrite=0x%lX,Wait=%d,Retrying=%d",G_STRLOC,
+                       FileObject,(gulong)BytesToWrite,(gint)Wait,(gint)Retrying);
+
        return TRUE;
 }
 
@@ -869,5 +977,8 @@ VOID CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject,IN ULONG Granularity)
        g_return_if_fail(Granularity>=PAGE_SIZE);
        g_return_if_fail((Granularity&(Granularity-1))==0);     /* Power of two */
 
+       g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: FileObject=%p,Granularity=0x%lX",G_STRLOC,
+                       FileObject,(gulong)Granularity);
+
        /* NOP; no caching by libcaptive */
 }