0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <asm/errno.h>
0016 #include <asm/io.h>
0017 #include <linux/uaccess.h>
0018 #include <linux/delay.h>
0019 #include <linux/slab.h>
0020 #include <linux/mtd/mtd.h>
0021 #include <linux/mtd/nftl.h>
0022 #include <linux/mtd/inftl.h>
0023
0024
0025
0026
0027
0028
0029
0030
0031 static int find_boot_record(struct INFTLrecord *inftl)
0032 {
0033 struct inftl_unittail h1;
0034
0035 unsigned int i, block;
0036 u8 buf[SECTORSIZE];
0037 struct INFTLMediaHeader *mh = &inftl->MediaHdr;
0038 struct mtd_info *mtd = inftl->mbd.mtd;
0039 struct INFTLPartition *ip;
0040 size_t retlen;
0041
0042 pr_debug("INFTL: find_boot_record(inftl=%p)\n", inftl);
0043
0044
0045
0046
0047
0048
0049 inftl->EraseSize = inftl->mbd.mtd->erasesize;
0050 inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
0051
0052 inftl->MediaUnit = BLOCK_NIL;
0053
0054
0055 for (block = 0; block < inftl->nb_blocks; block++) {
0056 int ret;
0057
0058
0059
0060
0061
0062 ret = mtd_read(mtd, block * inftl->EraseSize, SECTORSIZE,
0063 &retlen, buf);
0064
0065
0066 if (retlen != SECTORSIZE) {
0067 static int warncount = 5;
0068
0069 if (warncount) {
0070 printk(KERN_WARNING "INFTL: block read at 0x%x "
0071 "of mtd%d failed: %d\n",
0072 block * inftl->EraseSize,
0073 inftl->mbd.mtd->index, ret);
0074 if (!--warncount)
0075 printk(KERN_WARNING "INFTL: further "
0076 "failures for this block will "
0077 "not be printed\n");
0078 }
0079 continue;
0080 }
0081
0082 if (retlen < 6 || memcmp(buf, "BNAND", 6)) {
0083
0084 continue;
0085 }
0086
0087
0088 ret = inftl_read_oob(mtd,
0089 block * inftl->EraseSize + SECTORSIZE + 8,
0090 8, &retlen,(char *)&h1);
0091 if (ret < 0) {
0092 printk(KERN_WARNING "INFTL: ANAND header found at "
0093 "0x%x in mtd%d, but OOB data read failed "
0094 "(err %d)\n", block * inftl->EraseSize,
0095 inftl->mbd.mtd->index, ret);
0096 continue;
0097 }
0098
0099
0100
0101
0102
0103
0104 memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
0105
0106
0107 mtd_read(mtd, block * inftl->EraseSize + 4096, SECTORSIZE,
0108 &retlen, buf);
0109 if (retlen != SECTORSIZE) {
0110 printk(KERN_WARNING "INFTL: Unable to read spare "
0111 "Media Header\n");
0112 return -1;
0113 }
0114
0115 if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
0116 printk(KERN_WARNING "INFTL: Primary and spare Media "
0117 "Headers disagree.\n");
0118 return -1;
0119 }
0120
0121 mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
0122 mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
0123 mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
0124 mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
0125 mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
0126 mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
0127
0128 pr_debug("INFTL: Media Header ->\n"
0129 " bootRecordID = %s\n"
0130 " NoOfBootImageBlocks = %d\n"
0131 " NoOfBinaryPartitions = %d\n"
0132 " NoOfBDTLPartitions = %d\n"
0133 " BlockMultiplierBits = %d\n"
0134 " FormatFlgs = %d\n"
0135 " OsakVersion = 0x%x\n"
0136 " PercentUsed = %d\n",
0137 mh->bootRecordID, mh->NoOfBootImageBlocks,
0138 mh->NoOfBinaryPartitions,
0139 mh->NoOfBDTLPartitions,
0140 mh->BlockMultiplierBits, mh->FormatFlags,
0141 mh->OsakVersion, mh->PercentUsed);
0142
0143 if (mh->NoOfBDTLPartitions == 0) {
0144 printk(KERN_WARNING "INFTL: Media Header sanity check "
0145 "failed: NoOfBDTLPartitions (%d) == 0, "
0146 "must be at least 1\n", mh->NoOfBDTLPartitions);
0147 return -1;
0148 }
0149
0150 if ((mh->NoOfBDTLPartitions + mh->NoOfBinaryPartitions) > 4) {
0151 printk(KERN_WARNING "INFTL: Media Header sanity check "
0152 "failed: Total Partitions (%d) > 4, "
0153 "BDTL=%d Binary=%d\n", mh->NoOfBDTLPartitions +
0154 mh->NoOfBinaryPartitions,
0155 mh->NoOfBDTLPartitions,
0156 mh->NoOfBinaryPartitions);
0157 return -1;
0158 }
0159
0160 if (mh->BlockMultiplierBits > 1) {
0161 printk(KERN_WARNING "INFTL: sorry, we don't support "
0162 "UnitSizeFactor 0x%02x\n",
0163 mh->BlockMultiplierBits);
0164 return -1;
0165 } else if (mh->BlockMultiplierBits == 1) {
0166 printk(KERN_WARNING "INFTL: support for INFTL with "
0167 "UnitSizeFactor 0x%02x is experimental\n",
0168 mh->BlockMultiplierBits);
0169 inftl->EraseSize = inftl->mbd.mtd->erasesize <<
0170 mh->BlockMultiplierBits;
0171 inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
0172 block >>= mh->BlockMultiplierBits;
0173 }
0174
0175
0176 for (i = 0; (i < 4); i++) {
0177 ip = &mh->Partitions[i];
0178 ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
0179 ip->firstUnit = le32_to_cpu(ip->firstUnit);
0180 ip->lastUnit = le32_to_cpu(ip->lastUnit);
0181 ip->flags = le32_to_cpu(ip->flags);
0182 ip->spareUnits = le32_to_cpu(ip->spareUnits);
0183 ip->Reserved0 = le32_to_cpu(ip->Reserved0);
0184
0185 pr_debug(" PARTITION[%d] ->\n"
0186 " virtualUnits = %d\n"
0187 " firstUnit = %d\n"
0188 " lastUnit = %d\n"
0189 " flags = 0x%x\n"
0190 " spareUnits = %d\n",
0191 i, ip->virtualUnits, ip->firstUnit,
0192 ip->lastUnit, ip->flags,
0193 ip->spareUnits);
0194
0195 if (ip->Reserved0 != ip->firstUnit) {
0196 struct erase_info *instr = &inftl->instr;
0197
0198
0199
0200
0201
0202
0203
0204
0205 instr->addr = ip->Reserved0 * inftl->EraseSize;
0206 instr->len = inftl->EraseSize;
0207 mtd_erase(mtd, instr);
0208 }
0209 if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
0210 printk(KERN_WARNING "INFTL: Media Header "
0211 "Partition %d sanity check failed\n"
0212 " firstUnit %d : lastUnit %d > "
0213 "virtualUnits %d\n", i, ip->lastUnit,
0214 ip->firstUnit, ip->Reserved0);
0215 return -1;
0216 }
0217 if (ip->Reserved1 != 0) {
0218 printk(KERN_WARNING "INFTL: Media Header "
0219 "Partition %d sanity check failed: "
0220 "Reserved1 %d != 0\n",
0221 i, ip->Reserved1);
0222 return -1;
0223 }
0224
0225 if (ip->flags & INFTL_BDTL)
0226 break;
0227 }
0228
0229 if (i >= 4) {
0230 printk(KERN_WARNING "INFTL: Media Header Partition "
0231 "sanity check failed:\n No partition "
0232 "marked as Disk Partition\n");
0233 return -1;
0234 }
0235
0236 inftl->nb_boot_blocks = ip->firstUnit;
0237 inftl->numvunits = ip->virtualUnits;
0238 if (inftl->numvunits > (inftl->nb_blocks -
0239 inftl->nb_boot_blocks - 2)) {
0240 printk(KERN_WARNING "INFTL: Media Header sanity check "
0241 "failed:\n numvunits (%d) > nb_blocks "
0242 "(%d) - nb_boot_blocks(%d) - 2\n",
0243 inftl->numvunits, inftl->nb_blocks,
0244 inftl->nb_boot_blocks);
0245 return -1;
0246 }
0247
0248 inftl->mbd.size = inftl->numvunits *
0249 (inftl->EraseSize / SECTORSIZE);
0250
0251
0252
0253
0254
0255 inftl->firstEUN = ip->firstUnit;
0256 inftl->lastEUN = ip->lastUnit;
0257 inftl->nb_blocks = ip->lastUnit + 1;
0258
0259
0260 inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
0261 GFP_KERNEL);
0262 if (!inftl->PUtable)
0263 return -ENOMEM;
0264
0265 inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
0266 GFP_KERNEL);
0267 if (!inftl->VUtable) {
0268 kfree(inftl->PUtable);
0269 return -ENOMEM;
0270 }
0271
0272
0273 for (i = 0; i < inftl->nb_boot_blocks; i++)
0274 inftl->PUtable[i] = BLOCK_RESERVED;
0275
0276 for (; i < inftl->nb_blocks; i++)
0277 inftl->PUtable[i] = BLOCK_NOTEXPLORED;
0278
0279
0280 inftl->PUtable[block] = BLOCK_RESERVED;
0281
0282
0283 for (i = 0; i < inftl->nb_blocks; i++) {
0284 int physblock;
0285
0286
0287 for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
0288 if (mtd_block_isbad(inftl->mbd.mtd,
0289 i * inftl->EraseSize + physblock))
0290 inftl->PUtable[i] = BLOCK_RESERVED;
0291 }
0292 }
0293
0294 inftl->MediaUnit = block;
0295 return 0;
0296 }
0297
0298
0299 return -1;
0300 }
0301
0302 static int memcmpb(void *a, int c, int n)
0303 {
0304 int i;
0305 for (i = 0; i < n; i++) {
0306 if (c != ((unsigned char *)a)[i])
0307 return 1;
0308 }
0309 return 0;
0310 }
0311
0312
0313
0314
0315
0316 static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
0317 int len, int check_oob)
0318 {
0319 struct mtd_info *mtd = inftl->mbd.mtd;
0320 size_t retlen;
0321 int i, ret;
0322 u8 *buf;
0323
0324 buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL);
0325 if (!buf)
0326 return -ENOMEM;
0327
0328 ret = -1;
0329 for (i = 0; i < len; i += SECTORSIZE) {
0330 if (mtd_read(mtd, address, SECTORSIZE, &retlen, buf))
0331 goto out;
0332 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
0333 goto out;
0334
0335 if (check_oob) {
0336 if(inftl_read_oob(mtd, address, mtd->oobsize,
0337 &retlen, &buf[SECTORSIZE]) < 0)
0338 goto out;
0339 if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
0340 goto out;
0341 }
0342 address += SECTORSIZE;
0343 }
0344
0345 ret = 0;
0346
0347 out:
0348 kfree(buf);
0349 return ret;
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361 int INFTL_formatblock(struct INFTLrecord *inftl, int block)
0362 {
0363 size_t retlen;
0364 struct inftl_unittail uci;
0365 struct erase_info *instr = &inftl->instr;
0366 struct mtd_info *mtd = inftl->mbd.mtd;
0367 int physblock;
0368
0369 pr_debug("INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block);
0370
0371 memset(instr, 0, sizeof(struct erase_info));
0372
0373
0374
0375
0376
0377 instr->addr = block * inftl->EraseSize;
0378 instr->len = inftl->mbd.mtd->erasesize;
0379
0380
0381
0382 for (physblock = 0; physblock < inftl->EraseSize;
0383 physblock += instr->len, instr->addr += instr->len) {
0384 int ret;
0385
0386 ret = mtd_erase(inftl->mbd.mtd, instr);
0387 if (ret) {
0388 printk(KERN_WARNING "INFTL: error while formatting block %d\n",
0389 block);
0390 goto fail;
0391 }
0392
0393
0394
0395
0396
0397
0398 if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
0399 goto fail;
0400 }
0401
0402 uci.EraseMark = cpu_to_le16(ERASE_MARK);
0403 uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
0404 uci.Reserved[0] = 0;
0405 uci.Reserved[1] = 0;
0406 uci.Reserved[2] = 0;
0407 uci.Reserved[3] = 0;
0408 instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
0409 if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0)
0410 goto fail;
0411 return 0;
0412 fail:
0413
0414
0415 mtd_block_markbad(inftl->mbd.mtd, instr->addr);
0416 return -1;
0417 }
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 static void format_chain(struct INFTLrecord *inftl, unsigned int first_block)
0428 {
0429 unsigned int block = first_block, block1;
0430
0431 printk(KERN_WARNING "INFTL: formatting chain at block %d\n",
0432 first_block);
0433
0434 for (;;) {
0435 block1 = inftl->PUtable[block];
0436
0437 printk(KERN_WARNING "INFTL: formatting block %d\n", block);
0438 if (INFTL_formatblock(inftl, block) < 0) {
0439
0440
0441
0442 inftl->PUtable[block] = BLOCK_RESERVED;
0443 } else {
0444 inftl->PUtable[block] = BLOCK_FREE;
0445 }
0446
0447
0448 block = block1;
0449
0450 if (block == BLOCK_NIL || block >= inftl->lastEUN)
0451 break;
0452 }
0453 }
0454
0455 void INFTL_dumptables(struct INFTLrecord *s)
0456 {
0457 int i;
0458
0459 pr_debug("-------------------------------------------"
0460 "----------------------------------\n");
0461
0462 pr_debug("VUtable[%d] ->", s->nb_blocks);
0463 for (i = 0; i < s->nb_blocks; i++) {
0464 if ((i % 8) == 0)
0465 pr_debug("\n%04x: ", i);
0466 pr_debug("%04x ", s->VUtable[i]);
0467 }
0468
0469 pr_debug("\n-------------------------------------------"
0470 "----------------------------------\n");
0471
0472 pr_debug("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
0473 for (i = 0; i <= s->lastEUN; i++) {
0474 if ((i % 8) == 0)
0475 pr_debug("\n%04x: ", i);
0476 pr_debug("%04x ", s->PUtable[i]);
0477 }
0478
0479 pr_debug("\n-------------------------------------------"
0480 "----------------------------------\n");
0481
0482 pr_debug("INFTL ->\n"
0483 " EraseSize = %d\n"
0484 " h/s/c = %d/%d/%d\n"
0485 " numvunits = %d\n"
0486 " firstEUN = %d\n"
0487 " lastEUN = %d\n"
0488 " numfreeEUNs = %d\n"
0489 " LastFreeEUN = %d\n"
0490 " nb_blocks = %d\n"
0491 " nb_boot_blocks = %d",
0492 s->EraseSize, s->heads, s->sectors, s->cylinders,
0493 s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
0494 s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
0495
0496 pr_debug("\n-------------------------------------------"
0497 "----------------------------------\n");
0498 }
0499
0500 void INFTL_dumpVUchains(struct INFTLrecord *s)
0501 {
0502 int logical, block, i;
0503
0504 pr_debug("-------------------------------------------"
0505 "----------------------------------\n");
0506
0507 pr_debug("INFTL Virtual Unit Chains:\n");
0508 for (logical = 0; logical < s->nb_blocks; logical++) {
0509 block = s->VUtable[logical];
0510 if (block >= s->nb_blocks)
0511 continue;
0512 pr_debug(" LOGICAL %d --> %d ", logical, block);
0513 for (i = 0; i < s->nb_blocks; i++) {
0514 if (s->PUtable[block] == BLOCK_NIL)
0515 break;
0516 block = s->PUtable[block];
0517 pr_debug("%d ", block);
0518 }
0519 pr_debug("\n");
0520 }
0521
0522 pr_debug("-------------------------------------------"
0523 "----------------------------------\n");
0524 }
0525
0526 int INFTL_mount(struct INFTLrecord *s)
0527 {
0528 struct mtd_info *mtd = s->mbd.mtd;
0529 unsigned int block, first_block, prev_block, last_block;
0530 unsigned int first_logical_block, logical_block, erase_mark;
0531 int chain_length, do_format_chain;
0532 struct inftl_unithead1 h0;
0533 struct inftl_unittail h1;
0534 size_t retlen;
0535 int i;
0536 u8 *ANACtable, ANAC;
0537
0538 pr_debug("INFTL: INFTL_mount(inftl=%p)\n", s);
0539
0540
0541 if (find_boot_record(s) < 0) {
0542 printk(KERN_WARNING "INFTL: could not find valid boot record?\n");
0543 return -ENXIO;
0544 }
0545
0546
0547 for (i = 0; i < s->nb_blocks; i++)
0548 s->VUtable[i] = BLOCK_NIL;
0549
0550 logical_block = block = BLOCK_NIL;
0551
0552
0553 ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL);
0554 if (!ANACtable)
0555 return -ENOMEM;
0556
0557
0558
0559
0560
0561
0562
0563
0564 pr_debug("INFTL: pass 1, explore each unit\n");
0565 for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
0566 if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
0567 continue;
0568
0569 do_format_chain = 0;
0570 first_logical_block = BLOCK_NIL;
0571 last_block = BLOCK_NIL;
0572 block = first_block;
0573
0574 for (chain_length = 0; ; chain_length++) {
0575
0576 if ((chain_length == 0) &&
0577 (s->PUtable[block] != BLOCK_NOTEXPLORED)) {
0578
0579 break;
0580 }
0581
0582 if (inftl_read_oob(mtd, block * s->EraseSize + 8,
0583 8, &retlen, (char *)&h0) < 0 ||
0584 inftl_read_oob(mtd, block * s->EraseSize +
0585 2 * SECTORSIZE + 8, 8, &retlen,
0586 (char *)&h1) < 0) {
0587
0588 do_format_chain++;
0589 break;
0590 }
0591
0592 logical_block = le16_to_cpu(h0.virtualUnitNo);
0593 prev_block = le16_to_cpu(h0.prevUnitNo);
0594 erase_mark = le16_to_cpu((h1.EraseMark | h1.EraseMark1));
0595 ANACtable[block] = h0.ANAC;
0596
0597
0598 if (prev_block < s->nb_blocks)
0599 prev_block += s->firstEUN;
0600
0601
0602 if (s->PUtable[block] != BLOCK_NOTEXPLORED) {
0603
0604 if (logical_block == first_logical_block) {
0605 if (last_block != BLOCK_NIL)
0606 s->PUtable[last_block] = block;
0607 }
0608 break;
0609 }
0610
0611
0612 if (erase_mark != ERASE_MARK) {
0613 printk(KERN_WARNING "INFTL: corrupt block %d "
0614 "in chain %d, chain length %d, erase "
0615 "mark 0x%x?\n", block, first_block,
0616 chain_length, erase_mark);
0617
0618
0619
0620
0621 if (chain_length == 0)
0622 do_format_chain++;
0623 break;
0624 }
0625
0626
0627 if ((logical_block == BLOCK_FREE) ||
0628 (logical_block == BLOCK_NIL)) {
0629 s->PUtable[block] = BLOCK_FREE;
0630 break;
0631 }
0632
0633
0634 if ((logical_block >= s->nb_blocks) ||
0635 ((prev_block >= s->nb_blocks) &&
0636 (prev_block != BLOCK_NIL))) {
0637 if (chain_length > 0) {
0638 printk(KERN_WARNING "INFTL: corrupt "
0639 "block %d in chain %d?\n",
0640 block, first_block);
0641 do_format_chain++;
0642 }
0643 break;
0644 }
0645
0646 if (first_logical_block == BLOCK_NIL) {
0647 first_logical_block = logical_block;
0648 } else {
0649 if (first_logical_block != logical_block) {
0650
0651 break;
0652 }
0653 }
0654
0655
0656
0657
0658
0659
0660
0661 s->PUtable[block] = BLOCK_NIL;
0662 if (last_block != BLOCK_NIL)
0663 s->PUtable[last_block] = block;
0664 last_block = block;
0665 block = prev_block;
0666
0667
0668 if (block == BLOCK_NIL)
0669 break;
0670
0671
0672 if (block > s->lastEUN) {
0673 printk(KERN_WARNING "INFTL: invalid previous "
0674 "block %d in chain %d?\n", block,
0675 first_block);
0676 do_format_chain++;
0677 break;
0678 }
0679 }
0680
0681 if (do_format_chain) {
0682 format_chain(s, first_block);
0683 continue;
0684 }
0685
0686
0687
0688
0689
0690
0691
0692 s->VUtable[first_logical_block] = first_block;
0693 logical_block = BLOCK_NIL;
0694 }
0695
0696 INFTL_dumptables(s);
0697
0698
0699
0700
0701
0702
0703 pr_debug("INFTL: pass 2, validate virtual chains\n");
0704 for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
0705 block = s->VUtable[logical_block];
0706 last_block = BLOCK_NIL;
0707
0708
0709 if (block >= BLOCK_RESERVED)
0710 continue;
0711
0712 ANAC = ANACtable[block];
0713 for (i = 0; i < s->numvunits; i++) {
0714 if (s->PUtable[block] == BLOCK_NIL)
0715 break;
0716 if (s->PUtable[block] > s->lastEUN) {
0717 printk(KERN_WARNING "INFTL: invalid prev %d, "
0718 "in virtual chain %d\n",
0719 s->PUtable[block], logical_block);
0720 s->PUtable[block] = BLOCK_NIL;
0721
0722 }
0723 if (ANACtable[block] != ANAC) {
0724
0725
0726
0727
0728
0729 s->VUtable[logical_block] = block;
0730 s->PUtable[last_block] = BLOCK_NIL;
0731 break;
0732 }
0733
0734 ANAC--;
0735 last_block = block;
0736 block = s->PUtable[block];
0737 }
0738
0739 if (i >= s->nb_blocks) {
0740
0741
0742
0743
0744 format_chain(s, first_block);
0745 }
0746 }
0747
0748 INFTL_dumptables(s);
0749 INFTL_dumpVUchains(s);
0750
0751
0752
0753
0754 s->numfreeEUNs = 0;
0755 s->LastFreeEUN = BLOCK_NIL;
0756
0757 pr_debug("INFTL: pass 3, format unused blocks\n");
0758 for (block = s->firstEUN; block <= s->lastEUN; block++) {
0759 if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
0760 printk("INFTL: unreferenced block %d, formatting it\n",
0761 block);
0762 if (INFTL_formatblock(s, block) < 0)
0763 s->PUtable[block] = BLOCK_RESERVED;
0764 else
0765 s->PUtable[block] = BLOCK_FREE;
0766 }
0767 if (s->PUtable[block] == BLOCK_FREE) {
0768 s->numfreeEUNs++;
0769 if (s->LastFreeEUN == BLOCK_NIL)
0770 s->LastFreeEUN = block;
0771 }
0772 }
0773
0774 kfree(ANACtable);
0775 return 0;
0776 }