GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_FAT_entry_write.c Lines: 40 40 100.0 %
Date: 2024-03-11 05:15:45 Branches: 20 20 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** FileX Component                                                       */
16
/**                                                                       */
17
/**   Utility                                                             */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define FX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "fx_api.h"
28
#include "fx_system.h"
29
#include "fx_utility.h"
30
#ifdef FX_ENABLE_FAULT_TOLERANT
31
#include "fx_fault_tolerant.h"
32
#endif /* FX_ENABLE_FAULT_TOLERANT */
33
34
35
/**************************************************************************/
36
/*                                                                        */
37
/*  FUNCTION                                               RELEASE        */
38
/*                                                                        */
39
/*    _fx_utility_FAT_entry_write                         PORTABLE C      */
40
/*                                                           6.1          */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    William E. Lamie, Microsoft Corporation                             */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    This function writes to the supplied FAT entry to all FATs in       */
48
/*    the media.  12-bit, 16-bit, and 32-bit FAT writing is supported.    */
49
/*                                                                        */
50
/*  INPUT                                                                 */
51
/*                                                                        */
52
/*    media_ptr                             Media control block pointer   */
53
/*    cluster                               Cluster entry number          */
54
/*    next_cluster                          Next cluster integer pointer  */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    return status                                                       */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    _fx_utility_FAT_flush                 FLUSH dirty entries in the    */
63
/*                                            FAT cache                   */
64
/*    _fx_fault_tolerant_add_fat_log        Add FAT redo log              */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    FileX System Functions                                              */
69
/*                                                                        */
70
/*  RELEASE HISTORY                                                       */
71
/*                                                                        */
72
/*    DATE              NAME                      DESCRIPTION             */
73
/*                                                                        */
74
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
75
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
76
/*                                            resulting in version 6.1    */
77
/*                                                                        */
78
/**************************************************************************/
79
3575357
UINT  _fx_utility_FAT_entry_write(FX_MEDIA *media_ptr, ULONG cluster, ULONG next_cluster)
80
{
81
82
UINT                status, index, i;
83
FX_FAT_CACHE_ENTRY *cache_entry_ptr;
84
#ifdef FX_ENABLE_FAULT_TOLERANT
85
ULONG               FAT_sector;
86
87
    /* While fault_tolerant is enabled, only FAT entries in the same sector are allowed to be cached. */
88
    /* We must flush FAT sectors in the order of FAT chains. */
89
    if (media_ptr -> fx_media_fault_tolerant_enabled &&
90
        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
91
    {
92
93
        if (!(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN))
94
        {
95
96
            /* Redirect this request to log file. */
97
            return(_fx_fault_tolerant_add_FAT_log(media_ptr, cluster, next_cluster));
98
        }
99
100
        /* Get sector number of the incoming FAT entry. */
101
        FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cluster);
102
103
        /* Is FAT sector changed? */
104
        if (FAT_sector != media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
105
        {
106
107
            /* Are there any cached FAT entries? */
108
            if (media_ptr -> fx_media_fault_tolerant_cached_FAT_sector)
109
            {
110
111
                /* Current FAT entry is located in different sector. Force flush. */
112
                /* Flush the cached individual FAT entries */
113
                _fx_utility_FAT_flush(media_ptr);
114
115
            }
116
117
            /* Record sector number of current FAT entry. */
118
            media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = FAT_sector;
119
        }
120
    }
121
#endif /* FX_ENABLE_FAULT_TOLERANT */
122
123
#ifndef FX_MEDIA_STATISTICS_DISABLE
124
/* Increment the number of FAT entry writes and cache hits.  */
125
3575357
media_ptr -> fx_media_fat_entry_writes++;
126
3575357
media_ptr -> fx_media_fat_entry_cache_write_hits++;
127
#endif
128
129
/* Extended port-specific processing macro, which is by default defined to white space.  */
130

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

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

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