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