- Release streaming file object for directories in vfatReleaseFCB.

- Removed initialization of caching in vfatAttacheFCBToFileObject.
  The cache for files is initialized at the first read/write operation.
- Merged vfatExtendSpace and VfatSetAllocationSizeInformation in one function.

svn path=/trunk/; revision=3339
This commit is contained in:
Hartmut Birr 2002-08-17 15:15:50 +00:00
parent 01d5ad9279
commit 6130c02167
6 changed files with 157 additions and 226 deletions

View file

@ -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.43 2002/08/14 20:58:31 dwelch Exp $
/* $Id: create.c,v 1.44 2002/08/17 15:15:50 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/create.c
@ -759,7 +759,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
Irp->IoStatus.Information = FILE_CREATED;
VfatSetAllocationSizeInformation(FileObject,
pFcb,
DeviceObject,
DeviceExt,
&Irp->Overlay.AllocationSize);
VfatSetExtendedAttributes(FileObject,
Irp->AssociatedIrp.SystemBuffer,

View file

@ -1,4 +1,4 @@
/* $Id: dirwr.c,v 1.27 2002/08/14 20:58:31 dwelch Exp $
/* $Id: dirwr.c,v 1.28 2002/08/17 15:15:50 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -135,6 +135,7 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
*start = i - nbFree;
if (*start + nbSlots > count)
{
LARGE_INTEGER AllocationSize;
CHECKPOINT;
// extend the directory
if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32)
@ -142,8 +143,9 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
// We can't extend a root directory on a FAT12/FAT16 partition
return FALSE;
}
Status = vfatExtendSpace (DeviceExt, pDirFcb->FileObject,
pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster);
AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster;
Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb,
DeviceExt, &AllocationSize);
if (!NT_SUCCESS(Status))
{
return FALSE;
@ -488,12 +490,12 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
}
size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = start * sizeof(FATDirEntry);
if (start / size == (start + nbSlots - 1) / size)
{
// one cluster
CHECKPOINT;
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = start * sizeof(FATDirEntry);
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, nbSlots * sizeof(FATDirEntry));
@ -502,8 +504,6 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
{
// two clusters
CHECKPOINT;
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = start * sizeof(FATDirEntry);
size = DeviceExt->FatInfo.BytesPerCluster -
(start * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster;
CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE,

View file

@ -1,4 +1,4 @@
/* $Id: fcb.c,v 1.17 2002/08/14 20:58:31 dwelch Exp $
/* $Id: fcb.c,v 1.18 2002/08/17 15:15:50 hbirr Exp $
*
*
* FILE: fcb.c
@ -105,9 +105,18 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
if (pFCB->RefCount <= 0 && (!vfatFCBIsDirectory (pVCB, pFCB) || pFCB->Flags & FCB_DELETE_PENDING))
{
RemoveEntryList (&pFCB->FcbListEntry);
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
if (vfatFCBIsDirectory(pVCB, pFCB))
{
CcRosReleaseFileCache(pFCB->FileObject, pFCB->RFCB.Bcb);
ExFreePool(pFCB->FileObject->FsContext2);
pFCB->FileObject->FsContext2 = NULL;
ObDereferenceObject(pFCB->FileObject);
}
vfatDestroyFCB (pFCB);
}
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
else
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
}
VOID
@ -190,7 +199,6 @@ vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb)
KeBugCheck (0);
}
ObDereferenceObject (fileObject);
fcb->Flags |= FCB_CACHE_INITIALIZED;
return status;
@ -349,24 +357,6 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
newCCB->pFcb = fcb;
newCCB->PtrFileObject = fileObject;
fcb->pDevExt = vcb;
if (!(fcb->Flags & FCB_CACHE_INITIALIZED))
{
ULONG fileCacheQuantum;
fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGESIZE) ?
vcb->FatInfo.BytesPerCluster : PAGESIZE;
status = CcRosInitializeFileCache (fileObject,
&fcb->RFCB.Bcb,
fileCacheQuantum);
if (!NT_SUCCESS (status))
{
DbgPrint ("CcRosInitializeFileCache failed\n");
KeBugCheck (0);
}
fcb->Flags |= FCB_CACHE_INITIALIZED;
}
DPRINT ("file open: fcb:%x file size: %d\n", fcb, fcb->entry.FileSize);
return STATUS_SUCCESS;

View file

@ -1,4 +1,4 @@
/* $Id: finfo.c,v 1.16 2002/08/17 14:14:19 dwelch Exp $
/* $Id: finfo.c,v 1.17 2002/08/17 15:15:50 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -347,90 +347,130 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
NTSTATUS
VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_OBJECT DeviceObject,
PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER AllocationSize)
{
ULONG OldSize;
ULONG FirstCluster;
ULONG Cluster;
ULONG i;
ULONG Offset;
NTSTATUS Status;
PDEVICE_EXTENSION DeviceExt =
(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
ULONG NewSize = AllocationSize->u.LowPart;
ULONG PreviousCluster;
ULONG NCluster;
DPRINT1("VfatSetAllocationSizeInformation()\n");
OldSize = Fcb->entry.FileSize;
if (OldSize == AllocationSize->u.LowPart)
if (AllocationSize->u.HighPart > 0)
{
return STATUS_INVALID_PARAMETER;
}
if (OldSize == NewSize)
{
return(STATUS_SUCCESS);
}
Fcb->entry.FileSize = AllocationSize->u.LowPart;
Fcb->RFCB.AllocationSize = *AllocationSize;
Fcb->RFCB.FileSize = *AllocationSize;
Fcb->RFCB.ValidDataLength = *AllocationSize;
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
Cluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
if (DeviceExt->FatInfo.FatType == FAT32)
if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
{
if (Cluster == 0)
{
FirstCluster = Fcb->entry.FirstCluster +
Fcb->entry.FirstClusterHigh * 65536;
Status = NextCluster (DeviceExt, Fcb, Cluster, &Cluster, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("NextCluster failed.\n");
return Status;
}
if (Cluster == 0xffffffff)
{
return STATUS_DISK_FULL;
}
Status = OffsetToCluster(DeviceExt, Fcb, Cluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&NCluster, TRUE);
if (NCluster == 0xffffffff)
{
/* disk is full */
NCluster = Cluster;
while (Cluster != 0xffffffff)
{
NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
return STATUS_DISK_FULL;
}
Fcb->entry.FirstCluster = (Cluster & 0x0000FFFF);
Fcb->entry.FirstClusterHigh = (Cluster & 0xFFFF0000) >> 16;
}
else
{
Status = OffsetToCluster(DeviceExt, Fcb, Cluster,
Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
&Cluster, FALSE);
/* Cluster points now to the last cluster within the chain */
Status = OffsetToCluster(DeviceExt, Fcb, Cluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&NCluster, TRUE);
if (NCluster == 0xffffffff)
{
/* disk is full */
NCluster = Cluster;
NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
WriteCluster(DeviceExt, Cluster, 0xffffffff);
Cluster = NCluster;
while (Cluster != 0xffffffff)
{
NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
return STATUS_DISK_FULL;
}
}
}
else if (NewSize <= Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize)
{
if (NewSize > 0)
{
Status = OffsetToCluster(DeviceExt, Fcb, Cluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&Cluster, FALSE);
}
NCluster = Cluster;
Status = NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
WriteCluster(DeviceExt, Cluster, 0xffffffff);
Cluster = NCluster;
while (Cluster != 0xffffffff)
{
NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
}
Fcb->entry.FileSize = NewSize;
if (NewSize > 0)
{
Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(NewSize - 1, ClusterSize);
}
else
{
FirstCluster = Fcb->entry.FirstCluster;
}
Cluster = FirstCluster;
if (OldSize > NewSize &&
ROUND_UP(OldSize, ClusterSize) > ROUND_DOWN(NewSize, ClusterSize))
{
/* Seek to the new end of the file. */
for (i = 0; i < (NewSize / ClusterSize); i++)
{
Status = NextCluster (DeviceExt, Fcb, FirstCluster, &Cluster, FALSE);
}
/* Terminate the FAT chain at this point. */
if (NewSize > 0)
{
PreviousCluster = Cluster;
Status = NextCluster (DeviceExt, Fcb, FirstCluster, &Cluster, FALSE);
WriteCluster (DeviceExt, PreviousCluster, 0xFFFFFFFF);
}
/* Free everything beyond this point. */
while (Cluster != 0xffffffff && Cluster > 1)
{
PreviousCluster = Cluster;
Status = NextCluster (DeviceExt, Fcb, FirstCluster, &Cluster, FALSE);
WriteCluster (DeviceExt, PreviousCluster, 0);
}
if (NewSize == 0)
{
Fcb->entry.FirstCluster = 0;
Fcb->entry.FirstClusterHigh = 0;
}
}
else if (NewSize > OldSize &&
ROUND_UP(NewSize, ClusterSize) > ROUND_DOWN(OldSize, ClusterSize))
{
/* Seek to the new end of the file. */
if (OldSize == 0)
{
assert(FirstCluster == 0);
Status = NextCluster (DeviceExt, Fcb, FirstCluster, &Cluster, TRUE);
FirstCluster = Cluster;
Fcb->entry.FirstCluster = (FirstCluster & 0x0000FFFF) >> 0;
Fcb->entry.FirstClusterHigh = (FirstCluster & 0xFFFF0000) >> 16;
}
for (i = 0; i < (NewSize / ClusterSize); i++)
{
Status = NextCluster (DeviceExt, Fcb, FirstCluster, &Cluster, TRUE);
}
}
{
Fcb->RFCB.AllocationSize.QuadPart = 0LL;
Fcb->entry.FirstCluster = 0;
Fcb->entry.FirstClusterHigh = 0;
}
Fcb->RFCB.FileSize.QuadPart = NewSize;
Fcb->RFCB.ValidDataLength.QuadPart = NewSize;
if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
{
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
}
DPRINT1("\n");
/* Update the on-disk directory entry */
VfatUpdateEntry(DeviceExt, FileObject);
return STATUS_SUCCESS;
}
NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
@ -591,7 +631,7 @@ NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
case FileEndOfFileInformation:
RC = VfatSetAllocationSizeInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
IrpContext->DeviceExt,
(PLARGE_INTEGER)SystemBuffer);
break;
case FileBasicInformation:

View file

@ -1,5 +1,5 @@
/* $Id: rw.c,v 1.44 2002/08/14 20:58:31 dwelch Exp $
/* $Id: rw.c,v 1.45 2002/08/17 15:15:50 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -575,123 +575,6 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
return Status;
}
NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject, ULONG NewSize)
{
ULONG FirstCluster;
ULONG CurrentCluster;
ULONG NewCluster;
NTSTATUS Status;
PVFATFCB pFcb;
pFcb = ((PVFATCCB) (pFileObject->FsContext2))->pFcb;
DPRINT ("New Size %d, AllocationSize %d, BytesPerCluster %d\n", NewSize,
(ULONG)pFcb->RFCB.AllocationSize.QuadPart, pDeviceExt->FatInfo.BytesPerCluster);
FirstCluster = CurrentCluster = vfatDirEntryGetFirstCluster (pDeviceExt, &pFcb->entry);
if (NewSize > pFcb->RFCB.AllocationSize.QuadPart || FirstCluster==0)
{
// size on disk must be extended
if (FirstCluster == 0)
{
// file of size zero
Status = NextCluster (pDeviceExt, pFcb, FirstCluster, &CurrentCluster, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("NextCluster failed, Status %x\n", Status);
return Status;
}
NewCluster = FirstCluster = CurrentCluster;
}
else
{
Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster,
pFcb->RFCB.AllocationSize.QuadPart - pDeviceExt->FatInfo.BytesPerCluster,
&CurrentCluster, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("OffsetToCluster failed, Status %x\n", Status);
return Status;
}
if (CurrentCluster == 0xffffffff)
{
DPRINT1("Not enough disk space.\n");
return STATUS_DISK_FULL;
}
// CurrentCluster zeigt jetzt auf den letzten Cluster in der Kette
NewCluster = CurrentCluster;
Status = NextCluster(pDeviceExt, pFcb, FirstCluster, &NewCluster, FALSE);
if (NewCluster != 0xffffffff)
{
DPRINT1("Difference between size from direntry and the FAT.\n");
}
}
Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster,
ROUND_DOWN(NewSize-1, pDeviceExt->FatInfo.BytesPerCluster),
&NewCluster, TRUE);
if (!NT_SUCCESS(Status) || NewCluster == 0xffffffff)
{
DPRINT1("Not enough free space on disk\n");
if (pFcb->RFCB.AllocationSize.QuadPart > 0)
{
NewCluster = CurrentCluster;
// FIXME: check status
NextCluster(pDeviceExt, pFcb, FirstCluster, &NewCluster, FALSE);
WriteCluster(pDeviceExt, CurrentCluster, 0xffffffff);
}
// free the allocated space
while (NewCluster != 0xffffffff)
{
CurrentCluster = NewCluster;
// FIXME: check status
NextCluster (pDeviceExt, pFcb, FirstCluster, &NewCluster, FALSE);
WriteCluster (pDeviceExt, CurrentCluster, 0);
}
return STATUS_DISK_FULL;
}
if (pFcb->RFCB.AllocationSize.QuadPart == 0)
{
pFcb->entry.FirstCluster = FirstCluster;
if(pDeviceExt->FatInfo.FatType == FAT32)
pFcb->entry.FirstClusterHigh = FirstCluster >> 16;
}
pFcb->RFCB.AllocationSize.QuadPart = ROUND_UP(NewSize, pDeviceExt->FatInfo.BytesPerCluster);
if (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pFcb->RFCB.FileSize.QuadPart = pFcb->RFCB.AllocationSize.QuadPart;
pFcb->RFCB.ValidDataLength.QuadPart = pFcb->RFCB.AllocationSize.QuadPart;
}
else
{
pFcb->entry.FileSize = NewSize;
pFcb->RFCB.FileSize.QuadPart = NewSize;
pFcb->RFCB.ValidDataLength.QuadPart = NewSize;
}
CcSetFileSizes(pFileObject, (PCC_FILE_SIZES)&pFcb->RFCB.AllocationSize);
}
else
{
if (NewSize > pFcb->RFCB.FileSize.QuadPart)
{
// size on disk must not be extended
if (!(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
{
pFcb->entry.FileSize = NewSize;
}
pFcb->RFCB.FileSize.QuadPart = NewSize;
CcSetFileSizes(pFileObject, (PCC_FILE_SIZES)&pFcb->RFCB.AllocationSize);
}
else
{
// nothing to do
}
}
return STATUS_SUCCESS;
}
NTSTATUS
VfatRead(PVFAT_IRP_CONTEXT IrpContext)
{
@ -809,6 +692,16 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
}
CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL)
{
ULONG CacheSize;
CacheSize = IrpContext->DeviceExt->FatInfo.BytesPerCluster;
if (CacheSize < PAGESIZE)
{
CacheSize = PAGESIZE;
}
CcRosInitializeFileCache(IrpContext->FileObject, &Fcb->RFCB.Bcb, CacheSize);
}
if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length,
IrpContext->Flags & IRPCONTEXT_CANWAIT, Buffer,
&IrpContext->Irp->IoStatus))
@ -1039,8 +932,10 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
if (!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)) && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
{
Status = vfatExtendSpace(IrpContext->DeviceExt, IrpContext->FileObject,
ByteOffset.u.LowPart + Length);
LARGE_INTEGER AllocationSize;
AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
Status = VfatSetAllocationSizeInformation(IrpContext->FileObject, Fcb,
IrpContext->DeviceExt, &AllocationSize);
CHECKPOINT;
if (!NT_SUCCESS (Status))
{
@ -1067,7 +962,16 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
goto ByeBye;
}
CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL)
{
ULONG CacheSize;
CacheSize = IrpContext->DeviceExt->FatInfo.BytesPerCluster;
if (CacheSize < PAGESIZE)
{
CacheSize = PAGESIZE;
}
CcRosInitializeFileCache(IrpContext->FileObject, &Fcb->RFCB.Bcb, CacheSize);
}
if (CcCopyWrite(IrpContext->FileObject, &ByteOffset, Length,
1 /*IrpContext->Flags & IRPCONTEXT_CANWAIT*/, Buffer))
{

View file

@ -1,4 +1,4 @@
/* $Id: vfat.h,v 1.44 2002/08/14 20:58:32 dwelch Exp $ */
/* $Id: vfat.h,v 1.45 2002/08/17 15:15:50 hbirr Exp $ */
#include <ddk/ntifs.h>
@ -20,7 +20,8 @@ struct _BootSector
unsigned char Drive, Res1, Sig;
unsigned long VolumeID;
unsigned char VolumeLabel[11], SysType[8];
unsigned char Res2[450];
unsigned char Res2[446];
unsigned long Signatur1;
} __attribute__((packed));
struct _BootSector32
@ -327,7 +328,7 @@ NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS
VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_OBJECT DeviceObject,
PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER AllocationSize);
/* --------------------------------------------------------- iface.c */
@ -477,10 +478,6 @@ NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt,
PFILE_OBJECT pFileObject,
ULONG NewSize);
NTSTATUS VfatWriteFile (PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PVOID Buffer,