⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zfssec.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 C
📖 第 1 页 / 共 2 页
字号:
	// 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 + -