📄 zfsgc.c
字号:
/*
* File : ZFSGc.c
* Description: This file contains the implementation of garbage collection
* 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
*/
#include "glextern.h"
UINT8 g_sec_gc[ ZFS_SEC_SIZE ] ;
//Function Name: GC
//Description: This API implements the GC
ZFS_STATUS_t GC( PZFS_VOL_INFO_t pvol_info )
{
ZFS_BLK_HDR_t blk_hdr ;
PZFS_BLK_INFO_t tb_blk ;
PZFS_BLK_INFO_t ab_blk ;
PZFS_SEC_HDR_t tb_sec_hdr ;
PZFS_SEC_HDR_t ab_sec_hdr ;
UINT16 num_valid_secs = 0 ;
PZFS_FIR_t pfir_addr ;
ZFS_FIR_t fir_hdr ;
UINT or_cnt = 0 ;
UINT fir_cnt ;
UINT8 status ;
ZFS_SEC_HDR_t sec_hdr ;
PZFS_OPEN_REC_t por ;
UINT16 num_of_sec = (pvol_info->pcfg->vol_secs/pvol_info->pcfg->vol_blks) - 1 ;
UINT32 blk_size = (pvol_info->pcfg->vol_size/pvol_info->pcfg->vol_blks) ;
UINT16 num_of_sec1 = num_of_sec;
VOID **ppsat ;
UINT16 byte_to_write = ZFS_SEC_HDR_WRITTEN ;
// UINT8 bysec_hdr ;
tb_blk = GetTBPtr(pvol_info);
// get the allocation block for which GC need to run.
ab_blk = GetABForGC( pvol_info ) ;
tb_sec_hdr = (PZFS_SEC_HDR_t)((UINT8*)tb_blk->blk_start_addr + ZFS_SEC_SIZE );
ab_sec_hdr = (PZFS_SEC_HDR_t)((UINT8*)ab_blk->blk_start_addr + ZFS_SEC_SIZE );
// now mark the TB header as gc_started.
// Read the TB header.
pvol_info->pcfg->pfn_drv_read( (void *) tb_blk->blk_start_addr, &blk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
blk_hdr.tb_gc_start = ~ZFS_STARTED ;
blk_hdr.gc_frmblk = ab_blk->blk_hdr.blk_num;
// write the TB header
pvol_info->pcfg->pfn_drv_write( (void *) tb_blk->blk_start_addr, &blk_hdr, sizeof( ZFS_BLK_HDR_t) ) ;
// get the AB header
pvol_info->pcfg->pfn_drv_read( (void *) ab_blk->blk_start_addr, &blk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
blk_hdr.ab_gc_start = ~ZFS_STARTED ;
blk_hdr.gc_toblk = tb_blk->blk_hdr.blk_num;
// blk_hdr.gc_frmblk = tb_blk->blk_hdr.blk_num;
// write the AB header
pvol_info->pcfg->pfn_drv_write( (void *) ab_blk->blk_start_addr, &blk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
// get the address of the SAT
ppsat = ( VOID ** ) pvol_info->pvol_sat ;
//now go through the AB for valid sectors, copy it them into TB
while( num_of_sec > 0 )
{
// read the AB sec header
pvol_info->pcfg->pfn_drv_read( ab_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t )) ;
// if( (~(sec_hdr.status)) & (ZFS_SEC_DIRTY ) )
// {
// // do nothing
// or_cnt = 0 ;
// }
// BUG_FIX : 16_SEP
// bysec_hdr = ~sec_hdr.status ;
// if( sec_hdr.sec_num == (ZFS_SEC_ID_t)234 )
// printf("We hit here\n");
if( ( ( (~((UINT8)sec_hdr.status)) & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP)) == (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) ) ||
( ( (~((UINT8)sec_hdr.status)) & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_DUP)) == (ZFS_SEC_DIRTY) ) )
// if( ( bysec_hdr & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) == (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) ) ||
// ( bysec_hdr & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) == (ZFS_SEC_DIRTY) ) )
{
// do nothing
or_cnt = 0 ;
}
else if( ( ( (~(sec_hdr.status)) & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) ) == (ZFS_SEC_DIRTY|ZFS_SEC_DUP) ) )
{
// if the sector is data sector, just copy it
pvol_info->pcfg->pfn_drv_read( ab_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
// write onto TB.
pvol_info->pcfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
num_valid_secs++;
// store the address of this sector in the SAT
//((UINT8*)tb_sec_hdr) += ZFS_SEC_SIZE ;
tb_sec_hdr = (PZFS_SEC_HDR_t)(((UINT8*)tb_sec_hdr) + ZFS_SEC_SIZE) ;
}
// BUG_FIX : 16_SEP
else if( ( (~(sec_hdr.status)) & ZFS_SEC_ALLOCATED ) &&
(~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_DATA )
{
// if the sector is data sector, just copy it
pvol_info->pcfg->pfn_drv_read( ab_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
// write onto TB.
pvol_info->pcfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
num_valid_secs++;
// store the address of this sector in the SAT
*(ppsat + (UINT32)(( PZFS_SEC_HDR_t ) &g_sec_gc[0] )->sec_num ) = tb_sec_hdr ;
//((UINT8*)tb_sec_hdr) += ZFS_SEC_SIZE ;
tb_sec_hdr = (PZFS_SEC_HDR_t)(((UINT8*)tb_sec_hdr) + ZFS_SEC_SIZE) ;
}
else if( ( (~(sec_hdr.status)) & ZFS_SEC_ALLOCATED ) &&
(~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_FIT )
{
// if FIT sector
UINT8 *ptr = &g_sec_gc[0] ;
UINT16 ttl_sec_bit = ZFS_SEC_HDR_WRITTEN ;
UINT16 sec_data_bit = 0x02 ;
// already read teh sector header,
// copy the sector header at the starting of gc
InitializeHeader( &g_sec_gc[0], ZFS_SEC_SIZE ) ;
memcpy( ptr, &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
ptr += 32 ;
// if sector is FIT, then copy only the valid FIRs onto the TB
pfir_addr = (PZFS_FIR_t)((UINT8*)ab_sec_hdr + sizeof(ZFS_FIR_t)) ;
fir_cnt = ZFS_SEC_SIZE/sizeof( ZFS_FIR_t ) - 1 ;
while( fir_cnt > 0 )
{
// get the first fir
pvol_info->pcfg->pfn_drv_read( pfir_addr, &status, 1 ) ;
if( ~(status) & ZFS_FIR_DIRTY )
{
// do nothing
}
else if( ~(status) & ZFS_FIR_ALLOCATED )
{
pvol_info->pcfg->pfn_drv_read( pfir_addr, &fir_hdr, sizeof( ZFS_FIR_t) ) ;
// if valid FIR, copy it into the data buffer.
memcpy(ptr, &fir_hdr, sizeof(ZFS_FIR_t) ) ;
//ptr+= sizeof(ZFS_FIR_t) ; // MK $ CR XXXX $ 22-DEC-2005
ttl_sec_bit &= ( ~sec_data_bit ) ;
sec_data_bit <<= 1 ;
// need to update the fir address onto the OR if the file is already open
for( or_cnt = 0 ; or_cnt < g_max_or_entries; or_cnt++ )
{
por = &g_zfs_or[ or_cnt] ;
if( (por->status & ZFS_OR_MAGIC_NUM) &&
(por->pfir_file == pfir_addr))
{
por->pfir_file = (PZFS_FIR_t)((UINT8*)tb_sec_hdr + (ptr - &g_sec_gc[0])) ;
}
}
ptr+= sizeof(ZFS_FIR_t) ; // MK $ CR XXXX $ 22-DEC-2005
}
pfir_addr++ ;
fir_cnt--;
}
// write the sector onto the new TB.
#ifdef POWER_FAIL_SAFE
*((UINT16 *)(&g_sec_gc[0] + SEC_DATA_BIT_OFFSET)) = ttl_sec_bit ;
#endif
pvol_info->pcfg->pfn_drv_write(tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
num_valid_secs++;
// store the address of this sector in the SAT
*(ppsat + (UINT32)(( PZFS_SEC_HDR_t ) &g_sec_gc[0] )->sec_num ) = tb_sec_hdr ;
//((UINT8*)tb_sec_hdr) += ZFS_SEC_SIZE ;
tb_sec_hdr = (PZFS_SEC_HDR_t)(((UINT8*)tb_sec_hdr) + ZFS_SEC_SIZE) ;
}
num_of_sec-- ;
//((UINT8*)ab_sec_hdr) += ZFS_SEC_SIZE ;
ab_sec_hdr = (PZFS_SEC_HDR_t)(((UINT8*)ab_sec_hdr) + ZFS_SEC_SIZE) ;
}
// write GC complete
// now mark the TB header as gc_started.
// Read the TB header.
pvol_info->pcfg->pfn_drv_read( (void *) tb_blk->blk_start_addr, &blk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
blk_hdr.tb_gc_end = ~ZFS_COMPLETED ;
blk_hdr.sec_hdr.sec_type &= ~ZFS_SEC_TYPE_NEW_AB ;
// write the TB header
pvol_info->pcfg->pfn_drv_write( (void*)tb_blk->blk_start_addr,
&blk_hdr,
sizeof(ZFS_BLK_HDR_t)) ;
// now all valid info is transferred into TB. Make it as TB in RAM also.
tb_blk->blk_hdr.sec_hdr.sec_type &= ~ZFS_SEC_TYPE_NEW_AB ;
tb_blk->free_sec_count = num_of_sec1 - num_valid_secs ;
tb_blk->dirty_sec_count = 0 ;
tb_blk->next_free_sec_addr = ( UINT8 * ) tb_sec_hdr ;
// Now erase the AB.
pvol_info->pcfg->pfn_drv_erase((void *) ab_blk->blk_start_addr, blk_size) ;
// replace in the RAM copy and then write the RAM copy into the flash
ab_blk->blk_hdr.sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
ab_blk->dirty_sec_count = 0 ;
ab_blk->free_sec_count = 0 ;
ab_blk->next_free_sec_addr = ( UINT8 * ) NULL ;
// write into the flash
pvol_info->pcfg->pfn_drv_write( (void*)ab_blk->blk_start_addr,
&ab_blk->blk_hdr,
sizeof(ZFS_BLK_HDR_t)) ;
// write sec_hdr.sec_data_bit = 0xFE to say that the block header is written properly
pvol_info->pcfg->pfn_drv_write(
ab_blk->blk_start_addr + SEC_DATA_BIT_OFFSET,
&byte_to_write,
2) ;
return ZFSERR_SUCCESS ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -