📄 zfssec.c
字号:
/*
* File : ZFSSec.c
* Description: This file contains the implementations of the required sector related
* operations.
* 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
*/
/*
* Revision History
*
* CR 6245, MKC
* The sector after deleted was not filled up with 0xFFs causing invalid length
* of the file.
*
* CR 6500, MK on 3-OCT-2005
* While erasing the flash incase of RAM file system, the sector header information also
* was made FF, which was erasing the first sector only when delete is called as the
* rest of the sectors information is lost from the header of the first sector.
* Now it is corrected to erase only the data portion, not the sector header.
* The status of each header is made ZFS_SEC_FREE.
*/
#include "glextern.h"
extern ZFS_STATUS_t GC( PZFS_VOL_INFO_t pvol_info ) ;
extern UINT8 GetTimeData( UINT32 *date_time, UINT8 *time_century ) ;
extern PZFS_SEC_HDR_t FindDupSector( PZFS_VOL_INFO_t pvol_info, PZFS_SEC_HDR_t pold_sec_hdr ) ;
//Function definitions
//Function: GetBlkWithFreeSector
//Description: This function will return the block which has free sector (Valid only in FLASH)
PZFS_BLK_INFO_t GetBlkWithFreeSector( PZFS_VOL_INFO_t pvol_info )
{
UINT blk_num = pvol_info->pcfg->vol_blks ;
PZFS_BLK_INFO_t pblk ;
UINT cnt = 0 ;
pblk = pvol_info->blk_info ;
for( cnt = 0 ; cnt < blk_num; cnt++)
{
if( ( pblk->free_sec_count > 0 ) &&
(~(pblk->blk_hdr.sec_hdr.sec_type) & ( ZFS_SEC_TYPE_AB | ZFS_SEC_TYPE_NEW_AB ) ) )
{
return pblk ;
}
pblk++ ;
}
return ( PZFS_BLK_INFO_t ) NULL ;
}
//Function Name: AllocSector
//Description: This function will search for a free sector and allocates it
ZFS_SEC_ID_t AllocSector( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t sec_num, UINT8 sec_type )
{
PZFS_BLK_INFO_t pblk_free ;
ZFS_SEC_ID_t free_sec_addr ;
ZFS_SEC_ID_t free_sec_id ;
ZFS_SEC_HDR_t sec_hdr ;
UINT8 **sat_start_addr ;
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
// first get the block where more number of sectors are free.
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 )
{
// call GC
if ( GC( pvol_info ) != ZFSERR_SUCCESS )
{
// some problem exists
return NULL ;
}
else
{
// get the block with free sectors
// first get the block where more number of sectors are free.
pblk_free = GetBlkWithFreeSector( pvol_info ) ;
}
}
else
{
// disk is full return error.
return NULL ;
}
}
// just get the next free sec addr from blk_info structure.
free_sec_addr = pblk_free->next_free_sec_addr ;
if( sec_num == NULL )
free_sec_id = GetNewSecNum( pvol_info ) ;
else
free_sec_id = sec_num ;
// write the sector header as allocated.
InitializeHeader( &sec_hdr, sizeof( ZFS_SEC_HDR_t ) );
sec_hdr.sec_type = ~sec_type ;
sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
sec_hdr.sec_num = free_sec_id ;
pvol_info->pcfg->pfn_drv_write( free_sec_addr, &sec_hdr, sizeof(sec_hdr)) ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
pvol_info->pcfg->pfn_drv_write( ((UINT8*)free_sec_addr+SEC_DATA_BIT_OFFSET), &sec_hdr.sec_data_bit, 2) ;
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
#endif
// update the SAT.
sat_start_addr = (UINT8**) pvol_info->pvol_sat ;
*(sat_start_addr + (UINT32)free_sec_id ) = ( UINT8 * ) free_sec_addr ;
//pvol_info->pvol_sat[ free_sec_id ] = free_sec_addr ;
// update the blk_info
pblk_free->next_free_sec_addr = (UINT8*) free_sec_addr + ZFS_SEC_SIZE ;
pblk_free->free_sec_count -- ;
}
else
{
// for RAM type,
// first get the free sector by checking through memory locations
free_sec_addr = GetFreeSector( pvol_info ) ;
if( free_sec_addr == NULL )
{
// media is full,
return NULL ;
}
InitializeHeader( &sec_hdr, sizeof( ZFS_SEC_HDR_t) ) ;
// write the sector header
sec_hdr.sec_type = ~sec_type ;
sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
sec_hdr.sec_num = free_sec_addr ;
pvol_info->pcfg->pfn_drv_write( free_sec_addr, &sec_hdr, sizeof(sec_hdr)) ;
#ifdef POWER_FAIL_SAFE
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
pvol_info->pcfg->pfn_drv_write( ((UINT8*)free_sec_addr+SEC_DATA_BIT_OFFSET), &sec_hdr.sec_data_bit, 2) ;
// POWER_FAIL_SAFE: Here just update the sec_hdr.sec_data_bit for this sector header.
//////////
#endif
// update the blk_info
pvol_info->blk_info->free_sec_count -- ;
pvol_info->free_sec_count -- ;
free_sec_id = free_sec_addr ;
}
return free_sec_id ;
}
//Function Name: GetFreeSector
//Description: This function will return the free sector's address (this requires searching of whole volume for a free sector
// or some kind of RAM variables or RAM tables)
// Valid for RAM
ZFS_SEC_ID_t GetFreeSector( PZFS_VOL_INFO_t pvol_info )
{
PZFS_SEC_HDR_t pstart_addr, pend_addr ;
PZFS_SEC_HDR_t psec_hdr ;
UINT8 free_sec ;
if( pvol_info->pcfg->vol_type == ZFS_RAM_DEV_TYPE )
{
pstart_addr = ( PZFS_SEC_HDR_t) pvol_info->pcfg->vol_addr ;
pend_addr = (PZFS_SEC_HDR_t) ((UINT8*)pstart_addr + pvol_info->pcfg->vol_size) ;
psec_hdr = pstart_addr ;
while( psec_hdr != pend_addr )
{
pvol_info->pcfg->pfn_drv_read( ((UINT8*)psec_hdr + 1), &free_sec, 1 ) ;
if( (UINT8)( free_sec & (UINT8)(~ZFS_SEC_FREE) ) == (UINT8)(~ZFS_SEC_FREE) )
return psec_hdr ;
psec_hdr = ( PZFS_SEC_HDR_t ) (((UINT8*)psec_hdr) + ZFS_SEC_SIZE) ;
}
}
return NULL ;
}
//Function Name: GetNewSecNum
//Description: This function will search through the SAT table to find a new sector num
ZFS_SEC_ID_t GetNewSecNum( PZFS_VOL_INFO_t pvol_info )
{
UINT cnt =0 ;
UINT max_sec ;
void **ppvoid ;
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
max_sec = pvol_info->pcfg->vol_secs ;
ppvoid = ( void ** ) pvol_info->pvol_sat ;
while( max_sec != 0 )
{
// if( ( void * ) pvol_info->pvol_sat[ cnt ] == NULL )
if( *ppvoid == NULL )
return ( void *) cnt ;
ppvoid ++ ;
cnt++ ;
max_sec-- ;
}
}
return NULL;
}
//Function Name: FreeSector
//Description: This function will free the sector pointed by sector number and its linked sectors
UINT8 FreeSector( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t sec_num )
{
UINT8 *sec_addr ;
UINT8* blk_addr ;
UINT32 blk_size ;
// UINT blk_num ;
ZFS_SEC_HDR_t sec_hdr ;
PZFS_BLK_INFO_t pcur_blk_info ;
VOID **ppsat ;
blk_size = pvol_info->pcfg->vol_size / pvol_info->pcfg->vol_blks ;
sec_addr = GetSecAddr( pvol_info, sec_num) ;
blk_addr = (sec_addr - ((( UINT32 )sec_addr) % blk_size ) ) ;
// blk_num = blk_addr / blk_size ;
ppsat = ( VOID ** ) pvol_info->pvol_sat ;
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
// now find the pointer to the blk_info structure
for( pcur_blk_info = pvol_info->blk_info;
pcur_blk_info->blk_start_addr != blk_addr ; pcur_blk_info++) ;
// read the sector header.
pvol_info->pcfg->pfn_drv_read( sec_addr, &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
sec_hdr.status &= ~ZFS_SEC_DIRTY ;
// write the sector header.
pvol_info->pcfg->pfn_drv_write( ((UINT8*)sec_addr)+1, ((UINT8 *) &sec_hdr)+1, 1 ) ;
// update the number of sectors present in this block
pcur_blk_info->dirty_sec_count ++ ;
pvol_info->dirty_sec_count ++ ;
*(ppsat + (UINT32)sec_num ) = NULL ;
}
else
{
pcur_blk_info = pvol_info->blk_info ;
// CR 6245, MKC
//pvol_info->pcfg->pfn_drv_erase( sec_addr, ZFS_SEC_SIZE ) ;
// CR 6500, MK, 3-OCT-2005, the parameters are corrected
pvol_info->pcfg->pfn_drv_erase( sec_addr+sizeof(ZFS_SEC_HDR_t), ZFS_SEC_SIZE -sizeof(ZFS_SEC_HDR_t)) ;
// CR 6500, MK on 3-OCT-2005, Status is made FREE
*(sec_addr+1) = ~ZFS_SEC_FREE;
// if device is RAM type
// pvol_info->pcfg->pfn_drv_read( sec_addr, &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
// sec_hdr.status = ~ZFS_SEC_FREE;
// write the sector header.
// pvol_info->pcfg->pfn_drv_write( ((UINT8*)sec_addr)+1, ((UINT8 *) &sec_hdr)+1, 1 ) ;
pcur_blk_info->free_sec_count ++ ;
pvol_info->free_sec_count ++ ;
}
return ZFS_TRUE ;
}
//Function Name: AllocFIR
//Description: This function will allocate an FIR from the FIT
PZFS_FIR_t AllocFIR( PZFS_VOL_INFO_t pvol_info, PZFS_FIT_HDR_t pfit_hdr )
{
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 ;
ZFS_SEC_ID_t new_sec_id ;
ZFS_SEC_ID_t prev_sec_id ;
UINT8 fir_alloc = ~ZFS_FIR_ALLOCATED ;
// get which sector does current pfir belongs to.
pfit_sec = ( PZFS_FIT_HDR_t ) pfit_hdr ;//GetSecAddr(pvol_info, (ZFS_SEC_ID_t) pfit_hdr ) ;
prev_sec_id = (ZFS_SEC_ID_t ) pfit_sec ;
fir_addr = ( PZFS_FIR_t) GetSecAddr(pvol_info, (ZFS_SEC_ID_t) pfit_hdr ) + 1 ;
num_firs_in_sec = ( ZFS_SEC_DATA_SIZE / sizeof( ZFS_FIR_t ) ) ;
while( pfit_sec != ( PZFS_FIT_HDR_t ) FREE_SECTOR )
{
// read the FIR.
pvol_info->pcfg->pfn_drv_read( fir_addr, &fir_hdr, 1) ;
// check whether it is a valid fir or not. If not just continue from the beginning.
if( ( (fir_hdr.fir_type_status) & (~ZFS_FIR_FREE)) == (UINT8)(~ZFS_FIR_FREE) )
{
// allocate it.
// fir_hdr.fir_type_status &= ~(ZFS_FIR_ALLOCATED) ;
// write to the media
pvol_info->pcfg->pfn_drv_write( fir_addr, &fir_alloc, 1) ;
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
// pfit_sec = ( PZFS_FIT_HDR_t ) GetSecAddr( pvol_info, pfit_sec->sec_hdr.nxtsecnum ) ;
pvol_info->pcfg->pfn_drv_read( GetSecAddr(pvol_info, pfit_sec), &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
prev_sec_id = pfit_sec ;
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 ) ) ;
}
}
// if it comes here, it means that current FIT is full, need to allocate a new FIT and link it to the older one.
new_sec_id = AllocSector(pvol_info, 0, ZFS_SEC_TYPE_FIT) ;
if( new_sec_id == 0 )
{
// data media is full,
return ( PZFS_FIR_t ) NULL ;
}
LinkSector( pvol_info, prev_sec_id, new_sec_id) ;
InitializeHeader( &fir_hdr, sizeof( ZFS_FIR_t ) ) ;
fir_hdr.fir_type_status &= ~(ZFS_FIR_ALLOCATED) ;
fir_addr = (PZFS_FIR_t) GetSecAddr( pvol_info, new_sec_id) + 1 ;
pvol_info->pcfg->pfn_drv_write( fir_addr, &fir_hdr, 1) ;
return fir_addr ;
}
//Function Name: FreeFIR
//Description: This function will free the FIR pointing to it.
UINT8 FreeFIR( PZFS_VOL_INFO_t pvol_info, PZFS_FIR_t pfir )
{
// UINT num_bytes_read ;
UINT8 fir_status ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -