GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 79 / 0 / 79
Functions: 100.0% 1 / 0 / 1
Branches: 100.0% 54 / 0 / 54

fx_media_flush.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
10 **************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** FileX Component */
17 /** */
18 /** Media */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define FX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "fx_api.h"
29 #include "fx_system.h"
30 #include "fx_media.h"
31 #include "fx_file.h"
32 #include "fx_directory.h"
33 #include "fx_utility.h"
34
35
36 /**************************************************************************/
37 /* */
38 /* FUNCTION RELEASE */
39 /* */
40 /* _fx_media_flush PORTABLE C */
41 /* 6.1 */
42 /* AUTHOR */
43 /* */
44 /* William E. Lamie, Microsoft Corporation */
45 /* */
46 /* DESCRIPTION */
47 /* */
48 /* This function examines the list of open files for this media and */
49 /* "flushes" each written open file to the underlying media. After */
50 /* the open files have been flushed, the internal logical sector is */
51 /* flushed. Finally, the attached driver is sent a flush command so */
52 /* that it can flush its sector cache (if any) to the media. */
53 /* */
54 /* INPUT */
55 /* */
56 /* media_ptr Media control block pointer */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* return status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _fx_directory_entry_write Write the directory entry */
65 /* _fx_utility_FAT_flush Flush cached FAT entries */
66 /* _fx_utility_FAT_map_flush Flush primary FAT changes to */
67 /* secondary FAT(s) */
68 /* _fx_utility_logical_sector_flush Flush logical sector cache */
69 /* _fx_utility_32_unsigned_read Read 32-bit unsigned */
70 /* _fx_utility_32_unsigned_write Write 32-bit unsigned */
71 /* */
72 /* CALLED BY */
73 /* */
74 /* Application Code */
75 /* */
76 /**************************************************************************/
77 366186 UINT _fx_media_flush(FX_MEDIA *media_ptr)
78 {
79
80 UINT status;
81 ULONG open_count;
82 FX_FILE *file_ptr;
83 FX_INT_SAVE_AREA
84
85
86 #ifndef FX_MEDIA_STATISTICS_DISABLE
87
88 /* Increment the number of times this service has been called. */
89 366186 media_ptr -> fx_media_flushes++;
90 #endif
91
92 /* Check the media to make sure it is open. */
93
2/2
✓ Branch 2 → 3 taken 9 times.
✓ Branch 2 → 4 taken 366177 times.
366186 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
94 {
95
96 /* Return the media not opened error. */
97 9 return(FX_MEDIA_NOT_OPEN);
98 }
99
100 /* If trace is enabled, insert this event into the trace buffer. */
101 FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_FLUSH, media_ptr, 0, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
102
103 /* Protect against other threads accessing the media. */
104 199598 FX_PROTECT
105
106 /* Check for write protect at the media level (set by driver). */
107
4/4
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 6 taken 166575 times.
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 8 taken 199593 times.
366177 if (media_ptr -> fx_media_driver_write_protect)
108 {
109
110 /* Release media protection. */
111 5 FX_UNPROTECT
112
113 /* Return write protect error. */
114 9 return(FX_WRITE_PROTECT);
115 }
116
117 /* Loop through the media's open files. */
118 366168 open_count = media_ptr -> fx_media_opened_file_count;
119 366168 file_ptr = media_ptr -> fx_media_opened_file_list;
120
4/4
✓ Branch 14 → 7 taken 502615 times.
✓ Branch 14 → 15 taken 166570 times.
✓ Branch 19 → 9 taken 593747 times.
✓ Branch 19 → 20 taken 199587 times.
1462519 while (open_count)
121 {
122
123 /* Look at each opened file to see if the same file is opened
124 for writing and has been written to. */
125
4/4
✓ Branch 7 → 8 taken 291367 times.
✓ Branch 7 → 13 taken 211248 times.
✓ Branch 9 → 10 taken 346948 times.
✓ Branch 9 → 18 taken 246799 times.
1096362 if ((file_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE) &&
126
4/4
✓ Branch 8 → 9 taken 94527 times.
✓ Branch 8 → 13 taken 196840 times.
✓ Branch 10 → 11 taken 115426 times.
✓ Branch 10 → 18 taken 231522 times.
638315 (file_ptr -> fx_file_modified))
127 {
128
129 /* Protect against update. */
130 115426 FX_DISABLE_INTS
131
132 /* Set the new time and date. */
133 209953 file_ptr -> fx_file_dir_entry.fx_dir_entry_time = _fx_system_time;
134 209953 file_ptr -> fx_file_dir_entry.fx_dir_entry_date = _fx_system_date;
135
136 /* Restore interrupts. */
137 115426 FX_RESTORE_INTS
138
139 /* Copy the new file size into the directory entry. */
140 209953 file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =
141 209953 file_ptr -> fx_file_current_file_size;
142
143 /* Write the directory entry to the media. */
144 209953 status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
145
146 /* Check for a good status. */
147
4/4
✓ Branch 10 → 11 taken 5 times.
✓ Branch 10 → 12 taken 94522 times.
✓ Branch 14 → 15 taken 6 times.
✓ Branch 14 → 17 taken 115420 times.
209953 if (status != FX_SUCCESS)
148 {
149
150 /* Release media protection. */
151 6 FX_UNPROTECT
152
153 /* Error writing the directory. */
154 11 return(status);
155 }
156
157 /* Clear the file modified flag. */
158 209942 file_ptr -> fx_file_modified = FX_FALSE;
159 }
160
161 /* Adjust the pointer and decrement the opened count. */
162 1096351 file_ptr = file_ptr -> fx_file_opened_next;
163 1096351 open_count--;
164 }
165
166 /* Flush the cached individual FAT entries */
167 366157 _fx_utility_FAT_flush(media_ptr);
168
169 /* Flush changed sector(s) in the primary FAT to secondary FATs. */
170 366157 _fx_utility_FAT_map_flush(media_ptr);
171
172
173 /* Flush the internal logical sector cache. */
174 366157 status = _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_FALSE);
175
176 /* Check for a good status. */
177
4/4
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 20 taken 166568 times.
✓ Branch 23 → 24 taken 3 times.
✓ Branch 23 → 26 taken 199584 times.
366157 if (status != FX_SUCCESS)
178 {
179
180 /* Release media protection. */
181 3 FX_UNPROTECT
182
183 /* Error writing the directory. */
184 5 return(status);
185 }
186
187 /* Determine if the media needs to have the additional information sector updated. This will
188 only be the case for 32-bit FATs. The logic here only needs to be done if the last reported
189 available cluster count is different that the currently available clusters. */
190
4/4
✓ Branch 20 → 21 taken 4110 times.
✓ Branch 20 → 35 taken 162458 times.
✓ Branch 26 → 27 taken 5137 times.
✓ Branch 26 → 43 taken 194447 times.
366152 if ((media_ptr -> fx_media_FAT32_additional_info_sector) &&
191
4/4
✓ Branch 21 → 22 taken 4034 times.
✓ Branch 21 → 35 taken 76 times.
✓ Branch 27 → 28 taken 5042 times.
✓ Branch 27 → 43 taken 95 times.
9247 (media_ptr -> fx_media_FAT32_additional_info_last_available != media_ptr -> fx_media_available_clusters))
192 {
193
194 UCHAR *buffer_ptr;
195 ULONG signature;
196
197 #ifndef FX_DISABLE_CACHE
198
199 /* Setup a pointer to the first cached entry's buffer. */
200 5042 buffer_ptr = (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_memory_buffer;
201
202 /* Invalidate this cache entry. */
203 5042 (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector = (~(ULONG64)0);
204 5042 (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_valid = FX_FALSE;
205 #else
206 4034 buffer_ptr = media_ptr -> fx_media_memory_buffer;
207 #endif /* FX_DISABLE_CACHE */
208
209 /* Read the FAT32 additional information sector from the device. */
210 9076 media_ptr -> fx_media_driver_request = FX_DRIVER_READ;
211 9076 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
212 9076 media_ptr -> fx_media_driver_buffer = buffer_ptr;
213 9076 media_ptr -> fx_media_driver_logical_sector = media_ptr -> fx_media_FAT32_additional_info_sector;
214 9076 media_ptr -> fx_media_driver_sectors = 1;
215 9076 media_ptr -> fx_media_driver_sector_type = FX_DIRECTORY_SECTOR;
216
217 #ifndef FX_MEDIA_STATISTICS_DISABLE
218
219 /* Increment the number of driver read sector(s) requests. */
220 9076 media_ptr -> fx_media_driver_read_requests++;
221 #endif
222
223 /* If trace is enabled, insert this event into the trace buffer. */
224 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
225
226 /* Invoke the driver to read the FAT32 additional information sector. */
227 9076 (media_ptr -> fx_media_driver_entry) (media_ptr);
228
229 /* Determine if the FAT32 sector was read correctly. */
230
4/4
✓ Branch 23 → 24 taken 820 times.
✓ Branch 23 → 25 taken 3214 times.
✓ Branch 29 → 30 taken 1025 times.
✓ Branch 29 → 32 taken 4017 times.
9076 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
231 {
232
233 /* Release media protection. */
234 1025 FX_UNPROTECT
235
236 /* Return the error status. */
237 1845 return(FX_IO_ERROR);
238 }
239
240 /* Setup a pointer into the FAT32 additional information sector. */
241 7231 buffer_ptr = media_ptr -> fx_media_driver_buffer;
242
243 /* Pickup the first signature long word. */
244 7231 signature = _fx_utility_32_unsigned_read(&buffer_ptr[0]);
245
246 /* Determine if the signature is correct. */
247
4/4
✓ Branch 26 → 27 taken 3206 times.
✓ Branch 26 → 35 taken 8 times.
✓ Branch 33 → 34 taken 4007 times.
✓ Branch 33 → 43 taken 10 times.
7231 if (signature == 0x41615252)
248 {
249
250 /* Yes, the first signature is correct, now pickup the next signature. */
251 7213 signature = _fx_utility_32_unsigned_read(&buffer_ptr[484]);
252
253 /* Determine if this signature is correct. */
254
4/4
✓ Branch 28 → 29 taken 3202 times.
✓ Branch 28 → 35 taken 4 times.
✓ Branch 35 → 36 taken 4002 times.
✓ Branch 35 → 43 taken 5 times.
7213 if (signature == 0x61417272)
255 {
256
257 /* Yes, we have a good FAT32 additional information sector. */
258
259 /* Set the free cluster count to the available clusters in the media control block. */
260 7204 _fx_utility_32_unsigned_write(&buffer_ptr[488], media_ptr -> fx_media_available_clusters);
261
262 /* Set the next free cluster number hint to starting search cluster in the media control block. */
263 7204 _fx_utility_32_unsigned_write(&buffer_ptr[492], media_ptr -> fx_media_cluster_search_start);
264
265 /* Now write the sector back out to the media. */
266 7204 media_ptr -> fx_media_driver_request = FX_DRIVER_WRITE;
267 7204 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
268 7204 media_ptr -> fx_media_driver_buffer = buffer_ptr;
269 7204 media_ptr -> fx_media_driver_logical_sector = media_ptr -> fx_media_FAT32_additional_info_sector;
270 7204 media_ptr -> fx_media_driver_sectors = 1;
271 7204 media_ptr -> fx_media_driver_sector_type = FX_DIRECTORY_SECTOR;
272
273 /* Set the system write flag since we are writing a directory sector. */
274 7204 media_ptr -> fx_media_driver_system_write = FX_TRUE;
275
276 #ifndef FX_MEDIA_STATISTICS_DISABLE
277
278 /* Increment the number of driver write sector(s) requests. */
279 7204 media_ptr -> fx_media_driver_write_requests++;
280 #endif
281
282 /* If trace is enabled, insert this event into the trace buffer. */
283 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
284
285 /* Invoke the driver to write the FAT32 additional information sector. */
286 7204 (media_ptr -> fx_media_driver_entry) (media_ptr);
287
288 /* Clear the system write flag. */
289 7204 media_ptr -> fx_media_driver_system_write = FX_FALSE;
290
291 /* Determine if the FAT32 sector was written correctly. */
292
4/4
✓ Branch 32 → 33 taken 360 times.
✓ Branch 32 → 34 taken 2842 times.
✓ Branch 39 → 40 taken 450 times.
✓ Branch 39 → 42 taken 3552 times.
7204 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
293 {
294
295 /* Release media protection. */
296 450 FX_UNPROTECT
297
298 /* Return the sector IO error status. */
299 810 return(FX_IO_ERROR);
300 }
301
302 /* Successful update of the FAT32 additional information sector. Update the
303 last written available cluster count. */
304 6394 media_ptr -> fx_media_FAT32_additional_info_last_available = media_ptr -> fx_media_available_clusters;
305 }
306 }
307 }
308
309 #ifndef FX_MEDIA_STATISTICS_DISABLE
310
311 /* Increment the number of driver flush requests. */
312 363497 media_ptr -> fx_media_driver_flush_requests++;
313 #endif
314
315 /* Build the "flush" I/O driver request. */
316 363497 media_ptr -> fx_media_driver_request = FX_DRIVER_FLUSH;
317 363497 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
318
319 /* If trace is enabled, insert this event into the trace buffer. */
320 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_FLUSH, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
321
322 /* Call the specified I/O driver with the flush request. */
323 363497 (media_ptr -> fx_media_driver_entry) (media_ptr);
324
325 /* Determine if the I/O driver flushed successfully. */
326
4/4
✓ Branch 36 → 37 taken 400 times.
✓ Branch 36 → 38 taken 164988 times.
✓ Branch 44 → 45 taken 500 times.
✓ Branch 44 → 47 taken 197609 times.
363497 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
327 {
328
329 /* Release media protection. */
330 500 FX_UNPROTECT
331
332 /* Return the driver error status. */
333 900 return(FX_IO_ERROR);
334 }
335
336 /* Release media protection. */
337 197609 FX_UNPROTECT
338
339 /* If we get here, return successful status to the caller. */
340 362597 return(FX_SUCCESS);
341 }
342
343