xref: /reactos/drivers/filesystems/fastfat/flush.c (revision aad80191)
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