📄 tfsclean.c
字号:
if (verbose > 1) {
printf(" Middleof_copy (nda offset=0x%x, size=%d",
offset,ssize);
if (phc)
printf(", phc=0x%x)\n",phc);
else
printf(")\n");
}
TEST_EXIT_POINT(39,tfssector);
/* On the first "middle-of-file" copy, if a PHC is active,
* then we don't copy a full sector (because the remaining
* portion of the header was copied in earlier). We use
* the TFS_PHCDONE bit to indicate that this is the first
* middle-of-file copy in a phc condition...
*/
if (phc && (PHC_IS_COPIED(dp->phc))) {
ulong phctmp;
if (tfsflashwrite((ulong *)(dp->nda+offset+phc),
(ulong *)(tdp->spare+phc),ssize-phc) == -1) {
printf("Sector-update8 (dp=0x%lx) failed\n",(ulong)dp);
return(TFSERR_FLASHFAILURE);
}
phctmp = SET_PHC_DONE(dp->phc);
if (tfsflashwrite(&dp->phc,&phctmp,sizeof(int)) == -1) {
printf("Phc clear2 (dp=0x%lx) failed\n",(ulong)dp);
return(TFSERR_FLASHFAILURE);
}
}
else {
if (tfsflashwrite((ulong *)(dp->nda+offset),
(ulong *)(tdp->spare),ssize) == -1) {
printf("Sector-update9 (dp=0x%lx) failed\n",(ulong)dp);
return(TFSERR_FLASHFAILURE);
}
}
TEST_EXIT_POINT(30,tfssector);
}
dp++;
}
TEST_EXIT_POINT(31,tfssector);
if (setdefragstate(sidx,SECTOR_UPDATE_COMPLETE,verbose)!=TFS_OKAY)
return(TFSERR_FLASHFAILURE);
TEST_EXIT_POINT(32,tfssector);
sector_update_complete:
/* Erase the SPARE sector, then update state. */
if (tfssector != lasttfssector) {
if (tfsflasherase(sparesnum) < 0) {
printf("Flash SPARE sector erase failed\n");
return(TFSERR_FLASHFAILURE);
}
TEST_EXIT_POINT(33,tfssector);
}
TEST_EXIT_POINT(34,tfssector);
sector_defrag_skip:
if (setdefragstate(sidx,SECTOR_DEFRAG_COMPLETE,verbose)!=TFS_OKAY)
return(TFSERR_FLASHFAILURE);
sector_defrag_complete:
sbase += ssize;
if (addrtosector(sbase,0,&ssize,0) < 0)
return(TFSERR_MEMFAIL);
}
/* If the last file copy did not enter the last file sector,
* then erase the last tfssector...
*/
if (sectortoaddr(lasttfssector,0,(unsigned char **)&sbase) < 0)
return(TFSERR_MEMFAIL);
dp = (struct defraghdr *)DefragStateTbl - 1;
if ((dp->nda + dp->fhdr.filsize + TFSHDRSIZ) < sbase) {
/* Must use spare sector to record this state because this is
* the same sector that we were using to keep track of state.
*/
DefragStateTbl = (ulong *)(tdp->spare + tdp->sparesize - 4);
if (setdefragstate(0,ERASING_LAST_SECTOR,verbose)!=TFS_OKAY)
return(TFSERR_FLASHFAILURE);
TEST_EXIT_POINT(35,-1);
erasing_last_sector:
if (tfsflasherase(lasttfssector) < 0) {
printf("Final sector erase (%d) failed\n",lasttfssector);
return(TFSERR_FLASHFAILURE);
}
TEST_EXIT_POINT(36,-1);
}
/* All defragmentation is done, so verify sanity of files... */
chkstat = tfscheck(tdp,verbose);
TEST_EXIT_POINT(37,-1);
/* Erase spare sector... */
if (tfsflasherase(sparesnum) < 0) {
printf("Final spare sector (%d) failed\n",sparesnum);
return(TFSERR_FLASHFAILURE);
}
/* If resetwhendone flag is set, then reset here; else return result of
* the file system check.
*/
if (resetwhendone)
monrestart(INITIALIZE);
return(chkstat);
}
/* tfsclean():
* Wrapper for tfsclean so that we can enable a call to appexit() if there
* is an error returned by tfsclean(). This is used for testing TFS...
* If a script is running to try to cause tfsclean to break, then we want
* it to halt if tfsclean does return an error.
*/
int
tfsclean(int filtot,ulong *tbl1,struct defraghdr *tbl2,int snum,
TDEV *tdp,int rwd,int verbose)
{
extern void appexit(int);
int cleanresult;
cleanresult = _tfsclean(filtot,tbl1,tbl2,snum,tdp,rwd,verbose);
if (cleanresult != TFS_OKAY) {
if (getenv("APP_EXITONCLEANERROR"))
appexit(0);
if (getenv("SCR_EXITONCLEANERROR"))
ScriptExitFlag = EXIT_SCRIPT;
}
return(cleanresult);
}
/* tfsfixup():
* See if a defragmentation was in progress. If yes, finish it; else
* return.
* If 'dontquery' is set, then we won't query the user even on the first
* pass.
*/
int
tfsfixup(int verbose, int dontquery)
{
struct defraghdr *dfhp;
TFILE thdr, *tfp;
ulong *statetbl, *spare_statetbl;
int ftot, i, tfssector, snum, query;
TDEV *tdp;
#if DEFRAG_TEST_ENABLED
ExitPoint=0;
ExitSector=0;
#endif
query = dontquery;
for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
/* Set statetbl to point to what would be the first TFS sector's
* state information bitfield (if defrag were in progress).
*/
statetbl = (ulong *)(tdp->end+1);
statetbl -= tdp->sectorcount;
/* Set spare_statetbl to point to the last 'long' in spare sector. */
spare_statetbl = (ulong *)(tdp->spare + tdp->sparesize) - 1;
/* Check the end of the TFS space to see if a state table exists,
* and also check to see if the last location in the spare sector
* contains state. If neither, then defragmentation was not in
* progress so just return here.
*/
if ((*statetbl == (ulong)ERASED32) &&
(*spare_statetbl == (ulong)ERASED32)) {
continue;
}
/* Allow the user to break out of the automatic cleanup... */
if (!query) {
if (pollConsole("TFS auto-cleanup?"))
return(0);
query = 1;
}
if (addrtosector((char *)tdp->start,&tfssector,0,0) < 0)
return(TFSERR_MEMFAIL);
/* Maybe only the last sector (and spare) needs to be erased...
* This means that all the files are up-to-date, but the
* final stages of sector cleanup didn't finish.
* This messiness is caused by the fact that the defragmentation
* could have been interrupted when it was erasing the same sector
* that it was storing state in. For this sector, the defragmentor
* uses the spare sector to store state.
*/
if (*spare_statetbl == ERASING_LAST_SECTOR) {
spare_statetbl -= (tdp->sectorcount-1);
tfsclean(1,spare_statetbl,0,tdp->sectorcount-1,tdp,0,verbose);
continue;
}
if (verbose)
printf("Device %s fixup in progress\n",tdp->prefix);
if (*statetbl == (ulong)ERASED32) {
statetbl = (ulong *)(tdp->spare + tdp->sparesize);
statetbl -= tdp->sectorcount;
}
dfhp = (struct defraghdr *)statetbl - 1;
if (*statetbl == (ulong)BUILDING_HEADER_TABLE) {
ftot = 0;
tfp = (TFILE *) tdp->start;
while(validtfshdr(tfp)) {
if (TFS_FILEEXISTS(tfp)) {
ftot++;
dfhp--;
}
tfp = nextfp(tfp,tdp);
}
tfsclean(ftot,statetbl,dfhp,0,tdp,0,verbose);
continue;
}
ftot = 0;
while(1) {
if (dfhp->fhdr.hdrsize == ERASED16)
break;
thdr = dfhp->fhdr;
thdr.next = 0;
thdr.hdrcrc = 0;
if (crc32((uchar *)&thdr,TFSHDRSIZ) != dfhp->fhdr.hdrcrc)
break;
ftot++;
dfhp--;
}
dfhp++;
/* If ftot is zero, then we are fixing up an empty file system that
* was in the process of being defragmented, so just erase all
* sectors and be done...
*/
if (ftot == 0) {
if (verbose)
printf("Cleaning up empty device...\n");
if (tfsflasheraseall(tdp) < 0)
printf("Device erase-all failed\n");
continue;
}
if (verbose)
printf("%d files being defragmented\n",ftot);
snum = -1;
/* Find currently active sector by stepping through the state table
* until SECTOR_DEFRAG_INACTIVE state is detected, then step back 1.
*/
for(i=0;i<(int)tdp->sectorcount;i++) {
if (verbose > 1) {
printf("TFS Sector %d state: 0x%lx (%s)\n",
tfssector+i, (ulong)(statetbl[i]),
tfsdefragmsg(statetbl[i]));
}
if ((snum == -1) && (statetbl[i] == SECTOR_DEFRAG_INACTIVE))
snum = i-1;
}
if (snum == -1) {
printf("*****Starting at last sector\n");
snum = tdp->sectorcount-1;
if (statetbl[snum] == COPY_HDRS_TO_SPARE) {
spare_statetbl = (ulong *)(tdp->spare + tdp->sparesize) - 1;
if ((*spare_statetbl == HDRS_IN_SPARE) ||
(*spare_statetbl == LASTSECTOR_IN_SPARE)) {
printf("Adjusting statetbl from 0x%lx to 0x%lx\n",
(ulong)statetbl,
(ulong)(spare_statetbl - (tdp->sectorcount-1)));
statetbl = spare_statetbl - (tdp->sectorcount-1);
}
}
}
if (verbose > 1)
printf("Defrag restart at TFS sector %d\n",tfssector+snum);
tfsclean(ftot,statetbl,dfhp,snum,tdp,0,verbose);
}
return(0);
}
#else
int
tfsfixup(int verbose, int dontquery)
{
return(TFSERR_NOTAVAILABLE);
}
/* tfsclean():
* This is an alternative to the complicated defragmentation above.
* It simply scans through the file list and copies all valid files
* to RAM; then flash is erased and the RAM is copied back to flash.
* <<< WARNING >>>
* THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY
* ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE.
*/
int
tfsclean(int filtot,ulong *tbl1,struct defraghdr *tbl2,int snum,
TDEV *tdp,int rwd,int verbose)
{
extern ulong APPLICATION_RAMSTART;
TFILE *tfp;
uchar *tbuf;
int dtot, nfadd, len, err;
/* Determine how many "dead" files exist. */
dtot = 0;
tfp = (TFILE *)tdp->start;
while(validtfshdr(tfp)) {
if (!TFS_FILEEXISTS(tfp))
dtot++;
tfp = nextfp(tfp,tdp);
}
if (dtot == 0)
return(TFS_OKAY);
printf("Reconstructing device %s with %d dead file%s removed...\n",
tdp->prefix, dtot,dtot>1 ? "s":"");
tbuf = (char *)APPLICATION_RAMSTART;
tfp = (TFILE *)(tdp->start);
nfadd = tdp->start;
while(validtfshdr(tfp)) {
if (TFS_FILEEXISTS(tfp)) {
len = TFS_SIZE(tfp) + sizeof(struct tfshdr);
if (len % TFS_FSIZEMOD)
len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD);
nfadd += len;
err = tfsmemcpy(tbuf,(uchar *)tfp,len,0,0);
if (err != TFS_OKAY)
return(err);
((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd;
tbuf += len;
}
tfp = nextfp(tfp,tdp);
}
/* Erase the flash device: */
err = _tfsinit(tdp);
if (err != TFS_OKAY)
return(err);
/* Copy data placed in RAM back to flash: */
err = AppFlashWrite((ulong *)(tdp->start),(ulong *)APPLICATION_RAMSTART,
(tbuf-(uchar*)APPLICATION_RAMSTART));
if (err < 0)
return(TFSERR_FLASHFAILURE);
return(TFS_OKAY);
}
#endif /* INCLUDE_TFS */
/* If INCLUDE_TFSCLEAN is not defined, then we do not want to do any
* automatic cleanup of the flash...
*/
int
tfsautoclean(int filtot,ulong *tbl1,struct defraghdr *tbl2,int snum,
TDEV *tdp,int rwd,int verbose)
{
#if INCLUDE_TFSCLEAN
return(_tfsclean(filtot,tbl1,tbl2,snum,tdp,rwd,verbose));
#else
return(TFSERR_NOTAVAILABLE);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -