📄 zfssec.c
字号:
// read the FIR status byte from device.
pvol_info->pcfg->pfn_drv_read( pfir, &fir_status, 1 ) ;
// check if FIR is valid and then made it as dirty
if( !(~(fir_status) & ZFS_FIR_ALLOCATED ) )
{
return ZFS_FALSE ;
}
if( pvol_info->pcfg->vol_type == ZFS_RAM_DEV_TYPE )
fir_status = ~(ZFS_FIR_FREE) ;
else
{
fir_status &= ~(ZFS_FIR_DIRTY) ;
}
// write the byte onto the device.
// read the FIR status byte from device.
pvol_info->pcfg->pfn_drv_write( (UINT8*)pfir, &fir_status, 1 ) ;
return ZFS_TRUE ;
}
//Function Name: SearchFIR
//Description: This function will search through the FIT for particular file/director name
PZFS_FIR_t SearchFIR( PZFS_VOL_INFO_t pvol_info, PZFS_FIT_HDR_t fit_sec_num, INT8 *fd_name, UINT len )
{
UINT num_firs_in_sec ;
PZFS_FIR_t fir_addr ;
ZFS_FIR_t fir_hdr ;
ZFS_SEC_HDR_t sec_hdr ;
PZFS_FIT_HDR_t pfit_sec ;
// PZFS_FIR_t pfir ;
UINT8 bcomp ;
// UINT fd_len ;
// get which sector does current pfir belongs to.
pfit_sec = ( PZFS_FIT_HDR_t) fit_sec_num ;
fir_addr = (PZFS_FIR_t) GetSecAddr( pvol_info, (ZFS_SEC_ID_t) fit_sec_num ) + 1 ;
num_firs_in_sec = ( ZFS_SEC_DATA_SIZE / sizeof( ZFS_FIR_t ) ) ;
while( pfit_sec != ( PZFS_FIT_HDR_t ) FREE_SECTOR )
{
bcomp = ZFS_FALSE ;
// read the FIR.
pvol_info->pcfg->pfn_drv_read( fir_addr, &fir_hdr, sizeof(ZFS_FIR_t)) ;
// check whether it is a valid fir or not. If not just continue from the beginning.
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
if( !( ~((UINT8)fir_hdr.fir_type_status) & ZFS_FIR_DIRTY ) )
{
// if it is not dirty, check whether the FIR is FREE or allocated.
if( ~((UINT8)fir_hdr.fir_type_status) & ZFS_FIR_ALLOCATED )
{
bcomp = ZFS_TRUE ;
}
}
}
else
{
if( ( ~fir_hdr.fir_type_status & ( ZFS_FIR_ALLOCATED ) == ZFS_FIR_ALLOCATED ) )
{
bcomp = ZFS_TRUE ;
}
}
if( bcomp == ZFS_TRUE )
{
// now compare the filename present in FIR with file name given, and if equal return the
// address of fir.
if( len == GetLenOfFDNameFromFIR( fir_hdr.fir_name ) )
{
if( memcmp( ( const void * ) fir_hdr.fir_name, fd_name, len ) == 0 )
{
return fir_addr ;
}
}
}
num_firs_in_sec -- ;
fir_addr++;
if( num_firs_in_sec == 0 )
{
// store the new address into it.
// read the fit header
pvol_info->pcfg->pfn_drv_read( GetSecAddr( pvol_info, pfit_sec), &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
// pfit_sec = ( PZFS_FIT_HDR_t ) GetSecAddr( pvol_info, fit_hdr.sec_hdr.nxtsecnum ) ;
pfit_sec = ( PZFS_FIT_HDR_t ) sec_hdr.nxtsecnum ;
fir_addr = ( PZFS_FIR_t) GetSecAddr( pvol_info, pfit_sec ) + 1 ;
num_firs_in_sec = ( ZFS_SEC_DATA_SIZE / sizeof( ZFS_FIR_t ) ) ;
}
}
return ( PZFS_FIR_t ) NULL ;
}
//Function Name: WriteFIR
//Description: This function will write the FIR contents at the FIR address for the given volume.
void WriteFIR( PZFS_VOL_INFO_t pvol_info, PZFS_FIR_t pfir, PZFS_FIR_t new_fir_data )
{
// Get the time and data
if( GetTimeData( &(new_fir_data->tom), &(new_fir_data->tom_century) ) != ZFSERR_SUCCESS )
{
// do not do anything here, just write the old date and time.
}
pvol_info->pcfg->pfn_drv_write( pfir, new_fir_data, sizeof( ZFS_FIR_t ) ) ;
#ifdef POWER_FAIL_SAFE
{
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
UINT32 blk_size = pvol_info->pcfg->vol_size / pvol_info->pcfg->vol_blks ;
UINT32 umod = (UINT)((UINT8*)pfir - (UINT8*)pvol_info->pcfg->vol_addr ) ;
UINT i ;
UINT32 j ;
void * pfit ;
UINT16 sec_data_bit = 0x01 ;
UINT16 read_data_bit ;
umod = umod % blk_size ;
umod = umod % ZFS_SEC_SIZE ;
j = umod ;
umod = umod / sizeof( ZFS_FIR_t ) ;
pfit = ( void * ) ((UINT8*)pfir - j + SEC_DATA_BIT_OFFSET) ;
// loop through till we get the fir_cnt
for( i = 0 ; i < umod ; i++ )
sec_data_bit <<= 1 ;
// read the data.
pvol_info->pcfg->pfn_drv_read( pfit, &read_data_bit, 2) ;
read_data_bit &= ~sec_data_bit ;
pvol_info->pcfg->pfn_drv_write( pfit, &read_data_bit, 2) ;
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
}
#endif
}
//Function Name: OverWriteFIR
//Description: This function will free up the previous FIR and allocates a new FIR in case of
// Flash and in case of RAM, just overwrites into appropriate RAM location. returns address
// of new FIR allocated
PZFS_FIR_t OverWriteFIR( PZFS_VOL_INFO_t pvol_info, PZFS_FIT_HDR_t pfit, PZFS_FIR_t pfir, PZFS_FIR_t new_fir_data )
{
PZFS_FIR_t pnew_fir ;
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
// allocate a FIR first.
pnew_fir = AllocFIR( pvol_info, pfit ) ;
if( pnew_fir == NULL )
return ( PZFS_FIR_t ) NULL ;
// FIR has been allocated, just write its contents with new_fir_data
new_fir_data->fir_type_status &= ~ZFS_FIR_ALLOCATED ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Now the original record is destroyed, write NOT_DUP in the
// current fir.
//////////////
new_fir_data->fir_type_status &= ~ZFS_FIR_DUP ;
// POWER_FAIL_SAFE:
//////////////
#endif //POWER_FAIL_SAFE
// pvol_info->pcfg->pfn_drv_write( pnew_fir, new_fir_data, sizeof( ZFS_FIR_t) );
WriteFIR( pvol_info, pnew_fir, new_fir_data ) ;
// make old fir as dirty
FreeFIR(pvol_info, pfir ) ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Now the original record is destroyed, write NOT_DUP in the
// current fir.
//////////////
new_fir_data->fir_type_status &= ~ZFS_FIR_NOT_DUP ;
// write to the flash
pvol_info->pcfg->pfn_drv_write( pnew_fir, &new_fir_data->fir_type_status, 1 ) ;
// POWER_FAIL_SAFE:
//////////////
#endif //POWER_FAIL_SAFE
}
else
{
pnew_fir = pfir ;
// FIR has been allocated, just write its contents with new_fir_data
new_fir_data->fir_type_status &= ~ZFS_FIR_ALLOCATED ;
// pvol_info->pcfg->pfn_drv_write( pnew_fir, new_fir_data, sizeof( ZFS_FIR_t) );
WriteFIR( pvol_info, pnew_fir, new_fir_data ) ;
}
return pnew_fir ;
}
//Function Name: OverWriteSector
//Description: This function will free the previous sector and allocates a new sector and returns the
// sector id of the newly allocated sector to the caller
// Only for Flash
ZFS_SEC_ID_t OverWriteSector( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t cur_sec_id, UINT8 sec_type )
{
ZFS_SEC_ID_t new_sec_id ;
UINT8 sec_status ;
UINT8 *old_sec_addr = GetSecAddr( pvol_info, cur_sec_id ) ;
ZFS_SEC_HDR_t old_sec_hdr, new_sec_hdr, old_sec_hdr_gc ;
PZFS_BLK_INFO_t pblk_free ;
UINT8 *nxt_sec_addr ;
// TBD TBD POWER FAILURE CONDITION
// During overwriting of the sectors, if power failure happens, then
// whole volume should be searched for the duplicate sector. If
// duplicate sector is found, that need to be handled.
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Write SEC_DUP in the newly allocated sector
//////////////
pblk_free = GetBlkWithFreeSector( pvol_info ) ;
if( pblk_free == NULL )
{
// now all blocks are full, need to check if any dirty sectors are present
if( IsDirtySectorsPresent( pvol_info ) == ZFS_TRUE )
{
pvol_info->pcfg->pfn_drv_read( old_sec_addr, &old_sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
old_sec_hdr.status &= ~ZFS_SEC_DUP ;
pvol_info->pcfg->pfn_drv_write( old_sec_addr + 1, &old_sec_hdr.status, 1 ) ;
}
else
return NULL ;
}
else
{
pvol_info->pcfg->pfn_drv_read( old_sec_addr, &old_sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
old_sec_hdr.status &= ~ZFS_SEC_DUP ;
pvol_info->pcfg->pfn_drv_write( old_sec_addr + 1, &old_sec_hdr.status, 1 ) ;
}
// POWER_FAIL_SAFE:
//////////////
#endif //POWER_FAIL_SAFE
// POWER FAILURE CONDITIONS
// after freeing the old sector, before allocating the new sector, power fails... the INIT should retrieve the old sector.
// after freeing the old sector, in process of allocation, GC happens, then what need to be done is that the old sector
// should not be made dirty. After GC is completed, then search for the valid sector with the DUP bit is set. This
// is the old sector. Once the write is completed, delete the previous sector.
// Free the sector
FreeSector( pvol_info, cur_sec_id ) ;
// allocate a new sector and free the old sector.
new_sec_id = AllocSector( pvol_info, cur_sec_id, sec_type ) ;
if( new_sec_id != NULL )
{
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Write SEC_DUP in the newly allocated sector
//////////////
// write the old sector headers field.
nxt_sec_addr = GetSecAddr( pvol_info, new_sec_id ) ;
pvol_info->pcfg->pfn_drv_read( nxt_sec_addr , &new_sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
// read the old_sec_hdr with the new address. If this sector is relocated to a new address during
// GC operation, then we have to search where the old sector exists in the volume.
pvol_info->pcfg->pfn_drv_read( old_sec_addr , &old_sec_hdr_gc, sizeof( ZFS_SEC_HDR_t ) ) ;
old_sec_hdr.status &= ~ZFS_SEC_DIRTY ;
if( memcmp( &old_sec_hdr_gc, &old_sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) != 0 )
{
// the sector is moved to some other location, just find out where it is moved.
old_sec_addr = ( UINT8 * ) FindDupSector( pvol_info, &old_sec_hdr ) ;
}
new_sec_hdr.nxtsecnum = old_sec_hdr.nxtsecnum;
new_sec_hdr.nxt_sec_data_bit = old_sec_hdr.nxt_sec_data_bit ;
pvol_info->pcfg->pfn_drv_write( nxt_sec_addr, &new_sec_hdr, sizeof(ZFS_SEC_HDR_t ) ) ;
// make the old sector is no more duplicate
pvol_info->pcfg->pfn_drv_read( old_sec_addr + 1, &sec_status, 1 ) ;
sec_status &= ~ZFS_SEC_NO_DUP ;
pvol_info->pcfg->pfn_drv_write( old_sec_addr + 1, &sec_status, 1 ) ;
// POWER_FAIL_SAFE:
//////////////
#endif //POWER_FAIL_SAFE
}
return new_sec_id ;
}
//Function Name: LinkSector
//Description: This function will link the old and new sectors
void LinkSector( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t old_sec_id, ZFS_SEC_ID_t new_sec_id )
{
// ZFS_SEC_HDR_t old_sec_hdr ; //, new_sec_hdr ;
UINT8 *old_sec_addr = GetSecAddr( pvol_info, old_sec_id ) ;
UINT8 nxt_sec_data_bit ;
// read the old sector header
// pvol_info->pcfg->pfn_drv_read( old_sec_addr, &old_sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Write the sec_hdr.nxt_sec_data_bit is set if the next sector is linked.
//////////
nxt_sec_data_bit = ~ZFS_SEC_LINK_START ;
pvol_info->pcfg->pfn_drv_write( (old_sec_addr+SEC_DATA_BIT_OFFSET+2), &nxt_sec_data_bit, 1) ;
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
#endif
// old_sec_hdr.nxtsecnum = new_sec_id ;
pvol_info->pcfg->pfn_drv_write( old_sec_addr + SEC_NXT_SEC_NUM_OFFSET, &new_sec_id, sizeof( ZFS_SEC_ID_t )) ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Write the sec_hdr.nxt_sec_data_bit is set if the next sector is linked.
//////////
nxt_sec_data_bit = ~(ZFS_SEC_LINK_END | ZFS_SEC_LINK_START );
pvol_info->pcfg->pfn_drv_write( (old_sec_addr+SEC_DATA_BIT_OFFSET+2), &nxt_sec_data_bit, 1) ;
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
#endif
// POWER_FAIL_SAFE: Write the sec_hdr.nxt_sec_data_bit is set if the next sector is linked.
//////////////
//////////////
return ;
}
UINT8 * GetSecAddr( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t sec_id )
{
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
// get the address from SAT.
void **ptr ;
ptr = (void**) pvol_info->pvol_sat ;
return ( (UINT8*) *(ptr + (UINT32) sec_id ) ) ;
}
else
{
return ( UINT8*) sec_id ;
}
}
ZFS_STATUS_t IsDirtySectorsPresent( PZFS_VOL_INFO_t pvol_info )
{
UINT num_blks = pvol_info->pcfg->vol_blks ;
PZFS_BLK_INFO_t pblk = pvol_info->blk_info ;
while( num_blks > 0 )
{
if( ( pblk->dirty_sec_count > 0 ) &&
(~((UINT8)pblk->blk_hdr.sec_hdr.sec_type) & ((UINT8)( ZFS_SEC_TYPE_AB | ZFS_SEC_TYPE_NEW_AB) ) ) )
{
return ZFS_TRUE ;
}
pblk++;
num_blks--;
}
return ZFS_FALSE ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -