?? tfs_with_appexit_support.c
字號:
}/* tfsclean(): Defragment the file system. During defragmentation, continually save enough state so that this function may be interrupted by a reset or power hit and can recover from it. Requires that one of the largest sectors of the flash device be designated as a SPARE sector, to be used only by defragmentation. Defragmentation state is stored at the end of the last TFS sector, so it is maintained across reset/powerhit also. Use of the SPARE sector and flash-based defragmentation state eliminates the vulnerability of the TFS being corrupted if the system is reset during defragmentation. It also eliminates the need for a large amount of RAM space (as was needed in earlier versions of tfsclean()). The function is designed to be entered at various points of the defragmentation process. If defragmentation is starting from scratch, then all arguments (except verbose) will be zero. If filtot is non-zero on entry, then this means that tfsclean() must pick up from a previously started defragmentation and cannot assume that a sane file system currently exists.*/static ulong *DefragStateTbl;#define DEFRAG_TEST_ENABLED 0#if DEFRAG_TEST_ENABLEDint ExitPoint, ExitSector;#define TEST_EXIT_POINT(pt,sno) \ if (ExitPoint == pt) { \ if ((ExitSector == sno) || (sno == -1)) { \ printf("!!!!!!!!!!!!! TestExit at point %d, sector %d\n",pt,sno); \ return(1); \ } \ }#else#define TEST_EXIT_POINT(pt,sno)#endifstatic inttfsclean(filtot,tbl1,tbl2,snum,resetwhendone,verbose)int filtot, verbose, snum, resetwhendone;ulong *tbl1;struct defraghdr *tbl2;{ int rslt; rslt = _tfsclean(filtot,tbl1,tbl2,snum,resetwhendone,verbose); return(rslt);}static int_tfsclean(filtot,tbl1,tbl2,snum,resetwhendone,verbose)int filtot, verbose, snum, resetwhendone;ulong *tbl1;struct defraghdr *tbl2;{ int ftot, fcnt, fsize, dtot, sparesnum, sparesize, ssize; int firsttfssector, lasttfssector, sectorcheck; int tfssector, sidx, dummy; char *newaddress, *sbase, *firstdeadfile; struct tfshdr *tfp; struct defraghdr *defraghdrtbl, *dp, defrag; ulong *lp, *lp1; if (verbose > 1) { printf("tfsclean(%d,0x%x,0x%x,%d,%d,%d)\n", filtot,tbl1,tbl2,snum,resetwhendone,verbose); } /* Do some initial configuration retrieval... */ /* Determine the first and last sector within TFS... */ if (addrtosector(TFSSTART,&firsttfssector,&ssize,&sbase) < 0) return(TFSERR_MEMFAIL); lasttfssector = firsttfssector + TFSSECTORCOUNT - 1; if (addrtosector(TFSEND,§orcheck,0,0) < 0) return(TFSERR_MEMFAIL); if (lasttfssector != sectorcheck) { printf("TFS SECTORCOUNT does not match TFSSTART <-> TFSEND\n"); printf("First TFS sector = %d\n",firsttfssector); printf("Last TFS sector = %d\n",sectorcheck); return(TFSERR_MEMFAIL); } /* Store away information about spare sector... */ if (addrtosector(TFSSPARE,&sparesnum,&sparesize,0) < 0) return(TFSERR_MEMFAIL); if (filtot) { sidx = snum; ftot = filtot; defraghdrtbl = tbl2; DefragStateTbl = tbl1; tfssector = firsttfssector+snum; printf("Continuing defragmentation at sector %3d ",tfssector); printf("(state=%s)...\n",tfsdefragmsg(DefragStateTbl[snum])); if (sectortoaddr(tfssector,&ssize,&sbase) == -1) return(TFSERR_MEMFAIL); switch(DefragStateTbl[snum]) { case BUILDING_HEADER_TABLE: goto building_hdr; case HEADER_TABLE_READY: goto hdr_table_ready; case COPY_HDRS_TO_SPARE: goto copy_hdrs_to_spare; case HDRS_IN_SPARE: goto hdrs_in_spare; case LASTSECTOR_IN_SPARE: goto lastsector_in_spare; case SECTOR_COPIED_TO_SPARE: goto sector_copied_to_spare; case SECTOR_UPDATE_STARTED: goto sector_update_started; case SECTOR_UPDATE_COMPLETE: goto sector_update_complete; case SECTOR_DEFRAG_COMPLETE: goto sector_defrag_complete; case ERASING_DEAD_SECTOR: goto erasing_dead_sector; case ERASED_DEAD_SECTOR: goto erased_dead_sector; case ERASING_LAST_SECTOR: goto erasing_last_sector; default: return(TFSERR_BADARG); } } /* Determine how many "live" files exist so that we can determine */ /* where to start building the defragstate[] and defraghdrtbl[] tables. */ tfp = (struct tfshdr *)TFSSTART; ftot = dtot = 0; while(validtfshdr(tfp)) { if (tfp->flags) ftot++; else dtot++; tfp = nextfp(tfp); } /* If dtot is 0, then all TFS file headers indicate that there is no */ /* need to clean up the flash. There is still a chance that the flash */ /* (after the end of the last file in TFS) may not be erased, so check */ /* for that also... */ if (dtot == 0) { printf("No dead files detected.\n"); if (tfsflasherased(1)) return(0); else printf("Running defrag to cleanup...\n"); } /* If ftot is 0, then there are no valid files in the flash, so simply */ /* erase all TFS flash space and return... */ if (ftot == 0) { printf("No active files detected, erasing all TFS flash...\n"); tfsinit(); return(0); } printf("%s with %d dead file%s (%d bytes) removed.\n", "Defragmenting file system",dtot,dtot>1 ? "s":"",tfsmemdead()); DefragStateTbl = (ulong *)(TFSEND+1); DefragStateTbl -= TFSSECTORCOUNT; defraghdrtbl = (struct defraghdr *)(DefragStateTbl) - ftot; /* Verify that the space to be written to for the */ /* defrag stuff is erased... */ lp = (ulong *)defraghdrtbl; while(lp < (ulong *)TFSEND) { if (*lp++ != (ulong)ERASED32) { printf("Defragmentation table space (0x%x-0x%x) not erased.\n", defraghdrtbl,TFSEND); return(TFSERR_FLASHFAILURE); } } TEST_EXIT_POINT(1,-1); /* Erase SPARE sector. */ if (tfsflasherase(sparesnum) < 0) { printf("Flash SPARE sector erase failed\n"); return(TFSERR_FLASHFAILURE); } TEST_EXIT_POINT(2,-1); if (verbose > 2) { printf("Building defrag header for %d files...\n",ftot); printf("DefragStateTbl=0x%x\n",DefragStateTbl); printf("defraghdrtbl=0x%x\n",defraghdrtbl); } /* Mark the defragmentation state table to indicate that we are */ /* about to begin defragmentation. */ if (setdefragstate(0,BUILDING_HEADER_TABLE,verbose) != TFS_OKAY) return(TFSERR_FLASHFAILURE);building_hdr: firstdeadfile = (char *)0; tfp = (struct tfshdr *)TFSSTART; while(validtfshdr(tfp)) { if (!tfp->flags) { firstdeadfile = (char *)tfp; break; } tfp = nextfp(tfp); } tfp = (struct tfshdr *)TFSSTART; newaddress = (char *)TFSSTART; fcnt = 0; if (verbose > 2) printf("\nDEFRAGMETATION HEADER DATA:\n"); while(validtfshdr(tfp)) { if (tfp->flags) { uchar *base, *eof; int size, slot; struct tfsdat *slotptr; defrag.fhdr = *tfp; if (addrtosector(tfp,&defrag.bsn,0,&base) < 0) return(TFSERR_MEMFAIL); defrag.bso = (uchar *)tfp - base; eof = (uchar *)(tfp+1)+TFS_SIZE(tfp)-1; if (addrtosector(eof,&defrag.esn,0,&base) < 0) return(TFSERR_MEMFAIL); defrag.fdf = firstdeadfile; defrag.eso = eof - base + 1; defrag.nda = newaddress; /* If the file is currently opened, adjust the base address. */ slotptr = fileslots; for (slot=0;slot<TFS_MAXOPEN;slot++,slotptr++) { if (slotptr->offset != -1) { if (slotptr->base == (uchar *)(TFS_BASE(tfp))) { slotptr->base = (uchar *)(newaddress+TFSHDRSIZ); if (verbose) printf("Base of opened file '%s' shifted from 0x%x to 0x%x\n", TFS_NAME(tfp),TFS_BASE(tfp),slotptr->base); } } } if (verbose > 2) { printf(" File %s:\n",TFS_NAME(tfp)); printf(" bsn=%d, bso=0x%08x,",defrag.bsn,defrag.bso); printf(" esn=%d, eso=0x%08x,",defrag.esn,defrag.eso); printf(" nda=0x%08x, fdf=0x%08x\n",defrag.nda,defrag.fdf); } size = TFS_SIZE(tfp) + TFSHDRSIZ; if (size & 0xf) { size += 16; size &= ~0xf; } newaddress += size; defrag.fhdr.next = (struct tfshdr *)newaddress; if (tfsflashwrite(&defraghdrtbl[fcnt],&defrag,DEFRAGHDRSIZ) == -1) { printf("Flash write failed during header build\n"); return(TFSERR_FLASHFAILURE); } fcnt++; TEST_EXIT_POINT(3,-1); } tfp = nextfp(tfp); } if (fcnt != ftot) printf("\007 fcnt != ftot!\n"); TEST_EXIT_POINT(4,-1); /* Mark the defragmentation state table to indicate that the */ /* defragmentation headers have been constructed. */ if (setdefragstate(0,HEADER_TABLE_READY,verbose) != TFS_OKAY) return(TFSERR_FLASHFAILURE);hdr_table_ready: /* For each sector dedicated to TFS, do the following... */ if (verbose) { if (verbose > 1) printf("\nPER-SECTOR DEFRAGMENTATION STEPS:\n"); printf("Defragmenting sectors %d - %d...\n", firsttfssector,lasttfssector); } sidx = 0; for(tfssector=firsttfssector;tfssector<=lasttfssector;tfssector++,sidx++) { if (verbose) { printf(" Sector %3d (base=0x%x, size=%d)...\n", tfssector,sbase,ssize); } /* If the current sector is prior to the first sector that contains */ /* a file that has been removed, then this sector will not change, */ /* so we can skip over it... */ dp = defraghdrtbl; if (dp->fdf > sbase+ssize) { if (verbose > 2) printf(" no change",dp->fdf,sbase,ssize); if (verbose > 3) printf(" (0x%x > 0x%x+0x%x",dp->fdf,sbase,ssize); if (verbose > 2) printf(".\n"); goto sector_defrag_skip; } /* Look to see if this sector has any valid file data in it. */ /* If not, continue with next sector. */ dp = defraghdrtbl; while (dp < (struct defraghdr *)DefragStateTbl) { if ((tfssector >= dp->bsn) && (tfssector <= dp->esn)) break; dp++; } if (dp >= (struct defraghdr *)DefragStateTbl) { TEST_EXIT_POINT(5,tfssector); if (setdefragstate(sidx,ERASING_DEAD_SECTOR,verbose) != TFS_OKAY) return(TFSERR_FLASHFAILURE);erasing_dead_sector: TEST_EXIT_POINT(6,tfssector); /* Erase the sector within valid TFS space, then update state. */ if (tfsflasherase(tfssector) < 0) { printf("Flash sector erase (%d) failed\n",tfssector); return(TFSERR_FLASHFAILURE); } TEST_EXIT_POINT(7,tfssector); if (setdefragstate(sidx,ERASED_DEAD_SECTOR,verbose) != TFS_OKAY) return(TFSERR_FLASHFAILURE); TEST_EXIT_POINT(8,tfssector);erased_dead_sector: sbase += ssize; if (addrtosector(sbase,0,&ssize,0) < 0) return(TFSERR_MEMFAIL); continue; } /* If this is the last sector of TFS, then we must copy the defrag */ /* tables to the end of the SPARE sector (recall that the defrag */ /* tables are stored in the last TFS sector). */ if (tfssector == lasttfssector) { ulong *newdefragstatetbl; struct defraghdr *newdefraghdrtbl; TEST_EXIT_POINT(9,tfssector); if (setdefragstate(sidx,COPY_HDRS_TO_SPARE,verbose) != TFS_OKAY) return(TFSERR_FLASHFAILURE); TEST_EXIT_POINT(10,tfssector);copy_hdrs_to_spare: newdefragstatetbl = (ulong *)(TFSSPARE+sparesize); newdefragstatetbl -= TFSSECTORCOUNT; newdefraghdrtbl = (struct defraghdr *)(newdefragstatetbl) - ftot; /* Copy defrag tables to end of SPARE sector... */ if (tfsflashwrite(newdefraghdrtbl,defraghdrtbl, TFSEND-(int)defraghdrtbl+1) < 0) { printf("Flash defraghdrtbl write failed\n",tfssector); return(TFSERR_FLASHFAILURE); } DefragStateTbl = (ulong *)(TFSSPARE+sparesize); DefragStateTbl -= TFSSECTORCOUNT; TEST_EXIT_POINT(11,tfssector); if (setdefragstate(sidx,HDRS_IN_SPARE,verbose)!=TFS_OKAY) return(TFSERR_FLASHFAILURE);hdrs_in_spare: DefragStateTbl = (ulong *)(TFSSPARE+sparesize); DefragStateTbl -= TFSSECTORCOUNT; TEST_EXIT_POINT(12,tfssector); /* Copy remainder of last TFS sector to SPARE... */ if (tfsflashwrite(TFSSPARE,sbase, ssize-(TFSEND-(int)defraghdrtbl+1)) < 0) { printf("Flash final sector (%d) copy failed\n",tfssector); return(TFSERR_FLASHFAILURE); } TEST_EXIT_POINT(13,tfssector); if (setdefragstate(sidx,LASTSECTOR_IN_SPARE,verbose)!=TFS_OKAY) return(TFSERR_FLASHFAILURE);lastsector_in_spare: defraghdrtbl = (struct defraghdr *)(DefragStateTbl) - ftot;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -