1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: flush.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 21 #ifdef __REACTOS__ 22 NTSTATUS NTAPI 23 #else 24 NTSTATUS 25 #endif 26 Ext2FlushCompletionRoutine ( 27 IN PDEVICE_OBJECT DeviceObject, 28 IN PIRP Irp, 29 IN PVOID Context ) 30 31 { 32 if (Irp->PendingReturned) 33 IoMarkIrpPending( Irp ); 34 35 36 if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) 37 Irp->IoStatus.Status = STATUS_SUCCESS; 38 39 return STATUS_SUCCESS; 40 } 41 42 NTSTATUS 43 Ext2FlushVolume ( 44 IN PEXT2_IRP_CONTEXT IrpContext, 45 IN PEXT2_VCB Vcb, 46 IN BOOLEAN bShutDown 47 ) 48 { 49 DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n")); 50 51 ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); 52 ExReleaseResourceLite(&Vcb->PagingIoResource); 53 54 return Ext2FlushVcb(Vcb); 55 } 56 57 NTSTATUS 58 Ext2FlushFile ( 59 IN PEXT2_IRP_CONTEXT IrpContext, 60 IN PEXT2_FCB Fcb, 61 IN PEXT2_CCB Ccb 62 ) 63 { 64 IO_STATUS_BLOCK IoStatus = {0}; 65 66 ASSERT(Fcb != NULL); 67 ASSERT((Fcb->Identifier.Type == EXT2FCB) && 68 (Fcb->Identifier.Size == sizeof(EXT2_FCB))); 69 70 _SEH2_TRY { 71 72 /* do nothing if target fie was deleted */ 73 if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { 74 IoStatus.Status = STATUS_FILE_DELETED; 75 _SEH2_LEAVE; 76 } 77 78 /* update timestamp and achieve attribute */ 79 if (Ccb != NULL) { 80 81 if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) { 82 83 LARGE_INTEGER SysTime; 84 KeQuerySystemTime(&SysTime); 85 86 Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); 87 Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime); 88 Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode); 89 } 90 } 91 92 if (IsDirectory(Fcb)) { 93 IoStatus.Status = STATUS_SUCCESS; 94 _SEH2_LEAVE; 95 } 96 97 DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n", 98 Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer)); 99 100 CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus); 101 ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); 102 103 } _SEH2_FINALLY { 104 105 /* do cleanup here */ 106 } _SEH2_END; 107 108 return IoStatus.Status; 109 } 110 111 NTSTATUS 112 Ext2FlushFiles( 113 IN PEXT2_IRP_CONTEXT IrpContext, 114 IN PEXT2_VCB Vcb, 115 IN BOOLEAN bShutDown 116 ) 117 { 118 IO_STATUS_BLOCK IoStatus; 119 120 PEXT2_FCB Fcb; 121 PLIST_ENTRY ListEntry; 122 123 if (IsVcbReadOnly(Vcb)) { 124 return STATUS_SUCCESS; 125 } 126 127 IoStatus.Status = STATUS_SUCCESS; 128 129 DEBUG(DL_INF, ( "Flushing Files ...\n")); 130 131 // Flush all Fcbs in Vcb list queue. 132 for (ListEntry = Vcb->FcbList.Flink; 133 ListEntry != &Vcb->FcbList; 134 ListEntry = ListEntry->Flink ) { 135 136 Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next); 137 ExAcquireResourceExclusiveLite( 138 &Fcb->MainResource, TRUE); 139 Ext2FlushFile(IrpContext, Fcb, NULL); 140 ExReleaseResourceLite(&Fcb->MainResource); 141 } 142 143 return IoStatus.Status; 144 } 145 146 147 NTSTATUS 148 Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext) 149 { 150 NTSTATUS Status = STATUS_SUCCESS; 151 152 PIRP Irp = NULL; 153 PIO_STACK_LOCATION IrpSp = NULL; 154 155 PEXT2_VCB Vcb = NULL; 156 PEXT2_FCB Fcb = NULL; 157 PEXT2_FCBVCB FcbOrVcb = NULL; 158 PEXT2_CCB Ccb = NULL; 159 PFILE_OBJECT FileObject = NULL; 160 161 PDEVICE_OBJECT DeviceObject = NULL; 162 163 BOOLEAN MainResourceAcquired = FALSE; 164 165 _SEH2_TRY { 166 167 ASSERT(IrpContext); 168 169 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 170 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 171 172 DeviceObject = IrpContext->DeviceObject; 173 174 // 175 // This request is not allowed on the main device object 176 // 177 if (IsExt2FsDevice(DeviceObject)) { 178 Status = STATUS_INVALID_DEVICE_REQUEST; 179 _SEH2_LEAVE; 180 } 181 182 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 183 ASSERT(Vcb != NULL); 184 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 185 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 186 187 ASSERT(IsMounted(Vcb)); 188 if (IsVcbReadOnly(Vcb)) { 189 Status = STATUS_SUCCESS; 190 _SEH2_LEAVE; 191 } 192 193 Irp = IrpContext->Irp; 194 IrpSp = IoGetCurrentIrpStackLocation(Irp); 195 196 FileObject = IrpContext->FileObject; 197 FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; 198 ASSERT(FcbOrVcb != NULL); 199 200 Ccb = (PEXT2_CCB) FileObject->FsContext2; 201 if (Ccb == NULL) { 202 Status = STATUS_SUCCESS; 203 _SEH2_LEAVE; 204 } 205 206 MainResourceAcquired = 207 ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE); 208 ASSERT(MainResourceAcquired); 209 DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n", 210 FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); 211 212 if (FcbOrVcb->Identifier.Type == EXT2VCB) { 213 214 Ext2VerifyVcb(IrpContext, Vcb); 215 Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE); 216 if (NT_SUCCESS(Status)) { 217 _SEH2_LEAVE; 218 } 219 220 Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE); 221 222 if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) { 223 ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED); 224 } 225 226 } else if (FcbOrVcb->Identifier.Type == EXT2FCB) { 227 228 Fcb = (PEXT2_FCB)(FcbOrVcb); 229 230 Status = Ext2FlushFile(IrpContext, Fcb, Ccb); 231 if (NT_SUCCESS(Status)) { 232 if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) { 233 Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE; 234 ClearFlag(FileObject->Flags, FO_FILE_MODIFIED); 235 } 236 } 237 } 238 239 DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n", 240 FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); 241 242 243 } _SEH2_FINALLY { 244 245 if (MainResourceAcquired) { 246 ExReleaseResourceLite(&FcbOrVcb->MainResource); 247 } 248 249 if (!IrpContext->ExceptionInProgress) { 250 251 if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) { 252 253 // Call the disk driver to flush the physial media. 254 NTSTATUS DriverStatus; 255 PIO_STACK_LOCATION NextIrpSp; 256 257 NextIrpSp = IoGetNextIrpStackLocation(Irp); 258 259 *NextIrpSp = *IrpSp; 260 261 IoSetCompletionRoutine( Irp, 262 Ext2FlushCompletionRoutine, 263 NULL, 264 TRUE, 265 TRUE, 266 TRUE ); 267 268 DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp); 269 270 Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ? 271 Status : DriverStatus; 272 273 IrpContext->Irp = Irp = NULL; 274 } 275 276 Ext2CompleteIrpContext(IrpContext, Status); 277 } 278 } _SEH2_END; 279 280 return Status; 281 } 282