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

📄 zfsinit.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 C
📖 第 1 页 / 共 4 页
字号:
				ZFSFormat(pzfs_cfg->vol_name, ZFS_FALSE ) ;
				g_fmt_from_init = ZFS_FALSE ;
				g_zfs_init = ZFS_FALSE ;
				pvol_info->new_format_flag = ZFS_TRUE ;
				blk_info_offset += pvol_info->pcfg->vol_blks ;
				sat_info_offset += pvol_info->pcfg->vol_secs ;
*/
				SetVolParamsInvalid( pvol_info, pvol_params ) ;
				pvol_params++ ;

				blk_info_offset += pvol_info->pcfg->vol_blks ;
				sat_info_offset += pvol_info->pcfg->vol_secs ;

				continue ;

				}
			}
		else
			{
			// TB exist, check for below conditions.

			//	2. Check whether the GC in progress or not.
			// check for the gc_Start bit of TB.
			if( (UINT8)(~ptb_blk->blk_hdr.tb_gc_start) == ZFS_STARTED )
				{
				// then check if the GC is not ended. If so, perform the GC again
				if( (UINT8)(~ptb_blk->blk_hdr.tb_gc_end) != ZFS_COMPLETED )
					{
					// The GC is in progress, power failed. just get the alloc block and do the GC again,
					if( ptb_blk->blk_hdr.gc_frmblk==  0xFF )
						{
						// power failed during writing these bits, so start the GC process again.
						GC( pvol_info ) ;
						}
					else
						{
#ifdef POWER_FAIL_SAFE					
						// GC was taking place, power failed. Get the AB that is used in GC and perform the
						// GC from power fail.
						PerFormGCFromPowerFail( 
							pvol_info, 
							&g_blk_info[ blk_info_offset + ptb_blk->blk_hdr.gc_frmblk], 
							ptb_blk ) ;
#endif // POWER_FAIL_SAFE
						}
					pvol_info->is_valid = ZFS_TRUE ;
					}
				}
			else
				
			// check whether the format is in progress or not. If in progress, erase the TB.
			if( (UINT8)(~ptb_blk->blk_hdr.byfmt_start) == ZFS_STARTED )
				{
				g_fmt_from_init = ZFS_TRUE ;
				g_zfs_init = ZFS_TRUE ;
				ZFSFormat(pzfs_cfg->vol_name) ;
				g_fmt_from_init = ZFS_FALSE ;
				g_zfs_init = ZFS_FALSE ;
				pvol_info->new_format_flag = ZFS_TRUE ;
				blk_info_offset += pvol_info->pcfg->vol_blks ;
				sat_info_offset += pvol_info->pcfg->vol_secs ;
				continue ;
				}
			else				
			// 1. AB does not exist, in GC, erase AB happened, or AB header is not written after gC completed, then just
			// erase the AB and make it as TB.
			if( pab_blk_gc_start != NULL )
				{
				
				pzfs_cfg->pfn_drv_erase( pab_blk_gc_start->blk_start_addr, blk_size) ;

				// get the block number of pab_blk_gc_start.
				blk_num = GetBlkNum( pvol_info, pab_blk_gc_start ) ;
				InitializeHeader(&(pab_blk_gc_start->blk_hdr), sizeof( ZFS_BLK_HDR_t ) ) ;

				pab_blk_gc_start->blk_hdr.zfs_magic_num = ZFS_BLOCK_MAGIC_NUM ;
				pab_blk_gc_start->blk_hdr.sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
				pab_blk_gc_start->blk_hdr.sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
				pab_blk_gc_start->blk_hdr.blk_num = blk_num ;
				// write the block header.
				pzfs_cfg->pfn_drv_write( pab_blk_gc_start->blk_start_addr, &pab_blk_gc_start->blk_hdr, sizeof( ZFS_BLK_HDR_t ) ) ;

				// write the bit
				pab_blk_gc_start->blk_hdr.sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
				pzfs_cfg->pfn_drv_write( ( UINT8 *) pab_blk_gc_start->blk_start_addr + SEC_DATA_BIT_OFFSET, &pab_blk_gc_start->blk_hdr.sec_hdr.sec_data_bit, 2 ) ;
				pvol_info->is_valid = ZFS_TRUE ;
				}
			else 
			

			// check whether the invalid block is present or not. If invalid block is present, then 
			// erase the block and write the block header. This will be a AB.
			if( pinval_blk != NULL )
				{
				pzfs_cfg->pfn_drv_erase( pinval_blk->blk_start_addr, blk_size) ;

				blk_num = GetBlkNum( pvol_info, pinval_blk ) ;
				InitializeHeader(&(pinval_blk->blk_hdr), sizeof( ZFS_BLK_HDR_t ) ) ;

				pinval_blk->blk_hdr.zfs_magic_num = ZFS_BLOCK_MAGIC_NUM ;
				pinval_blk->blk_hdr.sec_hdr.sec_type = ~ZFS_SEC_TYPE_TB ;
				pinval_blk->blk_hdr.sec_hdr.status = ~ZFS_SEC_ALLOCATED ;
				pinval_blk->blk_hdr.blk_num = blk_num ;
				
				// write the block header.
				pzfs_cfg->pfn_drv_write( pinval_blk->blk_start_addr, &pinval_blk->blk_hdr, sizeof( ZFS_BLK_HDR_t ) ) ;

				// write the bit
				pinval_blk->blk_hdr.sec_hdr.sec_data_bit = ZFS_SEC_HDR_WRITTEN ;
				pzfs_cfg->pfn_drv_write( ( UINT8 *) pinval_blk->blk_start_addr + SEC_DATA_BIT_OFFSET, &pinval_blk->blk_hdr.sec_hdr.sec_data_bit, 2 ) ;
				pvol_info->is_valid = ZFS_TRUE ;
				}
			}

		// Try to check the root directory location. If root directory is not found throughout the
		// volume, then re-format the disk.
		if( IsRootDirPresent( pvol_info ) == ZFS_FALSE )
			{
			// reformat the disk here
/*				
			g_fmt_from_init = ZFS_TRUE ;
			g_zfs_init = ZFS_TRUE ;
			ZFSFormat(pzfs_cfg->vol_name, ZFS_FALSE ) ;
			g_fmt_from_init = ZFS_FALSE ;
			g_zfs_init = ZFS_FALSE ;
			pvol_info->new_format_flag = ZFS_TRUE ;
			blk_info_offset += pvol_info->pcfg->vol_blks ;
			sat_info_offset += pvol_info->pcfg->vol_secs ;
*/
			SetVolParamsInvalid( pvol_info, pvol_params ) ;
			pvol_params++ ;
			blk_info_offset += pvol_info->pcfg->vol_blks ;
			sat_info_offset += pvol_info->pcfg->vol_secs ;

			continue ;
			}
		else
			pvol_info->is_valid = ZFS_TRUE ;


		blk_info_offset += pvol_info->pcfg->vol_blks ;
		sat_info_offset += pvol_info->pcfg->vol_secs ;

		}
	}


	////////////////////////////////////////////////////////////////////////////////
	// Evert thing related to recover is over, just scan each of the sector and if valid, write the address
	// into the SAT. If invalid sectors are found, make them dirty.
//	sat_info_offset = 0 ;
	pzfs_cfg = &g_zfs_cfg[0];
	pvol_info = &g_zfs_vol_info[0] ;

	tmp_ib_cnt = 0 ;

	for( vol_cnt = 0 ; vol_cnt < g_max_volumes ; vol_cnt++, pzfs_cfg++, pvol_info++ )
		{

		if( pvol_info->is_valid == ZFS_FALSE )
			tmp_ib_cnt++ ;
		
		// if the volume is formatted, then no need to build the tree
		if( ( pvol_info->new_format_flag == ZFS_TRUE ) || ( pvol_info->is_valid == ZFS_FALSE ) )
			continue ;
			
	
		// now read through the sectors present in this volume and update the SAT with values.
//		num_of_sec = pzfs_cfg->vol_secs ;
		pblk_info = pvol_info->blk_info ;
		ab_sec_hdr = ( PZFS_SEC_HDR_t) pzfs_cfg->vol_addr ;
		blk_size = pzfs_cfg->vol_size /pzfs_cfg->vol_blks ; 


		psat = ( UINT8 ** ) pvol_info->pvol_sat ; 
			
		// for each block, get the status of each sectors and then update the SAT with the address and sector number
		for( idx = 0 ; idx < num_blks ; idx++, pblk_info++ )
			{
			if((UINT8) ((~pblk_info->blk_hdr.sec_hdr.sec_type) & ( ZFS_SEC_TYPE_TB | ZFS_SEC_TYPE_NEW_AB )) ==  ( ZFS_SEC_TYPE_TB ) )
				{
				// it is an TB, just continue with next block
				continue ;
				}

			// not it is an AB, just traverse through the blocks and update the SAT
			secs_in_a_blk = blk_size / ZFS_SEC_SIZE ;
			ab_sec_hdr = (PZFS_SEC_HDR_t ) ((UINT8*)pblk_info->blk_start_addr + ZFS_SEC_SIZE );
			num_dirty_secs = 0 ;
			num_free_secs = 0 ;
			free_sec_addr = ( void * ) -1 ;
			for( cnt = 1 ; cnt < secs_in_a_blk ; cnt++ )
				{
				//read the sector header
				pzfs_cfg->pfn_drv_read(ab_sec_hdr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;

#ifdef POWER_FAIL_SAFE					
				// POWER_FAIL_SAFE: Check the sec_hdr.sec_data_bit is set or not, if not set,
				// probably hte power is failed when setting this bit but the sector was allocated. Just make
				// this sector as dirty.
				//////////////
				if( !((UINT8)(~(sec_hdr.sec_data_bit)) & 0x01 ) && 
						(((UINT8)(~sec_hdr.status ) != ZFS_SEC_FREE ) ||
						((UINT8)(~sec_hdr.sec_type) != ZFS_SEC_FREE ) ) )
					{
					// the sector header may have been corrupted or half written or fully written
					// but not the bit, means allocated but not linked to any sector or any FIR.
					// make sector dirty
					sec_hdr.status &= ~(ZFS_SEC_DIRTY | ZFS_SEC_ALLOCATED );
					pzfs_cfg->pfn_drv_write(ab_sec_hdr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
					num_dirty_secs++ ;
					}
				else
#endif // POWER_FAIL_SAFE
// BUG_FIX : 16_SEP
			  	if( ( ( (UINT8)(~sec_hdr.status) & (ZFS_SEC_DIRTY|ZFS_SEC_DUP|ZFS_SEC_NO_DUP) )  ==  (ZFS_SEC_DIRTY|ZFS_SEC_DUP) ) )
			  		{
// TBD TBD
// if a duplicate sector is found, then do not store the address onto the SAT.
// Check this in CheckIntegrityOfFile function. In that function, it should search whole MEDIA and
// If the new sector is found, then probably the OVERWRITESECTOR operation is not completed, otherwise
// if not found, allocate a new sector and copy the data whatever present in the file

// LATEST is VALID
// Here we should search for the newly allocated sector. If it is found, probably this bit is not updated. 
// So, make the the old sector as dirty after checking with whether the sector header is written properly with the bit.
// If not found, then the old sector is freed before allocating the new one, then put the old sector's address onto
// SAT. The checkIntegrityOfFile will check for this bit, and if found, then it will overwrite the old sector.

					if(  IsNewOverWrittenSectorExist( pvol_info, &sec_hdr, ab_sec_hdr ) == ZFS_FALSE )
						{
						// now update the old sector address into the SAT.
						if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE)
							*(psat + (UINT32)sec_hdr.sec_num ) = ( UINT8 *)ab_sec_hdr ;
						}
					
			  		}
				else
// BUG_FIX : 16_SEP
				if( ( ~sec_hdr.status & ZFS_SEC_DIRTY ) == ZFS_SEC_DIRTY )
					{
					// this is an dirty sector, move to next
					num_dirty_secs++ ;
					}
				else if( (~sec_hdr.status & ZFS_SEC_ALLOCATED) == ZFS_SEC_ALLOCATED )
					{
					// valid sector. Just update the SAT with the address.
					if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE)
						*(psat + (UINT32)sec_hdr.sec_num ) = ( UINT8 *)ab_sec_hdr ;
					}
				else if( (UINT8)(~sec_hdr.status) == ZFS_SEC_FREE )
					{
					if( free_sec_addr == ( void * ) -1 )
						{
						free_sec_addr = ( VOID * ) ab_sec_hdr ;
						}
					num_free_secs++ ;
					}
				ab_sec_hdr = ( PZFS_SEC_HDR_t ) ( (( UINT8 * ) ab_sec_hdr) + ZFS_SEC_SIZE ) ;
				
				}

			pblk_info->dirty_sec_count = num_dirty_secs ;
			pblk_info->free_sec_count = num_free_secs ;
			pblk_info->next_free_sec_addr = ( UINT8 * ) free_sec_addr ;
			}
			
	
		// Now the SAT is built up, scan for root directory by reading the 0 sec_num. then scan each of the 
		// directory and the files present in the directory and fill up the dir_nodes.
		/////////////////////////////////////////////////////////////////////////////////////
		// Now perform the below:
		// 1. recover the missing links
		// 2. recover the duplicate of FIRs
		// 3. recover the file size and file linked chains
		// 4. recover the invalid sectors, invalid FIRs
		// 5. build the directory structure in RAM.
		
		if( 	pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
			proot_sec_addr = ( PZFS_SEC_HDR_t ) *((UINT8**) pvol_info->pvol_sat ) ;
		else
			proot_sec_addr = (PZFS_SEC_HDR_t ) (((UINT8*)pvol_info->pcfg->vol_addr) + ZFS_SEC_SIZE);

		pdir_sec_addr = proot_sec_addr ;
		pfir_ab_addr = (PZFS_FIR_t)((UINT8*)proot_sec_addr + sizeof( ZFS_FIR_t ) );

		// allocate a dir node for root directory and update with root directory details.
		root_dir_node = AllocDirNode() ;
		if( root_dir_node == NULL )
			{
			// maximum dir count is reached,
			EnablePreemption(preempt_status) ;
			return ZFSERR_DIR_COUNT_LIMIT_REACHED ;
			}

		// copy the root directory details
		strcpy((INT8 *)root_dir_node->dir_name, ( const INT8 *)pzfs_cfg->vol_name ) ;

		if( pzfs_cfg->vol_type != ZFS_RAM_DEV_TYPE )
		{
			root_dir_node->sec_num = 0 ; // root directory will always have 0 sector
			pdir_sec_id = 0 ;	// root directory sector number
		}
		else
		{
			root_dir_node->sec_num = ((pzfs_cfg->vol_addr) +ZFS_SEC_SIZE);// For RAM the second sector is the Root dir node
			pdir_sec_id = ((pzfs_cfg->vol_addr) +ZFS_SEC_SIZE);	// root directory sector number
		}

		parent_dir_node = root_dir_node ;
		firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
		// this loop will traverse through the directory structure present on flash device and
		// replicate it on the RAM.
		while( parent_dir_node != NULL )
			{
	at_begin:
#ifdef POWER_FAIL_SAFE
			FindDuplicateFIREntry( pvol_info, pdir_sec_id ) ;
#endif //POWER_FAIL_SAFE
			while ( pdir_sec_id != (PZFS_SEC_HDR_t) FREE_SECTOR) 
				{
				while( firs_in_a_sec > 0 )
					{
					// read the FIR
					pzfs_cfg->pfn_drv_read(pfir_ab_addr, &fir_ab_hdr, sizeof(ZFS_FIR_t)) ;

					// check if it is a directory
					if( ( ~((UINT8)fir_ab_hdr.fir_type_status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY | ZFS_DIR_TYPE ) ) == 
								( ZFS_FIR_ALLOCATED | ZFS_DIR_TYPE ) )
						{
						// it is a directory, just allocate a dir_node
						new_dir_node = AllocDirNode() ;
						if( new_dir_node == NULL )
							{
							// maximum dir count is reached,
							EnablePreemption(preempt_status) ;
							return ZFSERR_DIR_COUNT_LIMIT_REACHED ;
							}
						
						// get the length of the FIR name.
						len = GetLenOfFDNameFromFIR( fir_ab_hdr.fir_name ) ;
						memcpy( new_dir_node->dir_name, fir_ab_hdr.fir_name, len ) ;
						new_dir_node->sec_num = fir_ab_hdr.sec_datanum ;

						// point to the next FIR
						parent_dir_node->tmp_fir_addr = (PZFS_FIR_t) pfir_ab_addr + 1 ;
						parent_dir_node->tmp_sec_id = pdir_sec_id ;

						// add the node to the list
						AddSubDirNode( parent_dir_node, new_dir_node ) ;
						
						parent_dir_node = new_dir_node ;
						pdir_sec_id = fir_ab_hdr.sec_datanum ;
						pdir_sec_addr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, pdir_sec_id ) ;
						pfir_ab_addr = ((PZFS_FIR_t)pdir_sec_addr) + 1 ;
						firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;
						goto at_begin ;

						}
					else if( ( (~fir_ab_hdr.fir_type_status) & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY | ZFS_FILE_TYPE ) ) == 
							( ZFS_FIR_ALLOCATED | ZFS_FILE_TYPE ) )
						{
						// it is a file, just increase the fd_cnt
						parent_dir_node->fd_cnt++ ;

#ifdef POWER_FAIL_SAFE
						CheckIntegrityOfFile( pvol_info, parent_dir_node, pfir_ab_addr, &fir_ab_hdr ) ;
#endif //POWER_FAIL_SAFE
						}
					pfir_ab_addr ++ ;
					firs_in_a_sec-- ;
					}
				firs_in_a_sec = ZFS_SEC_SIZE / sizeof( ZFS_FIR_t) - 1 ;

				// read the sector header
				pzfs_cfg->pfn_drv_read(GetSecAddr( pvol_info, pdir_sec_id ), &sec_hdr, sizeof( ZFS_SEC_HDR_t ) ) ;

#ifdef POWER_FAIL_SAFE
				CheckLinkChainOfSector( pvol_info, pdir_sec_id, &sec_hdr ) ;
#endif //POWER_FAIL_SAFE

				pdir_sec_id = sec_hdr.nxtsecnum ;
				pdir_sec_addr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, pdir_sec_id ) ;
				pfir_ab_addr = (PZFS_FIR_t)(((PZFS_FIR_t) pdir_sec_addr) + 1 );
				}

			// here for one directory is over. If it comes here it means that all the FIR's in the current FIT
			// is read, so need to read rest of the FIR's in parent directories FIT from the point where it
			// stopped
			parent_dir_node = parent_dir_node->up_list ;
			pdir_sec_addr = (PZFS_SEC_HDR_t) (( (UINT32) parent_dir_node->tmp_fir_addr ) - ( ((UINT32) parent_dir_node->tmp_fir_addr % ZFS_SEC_SIZE))) ;
			firs_in_a_sec = ( ZFS_SEC_SIZE - ( (UINT32) parent_dir_node->tmp_fir_addr % ZFS_SEC_SIZE )) / sizeof(ZFS_FIR_t) ;
			pfir_ab_addr = ( PZFS_FIR_t ) parent_dir_node->tmp_fir_addr ;
			pdir_sec_id = parent_dir_node->tmp_sec_id ;

			}

		// now update the vol_info table
		pvol_info->proot_node = root_dir_node ;
		pvol_info->root_sec_num = 0 ;
		
		}

	// Here every thing is done, return SUCCESS to the caller
	g_zfs_init = ZFS_TRUE ;

	hSem_FS = RZKCreateSemaphore((RZK_NAME_t *)"hSem_FS",1,RECV_ORDER_PRIORITY);
	if(hSem_FS == NULL)
		printf("\nFS Semaphore creation error");
	
	EnablePreemption(preempt_status) ;
	return tmp_ib_cnt ;
}








⌨️ 快捷键说明

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