GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_logical_sector_cache_entry_read.c Lines: 126 126 100.0 %
Date: 2024-03-11 05:15:45 Branches: 28 28 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
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _fx_utility_logical_sector_cache_entry_read         PORTABLE C      */
37
/*                                                           6.1.10       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    William E. Lamie, Microsoft Corporation                             */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function handles logical sector cache read requests for the    */
45
/*    logical sector read function. If the function finds the requested   */
46
/*    sector in the cache, it setup the appropriate pointers and          */
47
/*    returns a FX_NULL.                                                  */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    media_ptr                             Media control block pointer   */
52
/*    logical_sector                        Logical sector number         */
53
/*    previous_cache_entry                  Pointer to previous entry in  */
54
/*                                            non-hashed cache            */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    FX_CACHED_SECTOR *                    Cache entry to setup          */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    None                                                                */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    _fx_utility_logical_sector_read       Logical sector read function  */
67
/*                                                                        */
68
/*  RELEASE HISTORY                                                       */
69
/*                                                                        */
70
/*    DATE              NAME                      DESCRIPTION             */
71
/*                                                                        */
72
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
73
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
74
/*                                            added conditional to        */
75
/*                                            disable cache,              */
76
/*                                            resulting in version 6.1    */
77
/*  01-31-2022     William E. Lamie         Modified comment(s), fixed    */
78
/*                                            errors without cache,       */
79
/*                                            resulting in version 6.1.10 */
80
/*                                                                        */
81
/**************************************************************************/
82
9703907
FX_CACHED_SECTOR  *_fx_utility_logical_sector_cache_entry_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
83
                                                               FX_CACHED_SECTOR **previous_cache_entry)
84
{
85
86
#ifndef FX_DISABLE_CACHE
87
FX_CACHED_SECTOR *cache_entry;
88
FX_CACHED_SECTOR  temp_storage;
89
ULONG             cache_size;
90
ULONG             index;
91
92
93
    /* Determine if the logical sector cache access should use the hash function.  */
94
9703907
    if (media_ptr -> fx_media_sector_cache_hashed)
95
    {
96
97
        /* Calculate the area of the cache for this logical sector.  */
98
99
        /* First compute the hashed value of this index by simply using the lower bits of
100
           the sector number.  */
101
2827822
        index =  (ULONG)(logical_sector & media_ptr -> fx_media_sector_cache_hash_mask);
102
103
        /* Set the bit indicating there is one or more valid sectors at this cache index.  */
104
2827822
        media_ptr -> fx_media_sector_cache_hashed_sector_valid |=  ((ULONG)1) << (index % 32);
105
106
        /* Compute the actual array index by multiplying by the cache depth.  */
107
2827822
        index =  index * FX_SECTOR_CACHE_DEPTH;
108
109
        /* Build a pointer to the cache entry.  */
110
2827822
        cache_entry =  &(media_ptr -> fx_media_sector_cache[index]);
111
112
        /* Determine if the logical sector is in the cache - assuming the depth of the
113
           sector cache is 4 entries.  */
114

2827822
        if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
115
        {
116
117
            /* Yes, we found a match.  Simply setup the pointer to this
118
               buffer and return.  */
119
2657552
            media_ptr -> fx_media_memory_buffer =  cache_entry -> fx_cached_sector_memory_buffer;
120
121
#ifndef FX_MEDIA_STATISTICS_DISABLE
122
123
            /* Increment the number of logical sectors cache read hits.  */
124
2657552
            media_ptr -> fx_media_logical_sector_cache_read_hits++;
125
#endif
126
            /* Success, return to caller immediately!  */
127
2657552
            return(FX_NULL);
128
        }
129

170270
        else if (((cache_entry + 1) -> fx_cached_sector_valid) && ((cache_entry + 1) -> fx_cached_sector == logical_sector))
130
        {
131
132
            /* Yes, we found a match.  Simply setup the pointer to this
133
               buffer and return.  */
134
15171
            media_ptr -> fx_media_memory_buffer =  (cache_entry + 1) -> fx_cached_sector_memory_buffer;
135
136
#ifndef FX_MEDIA_STATISTICS_DISABLE
137
138
            /* Increment the number of logical sectors cache read hits.  */
139
15171
            media_ptr -> fx_media_logical_sector_cache_read_hits++;
140
#endif
141
142
            /* Swap the first and second cache entries to keep the most recently used
143
               at the top.  */
144
15171
            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
145
15171
            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
146
15171
            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
147
15171
            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
148
15171
            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
149
150
15171
            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 1) -> fx_cached_sector_memory_buffer;
151
15171
            (cache_entry) -> fx_cached_sector =                     (cache_entry + 1) -> fx_cached_sector;
152
15171
            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
153
15171
            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 1) -> fx_cached_sector_valid;
154
15171
            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 1) -> fx_cached_sector_type;
155
156
15171
            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
157
15171
            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
158
15171
            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
159
15171
            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
160
15171
            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
161
162
            /* Success, return to caller immediately!  */
163
15171
            return(FX_NULL);
164
        }
165

155099
        else if (((cache_entry + 2) -> fx_cached_sector_valid) && ((cache_entry + 2) -> fx_cached_sector == logical_sector))
166
        {
167
168
            /* Yes, we found a match.  Simply setup the pointer to this
169
               buffer and return.  */
170
1492
            media_ptr -> fx_media_memory_buffer =  (cache_entry + 2) -> fx_cached_sector_memory_buffer;
171
172
#ifndef FX_MEDIA_STATISTICS_DISABLE
173
174
            /* Increment the number of logical sectors cache read hits.  */
175
1492
            media_ptr -> fx_media_logical_sector_cache_read_hits++;
176
#endif
177
178
            /* Move the third entry to the top and the first two entries down.  */
179
1492
            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
180
1492
            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
181
1492
            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
182
1492
            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
183
1492
            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
184
185
1492
            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 2) -> fx_cached_sector_memory_buffer;
186
1492
            (cache_entry) -> fx_cached_sector =                     (cache_entry + 2) -> fx_cached_sector;
187
1492
            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
188
1492
            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 2) -> fx_cached_sector_valid;
189
1492
            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 2) -> fx_cached_sector_type;
190
191
1492
            (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
192
1492
            (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
193
1492
            (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
194
1492
            (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
195
1492
            (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
196
197
1492
            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
198
1492
            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
199
1492
            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
200
1492
            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
201
1492
            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
202
203
            /* Success, return to caller immediately!  */
204
1492
            return(FX_NULL);
205
        }
206

153607
        else if (((cache_entry + 3) -> fx_cached_sector_valid) && ((cache_entry + 3) -> fx_cached_sector == logical_sector))
207
        {
208
209
            /* Yes, we found a match.  Simply setup the pointer to this
210
               buffer and return.  */
211
1299
            media_ptr -> fx_media_memory_buffer =  (cache_entry + 3) -> fx_cached_sector_memory_buffer;
212
213
#ifndef FX_MEDIA_STATISTICS_DISABLE
214
215
            /* Increment the number of logical sectors cache read hits.  */
216
1299
            media_ptr -> fx_media_logical_sector_cache_read_hits++;
217
#endif
218
219
            /* Move the last entry to the top and the first three entries down.  */
220
1299
            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
221
1299
            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
222
1299
            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
223
1299
            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
224
1299
            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
225
226
1299
            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 3) -> fx_cached_sector_memory_buffer;
227
1299
            (cache_entry) -> fx_cached_sector =                     (cache_entry + 3) -> fx_cached_sector;
228
1299
            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
229
1299
            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 3) -> fx_cached_sector_valid;
230
1299
            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 3) -> fx_cached_sector_type;
231
232
1299
            (cache_entry + 3) -> fx_cached_sector_memory_buffer =   (cache_entry + 2) -> fx_cached_sector_memory_buffer;
233
1299
            (cache_entry + 3) -> fx_cached_sector =                 (cache_entry + 2) -> fx_cached_sector;
234
1299
            (cache_entry + 3) -> fx_cached_sector_buffer_dirty =    (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
235
1299
            (cache_entry + 3) -> fx_cached_sector_valid =           (cache_entry + 2) -> fx_cached_sector_valid;
236
1299
            (cache_entry + 3) -> fx_cached_sector_type =            (cache_entry + 2) -> fx_cached_sector_type;
237
238
1299
            (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
239
1299
            (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
240
1299
            (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
241
1299
            (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
242
1299
            (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
243
244
1299
            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
245
1299
            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
246
1299
            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
247
1299
            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
248
1299
            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
249
250
            /* Success, return to caller immediately!  */
251
1299
            return(FX_NULL);
252
        }
253
254
        /* At this point we have a cache miss.  We need to move all of the sectors down one slot, swapping
255
           the 4th entry with the first.  */
256
152308
        temp_storage.fx_cached_sector_memory_buffer =           (cache_entry + 3) -> fx_cached_sector_memory_buffer;
257
152308
        temp_storage.fx_cached_sector =                         (cache_entry + 3) -> fx_cached_sector;
258
152308
        temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
259
152308
        temp_storage.fx_cached_sector_valid =                   (cache_entry + 3) -> fx_cached_sector_valid;
260
152308
        temp_storage.fx_cached_sector_type =                    (cache_entry + 3) -> fx_cached_sector_type;
261
262
152308
        (cache_entry + 3) -> fx_cached_sector_memory_buffer =   (cache_entry + 2) -> fx_cached_sector_memory_buffer;
263
152308
        (cache_entry + 3) -> fx_cached_sector =                 (cache_entry + 2) -> fx_cached_sector;
264
152308
        (cache_entry + 3) -> fx_cached_sector_buffer_dirty =    (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
265
152308
        (cache_entry + 3) -> fx_cached_sector_valid =           (cache_entry + 2) -> fx_cached_sector_valid;
266
152308
        (cache_entry + 3) -> fx_cached_sector_type =            (cache_entry + 2) -> fx_cached_sector_type;
267
268
152308
        (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
269
152308
        (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
270
152308
        (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
271
152308
        (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
272
152308
        (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
273
274
152308
        (cache_entry + 1) -> fx_cached_sector_memory_buffer =   (cache_entry) -> fx_cached_sector_memory_buffer;
275
152308
        (cache_entry + 1) -> fx_cached_sector =                 (cache_entry) -> fx_cached_sector;
276
152308
        (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    (cache_entry) -> fx_cached_sector_buffer_dirty;
277
152308
        (cache_entry + 1) -> fx_cached_sector_valid =           (cache_entry) -> fx_cached_sector_valid;
278
152308
        (cache_entry + 1) -> fx_cached_sector_type =            (cache_entry) -> fx_cached_sector_type;
279
280
152308
        (cache_entry) -> fx_cached_sector_memory_buffer =       temp_storage.fx_cached_sector_memory_buffer;
281
152308
        (cache_entry) -> fx_cached_sector =                     temp_storage.fx_cached_sector;
282
152308
        (cache_entry) -> fx_cached_sector_buffer_dirty =        temp_storage.fx_cached_sector_buffer_dirty;
283
152308
        (cache_entry) -> fx_cached_sector_valid =               temp_storage.fx_cached_sector_valid;
284
152308
        (cache_entry) -> fx_cached_sector_type =                temp_storage.fx_cached_sector_type;
285
286
        /* Set the previous pointer to NULL to avoid the linked list update below.  */
287
152308
        *previous_cache_entry =  FX_NULL;
288
    }
289
    else
290
    {
291
292
        /* Search for an entry in the cache that matches this request.  */
293
6876085
        cache_size =            media_ptr -> fx_media_sector_cache_size;
294
6876085
        cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
295
6876085
        *previous_cache_entry =  FX_NULL;
296
297
        /* Look at the cache entries until a match is found or the end of
298
           the cache is reached.  */
299
49382853
        while (cache_size--)
300
        {
301
302
            /* Determine if the requested sector has been found.  */
303

46856837
            if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
304
            {
305
306
                /* Yes, we found a match.  Simply setup the pointer to this
307
                   buffer and return.  */
308
4350069
                media_ptr -> fx_media_memory_buffer =  cache_entry -> fx_cached_sector_memory_buffer;
309
310
                /* Determine if we need to update the last used list.  */
311
4350069
                if (*previous_cache_entry)
312
                {
313
314
                    /* Yes, the current entry is not at the front of the list
315
                       so we need to change the order.  */
316
317
                    /* Link the previous entry to this entry's next pointer.  */
318
2085927
                    (*previous_cache_entry) -> fx_cached_sector_next_used =
319
2085927
                        cache_entry -> fx_cached_sector_next_used;
320
321
                    /* Place this entry at the head of the list.  */
322
2085927
                    cache_entry -> fx_cached_sector_next_used =
323
2085927
                        media_ptr -> fx_media_sector_cache_list_ptr;
324
2085927
                    media_ptr -> fx_media_sector_cache_list_ptr =  cache_entry;
325
                }
326
327
#ifndef FX_MEDIA_STATISTICS_DISABLE
328
329
                /* Increment the number of logical sectors cache read hits.  */
330
4350069
                media_ptr -> fx_media_logical_sector_cache_read_hits++;
331
#endif
332
333
                /* Success, return to caller immediately!  */
334
4350069
                return(FX_NULL);
335
            }
336
337
            /* Otherwise, we have not found the cached entry yet.  */
338
339
            /* If there are more entries, move to the next one.  */
340
42506768
            if (cache_entry -> fx_cached_sector_next_used)
341
            {
342
343
39980752
                *previous_cache_entry =  cache_entry;
344
39980752
                cache_entry =           cache_entry -> fx_cached_sector_next_used;
345
            }
346
        }
347
    }
348
349
    /* The requested sector is not in cache, return the last cache entry.  */
350
2678324
    return(cache_entry);
351
#else
352
    FX_PARAMETER_NOT_USED(media_ptr);
353
    FX_PARAMETER_NOT_USED(logical_sector);
354
    FX_PARAMETER_NOT_USED(previous_cache_entry);
355
    return(FX_NULL);
356
#endif /* FX_DISABLE_CACHE */
357
}
358