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

📄 defrag.c

📁 嵌入式系统中文件系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}



/*************************************************************
Fuction : RD_defrag
	defragment the RAMDisk
Input:
	NONE
Output:
	0	no error is found
	-1	system error (check RDerrno)
Note:
	Remember to
	1. Check the file handle table if the buffered blocks
	   have been moved. Update any pointer in file handle
	   to the buffer block if it has been moved.
	2. Check the RD_FirstFreeBlock to see if it has been moved.
	   Oh, this is easy - just set RD_FirstFreeBlock to the
	   resulting single free block.
	3. Check the directory entries because the starting
	   block of a file may have been moved to other place.
**************************************************************/
int RD_defrag(void)
{
  struct diskBlock *currBlock;	// the current block
  long loop;
  long *src;
  long *des;
  long i;
//  long j;
  struct entryInfo eInfoList;	// the entry information list
  struct entryInfo *eLCurrent;
  struct pieceInfo pltList;	// the RD_PLT list
  struct pieceInfo *pLCurrent;	// the tail node of the RD_PLT list
  struct diskBlock *fblTail;	// the tail of free block list
//  struct diskBlock *tempTail;
  short fileOpened = 0;
  short jobDone = 0;
#ifdef RAMDISK_USE_VARIABLE_SIZE_BLOCK
  struct diskBlock *currFreeBlock;	// the previous free block for merging
  struct diskBlock *prevFreeBlock;	// the previous block
  struct diskBlock *nextFreeBlock;	// the previous block
  int found = 0;
//  long prevSize;			// size of the previous block
  long currFreeSize;			// size of the current free block
  
  /**** added by chilong 10/4/2001 ****/
  PIECE_DS *pPieceDS;
  /**** added by chilong 10/4/2001 ****/
#else
#endif

  if (InitRD == FALSE)
  {
	RDerrno = ERROR_FILE_SYSTEM_NOT_INIT;
	return -1;
  }

  RDerrno = 0;

  sc_waitSemaphore(RD_SemaphoreID);

  // check if any file is being opened
  for (i = 0; i < MAX_OPEN_FILE; i++)
  {
	if (RD_HandleTable[i] != NULL)
	{
		if (RD_HandleTable[i]->deviceID == RAMDISK_ID)
		{
			// there are opened files
			// have to update the current block field in the file handle when moving blocks
			fileOpened = 1;
			break;
		}
	}
  }
/*
  sprintf(StrTemp, "fileOpened=%d", fileOpened);
  SprintStringLn(StrTemp);
*/
  // initialize the entry information list
  eInfoList.prev = NULL;
  eInfoList.next = NULL;
  eInfoList.theEntry = NULL;

  // initialize the RD_PLT list
  pltList.next = NULL;
  pltList.piece = NULL;

  // create the entry information list
  currBlock = (struct diskBlock *)(((struct signature *)RD_BootBegin)->rootBegin);
  if (readDirEntryInfo(&eInfoList, currBlock) != 0)
  {
	// can't parse entry information of the whole RAMDisk
	// most probably caused by out of free memory
	clearDirEntryInfo(&eInfoList);
	sc_signalSemaphore(RD_SemaphoreID);
	return -1;
  }

/* marked by chilong 10/4/2001 
  // build the RD_PLT list
  for (i = 1; i < RD_PLT_ENTRY_NUM; i++)
  {
	if (RD_PLT[i] != NULL)
	{
		struct pieceInfo *myPiece;

		myPiece = (struct pieceInfo *)ap_malloc(sizeof(struct pieceInfo));
		if (myPiece == NULL)
		{
			// malloc failed
			clearPieceInfo(&pltList);
			clearDirEntryInfo(&eInfoList);
			sc_signalSemaphore(RD_SemaphoreID);
			RDerrno = ERROR_ALLOC_MEM;
			return -1;
		}
		myPiece->piece= RD_PLT[i];
		myPiece->next = NULL;
		pLInsert(&pltList, myPiece);
	}
  }
   marked by chilong 10/4/2001 */
   
  /**** modified by chilong 10/4/2001 ****/
  // build the RD_PLT list
  for (i = 1; i < RD_PLT_ENTRY_NUM; i++)
  {
  	pPieceDS = (PIECE_DS*) ((PIECE_DS*)RD_PLT + i);
  	if (pPieceDS->startAddress != NULL)
	{
		struct pieceInfo *myPiece;
		
		// check if the current piece could be moved. 
		// If it's a DLL block, we won't defrag it
		currFreeBlock = (struct diskBlock *)pPieceDS->startAddress;
		if (currFreeBlock->status == BLOCK_FOR_DLL)
			continue;
		

		myPiece = (struct pieceInfo *)ap_malloc(sizeof(struct pieceInfo));
		if (myPiece == NULL)
		{
			// malloc failed
			clearPieceInfo(&pltList);
			clearDirEntryInfo(&eInfoList);
			sc_signalSemaphore(RD_SemaphoreID);
			RDerrno = ERROR_ALLOC_MEM;
			return -1;
		}
		myPiece->piece= pPieceDS->startAddress;
		myPiece->next = NULL;
		pLInsert(&pltList, myPiece);
	}
  }
  /**** modified by chilong 10/4/2001 ****/
  
/*
  // print the piece list
  pLCurrent = pltList.next;
  SprintStringLn("piece list:");
  while (pLCurrent != NULL)
  {
	sprintf(StrTemp, "[%x]", pLCurrent->piece);
	SprintStringLn(StrTemp);
	pLCurrent = pLCurrent->next;
  }
*/
  // the RD_PLT list is in ascending order, find the head of the list
  pLCurrent = pltList.next;

#ifdef RAMDISK_USE_VARIABLE_SIZE_BLOCK

  // in this stage, the free blocks within a piece are merged into one free block

  // loop through the pieces ascendingly
  while (pLCurrent != NULL)
  {
	currFreeBlock = (struct diskBlock *)pLCurrent->piece;
	// check the blocks within the current piece
	while ((unsigned long)currFreeBlock < (unsigned long)pLCurrent->piece + RDPieceSize)
	{
		// move the free block
		if (currFreeBlock->status == BLOCK_FREE)
		{
			currBlock = (struct diskBlock *)((unsigned long)currFreeBlock + B_HEADER + currFreeBlock->size + B_TAIL);
			if ((unsigned long)currBlock >= (unsigned long)pLCurrent->piece + RDPieceSize)
			{
				// the current free block is the last block in the piece
				// current piece is done
				break;
			}

			// currFreeBlock points to the current free block and
			// currBlock is the used block following currFreeBlock
			// swaps the positions of these two blocks

			// records the block information of the current free block
			prevFreeBlock = currFreeBlock->prevBlock;
			nextFreeBlock = currFreeBlock->nextBlock;
			currFreeSize = currFreeBlock->size;

			// remove the free block from the free block list
			if (prevFreeBlock != NULL)
			{
				prevFreeBlock->nextBlock = nextFreeBlock;
			}
			else
			{
				// the current free block must be the first free block
				if (RD_FirstFreeBlock != currFreeBlock)
				{
					// there are no free block
					clearPieceInfo(&pltList);
					clearDirEntryInfo(&eInfoList);
					sc_signalSemaphore(RD_SemaphoreID);
					RDerrno = ERROR_FILE_SYSTEM;
					return -1;
				}

				RD_FirstFreeBlock = nextFreeBlock;
				((struct signature *)RD_BootBegin)->freeBegin = (void *)RD_FirstFreeBlock;
			}

			if (nextFreeBlock != NULL)
				nextFreeBlock->prevBlock = prevFreeBlock;

			// copy the used block to the free block
			loop = (currBlock->size + B_HEADER + B_TAIL) / sizeof(long);
			src = (long *)currBlock;
			des = (long *)currFreeBlock;
			for (i = 0; i < loop; i++)
				des[i] = src[i];

			// the new block locations
			currBlock = (struct diskBlock *)des;
			currFreeBlock = (struct diskBlock *)((unsigned long)currBlock + B_HEADER + currBlock->size + B_TAIL);

			// update the neighboring file block links of the used block
			if (currBlock->nextBlock != NULL)
				((struct diskBlock *)(currBlock->nextBlock))->prevBlock = currBlock;
			if (currBlock->prevBlock != NULL)
			{
				((struct diskBlock *)(currBlock->prevBlock))->nextBlock = currBlock;
			}
			else
			{
				// the current block is the starting block of a file/dir
				// update the dir entry information list
				eLCurrent = (struct entryInfo *)(eInfoList.next);
				while (eLCurrent != NULL)
				{
					if ((eLCurrent->theEntry)->startBlock == (struct diskBlock *)src)
					{
						(eLCurrent->theEntry)->startBlock = currBlock;
						if (((eLCurrent->theEntry)->attribute & DA_DIR) == DA_DIR)
						{
							// a dir block was moved, update its entries' address
							eLUpdate(&eInfoList, (void *)src, (unsigned long)currBlock - (unsigned long)src);
						}
						break;
					}

					eLCurrent = (struct entryInfo *)(eLCurrent->next);
				}
			}
				
			// update the file handle in case the used block the current block of a opened file handle
			if (fileOpened == 1)
			{
				for (i = RESERVED_HANDLE; i < MAX_OPEN_FILE; i++)
				{
					if (RD_HandleTable[i] != NULL)
					{
						if (RD_HandleTable[i]->deviceID == RAMDISK_ID)
						{
							/* marked by chilong 7/10/2001
							if (RD_HandleTable[i]->currentBlock == currBlock)
								RD_HandleTable[i]->currentBlock = currFreeBlock;
							   marked by chilong 7/10/2001 */

							/**** modified by chilong 7/10/2001 ****/
							// we use "src" here because currBlock & currFreeBlock have
							// been changed a few lines before
							// "src" now points to the original currBlock address and
							// currBlock points to the new address
							if (RD_HandleTable[i]->currentBlock == (struct diskBlock *)src)
								RD_HandleTable[i]->currentBlock = currBlock;
							/**** modified by chilong 7/10/2001 ****/
							   
						}
					}
				}
			}

			// recover the free block size and free it
			currFreeBlock->size = currFreeSize;
			*((long *)((unsigned long)currFreeBlock + B_HEADER + currFreeSize)) = currFreeSize;
			RD_freeBlock_r(currFreeBlock);

			// the original location of the just-freed block is at currBlock
			currFreeBlock = currBlock;
		}

		// current block done, try next block
		currFreeBlock = (struct diskBlock *)((unsigned long)currFreeBlock + B_HEADER + currFreeBlock->size + B_TAIL);
	} // while ((unsigned long)currBlock < (unsigned long)pLCurrent->piece + RDPieceSize)
	
	pLCurrent = pLCurrent->next;
  } // while (pLCurrent != NULL)

#endif
/*
  sc_signalSemaphore(RD_SemaphoreID);
  SprintStringLn("Phase one D");
  RD_showFileBlockList("\\FILE00.TXT");
  RD_showFileBlockList("\\FILE05.TXT");
  RD_showFileBlockList("\\FILE09.TXT");
  RD_showFreeMemSize();
  sc_waitSemaphore(RD_SemaphoreID);
*/
  // the RD_PLT list is in ascending order, find the head of the list
  pLCurrent = pltList.next;

  // the free block list is in ascending order, find its tail
  fblTail = RD_FirstFreeBlock;
  if (fblTail == NULL)
  {
	// there are no free block
	clearPieceInfo(&pltList);
	clearDirEntryInfo(&eInfoList);
	sc_signalSemaphore(RD_SemaphoreID);
	RDerrno = ERROR_FILE_SYSTEM;
	return -1;
  }

  // get the tail of free block list ==> the starting address of the tail free block is the highest
  while (fblTail->nextBlock != NULL)
  {
	if (RD_checkBlockLocation(fblTail) == -1)
	{
		// the block is out of bound
		clearPieceInfo(&pltList);
		clearDirEntryInfo(&eInfoList);
		sc_signalSemaphore(RD_SemaphoreID);
		RDerrno = ERROR_FILE_SYSTEM;
		return -1;
	}
	fblTail = fblTail->nextBlock;
  }
/*
  sprintf(StrTemp, "fblTail=%x", fblTail);
  SprintStringLn(StrTemp);
*/
  // eInfoList now has the list of dir entries of all files/dirs, solved by startBlock in descending order
  // pltList now has the list of starting address of all pieces, solved by starting address in descending order
  // pLCurrent now points to the first piece info node of pltList
  // fblTail now points the tail node of the free block list

  // defrag starts now

#ifdef RAMDISK_USE_VARIABLE_SIZE_BLOCK

  // block size is not fixed
  // low address blocks are copied to high address free blocks
  // of course the free blocks have to be cut in sizes matching the used blocks

  // loop through the pieces ascendingly
  while (pLCurrent != NULL)
  {
	currBlock = (struct diskBlock *)pLCurrent->piece;
	
  	/**** modified by chilong 10/4/2001 ****/
  	// find an emtry entry in the RD_PLT
  	for (i = 0; i < RD_PLT_ENTRY_NUM; i++)
  	{
  		pPieceDS = (PIECE_DS*) ((PIECE_DS*)RD_PLT + i);

⌨️ 快捷键说明

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