2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
22 Ext2FlushCompletionRoutine (
23 IN PDEVICE_OBJECT DeviceObject
,
28 if (Irp
->PendingReturned
)
29 IoMarkIrpPending( Irp
);
32 if (Irp
->IoStatus
.Status
== STATUS_INVALID_DEVICE_REQUEST
)
33 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
35 return STATUS_SUCCESS
;
40 IN PEXT2_IRP_CONTEXT IrpContext
,
45 IO_STATUS_BLOCK IoStatus
;
48 PLIST_ENTRY ListEntry
;
50 if (IsVcbReadOnly(Vcb
)) {
51 return STATUS_SUCCESS
;
54 IoStatus
.Status
= STATUS_SUCCESS
;
56 DEBUG(DL_INF
, ( "Flushing Files ...\n"));
58 // Flush all Fcbs in Vcb list queue.
59 for (ListEntry
= Vcb
->FcbList
.Flink
;
60 ListEntry
!= &Vcb
->FcbList
;
61 ListEntry
= ListEntry
->Flink
) {
63 Fcb
= CONTAINING_RECORD(ListEntry
, EXT2_FCB
, Next
);
64 ExAcquireResourceExclusiveLite(
65 &Fcb
->MainResource
, TRUE
);
66 IoStatus
.Status
= Ext2FlushFile(IrpContext
, Fcb
, NULL
);
67 ExReleaseResourceLite(&Fcb
->MainResource
);
70 return IoStatus
.Status
;
75 IN PEXT2_IRP_CONTEXT IrpContext
,
80 IO_STATUS_BLOCK IoStatus
;
82 DEBUG(DL_INF
, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
84 ExAcquireSharedStarveExclusive(&Vcb
->PagingIoResource
, TRUE
);
85 ExReleaseResourceLite(&Vcb
->PagingIoResource
);
87 CcFlushCache(&(Vcb
->SectionObject
), NULL
, 0, &IoStatus
);
89 return IoStatus
.Status
;
94 IN PEXT2_IRP_CONTEXT IrpContext
,
99 IO_STATUS_BLOCK IoStatus
;
102 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
103 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
107 /* update timestamp and achieve attribute */
110 if (!IsFlagOn(Ccb
->Flags
, CCB_LAST_WRITE_UPDATED
)) {
112 LARGE_INTEGER SysTime
;
113 KeQuerySystemTime(&SysTime
);
115 Fcb
->Inode
->i_mtime
= Ext2LinuxTime(SysTime
);
116 Fcb
->Mcb
->LastWriteTime
= Ext2NtTime(Fcb
->Inode
->i_mtime
);
117 Ext2SaveInode(IrpContext
, Fcb
->Vcb
, Fcb
->Inode
);
121 if (IsDirectory(Fcb
)) {
122 IoStatus
.Status
= STATUS_SUCCESS
;
126 DEBUG(DL_INF
, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
127 Fcb
->Inode
->i_ino
, Fcb
->Mcb
->ShortName
.Buffer
));
129 CcFlushCache(&(Fcb
->SectionObject
), NULL
, 0, &IoStatus
);
130 ClearFlag(Fcb
->Flags
, FCB_FILE_MODIFIED
);
134 /* do cleanup here */
137 return IoStatus
.Status
;
142 Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext
)
144 NTSTATUS Status
= STATUS_SUCCESS
;
147 PIO_STACK_LOCATION IrpSp
= NULL
;
149 PEXT2_VCB Vcb
= NULL
;
150 PEXT2_FCB Fcb
= NULL
;
151 PEXT2_FCBVCB FcbOrVcb
= NULL
;
152 PEXT2_CCB Ccb
= NULL
;
153 PFILE_OBJECT FileObject
= NULL
;
155 PDEVICE_OBJECT DeviceObject
= NULL
;
157 BOOLEAN MainResourceAcquired
= FALSE
;
163 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
164 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
166 DeviceObject
= IrpContext
->DeviceObject
;
169 // This request is not allowed on the main device object
171 if (IsExt2FsDevice(DeviceObject
)) {
172 Status
= STATUS_INVALID_DEVICE_REQUEST
;
176 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
178 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
179 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
181 ASSERT(IsMounted(Vcb
));
182 if (IsVcbReadOnly(Vcb
)) {
183 Status
= STATUS_SUCCESS
;
187 Irp
= IrpContext
->Irp
;
188 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
190 FileObject
= IrpContext
->FileObject
;
191 FcbOrVcb
= (PEXT2_FCBVCB
) FileObject
->FsContext
;
192 ASSERT(FcbOrVcb
!= NULL
);
194 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
196 Status
= STATUS_SUCCESS
;
200 MainResourceAcquired
=
201 ExAcquireResourceExclusiveLite(&FcbOrVcb
->MainResource
, TRUE
);
202 ASSERT(MainResourceAcquired
);
203 DEBUG(DL_INF
, ("Ext2Flush-pre: total mcb records=%u\n",
204 FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
206 if (FcbOrVcb
->Identifier
.Type
== EXT2VCB
) {
208 Ext2VerifyVcb(IrpContext
, Vcb
);
209 Status
= Ext2FlushFiles(IrpContext
, (PEXT2_VCB
)(FcbOrVcb
), FALSE
);
210 if (NT_SUCCESS(Status
)) {
214 Status
= Ext2FlushVolume(IrpContext
, (PEXT2_VCB
)(FcbOrVcb
), FALSE
);
216 if (NT_SUCCESS(Status
) && IsFlagOn(Vcb
->Volume
->Flags
, FO_FILE_MODIFIED
)) {
217 ClearFlag(Vcb
->Volume
->Flags
, FO_FILE_MODIFIED
);
220 } else if (FcbOrVcb
->Identifier
.Type
== EXT2FCB
) {
222 Fcb
= (PEXT2_FCB
)(FcbOrVcb
);
224 Status
= Ext2FlushFile(IrpContext
, Fcb
, Ccb
);
225 if (NT_SUCCESS(Status
)) {
226 if (IsFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
)) {
227 Fcb
->Mcb
->FileAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
228 ClearFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
233 DEBUG(DL_INF
, ("Ext2Flush-post: total mcb records=%u\n",
234 FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
239 if (MainResourceAcquired
) {
240 ExReleaseResourceLite(&FcbOrVcb
->MainResource
);
243 if (!IrpContext
->ExceptionInProgress
) {
245 if (Vcb
&& Irp
&& IrpSp
&& !IsVcbReadOnly(Vcb
)) {
247 // Call the disk driver to flush the physial media.
248 NTSTATUS DriverStatus
;
249 PIO_STACK_LOCATION NextIrpSp
;
251 NextIrpSp
= IoGetNextIrpStackLocation(Irp
);
255 IoSetCompletionRoutine( Irp
,
256 Ext2FlushCompletionRoutine
,
262 DriverStatus
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
264 Status
= (DriverStatus
== STATUS_INVALID_DEVICE_REQUEST
) ?
265 Status
: DriverStatus
;
267 IrpContext
->Irp
= Irp
= NULL
;
270 Ext2CompleteIrpContext(IrpContext
, Status
);