⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsck.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 5 页
字号:
    for (q = p + dev.blocksize/4 - 4; q > p; q -= 4) {
        if ( ~(q[0] & q[1] & q[2] & q[3]) )
            break;
    }

    if ( ~(q[0] & q[1] & q[2] & q[3]) )
        q += 4;
    used = atomalign((char *) q - (char *) p);

    tw(tr(TR_FUNC, TrFsckLow, "ffs_block_used(%d) %d\n", b, used));

    return used;
}


age_t age_distance(age_t x, age_t y)
{
    age_t a = x - y;
    
    if (a > 0x8000)
        a = -a;

    tw(tr(TR_FUNC, TrFsckLow, "age_distance(%d, %d) %d\n", x, y, a));
    
    return a;
}

// For each ffs block, we initialise the basic bstat array information,
// namely the number of used bytes. Also, we locate the inodes block and if
// a previous operation was interrupted by a powerfail, we clean it up.
//
// We return EFFS_OK if all is fine. If a positive integer is returned, it
// denotes a block that needs to be cleaned by block_clean() once FFS
// has been properly intialized (we actually return the block number + 1
// because otherwise it would clash with EFFS_OK return code). If no inodes
// block is found or another error occurs, we return the error code.
bref_t blocks_fsck(void)
{
	bref_t b, b_to_clean, b_inode_lost;
    int age_valid;
    age_t age_min, age_max, age_dist, age_dist_min, age_dist_max;
    struct block_header_s *bhp;
    uint16 flags_msb, flags_lsb;

    ttw(str(TTrInitLow, "blocks_fsck {" NL));
    tw(tr(TR_BEGIN, TrFsck, "blocks_fsck() {\n"));

    // initialize ages to the illegal/unset value
    age_min = age_max = age_dist = 0;

    fs.format    =  0;
    fs.inodes    = -1;
    fs.newinodes = -1;
	b_inode_lost = -1;
    b_to_clean   = EFFS_OK;

    for (b = 0; b < dev.numblocks; b++)
    {
        tlw(led_toggle(LED_DRV_INIT));

        // read block flags from flash
        bhp = (struct block_header_s *) offset2addr(dev.binfo[b].offset);
        fs.format = bhp->version;
            
        // Format check is performed early because this new version thinks
        // that the old state is in an intermediate state thus it tries to
        // fix it and we can not allow that
        if ((bhp->magic_low  == BLOCK_MAGIC_LOW &&
             bhp->magic_high == BLOCK_MAGIC_HIGH) && 
            (bhp->version >> 8) != (FFS_FORMAT_VERSION >> 8)) {
            tw(tr(TR_END, TrFsck, "} %d\n", EFFS_BADFORMAT));
            ttw(ttr(TTrInitLow, "} %d" NL, EFFS_BADFORMAT));
            return EFFS_BADFORMAT;
        }     

		tw(tr(TR_FUNC, TrFsck, "Block %d, flags 0x%x\n", b, bhp->flags));
#if 0         
        // Check block header flag for intermediate states (01 or 10)
        // NOTEME add further comments?
        if ((bhp->flags & 0xAAAA) != ((bhp->flags & 0x5555) << 1)) {
            tw(tr(TR_FUNC, TrFsck,"Intermediate state detected in block header:\n"));
            // Push the flags to well defined states (01,10 -> 00)
            flags_msb = (bhp->flags << 1) & 0xAAAA & bhp->flags;
            flags_lsb = (bhp->flags >> 1) & 0x5555 & bhp->flags;
            tw(tr(TR_FUNC, TrFsck,"    blk %d (0x%x->0x%x) \n", b, bhp->flags, 
                  BIT_SET(bstat[b].flags, ~(flags_msb | flags_lsb))));
            block_flags_write(b, ~(flags_msb | flags_lsb));
        }
#endif
        bstat[b].flags   = bhp->flags;
        bstat[b].used    = dev.blocksize;
        bstat[b].lost    = bstat[b].used;
        bstat[b].objects = 0;

        age_valid = 0;

        if (bhp->magic_low  != BLOCK_MAGIC_LOW ||
            bhp->magic_high != BLOCK_MAGIC_HIGH) {
            // The block magic as bad! It *could* be because the flash
            // memory map is incorrect or because another application has
            // spuriously written to the flash or ... who knows what. 
            // Quickly test if block is in empty state. We do not make a
            // full check with block_used() because that takes too
            // long --- we let preformat() do that.
            if (bhp->magic_low  == FLASH_NULL16 &&
                bhp->magic_high == FLASH_NULL16 &&
                bhp->age        == FLASH_NULL16 &&
                bhp->version    == FLASH_NULL16 &&
                bhp->flags      == FLASH_NULL16)
            {
                bstat[b].used  = 0;
                bstat[b].lost  = 0;
                bstat[b].flags = BF_IS_EMPTY;
                tw(tr(TR_FUNC, TrFsck, "EMPTY     "));
            }
            else {
                // If the block is not free, it is probably corrupted.
                // Thus we reset its age and free it.
                tw(tr(TR_FUNC, TrFsck, "magic = 0x%08x\n",
                      bhp->magic_low | (bhp->magic_high << 16)));
                ffsdrv.write_halfword(&bhp->age, 0);
                block_free(b);
                tw(tr(TR_FUNC, TrFsck, "BAD       "));
            }
        }
        else {
            age_valid = 1;

            if (!is_block(b, BF_IS_FREE)) {
                bstat[b].used = block_used(b);
                bstat[b].lost = bstat[b].used - BHEADER_SIZE; 
            }

            if (is_block(b, BF_IS_FREE)) {
                // The only case where we do not call block_used() is
                // when the block is truly free.
                bstat[b].used = 0;
                bstat[b].lost = 0;
                tw(tr(TR_FUNC, TrFsck, "FREE      "));
                ttw(ttr(TTrInitLow, "FREE" NL));

            }
            else if (is_block(b, BF_IS_DATA)) {
                tw(tr(TR_FUNC, TrFsck, "DATA      "));
                ttw(ttr(TTrInitLow, "DATA" NL)); 
            }
            else if (is_block(b, BF_IS_CLEANING)) {
                // Here we schedule a block_clean(). Note that we can
                // and do not execute the block cleaning now, as the info
                // that block_clean() needs is not at all ready at this
                // point in the initialization. So we set a flag and then
                // clean the block at the end of ffs_initialize()
                tw(tr(TR_FUNC, TrFsck, "CLEANING  "));
                ttw(ttr(TTrInitLow, "CLEANING" NL)); 
                b_to_clean = b + 1;
            }
            else if (is_block(b, BF_IS_COPYING)) {
                tw(tr(TR_FUNC, TrFsck, "COPYING   "));
                ttw(ttr(TTrInitLow, "COPYING" NL)); 
                fs.newinodes = b;
            }
            else if (is_block(b, BF_IS_INODES)) {
                tw(tr(TR_FUNC, TrFsck, "INODES    "));
                ttw(ttr(TTrInitLow, "INODES" NL)); 
                fs.inodes = b;
            }
            else if (is_block(b, BF_IS_INODES_LOST)) {
                tw(tr(TR_FUNC, TrFsck, "INODESLOST"));
                ttw(ttr(TTrInitLow, "INODESLOST" NL)); 
                b_inode_lost = b;
            }
            else {
                block_free(b);
                tw(tr(TR_FUNC, TrFsck, "INVALID   "));
                ttw(ttr(TTrInitLow, "INVALID" NL)); 
            }
        }

        tw(tr(TR_NULL, TrFsck, " %2d: (0x%05x) %02x, used = %6d\n",
              b, dev.binfo[b].offset, bstat[b].flags & 0xFF, bstat[b].used));

        if (age_valid) {
            if (age_min == 0) {
                // Initialize minimum and maximum block ages
                age_min = age_max = bhp->age;
                tw(tr(TR_FUNC, TrFsckLow, "age_min/max = %d\n", age_min));
            }
            else {
                age_dist_min = age_distance(bhp->age, age_min);
                age_dist_max = age_distance(bhp->age, age_max);
                if (age_dist_min > age_dist ||
                    age_dist_max > age_dist) {
                    if (age_dist_max > age_dist_min) {
                        age_dist = age_dist_max;
                        age_min  = bhp->age;
                        tw(tr(TR_FUNC, TrFsckLow, "age_min = %d (dist = %d)\n",
                              age_min, age_dist));
                    }
                    else {
                        age_dist = age_dist_min;
                        age_max  = bhp->age;
                        tw(tr(TR_FUNC, TrFsckLow, "age_max = %d (dist = %d)\n",
                              age_max, age_dist));
                    }
                }
            }
        }
    }
    tlw(led_off(LED_DRV_INIT));
    tw(tr(TR_FUNC, TrFsck, "age min, max, max-min = %d, %d, %d\n",
          age_min, age_max, (uint16) (age_max-age_min)));
    // If age_max is untouched is is because all blocks were in the 'Empty'
    // state. In this case we let the age be as it is (0xFFFF).
    if (age_max == 0)
        age_max = age_min = BLOCK_AGE_MAX;

    // Handle age wrap around thus ensuring fs.age_max is set correctly. We
    // have to type-cast the whole computation, otherwise it will be
    // incorrect.
    if ((age_t) (age_max - age_min) > 0x8000) {
        age_dist = age_max;
        age_max  = age_min;
        age_min  = age_dist;
    }

    // save maximum age found for the case of a bad block that is going to
    // be reclaimed later on by blocks_reclaim()
    fs.age_max = age_max;

    tw(tr(TR_FUNC, TrFsck, "fs.format = 0x%04x\n", fs.format));
    tw(tr(TR_FUNC, TrFsck, "fs.inodes, newinodes = %d, %d\n",
          fs.inodes, fs.newinodes));
    ttw(ttr(TTrInit, "fs.inodes, newinodes = %d, %d" NL, 
            fs.inodes, fs.newinodes));
    tw(tr(TR_FUNC, TrFsck, "age min, max = %d, %d\n", age_min, age_max));
    
    // If any blocks were in the EMPTY state, now is the time to bring them
    // into the FREE state. Note that we must only do this *after*
    // fs.age_max has been initialized.
    for (b = 0; b < dev.numblocks; b++) {
        if (is_block(b, BF_IS_EMPTY)) {
            if ((bstat[b].used = block_used(b)) == 0)
                block_preformat(b, 0);
            else
                block_free(b);
        }
    }

	if (fs.inodes >= 0) {  
        // The 'old' inode block is still valid thus we keep it.
		if (fs.newinodes >= 0)
            // The copying of inodes to the new block was not finished thus
            // we free the block
			block_free(fs.newinodes);   
		inodes_set(fs.inodes);
	}
	else {                                 
		// Copying must have been finished
		if (fs.newinodes >= 0 && b_inode_lost >= 0) {
            // The inode reclaim did finish but currently there is no valid
            // inode block thus the operation must be finished by committing
            // the new block as the valid inode block.
			fs.inodes = b_inode_lost;
			block_commit();
			
		}
		else {
            // No old or new Inode block!
			tw(tr(TR_END, TrFsck, "} %d\n", EFFS_NOFORMAT));
			ttw(ttr(TTrInitLow, "} %d" NL, EFFS_NOFORMAT));
			return EFFS_NOFORMAT;
		}
	}
	
    // FIXME: Insert age sanity check; age distance must not be too big (> 2
    // * FFS_AGE_DISTANCE)?

    tw(tr(TR_END, TrFsck, "} %d\n", b_to_clean));
    ttw(ttr(TTrInitLow, "} %d" NL, b_to_clean));

    return b_to_clean;
}

// Set fs.inodes and fs.inodes_addr
void inodes_set(iref_t i)
{
    fs.inodes = i;
    fs.inodes_addr = (struct inode_s *)
        (offset2addr(dev.binfo[fs.inodes].offset)
         + dev.atomsize - sizeof(struct inode_s));
}


/******************************************************************************
 * inodes_fsck()
 ******************************************************************************/

// Now for each inode in the inodes block, update the bstat array
// information: free, used, objects. Also, locate the root inode. We could
// optimize this a little, because bstat[binodes].used gives an inidication
// of how many inodes are actually present in the system.
iref_t inodes_fsck(void)
{
    iref_t i, nrepi = 0;
    struct inode_s *ip;
    char *addr;
    bref_t block;

    ttw(str(TTrInitLow, "inodes_fsck {" NL));
    tw(tr(TR_BEGIN, TrFsck, "inodes_fsck() {\n"));
    tw(tr(TR_FUNC, TrFsck, "inodes in block %d:\n", fs.inodes));

    // the fields of the bstat entry for the inodes have the meaning:
    // used = total number of used inodes (valid, erased, invalid)
    // lost = total number of lost inodes (erased, invalid)
    // objects = index of first free inode (used by inode_alloc())

    fs.root = 0;     // default to root inode not found
    fs.ijournal = 0; // default to journal file inode not found
    bstat[fs.inodes].objects = 1;
    bstat[fs.inodes].used = 0;
    bstat[fs.inodes].lost = 0;
    fs.sequence = 0; // just for debug (fun)
    memset(fs.repi_table, 0, sizeof(fs.repi_table));

    // we must set some default value for this, so we set it to max possible!
    fs.inodes_max = dev.blocksize / sizeof(struct inode_s);

    ip = inode_addr(1);
    tw(tr(TR_FUNC, TrFsck, "  i    addr  cld sib  seq upd  flag size name\n"));
    for (i = 1; i < fs.inodes_max; i++, ip++)
    {
        // just for debug (fun)
        if (ip->sequence > fs.sequence)
            fs.sequence = ip->sequence;
                
        // compute block index and total data space occupied
        block = offset2block(location2offset(ip->location));

        // Only scan used inodes. blocks_fsck() accounted all used space as
        // also being lost space, so now we subtract from the lost space,
        // the space used by valid objects
        if (ip->location != FLASH_NULL32)
        {
            bstat[fs.inodes].used++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -