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_fault_tolerant.h"
26 #include "fx_utility.h"
27
28 #ifdef FX_ENABLE_FAULT_TOLERANT
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* _fx_fault_tolerant_transaction_end PORTABLE C */
34 /* 6.1 */
35 /* AUTHOR */
36 /* */
37 /* William E. Lamie, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* This function completes a file system update operation protected */
42 /* by fault tolerant. This function first computes the checksum */
43 /* for the log entries, flush the log file to the file system (a */
44 /* necessary step to record vital information for the file system to */
45 /* recover, in case the update operation fails midway). After the */
46 /* log entries are written to the physical medium, the actualy file */
47 /* system changes (FAT table, directory entries) are applied. */
48 /* */
49 /* If the file system changes are successfully applied, the log */
50 /* entries can be removed. */
51 /* */
52 /* INPUT */
53 /* */
54 /* media_ptr Media control block pointer */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* return status */
59 /* */
60 /* CALLS */
61 /* */
62 /* _fx_utility_16_unsigned_write Write a USHORT from memory */
63 /* _fx_fault_tolerant_apply_logs Apply logs into file system */
64 /* _fx_fault_tolerant_calculate_checksum Compute Checksum of data */
65 /* _fx_fault_tolerant_write_log_file Write log file */
66 /* _fx_fault_tolerant_reset_log_file Reset the log file */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* _fx_directory_attributes_set */
71 /* _fx_directory_create */
72 /* _fx_directory_delete */
73 /* _fx_directory_rename */
74 /* _fx_file_allocate */
75 /* _fx_file_attributes_set */
76 /* _fx_file_best_effort_allocate */
77 /* _fx_file_create */
78 /* _fx_file_delete */
79 /* _fx_file_rename */
80 /* _fx_file_truncate */
81 /* _fx_file_truncate_release */
82 /* _fx_file_write */
83 /* _fx_unicode_directory_create */
84 /* _fx_unicode_file_create */
85 /* */
86 /* RELEASE HISTORY */
87 /* */
88 /* DATE NAME DESCRIPTION */
89 /* */
90 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
91 /* 09-30-2020 William E. Lamie Modified comment(s), */
92 /* resulting in version 6.1 */
93 /* */
94 /**************************************************************************/
_fx_fault_tolerant_transaction_end(FX_MEDIA * media_ptr)95 UINT _fx_fault_tolerant_transaction_end(FX_MEDIA *media_ptr)
96 {
97 ULONG relative_sector;
98 UINT status;
99 USHORT checksum;
100 UINT offset;
101 FX_FAULT_TOLERANT_LOG_HEADER *log_header;
102 FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
103
104 /* Is fault tolerant enabled? */
105 if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
106 {
107 return(FX_SUCCESS);
108 }
109
110 /* Decrease the transaction. */
111 media_ptr -> fx_media_fault_tolerant_transaction_count--;
112
113 /* Is transaction finished? */
114 if (media_ptr -> fx_media_fault_tolerant_transaction_count != 0)
115 {
116 return(FX_SUCCESS);
117 }
118
119 /* Close this transaction. */
120 media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
121
122 /* Set log header and FAT chain pointer. */
123 log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
124 log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
125 FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
126
127 /* Reset checksum field and update log entry counter field. */
128 _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, 0);
129 _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count,
130 media_ptr -> fx_media_fault_tolerant_total_logs);
131
132 /* Now calculate the checksum of log content. */
133 checksum = _fx_fault_tolerant_calculate_checksum((media_ptr -> fx_media_fault_tolerant_memory_buffer +
134 FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET),
135 (media_ptr -> fx_media_fault_tolerant_file_size -
136 FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET));
137
138 /* Record checksum field of log content. */
139 _fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, checksum);
140
141 /* Record log header. */
142 _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size,
143 media_ptr -> fx_media_fault_tolerant_file_size);
144 _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, 0);
145
146 /* Calculate checksum of the header. */
147 checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header, FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
148
149 /* Record checksum field of the header. */
150 _fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, checksum);
151
152 /* Flush log content and flush first sector at last. The first sector contains size of total log file.
153 * The log file will contain wrong value of size when it is interrupted after first sector flushed to file system. */
154 relative_sector = 1;
155 offset = media_ptr -> fx_media_bytes_per_sector;
156 while (offset < media_ptr -> fx_media_fault_tolerant_file_size)
157 {
158
159 /* Write back the log. */
160 status = _fx_fault_tolerant_write_log_file(media_ptr, relative_sector);
161
162 /* Check for good completion status. */
163 if (status != FX_SUCCESS)
164 {
165
166 /* Error. */
167 return(status);
168 }
169
170 /* Increase relative sector and offset. */
171 relative_sector++;
172 offset += media_ptr -> fx_media_bytes_per_sector;
173 }
174
175 /* Flush first sector. */
176 status = _fx_fault_tolerant_write_log_file(media_ptr, 0);
177
178 /* Check for good completion status. */
179 if (status != FX_SUCCESS)
180 {
181
182 /* Error. */
183 return(status);
184 }
185
186 /* At this pointer, the vital information has been flushed to the physical medium.
187 Update the file system (FAT table, directory entry) using information recorded in the
188 log file. */
189 status = _fx_fault_tolerant_apply_logs(media_ptr);
190
191 /* Check for a bad status. */
192 if (status != FX_SUCCESS)
193 {
194
195 /* Return the bad status. */
196 return(status);
197 }
198
199 /* The file system has been updated successfully. Remove and reset the fault tolerant
200 log file. */
201 status = _fx_fault_tolerant_reset_log_file(media_ptr);
202
203 return(status);
204 }
205 #endif /* FX_ENABLE_FAULT_TOLERANT */
206
207