📄 fsintrnl.c
字号:
}
/*-------------------------------------------------------------------*/
/* Return if the set size did not increase. */
/*-------------------------------------------------------------------*/
if (set_increase == FALSE)
return;
/*-------------------------------------------------------------------*/
/* If volume is full or adjust erase not set, don't increment. */
/*-------------------------------------------------------------------*/
if ((Flash->files_tbl->tbl[1].entry.comm.one_past_last.offset ||
!adjust_erase))
{
Flash->set_blocks = old_size;
return;
}
/*-------------------------------------------------------------------*/
/* Try to fill -1 slots with block numbers. */
/*-------------------------------------------------------------------*/
s_optimal = (Flash->set_blocks + 1) * 3 / 4;
for (s = 0; s < Flash->set_blocks; ++s)
if (!check_recycle || Flash->erase_set[s] == -1)
{
/*---------------------------------------------------------------*/
/* Choose the best block among the non-free ones. */
/*---------------------------------------------------------------*/
for (b = 0, max_f = -1; b < Flash->num_blocks; ++b)
{
/*-------------------------------------------------------------*/
/* If block is not bad, ctrl and has no free sects, candidate */
/*-------------------------------------------------------------*/
if (!Flash->blocks[b].bad_block &&
!Flash->blocks[b].ctrl_block &&
Flash->sect_tbl[(b + 1) * Flash->block_sects - 1].prev !=
FFREE_SECT)
{
/*-----------------------------------------------------------*/
/* Sanity check. */
/*-----------------------------------------------------------*/
PfAssert(Flash->high_wear >= Flash->blocks[b].wear_count);
/*-----------------------------------------------------------*/
/* Check that block is not in erase set. */
/*-----------------------------------------------------------*/
for (s1 = 0; s1 < Flash->set_blocks; ++s1)
if (Flash->erase_set[s1] == b)
break;
if (s1 == Flash->set_blocks)
{
/*---------------------------------------------------------*/
/* Compute the selector. */
/*---------------------------------------------------------*/
if (s < s_optimal)
f_b = (int)(16 * (Flash->block_sects -
Flash->blocks[b].used_sects) +
(Flash->high_wear - Flash->blocks[b].wear_count));
else
f_b = (int)(Flash->high_wear -Flash->blocks[b].wear_count);
/*---------------------------------------------------------*/
/* If better candidate, remember it. */
/*---------------------------------------------------------*/
if (max_f < f_b)
{
max_f = f_b;
max_b = b;
}
}
}
}
/*---------------------------------------------------------------*/
/* If no more replacement blocks, stop. */
/*---------------------------------------------------------------*/
if (max_f == -1)
break;
/*---------------------------------------------------------------*/
/* Add block to erase set. If recycle not possible afterwards, */
/* take block out and stop. */
/*---------------------------------------------------------------*/
Flash->erase_set[s] = max_b;
if (check_recycle && recycle_not_possible())
{
Flash->erase_set[s] = -1;
break;
}
}
/*-------------------------------------------------------------------*/
/* If there are still -1 entries in erase set, readjust set size. */
/*-------------------------------------------------------------------*/
while (Flash->erase_set[Flash->set_blocks - 1] == -1 &&
Flash->set_blocks > 1)
--Flash->set_blocks;
PfAssert(Flash->set_blocks >= old_size);
}
/***********************************************************************/
/* recycle_finish: Perform end of recycle - update sector table, */
/* write ctrl info, update sig bytes and wear count */
/* */
/* Inputs: check_full = flag to check for volume full */
/* write_ctrl = flag to write ctrl */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
static int recycle_finish(int check_full, int write_ctrl)
{
ui32 s, sect, i, old_set_size = Flash->set_blocks;
#if TIMING
clock_t sample = clock();
#endif
/*-------------------------------------------------------------------*/
/* Perform a sync now to save everything before erasing block if a */
/* sync is required. A sync is required on the last recycle in a */
/* contiguous set of recycles. */
/*-------------------------------------------------------------------*/
if (write_ctrl && FlashWrCtrl(SKIP_ADJUST_ERASE))
return -1;
#if TIMING
RecWrCtrl += (clock() - sample);
#endif
/*-------------------------------------------------------------------*/
/* Set all sectors in erase set back to free. */
/*-------------------------------------------------------------------*/
for (s = 0; s < Flash->set_blocks; ++s)
if (Flash->erase_set[s] != -1)
{
PfAssert(!Flash->blocks[Flash->erase_set[s]].ctrl_block);
sect = Flash->erase_set[s] * Flash->block_sects;
Flash->sect_tbl[Flash->last_free_sect].next =
(ui16)(sect + Flash->hdr_sects);
for (i = 0; i < Flash->block_sects; ++i, ++sect)
{
if (Flash->sect_tbl[sect].prev == FDRTY_SECT)
{
++Flash->free_sects;
Flash->sect_tbl[sect].prev = FFREE_SECT;
Flash->sect_tbl[sect].next = (ui16)(sect + 1);
}
else if (Flash->type == FFS_NOR)
{
PfAssert(Flash->sect_tbl[i].prev == FHDER_SECT);
}
else
{
PfAssert(FALSE); /*lint !e644 !e506 !e774 */
}
}
Flash->last_free_sect = sect - 1;
Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
}
/*-------------------------------------------------------------------*/
/* Do the last part of recycle: erase block, write signature bytes, */
/* and modify wear count, and check for volume full if needed. */
/*-------------------------------------------------------------------*/
if (erase_set((int)old_set_size) || (check_full && !FlashRoom(0)))
return -1;
/*-------------------------------------------------------------------*/
/* Choose the next erase set. */
/*-------------------------------------------------------------------*/
FlashChooseEraseSet(USE_WEAR);
for (;;)
{
/*-----------------------------------------------------------------*/
/* If recycles can proceed, we have a valid erase set. */
/*-----------------------------------------------------------------*/
if (!recycle_not_possible())
break;
/*-----------------------------------------------------------------*/
/* Attempt to select an erase set without looking at wear count. */
/*-----------------------------------------------------------------*/
FlashChooseEraseSet(IGNORE_WEAR);
/*-----------------------------------------------------------------*/
/* If recycles can proceed, we have a valid erase set. */
/*-----------------------------------------------------------------*/
if (Flash->set_blocks == 1 || !recycle_not_possible())
break;
/*-----------------------------------------------------------------*/
/* Shrink the erase set by one block. */
/*-----------------------------------------------------------------*/
Flash->erase_set[--Flash->set_blocks] = -1;
}
/*-------------------------------------------------------------------*/
/* Remember if control info was written. */
/*-------------------------------------------------------------------*/
Flash->wr_ctrl = write_ctrl;
#if TIMING
++RecCount;
#endif
return 0;
}
/***********************************************************************/
/* mark_ctrl_info: Clear header bit to mark recent control information */
/* */
/* Input: sector = start of most recent control information */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
static int mark_ctrl_info(uint sector)
{
uint byte_off, sect_off;
ui32 hdr_start, byte_addr;
FlashGlob *vol;
int status;
/*-------------------------------------------------------------------*/
/* The sector cannot be a header sector. */
/*-------------------------------------------------------------------*/
PfAssert((sector % Flash->block_sects) >= Flash->hdr_sects);
/*-------------------------------------------------------------------*/
/* Get pointer to the beginning of the header. */
/*-------------------------------------------------------------------*/
sect_off = sector % Flash->block_sects;
hdr_start = sector - sect_off;
/*-------------------------------------------------------------------*/
/* Figure out how far from the beginning of the header we are. */
/*-------------------------------------------------------------------*/
byte_off = sect_off / 8;
PfAssert(byte_off < Flash->hdr_sects * Flash->sect_sz);
/*-------------------------------------------------------------------*/
/* Calculate address of byte to write. */
/*-------------------------------------------------------------------*/
byte_addr = Flash->mem_base + hdr_start * Flash->sect_sz + byte_off;
/*-------------------------------------------------------------------*/
/* Release exclusive access to the flash file system. */
/*-------------------------------------------------------------------*/
vol = Flash;
semPost(FlashSem);
/*-------------------------------------------------------------------*/
/* Mark location of most recent control information. */
/*-------------------------------------------------------------------*/
status = vol->driver.nor.write_byte(byte_addr,
(ui8)~(1 << (7 - sect_off % 8)),
vol->vol);
/*-------------------------------------------------------------------*/
/* Acquire exclusive access to the flash file system. */
/*-------------------------------------------------------------------*/
semPend(FlashSem, WAIT_FOREVER);
Flash = vol;
if (status)
{
set_errno(EIO);
return -1;
}
return 0;
}
/***********************************************************************/
/* get_next_used_sector: Look for the next non_dirty_sector */
/* */
/* Inputs: sector = sector past which to find used sector */
/* sp = index in erase_set to current block */
/* */
/* Returns: Pointer to the next sector, or -1 when done */
/* */
/***********************************************************************/
static uint get_next_used_sector(uint sector, int *sp)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -