Revert "yaffs: Update stats when using mtdif2."
[firefly-linux-kernel-4.4.55.git] / fs / yaffs2 / yaffs_packedtags2.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2007 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include "yaffs_packedtags2.h"
15 #include "yportenv.h"
16 #include "yaffs_tagsvalidity.h"
17
18 /* This code packs a set of extended tags into a binary structure for
19  * NAND storage
20  */
21
22 /* Some of the information is "extra" struff which can be packed in to
23  * speed scanning
24  * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
25  */
26
27 /* Extra flags applied to chunkId */
28
29 #define EXTRA_HEADER_INFO_FLAG  0x80000000
30 #define EXTRA_SHRINK_FLAG       0x40000000
31 #define EXTRA_SHADOWS_FLAG      0x20000000
32 #define EXTRA_SPARE_FLAGS       0x10000000
33
34 #define ALL_EXTRA_FLAGS         0xF0000000
35
36 /* Also, the top 4 bits of the object Id are set to the object type. */
37 #define EXTRA_OBJECT_TYPE_SHIFT (28)
38 #define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
39
40 #ifndef CONFIG_YAFFS_DOES_ECC
41 #define YAFFS_IGNORE_TAGS_ECC 1
42 #endif
43
44 static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart *ptt)
45 {
46         T(YAFFS_TRACE_MTD,
47           (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
48            ptt->objectId, ptt->chunkId, ptt->byteCount,
49            ptt->sequenceNumber));
50 }
51 static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt)
52 {
53         yaffs_DumpPackedTags2TagsPart(&pt->t);
54 }
55
56 static void yaffs_DumpTags2(const yaffs_ExtendedTags *t)
57 {
58         T(YAFFS_TRACE_MTD,
59           (TSTR
60            ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
61             TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
62            t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
63            t->sequenceNumber));
64
65 }
66
67 void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt,
68                 const yaffs_ExtendedTags *t)
69 {
70         ptt->chunkId = t->chunkId;
71         ptt->sequenceNumber = t->sequenceNumber;
72         ptt->byteCount = t->byteCount;
73         ptt->objectId = t->objectId;
74
75         if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
76                 /* Store the extra header info instead */
77                 /* We save the parent object in the chunkId */
78                 ptt->chunkId = EXTRA_HEADER_INFO_FLAG
79                         | t->extraParentObjectId;
80                 if (t->extraIsShrinkHeader)
81                         ptt->chunkId |= EXTRA_SHRINK_FLAG;
82                 if (t->extraShadows)
83                         ptt->chunkId |= EXTRA_SHADOWS_FLAG;
84
85                 ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
86                 ptt->objectId |=
87                     (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
88
89                 if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
90                         ptt->byteCount = t->extraEquivalentObjectId;
91                 else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE)
92                         ptt->byteCount = t->extraFileLength;
93                 else
94                         ptt->byteCount = 0;
95         }
96
97         yaffs_DumpPackedTags2TagsPart(ptt);
98         yaffs_DumpTags2(t);
99 }
100
101
102 void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
103 {
104         yaffs_PackTags2TagsPart(&pt->t, t);
105
106 #ifndef YAFFS_IGNORE_TAGS_ECC
107         {
108                 yaffs_ECCCalculateOther((unsigned char *)&pt->t,
109                                         sizeof(yaffs_PackedTags2TagsPart),
110                                         &pt->ecc);
111         }
112 #endif
113 }
114
115
116 void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t,
117                 yaffs_PackedTags2TagsPart *ptt)
118 {
119
120         memset(t, 0, sizeof(yaffs_ExtendedTags));
121
122         yaffs_InitialiseTags(t);
123
124         if (ptt->sequenceNumber != 0xFFFFFFFF) {
125                 t->blockBad = 0;
126                 t->chunkUsed = 1;
127                 t->objectId = ptt->objectId;
128                 t->chunkId = ptt->chunkId;
129                 t->byteCount = ptt->byteCount;
130                 t->chunkDeleted = 0;
131                 t->serialNumber = 0;
132                 t->sequenceNumber = ptt->sequenceNumber;
133
134                 /* Do extra header info stuff */
135
136                 if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
137                         t->chunkId = 0;
138                         t->byteCount = 0;
139
140                         t->extraHeaderInfoAvailable = 1;
141                         t->extraParentObjectId =
142                             ptt->chunkId & (~(ALL_EXTRA_FLAGS));
143                         t->extraIsShrinkHeader =
144                             (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
145                         t->extraShadows =
146                             (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
147                         t->extraObjectType =
148                             ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
149                         t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
150
151                         if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
152                                 t->extraEquivalentObjectId = ptt->byteCount;
153                         else
154                                 t->extraFileLength = ptt->byteCount;
155                 }
156         }
157
158         yaffs_DumpPackedTags2TagsPart(ptt);
159         yaffs_DumpTags2(t);
160
161 }
162
163
164 void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
165 {
166
167         yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
168
169         if (pt->t.sequenceNumber != 0xFFFFFFFF) {
170                 /* Page is in use */
171 #ifndef YAFFS_IGNORE_TAGS_ECC
172                 {
173                         yaffs_ECCOther ecc;
174                         int result;
175                         yaffs_ECCCalculateOther((unsigned char *)&pt->t,
176                                                 sizeof
177                                                 (yaffs_PackedTags2TagsPart),
178                                                 &ecc);
179                         result =
180                             yaffs_ECCCorrectOther((unsigned char *)&pt->t,
181                                                   sizeof
182                                                   (yaffs_PackedTags2TagsPart),
183                                                   &pt->ecc, &ecc);
184                         switch (result) {
185                         case 0:
186                                 eccResult = YAFFS_ECC_RESULT_NO_ERROR;
187                                 break;
188                         case 1:
189                                 eccResult = YAFFS_ECC_RESULT_FIXED;
190                                 break;
191                         case -1:
192                                 eccResult = YAFFS_ECC_RESULT_UNFIXED;
193                                 break;
194                         default:
195                                 eccResult = YAFFS_ECC_RESULT_UNKNOWN;
196                         }
197                 }
198 #endif
199         }
200
201         yaffs_UnpackTags2TagsPart(t, &pt->t);
202
203         t->eccResult = eccResult;
204
205         yaffs_DumpPackedTags2(pt);
206         yaffs_DumpTags2(t);
207
208 }
209