📄 zfsinit.c
字号:
/*
* File : ZFSInit.c
* Description: This file contains the implementation of ZFS initialization
* Author : Mahadev K C
* Created on : 30-APR-2003
*
* Copyright 2004 ZiLOG Inc. ALL RIGHTS RESERVED.
*
* This file contains unpublished confidential and proprietary information
* of ZiLOG, Inc.
* NO PART OF THIS WORK MAY BE DUPLICATED, STORED, PUBLISHED OR DISCLOSED
* IN ANY FORM WITHOUT THE PRIOR WRITTEN CONSENT OF ZiLOG, INC.
* This is not a license and no use of any kind of this work is authorized
* in the absence of a written license granted by ZiLOG, Inc. in ZiLOG's
* sole discretion
*/
#include <string.h>
#include <stdlib.h>
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZSemaphore.h"
#include "glextern.h"
#include "zfscfg.h"
// RZK variables
extern UINT nRzkMaxCwdPathLen ;
extern UINT MAX_THREADS ;
extern UINT g_max_threads ;
extern UINT g_max_cwd_len ;
extern UINT8 g_byEraseFlash ;
extern ZFS_DIR_LIST_CB_t g_dir_list[ ] ;
extern ZFS_STATUS_t GC( PZFS_VOL_INFO_t pvol_info ) ;
extern UINT8 InitializeRTC( void ) ;
RZK_SEMAPHOREHANDLE_t hSem_FS;
extern ZFS_STATUS_t IsNewOverWrittenSectorExist( PZFS_VOL_INFO_t , PZFS_SEC_HDR_t , PZFS_SEC_HDR_t );
#ifdef POWER_FAIL_SAFE
// POWER FAIL_SAFE CODE for file system
UINT8 g_sec_buf[ ZFS_SEC_SIZE ] ;
void CarrySubGC( PZFS_VOL_INFO_t pvol_info, UINT num_of_sec, PZFS_SEC_HDR_t ab_sec_hdr, PZFS_SEC_HDR_t tb_sec_hdr )
{
UINT fir_cnt ;
ZFS_SEC_HDR_t sec_hdr ;
// ZFS_FIR_t fir_hdr ;
PZFS_FIR_t pfir_addr ;
// PZFS_FIR_t ptb_fir_addr ;
UINT8 status ;
PZFS_CONFIG_t pzfs_cfg ;
pzfs_cfg = pvol_info->pcfg ;
// just update the parameters
num_of_sec-- ;
tb_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) tb_sec_hdr + ZFS_SEC_SIZE) ;
ab_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) ab_sec_hdr + ZFS_SEC_SIZE) ;
//now go through the AB for valid sectors, copy it them into TB
while( num_of_sec > 0 )
{
// read the AB sec header
pzfs_cfg->pfn_drv_read( ab_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t )) ;
// BUG_FIX : 16_SEP
// if( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY )) == ZFS_SEC_ALLOCATED )
if( ( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY )) == ZFS_SEC_ALLOCATED ) ||
( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP | ZFS_SEC_NO_DUP )) == (ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP ))
)
// BUG_FIX : 16_SEP
{
if( (~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_DATA )
{
// if the sector is data sector, just copy it
pzfs_cfg->pfn_drv_read( ab_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
// write onto TB.
pzfs_cfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
tb_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) tb_sec_hdr + ZFS_SEC_SIZE) ;
}
else if( (~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_FIT )
{
// if FIT sector
UINT8 *ptr = &g_sec_gc[0] ;
UINT16 ttl_sec_bit = ZFS_SEC_HDR_WRITTEN ;
UINT16 sec_data_bit = 0x02 ;
InitializeHeader( &g_sec_gc[0], ZFS_SEC_SIZE ) ;
memcpy( &g_sec_gc[0], &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
// if sector is FIT, then copy only the valid FIRs onto the TB
ptr += sizeof( ZFS_FIR_t ) ;
fir_cnt = ZFS_SEC_SIZE / sizeof(ZFS_FIR_t) - 1 ;
pfir_addr = (PZFS_FIR_t)((UINT8*)ab_sec_hdr + sizeof(ZFS_FIR_t)) ;
while( fir_cnt > 0 )
{
// get the first fir
pzfs_cfg->pfn_drv_read( pfir_addr, &status, 1 ) ;
if( ( ~(status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY ) ) == ZFS_FIR_ALLOCATED )
{
pzfs_cfg->pfn_drv_read( pfir_addr, ptr, sizeof( ZFS_FIR_t ) ) ;
ptr+= sizeof( ZFS_FIR_t ) ;
ttl_sec_bit &= ( ~sec_data_bit ) ;
sec_data_bit <<= 1 ;
}
pfir_addr++ ;
fir_cnt--;
}
// write the sector onto the new TB.
*((UINT16 *)(&g_sec_gc[0] + SEC_DATA_BIT_OFFSET)) = ttl_sec_bit ;
pzfs_cfg->pfn_drv_write(tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
tb_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) tb_sec_hdr + ZFS_SEC_SIZE) ;
}
}
num_of_sec-- ;
ab_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) ab_sec_hdr + ZFS_SEC_SIZE) ;
}
return ;
}
ZFS_STATUS_t PerFormGCFromPowerFail( PZFS_VOL_INFO_t pvol_info, PZFS_BLK_INFO_t pab_blk_info, PZFS_BLK_INFO_t ptb_blk_info )
{
PZFS_SEC_HDR_t ab_sec_hdr ;
PZFS_SEC_HDR_t tb_sec_hdr ;
UINT num_of_sec ;
UINT fir_cnt ;
UINT8 *ptr ;
PZFS_CONFIG_t pzfs_cfg = pvol_info->pcfg ;
ZFS_SEC_HDR_t sec_hdr ;
PZFS_FIR_t pfir_ab_addr, pfir_tb_addr ;
ZFS_FIR_t fir_tb_hdr ;
UINT8 type_status ;
ZFS_BLK_HDR_t blk_hdr ;
// UINT cnt ;
UINT ab_blk_num ;
PZFS_BLK_HDR_t pblk_hdr ;
UINT32 blk_size = 0 ;
// The GC is in progress, power failed. just get the alloc block and do the GC again,
// now check for the valid sectors present in AB and the corresponding sector in TB
//now go through the AB for valid sectors, copy it them into TB
ab_sec_hdr = (PZFS_SEC_HDR_t) (( (UINT8*)pab_blk_info->blk_start_addr) + ZFS_SEC_SIZE );
tb_sec_hdr = (PZFS_SEC_HDR_t) (( (UINT8*)ptb_blk_info->blk_start_addr) + ZFS_SEC_SIZE ) ;
num_of_sec = (pzfs_cfg->vol_secs/pzfs_cfg->vol_blks) - 1;
// write the AB header here for gc_toblk and ab_gc_start flag
// read the AB header.
pzfs_cfg->pfn_drv_read( pab_blk_info->blk_start_addr, &blk_hdr, sizeof( ZFS_BLK_HDR_t )) ;
if( blk_hdr.ab_gc_start == 0xFF || blk_hdr.gc_toblk == 0xFF )
{
// block headers are not proper. Write proper block headers.
blk_hdr.ab_gc_start = 0xFE ;
blk_hdr.gc_toblk = ptb_blk_info->blk_hdr.blk_num ;
pzfs_cfg->pfn_drv_write( pab_blk_info->blk_start_addr, &blk_hdr, sizeof( ZFS_BLK_HDR_t )) ;
}
while( num_of_sec > 0 )
{
// read the AB sec header
pzfs_cfg->pfn_drv_read( ab_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t )) ;
// check whether the sector is dirty or valid
// BUG_FIX : 16_SEP
// if( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY ) ) == ZFS_SEC_ALLOCATED )
if( ( ((~sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY ) ) == ZFS_SEC_ALLOCATED ) ||
( ((~sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP | ZFS_SEC_NO_DUP )) == ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP )
)
// BUG_FIX : 16_SEP
{
if( (~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_DATA )
{
// if the sector is data sector, just copy it
// read AB sector
pzfs_cfg->pfn_drv_read( ab_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
// read TB sector
pzfs_cfg->pfn_drv_read( tb_sec_hdr, &g_sec_buf[0], ZFS_SEC_SIZE ) ;
if( memcmp( &g_sec_gc[0], g_sec_buf, ZFS_SEC_SIZE ) )
{
// error, just check from which offset the data need to be written
// optimize for performance here
//write the sector here
pzfs_cfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
// here onwards, only copy the sectors to sectors
CarrySubGC( pvol_info, num_of_sec, ab_sec_hdr, tb_sec_hdr ) ;
// go to the end of this function
goto _end_power_fail_gc ;
}
}
else if( (~(sec_hdr.status) & ZFS_SEC_TYPE_FIT) )
{
// if FIT sector
// already read teh sector header,
// if sector is FIT, then copy only the valid FIRs onto the TB
pfir_ab_addr = (PZFS_FIR_t)((UINT8*)ab_sec_hdr + sizeof(ZFS_FIR_t)) ;
InitializeHeader( &g_sec_gc[0], ZFS_SEC_SIZE ) ;
ptr = &g_sec_gc[0] + sizeof( ZFS_FIR_t ) ;
// store the sec header onto the buffer
memcpy( &g_sec_gc[0], &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
fir_cnt = (ZFS_SEC_SIZE / sizeof(ZFS_FIR_t)) - 1 ;
// first extract the valid FIRs into the buffer
while( fir_cnt > 0 )
{
// get the valid FIR from TB.
pzfs_cfg->pfn_drv_read( pfir_ab_addr, &type_status, 1 ) ;
if( (~(type_status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY ) ) == ZFS_FIR_ALLOCATED )
{
// read the FIR from tb
pzfs_cfg->pfn_drv_read( pfir_ab_addr, ptr, sizeof(ZFS_FIR_t) );
ptr += sizeof( ZFS_FIR_t ) ;
}
pfir_ab_addr++ ;
fir_cnt-- ;
}
// now just check whether the power is failued during writing the sector header, if so, copy this and
// perform GC from this point onwards.
// now all valid FIR has been stored in the buffer, now check one by one and if difference is present, then
// perform GC from there.
// read from TB and check one by one
pzfs_cfg->pfn_drv_read( tb_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
if( memcmp( &g_sec_gc[0], &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) )
{
// if it is not equal, power is failed during this, just write the contents of buff to the flash
pzfs_cfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
// here onwards, only copy the sectors to sectors
CarrySubGC( pvol_info, num_of_sec, ab_sec_hdr, tb_sec_hdr ) ;
break ;
}
else
{
// it is equal, check with the rest of the FIR
pfir_tb_addr = (PZFS_FIR_t)((UINT8*)tb_sec_hdr + sizeof(ZFS_FIR_t)) ;
fir_cnt = (ZFS_SEC_SIZE / sizeof(ZFS_FIR_t)) - 1 ;
ptr = &g_sec_gc[0] + sizeof( ZFS_FIR_t ) ;
while( fir_cnt > 0 )
{
// read from TB
pzfs_cfg->pfn_drv_read( pfir_tb_addr, &fir_tb_hdr, sizeof( ZFS_FIR_t ) ) ;
if( memcmp( &fir_tb_hdr, ptr, sizeof(ZFS_FIR_t) ) )
{
// FIR copy is different, power failed here, just copy from this FIR.
pzfs_cfg->pfn_drv_write( pfir_tb_addr, ptr, sizeof(ZFS_FIR_t) );
// memcmp fails here, just copy all the FIR entries till fir_cnt == 0
pfir_tb_addr++ ;
ptr += sizeof( ZFS_FIR_t ) ;
fir_cnt-- ;
while( fir_cnt > 0 )
{
// read the FIR from ab
pzfs_cfg->pfn_drv_write( pfir_tb_addr, ptr, sizeof(ZFS_FIR_t) ) ;
pfir_tb_addr++;
ptr += sizeof( ZFS_FIR_t ) ;
fir_cnt-- ;
}
CarrySubGC( pvol_info, num_of_sec, ab_sec_hdr, tb_sec_hdr ) ;
// go to the end of this function
goto _end_power_fail_gc ;
}
fir_cnt--;
pfir_tb_addr++ ;
ptr += sizeof( ZFS_FIR_t ) ;
}
// if it comes here, then the comparison is successfull, just do not do any thing.
}
}
tb_sec_hdr = (PZFS_SEC_HDR_t ) (( UINT8*) tb_sec_hdr + ZFS_SEC_SIZE );
}
else
{
// sector is dirty or is not allocated, do not do any thing here
}
num_of_sec -- ;
ab_sec_hdr = (PZFS_SEC_HDR_t ) (( UINT8*) ab_sec_hdr + ZFS_SEC_SIZE );
}
_end_power_fail_gc:
// now just write the TB header with AB header.
ptb_blk_info->blk_hdr.tb_gc_end = ~ZFS_COMPLETED ;
ptb_blk_info->blk_hdr.sec_hdr.sec_type &= ~ZFS_SEC_TYPE_NEW_AB ;
// write the block header onto the TB.
pzfs_cfg->pfn_drv_write( ptb_blk_info->blk_start_addr, &ptb_blk_info->blk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
// now every thing is over, just erase the AB and make it as TB.
pzfs_cfg->pfn_drv_erase( pab_blk_info->blk_start_addr, blk_size) ;
pblk_hdr = &pab_blk_info->blk_hdr ;
ab_blk_num = pblk_hdr->blk_num ;
InitializeHeader( pblk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
pblk_hdr->sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
pblk_hdr->sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
pblk_hdr->sec_hdr.sec_data_bit = ~01 ;
pblk_hdr->blk_num = ab_blk_num ;
pab_blk_info->free_sec_count = 0 ;
pab_blk_info->next_free_sec_addr = ( UINT8 * ) NULL ;
pzfs_cfg->pfn_drv_write( pab_blk_info->blk_start_addr, pblk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
return ZFSERR_SUCCESS ;
}
void CorrectDuplicateFIREntry( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t pdir_sec_id, PZFS_FIR_t pdup_fir )
{
// read the contents of sec id
PZFS_SEC_HDR_t psec_hdr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, pdir_sec_id ) ;
PZFS_FIR_t pfir = (PZFS_FIR_t ) ((UINT8*)psec_hdr + sizeof( ZFS_FIR_t ) );
ZFS_FIR_t fir, orig_fir ;
ZFS_SEC_HDR_t sec_hdr ;
UINT firs_in_a_sec ;
// ZFS_SEC_ID_t orig_sec_id = pdir_sec_id ;
UINT8 fir_status ;
UINT16 sec_data_bit ;
UINT16 tmp_data_bit ;
pvol_info->pcfg->pfn_drv_read( pdup_fir, &orig_fir, sizeof( ZFS_FIR_t ) ) ;
while( pdir_sec_id != (( ZFS_SEC_ID_t ) FREE_SECTOR) )
{
pvol_info->pcfg->pfn_drv_read( ( (UINT8*)GetSecAddr( pvol_info, pdir_sec_id) + SEC_DATA_BIT_OFFSET), &sec_data_bit, 2 ) ;
sec_data_bit = ~sec_data_bit ;
tmp_data_bit = 0x0002 ;
firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
for( ; firs_in_a_sec > 0 ; firs_in_a_sec--, pfir++ )
{
// get the fir header
pvol_info->pcfg->pfn_drv_read( pfir, &fir_status, 1 ) ;
// now check whether the FIR is written properly or not, if not make this fir as dirty.
if( !(sec_data_bit & tmp_data_bit ) )
{
if( (fir_status != (UINT8)(~ZFS_FIR_FREE) ) )
{
fir_status &= ~ZFS_FIR_DIRTY ;
// write down the FIR onto the flash
pvol_info->pcfg->pfn_drv_write( pfir, &fir_status, 1 ) ;
}
}
else
{
// read the FIR,
pvol_info->pcfg->pfn_drv_read( pfir, &fir, sizeof( ZFS_FIR_t ) ) ;
// now check whether the FIR is of the same FIR as of duplicate or not.
if( ( ( fir.sec_datanum == orig_fir.sec_datanum ) || !memcmp( &fir.fir_name[0], &orig_fir.fir_name[0], ZFS_MAX_FILE_NAME_SIZE ) )
&& pfir != pdup_fir )
{
// things are equal, but check whether this is the FIR which need to be made as dirty, because
// if some files were just opened for write and then closed, which is not made for overwrite, and the
// sec_num is still 0xFFFFFF, we should check whether the dirty is started or not. If both dirty_Start and dirty_stop
// bits are not set or is set, then there is no problem, if dirty_start bit is set, but not dirty_stop bit, then we need to
// set this record as duplicate and make it as dirty.
// sector number is equal, just check whether this record is made as dirty
// this may not work if the file is just created and renamed to something else. ****
// ********** TBD ***** A BUG is here, just need to fix this. ****Mahadev
if( ((~fir_status) & (ZFS_FIR_DIRTY | ZFS_FIR_ALLOCATED ) ) == ZFS_FIR_ALLOCATED )
{
// this is the duplicate entry, just make this entry as invalid.
fir_status &= ~ZFS_FIR_DIRTY ;
pvol_info->pcfg->pfn_drv_write( pfir, &fir_status, 1 ) ;
// go to end.
goto _end_CorrectDuplicateFIREntry;
}
}
}
}
pvol_info->pcfg->pfn_drv_read( ( (UINT8*)GetSecAddr( pvol_info, pdir_sec_id)), &sec_hdr, sizeof(ZFS_SEC_HDR_t ) ) ;
pdir_sec_id = sec_hdr.nxtsecnum ;
pfir = (PZFS_FIR_t) ((UINT8*) GetSecAddr( pvol_info, pdir_sec_id ) + sizeof( ZFS_FIR_t ) ) ;
}
_end_CorrectDuplicateFIREntry:
// now the either duplicate entry is found or not found, if found it is already been made as dirty, now
// write ZFS_FIR_NOT_DUP to the given FIR.
orig_fir.fir_type_status &= ~ZFS_FIR_NOT_DUP ;
pvol_info->pcfg->pfn_drv_write( pdup_fir, &orig_fir.fir_type_status, 1 ) ;
return ;
}
void FindDuplicateFIREntry( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t pdir_sec_id )
{
// read the contents of sec id
PZFS_SEC_HDR_t psec_hdr = (PZFS_SEC_HDR_t) GetSecAddr( pvol_info, pdir_sec_id ) ;
PZFS_FIR_t pfir = (PZFS_FIR_t ) ((UINT8*)psec_hdr + sizeof( ZFS_FIR_t ) );
// ZFS_FIR_t fir ;
ZFS_SEC_HDR_t sec_hdr ;
UINT firs_in_a_sec ;
ZFS_SEC_ID_t orig_sec_id = pdir_sec_id ;
UINT8 fir_status ;
UINT16 sec_data_bit ;
UINT16 tmp_data_bit ;
if( pvol_info->pcfg->vol_type == ZFS_RAM_DEV_TYPE )
return ;
while( pdir_sec_id != ( ZFS_SEC_ID_t ) FREE_SECTOR )
{
pvol_info->pcfg->pfn_drv_read( ( (UINT8*)GetSecAddr( pvol_info, pdir_sec_id) + SEC_DATA_BIT_OFFSET), &sec_data_bit, 2 ) ;
sec_data_bit = ~sec_data_bit ;
tmp_data_bit = 0x0002 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -