📄 tfsclean.c
字号:
*last = -1; sbase = (uchar *)tdp->start; crctbl = defragCrcTable(tdp); dhp = (struct defraghdr *)crctbl - 1; ftot = dhp->idx + 1; printf("TFS: calculating per-sector crcs... "); for(i=0;i<tdp->sectorcount;i++) { addrtosector(sbase,&snum,&ssize,0); if (i == tdp->sectorcount - 1) { ssize -= /* CRC table */ (tdp->sectorcount * sizeof(struct sectorcrc)); ssize -= (ftot * DEFRAGHDRSIZ); /* DHT table */ ssize -= 4; /* Crc of the tables */ } if (crc32(sbase,ssize) != crctbl[i].precrc) { if (*first == -1) *first = snum; *last = snum; } sbase += ssize; defragTick(0); } printf("done\n"); return;}/* defragPostCrcCheck(): * Return 1 if the post-crc check of the incoming sector number passes; * else 0. */intdefragPostCrcCheck(TDEV *tdp, int isnum){ uchar *sbase; struct defraghdr *dhp; struct sectorcrc *crctbl; int ftot, i, snum, ssize, lastsnum, lastssize; sbase = (uchar *)tdp->start; crctbl = defragCrcTable(tdp); dhp = (struct defraghdr *)crctbl - 1; ftot = dhp->idx + 1; addrtosector((uchar *)tdp->end,&lastsnum,&lastssize,0); for(i=0;i<tdp->sectorcount;i++) { addrtosector(sbase,&snum,&ssize,0); if (snum == isnum) break; sbase += ssize; } if (isnum == lastsnum) { ssize -= (tdp->sectorcount * sizeof(struct sectorcrc)); ssize -= (ftot * DEFRAGHDRSIZ); ssize -= 4; } if (crctbl[i].postcrc == crc32(sbase,ssize)) return(1); else return(0);}/* defragGetStateStr(): * Return a string that corresponds to the incoming state value. */static char *defragGetStateStr(int state){ char *str; switch(state) { case SECTOR_DEFRAG_INACTIVE: str = "SectorDefragInactive"; break; case SECTOR_DEFRAG_ABORT_RESTART: str = "DefragRestartAborted"; break; case SCANNING_ACTIVE_SECTOR_1: str = "ScanningActiveSector1"; break; case SCANNING_ACTIVE_SECTOR_2: str = "ScanningActiveSector2"; break; case SCANNING_ACTIVE_SECTOR_3: str = "ScanningActiveSector3"; break; case SCANNING_ACTIVE_SECTOR_4: str = "ScanningActiveSector4"; break; case SCANNING_ACTIVE_SECTOR_5: str = "ScanningActiveSector5"; break; case SECTOR_DEFRAG_ALMOST_DONE: str = "DefragAlmostDone"; break; default: str = "???"; break; } return(str);}/* defragRestart(): * Poll the console allowing the user to abort the auto-restart of * the defragmentation. If a character is received on the console, * then return 0 indicating that the defrag should not be restarted; * else return 1. */intdefragRestart(int state,int snum){ printf("TFS defrag restart state: %s sector %d\n", defragGetStateStr(state),snum); if (pollConsole("Hit any key to abort...")) return(0); return(1);}/* defragGetState(): * Step through the files in the specified device and check for * sanity. Return 1 if the conclusion is that we are in the middle * of a defragmentation; else 0. */static intdefragGetState(TDEV *tdp, int *activesnum){ TFILE *tfp; struct defraghdr *dhp; struct sectorcrc *crctbl; int snum_in_spare, firstsnum; int first_touched_snum, last_touched_snum; int break_cause, break1_cause, spare_is_erased, ftot, ftot1, errstate; /* Establish state of spare sector: */ spare_is_erased = flasherased((uchar *)tdp->spare, (uchar *)tdp->spare+tdp->sparesize); ftot = 0; break_cause = break1_cause = 0; for(tfp=(TFILE *)tdp->start; tfp < (TFILE *)tdp->end; tfp=tfp->next) { /* If we are legally at the end of file storage space, then we * will hit a header size that is ERASED16. If we reach this * point and the remaining space dedicated to file storage is * erased and the spare is erased, it is safe to assume that we * were not in the middle of a defrag. */ if (tfp->hdrsize == ERASED16) { /* Is space from last file to end of TFS space erased? */ if (!flasherased((uchar *)tfp,(uchar *)tdp->end)) { break_cause = 1; break; } if (!spare_is_erased) { break_cause = 2; break; }#if DEFRAG_TEST_ENABLED printf("\ndefragGetState: inactive_1\n");#endif return(SECTOR_DEFRAG_INACTIVE); } /* If the crc32 of the header is corrupt, or if the next pointer * doesn't make any sense, then we must assume that a defrag * was in progress... */ if (tfshdrcrc(tfp) != tfp->hdrcrc) { break; } if (!(tfp->next) || (tfp->next <= (TFILE *)tdp->start) || (tfp->next >= (TFILE *)tdp->end)) { break; } if (TFS_FILEEXISTS(tfp)) ftot++; } /* If we are here, then something is not "perfect" with the flash * space used by TFS. If break_cause is non-zero, there is a chance * that the only problem is that a file-write was interrupted and * we did not actually interrupt an in-progress-defrag. An interrupted * file write would place some incomplete data after the last file. */ ftot1 = defragValidDSI(tdp,&crctbl); /* If we don't have valid defrag state info (DSI), then we can assume * that the files in TFS have not yet been touched (since if we had * touched them, we would have already successfully created the DSI). * This being the case, then we will not continue with any defrag, * let TFS clean things up when the space is needed. */ if (!ftot1) { if (break_cause) { /* Hmmm... Should something be done here? */ }#if DEFRAG_TEST_ENABLED printf("\ndefragGetState: inactive_2\n");#endif return(SECTOR_DEFRAG_INACTIVE); } /* If we get here, then we have a valid defrag header table, so we * can use it and the state of each of the sectors to figure out * where we are in the defragmentation process. We need to determine * which sector was being worked on at the point in time when the * defragmentation was interrupted. A sector is in the "touched" * state if a crc32 on its content does not match the crc32 stored * in the crc table above the defrag header table. * * Here we step through the defrag header table and see if each file * in the header table exists in TFS. If all files exist, then we * must have been very close to completion of the defrag process. */ printf("TFS: scanning DSI space... "); dhp = (struct defraghdr *)crctbl - ftot1; while(dhp < (struct defraghdr *)crctbl) { tfp = (TFILE *)dhp->nda; if (tfp->hdrcrc != dhp->ohdrcrc) break; if (tfshdrcrc(tfp) != tfp->hdrcrc) { break1_cause = 1; break; } if (crc32((uchar *)(tfp+1),tfp->filsize) != tfp->filcrc) { break1_cause = 2; break; } dhp++; defragTick(0); } printf("done\n"); /* If we stepped through the entire table, then we've completed the * file relocation process, but we still have to clean up... */ if (dhp >= (struct defraghdr *)crctbl) { if (defragRestart(SECTOR_DEFRAG_ALMOST_DONE,0)) { return(SECTOR_DEFRAG_ALMOST_DONE); } else { return(SECTOR_DEFRAG_ABORT_RESTART); } } if (addrtosector((char *)tdp->start,&firstsnum,0,0) < 0) { errstate = 50; goto state_error; } defragTouchedSectors(tdp,&first_touched_snum,&last_touched_snum); /* If there are no touched sectors, then we will not continue with * the defrag because we didn't start relocation of any of the files * yet. */ if (first_touched_snum == -1) {#if DEFRAG_TEST_ENABLED printf("\ndefragGetState: inactive_3\n");#endif return(SECTOR_DEFRAG_INACTIVE); } if (spare_is_erased) snum_in_spare = -1; else snum_in_spare = defragSectorInSpare(tdp,crctbl);#if DEFRAG_TEST_ENABLED printf("\ndefragGetState info: %d %d %d\n", first_touched_snum, last_touched_snum, snum_in_spare);#endif /* At this point we know what sector was the last to be touched. * What we don't know is whether or not the "touch" was completed. * So we don't know if the active sector is last_touched_snum or * last_touched_snum+1. * The only useful piece of data we 'might' have is the fact that * the spare may contain the content of the last touched sector. */ /* If the spare is erased, it may be because defrag was just getting * ready to start working on the next sector (meaning that the active * sector is last_touched_snum+1) or the sector was in the process of * being modified. We use the post-crc in the DHT to determine what * the active sector is... */ if (spare_is_erased) { if (last_touched_snum >= 0) { if (defragPostCrcCheck(tdp,last_touched_snum)) { *activesnum = last_touched_snum + 1; if (defragRestart(SCANNING_ACTIVE_SECTOR_1,*activesnum)) return(SCANNING_ACTIVE_SECTOR_1); else return(SECTOR_DEFRAG_ABORT_RESTART); } else { if (defragSerase(2,last_touched_snum) < 0) { errstate = 51; goto state_error; } *activesnum = last_touched_snum; if (defragRestart(SCANNING_ACTIVE_SECTOR_2,*activesnum)) return(SCANNING_ACTIVE_SECTOR_2); else return(SECTOR_DEFRAG_ABORT_RESTART); } } else { errstate = 52; goto state_error; } } /* If the sector copied to spare is one greater than the last touched * sector, then the active sector is last_touched_snum+1 and it was * just copied to the spare. In this case we erase the spare and * return indicating the active sector. */ if (snum_in_spare == last_touched_snum+1) { if (defragEraseSpare(tdp) < 0) { errstate = 53; goto state_error; } *activesnum = snum_in_spare; if (defragRestart(SCANNING_ACTIVE_SECTOR_3,*activesnum)) return(SCANNING_ACTIVE_SECTOR_3); else return(SECTOR_DEFRAG_ABORT_RESTART); } /* If the spare is not erased, but it does not match any of the * sector CRCs, then we must have been in the process of copying * the active sector to the spare, so we can erase it and return * to the SCANNING_ACTIVE_SECTOR state. */ if (snum_in_spare == -1) { if (last_touched_snum >= 0) { *activesnum = last_touched_snum + 1; if (!defragRestart(SCANNING_ACTIVE_SECTOR_4,*activesnum)) return(SECTOR_DEFRAG_ABORT_RESTART); if (defragEraseSpare(tdp) < 0) { errstate = 54; goto state_error; } return(SCANNING_ACTIVE_SECTOR_4); } else { errstate = 55; goto state_error; } } /* If the sector copied to spare is the number of the last touched * sector, then we were in the middle of modifying the sector, so * we have to erase that sector, copy the spare to it and return * to the scanning state. */ if (snum_in_spare == last_touched_snum) { int ssize; uchar *sbase; *activesnum = snum_in_spare; if (!defragRestart(SCANNING_ACTIVE_SECTOR_5,*activesnum)) return(SECTOR_DEFRAG_ABORT_RESTART); if (defragSerase(3,snum_in_spare) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -