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 /* acquire gd lock to avoid gd/bh creation */
88 ExAcquireResourceExclusiveLite(&Vcb
->sbi
.s_gd_lock
, TRUE
);
90 /* discard buffer_headers for group_desc */
94 CcFlushCache(&(Vcb
->SectionObject
), NULL
, 0, &IoStatus
);
97 ExReleaseResourceLite(&Vcb
->sbi
.s_gd_lock
);
99 return IoStatus
.Status
;
104 IN PEXT2_IRP_CONTEXT IrpContext
,
109 IO_STATUS_BLOCK IoStatus
;
112 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
113 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
117 /* update timestamp and achieve attribute */
120 if (!IsFlagOn(Ccb
->Flags
, CCB_LAST_WRITE_UPDATED
)) {
122 LARGE_INTEGER SysTime
;
123 KeQuerySystemTime(&SysTime
);
125 Fcb
->Inode
->i_mtime
= Ext2LinuxTime(SysTime
);
126 Fcb
->Mcb
->LastWriteTime
= Ext2NtTime(Fcb
->Inode
->i_mtime
);
127 Ext2SaveInode(IrpContext
, Fcb
->Vcb
, Fcb
->Inode
);
131 if (IsDirectory(Fcb
)) {
132 IoStatus
.Status
= STATUS_SUCCESS
;
136 DEBUG(DL_INF
, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
137 Fcb
->Inode
->i_ino
, Fcb
->Mcb
->ShortName
.Buffer
));
139 CcFlushCache(&(Fcb
->SectionObject
), NULL
, 0, &IoStatus
);
140 ClearFlag(Fcb
->Flags
, FCB_FILE_MODIFIED
);
144 /* do cleanup here */
147 return IoStatus
.Status
;
152 Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext
)
154 NTSTATUS Status
= STATUS_SUCCESS
;
157 PIO_STACK_LOCATION IrpSp
= NULL
;
159 PEXT2_VCB Vcb
= NULL
;
160 PEXT2_FCB Fcb
= NULL
;
161 PEXT2_FCBVCB FcbOrVcb
= NULL
;
162 PEXT2_CCB Ccb
= NULL
;
163 PFILE_OBJECT FileObject
= NULL
;
165 PDEVICE_OBJECT DeviceObject
= NULL
;
167 BOOLEAN MainResourceAcquired
= FALSE
;
173 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
174 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
176 DeviceObject
= IrpContext
->DeviceObject
;
179 // This request is not allowed on the main device object
181 if (IsExt2FsDevice(DeviceObject
)) {
182 Status
= STATUS_INVALID_DEVICE_REQUEST
;
186 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
188 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
189 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
191 ASSERT(IsMounted(Vcb
));
192 if (IsVcbReadOnly(Vcb
)) {
193 Status
= STATUS_SUCCESS
;
197 Irp
= IrpContext
->Irp
;
198 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
200 FileObject
= IrpContext
->FileObject
;
201 FcbOrVcb
= (PEXT2_FCBVCB
) FileObject
->FsContext
;
202 ASSERT(FcbOrVcb
!= NULL
);
204 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
206 Status
= STATUS_SUCCESS
;
210 MainResourceAcquired
=
211 ExAcquireResourceExclusiveLite(&FcbOrVcb
->MainResource
, TRUE
);
212 ASSERT(MainResourceAcquired
);
213 DEBUG(DL_INF
, ("Ext2Flush-pre: total mcb records=%u\n",
214 FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
216 if (FcbOrVcb
->Identifier
.Type
== EXT2VCB
) {
218 Ext2VerifyVcb(IrpContext
, Vcb
);
219 Status
= Ext2FlushFiles(IrpContext
, (PEXT2_VCB
)(FcbOrVcb
), FALSE
);
220 if (NT_SUCCESS(Status
)) {
224 Status
= Ext2FlushVolume(IrpContext
, (PEXT2_VCB
)(FcbOrVcb
), FALSE
);
226 if (NT_SUCCESS(Status
) && IsFlagOn(Vcb
->Volume
->Flags
, FO_FILE_MODIFIED
)) {
227 ClearFlag(Vcb
->Volume
->Flags
, FO_FILE_MODIFIED
);
230 } else if (FcbOrVcb
->Identifier
.Type
== EXT2FCB
) {
232 Fcb
= (PEXT2_FCB
)(FcbOrVcb
);
234 Status
= Ext2FlushFile(IrpContext
, Fcb
, Ccb
);
235 if (NT_SUCCESS(Status
)) {
236 if (IsFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
)) {
237 Fcb
->Mcb
->FileAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
238 ClearFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
243 DEBUG(DL_INF
, ("Ext2Flush-post: total mcb records=%u\n",
244 FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
249 if (MainResourceAcquired
) {
250 ExReleaseResourceLite(&FcbOrVcb
->MainResource
);
253 if (!IrpContext
->ExceptionInProgress
) {
255 if (Vcb
&& Irp
&& IrpSp
&& !IsVcbReadOnly(Vcb
)) {
257 // Call the disk driver to flush the physial media.
258 NTSTATUS DriverStatus
;
259 PIO_STACK_LOCATION NextIrpSp
;
261 NextIrpSp
= IoGetNextIrpStackLocation(Irp
);
265 IoSetCompletionRoutine( Irp
,
266 Ext2FlushCompletionRoutine
,
272 DriverStatus
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
274 Status
= (DriverStatus
== STATUS_INVALID_DEVICE_REQUEST
) ?
275 Status
: DriverStatus
;
277 IrpContext
->Irp
= Irp
= NULL
;
280 Ext2CompleteIrpContext(IrpContext
, Status
);