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

📄 ftllite.c

📁 该程序是一个tffs文件系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  toLE2(unitNoToWrite,logicalUnitNo);  return flashWrite(&vol,		    physicalBase(&vol,unit) + logicalUnitNoOffset,		    &unitNoToWrite,		    sizeof unitNoToWrite,		    OVERWRITE);}/*----------------------------------------------------------------------*//*		    b e s t U n i t T o T r a n s f e r			*//*									*//* Find best candidate for unit transfer, usually on the basis of which	*//* unit has the most garbage space. A lower wear-leveling info serves	*//* as a tie-breaker. If 'leastUsed' is NOT specified, then the least	*//* wear-leveling info is the only criterion.				*//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	leastUsed	: Whether most garbage space is the criterion	*//*                                                                      *//* Returns:                                                             *//*	Best unit to transfer						*//*----------------------------------------------------------------------*/static UnitNo bestUnitToTransfer(Flare vol,  FLBoolean leastUsed){  UnitNo i;  int mostGarbageSectors = 1;  unsigned long int leastWearLevelingInfo = 0xffffffffl;  UnitNo bestUnitSoFar = UNASSIGNED_UNIT_NO;  for (i = 0; i < vol.noOfUnits; i++) {    Unit *unit = vol.logicalUnits[i];    if (unit && (!leastUsed || (unit->noOfGarbageSectors >= mostGarbageSectors))) {      UnitHeader FAR0 *unitHeader = mapUnitHeader(&vol,unit,NULL);      if ((leastUsed && (unit->noOfGarbageSectors > mostGarbageSectors)) ||	  (LE4(unitHeader->wearLevelingInfo) < leastWearLevelingInfo)) {	mostGarbageSectors = unit->noOfGarbageSectors;	leastWearLevelingInfo = LE4(unitHeader->wearLevelingInfo);	bestUnitSoFar = i;      }    }  }  return bestUnitSoFar;}/*----------------------------------------------------------------------*//*		           u n i t T r a n s f e r			*//*									*//* Performs a unit transfer from a selected unit to a tranfer unit.	*//*                                                                      *//* A side effect is to invalidate the map cache (reused as buffer).	*//*									*//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	toUnit          : Target transfer unit				*//*	fromUnitNo:	: Source logical unit no.			*//*                                                                      *//* Returns:                                                             *//*	FLStatus	: 0 on success, failed otherwise		*//*----------------------------------------------------------------------*/static FLStatus unitTransfer(Flare vol,  Unit *toUnit, UnitNo fromUnitNo){  unsigned i;  Unit *fromUnit = vol.logicalUnits[fromUnitNo];  UnitHeader FAR0 *transferUnitHeader = mapUnitHeader(&vol,toUnit,NULL);  if (!verifyFormat(transferUnitHeader) ||      LE2(transferUnitHeader->logicalUnitNo) != UNASSIGNED_UNIT_NO)    /* previous formatting failed or did not complete. 		*/    checkStatus(formatUnit(&vol,toUnit));  /* Should the transfer not complete, the unit is marked to be erased */  checkStatus(assignUnit(&vol,toUnit,MARKED_FOR_ERASE));#ifdef BACKGROUND  vol.mirrorFrom = vol.mirrorTo = physicalBase(&vol,fromUnit);  vol.mirrorOffset = physicalBase(&vol,toUnit) - vol.mirrorFrom;#endif  /* copy the block allocation table and the good sectors */  for (i = 0; i < vol.sectorsPerUnit;) {    int j;    FLBoolean needToWrite = FALSE;    int firstOffset = allocEntryOffset(&vol,i);    /* Up to 128 bytes of the BAM are processed per loop */    int nEntries = (128 - (firstOffset & 127)) / sizeof(VirtualAddress);    /* We are going to use the Virtual Map cache as our sector buffer in the */    /* transfer, so let's better invalidate the cache first.		   */#ifdef SINGLE_BUFFER    if (buffer.dirty)      return flBufferingError;#endif    buffer.sectorNo = UNASSIGNED_SECTOR;    /* Read some of the BAM */    vol.flash.read(&vol.flash,	       physicalBase(&vol,fromUnit) + firstOffset,	       sectorCopy,	       nEntries * sizeof(VirtualAddress),	       0);    /* Convert garbage entries to free entries */    for (j = 0; j < nEntries && i+j < vol.sectorsPerUnit; j++) {      unsigned bamSignature = (unsigned) LE4(sectorCopy[j]) & SECTOR_OFFSET_MASK;      if (bamSignature == DATA_SECTOR ||	  bamSignature == REPLACEMENT_PAGE)	needToWrite = TRUE;      else if (bamSignature != FORMAT_SECTOR)	toLE4(sectorCopy[j],FREE_SECTOR);    }    if (needToWrite) {      FLStatus status;      /* Write new BAM, and copy sectors that need to be copied */      status = flashWrite(&vol,			  physicalBase(&vol,toUnit) + firstOffset,			  sectorCopy,			  nEntries * sizeof(VirtualAddress),			  0);      if (status != flOK) {#ifdef BACKGROUND	vol.mirrorOffset = 0;	/* no more mirroring */#endif	return status;      }      for (j = 0; j < nEntries && i+j < vol.sectorsPerUnit; j++) {	unsigned bamSignature = (unsigned) LE4(sectorCopy[j]) & SECTOR_OFFSET_MASK;	if (bamSignature == DATA_SECTOR ||	    bamSignature == REPLACEMENT_PAGE) { /* a good sector */	  CardAddress sectorOffset = (CardAddress) (i+j) << SECTOR_SIZE_BITS;	  vol.flash.read(&vol.flash,		     physicalBase(&vol,fromUnit) + sectorOffset,		     sectorCopy,SECTOR_SIZE,0);	  status = flashWrite(&vol,			      physicalBase(&vol,toUnit) + sectorOffset,			      sectorCopy,			      SECTOR_SIZE,			      0);	  if (status != flOK) {#ifdef BACKGROUND	    vol.mirrorOffset = 0;	/* no more mirroring */#endif	    return status;	  }	  vol.flash.read(&vol.flash,		     physicalBase(&vol,fromUnit) + firstOffset,		     sectorCopy,		     nEntries * sizeof(VirtualAddress),0);	}      }#ifdef BACKGROUND      vol.mirrorTo = vol.mirrorFrom +		     ((CardAddress) (i + nEntries) << SECTOR_SIZE_BITS);      while (flForeground(1) == BG_SUSPEND)	;#endif    }    i += nEntries;  }#ifdef BACKGROUND  vol.mirrorOffset = 0;	/* no more mirroring */#endif  /* Write the new logical unit no. */  checkStatus(assignUnit(&vol,toUnit,fromUnitNo));  /* Mount the new unit in place of old one */  vol.logicalUnits[fromUnitNo] = NULL;  if (mountUnit(&vol,toUnit) == flOK) {    vol.totalFreeSectors -= fromUnit->noOfFreeSectors;    /* Finally, format the source unit (the new transfer unit) */    vol.transferUnit = fromUnit;    formatUnit(&vol,fromUnit);	/* nothing we can or should do if this fails */  }  else {		/* Something went wrong */    vol.logicalUnits[fromUnitNo] = fromUnit;	/* reinstate original unit */    return flGeneralFailure;  }  return flOK;}/*----------------------------------------------------------------------*//*		         g a r b a g e C o l l e c t			*//*									*//* Performs a unit transfer, selecting a unit to transfer and a		*//* transfer unit.                                                       *//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*                                                                      *//* Returns:                                                             *//*	FLStatus	: 0 on success, failed otherwise		*//*----------------------------------------------------------------------*/static FLStatus garbageCollect(Flare vol){  FLStatus status;  UnitNo fromUnitNo;  if (vol.transferUnit == NULL)    return flWriteProtect;	/* Cannot recover space without a spare unit */  fromUnitNo = bestUnitToTransfer(&vol,flRandByte() >= 4);  if (fromUnitNo == UNASSIGNED_UNIT_NO)    return flGeneralFailure;	/* nothing to collect */  /* Find a unit we can transfer to.				*/  status = unitTransfer(&vol,vol.transferUnit,fromUnitNo);  if (status == flWriteFault) {    int i;    Unit *unit = vol.physicalUnits;    for (i = 0; i < vol.noOfUnits; i++, unit++) {      if (unit->noOfGarbageSectors == 0 && unit->noOfFreeSectors < 0) {	if (unitTransfer(&vol,unit,fromUnitNo) == flOK)	  return flOK;	/* found a good one */      }    }  }  return status;}#ifdef BACKGROUND/*----------------------------------------------------------------------*//*		        b g G a r b a g e C o l l e c t			*//*									*//* Entry point for garbage collection in the background.		*//*                                                                      *//* Status is returned in vol.garbageCollectStatus			*//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*          								*//* Returns:                                                             *//*	None								*//*----------------------------------------------------------------------*/static void bgGarbageCollect(void * object){  Flare vol = (Flare *)object;  vol.garbageCollectStatus = flIncomplete;  vol.garbageCollectStatus = garbageCollect(&vol);}#endif/*----------------------------------------------------------------------*//*      	            d e f r a g m e n t				*//*									*//* Performs unit transfers to arrange a minimum number of writable	*//* sectors.                                                             *//*									*//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	sectorsNeeded	: Minimum required sectors			*//*                                                                      *//* Returns:                                                             *//*	FLStatus	: 0 on success, failed otherwise		*//*----------------------------------------------------------------------*/#define GARBAGE_COLLECT_THRESHOLD	20static FLStatus defragment(Flare vol, long FAR2 *sectorsNeeded){  while ((long)(vol.totalFreeSectors) < *sectorsNeeded#ifdef BACKGROUND	 || vol.totalFreeSectors < GARBAGE_COLLECT_THRESHOLD#endif	 ) {    if (vol.badFormat)      return flBadFormat;#ifdef BACKGROUND    if (vol.garbageCollectStatus == flIncomplete)      flBackground(BG_RESUME);    else      flStartBackground(&vol - vols,bgGarbageCollect,&vol);    if (vol.garbageCollectStatus != flOK &&	vol.garbageCollectStatus != flIncomplete)      return vol.garbageCollectStatus;    if (vol.totalFreeSectors >= *sectorsNeeded)      break;  }  if (vol.unitEraseInProgress)    flBackground(BG_SUSPEND);#else    checkStatus(garbageCollect(&vol));  }#endif  *sectorsNeeded = vol.totalFreeSectors;  return flOK;}/*----------------------------------------------------------------------*//*		    b e s t U n i t T o A l l o c a t e			*//*									*//* Finds the best unit from which to allocate a sector. The unit	*//* 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)

⌨️ 快捷键说明

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