1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: drivers/fs/vfat/flush.c 5 * PURPOSE: VFAT Filesystem 6 * PROGRAMMER: 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include "vfat.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* FUNCTIONS ****************************************************************/ 17 18 static 19 NTSTATUS 20 VfatFlushFile( 21 PDEVICE_EXTENSION DeviceExt, 22 PVFATFCB Fcb) 23 { 24 IO_STATUS_BLOCK IoStatus; 25 NTSTATUS Status; 26 27 DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU); 28 29 CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus); 30 if (IoStatus.Status == STATUS_INVALID_PARAMETER) 31 { 32 /* FIXME: Caching was possible not initialized */ 33 IoStatus.Status = STATUS_SUCCESS; 34 } 35 36 if (BooleanFlagOn(Fcb->Flags, FCB_IS_DIRTY)) 37 { 38 Status = VfatUpdateEntry(DeviceExt, Fcb); 39 if (!NT_SUCCESS(Status)) 40 { 41 IoStatus.Status = Status; 42 } 43 } 44 return IoStatus.Status; 45 } 46 47 NTSTATUS 48 VfatFlushVolume( 49 PDEVICE_EXTENSION DeviceExt, 50 PVFATFCB VolumeFcb) 51 { 52 PLIST_ENTRY ListEntry; 53 PVFATFCB Fcb; 54 NTSTATUS Status, ReturnStatus = STATUS_SUCCESS; 55 PIRP Irp; 56 KEVENT Event; 57 IO_STATUS_BLOCK IoStatusBlock; 58 59 DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb); 60 61 ListEntry = DeviceExt->FcbListHead.Flink; 62 while (ListEntry != &DeviceExt->FcbListHead) 63 { 64 Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry); 65 ListEntry = ListEntry->Flink; 66 if (!vfatFCBIsDirectory(Fcb)) 67 { 68 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 69 Status = VfatFlushFile(DeviceExt, Fcb); 70 ExReleaseResourceLite (&Fcb->MainResource); 71 if (!NT_SUCCESS(Status)) 72 { 73 DPRINT1("VfatFlushFile failed, status = %x\n", Status); 74 ReturnStatus = Status; 75 } 76 } 77 /* FIXME: Stop flushing if this is a removable media and the media was removed */ 78 } 79 80 ListEntry = DeviceExt->FcbListHead.Flink; 81 while (ListEntry != &DeviceExt->FcbListHead) 82 { 83 Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry); 84 ListEntry = ListEntry->Flink; 85 if (vfatFCBIsDirectory(Fcb)) 86 { 87 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 88 Status = VfatFlushFile(DeviceExt, Fcb); 89 ExReleaseResourceLite (&Fcb->MainResource); 90 if (!NT_SUCCESS(Status)) 91 { 92 DPRINT1("VfatFlushFile failed, status = %x\n", Status); 93 ReturnStatus = Status; 94 } 95 } 96 /* FIXME: Stop flushing if this is a removable media and the media was removed */ 97 } 98 99 Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext; 100 101 ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE); 102 Status = VfatFlushFile(DeviceExt, Fcb); 103 ExReleaseResourceLite(&DeviceExt->FatResource); 104 105 /* Prepare an IRP to flush device buffers */ 106 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, 107 DeviceExt->StorageDevice, 108 NULL, 0, NULL, &Event, 109 &IoStatusBlock); 110 if (Irp != NULL) 111 { 112 KeInitializeEvent(&Event, NotificationEvent, FALSE); 113 114 Status = IoCallDriver(DeviceExt->StorageDevice, Irp); 115 if (Status == STATUS_PENDING) 116 { 117 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 118 Status = IoStatusBlock.Status; 119 } 120 121 /* Ignore device not supporting flush operation */ 122 if (Status == STATUS_INVALID_DEVICE_REQUEST) 123 { 124 DPRINT1("Flush not supported, ignored\n"); 125 Status = STATUS_SUCCESS; 126 127 } 128 } 129 else 130 { 131 Status = STATUS_INSUFFICIENT_RESOURCES; 132 } 133 134 if (!NT_SUCCESS(Status)) 135 { 136 DPRINT1("VfatFlushFile failed, status = %x\n", Status); 137 ReturnStatus = Status; 138 } 139 140 return ReturnStatus; 141 } 142 143 NTSTATUS 144 VfatFlush( 145 PVFAT_IRP_CONTEXT IrpContext) 146 { 147 NTSTATUS Status; 148 PVFATFCB Fcb; 149 150 /* This request is not allowed on the main device object. */ 151 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) 152 { 153 IrpContext->Irp->IoStatus.Information = 0; 154 return STATUS_INVALID_DEVICE_REQUEST; 155 } 156 157 Fcb = (PVFATFCB)IrpContext->FileObject->FsContext; 158 ASSERT(Fcb); 159 160 if (BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME)) 161 { 162 ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE); 163 Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb); 164 ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); 165 } 166 else 167 { 168 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 169 Status = VfatFlushFile(IrpContext->DeviceExt, Fcb); 170 ExReleaseResourceLite (&Fcb->MainResource); 171 } 172 173 IrpContext->Irp->IoStatus.Information = 0; 174 return Status; 175 } 176 177 /* EOF */ 178