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