📄 tfsclean.c
字号:
if (new_fspan == SPANTYPE_BPEP) continue; else if (new_fspan == SPANTYPE_BLEL) break; /* Now retrieve span information about header and data * portions of the file (new and orig)... */ new_hbase = new_fbase; new_hend = new_hbase + TFSHDRSIZ; new_dbase = new_hbase + TFSHDRSIZ; new_dend = new_fend; orig_fend = ((char *)dhp->ohdr + fullsize); new_hspan = defragGetSpantype(activesbase,activesend, new_hbase,new_hend); new_dspan = defragGetSpantype(activesbase,activesend, new_dbase,new_dend); finfo.fhdr = 1; fillstat = defragFillFlash(&finfo,new_hspan,&activeaddr,0); if (fillstat < 0) return(fillstat); if (new_hspan == SPANTYPE_BCEL) break; finfo.fhdr = 0; fillstat = defragFillFlash(&finfo,new_dspan,&activeaddr,0); if (fillstat < 0) return(fillstat); if (new_dspan == SPANTYPE_BCEL || new_dspan == SPANTYPE_BPEL) break; } sz = activessize - finfo.crcsz; /* If this is the last sector, then we must not include the space used * for defrag state storage in the crc calculation. * We deduct size of CRC table, DHT table and the crc of the DSI space... */ if (activesnum == lastsnum) { sz -= (tdp->sectorcount * sizeof(struct sectorcrc)); sz -= (ftot * DEFRAGHDRSIZ); sz -= 4; } while(sz) { temp = (finfo.crc ^ 0xff) & 0x000000FFL; finfo.crc = ((finfo.crc >> 8) & 0x00FFFFFFL) ^ crc32tab[temp]; sz--; } *newcrc = ~finfo.crc; return(0);}/* defragBuildCrcTable(): * Build the table of sector crcs. * This consists of a set of CRCs representing each sector * before defrag starts and after defrag has completed. * One set for each sector. This table is then used if the * defrag process is interrupted to determine the state of * the interrupted defragmentation process. */intdefragBuildCrcTable(TDEV *tdp, struct defraghdr *dht, int verbose){ ulong crc; uchar *sbase; int i, ssize, dhstsize; struct sectorcrc *crctbl; dhstsize = (ulong)(tdp->end+1) - (ulong)dht + 4; crctbl = defragCrcTable(tdp); /* The pre-defrag crc table... * This one's easy because it is simply a crc for each of the current * sectors. */ sbase = (uchar *)tdp->start; for(i=0;i<tdp->sectorcount;i++) { if (addrtosector(sbase,0,&ssize,0) < 0) return(-1); if (i == tdp->sectorcount-1) ssize -= dhstsize; /* The pre-defrag crc: */ crc = crc32(sbase,ssize); if (defragFwrite(7,(uchar *)&crctbl[i].precrc, (uchar *)&crc,4) == -1) { return(-1); } /* The post-defrag crc: */ if (defragNewSectorCrc(tdp,dht,i,&crc) < 0) return(-1); if (defragFwrite(8,(uchar *)&crctbl[i].postcrc, (uchar *)&crc,4) == -1) { return(-1); } sbase += ssize; defragTick(0); } return(0);}/* _tfsclean(): * This is the front-end of the defragmentation process, following are the * basic steps of defragmentation... * * Build the Defrag State Information (DSI) area: * 1. Create a table of 32-bit CRCs, two for each sector. One is the CRC * of the sector prior to beginning defragmentation and the other is * what will be the CRC of the sector after defragmentation has completed. * These CRCs are used to help recover from an interrupted defragmentation. * 2. Create a table of struct defraghdr structures, one for each file in * TFS that is currently active (not dead). * 3. Create a CRC of the tables created in steps 1 & 2. * * The data created in steps 1-3 is stored at the end of the last sector * used by TFS for file storage. After this is created, the actual flash * defragmentation process starts. * * File relocation: * 4. Step through each sector in TFS flash space, process each file whose * relocated space overlaps with that sector. As each sector is being * re-built, the original version of that sector is stored in the spare. * * End of flash cleanup: * 5. Run through the remaining, now unsused, space in TFS flash and make * sure it is erased. * * File check: * 6. Run a check of all of the relocated files to make sure everything is * still sane. * * Defragmentation success depends on some coordination with tfsadd()... * Whenever a file is added to TFS, tfsadd() must verify that the space * needed for defrag overhead (defrag state & header tables) will be * available. Also, tfsadd() must make sure that the defrag overhead will * always fit into one sector (the sector just prior to the spare). */static int_tfsclean(TDEV *tdp, int restart, int verbose){ int dhstsize; /* Size of state table overhead */ int firstsnum; /* Number of first sector in TFS device. */ int lastsnum; /* Number of last sector in TFS device. */ int lastssize; /* Size of last sector in TFS device. */ char *lastsbase; /* Base address of last sector in TFS device. */ int sectorcheck; /* Used to verify proper TFS configuration. */ struct defraghdr *dht; /* Pointer to defrag header table. */ int chkstat; /* Result of tfscheck() after defrag is done. */ int ftot; /* Total number of active files in TFS. */ int dtot; /* Total number of deleted files in TFS. */ int fcnt; /* Running file total, used in hdrtbl build. */ TFILE *tfp; /* Misc file pointer */ char *newaddress; /* Used to calculate "new" location of file. */ struct defraghdr defrag; /* Used to build defrag header table. */ int activesnum; /* Sector being worked on restarted defrag. */ struct sectorcrc *crctbl; /* Pointer to table of per-sector crcs. */ int defrag_state; int sidx, snum; char *end; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); /* If incoming TFS device pointer is NULL, return error */ if (!tdp) return(TFSERR_BADARG); /* If the 'restart' flag is set, then we only want to do a defrag if * we determine that one is already in progress; so we have to look at * the current state of the defrag state table to figure out if a defrag * was active. If not, just return. */ if (restart) { defrag_state = defragGetState(tdp,&activesnum); switch(defrag_state) { case SECTOR_DEFRAG_INACTIVE: case SECTOR_DEFRAG_ABORT_RESTART: return(TFS_OKAY); case SCANNING_ACTIVE_SECTOR_1: case SCANNING_ACTIVE_SECTOR_2: case SCANNING_ACTIVE_SECTOR_3: case SCANNING_ACTIVE_SECTOR_4: case SCANNING_ACTIVE_SECTOR_5: defrag_state = SCANNING_ACTIVE_SECTOR; break; } } else { defrag_state = SECTOR_DEFRAG_INACTIVE; } if ((verbose) || (!MFLAGS_NODEFRAGPRN())) printf("TFS device '%s' defragmentation\n",tdp->prefix); if (addrtosector((char *)tdp->start,&firstsnum,0,0) < 0) return(TFSERR_MEMFAIL); lastsnum = firstsnum + tdp->sectorcount - 1; if (addrtosector((char *)tdp->end,§orcheck,0,0) < 0) return(TFSERR_MEMFAIL); if (lastsnum != sectorcheck) { printf("%s: SECTORCOUNT != TFSSTART <-> TFSEND\n", tdp->prefix); printf("First TFS sector = %d, last = %d\n",firstsnum,sectorcheck); return(TFSERR_MEMFAIL); } if (defrag_state == SECTOR_DEFRAG_INACTIVE) { activesnum = firstsnum; } /* Retrieve information about last sector: */ if (sectortoaddr(lastsnum,&lastssize,(uchar **)&lastsbase) == -1) return(TFSERR_MEMFAIL); /* Establish a pointer to a table of CRCs that will contain * one 32-bit CRC for each sector (prior to starting the defrag). */ crctbl = defragCrcTable(tdp); /* Retrieve the number of "dead" and "living" files: * If there are no dead files, then there is no need to defrag. * If there are no "living" files, then we can just init the flash. */ ftot = dtot = 0; if (restart && defragValidDSI(tdp,0)) { dht = (struct defraghdr *)crctbl - 1; ftot = dht->idx + 1; } else { tfp = (TFILE *)tdp->start; while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) ftot++; else dtot++; tfp = nextfp(tfp,tdp); } if (dtot == 0) { if (verbose) printf("No dead files in %s.\n",tdp->prefix); if (tfsflasherased(tdp,verbose)) return(0); if (verbose) printf("Cleaning up end of flash...\n"); } } if (ftot == 0) { if (verbose) printf("No active files detected, erasing all %s flash...\n", tdp->prefix); _tfsinit(tdp); return(0); } /* Now that we know how many files are in TFS, we can establish * a pointer to the defrag header table, and the size of the table... */ dht = (struct defraghdr *)crctbl - ftot; dhstsize = (ulong)(tdp->end+1) - (ulong)dht; dhstsize += 4; /* Account for the CRC of the state tables. */ if (defrag_state == SECTOR_DEFRAG_INACTIVE) { ulong crc; if (verbose) { printf("TFS defrag: building DSI space...\n"); } /* We start by making sure that the space needed by the * defrag header and state table at the end of the last * sector is clear... */ if (!flasherased((uchar *)dht, (uchar *)(tdp->end))) { if (defragEraseSpare(tdp) < 0) return(TFSERR_FLASHFAILURE); if (defragFwrite(9,(uchar *)(tdp->spare),lastsbase, lastssize-dhstsize) == -1) { return(TFSERR_FLASHFAILURE); } if (defragSerase(5,lastsnum) < 0) { return(TFSERR_FLASHFAILURE); } if (defragFwrite(10,lastsbase,(uchar *)(tdp->spare), lastssize) == -1) { return(TFSERR_FLASHFAILURE); } } /* Erase the spare then copy the portion of the last TFS * sector that does not overlap with the defrag header and * state table area to the spare. We do this so that the spare * sector contains a defrag header and state table area that * is erased. */ if (defragEraseSpare(tdp) < 0) return(TFSERR_FLASHFAILURE); if (defragFwrite(11,(uchar *)tdp->spare, lastsbase,lastssize-dhstsize) == -1) { return(TFSERR_FLASHFAILURE); } /* At this point we have a valid copy of the last sector in * the spare. If any portion of the last sector is not identical * to what is in the spare, then we need to erase the last sector * and re-copy what is in the spare to the last sector. This is * necessary because an interrupt may have occurred while writing * to the last sector, and it may have corrupted something. */ if ((memcmp(lastsbase,(char *)(tdp->spare),lastssize-dhstsize)) || (!flasherased((uchar *)dht,(uchar *)tdp->end))) { if (defragSerase(6,lastsnum) < 0) { return(TFSERR_FLASHFAILURE); } if (defragFwrite(12,lastsbase,(uchar *)(tdp->spare), lastssize) == -1) { return(TFSERR_FLASHFAILURE); } } /* Build the header table: */ fcnt = 0; tfp = (TFILE *)tdp->start; newaddress = (char *)tdp->start; if (verbose > 2) { printf("\nDEFRAG HEADER DATA (dht=0x%lx, ftot=%d):\n", (ulong)dht,ftot); } while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) { uchar *base, *eof, *neof, *nbase; int size, slot; struct tfsdat *slotptr; strcpy(defrag.fname,TFS_NAME(tfp)); defrag.ohdr = tfp; defrag.ohdrcrc = tfp->hdrcrc; defrag.filsize = TFS_SIZE(tfp); if (addrtosector((char *)tfp,0,0,&base) < 0) return(TFSERR_MEMFAIL); eof = (uchar *)(tfp+1)+TFS_SIZE(tfp)-1; if (addrtosector((char *)eof,0,0,&base) < 0) return(TFSERR_MEMFAIL); defrag.oeso = eof - base + 1; neof = newaddress+TFSHDRSIZ+TFS_SIZE(tfp)-1; if (addrtosector((char *)neof,(int *)&defrag.nesn,0,&nbase) < 0) return(TFSERR_MEMFAIL); defrag.neso = neof - nbase + 1; defrag.crc = 0; defrag.idx = fcnt; defrag.nda = newaddress; /* If the file is currently opened, adjust the base address. */ slotptr = tfsSlots; for (slot=0;slot<TFS_MAXOPEN;slot++,slotptr++) { if (slotptr->offset != -1) { if (slotptr->base == (uchar *)(TFS_BASE(tfp))) { slotptr->base = (uchar *)(newaddress+TFSHDRSIZ);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -