mirror of
https://github.com/reactos/reactos.git
synced 2025-05-16 15:50:24 +00:00
- Change all FAT*FindAvailableCluster functions to new functions
FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
This commit is contained in:
parent
0f48b872aa
commit
a9f6cf2b6c
11 changed files with 363 additions and 290 deletions
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: create.c,v 1.70 2004/07/05 21:39:02 hbirr Exp $
|
||||
/* $Id: create.c,v 1.71 2004/08/01 21:57:17 navaraf Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/fs/vfat/create.c
|
||||
|
@ -453,6 +453,7 @@ VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
|||
}
|
||||
Fcb->entry.FirstCluster = 0;
|
||||
Fcb->entry.FirstClusterHigh = 0;
|
||||
Fcb->LastOffset = Fcb->LastCluster = 0;
|
||||
VfatUpdateEntry (Fcb);
|
||||
if (Fcb->RFCB.FileSize.QuadPart > 0)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: direntry.c,v 1.16 2003/10/19 17:07:58 hbirr Exp $
|
||||
/* $Id: direntry.c,v 1.17 2004/08/01 21:57:17 navaraf Exp $
|
||||
*
|
||||
*
|
||||
* FILE: DirEntry.c
|
||||
|
@ -297,11 +297,3 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
|
|||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: dirwr.c,v 1.39 2003/10/11 17:51:56 hbirr Exp $
|
||||
/* $Id: dirwr.c,v 1.40 2004/08/01 21:57:17 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -203,6 +203,13 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (!ExAcquireResourceExclusiveLite(&pDirFcb->MainResource, TRUE))
|
||||
{
|
||||
DPRINT("Failed acquiring lock\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1; //nb of entry needed for long name+normal entry
|
||||
DPRINT ("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
|
||||
Buffer = ExAllocatePool (NonPagedPool, (nbSlots - 1) * sizeof (FATDirEntry));
|
||||
|
@ -247,6 +254,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
if (i == 100) /* FIXME : what to do after this ? */
|
||||
{
|
||||
ExReleaseResourceLite(&pDirFcb->MainResource);
|
||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||
ExFreePool (Buffer);
|
||||
CHECKPOINT;
|
||||
|
@ -400,6 +408,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
/* try to find nbSlots contiguous entries frees in directory */
|
||||
if (!vfatFindDirSpace(DeviceExt, pDirFcb, nbSlots, &DirContext.StartIndex))
|
||||
{
|
||||
ExReleaseResourceLite(&pDirFcb->MainResource);
|
||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||
ExFreePool (Buffer);
|
||||
return STATUS_DISK_FULL;
|
||||
|
@ -407,10 +416,11 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
|
||||
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
||||
{
|
||||
CurrentCluster = 0xffffffff;
|
||||
CurrentCluster = 0;
|
||||
Status = NextCluster (DeviceExt, 0, &CurrentCluster, TRUE);
|
||||
if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&pDirFcb->MainResource);
|
||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||
ExFreePool (Buffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -495,6 +505,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
|
|||
CcSetDirtyPinnedData(Context, NULL);
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
ExReleaseResourceLite(&pDirFcb->MainResource);
|
||||
vfatReleaseFCB (DeviceExt, pDirFcb);
|
||||
ExFreePool (Buffer);
|
||||
DPRINT ("addentry ok\n");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: fat.c,v 1.44 2003/10/11 17:51:56 hbirr Exp $
|
||||
* $Id: fat.c,v 1.45 2004/08/01 21:57:17 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -31,7 +31,7 @@
|
|||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG CurrentCluster,
|
||||
PULONG NextCluster)
|
||||
/*
|
||||
|
@ -61,7 +61,7 @@ Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG CurrentCluster,
|
||||
PULONG NextCluster)
|
||||
/*
|
||||
|
@ -90,7 +90,7 @@ Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG CurrentCluster,
|
||||
PULONG NextCluster)
|
||||
/*
|
||||
|
@ -131,8 +131,8 @@ Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
PULONG Cluster)
|
||||
FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
PULONG Cluster)
|
||||
/*
|
||||
* FUNCTION: Finds the first available cluster in a FAT16 table
|
||||
*/
|
||||
|
@ -144,55 +144,54 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
ULONG ChunkSize;
|
||||
PVOID Context = 0;
|
||||
LARGE_INTEGER Offset;
|
||||
PUSHORT Block = NULL;
|
||||
PUSHORT Block;
|
||||
PUSHORT BlockEnd;
|
||||
|
||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2;
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
|
||||
*Cluster = 0;
|
||||
StartCluster = DeviceExt->LastAvailableCluster;
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
for (i = StartCluster * 2; i < FatLength; i += 2, Block++)
|
||||
for (i = StartCluster; i < FatLength; )
|
||||
{
|
||||
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||
Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
||||
if (Context != NULL)
|
||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
|
||||
BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
|
||||
|
||||
/* Now process the whole block */
|
||||
while (Block < BlockEnd && i < FatLength)
|
||||
{
|
||||
if (*Block == 0)
|
||||
{
|
||||
DPRINT("Found available cluster 0x%x\n", i);
|
||||
DeviceExt->LastAvailableCluster = *Cluster = i;
|
||||
*Block = 0xffff;
|
||||
CcSetDirtyPinnedData(Context, NULL);
|
||||
CcUnpinData(Context);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
CHECKPOINT;
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CHECKPOINT;
|
||||
Block = (PUSHORT)((char*)BaseAddress + i % ChunkSize);
|
||||
|
||||
Block++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (*Block == 0)
|
||||
{
|
||||
DPRINT("Found available cluster 0x%x\n", i / 2);
|
||||
DeviceExt->LastAvailableCluster = *Cluster = i / 2;
|
||||
CcUnpinData(Context);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
FatLength = StartCluster * 2;
|
||||
StartCluster = 2;
|
||||
if (Context != NULL)
|
||||
{
|
||||
CcUnpinData(Context);
|
||||
Context =NULL;
|
||||
}
|
||||
FatLength = StartCluster;
|
||||
StartCluster = 2;
|
||||
}
|
||||
return(STATUS_DISK_FULL);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
||||
FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
||||
/*
|
||||
* FUNCTION: Finds the first available cluster in a FAT12 table
|
||||
*/
|
||||
|
@ -233,7 +232,12 @@ FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
|||
{
|
||||
DPRINT("Found available cluster 0x%x\n", i);
|
||||
DeviceExt->LastAvailableCluster = *Cluster = i;
|
||||
CcUnpinData(Context);
|
||||
if ((i % 2) == 0)
|
||||
*CBlock = (*CBlock & 0xf000) | 0xfff;
|
||||
else
|
||||
*CBlock = (*CBlock & 0xf) | 0xfff0;
|
||||
CcSetDirtyPinnedData(Context, NULL);
|
||||
CcUnpinData(Context);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +249,7 @@ FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
||||
FAT32FindAndMarkAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
||||
/*
|
||||
* FUNCTION: Finds the first available cluster in a FAT32 table
|
||||
*/
|
||||
|
@ -255,49 +259,50 @@ FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
|||
ULONG i, j;
|
||||
PVOID BaseAddress;
|
||||
ULONG ChunkSize;
|
||||
PVOID Context = 0;
|
||||
PVOID Context;
|
||||
LARGE_INTEGER Offset;
|
||||
PULONG Block = NULL;
|
||||
PULONG Block;
|
||||
PULONG BlockEnd;
|
||||
|
||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4;
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
|
||||
*Cluster = 0;
|
||||
StartCluster = DeviceExt->LastAvailableCluster;
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
for (i = StartCluster * 4; i < FatLength; i += 4, Block++)
|
||||
for (i = StartCluster; i < FatLength;)
|
||||
{
|
||||
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||
Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
||||
if (Context != NULL)
|
||||
{
|
||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
|
||||
BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
|
||||
|
||||
/* Now process the whole block */
|
||||
while (Block < BlockEnd && i < FatLength)
|
||||
{
|
||||
if ((*Block & 0x0fffffff) == 0)
|
||||
{
|
||||
DPRINT("Found available cluster 0x%x\n", i);
|
||||
DeviceExt->LastAvailableCluster = *Cluster = i;
|
||||
*Block = 0x0fffffff;
|
||||
CcSetDirtyPinnedData(Context, NULL);
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PULONG)((char*)BaseAddress + i % ChunkSize);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
Block++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((*Block & 0x0fffffff) == 0)
|
||||
{
|
||||
DPRINT("Found available cluster 0x%x\n", i / 4);
|
||||
DeviceExt->LastAvailableCluster = *Cluster = i / 4;
|
||||
CcUnpinData(Context);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
FatLength = StartCluster * 4;
|
||||
StartCluster = 2;
|
||||
if (Context != NULL)
|
||||
{
|
||||
CcUnpinData(Context);
|
||||
Context=NULL;
|
||||
}
|
||||
FatLength = StartCluster;
|
||||
StartCluster = 2;
|
||||
}
|
||||
return (STATUS_DISK_FULL);
|
||||
}
|
||||
|
@ -355,7 +360,8 @@ FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
* FUNCTION: Counts free clusters in a FAT16 table
|
||||
*/
|
||||
{
|
||||
PUSHORT Block = NULL;
|
||||
PUSHORT Block;
|
||||
PUSHORT BlockEnd;
|
||||
PVOID BaseAddress = NULL;
|
||||
ULONG ulCount = 0;
|
||||
ULONG i;
|
||||
|
@ -365,31 +371,32 @@ FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
ULONG FatLength;
|
||||
|
||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 2;
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
|
||||
|
||||
for (i = 4; i< FatLength; i += 2, Block++)
|
||||
for (i = 2; i < FatLength; )
|
||||
{
|
||||
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||
Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
DPRINT("%d\n", i/2);
|
||||
if (Context)
|
||||
{
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PUSHORT)((char*)BaseAddress + i % ChunkSize);
|
||||
}
|
||||
if (*Block == 0)
|
||||
ulCount++;
|
||||
}
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
|
||||
BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
|
||||
|
||||
/* Now process the whole block */
|
||||
while (Block < BlockEnd && i < FatLength)
|
||||
{
|
||||
if (*Block == 0)
|
||||
ulCount++;
|
||||
Block++;
|
||||
i++;
|
||||
}
|
||||
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
|
||||
DeviceExt->AvailableClusters = ulCount;
|
||||
DeviceExt->AvailableClustersValid = TRUE;
|
||||
CcUnpinData(Context);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -401,7 +408,8 @@ FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
* FUNCTION: Counts free clusters in a FAT32 table
|
||||
*/
|
||||
{
|
||||
PULONG Block = NULL;
|
||||
PULONG Block;
|
||||
PULONG BlockEnd;
|
||||
PVOID BaseAddress = NULL;
|
||||
ULONG ulCount = 0;
|
||||
ULONG i;
|
||||
|
@ -411,30 +419,33 @@ FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
ULONG FatLength;
|
||||
|
||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4;
|
||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
|
||||
|
||||
for (i = 8; i< FatLength; i += 4, Block++)
|
||||
for (i = 2; i < FatLength; )
|
||||
{
|
||||
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||
{
|
||||
if (Context)
|
||||
{
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PULONG)((char*)BaseAddress + i % ChunkSize);
|
||||
}
|
||||
if ((*Block & 0x0fffffff) == 0)
|
||||
ulCount++;
|
||||
Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
|
||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||
{
|
||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
|
||||
BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
|
||||
|
||||
/* Now process the whole block */
|
||||
while (Block < BlockEnd && i < FatLength)
|
||||
{
|
||||
if ((*Block & 0x0fffffff) == 0)
|
||||
ulCount++;
|
||||
Block++;
|
||||
i++;
|
||||
}
|
||||
|
||||
CcUnpinData(Context);
|
||||
}
|
||||
|
||||
DeviceExt->AvailableClusters = ulCount;
|
||||
DeviceExt->AvailableClustersValid = TRUE;
|
||||
CcUnpinData(Context);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -592,25 +603,14 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
NTSTATUS Status;
|
||||
ULONG OldValue;
|
||||
ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
|
||||
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||
{
|
||||
Status = FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
|
||||
}
|
||||
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||
{
|
||||
Status = FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
|
||||
}
|
||||
Status = DeviceExt->WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
|
||||
if (DeviceExt->AvailableClustersValid)
|
||||
{
|
||||
{
|
||||
if (OldValue && NewValue == 0)
|
||||
InterlockedIncrement(&DeviceExt->AvailableClusters);
|
||||
else if (OldValue == 0 && NewValue)
|
||||
InterlockedDecrement(&DeviceExt->AvailableClusters);
|
||||
}
|
||||
}
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
|
@ -659,37 +659,13 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
{
|
||||
ULONG NewCluster;
|
||||
|
||||
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||
{
|
||||
CHECKPOINT;
|
||||
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
||||
CHECKPOINT;
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||
{
|
||||
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = FAT12FindAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
/* Mark the new AU as the EOF */
|
||||
WriteCluster (DeviceExt, NewCluster, 0xFFFFFFFF);
|
||||
Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return Status;
|
||||
}
|
||||
|
||||
*NextCluster = NewCluster;
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -700,53 +676,22 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||
{
|
||||
Status = Fat16GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
||||
}
|
||||
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||
{
|
||||
Status = Fat32GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = Fat12GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
||||
}
|
||||
Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
||||
|
||||
if (Extend && (*NextCluster) == 0xFFFFFFFF)
|
||||
{
|
||||
ULONG NewCluster;
|
||||
|
||||
/* We are after last existing cluster, we must add one to file */
|
||||
/* Firstly, find the next available open allocation unit */
|
||||
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||
{
|
||||
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||
{
|
||||
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = FAT12FindAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
/* Mark the new AU as the EOF */
|
||||
WriteCluster(DeviceExt, NewCluster, 0xFFFFFFFF);
|
||||
/* Firstly, find the next available open allocation unit and
|
||||
mark it as end of file */
|
||||
Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Now, write the AU of the LastCluster with the value of the newly
|
||||
found AU */
|
||||
WriteCluster(DeviceExt, CurrentCluster, NewCluster);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: fcb.c,v 1.39 2004/07/18 17:38:17 greatlrd Exp $
|
||||
/* $Id: fcb.c,v 1.40 2004/08/01 21:57:17 navaraf Exp $
|
||||
*
|
||||
*
|
||||
* FILE: drivers/fs/vfat/fcb.c
|
||||
|
@ -110,6 +110,7 @@ vfatNewFCB(PUNICODE_STRING pFileNameU)
|
|||
ExInitializeResourceLite(&rcFCB->PagingIoResource);
|
||||
ExInitializeResourceLite(&rcFCB->MainResource);
|
||||
FsRtlInitializeFileLock(&rcFCB->FileLock, NULL, NULL);
|
||||
ExInitializeFastMutex(&rcFCB->LastMutex);
|
||||
return rcFCB;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: finfo.c,v 1.35 2004/05/23 13:34:32 hbirr Exp $
|
||||
/* $Id: finfo.c,v 1.36 2004/08/01 21:57:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -178,7 +178,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
PFILE_DISPOSITION_INFORMATION DispositionInfo)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
int count;
|
||||
|
||||
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
|
||||
|
||||
|
@ -199,7 +198,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
{
|
||||
if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
|
||||
{
|
||||
count = FCB->RefCount;
|
||||
if (FCB->RefCount > 1)
|
||||
{
|
||||
DPRINT1("%d %x\n", FCB->RefCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer));
|
||||
|
@ -213,10 +211,9 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
|||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("MmFlushImageSection returned FALSE\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
DPRINT("MmFlushImageSection returned FALSE\n");
|
||||
Status = STATUS_CANNOT_DELETE;
|
||||
}
|
||||
DPRINT("RefCount:%d\n", count);
|
||||
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
|
||||
{
|
||||
if (!VfatIsDirectoryEmpty(FCB))
|
||||
|
@ -453,6 +450,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
AllocSizeChanged = TRUE;
|
||||
if (FirstCluster == 0)
|
||||
{
|
||||
Fcb->LastCluster = Fcb->LastOffset = 0;
|
||||
Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -464,29 +462,44 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
return STATUS_DISK_FULL;
|
||||
}
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(NewSize - 1, ClusterSize),
|
||||
&NCluster, TRUE);
|
||||
ROUND_DOWN(NewSize - 1, ClusterSize),
|
||||
&NCluster, TRUE);
|
||||
if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
|
||||
{
|
||||
/* disk is full */
|
||||
/* disk is full */
|
||||
NCluster = Cluster = FirstCluster;
|
||||
Status = STATUS_SUCCESS;
|
||||
Status = STATUS_SUCCESS;
|
||||
while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
|
||||
{
|
||||
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
|
||||
{
|
||||
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
|
||||
WriteCluster (DeviceExt, Cluster, 0);
|
||||
Cluster = NCluster;
|
||||
}
|
||||
return STATUS_DISK_FULL;
|
||||
Cluster = NCluster;
|
||||
}
|
||||
return STATUS_DISK_FULL;
|
||||
}
|
||||
Fcb->entry.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
|
||||
Fcb->entry.FirstClusterHigh = (unsigned short)((FirstCluster & 0xFFFF0000) >> 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
|
||||
&Cluster, FALSE);
|
||||
if (Fcb->LastCluster > 0 &&
|
||||
(Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize) > Fcb->LastOffset)
|
||||
{
|
||||
Status = OffsetToCluster(DeviceExt, Fcb->LastCluster,
|
||||
Fcb->RFCB.AllocationSize.u.LowPart -
|
||||
ClusterSize - Fcb->LastOffset,
|
||||
&Cluster, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
|
||||
&Cluster, FALSE);
|
||||
}
|
||||
|
||||
Fcb->LastCluster = Cluster;
|
||||
Fcb->LastOffset = Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize;
|
||||
|
||||
/* FIXME: Check status */
|
||||
/* Cluster points now to the last cluster within the chain */
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
|
@ -513,6 +526,8 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
|
|||
else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
|
||||
{
|
||||
AllocSizeChanged = TRUE;
|
||||
/* FIXME: Use the cached cluster/offset better way. */
|
||||
Fcb->LastCluster = Fcb->LastCluster = 0;
|
||||
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
|
||||
if (NewSize > 0)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: fsctl.c,v 1.33 2004/07/05 21:39:02 hbirr Exp $
|
||||
/* $Id: fsctl.c,v 1.34 2004/08/01 21:57:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -426,6 +426,27 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
|
|||
ExInitializeResourceLite(&DeviceExt->DirResource);
|
||||
ExInitializeResourceLite(&DeviceExt->FatResource);
|
||||
|
||||
switch (DeviceExt->FatInfo.FatType)
|
||||
{
|
||||
case FAT12:
|
||||
DeviceExt->GetNextCluster = FAT12GetNextCluster;
|
||||
DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
|
||||
DeviceExt->WriteCluster = FAT12WriteCluster;
|
||||
break;
|
||||
|
||||
case FAT16:
|
||||
DeviceExt->GetNextCluster = FAT16GetNextCluster;
|
||||
DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
|
||||
DeviceExt->WriteCluster = FAT16WriteCluster;
|
||||
break;
|
||||
|
||||
case FAT32:
|
||||
DeviceExt->GetNextCluster = FAT32GetNextCluster;
|
||||
DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
|
||||
DeviceExt->WriteCluster = FAT32WriteCluster;
|
||||
break;
|
||||
}
|
||||
|
||||
InitializeListHead(&DeviceExt->FcbListHead);
|
||||
RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$");
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.43 2003/10/11 17:51:56 hbirr Exp $
|
||||
# $Id: makefile,v 1.44 2004/08/01 21:57:18 navaraf Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
|
@ -40,7 +40,7 @@ include $(PATH_TO_TOP)/config
|
|||
ifeq ($(DBG), 1)
|
||||
TARGET_CFLAGS = -Wall -Werror -g
|
||||
else
|
||||
TARGET_CFLAGS = -Wall -Werror -fno-strict-aliasing -O6
|
||||
TARGET_CFLAGS = -Wall -Werror -Wno-strict-aliasing -O6
|
||||
endif
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
/* $Id: rw.c,v 1.66 2004/05/15 23:00:02 hbirr Exp $
|
||||
/* $Id: rw.c,v 1.67 2004/08/01 21:57:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -22,6 +22,15 @@
|
|||
|
||||
#include "vfat.h"
|
||||
|
||||
/*
|
||||
* Uncomment to enable strict verification of cluster/offset pair
|
||||
* caching. If this option is enabled you lose all the benefits of
|
||||
* the caching and the read/write operations will actually be
|
||||
* slower. It's meant only for debugging!!!
|
||||
* - Filip Navara, 26/07/2004
|
||||
*/
|
||||
/* #define DEBUG_VERIFY_OFFSET_CACHING */
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -41,26 +50,8 @@ NextCluster(PDEVICE_EXTENSION DeviceExt,
|
|||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* CN: FIXME: Real bug here or in dirwr, where CurrentCluster isn't
|
||||
* initialized when 0
|
||||
*/
|
||||
if (FirstCluster == 0)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = GetNextCluster(DeviceExt, 0, CurrentCluster,
|
||||
Extend);
|
||||
return(Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = GetNextCluster(DeviceExt, (*CurrentCluster), CurrentCluster,
|
||||
Extend);
|
||||
return(Status);
|
||||
}
|
||||
return GetNextCluster(DeviceExt, (*CurrentCluster), CurrentCluster,
|
||||
Extend);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +126,8 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext,
|
|||
ULONG BytesDone;
|
||||
ULONG BytesPerSector;
|
||||
ULONG BytesPerCluster;
|
||||
ULONG Count;
|
||||
ULONG LastCluster;
|
||||
ULONG LastOffset;
|
||||
|
||||
/* PRECONDITION */
|
||||
assert (IrpContext);
|
||||
|
@ -216,27 +208,51 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext,
|
|||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
ExAcquireFastMutex(&Fcb->LastMutex);
|
||||
LastCluster = Fcb->LastCluster;
|
||||
LastOffset = Fcb->LastOffset;
|
||||
ExReleaseFastMutex(&Fcb->LastMutex);
|
||||
|
||||
/*
|
||||
* Find the cluster to start the read from
|
||||
*/
|
||||
if (Ccb->LastCluster > 0 && ReadOffset.u.LowPart > Ccb->LastOffset)
|
||||
if (LastCluster > 0 && ReadOffset.u.LowPart >= LastOffset)
|
||||
{
|
||||
CurrentCluster = Ccb->LastCluster;
|
||||
Status = OffsetToCluster(DeviceExt, LastCluster,
|
||||
ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster) -
|
||||
LastOffset,
|
||||
&CurrentCluster, FALSE);
|
||||
#ifdef DEBUG_VERIFY_OFFSET_CACHING
|
||||
/* DEBUG VERIFICATION */
|
||||
{
|
||||
ULONG CorrectCluster;
|
||||
OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
|
||||
&CorrectCluster, FALSE);
|
||||
if (CorrectCluster != CurrentCluster)
|
||||
KEBUGCHECK(FAT_FILE_SYSTEM);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
|
||||
&CurrentCluster, FALSE);
|
||||
}
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster),
|
||||
&CurrentCluster, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Ccb->LastCluster = CurrentCluster;
|
||||
Ccb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster);
|
||||
ExAcquireFastMutex(&Fcb->LastMutex);
|
||||
Fcb->LastCluster = CurrentCluster;
|
||||
Fcb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster);
|
||||
ExReleaseFastMutex(&Fcb->LastMutex);
|
||||
|
||||
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
||||
IrpContext->RefCount = 1;
|
||||
Count = 0;
|
||||
|
||||
while (Length > 0 && CurrentCluster != 0xffffffff)
|
||||
{
|
||||
|
@ -271,10 +287,10 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext,
|
|||
DPRINT("start %08x, next %08x, count %d\n",
|
||||
StartCluster, CurrentCluster, ClusterCount);
|
||||
|
||||
Ccb->LastCluster = StartCluster + (ClusterCount - 1);
|
||||
Ccb->LastOffset = ReadOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
|
||||
|
||||
Count++;
|
||||
ExAcquireFastMutex(&Fcb->LastMutex);
|
||||
Fcb->LastCluster = StartCluster + (ClusterCount - 1);
|
||||
Fcb->LastOffset = ReadOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
|
||||
ExReleaseFastMutex(&Fcb->LastMutex);
|
||||
|
||||
// Fire up the read command
|
||||
Status = VfatReadDiskPartial (IrpContext, &StartOffset, BytesDone, *LengthRead, FALSE);
|
||||
|
@ -324,6 +340,8 @@ VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
|
|||
ULONG BytesPerCluster;
|
||||
LARGE_INTEGER StartOffset;
|
||||
ULONG BufferOffset;
|
||||
ULONG LastCluster;
|
||||
ULONG LastOffset;
|
||||
|
||||
/* PRECONDITION */
|
||||
assert (IrpContext);
|
||||
|
@ -400,28 +418,50 @@ VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
|
|||
return Status;
|
||||
}
|
||||
|
||||
ExAcquireFastMutex(&Fcb->LastMutex);
|
||||
LastCluster = Fcb->LastCluster;
|
||||
LastOffset = Fcb->LastOffset;
|
||||
ExReleaseFastMutex(&Fcb->LastMutex);
|
||||
|
||||
/*
|
||||
* Find the cluster to start the write from
|
||||
*/
|
||||
if (Ccb->LastCluster > 0 && WriteOffset.u.LowPart > Ccb->LastOffset)
|
||||
if (LastCluster > 0 && WriteOffset.u.LowPart >= LastOffset)
|
||||
{
|
||||
CurrentCluster = Ccb->LastCluster;
|
||||
Status = OffsetToCluster(DeviceExt, LastCluster,
|
||||
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) -
|
||||
LastOffset,
|
||||
&CurrentCluster, FALSE);
|
||||
#ifdef DEBUG_VERIFY_OFFSET_CACHING
|
||||
/* DEBUG VERIFICATION */
|
||||
{
|
||||
ULONG CorrectCluster;
|
||||
OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
|
||||
&CorrectCluster, FALSE);
|
||||
if (CorrectCluster != CurrentCluster)
|
||||
KEBUGCHECK(FAT_FILE_SYSTEM);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
|
||||
&CurrentCluster, FALSE);
|
||||
}
|
||||
|
||||
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
||||
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
|
||||
&CurrentCluster, FALSE);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Ccb->LastCluster = CurrentCluster;
|
||||
Ccb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster);
|
||||
ExAcquireFastMutex(&Fcb->LastMutex);
|
||||
Fcb->LastCluster = CurrentCluster;
|
||||
Fcb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster);
|
||||
ExReleaseFastMutex(&Fcb->LastMutex);
|
||||
|
||||
IrpContext->RefCount = 1;
|
||||
Count = 0;
|
||||
BufferOffset = 0;
|
||||
|
||||
while (Length > 0 && CurrentCluster != 0xffffffff)
|
||||
|
@ -457,12 +497,13 @@ VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
|
|||
DPRINT("start %08x, next %08x, count %d\n",
|
||||
StartCluster, CurrentCluster, ClusterCount);
|
||||
|
||||
Ccb->LastCluster = StartCluster + (ClusterCount - 1);
|
||||
Ccb->LastOffset = WriteOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
|
||||
ExAcquireFastMutex(&Fcb->LastMutex);
|
||||
Fcb->LastCluster = StartCluster + (ClusterCount - 1);
|
||||
Fcb->LastOffset = WriteOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
|
||||
ExReleaseFastMutex(&Fcb->LastMutex);
|
||||
|
||||
// Fire up the write command
|
||||
Status = VfatWriteDiskPartial (IrpContext, &StartOffset, BytesDone, BufferOffset, FALSE);
|
||||
Count++;
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
|
||||
{
|
||||
break;
|
||||
|
@ -629,11 +670,8 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
|
|||
if (IrpContext->FileObject->PrivateCacheMap == NULL)
|
||||
{
|
||||
ULONG CacheSize;
|
||||
CacheSize = IrpContext->DeviceExt->FatInfo.BytesPerCluster;
|
||||
if (CacheSize < PAGE_SIZE)
|
||||
{
|
||||
CacheSize = PAGE_SIZE;
|
||||
}
|
||||
CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster,
|
||||
8 * PAGE_SIZE);
|
||||
CcRosInitializeFileCache(IrpContext->FileObject, CacheSize);
|
||||
}
|
||||
if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length,
|
||||
|
@ -655,7 +693,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
|
|||
CHECKPOINT;
|
||||
if (ByteOffset.QuadPart + Length > ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector))
|
||||
{
|
||||
Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
|
||||
Length = ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart;
|
||||
}
|
||||
|
||||
Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
|
||||
|
@ -910,7 +948,6 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
|
||||
!(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME)))
|
||||
{
|
||||
|
@ -920,11 +957,8 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
|
|||
if (IrpContext->FileObject->PrivateCacheMap == NULL)
|
||||
{
|
||||
ULONG CacheSize;
|
||||
CacheSize = IrpContext->DeviceExt->FatInfo.BytesPerCluster;
|
||||
if (CacheSize < PAGE_SIZE)
|
||||
{
|
||||
CacheSize = PAGE_SIZE;
|
||||
}
|
||||
CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster,
|
||||
8 * PAGE_SIZE);
|
||||
CcRosInitializeFileCache(IrpContext->FileObject, CacheSize);
|
||||
}
|
||||
if (ByteOffset.QuadPart > OldFileSize.QuadPart)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: vfat.h,v 1.65 2004/07/05 21:39:02 hbirr Exp $ */
|
||||
/* $Id: vfat.h,v 1.66 2004/08/01 21:57:18 navaraf Exp $ */
|
||||
|
||||
#include <ddk/ntifs.h>
|
||||
|
||||
|
@ -144,7 +144,13 @@ HASHENTRY;
|
|||
|
||||
#define FCB_HASH_TABLE_SIZE 1024
|
||||
|
||||
typedef struct
|
||||
typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION;
|
||||
|
||||
typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG);
|
||||
typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG);
|
||||
typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG);
|
||||
|
||||
typedef struct DEVICE_EXTENSION
|
||||
{
|
||||
ERESOURCE DirResource;
|
||||
ERESOURCE FatResource;
|
||||
|
@ -162,8 +168,13 @@ typedef struct
|
|||
ULONG Flags;
|
||||
struct _VFATFCB * VolumeFcb;
|
||||
|
||||
/* Pointers to functions for manipulating FAT. */
|
||||
PGET_NEXT_CLUSTER GetNextCluster;
|
||||
PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
|
||||
PWRITE_CLUSTER WriteCluster;
|
||||
|
||||
LIST_ENTRY VolumeListEntry;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
|
||||
} DEVICE_EXTENSION, VCB, *PVCB;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -249,6 +260,14 @@ typedef struct _VFATFCB
|
|||
/* List of byte-range locks for this file */
|
||||
FILE_LOCK FileLock;
|
||||
|
||||
/*
|
||||
* Optimalization: caching of last read/write cluster+offset pair. Can't
|
||||
* be in VFATCCB because it must be reset everytime the allocated clusters
|
||||
* change.
|
||||
*/
|
||||
FAST_MUTEX LastMutex;
|
||||
ULONG LastCluster;
|
||||
ULONG LastOffset;
|
||||
} VFATFCB, *PVFATFCB;
|
||||
|
||||
typedef struct _VFATCCB
|
||||
|
@ -258,9 +277,6 @@ typedef struct _VFATCCB
|
|||
ULONG Entry;
|
||||
/* for DirectoryControl */
|
||||
UNICODE_STRING SearchPattern;
|
||||
ULONG LastCluster;
|
||||
ULONG LastOffset;
|
||||
|
||||
} VFATCCB, *PVFATCCB;
|
||||
|
||||
#ifndef TAG
|
||||
|
@ -446,6 +462,42 @@ BOOLEAN wstrcmpjoki (PWSTR s1,
|
|||
|
||||
/* ----------------------------------------------------------- fat.c */
|
||||
|
||||
NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG CurrentCluster,
|
||||
PULONG NextCluster);
|
||||
|
||||
NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
PULONG Cluster);
|
||||
|
||||
NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ClusterToWrite,
|
||||
ULONG NewValue,
|
||||
PULONG OldValue);
|
||||
|
||||
NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG CurrentCluster,
|
||||
PULONG NextCluster);
|
||||
|
||||
NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
PULONG Cluster);
|
||||
|
||||
NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ClusterToWrite,
|
||||
ULONG NewValue,
|
||||
PULONG OldValue);
|
||||
|
||||
NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG CurrentCluster,
|
||||
PULONG NextCluster);
|
||||
|
||||
NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
PULONG Cluster);
|
||||
|
||||
NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ClusterToWrite,
|
||||
ULONG NewValue,
|
||||
PULONG OldValue);
|
||||
|
||||
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG FirstCluster,
|
||||
ULONG FileOffset,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: volume.c,v 1.25 2003/11/12 15:26:44 ekohl Exp $
|
||||
/* $Id: volume.c,v 1.26 2004/08/01 21:57:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -67,7 +67,6 @@ FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
|
|||
DPRINT("FsdGetFsAttributeInformation()\n");
|
||||
DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length));
|
||||
|
||||
if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
@ -83,6 +82,8 @@ FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
|
|||
pName = L"FAT";
|
||||
}
|
||||
|
||||
DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length));
|
||||
|
||||
if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
|
|
Loading…
Reference in a new issue