📄 zfsinit.c
字号:
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 ;
*/
SetVolParamsInvalid( pvol_info, pvol_params ) ;
pvol_params++ ;
blk_info_offset += pvol_info->pcfg->vol_blks ;
sat_info_offset += pvol_info->pcfg->vol_secs ;
continue ;
}
}
else
{
// TB exist, check for below conditions.
// 2. Check whether the GC in progress or not.
// check for the gc_Start bit of TB.
if( (UINT8)(~ptb_blk->blk_hdr.tb_gc_start) == ZFS_STARTED )
{
// then check if the GC is not ended. If so, perform the GC again
if( (UINT8)(~ptb_blk->blk_hdr.tb_gc_end) != ZFS_COMPLETED )
{
// The GC is in progress, power failed. just get the alloc block and do the GC again,
if( ptb_blk->blk_hdr.gc_frmblk== 0xFF )
{
// power failed during writing these bits, so start the GC process again.
GC( pvol_info ) ;
}
else
{
#ifdef POWER_FAIL_SAFE
// GC was taking place, power failed. Get the AB that is used in GC and perform the
// GC from power fail.
PerFormGCFromPowerFail(
pvol_info,
&g_blk_info[ blk_info_offset + ptb_blk->blk_hdr.gc_frmblk],
ptb_blk ) ;
#endif // POWER_FAIL_SAFE
}
pvol_info->is_valid = ZFS_TRUE ;
}
}
else
// check whether the format is in progress or not. If in progress, erase the TB.
if( (UINT8)(~ptb_blk->blk_hdr.byfmt_start) == ZFS_STARTED )
{
g_fmt_from_init = ZFS_TRUE ;
g_zfs_init = ZFS_TRUE ;
ZFSFormat(pzfs_cfg->vol_name) ;
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 ;
}
else
// 1. AB does not exist, in GC, erase AB happened, or AB header is not written after gC completed, then just
// erase the AB and make it as TB.
if( pab_blk_gc_start != NULL )
{
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
// check whether the invalid block is present or not. If invalid block is present, then
// erase the block and write the block header. This will be a AB.
if( pinval_blk != NULL )
{
pzfs_cfg->pfn_drv_erase( pinval_blk->blk_start_addr, blk_size) ;
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 ;
}
}
// Try to check the root directory location. If root directory is not found throughout the
// volume, then re-format the disk.
if( IsRootDirPresent( pvol_info ) == ZFS_FALSE )
{
// reformat the disk here
/*
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 ;
*/
SetVolParamsInvalid( pvol_info, pvol_params ) ;
pvol_params++ ;
blk_info_offset += pvol_info->pcfg->vol_blks ;
sat_info_offset += pvol_info->pcfg->vol_secs ;
continue ;
}
else
pvol_info->is_valid = ZFS_TRUE ;
blk_info_offset += pvol_info->pcfg->vol_blks ;
sat_info_offset += pvol_info->pcfg->vol_secs ;
}
}
////////////////////////////////////////////////////////////////////////////////
// Evert thing related to recover is over, just scan each of the sector and if valid, write the address
// into the SAT. If invalid sectors are found, make them dirty.
// sat_info_offset = 0 ;
pzfs_cfg = &g_zfs_cfg[0];
pvol_info = &g_zfs_vol_info[0] ;
tmp_ib_cnt = 0 ;
for( vol_cnt = 0 ; vol_cnt < g_max_volumes ; vol_cnt++, pzfs_cfg++, pvol_info++ )
{
if( pvol_info->is_valid == ZFS_FALSE )
tmp_ib_cnt++ ;
// if the volume is formatted, then no need to build the tree
if( ( pvol_info->new_format_flag == ZFS_TRUE ) || ( pvol_info->is_valid == ZFS_FALSE ) )
continue ;
// now read through the sectors present in this volume and update the SAT with values.
// num_of_sec = pzfs_cfg->vol_secs ;
pblk_info = pvol_info->blk_info ;
ab_sec_hdr = ( PZFS_SEC_HDR_t) pzfs_cfg->vol_addr ;
blk_size = pzfs_cfg->vol_size /pzfs_cfg->vol_blks ;
psat = ( UINT8 ** ) pvol_info->pvol_sat ;
// 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) ((~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 ;
}
// not it is an AB, just traverse through the blocks and update the SAT
secs_in_a_blk = blk_size / ZFS_SEC_SIZE ;
ab_sec_hdr = (PZFS_SEC_HDR_t ) ((UINT8*)pblk_info->blk_start_addr + ZFS_SEC_SIZE );
num_dirty_secs = 0 ;
num_free_secs = 0 ;
free_sec_addr = ( void * ) -1 ;
for( cnt = 1 ; cnt < secs_in_a_blk ; cnt++ )
{
//read the sector header
pzfs_cfg->pfn_drv_read(ab_sec_hdr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Check the sec_hdr.sec_data_bit is set or not, if not set,
// probably hte power is failed when setting this bit but the sector was allocated. Just make
// this sector as dirty.
//////////////
if( !((UINT8)(~(sec_hdr.sec_data_bit)) & 0x01 ) &&
(((UINT8)(~sec_hdr.status ) != ZFS_SEC_FREE ) ||
((UINT8)(~sec_hdr.sec_type) != ZFS_SEC_FREE ) ) )
{
// the sector header may have been corrupted or half written or fully written
// but not the bit, means allocated but not linked to any sector or any FIR.
// make sector dirty
sec_hdr.status &= ~(ZFS_SEC_DIRTY | ZFS_SEC_ALLOCATED );
pzfs_cfg->pfn_drv_write(ab_sec_hdr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
num_dirty_secs++ ;
}
else
#endif // POWER_FAIL_SAFE
// BUG_FIX : 16_SEP
if( ( ( (UINT8)(~sec_hdr.status) & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) ) == (ZFS_SEC_DIRTY|ZFS_SEC_DUP) ) )
{
// TBD TBD
// if a duplicate sector is found, then do not store the address onto the SAT.
// Check this in CheckIntegrityOfFile function. In that function, it should search whole MEDIA and
// If the new sector is found, then probably the OVERWRITESECTOR operation is not completed, otherwise
// if not found, allocate a new sector and copy the data whatever present in the file
// LATEST is VALID
// Here we should search for the newly allocated sector. If it is found, probably this bit is not updated.
// So, make the the old sector as dirty after checking with whether the sector header is written properly with the bit.
// If not found, then the old sector is freed before allocating the new one, then put the old sector's address onto
// SAT. The checkIntegrityOfFile will check for this bit, and if found, then it will overwrite the old sector.
if( IsNewOverWrittenSectorExist( pvol_info, &sec_hdr, ab_sec_hdr ) == ZFS_FALSE )
{
// now update the old sector address into the SAT.
if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE)
*(psat + (UINT32)sec_hdr.sec_num ) = ( UINT8 *)ab_sec_hdr ;
}
}
else
// BUG_FIX : 16_SEP
if( ( ~sec_hdr.status & ZFS_SEC_DIRTY ) == ZFS_SEC_DIRTY )
{
// this is an dirty sector, move to next
num_dirty_secs++ ;
}
else if( (~sec_hdr.status & ZFS_SEC_ALLOCATED) == ZFS_SEC_ALLOCATED )
{
// valid sector. Just update the SAT with the address.
if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE)
*(psat + (UINT32)sec_hdr.sec_num ) = ( UINT8 *)ab_sec_hdr ;
}
else if( (UINT8)(~sec_hdr.status) == ZFS_SEC_FREE )
{
if( free_sec_addr == ( void * ) -1 )
{
free_sec_addr = ( VOID * ) ab_sec_hdr ;
}
num_free_secs++ ;
}
ab_sec_hdr = ( PZFS_SEC_HDR_t ) ( (( UINT8 * ) ab_sec_hdr) + ZFS_SEC_SIZE ) ;
}
pblk_info->dirty_sec_count = num_dirty_secs ;
pblk_info->free_sec_count = num_free_secs ;
pblk_info->next_free_sec_addr = ( UINT8 * ) free_sec_addr ;
}
// Now the SAT is built up, scan for root directory by reading the 0 sec_num. then scan each of the
// directory and the files present in the directory and fill up the dir_nodes.
/////////////////////////////////////////////////////////////////////////////////////
// Now perform the below:
// 1. recover the missing links
// 2. recover the duplicate of FIRs
// 3. recover the file size and file linked chains
// 4. recover the invalid sectors, invalid FIRs
// 5. build the directory structure in RAM.
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
proot_sec_addr = ( PZFS_SEC_HDR_t ) *((UINT8**) pvol_info->pvol_sat ) ;
else
proot_sec_addr = (PZFS_SEC_HDR_t ) (((UINT8*)pvol_info->pcfg->vol_addr) + ZFS_SEC_SIZE);
pdir_sec_addr = proot_sec_addr ;
pfir_ab_addr = (PZFS_FIR_t)((UINT8*)proot_sec_addr + sizeof( ZFS_FIR_t ) );
// allocate a dir node for root directory and update with root directory details.
root_dir_node = AllocDirNode() ;
if( root_dir_node == NULL )
{
// maximum dir count is reached,
EnablePreemption(preempt_status) ;
return ZFSERR_DIR_COUNT_LIMIT_REACHED ;
}
// copy the root directory details
strcpy((INT8 *)root_dir_node->dir_name, ( const INT8 *)pzfs_cfg->vol_name ) ;
if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE )
{
root_dir_node->sec_num = 0 ; // root directory will always have 0 sector
pdir_sec_id = 0 ; // root directory sector number
}
else
{
root_dir_node->sec_num = ((pzfs_cfg->vol_addr) +ZFS_SEC_SIZE);// For RAM the second sector is the Root dir node
pdir_sec_id = ((pzfs_cfg->vol_addr) +ZFS_SEC_SIZE); // root directory sector number
}
parent_dir_node = root_dir_node ;
firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
// this loop will traverse through the directory structure present on flash device and
// replicate it on the RAM.
while( parent_dir_node != NULL )
{
at_begin:
#ifdef POWER_FAIL_SAFE
FindDuplicateFIREntry( pvol_info, pdir_sec_id ) ;
#endif //POWER_FAIL_SAFE
while ( pdir_sec_id != (PZFS_SEC_HDR_t) FREE_SECTOR)
{
while( firs_in_a_sec > 0 )
{
// read the FIR
pzfs_cfg->pfn_drv_read(pfir_ab_addr, &fir_ab_hdr, sizeof(ZFS_FIR_t)) ;
// check if it is a directory
if( ( ~((UINT8)fir_ab_hdr.fir_type_status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY | ZFS_DIR_TYPE ) ) ==
( ZFS_FIR_ALLOCATED | ZFS_DIR_TYPE ) )
{
// it is a directory, just allocate a dir_node
new_dir_node = AllocDirNode() ;
if( new_dir_node == NULL )
{
// maximum dir count is reached,
EnablePreemption(preempt_status) ;
return ZFSERR_DIR_COUNT_LIMIT_REACHED ;
}
// get the length of the FIR name.
len = GetLenOfFDNameFromFIR( fir_ab_hdr.fir_name ) ;
memcpy( new_dir_node->dir_name, fir_ab_hdr.fir_name, len ) ;
new_dir_node->sec_num = fir_ab_hdr.sec_datanum ;
// point to the next FIR
parent_dir_node->tmp_fir_addr = (PZFS_FIR_t) pfir_ab_addr + 1 ;
parent_dir_node->tmp_sec_id = pdir_sec_id ;
// add the node to the list
AddSubDirNode( parent_dir_node, new_dir_node ) ;
parent_dir_node = new_dir_node ;
pdir_sec_id = fir_ab_hdr.sec_datanum ;
pdir_sec_addr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, pdir_sec_id ) ;
pfir_ab_addr = ((PZFS_FIR_t)pdir_sec_addr) + 1 ;
firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
goto at_begin ;
}
else if( ( (~fir_ab_hdr.fir_type_status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY | ZFS_FILE_TYPE ) ) ==
( ZFS_FIR_ALLOCATED | ZFS_FILE_TYPE ) )
{
// it is a file, just increase the fd_cnt
parent_dir_node->fd_cnt++ ;
#ifdef POWER_FAIL_SAFE
CheckIntegrityOfFile( pvol_info, parent_dir_node, pfir_ab_addr, &fir_ab_hdr ) ;
#endif //POWER_FAIL_SAFE
}
pfir_ab_addr ++ ;
firs_in_a_sec-- ;
}
firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
// read the sector header
pzfs_cfg->pfn_drv_read(GetSecAddr( pvol_info, pdir_sec_id ), &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
#ifdef POWER_FAIL_SAFE
CheckLinkChainOfSector( pvol_info, pdir_sec_id, &sec_hdr ) ;
#endif //POWER_FAIL_SAFE
pdir_sec_id = sec_hdr.nxtsecnum ;
pdir_sec_addr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, pdir_sec_id ) ;
pfir_ab_addr = (PZFS_FIR_t)(((PZFS_FIR_t) pdir_sec_addr) + 1 );
}
// here for one directory is over. If it comes here it means that all the FIR's in the current FIT
// is read, so need to read rest of the FIR's in parent directories FIT from the point where it
// stopped
parent_dir_node = parent_dir_node->up_list ;
pdir_sec_addr = (PZFS_SEC_HDR_t) (( (UINT32) parent_dir_node->tmp_fir_addr ) - ( ((UINT32) parent_dir_node->tmp_fir_addr % ZFS_SEC_SIZE))) ;
firs_in_a_sec = ( ZFS_SEC_SIZE - ( (UINT32) parent_dir_node->tmp_fir_addr % ZFS_SEC_SIZE )) / sizeof(ZFS_FIR_t) ;
pfir_ab_addr = ( PZFS_FIR_t ) parent_dir_node->tmp_fir_addr ;
pdir_sec_id = parent_dir_node->tmp_sec_id ;
}
// now update the vol_info table
pvol_info->proot_node = root_dir_node ;
pvol_info->root_sec_num = 0 ;
}
// Here every thing is done, return SUCCESS to the caller
g_zfs_init = ZFS_TRUE ;
hSem_FS = RZKCreateSemaphore((RZK_NAME_t *)"hSem_FS",1,RECV_ORDER_PRIORITY);
if(hSem_FS == NULL)
printf("\nFS Semaphore creation error");
EnablePreemption(preempt_status) ;
return tmp_ib_cnt ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -