GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 93 / 0 / 93
Functions: 100.0% 1 / 0 / 1
Branches: 98.1% 104 / 0 / 106

fx_utility_logical_sector_write.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 /** Utility */
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_utility.h"
31 #ifdef FX_ENABLE_FAULT_TOLERANT
32 #include "fx_fault_tolerant.h"
33 #endif /* FX_ENABLE_FAULT_TOLERANT */
34
35
36 /**************************************************************************/
37 /* */
38 /* FUNCTION RELEASE */
39 /* */
40 /* _fx_utility_logical_sector_write PORTABLE C */
41 /* 6.1.6 */
42 /* AUTHOR */
43 /* */
44 /* William E. Lamie, Microsoft Corporation */
45 /* */
46 /* DESCRIPTION */
47 /* */
48 /* This function handles logical sector write requests for all FileX */
49 /* components. If the logical sector is currently in the media's */
50 /* buffer supplied by the caller, the function simply marks the buffer */
51 /* as written to. Otherwise, physical I/O is requested through the */
52 /* corresponding I/O driver. */
53 /* */
54 /* Note: Conversion of the logical sector is done inside the driver. */
55 /* This results in a performance boost for FLASH or RAM media */
56 /* devices. */
57 /* */
58 /* INPUT */
59 /* */
60 /* media_ptr Media control block pointer */
61 /* logical_sector Logical sector number */
62 /* buffer_ptr Pointer of sector buffer */
63 /* sectors Number of sectors to write */
64 /* sector_type Type of sector(s) to write */
65 /* */
66 /* OUTPUT */
67 /* */
68 /* return status */
69 /* */
70 /* CALLS */
71 /* */
72 /* _fx_utility_logical_sector_flush Flush and invalidate sectors */
73 /* that overlap with non-cache */
74 /* sector I/O. */
75 /* I/O Driver */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* FileX System Functions */
80 /* */
81 /**************************************************************************/
82 713190778 UINT _fx_utility_logical_sector_write(FX_MEDIA *media_ptr, ULONG64 logical_sector,
83 VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
84 {
85
86 #ifndef FX_DISABLE_CACHE
87 FX_CACHED_SECTOR *cache_entry;
88 UINT cache_size;
89 UINT index;
90 UINT i;
91 369907244 UCHAR cache_found = FX_FALSE;
92 #endif /* FX_DISABLE_CACHE */
93
94 #ifndef FX_MEDIA_STATISTICS_DISABLE
95
96 /* Determine if the request is for FAT sector. */
97
2/2
✓ Branch 2 → 3 taken 35545257 times.
✓ Branch 2 → 4 taken 677645521 times.
713190778 if (sector_type == FX_FAT_SECTOR)
98 {
99
100 /* Increment the number of FAT sector writes. */
101 35545257 media_ptr -> fx_media_fat_sector_writes++;
102 }
103
104 /* Increment the number of logical sectors written. */
105 713190778 media_ptr -> fx_media_logical_sector_writes++;
106 #endif
107
108 /* Extended port-specific processing macro, which is by default defined to white space. */
109
4/4
✓ Branch 4 → 5 taken 326137 times.
✓ Branch 4 → 7 taken 712864641 times.
✓ Branch 5 → 6 taken 87647 times.
✓ Branch 5 → 7 taken 238490 times.
713190778 FX_UTILITY_LOGICAL_SECTOR_WRITE_EXTENSION
110
111 #ifndef FX_DISABLE_CACHE
112 /* Determine if the request is from the internal media buffer area. */
113
3/3
✓ Branch 7 → 8 taken 368203984 times.
✓ Branch 7 → 40 taken 96890 times.
✓ Branch 7 → 58 taken 1564075 times.
369864949 if ((((UCHAR *)buffer_ptr) >= media_ptr -> fx_media_memory_buffer) &&
114
3/3
✓ Branch 8 → 9 taken 200956643 times.
✓ Branch 8 → 40 taken 14086 times.
✓ Branch 8 → 58 taken 167233255 times.
368203984 (((UCHAR *)buffer_ptr) <= media_ptr -> fx_media_sector_cache_end))
115 {
116
117 /* Internal cache buffer is requested. */
118
119 /* Determine if the logical sector cache access should use the hash function. */
120
2/2
✓ Branch 9 → 10 taken 21302407 times.
✓ Branch 9 → 17 taken 179654236 times.
200956643 if (media_ptr -> fx_media_sector_cache_hashed)
121 {
122
123 /* Calculate the area of the cache for this logical sector. */
124 21302407 index = (ULONG)(logical_sector & media_ptr -> fx_media_sector_cache_hash_mask) * FX_SECTOR_CACHE_DEPTH;
125
126 /* Build a pointer to the cache entry. */
127 21302407 cache_entry = &(media_ptr -> fx_media_sector_cache[index]);
128
129
2/2
✓ Branch 15 → 11 taken 67557145 times.
✓ Branch 15 → 16 taken 15416847 times.
82973992 for (i = 0; i < FX_SECTOR_CACHE_DEPTH; i++, cache_entry++)
130 {
131
132
133 /* Determine if the logical sector is in the cache - assuming the depth of the
134 sector cache is 4 entries. */
135
4/4
✓ Branch 11 → 12 taken 12502986 times.
✓ Branch 11 → 14 taken 55054159 times.
✓ Branch 12 → 13 taken 5885560 times.
✓ Branch 12 → 14 taken 6617426 times.
67557145 if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
136 {
137 5885560 cache_found = FX_TRUE;
138 5885560 break;
139 }
140 }
141 }
142 else
143 {
144
145 /* Search for an entry in the cache that matches this request. */
146 179654236 cache_size = media_ptr -> fx_media_sector_cache_size;
147 179654236 cache_entry = media_ptr -> fx_media_sector_cache_list_ptr;
148
149 /* Look at the cache entries until a match is found or the end of
150 the cache is reached. */
151
2/2
✓ Branch 24 → 18 taken 2992327225 times.
✓ Branch 24 → 25 taken 11355742 times.
3003682967 while (cache_size--)
152 {
153
154 /* Determine if the requested sector has been found. */
155
4/4
✓ Branch 18 → 19 taken 1279777410 times.
✓ Branch 18 → 21 taken 1712549815 times.
✓ Branch 19 → 20 taken 168298494 times.
✓ Branch 19 → 21 taken 1111478916 times.
2992327225 if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
156 {
157 168298494 cache_found = FX_TRUE;
158 168298494 break;
159 }
160
161 /* Otherwise, we have not found the cached entry yet. */
162
163 /* If there are more entries, move to the next one. */
164
2/2
✓ Branch 21 → 22 taken 2812672989 times.
✓ Branch 21 → 23 taken 11355742 times.
2824028731 if (cache_entry -> fx_cached_sector_next_used)
165 {
166
167 /* Move to the next cache entry. */
168 2812672989 cache_entry = cache_entry -> fx_cached_sector_next_used;
169 }
170 }
171 }
172
173 #ifdef FX_ENABLE_FAULT_TOLERANT
174
2/2
✓ Branch 25 → 26 taken 170085774 times.
✓ Branch 25 → 40 taken 17593710 times.
187679484 if (media_ptr -> fx_media_fault_tolerant_enabled &&
175
4/4
✓ Branch 26 → 27 taken 84194425 times.
✓ Branch 26 → 40 taken 85891349 times.
✓ Branch 27 → 28 taken 81468054 times.
✓ Branch 27 → 40 taken 2726371 times.
170085774 (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
176
2/2
✓ Branch 28 → 29 taken 76810396 times.
✓ Branch 28 → 30 taken 4657658 times.
81468054 (sector_type == FX_DATA_SECTOR) &&
177
2/2
✓ Branch 29 → 30 taken 72 times.
✓ Branch 29 → 40 taken 76810324 times.
76810396 !(cache_found && (cache_entry -> fx_cached_sector_memory_buffer == buffer_ptr)))
178 {
179
180 /* Special use case for file write when fault tolerant is enabled. */
181 /* Data are read from one sector but write to another sector. */
182 /* Need to invalidate both of original and new caches. */
183
2/2
✓ Branch 30 → 31 taken 72 times.
✓ Branch 30 → 32 taken 4657658 times.
4657730 if (cache_found)
184 {
185
186 /* Invalidate the new cache. */
187 72 cache_entry -> fx_cached_sector_valid = FX_FALSE;
188 72 cache_found = FX_FALSE;
189 }
190
191 /* Search for original cache. */
192 4657730 cache_size = media_ptr -> fx_media_sector_cache_size;
193 4657730 cache_entry = media_ptr -> fx_media_sector_cache_list_ptr;
194
195 /* Look at the cache entries until a match is found or the end of
196 the cache is reached. */
197
2/2
✓ Branch 39 → 33 taken 66088882 times.
✓ Branch 39 → 40 taken 2 times.
66088884 while (cache_size--)
198 {
199
200 /* Determine if the original sector has been found. */
201
2/2
✓ Branch 33 → 34 taken 10651709 times.
✓ Branch 33 → 36 taken 55437173 times.
66088882 if ((cache_entry -> fx_cached_sector_valid) &&
202
2/2
✓ Branch 34 → 35 taken 4657728 times.
✓ Branch 34 → 36 taken 5993981 times.
10651709 (cache_entry -> fx_cached_sector_memory_buffer == buffer_ptr))
203 {
204
205 /* Invalidate the original cache. */
206 4657728 cache_entry -> fx_cached_sector_valid = FX_FALSE;
207 4657728 break;
208 }
209
210 /* Otherwise, we have not found the cached entry yet. */
211
212 /* If there are more entries, move to the next one. */
213
2/2
✓ Branch 36 → 37 taken 61431152 times.
✓ Branch 36 → 38 taken 2 times.
61431154 if (cache_entry -> fx_cached_sector_next_used)
214 {
215
216 /* Move to the next cache entry. */
217 61431152 cache_entry = cache_entry -> fx_cached_sector_next_used;
218 }
219 }
220 }
221 #endif /* FX_ENABLE_FAULT_TOLERANT */
222
223
4/4
✓ Branch 25 → 26 taken 3788312 times.
✓ Branch 25 → 29 taken 9488847 times.
✓ Branch 40 → 41 taken 170395670 times.
✓ Branch 40 → 47 taken 17283814 times.
200956643 if (cache_found)
224 {
225
226 /* Yes, we found a match. */
227
228 #ifdef FX_FAULT_TOLERANT
229
230 /* Check for a system sector. Data sector fault tolerance is selected with
231 the FX_FAULT_TOLERANT_DATA option. */
232
2/2
✓ Branch 41 → 42 taken 91821150 times.
✓ Branch 41 → 44 taken 78574520 times.
170395670 if (sector_type != FX_DATA_SECTOR)
233 {
234
235 /* With the fault tolerant option enabled, system sectors are written immediately to
236 the media. */
237
238 #ifndef FX_MEDIA_STATISTICS_DISABLE
239
240 /* Increment the number of driver write sector(s) requests. */
241 91821150 media_ptr -> fx_media_driver_write_requests++;
242 #endif
243
244 /* Build write request to the driver. */
245 91821150 media_ptr -> fx_media_driver_request = FX_DRIVER_WRITE;
246 91821150 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
247 91821150 media_ptr -> fx_media_driver_buffer = cache_entry -> fx_cached_sector_memory_buffer;
248 #ifdef FX_DRIVER_USE_64BIT_LBA
249 media_ptr -> fx_media_driver_logical_sector = logical_sector;
250 #else
251 91821150 media_ptr -> fx_media_driver_logical_sector = (ULONG)logical_sector;
252 #endif
253 91821150 media_ptr -> fx_media_driver_sectors = 1;
254 91821150 media_ptr -> fx_media_driver_sector_type = sector_type;
255
256 /* Yes, a system sector write is present so set the flag. The driver
257 can use this flag to make extra safeguards in writing the sector
258 out, yielding more fault tolerance. */
259 91821150 media_ptr -> fx_media_driver_system_write = FX_TRUE;
260
261 /* If trace is enabled, insert this event into the trace buffer. */
262 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, 1, cache_entry -> fx_cached_sector_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
263
264 /* Invoke the driver to write the sector(s). */
265 91821150 (media_ptr -> fx_media_driver_entry) (media_ptr);
266
267 /* Clear the system write flag. */
268 91820895 media_ptr -> fx_media_driver_system_write = FX_FALSE;
269
270 /* Return success. */
271 91820895 return(media_ptr -> fx_media_driver_status);
272 }
273 #endif
274
275 /* Determine if this is the first write of this logical sector. */
276
4/4
✓ Branch 26 → 27 taken 917731 times.
✓ Branch 26 → 28 taken 2870581 times.
✓ Branch 44 → 45 taken 77973050 times.
✓ Branch 44 → 46 taken 601470 times.
82362832 if (cache_entry -> fx_cached_sector_buffer_dirty == FX_FALSE)
277 {
278
279 /* Yes, increment the number of outstanding dirty sectors. */
280 78890781 media_ptr -> fx_media_sector_cache_dirty_count++;
281
282 /* Simply mark this entry as dirty. */
283 78890781 cache_entry -> fx_cached_sector_buffer_dirty = FX_TRUE;
284 }
285
286 /* Don't bother updating the cache linked list since writes are
287 preceded by reads anyway. */
288
289 /* Success, return to caller immediately! */
290 82362832 return(FX_SUCCESS);
291 }
292
293
294 /* Okay, so if we are here the request must be for the additional FAT writes, since this is the
295 only time a write request is made without a preceding read request. */
296
297 /* Is the logical sector valid? */
298
8/8
✓ Branch 29 → 30 taken 9488841 times.
✓ Branch 29 → 31 taken 6 times.
✓ Branch 30 → 31 taken 6 times.
✓ Branch 30 → 32 taken 9488835 times.
✓ Branch 47 → 48 taken 17283806 times.
✓ Branch 47 → 49 taken 8 times.
✓ Branch 48 → 49 taken 8 times.
✓ Branch 48 → 50 taken 17283798 times.
26772661 if ((logical_sector == 0) || (logical_sector == ((ULONG)0xFFFFFFFF)))
299 {
300 28 return(FX_SECTOR_INVALID);
301 }
302
303 /* Compare logical sector against total sectors to make sure it is valid. */
304
4/4
✓ Branch 32 → 33 taken 3 times.
✓ Branch 32 → 34 taken 9488832 times.
✓ Branch 50 → 51 taken 4 times.
✓ Branch 50 → 52 taken 17283794 times.
26772633 if ((logical_sector + sectors - 1) >= media_ptr -> fx_media_total_sectors)
305 {
306 7 return(FX_SECTOR_INVALID);
307 }
308
309 #ifndef FX_MEDIA_STATISTICS_DISABLE
310
311 /* Increment the number of driver write sector(s) requests. */
312 26772626 media_ptr -> fx_media_driver_write_requests++;
313 #endif
314
315 /* Build write request to the driver. */
316 26772626 media_ptr -> fx_media_driver_request = FX_DRIVER_WRITE;
317 26772626 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
318 26772626 media_ptr -> fx_media_driver_buffer = buffer_ptr;
319 #ifdef FX_DRIVER_USE_64BIT_LBA
320 media_ptr -> fx_media_driver_logical_sector = logical_sector;
321 #else
322 26772626 media_ptr -> fx_media_driver_logical_sector = (ULONG)logical_sector;
323 #endif
324 26772626 media_ptr -> fx_media_driver_sectors = sectors;
325 26772626 media_ptr -> fx_media_driver_sector_type = sector_type;
326
327 /* Determine if the system write flag needs to be set. */
328
4/4
✓ Branch 34 → 35 taken 9488559 times.
✓ Branch 34 → 36 taken 273 times.
✓ Branch 52 → 53 taken 12625722 times.
✓ Branch 52 → 54 taken 4658072 times.
26772626 if (sector_type != FX_DATA_SECTOR)
329 {
330
331 /* Yes, a system sector write is present so set the flag. The driver
332 can use this flag to make extra safeguards in writing the sector
333 out, yielding more fault tolerance. */
334 22114281 media_ptr -> fx_media_driver_system_write = FX_TRUE;
335 }
336
337 /* If trace is enabled, insert this event into the trace buffer. */
338 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
339
340 /* Invoke the driver to write the sector(s). */
341 26772626 (media_ptr -> fx_media_driver_entry) (media_ptr);
342
343 /* Clear the system write flag. */
344 26772590 media_ptr -> fx_media_driver_system_write = FX_FALSE;
345
346 /* Check for successful completion. */
347
4/4
✓ Branch 37 → 38 taken 3 times.
✓ Branch 37 → 39 taken 9488829 times.
✓ Branch 55 → 56 taken 14 times.
✓ Branch 55 → 57 taken 17283744 times.
26772590 if (media_ptr -> fx_media_driver_status)
348 {
349
350 /* Error writing a internal sector out. Return the
351 error status. */
352 17 return(media_ptr -> fx_media_driver_status);
353 }
354
355 /* At this point, we have a successful write. */
356 26772573 return(FX_SUCCESS);
357 }
358 else
359 #endif /* FX_DISABLE_CACHE */
360 {
361
362 /* Otherwise, the write request is being made directly from an application
363 buffer. Determine if the logical sector is valid. */
364
365 /* Is the logical sector valid? */
366
10/12
✓ Branch 7 → 8 taken 343238182 times.
✗ Branch 7 → 9 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 343238182 times.
✓ Branch 40 → 41 taken 110970 times.
✓ Branch 40 → 42 taken 6 times.
✓ Branch 41 → 42 taken 6 times.
✓ Branch 41 → 43 taken 110964 times.
✓ Branch 58 → 59 taken 168797322 times.
✓ Branch 58 → 60 taken 8 times.
✓ Branch 59 → 60 taken 8 times.
✓ Branch 59 → 61 taken 168797314 times.
512146488 if ((logical_sector == 0) || (logical_sector == ((ULONG)0xFFFFFFFF)))
367 {
368 28 return(FX_SECTOR_INVALID);
369 }
370
371 /* Compare logical sector against total sectors to make sure it is valid. */
372
6/6
✓ Branch 10 → 11 taken 4 times.
✓ Branch 10 → 12 taken 343238178 times.
✓ Branch 43 → 44 taken 9 times.
✓ Branch 43 → 45 taken 110955 times.
✓ Branch 61 → 62 taken 10 times.
✓ Branch 61 → 63 taken 168797304 times.
512146460 if ((logical_sector + sectors - 1) >= media_ptr -> fx_media_total_sectors)
373 {
374 23 return(FX_SECTOR_INVALID);
375 }
376
377 /* Flush and invalidate for any entries in the cache that are in this direct I/O read request range. */
378 512146437 _fx_utility_logical_sector_flush(media_ptr, logical_sector, (ULONG64) sectors, FX_TRUE);
379
380 #ifdef FX_DISABLE_CACHE
381
4/4
✓ Branch 13 → 14 taken 254110904 times.
✓ Branch 13 → 16 taken 89127274 times.
✓ Branch 14 → 15 taken 169712315 times.
✓ Branch 14 → 16 taken 84398589 times.
343238178 if ((logical_sector <= media_ptr -> fx_media_memory_buffer_sector) && (logical_sector + sectors >= media_ptr -> fx_media_memory_buffer_sector))
382 {
383 169712315 media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
384 }
385 #endif /* FX_DISABLE_CACHE */
386
387 #ifndef FX_MEDIA_STATISTICS_DISABLE
388
389 /* Increment the number of driver write sector(s) requests. */
390 512146437 media_ptr -> fx_media_driver_write_requests++;
391 #endif
392
393 /* Build request to the driver. */
394 512146437 media_ptr -> fx_media_driver_request = FX_DRIVER_WRITE;
395 512146437 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
396 512146437 media_ptr -> fx_media_driver_buffer = buffer_ptr;
397 #ifdef FX_DRIVER_USE_64BIT_LBA
398 media_ptr -> fx_media_driver_logical_sector = logical_sector;
399 #else
400 512146437 media_ptr -> fx_media_driver_logical_sector = (ULONG)logical_sector;
401 #endif
402 512146437 media_ptr -> fx_media_driver_sectors = sectors;
403 512146437 media_ptr -> fx_media_driver_sector_type = sector_type;
404
405 /* Determine if the system write flag needs to be set. */
406
6/6
✓ Branch 16 → 17 taken 90652377 times.
✓ Branch 16 → 18 taken 252585801 times.
✓ Branch 46 → 47 taken 6 times.
✓ Branch 46 → 48 taken 110949 times.
✓ Branch 64 → 65 taken 4 times.
✓ Branch 64 → 66 taken 168797300 times.
512146437 if (sector_type != FX_DATA_SECTOR)
407 {
408
409 /* Yes, a system sector write is present so set the flag. The driver
410 can use this flag to make extra safeguards in writing the sector
411 out, yielding more fault tolerance. */
412 90652387 media_ptr -> fx_media_driver_system_write = FX_TRUE;
413 }
414
415 /* If trace is enabled, insert this event into the trace buffer. */
416 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
417
418 /* Invoke the driver to write the sector(s). */
419 512146437 (media_ptr -> fx_media_driver_entry) (media_ptr);
420
421 /* Clear the system write flag. */
422 512145635 media_ptr -> fx_media_driver_system_write = FX_FALSE;
423
424 /* Return driver status. */
425 512145635 return(media_ptr -> fx_media_driver_status);
426 }
427 }
428
429