summaryrefslogtreecommitdiffstats
path: root/main/common/tfsclean3.c
blob: e8e003edf7acda122e1c186d471436b648635238 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/**************************************************************************
 *
 * Copyright (c) 2013 Alcatel-Lucent
 *
 * Alcatel Lucent licenses this file to You under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  A copy of the License is contained the
 * file LICENSE at the top level of this repository.
 * You may also obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************
 *
 * tfsclean3.c:
 *
 *  --- NOT READY YET ---
 *
 * This version of defragmentation is power-hit safe and requires
 * that there be double the amount of flash as is needed for use by
 * TFS.  The basic idea is similar to tfsclean2.c...
 * Copy all of the good files over to the "other" flash bank, then have
 * TFS use the "other" bank as the storage area.
 * The idea is that the defrag is simply a copy of the good stuff to
 * the alternate flash block.  This requires that after the
 * good stuff is copied, the now-dirty flash block must be erased in
 * the background prior to the next tfsclean() call.  The fact that
 * there is no sector erase is what makes this faster.
 *
 * If both of these flash banks are in the same flash device, then
 * having a background erase in progress means that it must be an
 * interruptible erase (device specific).  This is necessary because
 * while the background erase is in progress there may be a need to
 * interact with the flash and most devices don't let you do both at the
 * same time.
 *
 * Note that this "background-erase" is what makes this method the
 * fastest defrag method.  It does require that the erase operation be
 * interruptible, and it requires that the application will provide the
 * hooks to do this...
 *
 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
 *
 */
#include "config.h"
#include "cpu.h"
#include "stddefs.h"
#include "genlib.h"
#include "tfs.h"
#include "tfsprivate.h"
#include "flash.h"
#include "monflags.h"

#if INCLUDE_TFS

int
tfsfixup(int verbose, int dontquery)
{
    return(TFSERR_NOTAVAILABLE);
}

#if DEFRAG_TEST_ENABLED
int
dumpDhdr(DEFRAGHDR *dhp)
{
    return(TFSERR_NOTAVAILABLE);
}

int
dumpDhdrTbl(DEFRAGHDR *dhp, int ftot)
{
    return(TFSERR_NOTAVAILABLE);
}
#endif


/* _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(TDEV *tdp, int notused, int verbose)
{
    TFILE   *tfp;
    uchar   *tbuf;
    ulong   appramstart;
    int     dtot, nfadd, len, err, chkstat;

    if(TfsCleanEnable < 0) {
        return(TFSERR_CLEANOFF);
    }

    appramstart = getAppRamStart();

    /* 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 *)appramstart;
    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;
            if(s_memcpy(tbuf,(uchar *)tfp,len,0,0) != 0) {
                return(TFSERR_MEMFAIL);
            }

            ((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 *)appramstart,
                        (tbuf-(uchar *)appramstart));
    if(err < 0) {
        return(TFSERR_FLASHFAILURE);
    }

    /* All defragmentation is done, so verify sanity of files... */
    chkstat = tfscheck(tdp,verbose);

    return(chkstat);
}
#endif