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

📄 zfsinit.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * File       : ZFSInit.c
 * Description: This file contains the implementation of ZFS initialization
 * 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 <string.h>
#include <stdlib.h>
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZSemaphore.h"

#include "glextern.h"
#include "zfscfg.h"

// RZK variables
extern UINT nRzkMaxCwdPathLen ;
extern UINT MAX_THREADS ;

extern UINT g_max_threads ;
extern UINT g_max_cwd_len ;
extern UINT8 g_byEraseFlash ;
extern ZFS_DIR_LIST_CB_t   g_dir_list[ ] ;
extern ZFS_STATUS_t GC( PZFS_VOL_INFO_t pvol_info ) ;
extern UINT8 InitializeRTC( void ) ;
RZK_SEMAPHOREHANDLE_t hSem_FS;
extern ZFS_STATUS_t IsNewOverWrittenSectorExist( PZFS_VOL_INFO_t , PZFS_SEC_HDR_t , PZFS_SEC_HDR_t  );


#ifdef POWER_FAIL_SAFE
// POWER FAIL_SAFE CODE for file system

UINT8 g_sec_buf[ ZFS_SEC_SIZE ] ;

void CarrySubGC( PZFS_VOL_INFO_t pvol_info, UINT num_of_sec, PZFS_SEC_HDR_t ab_sec_hdr, PZFS_SEC_HDR_t tb_sec_hdr )
{
	UINT fir_cnt ;
	ZFS_SEC_HDR_t sec_hdr ;
//	ZFS_FIR_t fir_hdr ;
	PZFS_FIR_t pfir_addr ;
//	PZFS_FIR_t ptb_fir_addr ;
	UINT8 status ;
	PZFS_CONFIG_t pzfs_cfg ;

	pzfs_cfg = pvol_info->pcfg ;
	
	// just update the parameters
	num_of_sec-- ;
	tb_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) tb_sec_hdr + ZFS_SEC_SIZE) ;
	ab_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) ab_sec_hdr + ZFS_SEC_SIZE) ;

	//now go through the AB for valid sectors, copy it them into TB
	while( num_of_sec > 0 )
		{
		// read the AB sec header
		pzfs_cfg->pfn_drv_read( ab_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t )) ;

// BUG_FIX : 16_SEP
//		if( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY )) == ZFS_SEC_ALLOCATED )
		if( ( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY )) == ZFS_SEC_ALLOCATED ) ||
			( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP | ZFS_SEC_NO_DUP  )) == (ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP )) 
			)
// BUG_FIX : 16_SEP
			{
			if( (~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_DATA )
				{
				// if the sector is data sector, just copy it
				pzfs_cfg->pfn_drv_read( ab_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
				// write onto TB.
				pzfs_cfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE) ;
				tb_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) tb_sec_hdr + ZFS_SEC_SIZE) ;
				}
			else if( (~(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 ;
				InitializeHeader( &g_sec_gc[0], ZFS_SEC_SIZE ) ;
				memcpy( &g_sec_gc[0], &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
				
				// if sector is FIT, then copy only the valid FIRs onto the TB
				ptr += sizeof( ZFS_FIR_t ) ;
				fir_cnt = ZFS_SEC_SIZE / sizeof(ZFS_FIR_t) - 1 ;
				pfir_addr = (PZFS_FIR_t)((UINT8*)ab_sec_hdr + sizeof(ZFS_FIR_t)) ;
				while( fir_cnt > 0 )
					{
					// get the first fir
					pzfs_cfg->pfn_drv_read( pfir_addr, &status, 1 ) ;
					if( ( ~(status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY ) ) == ZFS_FIR_ALLOCATED )
						{
						pzfs_cfg->pfn_drv_read( pfir_addr, ptr, sizeof( ZFS_FIR_t ) ) ;
						ptr+= sizeof( ZFS_FIR_t ) ;
						ttl_sec_bit &= ( ~sec_data_bit ) ;
						sec_data_bit <<= 1 ;
						}
					pfir_addr++ ;
					fir_cnt--;
					}

				// write the sector onto the new TB.
				*((UINT16 *)(&g_sec_gc[0] + SEC_DATA_BIT_OFFSET)) = ttl_sec_bit ;
				pzfs_cfg->pfn_drv_write(tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
				tb_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) tb_sec_hdr + ZFS_SEC_SIZE) ;
				}
			}
		num_of_sec-- ;
		ab_sec_hdr = (PZFS_SEC_HDR_t) ((UINT8*) ab_sec_hdr + ZFS_SEC_SIZE) ;
		}

	return ;
}


ZFS_STATUS_t PerFormGCFromPowerFail( PZFS_VOL_INFO_t pvol_info, PZFS_BLK_INFO_t pab_blk_info, PZFS_BLK_INFO_t ptb_blk_info )
{
	PZFS_SEC_HDR_t ab_sec_hdr ;
	PZFS_SEC_HDR_t tb_sec_hdr ;
	UINT num_of_sec ;
	UINT fir_cnt ;
	UINT8 *ptr ; 
	PZFS_CONFIG_t pzfs_cfg = pvol_info->pcfg ;
	ZFS_SEC_HDR_t sec_hdr ;
	PZFS_FIR_t pfir_ab_addr, pfir_tb_addr ;
	ZFS_FIR_t  fir_tb_hdr ;
	UINT8 type_status ;
	ZFS_BLK_HDR_t blk_hdr ;
//	UINT cnt ;
	UINT ab_blk_num ;
	PZFS_BLK_HDR_t pblk_hdr ;
	UINT32 blk_size = 0 ;
	
	
	// The GC is in progress, power failed. just get the alloc block and do the GC again,

	// now check for the valid sectors present in AB and the corresponding sector in TB
	//now go through the AB for valid sectors, copy it them into TB
	ab_sec_hdr = (PZFS_SEC_HDR_t) (( (UINT8*)pab_blk_info->blk_start_addr) + ZFS_SEC_SIZE );
	tb_sec_hdr =  (PZFS_SEC_HDR_t) (( (UINT8*)ptb_blk_info->blk_start_addr) + ZFS_SEC_SIZE ) ;
	num_of_sec = (pzfs_cfg->vol_secs/pzfs_cfg->vol_blks) - 1;

	// write the AB header here for gc_toblk and ab_gc_start flag
	// read the AB header.
	pzfs_cfg->pfn_drv_read( pab_blk_info->blk_start_addr, &blk_hdr, sizeof( ZFS_BLK_HDR_t )) ;

	if( blk_hdr.ab_gc_start == 0xFF || blk_hdr.gc_toblk == 0xFF )
		{
		// block headers are not proper. Write proper block headers.
		blk_hdr.ab_gc_start = 0xFE ;
		blk_hdr.gc_toblk = ptb_blk_info->blk_hdr.blk_num ;
		
		pzfs_cfg->pfn_drv_write( pab_blk_info->blk_start_addr, &blk_hdr, sizeof( ZFS_BLK_HDR_t )) ;
		}
		

	while( num_of_sec > 0 )
		{

		// read the AB sec header
		pzfs_cfg->pfn_drv_read( ab_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t )) ;

		// check whether the sector is dirty or valid
// BUG_FIX : 16_SEP
//		if( (~(sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY ) ) == ZFS_SEC_ALLOCATED )
		if( ( ((~sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY ) ) == ZFS_SEC_ALLOCATED ) ||
			( ((~sec_hdr.status) & ( ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP | ZFS_SEC_NO_DUP  )) == ZFS_SEC_ALLOCATED | ZFS_SEC_DIRTY | ZFS_SEC_DUP ) 
			)			

// BUG_FIX : 16_SEP
			{
			if( (~(sec_hdr.sec_type)) & ZFS_SEC_TYPE_DATA )
				{
				// if the sector is data sector, just copy it
				// read AB sector
				pzfs_cfg->pfn_drv_read( ab_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;

				// read TB sector
				pzfs_cfg->pfn_drv_read( tb_sec_hdr, &g_sec_buf[0], ZFS_SEC_SIZE ) ;
				if( memcmp( &g_sec_gc[0], g_sec_buf, ZFS_SEC_SIZE ) )
					{
					// error, just check from which offset the data need to be written
					// optimize for performance here
					//write the sector here
					pzfs_cfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE ) ;
					// here onwards, only copy the sectors to sectors
					CarrySubGC( pvol_info, num_of_sec, ab_sec_hdr, tb_sec_hdr ) ;
					// go to the end of this function
					goto _end_power_fail_gc ;
					}
				}							
			else if( (~(sec_hdr.status) & ZFS_SEC_TYPE_FIT) )
				{
				// if FIT sector
				// already read teh sector header, 
					
				// if sector is FIT, then copy only the valid FIRs onto the TB
				pfir_ab_addr = (PZFS_FIR_t)((UINT8*)ab_sec_hdr + sizeof(ZFS_FIR_t)) ;

				InitializeHeader( &g_sec_gc[0], ZFS_SEC_SIZE ) ;
				ptr = &g_sec_gc[0] + sizeof( ZFS_FIR_t ) ;

				// store the sec header onto the buffer
				memcpy( &g_sec_gc[0], &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;

				fir_cnt = (ZFS_SEC_SIZE / sizeof(ZFS_FIR_t)) - 1 ;
				// first extract the valid FIRs into the buffer
				while( fir_cnt > 0 )
					{
					// get the valid FIR from TB.
					pzfs_cfg->pfn_drv_read( pfir_ab_addr, &type_status, 1 ) ;
					if( (~(type_status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY ) ) == ZFS_FIR_ALLOCATED )
	 					{
						// read the FIR from tb
						pzfs_cfg->pfn_drv_read( pfir_ab_addr, ptr, sizeof(ZFS_FIR_t) );
						ptr += sizeof( ZFS_FIR_t ) ;
						}
					pfir_ab_addr++ ;
					fir_cnt-- ;
					}

				// now just check whether the power is failued during writing the sector header, if so, copy this and 
				// perform GC from this point onwards.

				
				// now all valid FIR has been stored in the buffer, now check one by one and if difference is present, then
				// perform GC from there.
				// read from TB and check one by one
				pzfs_cfg->pfn_drv_read( tb_sec_hdr, &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;
				if( memcmp( &g_sec_gc[0], &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) )
					{
					// if it is not equal, power is failed during this, just write the contents of buff to the flash
					pzfs_cfg->pfn_drv_write( tb_sec_hdr, &g_sec_gc[0], ZFS_SEC_SIZE  ) ;
					// here onwards, only copy the sectors to sectors
					CarrySubGC( pvol_info, num_of_sec, ab_sec_hdr, tb_sec_hdr ) ;
					break ;
					}
				else
					{
					// it is equal, check with the rest of the FIR
					pfir_tb_addr = (PZFS_FIR_t)((UINT8*)tb_sec_hdr + sizeof(ZFS_FIR_t)) ;
					fir_cnt = (ZFS_SEC_SIZE / sizeof(ZFS_FIR_t)) - 1 ;
					ptr = &g_sec_gc[0] + sizeof( ZFS_FIR_t ) ;
					while( fir_cnt > 0 ) 
						{
						// read from TB
						pzfs_cfg->pfn_drv_read( pfir_tb_addr, &fir_tb_hdr, sizeof( ZFS_FIR_t ) ) ;
						if( memcmp( &fir_tb_hdr, ptr, sizeof(ZFS_FIR_t) ) )
							{
							// FIR copy is different, power failed here, just copy from this FIR.
							pzfs_cfg->pfn_drv_write( pfir_tb_addr, ptr, sizeof(ZFS_FIR_t) );
							// memcmp fails here, just copy all the FIR entries till fir_cnt == 0 
							pfir_tb_addr++ ;
							ptr += sizeof( ZFS_FIR_t ) ;
							fir_cnt-- ;
							while( fir_cnt > 0 )
								{
								// read the FIR from ab
								pzfs_cfg->pfn_drv_write( pfir_tb_addr, ptr, sizeof(ZFS_FIR_t) ) ;
								pfir_tb_addr++;
								ptr += sizeof( ZFS_FIR_t ) ;
								fir_cnt-- ;
								}
							CarrySubGC( pvol_info, num_of_sec, ab_sec_hdr, tb_sec_hdr ) ;
							// go to the end of this function
							goto _end_power_fail_gc ;
							}
						fir_cnt--;
						pfir_tb_addr++ ;
						ptr += sizeof( ZFS_FIR_t ) ;
						}
					// if it comes here, then the comparison is successfull, just do not do any thing.
					}
				}
			tb_sec_hdr = (PZFS_SEC_HDR_t ) (( UINT8*) tb_sec_hdr + ZFS_SEC_SIZE );
			}
		else
			{
			// sector is dirty or is not allocated, do not do any thing here
			}
		num_of_sec -- ;
		ab_sec_hdr = (PZFS_SEC_HDR_t ) (( UINT8*) ab_sec_hdr + ZFS_SEC_SIZE );
		}

_end_power_fail_gc:
	// now just write the TB header with AB header.
	ptb_blk_info->blk_hdr.tb_gc_end = ~ZFS_COMPLETED ;
	ptb_blk_info->blk_hdr.sec_hdr.sec_type &= ~ZFS_SEC_TYPE_NEW_AB ;

	// write the block header onto the TB.
	pzfs_cfg->pfn_drv_write( ptb_blk_info->blk_start_addr, &ptb_blk_info->blk_hdr, sizeof(ZFS_BLK_HDR_t)) ;

	// now every thing is over, just erase the AB and make it as TB.
	pzfs_cfg->pfn_drv_erase( pab_blk_info->blk_start_addr, blk_size) ;
	pblk_hdr = &pab_blk_info->blk_hdr ;
	ab_blk_num = pblk_hdr->blk_num ;

	InitializeHeader( pblk_hdr, sizeof(ZFS_BLK_HDR_t)) ;
	pblk_hdr->sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
	pblk_hdr->sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
	pblk_hdr->sec_hdr.sec_data_bit = ~01 ;
	pblk_hdr->blk_num = ab_blk_num ;
	pab_blk_info->free_sec_count = 0 ;
	pab_blk_info->next_free_sec_addr = ( UINT8 * ) NULL ;
	pzfs_cfg->pfn_drv_write( pab_blk_info->blk_start_addr, pblk_hdr, sizeof(ZFS_BLK_HDR_t)) ;

	return ZFSERR_SUCCESS ;
}


void CorrectDuplicateFIREntry( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t pdir_sec_id, PZFS_FIR_t pdup_fir )
{
	// read the contents of sec id
	PZFS_SEC_HDR_t psec_hdr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, pdir_sec_id ) ;
	PZFS_FIR_t pfir = (PZFS_FIR_t ) ((UINT8*)psec_hdr + sizeof( ZFS_FIR_t ) );
	ZFS_FIR_t fir, orig_fir ;
	ZFS_SEC_HDR_t sec_hdr ;
	UINT firs_in_a_sec ;
//	ZFS_SEC_ID_t orig_sec_id = pdir_sec_id ;
	UINT8 fir_status ;
	UINT16 sec_data_bit ;
	UINT16 tmp_data_bit ;

	pvol_info->pcfg->pfn_drv_read( pdup_fir, &orig_fir, sizeof( ZFS_FIR_t ) ) ;

	while( pdir_sec_id != (( ZFS_SEC_ID_t ) FREE_SECTOR) ) 
		{
		
		pvol_info->pcfg->pfn_drv_read( ( (UINT8*)GetSecAddr( pvol_info, pdir_sec_id) + SEC_DATA_BIT_OFFSET), &sec_data_bit, 2 ) ;
		sec_data_bit = ~sec_data_bit ;
		tmp_data_bit = 0x0002 ;
		firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
		for( ; firs_in_a_sec > 0 ; firs_in_a_sec--, pfir++ )
			{
			// get the fir header
			pvol_info->pcfg->pfn_drv_read( pfir, &fir_status, 1 ) ;
			
			// now check whether the FIR is written properly or not, if not make this fir as dirty.
			if( !(sec_data_bit & tmp_data_bit ) )
				{
				if( (fir_status != (UINT8)(~ZFS_FIR_FREE) ) )
					{
					fir_status &= ~ZFS_FIR_DIRTY ;

					// write down the FIR onto the flash
					pvol_info->pcfg->pfn_drv_write( pfir, &fir_status, 1 ) ;
					}
				}
			else
				{
				// read the FIR,
				pvol_info->pcfg->pfn_drv_read( pfir, &fir, sizeof( ZFS_FIR_t )  ) ;
				// now check whether the FIR is of the same FIR as of duplicate or not.

				if( ( ( fir.sec_datanum == orig_fir.sec_datanum ) || !memcmp( &fir.fir_name[0], &orig_fir.fir_name[0], ZFS_MAX_FILE_NAME_SIZE ) )
						&& pfir != pdup_fir )
					{

					// things are equal, but check whether this is the FIR which need to be made as dirty, because
					// if some files were just opened for write and then closed, which is not made for overwrite, and the
					// sec_num is still 0xFFFFFF, we should check whether the dirty is started or not. If both dirty_Start and dirty_stop
					// bits are not set or is set, then there is no problem, if dirty_start bit is set, but not dirty_stop bit, then we need to 
					// set this record as duplicate and make it as dirty.
					// sector number is equal, just check whether this record is made as dirty
					// this may not work if the file is just created and renamed to something else. ****
					// ********** TBD ***** A BUG is here, just need to fix this. ****Mahadev
					if( ((~fir_status) & (ZFS_FIR_DIRTY | ZFS_FIR_ALLOCATED ) ) == ZFS_FIR_ALLOCATED )
						{
						// this is the duplicate entry, just make this entry as invalid.
						fir_status &= ~ZFS_FIR_DIRTY ;
						pvol_info->pcfg->pfn_drv_write( pfir, &fir_status, 1 ) ;
						// go to end.
						goto _end_CorrectDuplicateFIREntry;
						}
					}
				}
			}
		pvol_info->pcfg->pfn_drv_read( ( (UINT8*)GetSecAddr( pvol_info, pdir_sec_id)), &sec_hdr, sizeof(ZFS_SEC_HDR_t ) ) ;
		pdir_sec_id = sec_hdr.nxtsecnum ;
		pfir = (PZFS_FIR_t) ((UINT8*) GetSecAddr( pvol_info, pdir_sec_id ) + sizeof( ZFS_FIR_t ) ) ;
		}
_end_CorrectDuplicateFIREntry:
	// now the either duplicate entry is found or not found, if found it is already been made as dirty, now 
	// write ZFS_FIR_NOT_DUP to the given FIR.
	orig_fir.fir_type_status &= ~ZFS_FIR_NOT_DUP ;
	pvol_info->pcfg->pfn_drv_write( pdup_fir, &orig_fir.fir_type_status, 1 ) ;
	return ;
}


void FindDuplicateFIREntry( PZFS_VOL_INFO_t pvol_info, ZFS_SEC_ID_t pdir_sec_id )
{
	// read the contents of sec id
	PZFS_SEC_HDR_t psec_hdr = (PZFS_SEC_HDR_t) GetSecAddr( pvol_info, pdir_sec_id ) ;
	PZFS_FIR_t pfir = (PZFS_FIR_t ) ((UINT8*)psec_hdr + sizeof( ZFS_FIR_t ) );
//	ZFS_FIR_t fir ;
	ZFS_SEC_HDR_t sec_hdr ;
	UINT firs_in_a_sec ;
	ZFS_SEC_ID_t orig_sec_id = pdir_sec_id ;
	UINT8 fir_status ;
	UINT16 sec_data_bit ;
	UINT16 tmp_data_bit ;

	if( pvol_info->pcfg->vol_type == ZFS_RAM_DEV_TYPE )
		return ;

	while( pdir_sec_id != ( ZFS_SEC_ID_t ) FREE_SECTOR ) 
		{
		
		pvol_info->pcfg->pfn_drv_read( ( (UINT8*)GetSecAddr( pvol_info, pdir_sec_id) + SEC_DATA_BIT_OFFSET), &sec_data_bit, 2 ) ;
		sec_data_bit = ~sec_data_bit ;
		tmp_data_bit = 0x0002 ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -