GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_FAT_entry_write.c Lines: 40 40 100.0 %
Date: 2026-03-06 18:49:02 Branches: 20 20 100.0 %

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_FAT_entry_write                         PORTABLE C      */
41
/*                                                           6.1          */
42
/*  AUTHOR                                                                */
43
/*                                                                        */
44
/*    William E. Lamie, Microsoft Corporation                             */
45
/*                                                                        */
46
/*  DESCRIPTION                                                           */
47
/*                                                                        */
48
/*    This function writes to the supplied FAT entry to all FATs in       */
49
/*    the media.  12-bit, 16-bit, and 32-bit FAT writing is supported.    */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    media_ptr                             Media control block pointer   */
54
/*    cluster                               Cluster entry number          */
55
/*    next_cluster                          Next cluster integer pointer  */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    return status                                                       */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _fx_utility_FAT_flush                 FLUSH dirty entries in the    */
64
/*                                            FAT cache                   */
65
/*    _fx_fault_tolerant_add_fat_log        Add FAT redo log              */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    FileX System Functions                                              */
70
/*                                                                        */
71
/**************************************************************************/
72
3575357
UINT  _fx_utility_FAT_entry_write(FX_MEDIA *media_ptr, ULONG cluster, ULONG next_cluster)
73
{
74
75
UINT                status, index, i;
76
FX_FAT_CACHE_ENTRY *cache_entry_ptr;
77
#ifdef FX_ENABLE_FAULT_TOLERANT
78
ULONG               FAT_sector;
79
80
    /* While fault_tolerant is enabled, only FAT entries in the same sector are allowed to be cached. */
81
    /* We must flush FAT sectors in the order of FAT chains. */
82
    if (media_ptr -> fx_media_fault_tolerant_enabled &&
83
        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
84
    {
85
86
        if (!(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN))
87
        {
88
89
            /* Redirect this request to log file. */
90
            return(_fx_fault_tolerant_add_FAT_log(media_ptr, cluster, next_cluster));
91
        }
92
93
        /* Get sector number of the incoming FAT entry. */
94
        FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cluster);
95
96
        /* Is FAT sector changed? */
97
        if (FAT_sector != media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
98
        {
99
100
            /* Are there any cached FAT entries? */
101
            if (media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
102
            {
103
104
                /* Current FAT entry is located in different sector. Force flush. */
105
                /* Flush the cached individual FAT entries */
106
                _fx_utility_FAT_flush(media_ptr);
107
108
            }
109
110
            /* Record sector number of current FAT entry. */
111
            media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = FAT_sector;
112
        }
113
    }
114
#endif /* FX_ENABLE_FAULT_TOLERANT */
115
116
#ifndef FX_MEDIA_STATISTICS_DISABLE
117
/* Increment the number of FAT entry writes and cache hits.  */
118
3575357
media_ptr -> fx_media_fat_entry_writes++;
119
3575357
media_ptr -> fx_media_fat_entry_cache_write_hits++;
120
#endif
121
122
/* Extended port-specific processing macro, which is by default defined to white space.  */
123

3575357
FX_UTILITY_FAT_ENTRY_WRITE_EXTENSION
124
125
/* Calculate the area of the cache for this FAT entry.  */
126
3575337
    index =  (cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH;
127
128
    /* Build a pointer to the cache entry.  */
129
3575337
    cache_entry_ptr =  &media_ptr -> fx_media_fat_cache[index];
130
131
    /* First search for the entry in the FAT entry cache.  */
132
13127340
    for (i = 0; i < FX_FAT_CACHE_DEPTH; i++)
133
    {
134
135
        /* See if the entry matches the write request.  */
136
10811839
        if (((cache_entry_ptr + i) -> fx_fat_cache_entry_cluster) == cluster)
137
        {
138
139
            /* Yes, we have a matching entry.  Save the new information in the FAT
140
               cache and mark this entry as dirty.  */
141
1259836
            (cache_entry_ptr + i) -> fx_fat_cache_entry_value =     next_cluster;
142
1259836
            (cache_entry_ptr + i) -> fx_fat_cache_entry_dirty =     1;
143
144
            /* Determine if the driver has requested notification when data sectors in the media
145
               become free.  This can be useful to FLASH manager software.  */
146

1259836
            if ((media_ptr -> fx_media_driver_free_sector_update) && (next_cluster == FX_FREE_CLUSTER))
147
            {
148
149
                /* Yes, the driver does wish to know that these specific sector(s) are
150
                   not in use.  */
151
152
#ifndef FX_MEDIA_STATISTICS_DISABLE
153
154
                /* Increment the number of driver release sectors requests.  */
155
96495
                media_ptr -> fx_media_driver_release_sectors_requests++;
156
#endif
157
158
                /* This cluster is being released so inform the driver that the
159
                   corresponding sectors are now available.  */
160
96495
                media_ptr -> fx_media_driver_request =          FX_DRIVER_RELEASE_SECTORS;
161
96495
                media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
162
96495
                media_ptr -> fx_media_driver_logical_sector =   (media_ptr -> fx_media_data_sector_start +
163
96495
                                                                 ((cluster - FX_FAT_ENTRY_START) * media_ptr -> fx_media_sectors_per_cluster));
164
96495
                media_ptr -> fx_media_driver_sectors =          media_ptr -> fx_media_sectors_per_cluster;
165
166
                /* If trace is enabled, insert this event into the trace buffer.  */
167
                FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS, media_ptr, media_ptr -> fx_media_driver_logical_sector, media_ptr -> fx_media_driver_sectors, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
168
169
                /* Call the driver.  */
170
96495
                (media_ptr -> fx_media_driver_entry)(media_ptr);
171
            }
172
173
            /* Done, return successful status.  */
174
1259836
            return(FX_SUCCESS);
175
        }
176
    }
177
178
    /* If we reach this point, we know that the FAT write request is not in
179
       the cache.  */
180
181
#ifndef FX_MEDIA_STATISTICS_DISABLE
182
    /* Decrement the number of cache hits.  */
183
2315501
    media_ptr -> fx_media_fat_entry_cache_write_hits--;
184
185
    /* Increment the number of cache misses.  */
186
2315501
    media_ptr -> fx_media_fat_entry_cache_write_misses++;
187
#endif
188
189
    /* Determine if the oldest entry is dirty and needs to be flushed.  */
190
2315501
    if (media_ptr -> fx_media_fat_cache[index + 3].fx_fat_cache_entry_dirty == 1)
191
    {
192
193
        /* Flush the dirty entry so it can be used to hold the current
194
           FAT entry write request.  */
195
87811
        status = _fx_utility_FAT_flush(media_ptr);
196
197
        /* Determine if the write was successful.  */
198
87811
        if (status != FX_SUCCESS)
199
        {
200
201
            /* No, return error status to caller.  */
202
47410
            return(status);
203
        }
204
205
    }
206
207
    /* Move all the cache entries down so the oldest is at the bottom.  */
208
2268091
    *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
209
2268091
    *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
210
2268091
    *(cache_entry_ptr + 1) =  *(cache_entry_ptr);
211
212
    /* Save the current FAT entry write request and mark as dirty.  */
213
2268091
    cache_entry_ptr -> fx_fat_cache_entry_dirty =    1;
214
2268091
    cache_entry_ptr -> fx_fat_cache_entry_cluster =  cluster;
215
2268091
    cache_entry_ptr -> fx_fat_cache_entry_value =    next_cluster;
216
217
    /* Determine if the driver has requested notification when data sectors in the media
218
       become free.  This can be useful to FLASH manager software.  */
219

2268091
    if ((media_ptr -> fx_media_driver_free_sector_update) && (next_cluster == FX_FREE_CLUSTER))
220
    {
221
222
        /* Yes, the driver does wish to know that these specific sector(s) are
223
           not in use.  */
224
225
#ifndef FX_MEDIA_STATISTICS_DISABLE
226
227
        /* Increment the number of driver release sectors requests.  */
228
66382
        media_ptr -> fx_media_driver_release_sectors_requests++;
229
#endif
230
231
        /* This cluster is being released so inform the driver that the
232
              corresponding sectors are now available.  */
233
66382
        media_ptr -> fx_media_driver_request =          FX_DRIVER_RELEASE_SECTORS;
234
66382
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
235
66382
        media_ptr -> fx_media_driver_logical_sector =   (media_ptr -> fx_media_data_sector_start +
236
66382
                                                         ((cluster - FX_FAT_ENTRY_START) * media_ptr -> fx_media_sectors_per_cluster));
237
66382
        media_ptr -> fx_media_driver_sectors =          media_ptr -> fx_media_sectors_per_cluster;
238
239
        /* If trace is enabled, insert this event into the trace buffer.  */
240
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_RELEASE_SECTORS, media_ptr, media_ptr -> fx_media_driver_logical_sector, media_ptr -> fx_media_driver_sectors, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
241
242
        /* Call the driver.  */
243
66382
        (media_ptr -> fx_media_driver_entry)(media_ptr);
244
    }
245
246
    /* Return success to caller.  */
247
2268091
    return(FX_SUCCESS);
248
}
249