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 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE); 37 if (BooleanFlagOn(Fcb->Flags, FCB_IS_DIRTY)) 38 { 39 Status = VfatUpdateEntry(DeviceExt, Fcb); 40 if (!NT_SUCCESS(Status)) 41 { 42 IoStatus.Status = Status; 43 } 44 } 45 ExReleaseResourceLite(&DeviceExt->DirResource); 46 47 return IoStatus.Status; 48 } 49 50 NTSTATUS 51 VfatFlushVolume( 52 PDEVICE_EXTENSION DeviceExt, 53 PVFATFCB VolumeFcb) 54 { 55 PLIST_ENTRY ListEntry; 56 PVFATFCB Fcb; 57 NTSTATUS Status, ReturnStatus = STATUS_SUCCESS; 58 PIRP Irp; 59 KEVENT Event; 60 IO_STATUS_BLOCK IoStatusBlock; 61 62 DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb); 63 64 ListEntry = DeviceExt->FcbListHead.Flink; 65 while (ListEntry != &DeviceExt->FcbListHead) 66 { 67 Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry); 68 ListEntry = ListEntry->Flink; 69 if (!vfatFCBIsDirectory(Fcb)) 70 { 71 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 72 Status = VfatFlushFile(DeviceExt, Fcb); 73 ExReleaseResourceLite (&Fcb->MainResource); 74 if (!NT_SUCCESS(Status)) 75 { 76 DPRINT1("VfatFlushFile failed, status = %x\n", Status); 77 ReturnStatus = Status; 78 } 79 } 80 /* FIXME: Stop flushing if this is a removable media and the media was removed */ 81 } 82 83 ListEntry = DeviceExt->FcbListHead.Flink; 84 while (ListEntry != &DeviceExt->FcbListHead) 85 { 86 Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry); 87 ListEntry = ListEntry->Flink; 88 if (vfatFCBIsDirectory(Fcb)) 89 { 90 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 91 Status = VfatFlushFile(DeviceExt, Fcb); 92 ExReleaseResourceLite (&Fcb->MainResource); 93 if (!NT_SUCCESS(Status)) 94 { 95 DPRINT1("VfatFlushFile failed, status = %x\n", Status); 96 ReturnStatus = Status; 97 } 98 } 99 /* FIXME: Stop flushing if this is a removable media and the media was removed */ 100 } 101 102 Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext; 103 104 ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE); 105 Status = VfatFlushFile(DeviceExt, Fcb); 106 ExReleaseResourceLite(&DeviceExt->FatResource); 107 108 /* Prepare an IRP to flush device buffers */ 109 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, 110 DeviceExt->StorageDevice, 111 NULL, 0, NULL, &Event, 112 &IoStatusBlock); 113 if (Irp != NULL) 114 { 115 KeInitializeEvent(&Event, NotificationEvent, FALSE); 116 117 Status = IoCallDriver(DeviceExt->StorageDevice, Irp); 118 if (Status == STATUS_PENDING) 119 { 120 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 121 Status = IoStatusBlock.Status; 122 } 123 124 /* Ignore device not supporting flush operation */ 125 if (Status == STATUS_INVALID_DEVICE_REQUEST) 126 { 127 DPRINT1("Flush not supported, ignored\n"); 128 Status = STATUS_SUCCESS; 129 130 } 131 } 132 else 133 { 134 Status = STATUS_INSUFFICIENT_RESOURCES; 135 } 136 137 if (!NT_SUCCESS(Status)) 138 { 139 DPRINT1("VfatFlushFile failed, status = %x\n", Status); 140 ReturnStatus = Status; 141 } 142 143 return ReturnStatus; 144 } 145 146 NTSTATUS 147 VfatFlush( 148 PVFAT_IRP_CONTEXT IrpContext) 149 { 150 NTSTATUS Status; 151 PVFATFCB Fcb; 152 153 /* This request is not allowed on the main device object. */ 154 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) 155 { 156 IrpContext->Irp->IoStatus.Information = 0; 157 return STATUS_INVALID_DEVICE_REQUEST; 158 } 159 160 Fcb = (PVFATFCB)IrpContext->FileObject->FsContext; 161 ASSERT(Fcb); 162 163 if (BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME)) 164 { 165 ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE); 166 Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb); 167 ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); 168 } 169 else 170 { 171 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 172 Status = VfatFlushFile(IrpContext->DeviceExt, Fcb); 173 ExReleaseResourceLite (&Fcb->MainResource); 174 } 175 176 IrpContext->Irp->IoStatus.Information = 0; 177 return Status; 178 } 179 180 /* EOF */ 181