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

📄 zfsgc.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 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 + -