diff --git a/reactos/drivers/fs/vfat/create.c b/reactos/drivers/fs/vfat/create.c index 433a516891c..191b1b5bd63 100644 --- a/reactos/drivers/fs/vfat/create.c +++ b/reactos/drivers/fs/vfat/create.c @@ -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) { diff --git a/reactos/drivers/fs/vfat/direntry.c b/reactos/drivers/fs/vfat/direntry.c index 4022975670a..23bc140857c 100644 --- a/reactos/drivers/fs/vfat/direntry.c +++ b/reactos/drivers/fs/vfat/direntry.c @@ -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; } - - - - - - - - diff --git a/reactos/drivers/fs/vfat/dirwr.c b/reactos/drivers/fs/vfat/dirwr.c index 4a885c51ac1..ac001f0e0e3 100644 --- a/reactos/drivers/fs/vfat/dirwr.c +++ b/reactos/drivers/fs/vfat/dirwr.c @@ -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"); diff --git a/reactos/drivers/fs/vfat/fat.c b/reactos/drivers/fs/vfat/fat.c index 43fbfda71b2..e2b8e82f234 100644 --- a/reactos/drivers/fs/vfat/fat.c +++ b/reactos/drivers/fs/vfat/fat.c @@ -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); diff --git a/reactos/drivers/fs/vfat/fcb.c b/reactos/drivers/fs/vfat/fcb.c index 528f3fb3b5c..78156a5e093 100644 --- a/reactos/drivers/fs/vfat/fcb.c +++ b/reactos/drivers/fs/vfat/fcb.c @@ -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; } diff --git a/reactos/drivers/fs/vfat/finfo.c b/reactos/drivers/fs/vfat/finfo.c index 94546f58632..2a2d8862447 100644 --- a/reactos/drivers/fs/vfat/finfo.c +++ b/reactos/drivers/fs/vfat/finfo.c @@ -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) { diff --git a/reactos/drivers/fs/vfat/fsctl.c b/reactos/drivers/fs/vfat/fsctl.c index f179d268afc..9fb5a95053d 100644 --- a/reactos/drivers/fs/vfat/fsctl.c +++ b/reactos/drivers/fs/vfat/fsctl.c @@ -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$$"); diff --git a/reactos/drivers/fs/vfat/makefile b/reactos/drivers/fs/vfat/makefile index 26c1abdae2a..6b0e913d92e 100644 --- a/reactos/drivers/fs/vfat/makefile +++ b/reactos/drivers/fs/vfat/makefile @@ -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 diff --git a/reactos/drivers/fs/vfat/rw.c b/reactos/drivers/fs/vfat/rw.c index 9facfb46857..7db6da35d44 100644 --- a/reactos/drivers/fs/vfat/rw.c +++ b/reactos/drivers/fs/vfat/rw.c @@ -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) diff --git a/reactos/drivers/fs/vfat/vfat.h b/reactos/drivers/fs/vfat/vfat.h index 56c2f151104..d583480a17e 100644 --- a/reactos/drivers/fs/vfat/vfat.h +++ b/reactos/drivers/fs/vfat/vfat.h @@ -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 @@ -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, diff --git a/reactos/drivers/fs/vfat/volume.c b/reactos/drivers/fs/vfat/volume.c index 1b1797518c9..da5dffd79ee 100644 --- a/reactos/drivers/fs/vfat/volume.c +++ b/reactos/drivers/fs/vfat/volume.c @@ -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;