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 /**   Fault Tolerant                                                      */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define FX_SOURCE_CODE
23 
24 #include "fx_api.h"
25 #include "fx_utility.h"
26 #include "fx_fault_tolerant.h"
27 
28 
29 #ifdef FX_ENABLE_FAULT_TOLERANT
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _fx_fault_tolerant_recover                          PORTABLE C      */
35 /*                                                           6.1          */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    William E. Lamie, Microsoft Corporation                             */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    This function is called after the FAT chain is been updated but     */
43 /*    the rest of the write operation fails.  At this point, there is     */
44 /*    need to undo the FAT chain operation, which includes:               */
45 /*    (1) Remove newly allocated FAT entries;                             */
46 /*    (2) Restore the origianl FAT chain removed during the FAT chain     */
47 /*        update;                                                         */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    media_ptr                             Media control block pointer   */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    return status                                                       */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _fx_fault_tolerant_cleanup_FAT_chain  Cleanup FAT chain             */
60 /*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
61 /*    _fx_utility_FAT_entry_write           Write a FAT entry             */
62 /*    _fx_utility_FAT_flush                 Flush written FAT entries     */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    _fx_directory_attributes_set                                        */
67 /*    _fx_directory_create                                                */
68 /*    _fx_directory_delete                                                */
69 /*    _fx_directory_rename                                                */
70 /*    _fx_file_allocate                                                   */
71 /*    _fx_file_attributes_set                                             */
72 /*    _fx_file_best_effort_allocate                                       */
73 /*    _fx_file_create                                                     */
74 /*    _fx_file_delete                                                     */
75 /*    _fx_file_rename                                                     */
76 /*    _fx_file_truncate                                                   */
77 /*    _fx_file_truncate_release                                           */
78 /*    _fx_file_write                                                      */
79 /*    _fx_unicode_directory_create                                        */
80 /*    _fx_unicode_file_create                                             */
81 /*    _fx_fault_tolerant_enable                                           */
82 /*                                                                        */
83 /*  RELEASE HISTORY                                                       */
84 /*                                                                        */
85 /*    DATE              NAME                      DESCRIPTION             */
86 /*                                                                        */
87 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
88 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
89 /*                                            resulting in version 6.1    */
90 /*                                                                        */
91 /**************************************************************************/
_fx_fault_tolerant_recover(FX_MEDIA * media_ptr)92 UINT _fx_fault_tolerant_recover(FX_MEDIA *media_ptr)
93 {
94 UINT                         status;
95 ULONG                        insertion_front;
96 ULONG                        origianl_head_cluster;
97 FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
98 
99 
100     /* Set fault tolerant state to IDLE. */
101     media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
102 
103     /* Set FAT chain pointer. */
104     FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
105 
106     /* Whether or not the supplied FAT chain is valid. */
107     if (!(FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID))
108     {
109 
110         /* Invalid, which indiates the FAT chain has been cleaned up already.  In this case, just return. */
111         return(FX_SUCCESS);
112     }
113 
114     /* Set FAT chain pointer. */
115     FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
116 
117     /* Recover FAT chain. */
118     status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER);
119     if (status != FX_SUCCESS)
120     {
121 
122         /* Return the error status.  */
123         return(status);
124     }
125 
126     /* Now, link the front of the insertion point back to the origianl FAT chain. */
127     insertion_front = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front);
128     origianl_head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original);
129 
130     if (insertion_front != FX_FREE_CLUSTER)
131     {
132 
133         /* Front of the insertion point exists. Link the origianl chain back to the front of the insertion point. */
134         status = _fx_utility_FAT_entry_write(media_ptr, insertion_front, origianl_head_cluster);
135         if (status != FX_SUCCESS)
136         {
137 
138             /* Return the error status.  */
139             return(status);
140         }
141     }
142 
143     /* New FAT chain is always linked by FAT entries. */
144 
145     /* Flush FAT table. */
146 #ifdef FX_FAULT_TOLERANT
147 
148     /* Ensure the new FAT chain is properly written to the media.  */
149 
150     /* Flush the cached individual FAT entries */
151     _fx_utility_FAT_flush(media_ptr);
152 #endif
153 
154     /* Return success. */
155     return(FX_SUCCESS);
156 }
157 #endif /* FX_ENABLE_FAULT_TOLERANT */
158 
159