CcMapData(): Never read any data pages until data structures are sinked.
authorshort <>
Sat, 1 Feb 2003 20:16:01 +0000 (20:16 +0000)
committershort <>
Sat, 1 Feb 2003 20:16:01 +0000 (20:16 +0000)
 - fixes problem on 16-bit FAT fastfat.sys
captive_privbcb_flush(): Also accept IoStatus.Information==0 during write. :-?
 - fixes problem on 32-bit FAT fastfat.sys

src/libcaptive/cc/map.c

index 8c4a06a..63b0801 100644 (file)
@@ -33,6 +33,7 @@
 #include <unistd.h>
 #include <glib/glist.h>
 #include "reactos/internal/io.h"       /* for IoSynchronousPageWrite() */
+#include <glib/garray.h>
 
 
 /* CONFIG: */
@@ -331,6 +332,7 @@ int errint;
 gpointer errptr;
 struct private_bcb *privbcb;
 gboolean after_eof=FALSE;      /* Did we reached the end of file already? */
+GPtrArray *read_array;
 
        g_return_val_if_fail(FileObject!=NULL,FALSE);
        g_return_val_if_fail(FileOffset!=NULL,FALSE);
@@ -411,6 +413,15 @@ gboolean after_eof=FALSE;  /* Did we reached the end of file already? */
                        PublicBcb,      /* key */
                        privbcb);       /* value */
 
+       /* We MUST NOT call captive_Cc_IoPageRead() inside our pagepos filling loop
+        * below as captive_Cc_IoPageRead() has very big consequences as it calls
+        * the filesystem code and we may get reentrancy.
+        * Therefore we store all missing page read requests to 'read_array' and we
+        * fill them when all the memory structures are in consistent state.
+        * We can also coalescence the requests more easily this way.
+        */
+       read_array=g_ptr_array_new();
+
        pagepos_local.FileObject=FileObject;
        pagepos_local.shmid=-1;
        pagepos_local.privbcb_list=NULL;
@@ -427,6 +438,7 @@ gpointer pageaddr;
                        *pagepos=pagepos_local;
                        pagepos->shmid=shmget(IPC_PRIVATE,PAGE_SIZE,IPC_CREAT|IPC_CREAT|0600);
                        pagepos->privbcb_list=NULL;
+                       g_ptr_array_add(read_array,pagepos);    /* enlist this 'pagepos' as todo read item */
                        }
                else
                        g_assert(pagepos->privbcb_list!=NULL);
@@ -447,21 +459,11 @@ 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 */
@@ -469,6 +471,38 @@ ULONG got;
                g_assert(validate_page_position(pagepos));
                }
 
+       /* Fill in the missing pages content todo-list stored in 'read_array': */
+       while (read_array->len && (pagepos=g_ptr_array_remove_index(read_array,
+                                       0))) {  /* index */
+ULONG read_size;
+ULONG got;
+struct pagepos *pagepos_next;
+gpointer pageaddr,pageaddr_next;
+
+               pageaddr=(gpointer)(((char *)base_aligned)+(pagepos->FileOffset.QuadPart-FileOffset_bottom.QuadPart));
+               read_size=PAGE_SIZE;
+               /* Coalescence of the requests */
+               while (read_array->len) {
+                       pagepos_next=g_ptr_array_index(read_array,
+                                       0);     /* index */
+                       pageaddr_next=(gpointer)(((char *)base_aligned)+(pagepos->FileOffset.QuadPart-FileOffset_bottom.QuadPart));
+                       if (pageaddr_next!=((char *)pageaddr)+read_size)
+                               break;
+                       read_size+=PAGE_SIZE;
+                       g_assert(pagepos_next==g_ptr_array_remove_index(read_array,
+                                       0));    /* index */
+                       }
+               /* Read the range content: */
+               got=captive_Cc_IoPageRead(FileObject,pageaddr,read_size,&pagepos_local.FileOffset);
+               if (after_eof)
+                       g_assert(got==0);
+               else
+                       g_assert(got<=PAGE_SIZE);
+               after_eof=(got<PAGE_SIZE);
+               }
+       g_ptr_array_free(read_array,
+                       TRUE);  /* free_seg; free the array of gpointer(==struct pagepos *) items */
+
 done:
        /* offset _into_ page, may not be PAGE_SIZE aligned: */
        *Buffer=privbcb->base;
@@ -519,9 +553,6 @@ BOOLEAN CcPinMappedData
                (IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb)
 {
 struct private_bcb *privbcb;
-gpointer base_aligned;
-ULONG got;
-LARGE_INTEGER FileOffset_bottom;
 
        g_return_val_if_fail(FileObject!=NULL,FALSE);
        g_return_val_if_fail(FileOffset!=NULL,FALSE);
@@ -657,8 +688,10 @@ LARGE_INTEGER FileOffset_sectoraligned;
        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.
+        * FIXME: Also we can get just value 0 if the write is considered 'not dirty'
+        * during FAT write by fastfat.sys.
         */
-       g_assert(IoStatus.Information>=CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize)
+       g_assert(IoStatus.Information==0 || IoStatus.Information>=CAPTIVE_ROUND_DOWN_EXCEEDING(privbcb->base,privbcb->FileObject->DeviceObject->SectorSize)
                        +privbcb->MappedLength);
        g_assert(IoStatus.Information<=length_sectoraligned);