⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tfs_with_appexit_support.c

📁 flash文件系统实现
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* 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,&sectorcheck,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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -