📄 zfsinit.c
字号:
pblk_info->blk_start_addr = pblk_addr ;
sec_data_bit = ~(pblk_info->blk_hdr.sec_hdr.sec_data_bit );
sec_type = ~(pblk_info->blk_hdr.sec_hdr.sec_type ) ;
sec_status = ~(pblk_info->blk_hdr.sec_hdr.status ) ;
// now check whether the block is a valid block or not.
if( !( sec_data_bit & 0x01 ) ||
( pblk_info->blk_hdr.zfs_magic_num != ZFS_BLOCK_MAGIC_NUM ) ||
!( sec_status & ZFS_SEC_ALLOCATED ) ||
sec_type == ZFS_SEC_FREE )
{
// invalid block.
*ppinval_blk = pblk_info ;
continue ;
}
if( ( ( sec_type & ( ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB )) == (ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB) ) &&
( pblk_info->blk_hdr.tb_gc_start == 0xFE ) && ( pblk_info->blk_hdr.tb_gc_end != 0xFE ) )
{
*pptmp_tb_blk = pblk_info ;
}
// now it is a valid block, just assign different blocks.
if( ( sec_type & ( ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB )) == ZFS_SEC_TYPE_TB )
{
*pptb_blk = pblk_info ;
}
else if( ((( sec_type & ( ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB )) == ( ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB ) ) ||
( sec_type & ZFS_SEC_TYPE_AB ) == ZFS_SEC_TYPE_AB ) &&
( pblk_info->blk_hdr.ab_gc_start == 0xFE ) )
{
// allocation block that was chosen for GC.
*ppab_blk_gc_start = pblk_info ;
}
}
return ;
}
UINT8 IsRootDirPresent( PZFS_VOL_INFO_t pvol_info )
{
UINT secs_in_a_blk ;
PZFS_BLK_INFO_t pblk_info ;
PZFS_SEC_HDR_t psec_hdr ;
ZFS_SEC_HDR_t sec_hdr ;
UINT num_blks = pvol_info->pcfg->vol_blks ;
UINT idx ;
UINT32 blk_size ;
UINT cnt ;
UINT root_sec_cnt = 0 ;
// This function will search for sector id = 0 and valid sector. If found,
// returns ZFS_TRUE, else return ZFS_FALSE
// now read through the sectors present in this volume and update the SAT with values.
pblk_info = pvol_info->blk_info ;
blk_size = pvol_info->pcfg->vol_size /pvol_info->pcfg->vol_blks ;
secs_in_a_blk = blk_size / ZFS_SEC_SIZE ;
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
// for each block, get the status of each sectors and then update the SAT with the address and sector number
for( idx = 0 ; idx < num_blks ; idx++, pblk_info++ )
{
if( ((UINT8)(~((UINT8)pblk_info->blk_hdr.sec_hdr.sec_type)) & ( ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB )) == ( ZFS_SEC_TYPE_TB ) )
{
// it is an TB, just continue with next block
continue ;
}
// check for the sector for 0 id.
psec_hdr = (PZFS_SEC_HDR_t ) ((UINT8*)pblk_info->blk_start_addr + ZFS_SEC_SIZE );
for( cnt = 1 ; cnt < secs_in_a_blk ; cnt++ )
{
//read the sector header
pvol_info->pcfg->pfn_drv_read(psec_hdr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
// check whether the sector is a valid sector or not. If valid, check the sec_id and if it is 0, then return
// ZFS_TRUE. If not found, return ZFS_FALSE
if( (~(sec_hdr.sec_data_bit) & 0x01 ) &&
( ( ~sec_hdr.sec_type) & ZFS_SEC_TYPE_FIT ) &&
( ( (~sec_hdr.status ) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY ) ) == ZFS_SEC_ALLOCATED ) )
{
// valid sector, check for the sector id. If the sector id is 0, then return ZFS_TRUE
if( sec_hdr.sec_num == 0x00 )
root_sec_cnt++ ;
}
psec_hdr = ( PZFS_SEC_HDR_t ) ( (( UINT8 * ) psec_hdr) + ZFS_SEC_SIZE ) ;
}
}
}
else
{
//The second sector is the Root Dir
psec_hdr = (PZFS_SEC_HDR_t ) (((UINT8*)pvol_info->pcfg->vol_addr) + ZFS_SEC_SIZE);
pvol_info->pcfg->pfn_drv_read(psec_hdr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
if( (~(sec_hdr.sec_data_bit) & 0x01 ) && ( ( ~sec_hdr.sec_type) & ZFS_SEC_TYPE_FIT ) &&
( ( (~sec_hdr.status ) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY ) ) == ZFS_SEC_ALLOCATED ) )
root_sec_cnt = 1;
}
if( root_sec_cnt == 1 )
return ZFS_TRUE ;
else
return ZFS_FALSE ;
}
UINT8 GetBlkNum( PZFS_VOL_INFO_t pvol_info, PZFS_BLK_INFO_t pblk_info )
{
UINT8 idx ;
PZFS_BLK_INFO_t ptmp_blk_info ;
ptmp_blk_info = pvol_info->blk_info ;
for( idx = 0 ; ptmp_blk_info != pblk_info ; idx++, ptmp_blk_info++ ) ;
return idx ;
}
void SetVolParamsInvalid( PZFS_VOL_INFO_t pvol_info, PZFS_VOL_PARAMS_t pvol_params )
{
/*
* copy the volume name and set the is_valid bit to false.
*/
pvol_info->is_valid = ZFS_FALSE ;
pvol_params->is_valid = ZFS_FALSE ;
strcpy( ( INT8 * ) pvol_params->vol_name, ( const INT8 * ) pvol_info->pcfg->vol_name ) ;
return ;
}
//Function Name: ZFSInit
//Description: This API initializes the file system
ZFS_STATUS_t ZFSInit( PZFS_VOL_PARAMS_t pvol_params )
{
UINT preempt_status ;
UINT cnt ;
UINT vol_cnt ;
ZFS_SEC_HDR_t sec_hdr ;
UINT8 *blk_addr ;
UINT32 blk_size ;
UINT idx ;
UINT num_blks ;
UINT blk_info_offset = 0 ;
UINT sat_info_offset = 0 ;
UINT secs_in_a_blk ;
UINT num_dirty_secs ;
UINT num_free_secs ;
VOID *free_sec_addr ;
PZFS_SEC_HDR_t ab_sec_hdr ;
PZFS_FIR_t pfir_ab_addr ;
ZFS_FIR_t fir_ab_hdr ;
PZFS_BLK_INFO_t pblk_info ;
PZFS_DIR_LIST_t root_dir_node ;
PZFS_DIR_LIST_t new_dir_node ;
PZFS_DIR_LIST_t parent_dir_node ;
PZFS_SEC_HDR_t proot_sec_addr ;
PZFS_SEC_HDR_t pdir_sec_addr ;
UINT firs_in_a_sec ;
UINT len ;
ZFS_SEC_ID_t pdir_sec_id ;
PZFS_CONFIG_t pzfs_cfg ;
PZFS_VOL_INFO_t pvol_info ;
UINT8 **psat ; // for SAT address
UINT tmp_ab_cnt = 0, tmp_tb_cnt = 0, tmp_ib_cnt = 0;
PZFS_BLK_INFO_t pinval_blk, ptb_blk, pab_blk_gc_start, ptmp_tb_blk ;
UINT8 blk_num ;
if( IsZFSInited())
return ZFSERR_ALREADY_INITIALIZED ;
// store the maximum number of threads and max CWD path len.
g_max_threads = MAX_THREADS ;
g_max_cwd_len = nRzkMaxCwdPathLen ;
// make all arrays/data structures to zero.
memset( &g_zfs_or[0], 0x00, sizeof(ZFS_OPEN_REC_t) * g_max_or_entries ) ;
memset( &g_dir_list[0], 0x00, sizeof(ZFS_DIR_LIST_t) * g_max_dirs_supported ) ;
memset(&g_zfs_vol_info[0], 0x00, sizeof(ZFS_VOL_INFO_t)*g_max_volumes) ;
memset(&g_sec_gc[0], 0x00, ZFS_SEC_SIZE) ;
memset(&g_sec_data_write[0], 0x00, ZFS_SEC_SIZE);
memset(&g_blk_info[0], 0x00, sizeof(ZFS_BLK_INFO_t) * g_max_flash_blks) ;
memset(&g_zfs_sat[0], 0x00, g_max_flash_sectors) ;
// now ZFS is not initialized, just check for
preempt_status = DisablePreemption();
InitializeRTC( ) ;
// now loop through the configuration table and initialize appropriate volume.
pzfs_cfg = &g_zfs_cfg[0] ;
pvol_info = &g_zfs_vol_info[0] ;
blk_info_offset = 0 ;
sat_info_offset = 0 ;
for( vol_cnt = 0 ; vol_cnt < g_max_volumes ; vol_cnt++, pzfs_cfg++, pvol_info++ )
{
if( pzfs_cfg->vol_type == ZFS_RAM_DEV_TYPE )
{
pblk_info = &g_blk_info[blk_info_offset] ;
num_blks = pzfs_cfg->vol_blks ;
// this is RAM device type, just format the RAM device and update appropraite OR structures
pzfs_cfg->pfn_drv_init( ( void * ) pzfs_cfg->vol_addr, pzfs_cfg->vol_size );
if( g_byEraseFlash == 1 )
{
pzfs_cfg->pfn_drv_erase( ( void * ) pzfs_cfg->vol_addr, pzfs_cfg->vol_size ) ;
}
pblk_info = &g_blk_info[blk_info_offset] ;
pvol_info->pcfg = pzfs_cfg ;
pvol_info->pvol_sat = ( UINT8 * ) NULL ;
pvol_info->ttl_num_secs = pzfs_cfg->vol_secs ;
pvol_info->dirty_sec_count = 0 ;
pvol_info->free_sec_count = pzfs_cfg->vol_secs ;
pvol_info->blk_info = pblk_info ;
pblk_info->blk_start_addr = pzfs_cfg->vol_addr ;
pblk_info->dirty_sec_count = 0 ;
pblk_info->free_sec_count = pzfs_cfg->vol_secs ;
tmp_ab_cnt = 0;
GetBlkInfo( pzfs_cfg, pvol_info->blk_info, &tmp_ab_cnt, &tmp_tb_cnt, &tmp_ib_cnt ) ;
if( tmp_ab_cnt !=1 )
{
SetVolParamsInvalid( pvol_info, pvol_params ) ;
pvol_params++ ;
}
else
{
if( IsRootDirPresent( pvol_info ) == ZFS_FALSE )
{
SetVolParamsInvalid( pvol_info, pvol_params ) ;
pvol_params++ ;
}
else
{
pvol_info->is_valid = ZFS_TRUE ;
}
}
blk_info_offset++;
}
else if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE )
{
// FLASH
// Need to recover stuff from here.
// first check whether all block headers are there properly or not by checking the
// bit sec_hdr.sec_data_bit 0xFE)
// first get the count of blocks which do not have correct block header. If more than 1 block found with
// bit not set, then we will format disk procedure again.
blk_addr = (UINT8*) pzfs_cfg->vol_addr ;
blk_size = pzfs_cfg->vol_size / pzfs_cfg->vol_blks ;
num_blks = pzfs_cfg->vol_blks ;
pzfs_cfg->pfn_drv_init( ( UINT8*) blk_addr, blk_size ) ;
// only for testing - erasing the whole flash for the file system
////////////////////////////////
if( g_byEraseFlash == 1 )
{
for( idx = 0 ; idx < num_blks; idx++ )
{
pzfs_cfg->pfn_drv_erase( ( UINT8*) blk_addr, blk_size ) ;
blk_addr += blk_size ;
}
}
////////////////////////////////
idx = 0 ;
// update the vol_info table
pvol_info->blk_info = &g_blk_info[blk_info_offset] ;
pvol_info->pcfg = pzfs_cfg ;
pvol_info->proot_node = ( PZFS_DIR_LIST_t ) NULL ;
pvol_info->pvol_sat = (UINT8*)&g_zfs_sat[ sat_info_offset] ;
// Get the block information.
tmp_ab_cnt = tmp_tb_cnt = tmp_ib_cnt =0;
GetBlkInfo( pzfs_cfg, pvol_info->blk_info, &tmp_ab_cnt, &tmp_tb_cnt, &tmp_ib_cnt ) ;
if( tmp_tb_cnt > 1 || tmp_ib_cnt > 1 ) //|| tmp_ab_cnt == pvol_info->pcfg->vol_blks )
{
// If > 1 invalid blocks else
// if > 1 TB
// if AB = Total num of blocks
// power off during writing the block header. re-format the stuff and continue from next volume
SetVolParamsInvalid( pvol_info, pvol_params ) ;
pvol_params++ ;
/*
g_fmt_from_init = ZFS_TRUE ;
g_zfs_init = ZFS_TRUE ;
ZFSFormat(pzfs_cfg->vol_name, ZFS_FALSE ) ;
g_fmt_from_init = ZFS_FALSE ;
g_zfs_init = ZFS_FALSE ;
pvol_info->new_format_flag = ZFS_TRUE ;
*/
blk_info_offset += pvol_info->pcfg->vol_blks ;
sat_info_offset += pvol_info->pcfg->vol_secs ;
continue ;
}
// ib_cnt = 1 || 0
// tb_cnt = 1 || 0
// In this case, just get what is the IB address, TB address.
pinval_blk = GetInvalidBlk( pvol_info ) ;
// Get the TB.
ptb_blk = GetTBPtr( pvol_info ) ;
// Get various blocks, invalid block, tb block, ab block with GC_STARTED
GetDiffBlks( pvol_info, &pinval_blk, &ptb_blk, &pab_blk_gc_start, &ptmp_tb_blk ) ;
// now you have got the info, check for below conditions.
// If TB does not exist
if( ptb_blk == NULL )
{
// TB block does not exist,
// conditions
// 1. If GC is completed, TB header written as ZFS_SEC_TYPE_NEW_AB and power is failed.
if( ptmp_tb_blk != NULL && pab_blk_gc_start != NULL )
{
UINT8 gc_complete = 0xFE ;
// write down the gc_complete bit.
pzfs_cfg->pfn_drv_write( ptmp_tb_blk->blk_start_addr + BLK_TB_GC_START_OFFSET, &gc_complete, 1 ) ;
// so get the invalid block and erase the block and write the TB header.
pzfs_cfg->pfn_drv_erase( pab_blk_gc_start->blk_start_addr, blk_size) ;
// get the block number of pab_blk_gc_start.
blk_num = GetBlkNum( pvol_info, pab_blk_gc_start ) ;
InitializeHeader(&(pab_blk_gc_start->blk_hdr), sizeof( ZFS_BLK_HDR_t ) ) ;
pab_blk_gc_start->blk_hdr.zfs_magic_num = ZFS_BLOCK_MAGIC_NUM ;
pab_blk_gc_start->blk_hdr.sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
pab_blk_gc_start->blk_hdr.sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
pab_blk_gc_start->blk_hdr.blk_num = blk_num ;
// write the block header.
pzfs_cfg->pfn_drv_write( pab_blk_gc_start->blk_start_addr, &pab_blk_gc_start->blk_hdr, sizeof( ZFS_BLK_HDR_t ) ) ;
// write the bit
pab_blk_gc_start->blk_hdr.sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
pzfs_cfg->pfn_drv_write( ( UINT8 *) pab_blk_gc_start->blk_start_addr + SEC_DATA_BIT_OFFSET, &pab_blk_gc_start->blk_hdr.sec_hdr.sec_data_bit, 2 ) ;
pvol_info->is_valid = ZFS_TRUE ;
}
else
// 1. GC finished, but the AB is not erased. - erase the block and designate it as TB.
if( pab_blk_gc_start != NULL && pinval_blk == NULL )
{
// so get the invalid block and erase the block and write the TB header.
pzfs_cfg->pfn_drv_erase( pab_blk_gc_start->blk_start_addr, blk_size) ;
// get the block number of pab_blk_gc_start.
blk_num = GetBlkNum( pvol_info, pab_blk_gc_start ) ;
InitializeHeader(&(pab_blk_gc_start->blk_hdr), sizeof( ZFS_BLK_HDR_t ) ) ;
pab_blk_gc_start->blk_hdr.zfs_magic_num = ZFS_BLOCK_MAGIC_NUM ;
pab_blk_gc_start->blk_hdr.sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
pab_blk_gc_start->blk_hdr.sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
pab_blk_gc_start->blk_hdr.blk_num = blk_num ;
// write the block header.
pzfs_cfg->pfn_drv_write( pab_blk_gc_start->blk_start_addr, &pab_blk_gc_start->blk_hdr, sizeof( ZFS_BLK_HDR_t ) ) ;
// write the bit
pab_blk_gc_start->blk_hdr.sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
pzfs_cfg->pfn_drv_write( ( UINT8 *) pab_blk_gc_start->blk_start_addr + SEC_DATA_BIT_OFFSET, &pab_blk_gc_start->blk_hdr.sec_hdr.sec_data_bit, 2 ) ;
pvol_info->is_valid = ZFS_TRUE ;
}
else
// 2. GC finished, but the AB is erased or AB header is partly written - erase the block and designate it as TB.
if( tmp_ib_cnt == 1 && tmp_ab_cnt == (pvol_info->pcfg->vol_blks - 1))
{
// so get the invalid block and erase the block and write the TB header.
pzfs_cfg->pfn_drv_erase( pinval_blk->blk_start_addr, blk_size) ;
// get the block number of pab_blk_gc_start.
blk_num = GetBlkNum( pvol_info, pinval_blk ) ;
InitializeHeader(&(pinval_blk->blk_hdr), sizeof( ZFS_BLK_HDR_t ) ) ;
pinval_blk->blk_hdr.zfs_magic_num = ZFS_BLOCK_MAGIC_NUM ;
pinval_blk->blk_hdr.sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
pinval_blk->blk_hdr.sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
pinval_blk->blk_hdr.blk_num = blk_num ;
// write the block header.
pzfs_cfg->pfn_drv_write( pinval_blk->blk_start_addr, &pinval_blk->blk_hdr, sizeof( ZFS_BLK_HDR_t ) ) ;
// write the bit
pinval_blk->blk_hdr.sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
pzfs_cfg->pfn_drv_write( ( UINT8 *) pinval_blk->blk_start_addr + SEC_DATA_BIT_OFFSET, &pinval_blk->blk_hdr.sec_hdr.sec_data_bit, 2 ) ;
pvol_info->is_valid = ZFS_TRUE ;
}
else
{
// 2. AB block headers are written, but not the TB, - format.
/*
g_fmt_from_init = ZFS_TRUE ;
g_zfs_init = ZFS_TRUE ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -