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

📄 defrag.c

📁 PDA上的CF CARD 文件系统的建立程式
💻 C
📖 第 1 页 / 共 3 页
字号:
  		if (pPieceDS->startAddress == pLCurrent->piece)
		{
			break;
		}
  	}
  	
  	if (i == RD_PLT_ENTRY_NUM)
  	{
  		// this error should not happen
		RDerrno = ERROR_FILE_SYSTEM;
  		return -1;
  	}
	/**** modified by chilong 10/4/2001 ****/

	/* marked by chilong 10/4/2001 	
	// check the blocks within the current piece
	while ((unsigned long)currBlock < (unsigned long)pLCurrent->piece + RDPieceSize)
	   marked by chilong 10/4/2001 */
	   
	/**** modified by chilong 10/4/2001 ****/
	while ((unsigned long)currBlock < (unsigned long)pPieceDS->startAddress + pPieceDS->size)
	/**** modified by chilong 10/4/2001 ****/
	{
//		sprintf(StrTemp, "[%x/%x]", currBlock, fblTail);
//		SprintStringLn(StrTemp);

		if (currBlock > fblTail)
		{
			// the current block is already at higher address than the
			//   last block in the free block list, defrag done 
			jobDone = 1;
			break;
		}

		/* marked by chilong 10/4/2001 
		// only non-free block will be moved
		if (currBlock->status != BLOCK_FREE)
		   marked by chilong 10/4/2001 */
		   
		// only non-free block will be moved
		if (currBlock->status != BLOCK_FREE && currBlock->status != BLOCK_FOR_DLL)
		{
			// the current block is not free, find a free block large enough to hold it
			currFreeBlock = fblTail;
			prevFreeBlock = NULL;
			found = 0;

			while (currFreeBlock != NULL)
			{
				if (currBlock > currFreeBlock)
				{
					// the current block is not going to be moved to lower address
					// try next used block
					break;
				}

				if (currFreeBlock->size > currBlock->size + B_HEADER + B_TAIL)
				{
					// the current free block is large enough to need cutting

					// prepare the remaining free block after cutting and update free block links
					prevFreeBlock = (struct diskBlock *)((unsigned long)currFreeBlock + currBlock->size + B_HEADER + B_TAIL);
					prevFreeBlock->nextBlock = currFreeBlock->nextBlock;
					prevFreeBlock->prevBlock = currFreeBlock->prevBlock;
					prevFreeBlock->size = currFreeBlock->size - currBlock->size - B_HEADER - B_TAIL;
					*((long *)((unsigned long)prevFreeBlock + B_HEADER + prevFreeBlock->size)) = prevFreeBlock->size;
					prevFreeBlock->dataSize = 0;
					prevFreeBlock->actualSize = 0;
					prevFreeBlock->status = BLOCK_FREE;
					prevFreeBlock->userCount = 0;
					if (currFreeBlock->nextBlock != NULL)
						((struct diskBlock *)(currFreeBlock->nextBlock))->prevBlock = prevFreeBlock;
					if (currFreeBlock->prevBlock != NULL)
						((struct diskBlock *)(currFreeBlock->prevBlock))->nextBlock = prevFreeBlock;
					if (fblTail == currFreeBlock)
						fblTail = prevFreeBlock;
					if (RD_FirstFreeBlock == currFreeBlock)
					{
						RD_FirstFreeBlock = prevFreeBlock;
						((struct signature *)RD_BootBegin)->freeBegin = (void *)RD_FirstFreeBlock;
					}

					found = 1;
				}
				else if (currFreeBlock->size >= currBlock->size)
				{
					// the current free block matches the current used block in size

					// update free block links
					if (currFreeBlock->nextBlock != NULL)
						((struct diskBlock *)(currFreeBlock->nextBlock))->prevBlock = currFreeBlock->prevBlock;
					if (currFreeBlock->prevBlock != NULL)
						((struct diskBlock *)(currFreeBlock->prevBlock))->nextBlock = currFreeBlock->nextBlock;
					if (fblTail == currFreeBlock)
						fblTail = currFreeBlock->prevBlock;
					if (RD_FirstFreeBlock == currFreeBlock)
					{
						RD_FirstFreeBlock = currFreeBlock->nextBlock;
						((struct signature *)RD_BootBegin)->freeBegin = (void *)RD_FirstFreeBlock;
					}

					found = 1;
				}

				if (found == 1)
				{
					// copy the file content from 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];

					// update file block links
					if (currBlock->nextBlock != NULL)
						((struct diskBlock *)(currBlock->nextBlock))->prevBlock = currFreeBlock;
					if (currBlock->prevBlock != NULL)
					{
						((struct diskBlock *)(currBlock->prevBlock))->nextBlock = currFreeBlock;
					}
					else
					{
						// there is no previous block
						// this block should be the starting block of a file/dir
						// have to update the corresponding dir entry
						eLCurrent = (struct entryInfo *)(eInfoList.next);
						while (eLCurrent != NULL)
						{
							if ((eLCurrent->theEntry)->startBlock == currBlock)
							{
								(eLCurrent->theEntry)->startBlock = currFreeBlock;
								eLRemove(&eInfoList, eLCurrent);
								if (((eLCurrent->theEntry)->attribute & DA_DIR) == DA_DIR)
								{
									// a dir block was moved, update its entries' address
									eLUpdate(&eInfoList, (void *)currBlock, (unsigned long)currFreeBlock - (unsigned long)currBlock);
								}
								break;
							}
							
							if ((unsigned long)((eLCurrent->theEntry)->startBlock) < (unsigned long)currBlock)
							{
								// the current entry's starting block address is smaller than the current block
								// directory entry checking can be stopped and the preceeding entries can be removed
								eLRemove(&eInfoList, (struct entryInfo *)(eLCurrent->prev));
								break;
							}

							eLCurrent = (struct entryInfo *)(eLCurrent->next);
						}
					}

					// check if the block is 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)
								{
									if (RD_HandleTable[i]->currentBlock == currBlock)
										RD_HandleTable[i]->currentBlock = currFreeBlock;
								}
							}
						}
					}

					// the old used block may merge with the tail free block
					if (((unsigned long)currBlock + B_HEADER + currBlock->size + B_TAIL) == (unsigned long)fblTail)
					{
						// check if the tail free block is within the same piece as the old used block
						if ((unsigned long)fblTail >= (unsigned long)(pLCurrent->piece) && \
						    (unsigned long)fblTail < (unsigned long)(pLCurrent->piece) + RDPieceSize)
						{
							// blocks will merge
							fblTail = currBlock;
						}
					}

					// release the new free block
					RD_freeBlock_r(currBlock);

					// the current block has been freed, it may have already merged with the next block
					// restarts the current piece
					currBlock = (struct diskBlock *)pLCurrent->piece;

					break;
				}

				// current free block not big enough, try next free block
				prevFreeBlock = currFreeBlock;
				currFreeBlock = currFreeBlock->prevBlock;
			} // while (currFreeBlock != NULL)
		} // if (currBlock->status != BLOCK_FREE)
		// current block done, try next block
		currBlock = (struct diskBlock *)((unsigned long)currBlock + B_HEADER + currBlock->size + B_TAIL);
	} // while ((unsigned long)currBlock < (unsigned long)pLCurrent->piece + RDPieceSize)

	if (jobDone == 1)
		break;

	// defrag not done yet, go to next piece
	pLCurrent = pLCurrent->next;
  } // while (pLCurrent != NULL)

  // blocks have been herded to higher address free blocks
  // free the unused pieces
  loop = freeUnusedPiece(0);
/*
  sprintf(StrTemp, "FP:%d", loop);
  SprintStringLn(StrTemp);
*/
  clearPieceInfo(&pltList);
  clearDirEntryInfo(&eInfoList);

  sc_signalSemaphore(RD_SemaphoreID);

  return 0;

#else	// #ifdef RAMDISK_USE_VARIABLE_SIZE_BLOCK

  // block size is fixed
  // defrag is achieved by simply copying the block content from
  //   low address used blocks to high address free blocks
  // block cutting is unnecessary

  loop = RDSystemBlockSize / sizeof(long);

  // loop through the pieces ascendingly
  while (pLCurrent != NULL)
  {
	currBlock = (struct diskBlock *)pLCurrent->piece;
	// check the blocks within the current piece
	for (i = 0; i < RD_BLOCKS_PER_PIECE; i++)
	{
		if (currBlock > fblTail)
		{
			// the current block is already at higher address than the
			//   last block in the free block list, defrag done 
			jobDone = 1;
			break;
		}

		// only non-free block will be moved
		if (currBlock->status != BLOCK_FREE)
		{
			// the current block is not free, move it to the tail free block
			tempTail = fblTail->prevBlock;
			if (tempTail != NULL)
			{
				tempTail->nextBlock = NULL;
			}
			else // if (tempTail != NULL)
			{
				// no previous block
				// is the tail block also the first free block?
				if (RD_FirstFreeBlock == fblTail)
				{
					RD_FirstFreeBlock = fblTail->nextBlock;
					((struct signature *)RD_BootBegin)->freeBegin = (void *)RD_FirstFreeBlock;
				}
				else
				{
					// file system error
					clearPieceInfo(&pltList);
					clearDirEntryInfo(&eInfoList);
					sc_signalSemaphore(RD_SemaphoreID);
					RDerrno = ERROR_FILE_SYSTEM;
					return -1;
				}
			} // if (tempTail != NULL)

			// copy the block content
			src = (long *)currBlock;
			des = (long *)fblTail;
			for (j = 0; j < loop; i++)
				des[j] = src[j];

			// update the block links
			if (currBlock->prevBlock != NULL)
			{
				// there is a previous block
				((struct diskBlock *)(currBlock->prevBlock))->nextBlock = fblTail;
			}
			else // if (currBlock->prevBlock != NULL)
			{
				// there is no previous block
				// this block should be a starting block of a file/dir
				// have to update the corresponding dir entry
				eLCurrent = (struct entryInfo *)(eInfoList.next);
				while (eLCurrent != NULL)
				{
					if ((eLCurrent->theEntry)->startBlock == currBlock)
					{
						(eLCurrent->theEntry)->startBlock = fblTail;
						eLRemove(&eInfoList, eLCurrent);
						if (((eLCurrent->theEntry)->attribute & DA_DIR) == DA_DIR)
						{
							// a dir block was moved, update its entries' address
							eLUpdate(&eInfoList, (void *)currBlock, (unsigned long)fblTail - (unsigned long)currBlock);
						}
						break;
					}

					if ((unsigned long)((eLCurrent->theEntry)->startBlock) < (unsigned long)currBlock)
					{
						// the current entry's starting block address is smaller than the current block
						// directory entry checking can be stopped and the preceeding entries can be removed
						eLRemove(&eInfoList, (struct entryInfo *)(eLCurrent->prev));
						break;
					}

					eLCurrent = (struct entryInfo *)(eLCurrent->next);
				}
			} // if (currBlock->prevBlock != NULL)

			if (currBlock->nextBlock != NULL)
				((struct diskBlock *)(currBlock->nextBlock))->prevBlock = fblTail;

			// check if the block is the current block of a opened file handle
			if (fileOpened == 1)
			{
				for (j = 2; j < MAX_OPEN_FILE; j++)
				{
					if (RD_HandleTable[i] != NULL)
					{
						if (RD_HandleTable[i]->deviceID == RAMDISK_ID)
						{
							if (RD_HandleTable[i]->currentBlock == currBlock)
								RD_HandleTable[i]->currentBlock = fblTail;
						}
					}
				}
			}

			// release the new free block
			RD_freeBlock_r(currBlock);

			// the tail of free block list go to the previous block
			fblTail = tempTail;
		} // if (currBlock->status != BLOCK_FREE)

		// current block done, go to next block
		currBlock = (struct diskBlock *)((unsigned long)currBlock + RDSystemBlockSize);
	} // for (i = 0; i < RD_BLOCKS_PER_PIECE; i++)

	if (jobDone == 1)
		break;

	// defrag not done yet, go to next piece
	pLCurrent = pLCurrent->next;
  } // while (pLCurrent != NULL)

  // blocks have been herded to higher address free blocks
  // free the unused pieces
  loop = freeUnusedPiece(1);
	
  clearPieceInfo(&pltList);
  clearDirEntryInfo(&eInfoList);

  sc_signalSemaphore(RD_SemaphoreID);

  return 0;

#endif	// #ifdef RAMDISK_USE_VARIABLE_SIZE_BLOCK

  return 0;
}



#endif	// #ifdef RAMDISK_ID



⌨️ 快捷键说明

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