2 * NFTL mount code with extensive checks
4 * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
5 * Copyright (C) 2000 Netgem S.A.
7 * $Id: nftlmount.c,v 1.34 2003/05/21 10:54:10 dwmw2 Exp $
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/kernel.h>
25 #include <asm/errno.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/mtd/mtd.h>
29 #include <linux/mtd/nand.h>
30 #include <linux/mtd/nftl.h>
32 #define SECTORSIZE 512
34 char nftlmountrev[]="$Revision: 1.34 $";
36 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
37 * various device information of the NFTL partition and Bad Unit Table. Update
38 * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
39 * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
41 static int find_boot_record(struct NFTLrecord *nftl)
45 unsigned int block, boot_record_count = 0;
48 struct NFTLMediaHeader *mh = &nftl->MediaHdr;
51 /* Assume logical EraseSize == physical erasesize for starting the scan.
52 We'll sort it out later if we find a MediaHeader which says otherwise */
53 nftl->EraseSize = nftl->mbd.mtd->erasesize;
54 nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
56 nftl->MediaUnit = BLOCK_NIL;
57 nftl->SpareMediaUnit = BLOCK_NIL;
59 /* search for a valid boot record */
60 for (block = 0; block < nftl->nb_blocks; block++) {
63 /* Check for ANAND header first. Then can whinge if it's found but later
65 if ((ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) {
66 static int warncount = 5;
69 printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n",
70 block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
72 printk(KERN_WARNING "Further failures for this block will not be printed\n");
77 if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
78 /* ANAND\0 not found. Continue */
80 printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
81 block * nftl->EraseSize, nftl->mbd.mtd->index);
86 /* To be safer with BIOS, also use erase mark as discriminant */
87 if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
88 8, &retlen, (char *)&h1) < 0)) {
89 printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n",
90 block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
94 #if 0 /* Some people seem to have devices without ECC or erase marks
95 on the Media Header blocks. There are enough other sanity
96 checks in here that we can probably do without it.
98 if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) {
99 printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n",
100 block * nftl->EraseSize, nftl->mbd.mtd->index,
101 le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1));
105 /* Finally reread to check ECC */
106 if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
107 &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP) < 0)) {
108 printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
109 block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
113 /* Paranoia. Check the ANAND header is still there after the ECC read */
114 if (memcmp(buf, "ANAND", 6)) {
115 printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but went away on reread!\n",
116 block * nftl->EraseSize, nftl->mbd.mtd->index);
117 printk(KERN_NOTICE "New data are: %02x %02x %02x %02x %02x %02x\n",
118 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
122 /* OK, we like it. */
124 if (boot_record_count) {
125 /* We've already processed one. So we just check if
126 this one is the same as the first one we found */
127 if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) {
128 printk(KERN_NOTICE "NFTL Media Headers at 0x%x and 0x%x disagree.\n",
129 nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);
130 /* if (debug) Print both side by side */
131 if (boot_record_count < 2) {
132 /* We haven't yet seen two real ones */
137 if (boot_record_count == 1)
138 nftl->SpareMediaUnit = block;
140 /* Mark this boot record (NFTL MediaHeader) block as reserved */
141 nftl->ReplUnitTable[block] = BLOCK_RESERVED;
148 /* This is the first we've seen. Copy the media header structure into place */
149 memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
151 /* Do some sanity checks on it */
152 if (mh->UnitSizeFactor == 0) {
153 printk(KERN_NOTICE "NFTL: UnitSizeFactor 0x00 detected. This violates the spec but we think we know what it means...\n");
154 } else if (mh->UnitSizeFactor < 0xfc) {
155 printk(KERN_NOTICE "Sorry, we don't support UnitSizeFactor 0x%02x\n",
158 } else if (mh->UnitSizeFactor != 0xff) {
159 printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n",
161 nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
162 nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
164 nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
165 if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
166 printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
167 printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
168 nftl->nb_boot_blocks, nftl->nb_blocks);
172 nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;
173 if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) {
174 printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
175 printk(KERN_NOTICE "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n",
176 nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks);
180 nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
182 /* If we're not using the last sectors in the device for some reason,
183 reduce nb_blocks accordingly so we forget they're there */
184 nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);
186 /* XXX: will be suppressed */
187 nftl->lastEUN = nftl->nb_blocks - 1;
190 nftl->EUNtable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
191 if (!nftl->EUNtable) {
192 printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n");
196 nftl->ReplUnitTable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
197 if (!nftl->ReplUnitTable) {
198 kfree(nftl->EUNtable);
199 printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
203 /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
204 for (i = 0; i < nftl->nb_boot_blocks; i++)
205 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
206 /* mark all remaining blocks as potentially containing data */
207 for (; i < nftl->nb_blocks; i++) {
208 nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
211 /* Mark this boot record (NFTL MediaHeader) block as reserved */
212 nftl->ReplUnitTable[block] = BLOCK_RESERVED;
214 /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
215 for (i = 0; i < nftl->nb_blocks; i++) {
216 if ((i & (SECTORSIZE - 1)) == 0) {
217 /* read one sector for every SECTORSIZE of blocks */
218 if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
219 i + SECTORSIZE, SECTORSIZE, &retlen, buf,
220 (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) {
221 printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
223 kfree(nftl->ReplUnitTable);
224 kfree(nftl->EUNtable);
228 /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
229 if (buf[i & (SECTORSIZE - 1)] != 0xff)
230 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
233 nftl->MediaUnit = block;
236 } /* foreach (block) */
238 return boot_record_count?0:-1;
241 static int memcmpb(void *a, int c, int n)
244 for (i = 0; i < n; i++) {
245 if (c != ((unsigned char *)a)[i])
251 /* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */
252 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
258 for (i = 0; i < len; i += SECTORSIZE) {
259 /* we want to read the sector without ECC check here since a free
260 sector does not have ECC syndrome on it yet */
261 if (MTD_READ(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0)
263 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
267 if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize,
270 if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0)
273 address += SECTORSIZE;
279 /* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and
280 * Update NFTL metadata. Each erase operation is checked with check_free_sectors
282 * Return: 0 when succeed, -1 on error.
284 * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
285 * 2. UnitSizeFactor != 0xFF
287 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
290 unsigned int nb_erases, erase_mark;
291 struct nftl_uci1 uci;
292 struct erase_info *instr = &nftl->instr;
294 /* Read the Unit Control Information #1 for Wear-Leveling */
295 if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
296 8, &retlen, (char *)&uci) < 0)
299 erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
300 if (erase_mark != ERASE_MARK) {
302 uci.EraseMark = cpu_to_le16(ERASE_MARK);
303 uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
304 uci.WearInfo = cpu_to_le32(0);
307 memset(instr, 0, sizeof(struct erase_info));
309 /* XXX: use async erase interface, XXX: test return code */
310 instr->addr = block * nftl->EraseSize;
311 instr->len = nftl->EraseSize;
312 MTD_ERASE(nftl->mbd.mtd, instr);
314 if (instr->state == MTD_ERASE_FAILED) {
315 /* could not format, FixMe: We should update the BadUnitTable
316 both in memory and on disk */
317 printk("Error while formatting block %d\n", block);
320 /* increase and write Wear-Leveling info */
321 nb_erases = le32_to_cpu(uci.WearInfo);
324 /* wrap (almost impossible with current flashs) or free block */
328 /* check the "freeness" of Erase Unit before updating metadata
329 * FixMe: is this check really necessary ? since we have check the
330 * return code after the erase operation. */
331 if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
334 uci.WearInfo = le32_to_cpu(nb_erases);
335 if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
336 &retlen, (char *)&uci) < 0)
342 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
343 * Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
344 * was being folded when NFTL was interrupted.
346 * The check_free_sectors in this function is neceressary. There is a possible
347 * situation that after writing the Data area, the Block Control Information is
348 * not updated according (due to power failure or something) which leaves the block
349 * in an umconsistent state. So we have to check if a block is really FREE in this
351 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
353 unsigned int block, i, status;
355 int sectors_per_block, retlen;
357 sectors_per_block = nftl->EraseSize / SECTORSIZE;
360 for (i = 0; i < sectors_per_block; i++) {
361 if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE,
362 8, &retlen, (char *)&bci) < 0)
363 status = SECTOR_IGNORE;
365 status = bci.Status | bci.Status1;
369 /* verify that the sector is really free. If not, mark
371 if (memcmpb(&bci, 0xff, 8) != 0 ||
372 check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
373 SECTORSIZE, 0) != 0) {
374 printk("Incorrect free sector %d in block %d: "
375 "marking it as ignored\n",
378 /* sector not free actually : mark it as SECTOR_IGNORE */
379 bci.Status = SECTOR_IGNORE;
380 bci.Status1 = SECTOR_IGNORE;
381 MTD_WRITEOOB(nftl->mbd.mtd,
382 block * nftl->EraseSize + i * SECTORSIZE,
383 8, &retlen, (char *)&bci);
391 /* proceed to next Erase Unit on the chain */
392 block = nftl->ReplUnitTable[block];
393 if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
394 printk("incorrect ReplUnitTable[] : %d\n", block);
395 if (block == BLOCK_NIL || block >= nftl->nb_blocks)
400 /* calc_chain_lenght: Walk through a Virtual Unit Chain and estimate chain length */
401 static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
403 unsigned int length = 0, block = first_block;
407 /* avoid infinite loops, although this is guaranted not to
408 happen because of the previous checks */
409 if (length >= nftl->nb_blocks) {
410 printk("nftl: length too long %d !\n", length);
414 block = nftl->ReplUnitTable[block];
415 if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
416 printk("incorrect ReplUnitTable[] : %d\n", block);
417 if (block == BLOCK_NIL || block >= nftl->nb_blocks)
423 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
424 * Virtual Unit Chain, i.e. all the units are disconnected.
426 * It is not stricly correct to begin from the first block of the chain because
427 * if we stop the code, we may see again a valid chain if there was a first_block
428 * flag in a block inside it. But is it really a problem ?
430 * FixMe: Figure out what the last statesment means. What if power failure when we are
431 * in the for (;;) loop formatting blocks ??
433 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
435 unsigned int block = first_block, block1;
437 printk("Formatting chain at block %d\n", first_block);
440 block1 = nftl->ReplUnitTable[block];
442 printk("Formatting block %d\n", block);
443 if (NFTL_formatblock(nftl, block) < 0) {
444 /* cannot format !!!! Mark it as Bad Unit,
445 FixMe: update the BadUnitTable on disk */
446 nftl->ReplUnitTable[block] = BLOCK_RESERVED;
448 nftl->ReplUnitTable[block] = BLOCK_FREE;
451 /* goto next block on the chain */
454 if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
455 printk("incorrect ReplUnitTable[] : %d\n", block);
456 if (block == BLOCK_NIL || block >= nftl->nb_blocks)
461 /* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or
462 * totally free (only 0xff).
464 * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
467 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
470 unsigned int erase_mark;
473 /* check erase mark. */
474 if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
475 &retlen, (char *)&h1) < 0)
478 erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
479 if (erase_mark != ERASE_MARK) {
480 /* if no erase mark, the block must be totally free. This is
481 possible in two cases : empty filsystem or interrupted erase (very unlikely) */
482 if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
485 /* free block : write erase mark */
486 h1.EraseMark = cpu_to_le16(ERASE_MARK);
487 h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
488 h1.WearInfo = cpu_to_le32(0);
489 if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
490 &retlen, (char *)&h1) < 0)
494 /* if erase mark present, need to skip it when doing check */
495 for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) {
496 /* check free sector */
497 if (check_free_sectors (nftl, block * nftl->EraseSize + i,
501 if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i,
502 16, &retlen, buf) < 0)
504 if (i == SECTORSIZE) {
505 /* skip erase mark */
506 if (memcmpb(buf, 0xff, 8))
509 if (memcmpb(buf, 0xff, 16))
519 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
520 * to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
521 * is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
522 * for some reason. A clean up/check of the VUC is neceressary in this case.
524 * WARNING: return 0 if read error
526 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
528 struct nftl_uci2 uci;
531 if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
532 8, &retlen, (char *)&uci) < 0)
535 return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
538 int NFTL_mount(struct NFTLrecord *s)
541 unsigned int first_logical_block, logical_block, rep_block, nb_erases, erase_mark;
542 unsigned int block, first_block, is_first_block;
543 int chain_length, do_format_chain;
548 /* search for NFTL MediaHeader and Spare NFTL Media Header */
549 if (find_boot_record(s) < 0) {
550 printk("Could not find valid boot record\n");
554 /* init the logical to physical table */
555 for (i = 0; i < s->nb_blocks; i++) {
556 s->EUNtable[i] = BLOCK_NIL;
559 /* first pass : explore each block chain */
560 first_logical_block = 0;
561 for (first_block = 0; first_block < s->nb_blocks; first_block++) {
562 /* if the block was not already explored, we can look at it */
563 if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) {
569 /* read the block header. If error, we format the chain */
570 if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
571 &retlen, (char *)&h0) < 0 ||
572 MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
573 &retlen, (char *)&h1) < 0) {
574 s->ReplUnitTable[block] = BLOCK_NIL;
579 logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum));
580 rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum));
581 nb_erases = le32_to_cpu (h1.WearInfo);
582 erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
584 is_first_block = !(logical_block >> 15);
585 logical_block = logical_block & 0x7fff;
587 /* invalid/free block test */
588 if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) {
589 if (chain_length == 0) {
590 /* if not currently in a chain, we can handle it safely */
591 if (check_and_mark_free_block(s, block) < 0) {
592 /* not really free: format it */
593 printk("Formatting block %d\n", block);
594 if (NFTL_formatblock(s, block) < 0) {
595 /* could not format: reserve the block */
596 s->ReplUnitTable[block] = BLOCK_RESERVED;
598 s->ReplUnitTable[block] = BLOCK_FREE;
601 /* free block: mark it */
602 s->ReplUnitTable[block] = BLOCK_FREE;
604 /* directly examine the next block. */
605 goto examine_ReplUnitTable;
607 /* the block was in a chain : this is bad. We
608 must format all the chain */
609 printk("Block %d: free but referenced in chain %d\n",
611 s->ReplUnitTable[block] = BLOCK_NIL;
617 /* we accept only first blocks here */
618 if (chain_length == 0) {
619 /* this block is not the first block in chain :
620 ignore it, it will be included in a chain
621 later, or marked as not explored */
623 goto examine_ReplUnitTable;
624 first_logical_block = logical_block;
626 if (logical_block != first_logical_block) {
627 printk("Block %d: incorrect logical block: %d expected: %d\n",
628 block, logical_block, first_logical_block);
629 /* the chain is incorrect : we must format it,
630 but we need to read it completly */
633 if (is_first_block) {
634 /* we accept that a block is marked as first
635 block while being last block in a chain
636 only if the chain is being folded */
637 if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS ||
638 rep_block != 0xffff) {
639 printk("Block %d: incorrectly marked as first block in chain\n",
641 /* the chain is incorrect : we must format it,
642 but we need to read it completly */
645 printk("Block %d: folding in progress - ignoring first block flag\n",
651 if (rep_block == 0xffff) {
652 /* no more blocks after */
653 s->ReplUnitTable[block] = BLOCK_NIL;
655 } else if (rep_block >= s->nb_blocks) {
656 printk("Block %d: referencing invalid block %d\n",
659 s->ReplUnitTable[block] = BLOCK_NIL;
661 } else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) {
662 /* same problem as previous 'is_first_block' test:
663 we accept that the last block of a chain has
664 the first_block flag set if folding is in
665 progress. We handle here the case where the
666 last block appeared first */
667 if (s->ReplUnitTable[rep_block] == BLOCK_NIL &&
668 s->EUNtable[first_logical_block] == rep_block &&
669 get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) {
670 /* EUNtable[] will be set after */
671 printk("Block %d: folding in progress - ignoring first block flag\n",
673 s->ReplUnitTable[block] = rep_block;
674 s->EUNtable[first_logical_block] = BLOCK_NIL;
676 printk("Block %d: referencing block %d already in another chain\n",
678 /* XXX: should handle correctly fold in progress chains */
680 s->ReplUnitTable[block] = BLOCK_NIL;
685 s->ReplUnitTable[block] = rep_block;
690 /* the chain was completely explored. Now we can decide
691 what to do with it */
692 if (do_format_chain) {
693 /* invalid chain : format it */
694 format_chain(s, first_block);
696 unsigned int first_block1, chain_to_format, chain_length1;
699 /* valid chain : get foldmark */
700 fold_mark = get_fold_mark(s, first_block);
701 if (fold_mark == 0) {
702 /* cannot get foldmark : format the chain */
703 printk("Could read foldmark at block %d\n", first_block);
704 format_chain(s, first_block);
706 if (fold_mark == FOLD_MARK_IN_PROGRESS)
707 check_sectors_in_chain(s, first_block);
709 /* now handle the case where we find two chains at the
710 same virtual address : we select the longer one,
711 because the shorter one is the one which was being
712 folded if the folding was not done in place */
713 first_block1 = s->EUNtable[first_logical_block];
714 if (first_block1 != BLOCK_NIL) {
715 /* XXX: what to do if same length ? */
716 chain_length1 = calc_chain_length(s, first_block1);
717 printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
718 first_block1, chain_length1, first_block, chain_length);
720 if (chain_length >= chain_length1) {
721 chain_to_format = first_block1;
722 s->EUNtable[first_logical_block] = first_block;
724 chain_to_format = first_block;
726 format_chain(s, chain_to_format);
728 s->EUNtable[first_logical_block] = first_block;
733 examine_ReplUnitTable:;
736 /* second pass to format unreferenced blocks and init free block count */
738 s->LastFreeEUN = le16_to_cpu(s->MediaHdr.FirstPhysicalEUN);
740 for (block = 0; block < s->nb_blocks; block++) {
741 if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {
742 printk("Unreferenced block %d, formatting it\n", block);
743 if (NFTL_formatblock(s, block) < 0)
744 s->ReplUnitTable[block] = BLOCK_RESERVED;
746 s->ReplUnitTable[block] = BLOCK_FREE;
748 if (s->ReplUnitTable[block] == BLOCK_FREE) {
750 s->LastFreeEUN = block;