mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[NTFS] - Fix IncreaseMftSize(); check IrpContext to see if waiting for exclusive access to the MFT is allowed. As pointed out by Pierre.
svn path=/branches/GSoC_2016/NTFS/; revision=75170
This commit is contained in:
parent
9ab86116a9
commit
98ddf610bc
3 changed files with 39 additions and 18 deletions
|
@ -323,7 +323,7 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
|
||||||
static
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PNTFS_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION DeviceExt;
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
|
@ -334,8 +334,9 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
||||||
// PWSTR FileName;
|
// PWSTR FileName;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UNICODE_STRING FullPath;
|
UNICODE_STRING FullPath;
|
||||||
|
PIRP Irp = IrpContext->Irp;
|
||||||
|
|
||||||
DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
|
DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, IrpContext);
|
||||||
|
|
||||||
DeviceExt = DeviceObject->DeviceExtension;
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
ASSERT(DeviceExt);
|
ASSERT(DeviceExt);
|
||||||
|
@ -561,7 +562,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the file record on disk
|
// Create the file record on disk
|
||||||
Status = NtfsCreateFileRecord(DeviceExt, FileObject);
|
Status = NtfsCreateFileRecord(DeviceExt, FileObject, BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT));
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("ERROR: Couldn't create file record!\n");
|
DPRINT1("ERROR: Couldn't create file record!\n");
|
||||||
|
@ -569,7 +570,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we should be able to open the file
|
// Now we should be able to open the file
|
||||||
return NtfsCreateFile(DeviceObject, Irp);
|
return NtfsCreateFile(DeviceObject, IrpContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +616,7 @@ NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
|
||||||
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
|
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
|
||||||
TRUE);
|
TRUE);
|
||||||
Status = NtfsCreateFile(DeviceObject,
|
Status = NtfsCreateFile(DeviceObject,
|
||||||
IrpContext->Irp);
|
IrpContext);
|
||||||
ExReleaseResourceLite(&DeviceExt->DirResource);
|
ExReleaseResourceLite(&DeviceExt->DirResource);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -634,13 +635,20 @@ NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
|
||||||
* @param FileObject
|
* @param FileObject
|
||||||
* Pointer to a FILE_OBJECT describing the file to be created
|
* Pointer to a FILE_OBJECT describing the file to be created
|
||||||
*
|
*
|
||||||
|
* @param CanWait
|
||||||
|
* Boolean indicating if the function is allowed to wait for exclusive access to the master file table.
|
||||||
|
* This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* STATUS_SUCCESS on success.
|
* STATUS_SUCCESS on success.
|
||||||
* STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record.
|
* STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record.
|
||||||
|
* STATUS_CANT_WAIT if CanWait was FALSE and the function needed to resize the MFT but
|
||||||
|
* couldn't get immediate, exclusive access to it.
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
|
NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
|
||||||
PFILE_OBJECT FileObject)
|
PFILE_OBJECT FileObject,
|
||||||
|
BOOLEAN CanWait)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PFILE_RECORD_HEADER FileRecord;
|
PFILE_RECORD_HEADER FileRecord;
|
||||||
|
@ -649,7 +657,7 @@ NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONGLONG ParentMftIndex;
|
ULONGLONG ParentMftIndex;
|
||||||
ULONGLONG FileMftIndex;
|
ULONGLONG FileMftIndex;
|
||||||
|
|
||||||
DPRINT1("NtfsCreateFileRecord(%p, %p)\n", DeviceExt, FileObject);
|
DPRINT1("NtfsCreateFileRecord(%p, %p, %s)\n", DeviceExt, FileObject, CanWait ? "TRUE" : "FALSE");
|
||||||
|
|
||||||
// allocate memory for file record
|
// allocate memory for file record
|
||||||
FileRecord = ExAllocatePoolWithTag(NonPagedPool,
|
FileRecord = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
@ -708,7 +716,7 @@ NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
|
||||||
NtfsDumpFileRecord(DeviceExt, FileRecord);
|
NtfsDumpFileRecord(DeviceExt, FileRecord);
|
||||||
|
|
||||||
// Now that we've built the file record in memory, we need to store it in the MFT.
|
// Now that we've built the file record in memory, we need to store it in the MFT.
|
||||||
Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex);
|
Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
// The highest 2 bytes should be the sequence number, unless the parent happens to be root
|
// The highest 2 bytes should be the sequence number, unless the parent happens to be root
|
||||||
|
|
|
@ -195,10 +195,16 @@ AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
|
||||||
* @param Vcb
|
* @param Vcb
|
||||||
* Pointer to the VCB (DEVICE_EXTENSION) of the target volume.
|
* Pointer to the VCB (DEVICE_EXTENSION) of the target volume.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* @param CanWait
|
||||||
|
* Boolean indicating if the function is allowed to wait for exclusive access to the master file table.
|
||||||
|
* This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* STATUS_SUCCESS on success.
|
* STATUS_SUCCESS on success.
|
||||||
* STATUS_INSUFFICIENT_RESOURCES if an allocation fails.
|
* STATUS_INSUFFICIENT_RESOURCES if an allocation fails.
|
||||||
* STATUS_INVALID_PARAMETER if there was an error reading the Mft's bitmap.
|
* STATUS_INVALID_PARAMETER if there was an error reading the Mft's bitmap.
|
||||||
|
* STATUS_CANT_WAIT if CanWait was FALSE and the function could not get immediate, exclusive access to the MFT.
|
||||||
*
|
*
|
||||||
* @remarks
|
* @remarks
|
||||||
* Increases the size of the Master File Table by 8 records. Bitmap entries for the new records are cleared,
|
* Increases the size of the Master File Table by 8 records. Bitmap entries for the new records are cleared,
|
||||||
|
@ -206,7 +212,7 @@ AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
|
||||||
* This function will wait for exlusive access to the volume fcb.
|
* This function will wait for exlusive access to the volume fcb.
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
IncreaseMftSize(PDEVICE_EXTENSION Vcb)
|
IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
|
||||||
{
|
{
|
||||||
PNTFS_ATTR_CONTEXT BitmapContext;
|
PNTFS_ATTR_CONTEXT BitmapContext;
|
||||||
LARGE_INTEGER BitmapSize;
|
LARGE_INTEGER BitmapSize;
|
||||||
|
@ -221,10 +227,10 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb)
|
||||||
ULONG LengthWritten;
|
ULONG LengthWritten;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT1("IncreaseMftSize(%p)\n", Vcb);
|
DPRINT1("IncreaseMftSize(%p, %s)\n", Vcb, CanWait ? "TRUE" : "FALSE");
|
||||||
|
|
||||||
// We need exclusive access to the mft while we change its size
|
// We need exclusive access to the mft while we change its size
|
||||||
if (!ExAcquireResourceExclusiveLite(&(Vcb->DirResource), TRUE))
|
if (!ExAcquireResourceExclusiveLite(&(Vcb->DirResource), CanWait))
|
||||||
{
|
{
|
||||||
return STATUS_CANT_WAIT;
|
return STATUS_CANT_WAIT;
|
||||||
}
|
}
|
||||||
|
@ -1638,17 +1644,22 @@ FixupUpdateSequenceArray(PDEVICE_EXTENSION Vcb,
|
||||||
* @param DestinationIndex
|
* @param DestinationIndex
|
||||||
* Pointer to a ULONGLONG which will receive the MFT index where the file record was stored.
|
* Pointer to a ULONGLONG which will receive the MFT index where the file record was stored.
|
||||||
*
|
*
|
||||||
|
* @param CanWait
|
||||||
|
* Boolean indicating if the function is allowed to wait for exclusive access to the master file table.
|
||||||
|
* This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* STATUS_SUCCESS on success.
|
* STATUS_SUCCESS on success.
|
||||||
* STATUS_OBJECT_NAME_NOT_FOUND if we can't find the MFT's $Bitmap or if we weren't able
|
* STATUS_OBJECT_NAME_NOT_FOUND if we can't find the MFT's $Bitmap or if we weren't able
|
||||||
* to read the attribute.
|
* to read the attribute.
|
||||||
* STATUS_INSUFFICIENT_RESOURCES if we can't allocate enough memory for a copy of $Bitmap.
|
* STATUS_INSUFFICIENT_RESOURCES if we can't allocate enough memory for a copy of $Bitmap.
|
||||||
*
|
* STATUS_CANT_WAIT if CanWait was FALSE and the function could not get immediate, exclusive access to the MFT.
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
|
AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
|
||||||
PDEVICE_EXTENSION DeviceExt,
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
PULONGLONG DestinationIndex)
|
PULONGLONG DestinationIndex,
|
||||||
|
BOOLEAN CanWait)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
ULONGLONG MftIndex;
|
ULONGLONG MftIndex;
|
||||||
|
@ -1661,7 +1672,7 @@ AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
|
||||||
LARGE_INTEGER BitmapBits;
|
LARGE_INTEGER BitmapBits;
|
||||||
UCHAR SystemReservedBits;
|
UCHAR SystemReservedBits;
|
||||||
|
|
||||||
DPRINT1("AddNewMftEntry(%p, %p, %p)\n", FileRecord, DeviceExt, DestinationIndex);
|
DPRINT1("AddNewMftEntry(%p, %p, %p, %s)\n", FileRecord, DeviceExt, DestinationIndex, CanWait ? "TRUE" : "FALSE");
|
||||||
|
|
||||||
// First, we have to read the mft's $Bitmap attribute
|
// First, we have to read the mft's $Bitmap attribute
|
||||||
Status = FindAttribute(DeviceExt, DeviceExt->MasterFileTable, AttributeBitmap, L"", 0, &BitmapContext, NULL);
|
Status = FindAttribute(DeviceExt, DeviceExt->MasterFileTable, AttributeBitmap, L"", 0, &BitmapContext, NULL);
|
||||||
|
@ -1717,14 +1728,14 @@ AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
|
||||||
ReleaseAttributeContext(BitmapContext);
|
ReleaseAttributeContext(BitmapContext);
|
||||||
|
|
||||||
// Couldn't find a free record in the MFT, add some blank records and try again
|
// Couldn't find a free record in the MFT, add some blank records and try again
|
||||||
Status = IncreaseMftSize(DeviceExt);
|
Status = IncreaseMftSize(DeviceExt, CanWait);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("ERROR: Couldn't find space in MFT for file or increase MFT size!\n");
|
DPRINT1("ERROR: Couldn't find space in MFT for file or increase MFT size!\n");
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AddNewMftEntry(FileRecord, DeviceExt, DestinationIndex);
|
return AddNewMftEntry(FileRecord, DeviceExt, DestinationIndex, CanWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Creating file record at MFT index: %I64u\n", MftIndex);
|
DPRINT1("Creating file record at MFT index: %I64u\n", MftIndex);
|
||||||
|
|
|
@ -667,7 +667,8 @@ NtfsCreate(PNTFS_IRP_CONTEXT IrpContext);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
|
NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt,
|
||||||
PFILE_OBJECT FileObject);
|
PFILE_OBJECT FileObject,
|
||||||
|
BOOLEAN CanWait);
|
||||||
|
|
||||||
/* devctl.c */
|
/* devctl.c */
|
||||||
|
|
||||||
|
@ -825,7 +826,8 @@ NtfsFileSystemControl(PNTFS_IRP_CONTEXT IrpContext);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
|
AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
|
||||||
PDEVICE_EXTENSION DeviceExt,
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
PULONGLONG DestinationIndex);
|
PULONGLONG DestinationIndex,
|
||||||
|
BOOLEAN CanWait);
|
||||||
|
|
||||||
PNTFS_ATTR_CONTEXT
|
PNTFS_ATTR_CONTEXT
|
||||||
PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord);
|
PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord);
|
||||||
|
|
Loading…
Reference in a new issue