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