#include <unistd.h>
#include <glib/glist.h>
#include "reactos/internal/io.h" /* for IoSynchronousPageWrite() */
+#include <glib/garray.h>
/* CONFIG: */
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);
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;
*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);
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 */
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;
(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);
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);