📄 ftllite.c
字号:
/* selected is the one with most free space. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* Best unit to allocate *//*----------------------------------------------------------------------*/static Unit *bestUnitToAllocate(Flare vol){ int i; int mostFreeSectors = 0; Unit *bestUnitSoFar = NULL; for(i = 0; i < vol.noOfUnits; i++) { Unit *unit = vol.logicalUnits[i]; if(unit && unit->noOfFreeSectors > mostFreeSectors) { mostFreeSectors = unit->noOfFreeSectors; bestUnitSoFar = unit; } } return bestUnitSoFar;}/*----------------------------------------------------------------------*//* f i n d F r e e S e c t o r *//* *//* The allocation strategy goes this way: *//* *//* We try to make consecutive virtual sectors physically consecutive if *//* possible. If not, we prefer to have consecutive sectors on the same *//* unit at least. If all else fails, a sector is allocated on the unit *//* with most space available. *//* *//* The object of this strategy is to cluster related data (e.g. a file *//* data) in one unit, and to distribute unrelated data evenly among all *//* units. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : virtual sector no. that we want to allocate. *//* *//* Returns: *//* newAddress : Allocated logical sector no. *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus findFreeSector(Flare vol, VirtualSectorNo sectorNo, LogicalSectorNo *newAddress){ unsigned iSector; LEulong FAR0 *blockAllocMap; UnitHeader FAR0 *unitHeader; Unit *allocationUnit = NULL; LogicalSectorNo previousSectorAddress = sectorNo > 0 ? virtual2Logical(&vol,sectorNo - 1) : UNASSIGNED_SECTOR;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: findFreeSector -> %d !!\n", sectorNo);#endif if(previousSectorAddress != UNASSIGNED_SECTOR && previousSectorAddress != DELETED_SECTOR) { allocationUnit = vol.logicalUnits[previousSectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS)]; if(allocationUnit->noOfFreeSectors > 0) { unsigned int sectorIndex = ((unsigned) previousSectorAddress & (vol.sectorsPerUnit - 1)) + 1; LEulong FAR0 *nextSectorAddress = (LEulong FAR0 *) vol.flash.map(&vol.flash, physicalBase(&vol,allocationUnit) + allocEntryOffset(&vol, sectorIndex), sizeof(VirtualAddress)); if(sectorIndex < vol.sectorsPerUnit && LE4(*nextSectorAddress) == FREE_SECTOR) { /* can write sequentially */ *newAddress = previousSectorAddress + 1; return flOK; } } else allocationUnit = NULL; /* no space here, try elsewhere */ } if (allocationUnit == NULL) allocationUnit = bestUnitToAllocate(&vol); if (allocationUnit == NULL) /* No ? then all is lost */ { dbgMsg(DEBUG_NORMAL,"findFreeSector: findFreeSector -> Unable to find free sector!!\n",0,0,0,0,0,0); return flGeneralFailure; } unitHeader = mapUnitHeader(&vol,allocationUnit,&blockAllocMap); for(iSector = vol.unitHeaderSectors; iSector < vol.sectorsPerUnit; iSector++) { if(LE4(blockAllocMap[iSector]) == FREE_SECTOR) { *newAddress = ((LogicalSectorNo) (LE2(unitHeader->logicalUnitNo)) << (vol.unitSizeBits - SECTOR_SIZE_BITS)) + iSector; return flOK; } } dbgMsg(DEBUG_NORMAL,"findFreeSector: findFreeSector -> Problem marking allocation map!!\n",0,0,0,0,0,0); return flGeneralFailure; /* what are we doing here ? */}/*----------------------------------------------------------------------*//* m a r k A l l o c M a p *//* *//* Writes a new value to a BAM entry. *//* *//* This routine also updates the free & garbage sector counts. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorAddress : Logical sector no. whose BAM entry to mark *//* allocMapEntry : New BAM entry value *//* overwrite : Whether we are overwriting some old value *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus markAllocMap(Flare vol, LogicalSectorNo sectorAddress, VirtualAddress allocMapEntry, FLBoolean overwrite){ UnitNo unitNo = (UnitNo) (sectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS)); Unit *unit = vol.logicalUnits[unitNo]; int sectorInUnit = (unsigned) sectorAddress & (vol.sectorsPerUnit - 1); LEulong bamEntry; if (unitNo >= vol.noOfUnits - vol.noOfTransferUnits) return flGeneralFailure; if(allocMapEntry == GARBAGE_SECTOR) unit->noOfGarbageSectors++; else if(!overwrite) { unit->noOfFreeSectors--; vol.totalFreeSectors--; } toLE4(bamEntry,allocMapEntry); return flashWrite(&vol, physicalBase(&vol,unit) + allocEntryOffset(&vol,sectorInUnit), &bamEntry, sizeof bamEntry, overwrite);}/*----------------------------------------------------------------------*//* d e l e t e L o g i c a l S e c t o r *//* *//* Marks a logical sector as deleted. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorAddress : Logical sector no. to delete *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus deleteLogicalSector(Flare vol, LogicalSectorNo sectorAddress){ if (sectorAddress == UNASSIGNED_SECTOR || sectorAddress == DELETED_SECTOR) return flOK; return markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);}/* forward definition */static FLStatus setVirtualMap(Flare vol, VirtualSectorNo sectorNo, LogicalSectorNo newAddress);/*----------------------------------------------------------------------*//* a l l o c a t e A n d W r i t e S e c t o r *//* *//* Allocates a sector or replacement page and (optionally) writes it. *//* *//* An allocated replacement page also becomes the active replacement *//* page. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : Virtual sector no. to write *//* fromAddress : Address of sector data. If NULL, sector is *//* not written. *//* replacementPage : This is a replacement page sector. *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus allocateAndWriteSector(Flare vol, VirtualSectorNo sectorNo, void FAR1 *fromAddress, FLBoolean replacementPage){ FLStatus status; LogicalSectorNo sectorAddress; VirtualAddress bamEntry = ((VirtualAddress) sectorNo - vol.noOfPages) << SECTOR_SIZE_BITS; long sectorsNeeded = 1;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: calling defrgment routine!!\n");#endif checkStatus(defragment(&vol,§orsNeeded)); /* Organize a free sector */#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: calling routine findFreeSector !!\n");#endif checkStatus(findFreeSector(&vol,sectorNo,§orAddress)); if (replacementPage) bamEntry |= REPLACEMENT_PAGE; else bamEntry |= DATA_SECTOR; status = markAllocMap(&vol, sectorAddress, sectorNo < vol.directAddressingSectors ? ALLOCATED_SECTOR : bamEntry, FALSE); if (status == flOK && fromAddress) status = flashWrite(&vol, logical2Physical(&vol,sectorAddress), fromAddress, SECTOR_SIZE, 0); if (sectorNo < vol.directAddressingSectors && status == flOK) { status = markAllocMap(&vol, sectorAddress, bamEntry, TRUE); } if(status == flOK) { if(replacementPage) { vol.replacementPageAddress = sectorAddress; vol.replacementPageNo = sectorNo; } else { status = setVirtualMap(&vol,sectorNo,sectorAddress); } } if(status != flOK) { status = markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE); } if (status != flOK) dbgMsg(DEBUG_NORMAL,"allocateAndWriteSector: Bad status code at Allocate and Write sector !\n",0,0,0,0,0,0); return status;}/*----------------------------------------------------------------------*//* c l o s e R e p l a c e m e n t P a g e *//* *//* Closes the replacement page by merging it with the primary page. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus closeReplacementPage(Flare vol){ FLStatus status;#ifdef SINGLE_BUFFER int i; LogicalSectorNo nextReplacementPageAddress = vol.replacementPageAddress; VirtualSectorNo firstSectorNo = ((VirtualSectorNo) vol.replacementPageNo << (PAGE_SIZE_BITS - SECTOR_SIZE_BITS)) + vol.noOfPages; pageRetry: for(i = 0; i < ADDRESSES_PER_SECTOR; i++) { LogicalSectorNo logicalSectorNo = virtual2Logical(&vol,firstSectorNo + i); LEulong entryToWrite; toLE4(entryToWrite,logicalSectorNo == UNASSIGNED_SECTOR ? UNASSIGNED_ADDRESS : (LogicalAddress) logicalSectorNo << SECTOR_SIZE_BITS); if (flashWrite(&vol, logical2Physical(&vol,nextReplacementPageAddress) + i * sizeof(LogicalAddress), &entryToWrite, sizeof entryToWrite, OVERWRITE) != flOK) break; } if(i < ADDRESSES_PER_SECTOR && nextReplacementPageAddress == vol.replacementPageAddress) { /* Uh oh. Trouble. Let's replace this replacement page. */ LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress; checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,NULL,TRUE)); nextReplacementPageAddress = vol.replacementPageAddress; vol.replacementPageAddress = prevReplacementPageAddress; goto pageRetry; } if(nextReplacementPageAddress != vol.replacementPageAddress) { LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress; vol.replacementPageAddress = nextReplacementPageAddress; checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress)); }#else setupMapCache(&vol,vol.replacementPageNo); /* read replacement page into map cache */ status = flashWrite(&vol, logical2Physical(&vol,vol.replacementPageAddress), mapCache,SECTOR_SIZE,OVERWRITE); if(status != flOK) /* this should never happen. EAN */ { /* Uh oh. Trouble. Let's replace this replacement page. */ LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress; logMsg("trouble / trouble\n",1,2,3,4,5,6); checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,mapCache,TRUE)); checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress)); }#endif checkStatus(setVirtualMap(&vol,vol.replacementPageNo,vol.replacementPageAddress)); status = markAllocMap(&vol, vol.replacementPageAddress, (((VirtualAddress) vol.replacementPageNo - vol.noOfPages) << SECTOR_SIZE_BITS) | DATA_SECTOR, TRUE); if(status != flOK){ logMsg("markAllocMap ERROR line %i in "__FILE__"\n",__LINE__,2,3,4,5,6); return status; }; vol.replacementPageNo = UNASSIGNED_SECTOR; return flOK;}/*----------------------------------------------------------------------*//* s e t V i r t u a l M a p *//* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -