📄 defrag.c
字号:
}
/*************************************************************
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 + -