ia64/linux-2.6.18-xen.hg

view drivers/mtd/inftlmount.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * inftlmount.c -- INFTL mount code with extensive checks.
3 *
4 * Author: Greg Ungerer (gerg@snapgear.com)
5 * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com)
6 *
7 * Based heavily on the nftlmount.c code which is:
8 * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
9 * Copyright (C) 2000 Netgem S.A.
10 *
11 * $Id: inftlmount.c,v 1.18 2005/11/07 11:14:20 gleixner Exp $
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <asm/errno.h>
31 #include <asm/io.h>
32 #include <asm/uaccess.h>
33 #include <linux/miscdevice.h>
34 #include <linux/pci.h>
35 #include <linux/delay.h>
36 #include <linux/slab.h>
37 #include <linux/sched.h>
38 #include <linux/init.h>
39 #include <linux/mtd/mtd.h>
40 #include <linux/mtd/nftl.h>
41 #include <linux/mtd/inftl.h>
42 #include <linux/mtd/compatmac.h>
44 char inftlmountrev[]="$Revision: 1.18 $";
46 extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
47 size_t *retlen, uint8_t *buf);
48 extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
49 size_t *retlen, uint8_t *buf);
51 /*
52 * find_boot_record: Find the INFTL Media Header and its Spare copy which
53 * contains the various device information of the INFTL partition and
54 * Bad Unit Table. Update the PUtable[] table according to the Bad
55 * Unit Table. PUtable[] is used for management of Erase Unit in
56 * other routines in inftlcore.c and inftlmount.c.
57 */
58 static int find_boot_record(struct INFTLrecord *inftl)
59 {
60 struct inftl_unittail h1;
61 //struct inftl_oob oob;
62 unsigned int i, block;
63 u8 buf[SECTORSIZE];
64 struct INFTLMediaHeader *mh = &inftl->MediaHdr;
65 struct mtd_info *mtd = inftl->mbd.mtd;
66 struct INFTLPartition *ip;
67 size_t retlen;
69 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
71 /*
72 * Assume logical EraseSize == physical erasesize for starting the
73 * scan. We'll sort it out later if we find a MediaHeader which says
74 * otherwise.
75 */
76 inftl->EraseSize = inftl->mbd.mtd->erasesize;
77 inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
79 inftl->MediaUnit = BLOCK_NIL;
81 /* Search for a valid boot record */
82 for (block = 0; block < inftl->nb_blocks; block++) {
83 int ret;
85 /*
86 * Check for BNAND header first. Then whinge if it's found
87 * but later checks fail.
88 */
89 ret = mtd->read(mtd, block * inftl->EraseSize,
90 SECTORSIZE, &retlen, buf);
91 /* We ignore ret in case the ECC of the MediaHeader is invalid
92 (which is apparently acceptable) */
93 if (retlen != SECTORSIZE) {
94 static int warncount = 5;
96 if (warncount) {
97 printk(KERN_WARNING "INFTL: block read at 0x%x "
98 "of mtd%d failed: %d\n",
99 block * inftl->EraseSize,
100 inftl->mbd.mtd->index, ret);
101 if (!--warncount)
102 printk(KERN_WARNING "INFTL: further "
103 "failures for this block will "
104 "not be printed\n");
105 }
106 continue;
107 }
109 if (retlen < 6 || memcmp(buf, "BNAND", 6)) {
110 /* BNAND\0 not found. Continue */
111 continue;
112 }
114 /* To be safer with BIOS, also use erase mark as discriminant */
115 if ((ret = inftl_read_oob(mtd, block * inftl->EraseSize +
116 SECTORSIZE + 8, 8, &retlen,
117 (char *)&h1) < 0)) {
118 printk(KERN_WARNING "INFTL: ANAND header found at "
119 "0x%x in mtd%d, but OOB data read failed "
120 "(err %d)\n", block * inftl->EraseSize,
121 inftl->mbd.mtd->index, ret);
122 continue;
123 }
126 /*
127 * This is the first we've seen.
128 * Copy the media header structure into place.
129 */
130 memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
132 /* Read the spare media header at offset 4096 */
133 mtd->read(mtd, block * inftl->EraseSize + 4096,
134 SECTORSIZE, &retlen, buf);
135 if (retlen != SECTORSIZE) {
136 printk(KERN_WARNING "INFTL: Unable to read spare "
137 "Media Header\n");
138 return -1;
139 }
140 /* Check if this one is the same as the first one we found. */
141 if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
142 printk(KERN_WARNING "INFTL: Primary and spare Media "
143 "Headers disagree.\n");
144 return -1;
145 }
147 mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
148 mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
149 mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
150 mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
151 mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
152 mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
154 #ifdef CONFIG_MTD_DEBUG_VERBOSE
155 if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
156 printk("INFTL: Media Header ->\n"
157 " bootRecordID = %s\n"
158 " NoOfBootImageBlocks = %d\n"
159 " NoOfBinaryPartitions = %d\n"
160 " NoOfBDTLPartitions = %d\n"
161 " BlockMultiplerBits = %d\n"
162 " FormatFlgs = %d\n"
163 " OsakVersion = 0x%x\n"
164 " PercentUsed = %d\n",
165 mh->bootRecordID, mh->NoOfBootImageBlocks,
166 mh->NoOfBinaryPartitions,
167 mh->NoOfBDTLPartitions,
168 mh->BlockMultiplierBits, mh->FormatFlags,
169 mh->OsakVersion, mh->PercentUsed);
170 }
171 #endif
173 if (mh->NoOfBDTLPartitions == 0) {
174 printk(KERN_WARNING "INFTL: Media Header sanity check "
175 "failed: NoOfBDTLPartitions (%d) == 0, "
176 "must be at least 1\n", mh->NoOfBDTLPartitions);
177 return -1;
178 }
180 if ((mh->NoOfBDTLPartitions + mh->NoOfBinaryPartitions) > 4) {
181 printk(KERN_WARNING "INFTL: Media Header sanity check "
182 "failed: Total Partitions (%d) > 4, "
183 "BDTL=%d Binary=%d\n", mh->NoOfBDTLPartitions +
184 mh->NoOfBinaryPartitions,
185 mh->NoOfBDTLPartitions,
186 mh->NoOfBinaryPartitions);
187 return -1;
188 }
190 if (mh->BlockMultiplierBits > 1) {
191 printk(KERN_WARNING "INFTL: sorry, we don't support "
192 "UnitSizeFactor 0x%02x\n",
193 mh->BlockMultiplierBits);
194 return -1;
195 } else if (mh->BlockMultiplierBits == 1) {
196 printk(KERN_WARNING "INFTL: support for INFTL with "
197 "UnitSizeFactor 0x%02x is experimental\n",
198 mh->BlockMultiplierBits);
199 inftl->EraseSize = inftl->mbd.mtd->erasesize <<
200 mh->BlockMultiplierBits;
201 inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
202 block >>= mh->BlockMultiplierBits;
203 }
205 /* Scan the partitions */
206 for (i = 0; (i < 4); i++) {
207 ip = &mh->Partitions[i];
208 ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
209 ip->firstUnit = le32_to_cpu(ip->firstUnit);
210 ip->lastUnit = le32_to_cpu(ip->lastUnit);
211 ip->flags = le32_to_cpu(ip->flags);
212 ip->spareUnits = le32_to_cpu(ip->spareUnits);
213 ip->Reserved0 = le32_to_cpu(ip->Reserved0);
215 #ifdef CONFIG_MTD_DEBUG_VERBOSE
216 if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
217 printk(" PARTITION[%d] ->\n"
218 " virtualUnits = %d\n"
219 " firstUnit = %d\n"
220 " lastUnit = %d\n"
221 " flags = 0x%x\n"
222 " spareUnits = %d\n",
223 i, ip->virtualUnits, ip->firstUnit,
224 ip->lastUnit, ip->flags,
225 ip->spareUnits);
226 }
227 #endif
229 if (ip->Reserved0 != ip->firstUnit) {
230 struct erase_info *instr = &inftl->instr;
232 instr->mtd = inftl->mbd.mtd;
234 /*
235 * Most likely this is using the
236 * undocumented qiuck mount feature.
237 * We don't support that, we will need
238 * to erase the hidden block for full
239 * compatibility.
240 */
241 instr->addr = ip->Reserved0 * inftl->EraseSize;
242 instr->len = inftl->EraseSize;
243 mtd->erase(mtd, instr);
244 }
245 if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
246 printk(KERN_WARNING "INFTL: Media Header "
247 "Partition %d sanity check failed\n"
248 " firstUnit %d : lastUnit %d > "
249 "virtualUnits %d\n", i, ip->lastUnit,
250 ip->firstUnit, ip->Reserved0);
251 return -1;
252 }
253 if (ip->Reserved1 != 0) {
254 printk(KERN_WARNING "INFTL: Media Header "
255 "Partition %d sanity check failed: "
256 "Reserved1 %d != 0\n",
257 i, ip->Reserved1);
258 return -1;
259 }
261 if (ip->flags & INFTL_BDTL)
262 break;
263 }
265 if (i >= 4) {
266 printk(KERN_WARNING "INFTL: Media Header Partition "
267 "sanity check failed:\n No partition "
268 "marked as Disk Partition\n");
269 return -1;
270 }
272 inftl->nb_boot_blocks = ip->firstUnit;
273 inftl->numvunits = ip->virtualUnits;
274 if (inftl->numvunits > (inftl->nb_blocks -
275 inftl->nb_boot_blocks - 2)) {
276 printk(KERN_WARNING "INFTL: Media Header sanity check "
277 "failed:\n numvunits (%d) > nb_blocks "
278 "(%d) - nb_boot_blocks(%d) - 2\n",
279 inftl->numvunits, inftl->nb_blocks,
280 inftl->nb_boot_blocks);
281 return -1;
282 }
284 inftl->mbd.size = inftl->numvunits *
285 (inftl->EraseSize / SECTORSIZE);
287 /*
288 * Block count is set to last used EUN (we won't need to keep
289 * any meta-data past that point).
290 */
291 inftl->firstEUN = ip->firstUnit;
292 inftl->lastEUN = ip->lastUnit;
293 inftl->nb_blocks = ip->lastUnit + 1;
295 /* Memory alloc */
296 inftl->PUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL);
297 if (!inftl->PUtable) {
298 printk(KERN_WARNING "INFTL: allocation of PUtable "
299 "failed (%zd bytes)\n",
300 inftl->nb_blocks * sizeof(u16));
301 return -ENOMEM;
302 }
304 inftl->VUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL);
305 if (!inftl->VUtable) {
306 kfree(inftl->PUtable);
307 printk(KERN_WARNING "INFTL: allocation of VUtable "
308 "failed (%zd bytes)\n",
309 inftl->nb_blocks * sizeof(u16));
310 return -ENOMEM;
311 }
313 /* Mark the blocks before INFTL MediaHeader as reserved */
314 for (i = 0; i < inftl->nb_boot_blocks; i++)
315 inftl->PUtable[i] = BLOCK_RESERVED;
316 /* Mark all remaining blocks as potentially containing data */
317 for (; i < inftl->nb_blocks; i++)
318 inftl->PUtable[i] = BLOCK_NOTEXPLORED;
320 /* Mark this boot record (NFTL MediaHeader) block as reserved */
321 inftl->PUtable[block] = BLOCK_RESERVED;
323 /* Read Bad Erase Unit Table and modify PUtable[] accordingly */
324 for (i = 0; i < inftl->nb_blocks; i++) {
325 int physblock;
326 /* If any of the physical eraseblocks are bad, don't
327 use the unit. */
328 for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
329 if (inftl->mbd.mtd->block_isbad(inftl->mbd.mtd, i * inftl->EraseSize + physblock))
330 inftl->PUtable[i] = BLOCK_RESERVED;
331 }
332 }
334 inftl->MediaUnit = block;
335 return 0;
336 }
338 /* Not found. */
339 return -1;
340 }
342 static int memcmpb(void *a, int c, int n)
343 {
344 int i;
345 for (i = 0; i < n; i++) {
346 if (c != ((unsigned char *)a)[i])
347 return 1;
348 }
349 return 0;
350 }
352 /*
353 * check_free_sector: check if a free sector is actually FREE,
354 * i.e. All 0xff in data and oob area.
355 */
356 static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
357 int len, int check_oob)
358 {
359 u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
360 struct mtd_info *mtd = inftl->mbd.mtd;
361 size_t retlen;
362 int i;
364 for (i = 0; i < len; i += SECTORSIZE) {
365 if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
366 return -1;
367 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
368 return -1;
370 if (check_oob) {
371 if(inftl_read_oob(mtd, address, mtd->oobsize,
372 &retlen, &buf[SECTORSIZE]) < 0)
373 return -1;
374 if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
375 return -1;
376 }
377 address += SECTORSIZE;
378 }
380 return 0;
381 }
383 /*
384 * INFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase
385 * Unit and Update INFTL metadata. Each erase operation is
386 * checked with check_free_sectors.
387 *
388 * Return: 0 when succeed, -1 on error.
389 *
390 * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
391 */
392 int INFTL_formatblock(struct INFTLrecord *inftl, int block)
393 {
394 size_t retlen;
395 struct inftl_unittail uci;
396 struct erase_info *instr = &inftl->instr;
397 struct mtd_info *mtd = inftl->mbd.mtd;
398 int physblock;
400 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
401 "block=%d)\n", inftl, block);
403 memset(instr, 0, sizeof(struct erase_info));
405 /* FIXME: Shouldn't we be setting the 'discarded' flag to zero
406 _first_? */
408 /* Use async erase interface, test return code */
409 instr->mtd = inftl->mbd.mtd;
410 instr->addr = block * inftl->EraseSize;
411 instr->len = inftl->mbd.mtd->erasesize;
412 /* Erase one physical eraseblock at a time, even though the NAND api
413 allows us to group them. This way we if we have a failure, we can
414 mark only the failed block in the bbt. */
415 for (physblock = 0; physblock < inftl->EraseSize;
416 physblock += instr->len, instr->addr += instr->len) {
417 mtd->erase(inftl->mbd.mtd, instr);
419 if (instr->state == MTD_ERASE_FAILED) {
420 printk(KERN_WARNING "INFTL: error while formatting block %d\n",
421 block);
422 goto fail;
423 }
425 /*
426 * Check the "freeness" of Erase Unit before updating metadata.
427 * FixMe: is this check really necessary? Since we have check
428 * the return code after the erase operation.
429 */
430 if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
431 goto fail;
432 }
434 uci.EraseMark = cpu_to_le16(ERASE_MARK);
435 uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
436 uci.Reserved[0] = 0;
437 uci.Reserved[1] = 0;
438 uci.Reserved[2] = 0;
439 uci.Reserved[3] = 0;
440 instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
441 if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0)
442 goto fail;
443 return 0;
444 fail:
445 /* could not format, update the bad block table (caller is responsible
446 for setting the PUtable to BLOCK_RESERVED on failure) */
447 inftl->mbd.mtd->block_markbad(inftl->mbd.mtd, instr->addr);
448 return -1;
449 }
451 /*
452 * format_chain: Format an invalid Virtual Unit chain. It frees all the Erase
453 * Units in a Virtual Unit Chain, i.e. all the units are disconnected.
454 *
455 * Since the chain is invalid then we will have to erase it from its
456 * head (normally for INFTL we go from the oldest). But if it has a
457 * loop then there is no oldest...
458 */
459 static void format_chain(struct INFTLrecord *inftl, unsigned int first_block)
460 {
461 unsigned int block = first_block, block1;
463 printk(KERN_WARNING "INFTL: formatting chain at block %d\n",
464 first_block);
466 for (;;) {
467 block1 = inftl->PUtable[block];
469 printk(KERN_WARNING "INFTL: formatting block %d\n", block);
470 if (INFTL_formatblock(inftl, block) < 0) {
471 /*
472 * Cannot format !!!! Mark it as Bad Unit,
473 */
474 inftl->PUtable[block] = BLOCK_RESERVED;
475 } else {
476 inftl->PUtable[block] = BLOCK_FREE;
477 }
479 /* Goto next block on the chain */
480 block = block1;
482 if (block == BLOCK_NIL || block >= inftl->lastEUN)
483 break;
484 }
485 }
487 void INFTL_dumptables(struct INFTLrecord *s)
488 {
489 int i;
491 printk("-------------------------------------------"
492 "----------------------------------\n");
494 printk("VUtable[%d] ->", s->nb_blocks);
495 for (i = 0; i < s->nb_blocks; i++) {
496 if ((i % 8) == 0)
497 printk("\n%04x: ", i);
498 printk("%04x ", s->VUtable[i]);
499 }
501 printk("\n-------------------------------------------"
502 "----------------------------------\n");
504 printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
505 for (i = 0; i <= s->lastEUN; i++) {
506 if ((i % 8) == 0)
507 printk("\n%04x: ", i);
508 printk("%04x ", s->PUtable[i]);
509 }
511 printk("\n-------------------------------------------"
512 "----------------------------------\n");
514 printk("INFTL ->\n"
515 " EraseSize = %d\n"
516 " h/s/c = %d/%d/%d\n"
517 " numvunits = %d\n"
518 " firstEUN = %d\n"
519 " lastEUN = %d\n"
520 " numfreeEUNs = %d\n"
521 " LastFreeEUN = %d\n"
522 " nb_blocks = %d\n"
523 " nb_boot_blocks = %d",
524 s->EraseSize, s->heads, s->sectors, s->cylinders,
525 s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
526 s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
528 printk("\n-------------------------------------------"
529 "----------------------------------\n");
530 }
532 void INFTL_dumpVUchains(struct INFTLrecord *s)
533 {
534 int logical, block, i;
536 printk("-------------------------------------------"
537 "----------------------------------\n");
539 printk("INFTL Virtual Unit Chains:\n");
540 for (logical = 0; logical < s->nb_blocks; logical++) {
541 block = s->VUtable[logical];
542 if (block > s->nb_blocks)
543 continue;
544 printk(" LOGICAL %d --> %d ", logical, block);
545 for (i = 0; i < s->nb_blocks; i++) {
546 if (s->PUtable[block] == BLOCK_NIL)
547 break;
548 block = s->PUtable[block];
549 printk("%d ", block);
550 }
551 printk("\n");
552 }
554 printk("-------------------------------------------"
555 "----------------------------------\n");
556 }
558 int INFTL_mount(struct INFTLrecord *s)
559 {
560 struct mtd_info *mtd = s->mbd.mtd;
561 unsigned int block, first_block, prev_block, last_block;
562 unsigned int first_logical_block, logical_block, erase_mark;
563 int chain_length, do_format_chain;
564 struct inftl_unithead1 h0;
565 struct inftl_unittail h1;
566 size_t retlen;
567 int i;
568 u8 *ANACtable, ANAC;
570 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);
572 /* Search for INFTL MediaHeader and Spare INFTL Media Header */
573 if (find_boot_record(s) < 0) {
574 printk(KERN_WARNING "INFTL: could not find valid boot record?\n");
575 return -ENXIO;
576 }
578 /* Init the logical to physical table */
579 for (i = 0; i < s->nb_blocks; i++)
580 s->VUtable[i] = BLOCK_NIL;
582 logical_block = block = BLOCK_NIL;
584 /* Temporary buffer to store ANAC numbers. */
585 ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL);
586 if (!ANACtable) {
587 printk(KERN_WARNING "INFTL: allocation of ANACtable "
588 "failed (%zd bytes)\n",
589 s->nb_blocks * sizeof(u8));
590 return -ENOMEM;
591 }
592 memset(ANACtable, 0, s->nb_blocks);
594 /*
595 * First pass is to explore each physical unit, and construct the
596 * virtual chains that exist (newest physical unit goes into VUtable).
597 * Any block that is in any way invalid will be left in the
598 * NOTEXPLORED state. Then at the end we will try to format it and
599 * mark it as free.
600 */
601 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n");
602 for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
603 if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
604 continue;
606 do_format_chain = 0;
607 first_logical_block = BLOCK_NIL;
608 last_block = BLOCK_NIL;
609 block = first_block;
611 for (chain_length = 0; ; chain_length++) {
613 if ((chain_length == 0) &&
614 (s->PUtable[block] != BLOCK_NOTEXPLORED)) {
615 /* Nothing to do here, onto next block */
616 break;
617 }
619 if (inftl_read_oob(mtd, block * s->EraseSize + 8,
620 8, &retlen, (char *)&h0) < 0 ||
621 inftl_read_oob(mtd, block * s->EraseSize +
622 2 * SECTORSIZE + 8, 8, &retlen,
623 (char *)&h1) < 0) {
624 /* Should never happen? */
625 do_format_chain++;
626 break;
627 }
629 logical_block = le16_to_cpu(h0.virtualUnitNo);
630 prev_block = le16_to_cpu(h0.prevUnitNo);
631 erase_mark = le16_to_cpu((h1.EraseMark | h1.EraseMark1));
632 ANACtable[block] = h0.ANAC;
634 /* Previous block is relative to start of Partition */
635 if (prev_block < s->nb_blocks)
636 prev_block += s->firstEUN;
638 /* Already explored partial chain? */
639 if (s->PUtable[block] != BLOCK_NOTEXPLORED) {
640 /* Check if chain for this logical */
641 if (logical_block == first_logical_block) {
642 if (last_block != BLOCK_NIL)
643 s->PUtable[last_block] = block;
644 }
645 break;
646 }
648 /* Check for invalid block */
649 if (erase_mark != ERASE_MARK) {
650 printk(KERN_WARNING "INFTL: corrupt block %d "
651 "in chain %d, chain length %d, erase "
652 "mark 0x%x?\n", block, first_block,
653 chain_length, erase_mark);
654 /*
655 * Assume end of chain, probably incomplete
656 * fold/erase...
657 */
658 if (chain_length == 0)
659 do_format_chain++;
660 break;
661 }
663 /* Check for it being free already then... */
664 if ((logical_block == BLOCK_FREE) ||
665 (logical_block == BLOCK_NIL)) {
666 s->PUtable[block] = BLOCK_FREE;
667 break;
668 }
670 /* Sanity checks on block numbers */
671 if ((logical_block >= s->nb_blocks) ||
672 ((prev_block >= s->nb_blocks) &&
673 (prev_block != BLOCK_NIL))) {
674 if (chain_length > 0) {
675 printk(KERN_WARNING "INFTL: corrupt "
676 "block %d in chain %d?\n",
677 block, first_block);
678 do_format_chain++;
679 }
680 break;
681 }
683 if (first_logical_block == BLOCK_NIL) {
684 first_logical_block = logical_block;
685 } else {
686 if (first_logical_block != logical_block) {
687 /* Normal for folded chain... */
688 break;
689 }
690 }
692 /*
693 * Current block is valid, so if we followed a virtual
694 * chain to get here then we can set the previous
695 * block pointer in our PUtable now. Then move onto
696 * the previous block in the chain.
697 */
698 s->PUtable[block] = BLOCK_NIL;
699 if (last_block != BLOCK_NIL)
700 s->PUtable[last_block] = block;
701 last_block = block;
702 block = prev_block;
704 /* Check for end of chain */
705 if (block == BLOCK_NIL)
706 break;
708 /* Validate next block before following it... */
709 if (block > s->lastEUN) {
710 printk(KERN_WARNING "INFTL: invalid previous "
711 "block %d in chain %d?\n", block,
712 first_block);
713 do_format_chain++;
714 break;
715 }
716 }
718 if (do_format_chain) {
719 format_chain(s, first_block);
720 continue;
721 }
723 /*
724 * Looks like a valid chain then. It may not really be the
725 * newest block in the chain, but it is the newest we have
726 * found so far. We might update it in later iterations of
727 * this loop if we find something newer.
728 */
729 s->VUtable[first_logical_block] = first_block;
730 logical_block = BLOCK_NIL;
731 }
733 #ifdef CONFIG_MTD_DEBUG_VERBOSE
734 if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
735 INFTL_dumptables(s);
736 #endif
738 /*
739 * Second pass, check for infinite loops in chains. These are
740 * possible because we don't update the previous pointers when
741 * we fold chains. No big deal, just fix them up in PUtable.
742 */
743 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n");
744 for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
745 block = s->VUtable[logical_block];
746 last_block = BLOCK_NIL;
748 /* Check for free/reserved/nil */
749 if (block >= BLOCK_RESERVED)
750 continue;
752 ANAC = ANACtable[block];
753 for (i = 0; i < s->numvunits; i++) {
754 if (s->PUtable[block] == BLOCK_NIL)
755 break;
756 if (s->PUtable[block] > s->lastEUN) {
757 printk(KERN_WARNING "INFTL: invalid prev %d, "
758 "in virtual chain %d\n",
759 s->PUtable[block], logical_block);
760 s->PUtable[block] = BLOCK_NIL;
762 }
763 if (ANACtable[block] != ANAC) {
764 /*
765 * Chain must point back to itself. This is ok,
766 * but we will need adjust the tables with this
767 * newest block and oldest block.
768 */
769 s->VUtable[logical_block] = block;
770 s->PUtable[last_block] = BLOCK_NIL;
771 break;
772 }
774 ANAC--;
775 last_block = block;
776 block = s->PUtable[block];
777 }
779 if (i >= s->nb_blocks) {
780 /*
781 * Uhoo, infinite chain with valid ANACS!
782 * Format whole chain...
783 */
784 format_chain(s, first_block);
785 }
786 }
788 #ifdef CONFIG_MTD_DEBUG_VERBOSE
789 if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
790 INFTL_dumptables(s);
791 if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
792 INFTL_dumpVUchains(s);
793 #endif
795 /*
796 * Third pass, format unreferenced blocks and init free block count.
797 */
798 s->numfreeEUNs = 0;
799 s->LastFreeEUN = BLOCK_NIL;
801 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n");
802 for (block = s->firstEUN; block <= s->lastEUN; block++) {
803 if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
804 printk("INFTL: unreferenced block %d, formatting it\n",
805 block);
806 if (INFTL_formatblock(s, block) < 0)
807 s->PUtable[block] = BLOCK_RESERVED;
808 else
809 s->PUtable[block] = BLOCK_FREE;
810 }
811 if (s->PUtable[block] == BLOCK_FREE) {
812 s->numfreeEUNs++;
813 if (s->LastFreeEUN == BLOCK_NIL)
814 s->LastFreeEUN = block;
815 }
816 }
818 kfree(ANACtable);
819 return 0;
820 }