PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/fs/fs/yaffs2/yaffs_yaffs1.c

https://bitbucket.org/droidzone/supernova-kernel
C | 465 lines | 306 code | 86 blank | 73 comment | 74 complexity | f83a59976339bcb1f424294d9fc27e4b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  3. *
  4. * Copyright (C) 2002-2010 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. #include "yaffs_yaffs1.h"
  14. #include "yportenv.h"
  15. #include "yaffs_trace.h"
  16. #include "yaffs_bitmap.h"
  17. #include "yaffs_getblockinfo.h"
  18. #include "yaffs_nand.h"
  19. int yaffs1_Scan(yaffs_Device *dev)
  20. {
  21. yaffs_ExtendedTags tags;
  22. int blk;
  23. int blockIterator;
  24. int startIterator;
  25. int endIterator;
  26. int result;
  27. int chunk;
  28. int c;
  29. int deleted;
  30. yaffs_BlockState state;
  31. yaffs_Object *hardList = NULL;
  32. yaffs_BlockInfo *bi;
  33. __u32 sequenceNumber;
  34. yaffs_ObjectHeader *oh;
  35. yaffs_Object *in;
  36. yaffs_Object *parent;
  37. int alloc_failed = 0;
  38. struct yaffs_ShadowFixerStruct *shadowFixerList = NULL;
  39. __u8 *chunkData;
  40. T(YAFFS_TRACE_SCAN,
  41. (TSTR("yaffs1_Scan starts intstartblk %d intendblk %d..." TENDSTR),
  42. dev->internalStartBlock, dev->internalEndBlock));
  43. chunkData = yaffs_GetTempBuffer(dev, __LINE__);
  44. dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
  45. /* Scan all the blocks to determine their state */
  46. bi = dev->blockInfo;
  47. for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
  48. yaffs_ClearChunkBits(dev, blk);
  49. bi->pagesInUse = 0;
  50. bi->softDeletions = 0;
  51. yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
  52. bi->blockState = state;
  53. bi->sequenceNumber = sequenceNumber;
  54. if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK)
  55. bi->blockState = state = YAFFS_BLOCK_STATE_DEAD;
  56. T(YAFFS_TRACE_SCAN_DEBUG,
  57. (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
  58. state, sequenceNumber));
  59. if (state == YAFFS_BLOCK_STATE_DEAD) {
  60. T(YAFFS_TRACE_BAD_BLOCKS,
  61. (TSTR("block %d is bad" TENDSTR), blk));
  62. } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
  63. T(YAFFS_TRACE_SCAN_DEBUG,
  64. (TSTR("Block empty " TENDSTR)));
  65. dev->nErasedBlocks++;
  66. dev->nFreeChunks += dev->param.nChunksPerBlock;
  67. }
  68. bi++;
  69. }
  70. startIterator = dev->internalStartBlock;
  71. endIterator = dev->internalEndBlock;
  72. /* For each block.... */
  73. for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
  74. blockIterator++) {
  75. YYIELD();
  76. YYIELD();
  77. blk = blockIterator;
  78. bi = yaffs_GetBlockInfo(dev, blk);
  79. state = bi->blockState;
  80. deleted = 0;
  81. /* For each chunk in each block that needs scanning....*/
  82. for (c = 0; !alloc_failed && c < dev->param.nChunksPerBlock &&
  83. state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {
  84. /* Read the tags and decide what to do */
  85. chunk = blk * dev->param.nChunksPerBlock + c;
  86. result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
  87. &tags);
  88. /* Let's have a good look at this chunk... */
  89. if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {
  90. /* YAFFS1 only...
  91. * A deleted chunk
  92. */
  93. deleted++;
  94. dev->nFreeChunks++;
  95. /*T((" %d %d deleted\n",blk,c)); */
  96. } else if (!tags.chunkUsed) {
  97. /* An unassigned chunk in the block
  98. * This means that either the block is empty or
  99. * this is the one being allocated from
  100. */
  101. if (c == 0) {
  102. /* We're looking at the first chunk in the block so the block is unused */
  103. state = YAFFS_BLOCK_STATE_EMPTY;
  104. dev->nErasedBlocks++;
  105. } else {
  106. /* this is the block being allocated from */
  107. T(YAFFS_TRACE_SCAN,
  108. (TSTR
  109. (" Allocating from %d %d" TENDSTR),
  110. blk, c));
  111. state = YAFFS_BLOCK_STATE_ALLOCATING;
  112. dev->allocationBlock = blk;
  113. dev->allocationPage = c;
  114. dev->allocationBlockFinder = blk;
  115. /* Set block finder here to encourage the allocator to go forth from here. */
  116. }
  117. dev->nFreeChunks += (dev->param.nChunksPerBlock - c);
  118. } else if (tags.chunkId > 0) {
  119. /* chunkId > 0 so it is a data chunk... */
  120. unsigned int endpos;
  121. yaffs_SetChunkBit(dev, blk, c);
  122. bi->pagesInUse++;
  123. in = yaffs_FindOrCreateObjectByNumber(dev,
  124. tags.
  125. objectId,
  126. YAFFS_OBJECT_TYPE_FILE);
  127. /* PutChunkIntoFile checks for a clash (two data chunks with
  128. * the same chunkId).
  129. */
  130. if (!in)
  131. alloc_failed = 1;
  132. if (in) {
  133. if (!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, 1))
  134. alloc_failed = 1;
  135. }
  136. endpos =
  137. (tags.chunkId - 1) * dev->nDataBytesPerChunk +
  138. tags.byteCount;
  139. if (in &&
  140. in->variantType == YAFFS_OBJECT_TYPE_FILE
  141. && in->variant.fileVariant.scannedFileSize <
  142. endpos) {
  143. in->variant.fileVariant.
  144. scannedFileSize = endpos;
  145. if (!dev->param.useHeaderFileSize) {
  146. in->variant.fileVariant.
  147. fileSize =
  148. in->variant.fileVariant.
  149. scannedFileSize;
  150. }
  151. }
  152. /* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); */
  153. } else {
  154. /* chunkId == 0, so it is an ObjectHeader.
  155. * Thus, we read in the object header and make the object
  156. */
  157. yaffs_SetChunkBit(dev, blk, c);
  158. bi->pagesInUse++;
  159. result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk,
  160. chunkData,
  161. NULL);
  162. oh = (yaffs_ObjectHeader *) chunkData;
  163. in = yaffs_FindObjectByNumber(dev,
  164. tags.objectId);
  165. if (in && in->variantType != oh->type) {
  166. /* This should not happen, but somehow
  167. * Wev'e ended up with an objectId that has been reused but not yet
  168. * deleted, and worse still it has changed type. Delete the old object.
  169. */
  170. yaffs_DeleteObject(in);
  171. in = 0;
  172. }
  173. in = yaffs_FindOrCreateObjectByNumber(dev,
  174. tags.
  175. objectId,
  176. oh->type);
  177. if (!in)
  178. alloc_failed = 1;
  179. if (in && oh->shadowsObject > 0) {
  180. struct yaffs_ShadowFixerStruct *fixer;
  181. fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct));
  182. if (fixer) {
  183. fixer->next = shadowFixerList;
  184. shadowFixerList = fixer;
  185. fixer->objectId = tags.objectId;
  186. fixer->shadowedId = oh->shadowsObject;
  187. T(YAFFS_TRACE_SCAN,
  188. (TSTR
  189. (" Shadow fixer: %d shadows %d" TENDSTR),
  190. fixer->objectId, fixer->shadowedId));
  191. }
  192. }
  193. if (in && in->valid) {
  194. /* We have already filled this one. We have a duplicate and need to resolve it. */
  195. unsigned existingSerial = in->serial;
  196. unsigned newSerial = tags.serialNumber;
  197. if (((existingSerial + 1) & 3) == newSerial) {
  198. /* Use new one - destroy the exisiting one */
  199. yaffs_DeleteChunk(dev,
  200. in->hdrChunk,
  201. 1, __LINE__);
  202. in->valid = 0;
  203. } else {
  204. /* Use existing - destroy this one. */
  205. yaffs_DeleteChunk(dev, chunk, 1,
  206. __LINE__);
  207. }
  208. }
  209. if (in && !in->valid &&
  210. (tags.objectId == YAFFS_OBJECTID_ROOT ||
  211. tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) {
  212. /* We only load some info, don't fiddle with directory structure */
  213. in->valid = 1;
  214. in->variantType = oh->type;
  215. in->yst_mode = oh->yst_mode;
  216. #ifdef CONFIG_YAFFS_WINCE
  217. in->win_atime[0] = oh->win_atime[0];
  218. in->win_ctime[0] = oh->win_ctime[0];
  219. in->win_mtime[0] = oh->win_mtime[0];
  220. in->win_atime[1] = oh->win_atime[1];
  221. in->win_ctime[1] = oh->win_ctime[1];
  222. in->win_mtime[1] = oh->win_mtime[1];
  223. #else
  224. in->yst_uid = oh->yst_uid;
  225. in->yst_gid = oh->yst_gid;
  226. in->yst_atime = oh->yst_atime;
  227. in->yst_mtime = oh->yst_mtime;
  228. in->yst_ctime = oh->yst_ctime;
  229. in->yst_rdev = oh->yst_rdev;
  230. #endif
  231. in->hdrChunk = chunk;
  232. in->serial = tags.serialNumber;
  233. } else if (in && !in->valid) {
  234. /* we need to load this info */
  235. in->valid = 1;
  236. in->variantType = oh->type;
  237. in->yst_mode = oh->yst_mode;
  238. #ifdef CONFIG_YAFFS_WINCE
  239. in->win_atime[0] = oh->win_atime[0];
  240. in->win_ctime[0] = oh->win_ctime[0];
  241. in->win_mtime[0] = oh->win_mtime[0];
  242. in->win_atime[1] = oh->win_atime[1];
  243. in->win_ctime[1] = oh->win_ctime[1];
  244. in->win_mtime[1] = oh->win_mtime[1];
  245. #else
  246. in->yst_uid = oh->yst_uid;
  247. in->yst_gid = oh->yst_gid;
  248. in->yst_atime = oh->yst_atime;
  249. in->yst_mtime = oh->yst_mtime;
  250. in->yst_ctime = oh->yst_ctime;
  251. in->yst_rdev = oh->yst_rdev;
  252. #endif
  253. in->hdrChunk = chunk;
  254. in->serial = tags.serialNumber;
  255. yaffs_SetObjectNameFromOH(in, oh);
  256. in->dirty = 0;
  257. /* directory stuff...
  258. * hook up to parent
  259. */
  260. parent =
  261. yaffs_FindOrCreateObjectByNumber
  262. (dev, oh->parentObjectId,
  263. YAFFS_OBJECT_TYPE_DIRECTORY);
  264. if (!parent)
  265. alloc_failed = 1;
  266. if (parent && parent->variantType ==
  267. YAFFS_OBJECT_TYPE_UNKNOWN) {
  268. /* Set up as a directory */
  269. parent->variantType =
  270. YAFFS_OBJECT_TYPE_DIRECTORY;
  271. YINIT_LIST_HEAD(&parent->variant.
  272. directoryVariant.
  273. children);
  274. } else if (!parent || parent->variantType !=
  275. YAFFS_OBJECT_TYPE_DIRECTORY) {
  276. /* Hoosterman, another problem....
  277. * We're trying to use a non-directory as a directory
  278. */
  279. T(YAFFS_TRACE_ERROR,
  280. (TSTR
  281. ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
  282. TENDSTR)));
  283. parent = dev->lostNFoundDir;
  284. }
  285. yaffs_AddObjectToDirectory(parent, in);
  286. if (0 && (parent == dev->deletedDir ||
  287. parent == dev->unlinkedDir)) {
  288. in->deleted = 1; /* If it is unlinked at start up then it wants deleting */
  289. dev->nDeletedFiles++;
  290. }
  291. /* Note re hardlinks.
  292. * Since we might scan a hardlink before its equivalent object is scanned
  293. * we put them all in a list.
  294. * After scanning is complete, we should have all the objects, so we run through this
  295. * list and fix up all the chains.
  296. */
  297. switch (in->variantType) {
  298. case YAFFS_OBJECT_TYPE_UNKNOWN:
  299. /* Todo got a problem */
  300. break;
  301. case YAFFS_OBJECT_TYPE_FILE:
  302. if (dev->param.useHeaderFileSize)
  303. in->variant.fileVariant.
  304. fileSize =
  305. oh->fileSize;
  306. break;
  307. case YAFFS_OBJECT_TYPE_HARDLINK:
  308. in->variant.hardLinkVariant.
  309. equivalentObjectId =
  310. oh->equivalentObjectId;
  311. in->hardLinks.next =
  312. (struct ylist_head *)
  313. hardList;
  314. hardList = in;
  315. break;
  316. case YAFFS_OBJECT_TYPE_DIRECTORY:
  317. /* Do nothing */
  318. break;
  319. case YAFFS_OBJECT_TYPE_SPECIAL:
  320. /* Do nothing */
  321. break;
  322. case YAFFS_OBJECT_TYPE_SYMLINK:
  323. in->variant.symLinkVariant.alias =
  324. yaffs_CloneString(oh->alias);
  325. if (!in->variant.symLinkVariant.alias)
  326. alloc_failed = 1;
  327. break;
  328. }
  329. }
  330. }
  331. }
  332. if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
  333. /* If we got this far while scanning, then the block is fully allocated.*/
  334. state = YAFFS_BLOCK_STATE_FULL;
  335. }
  336. if (state == YAFFS_BLOCK_STATE_ALLOCATING) {
  337. /* If the block was partially allocated then treat it as fully allocated.*/
  338. state = YAFFS_BLOCK_STATE_FULL;
  339. dev->allocationBlock = -1;
  340. }
  341. bi->blockState = state;
  342. /* Now let's see if it was dirty */
  343. if (bi->pagesInUse == 0 &&
  344. !bi->hasShrinkHeader &&
  345. bi->blockState == YAFFS_BLOCK_STATE_FULL) {
  346. yaffs_BlockBecameDirty(dev, blk);
  347. }
  348. }
  349. /* Ok, we've done all the scanning.
  350. * Fix up the hard link chains.
  351. * We should now have scanned all the objects, now it's time to add these
  352. * hardlinks.
  353. */
  354. yaffs_HardlinkFixup(dev, hardList);
  355. /* Fix up any shadowed objects */
  356. {
  357. struct yaffs_ShadowFixerStruct *fixer;
  358. yaffs_Object *obj;
  359. while (shadowFixerList) {
  360. fixer = shadowFixerList;
  361. shadowFixerList = fixer->next;
  362. /* Complete the rename transaction by deleting the shadowed object
  363. * then setting the object header to unshadowed.
  364. */
  365. obj = yaffs_FindObjectByNumber(dev, fixer->shadowedId);
  366. if (obj)
  367. yaffs_DeleteObject(obj);
  368. obj = yaffs_FindObjectByNumber(dev, fixer->objectId);
  369. if (obj)
  370. yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL);
  371. YFREE(fixer);
  372. }
  373. }
  374. yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
  375. if (alloc_failed)
  376. return YAFFS_FAIL;
  377. T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_Scan ends" TENDSTR)));
  378. return YAFFS_OK;
  379. }