GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_logical_sector_write.c Lines: 63 63 100.0 %
Date: 2024-01-10 21:53:23 Branches: 48 48 100.0 %

Line Branch Exec Source
1
/**************************************************************************/
2
/*                                                                        */
3
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4
/*                                                                        */
5
/*       This software is licensed under the Microsoft Software License   */
6
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8
/*       and in the root directory of this software.                      */
9
/*                                                                        */
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
/*  RELEASE HISTORY                                                       */
82
/*                                                                        */
83
/*    DATE              NAME                      DESCRIPTION             */
84
/*                                                                        */
85
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
86
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
87
/*                                            added conditional to        */
88
/*                                            disable cache,              */
89
/*                                            resulting in version 6.1    */
90
/*  04-02-2021     Bhupendra Naphade        Modified comment(s),          */
91
/*                                            updated check for logical   */
92
/*                                            sector value,               */
93
/*                                            resulting in version 6.1.6  */
94
/*                                                                        */
95
/**************************************************************************/
96
4467652
UINT  _fx_utility_logical_sector_write(FX_MEDIA *media_ptr, ULONG64 logical_sector,
97
                                       VOID *buffer_ptr, ULONG sectors, UCHAR sector_type)
98
{
99
100
#ifndef FX_DISABLE_CACHE
101
FX_CACHED_SECTOR *cache_entry;
102
UINT              cache_size;
103
UINT              index;
104
UINT              i;
105
4467652
UCHAR             cache_found = FX_FALSE;
106
#endif /* FX_DISABLE_CACHE */
107
108
#ifndef FX_MEDIA_STATISTICS_DISABLE
109
110
    /* Determine if the request is for FAT sector.  */
111
4467652
    if (sector_type == FX_FAT_SECTOR)
112
    {
113
114
        /* Increment the number of FAT sector writes.  */
115
3547771
        media_ptr -> fx_media_fat_sector_writes++;
116
    }
117
118
    /* Increment the number of logical sectors written.  */
119
4467652
    media_ptr -> fx_media_logical_sector_writes++;
120
#endif
121
122
    /* Extended port-specific processing macro, which is by default defined to white space.  */
123

4467652
    FX_UTILITY_LOGICAL_SECTOR_WRITE_EXTENSION
124
125
#ifndef FX_DISABLE_CACHE
126
    /* Determine if the request is from the internal media buffer area.  */
127
4463055
    if ((((UCHAR *)buffer_ptr) >= media_ptr -> fx_media_memory_buffer) &&
128
4426074
        (((UCHAR *)buffer_ptr) <= media_ptr -> fx_media_sector_cache_end))
129
    {
130
131
        /* Internal cache buffer is requested.  */
132
133
        /* Determine if the logical sector cache access should use the hash function.  */
134
4426063
        if (media_ptr -> fx_media_sector_cache_hashed)
135
        {
136
137
            /* Calculate the area of the cache for this logical sector.  */
138
2166735
            index =  (ULONG)(logical_sector & media_ptr -> fx_media_sector_cache_hash_mask) * FX_SECTOR_CACHE_DEPTH;
139
140
            /* Build a pointer to the cache entry.  */
141
2166735
            cache_entry =  &(media_ptr -> fx_media_sector_cache[index]);
142
143
8488147
            for (i = 0; i < FX_SECTOR_CACHE_DEPTH; i++, cache_entry++)
144
            {
145
146
147
                /* Determine if the logical sector is in the cache - assuming the depth of the
148
                   sector cache is 4 entries.  */
149

6907937
                if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
150
                {
151
586525
                    cache_found = FX_TRUE;
152
586525
                    break;
153
                }
154
            }
155
        }
156
        else
157
        {
158
159
            /* Search for an entry in the cache that matches this request.  */
160
2259328
            cache_size =            media_ptr -> fx_media_sector_cache_size;
161
2259328
            cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
162
163
            /* Look at the cache entries until a match is found or the end of
164
               the cache is reached.  */
165
405836871
            while (cache_size--)
166
            {
167
168
                /* Determine if the requested sector has been found.  */
169

404254132
                if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
170
                {
171
676589
                    cache_found = FX_TRUE;
172
676589
                    break;
173
                }
174
175
                /* Otherwise, we have not found the cached entry yet.  */
176
177
                /* If there are more entries, move to the next one.  */
178
403577543
                if (cache_entry -> fx_cached_sector_next_used)
179
                {
180
181
                    /* Move to the next cache entry.  */
182
401994804
                    cache_entry =  cache_entry -> fx_cached_sector_next_used;
183
                }
184
            }
185
        }
186
187
#ifdef FX_ENABLE_FAULT_TOLERANT
188
        if (media_ptr -> fx_media_fault_tolerant_enabled &&
189
            (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED) &&
190
            (sector_type == FX_DATA_SECTOR) &&
191
            !(cache_found && (cache_entry -> fx_cached_sector_memory_buffer == buffer_ptr)))
192
        {
193
194
            /* Special use case for file write when fault tolerant is enabled. */
195
            /* Data are read from one sector but write to another sector. */
196
            /* Need to invalidate both of original and new caches. */
197
            if (cache_found)
198
            {
199
200
                /* Invalidate the new cache. */
201
                cache_entry -> fx_cached_sector_valid = FX_FALSE;
202
                cache_found = FX_FALSE;
203
            }
204
205
            /* Search for original cache.  */
206
            cache_size =            media_ptr -> fx_media_sector_cache_size;
207
            cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
208
209
            /* Look at the cache entries until a match is found or the end of
210
               the cache is reached.  */
211
            while (cache_size--)
212
            {
213
214
                /* Determine if the original sector has been found.  */
215
                if ((cache_entry -> fx_cached_sector_valid) &&
216
                    (cache_entry -> fx_cached_sector_memory_buffer == buffer_ptr))
217
                {
218
219
                    /* Invalidate the original cache. */
220
                    cache_entry -> fx_cached_sector_valid = FX_FALSE;
221
                    break;
222
                }
223
224
                /* Otherwise, we have not found the cached entry yet.  */
225
226
                /* If there are more entries, move to the next one.  */
227
                if (cache_entry -> fx_cached_sector_next_used)
228
                {
229
230
                    /* Move to the next cache entry.  */
231
                    cache_entry =  cache_entry -> fx_cached_sector_next_used;
232
                }
233
            }
234
        }
235
#endif /* FX_ENABLE_FAULT_TOLERANT */
236
237
4426063
        if (cache_found)
238
        {
239
240
            /* Yes, we found a match.  */
241
242
#ifdef FX_FAULT_TOLERANT
243
244
            /* Check for a system sector. Data sector fault tolerance is selected with
245
               the FX_FAULT_TOLERANT_DATA option.  */
246
            if (sector_type != FX_DATA_SECTOR)
247
            {
248
249
                /* With the fault tolerant option enabled, system sectors are written immediately to
250
                   the media.  */
251
252
#ifndef FX_MEDIA_STATISTICS_DISABLE
253
254
                /* Increment the number of driver write sector(s) requests.  */
255
                media_ptr -> fx_media_driver_write_requests++;
256
#endif
257
258
                /* Build write request to the driver.  */
259
                media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
260
                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
261
                media_ptr -> fx_media_driver_buffer =           cache_entry -> fx_cached_sector_memory_buffer;
262
#ifdef FX_DRIVER_USE_64BIT_LBA
263
                media_ptr -> fx_media_driver_logical_sector =   logical_sector;
264
#else
265
                media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
266
#endif
267
                media_ptr -> fx_media_driver_sectors =          1;
268
                media_ptr -> fx_media_driver_sector_type =      sector_type;
269
270
                /* Yes, a system sector write is present so set the flag.  The driver
271
                   can use this flag to make extra safeguards in writing the sector
272
                   out, yielding more fault tolerance.  */
273
                media_ptr -> fx_media_driver_system_write =  FX_TRUE;
274
275
                /* If trace is enabled, insert this event into the trace buffer.  */
276
                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)
277
278
                /* Invoke the driver to write the sector(s).  */
279
                (media_ptr -> fx_media_driver_entry) (media_ptr);
280
281
                /* Clear the system write flag.  */
282
                media_ptr -> fx_media_driver_system_write =  FX_FALSE;
283
284
                /* Return success.  */
285
                return(media_ptr -> fx_media_driver_status);
286
            }
287
#endif
288
289
            /* Determine if this is the first write of this logical sector.  */
290
1263114
            if (cache_entry -> fx_cached_sector_buffer_dirty == FX_FALSE)
291
            {
292
293
                /* Yes, increment the number of outstanding dirty sectors.  */
294
306017
                media_ptr -> fx_media_sector_cache_dirty_count++;
295
296
                /* Simply mark this entry as dirty.  */
297
306017
                cache_entry -> fx_cached_sector_buffer_dirty =  FX_TRUE;
298
            }
299
300
            /* Don't bother updating the cache linked list since writes are
301
               preceded by reads anyway.  */
302
303
            /* Success, return to caller immediately!  */
304
1263114
            return(FX_SUCCESS);
305
        }
306
307
308
        /* Okay, so if we are here the request must be for the additional FAT writes, since this is the
309
           only time a write request is made without a preceding read request.  */
310
311
        /* Is the logical sector valid?  */
312

3162949
        if ((logical_sector == 0) || (logical_sector == ((ULONG)0xFFFFFFFF)))
313
        {
314
4
            return(FX_SECTOR_INVALID);
315
        }
316
317
        /* Compare logical sector against total sectors to make sure it is valid.  */
318
3162945
        if ((logical_sector + sectors - 1) >= media_ptr -> fx_media_total_sectors)
319
        {
320
1
            return(FX_SECTOR_INVALID);
321
        }
322
323
        /* Just write the buffer to the media.  */
324
325
#ifndef FX_MEDIA_STATISTICS_DISABLE
326
327
        /* Increment the number of driver write sector(s) requests.  */
328
3162944
        media_ptr -> fx_media_driver_write_requests++;
329
#endif
330
331
        /* Build write request to the driver.  */
332
3162944
        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
333
3162944
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
334
3162944
        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
335
#ifdef FX_DRIVER_USE_64BIT_LBA
336
        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
337
#else
338
3162944
        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
339
#endif
340
3162944
        media_ptr -> fx_media_driver_sectors =          sectors;
341
3162944
        media_ptr -> fx_media_driver_sector_type =      sector_type;
342
343
        /* Determine if the system write flag needs to be set.  */
344
3162944
        if (sector_type != FX_DATA_SECTOR)
345
        {
346
347
            /* Yes, a system sector write is present so set the flag.  The driver
348
               can use this flag to make extra safeguards in writing the sector
349
               out, yielding more fault tolerance.  */
350
3162853
            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
351
        }
352
353
        /* If trace is enabled, insert this event into the trace buffer.  */
354
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
355
356
        /* Invoke the driver to write the sector(s).  */
357
3162944
        (media_ptr -> fx_media_driver_entry) (media_ptr);
358
359
        /* Clear the system write flag.  */
360
3162944
        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
361
362
        /* Check for successful completion.  */
363
3162944
        if (media_ptr -> fx_media_driver_status)
364
        {
365
366
            /* Error writing a internal sector out.  Return the
367
               error status.  */
368
1
            return(media_ptr -> fx_media_driver_status);
369
        }
370
371
        /* At this point, we have a successful write.  */
372
3162943
        return(FX_SUCCESS);
373
    }
374
    else
375
#endif /* FX_DISABLE_CACHE */
376
    {
377
378
        /* Otherwise, the write request is being made directly from an application
379
           buffer. Determine if the logical sector is valid.  */
380
381
        /* Is the logical sector valid? */
382

36992
        if ((logical_sector == 0) || (logical_sector == ((ULONG)0xFFFFFFFF)))
383
        {
384
4
            return(FX_SECTOR_INVALID);
385
        }
386
387
        /* Compare logical sector against total sectors to make sure it is valid.  */
388
36988
        if ((logical_sector + sectors - 1) >= media_ptr -> fx_media_total_sectors)
389
        {
390
3
            return(FX_SECTOR_INVALID);
391
        }
392
393
        /* Flush and invalidate for any entries in the cache that are in this direct I/O read request range.  */
394
36985
        _fx_utility_logical_sector_flush(media_ptr, logical_sector, (ULONG64) sectors, FX_TRUE);
395
396
#ifdef FX_DISABLE_CACHE
397
        if ((logical_sector <= media_ptr -> fx_media_memory_buffer_sector) && (logical_sector + sectors >= media_ptr -> fx_media_memory_buffer_sector))
398
        {
399
            media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
400
        }
401
#endif /* FX_DISABLE_CACHE */
402
403
#ifndef FX_MEDIA_STATISTICS_DISABLE
404
405
        /* Increment the number of driver write sector(s) requests.  */
406
36985
        media_ptr -> fx_media_driver_write_requests++;
407
#endif
408
409
        /* Build request to the driver.  */
410
36985
        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
411
36985
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
412
36985
        media_ptr -> fx_media_driver_buffer =           buffer_ptr;
413
#ifdef FX_DRIVER_USE_64BIT_LBA
414
        media_ptr -> fx_media_driver_logical_sector =   logical_sector;
415
#else
416
36985
        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
417
#endif
418
36985
        media_ptr -> fx_media_driver_sectors =          sectors;
419
36985
        media_ptr -> fx_media_driver_sector_type =      sector_type;
420
421
        /* Determine if the system write flag needs to be set.  */
422
36985
        if (sector_type != FX_DATA_SECTOR)
423
        {
424
425
            /* Yes, a system sector write is present so set the flag.  The driver
426
               can use this flag to make extra safeguards in writing the sector
427
               out, yielding more fault tolerance.  */
428
2
            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
429
        }
430
431
        /* If trace is enabled, insert this event into the trace buffer.  */
432
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, logical_sector, sectors, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
433
434
        /* Invoke the driver to write the sector(s).  */
435
36985
        (media_ptr -> fx_media_driver_entry) (media_ptr);
436
437
        /* Clear the system write flag.  */
438
36985
        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
439
440
        /* Return driver status.  */
441
36985
        return(media_ptr -> fx_media_driver_status);
442
    }
443
}
444