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