Files
filex/common/src/fx_fault_tolerant_apply_logs.c
T
Frédéric Desbiens 61b0b06c3e Updated copyright headers and removed revision history
* Updated version number constants

* Updated copyright headers and removed revision history
2026-03-05 08:39:33 +01:00

257 lines
11 KiB
C

/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2026-present Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** FileX Component */
/** */
/** Fault Tolerant */
/** */
/**************************************************************************/
/**************************************************************************/
#define FX_SOURCE_CODE
#include "fx_api.h"
#include "fx_utility.h"
#include "fx_fault_tolerant.h"
#ifdef FX_ENABLE_FAULT_TOLERANT
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _fx_fault_tolerant_apply_logs PORTABLE C */
/* 6.2.0 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function applies changes to the file system. The changes are */
/* already recorded in the fault tolerant log file. Therefore this */
/* function reads the content of the log entries and apply these */
/* changes to the file system. */
/* */
/* INPUT */
/* */
/* media_ptr Media control block pointer */
/* */
/* OUTPUT */
/* */
/* return status */
/* */
/* CALLS */
/* */
/* _fx_utility_logical_sector_write Write a logical sector */
/* _fx_utility_logical_sector_read Read a logical sector */
/* _fx_utility_16_unsigned_read Read a USHORT from memory */
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
/* _fx_utility_64_unsigned_read Read a ULONG64 from memory */
/* _fx_utility_FAT_entry_write Write a FAT entry */
/* _fx_fault_tolerant_cleanup_FAT_chain Cleanup FAT chain */
/* memcpy Memory Copy */
/* _fx_utility_FAT_flush Flush written FAT entries */
/* _fx_utility_logical_sector_flush Flush written logical sectors */
/* */
/* CALLED BY */
/* */
/* _fx_fault_tolerant_enable */
/* _fx_fault_tolerant_transaction_end */
/* */
/**************************************************************************/
UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr)
{
UINT status;
ULONG64 log_sector;
ULONG remaining_logs;
ULONG copy_size;
ULONG copy_offset;
UCHAR *current_ptr;
ULONG size;
USHORT log_type;
ULONG log_len;
FX_FAULT_TOLERANT_LOG_HEADER *log_header;
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
FX_FAULT_TOLERANT_FAT_LOG *fat_log;
FX_FAULT_TOLERANT_DIR_LOG *dir_log;
/* Set log header, FAT chain and log content pointer. */
log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
/* Find the size of the log file. */
size = _fx_utility_16_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size);
/* Extended port-specific processing macro, which is by default defined to white space. */
FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
size -= FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
/* Find the number of log entries. */
remaining_logs = _fx_utility_16_unsigned_read((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count);
/* Get start address of logs. */
current_ptr = (UCHAR *)log_content + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
/* Loop through all the logs to apply the changes. */
while (remaining_logs)
{
/* Obtain log type of this entry. */
log_type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
/* Read log length. */
log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
/* Validate log entry size. */
if (log_len > size)
{
/* Something wrong with log file. */
return(FX_FILE_CORRUPT);
}
/* Reduce the total log file size. */
size -= log_len;
/* Process log entry by type. */
switch (log_type)
{
case FX_FAULT_TOLERANT_FAT_LOG_TYPE:
/* This is a FAT log. */
fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)current_ptr;
/* Write FAT entry. */
status = _fx_utility_FAT_entry_write(media_ptr,
_fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster),
_fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value));
if (status != FX_SUCCESS)
{
/* Return the error status. */
return(status);
}
break;
case FX_FAULT_TOLERANT_DIR_LOG_TYPE:
/* This is a DIR log. */
dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
/* Get the destination sector. */
status = _fx_utility_logical_sector_read(media_ptr,
log_sector,
media_ptr -> fx_media_memory_buffer,
((ULONG) 1), FX_DATA_SECTOR);
if (status != FX_SUCCESS)
{
/* Return the error status. */
return(status);
}
/* Set copy information. */
copy_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
copy_size = log_len - FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
if (((ULONG64)copy_offset + (ULONG64)copy_size) > (ULONG64)(media_ptr -> fx_media_memory_size))
{
return(FX_FILE_CORRUPT);
}
/* Copy data into destination sector. */
memcpy(media_ptr -> fx_media_memory_buffer + copy_offset, /* Use case of memcpy is verified. */
current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE, copy_size);
/* Write back the current logical sector. */
status = _fx_utility_logical_sector_write(media_ptr,
log_sector,
media_ptr -> fx_media_memory_buffer,
((ULONG) 1), FX_DIRECTORY_SECTOR);
if (status != FX_SUCCESS)
{
/* Return the error status. */
return(status);
}
break;
default:
/* Wrong type. */
return(FX_SECTOR_INVALID);
}
/* Decrement the remaining log counter. */
remaining_logs--;
/* Move to start position of next log entry. */
current_ptr += log_len;
}
/* Check whether or not to process FAT chain. */
if (FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID)
{
/* Free old link of FAT. */
status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP);
if (status != FX_SUCCESS)
{
/* Return the error status. */
return(status);
}
}
/* Flush the internal logical sector cache. */
status = _fx_utility_logical_sector_flush(media_ptr, 1, (ULONG64) media_ptr -> fx_media_total_sectors, FX_FALSE);
/* Check for a bad status. */
if (status != FX_SUCCESS)
{
/* Return the bad status. */
return(status);
}
/* Flush FAT table. */
#ifdef FX_FAULT_TOLERANT
/* Ensure the new FAT chain is properly written to the media. */
/* Flush the cached individual FAT entries */
_fx_utility_FAT_flush(media_ptr);
#endif
/* Return success. */
return(FX_SUCCESS);
}
#endif /* FX_ENABLE_FAULT_TOLERANT */