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

📄 fsck.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 5 页
字号:
        tw(tr(TR_FUNC, TrJournal, "Last journal is between WRITING and READY\n"));
        ffsdrv_write_byte(&addr->state, JOURNAL_IS_DONE);
        fs.journal_pos += sizeof(fs.journal);
    }

    // Never create a new journal file if a replacementinode just have been
    // made because the new replacementinode is not yet added in the table
    // fs.repi_table[] and it could be the journal which is replaced.
    if (i == EFFS_OK) {
        if (ip->size != fs.journal_size + atomalign(sizeof(FFS_JOURNAL_NAME) + 1)) {
            tw(tr(TR_FUNC, TrJournal, "Wrong journal size, create new\n"));
            // Journal size do not match default size, so create new. This
            // should only happen if there is use an old FFS image with a newer FFS
            // version.
            if ((i = journal_create(fs.ijournal)) <= 0) {
                fs.ijournal = 0;
                return i;
            }
        }
        // Minimize the risk of running out of journal space.
        if (fs.journal_pos >= fs.journal_size - FFS_JOURNAL_MARGIN * 
            sizeof(struct journal_s)) {
            tw(tr(TR_FUNC, TrJournal, "Journal file (near) full! Create new\n"));
            if ((i = journal_create(fs.ijournal)) <= 0) {
                fs.ijournal = 0;
                return i;
            }
        }
    }

    tw(tr(TR_FUNC, TrJournal, "journal_pos = 0x%04x\n", fs.journal_pos));
    tw(tr(TR_END, TrJournal, "} %d\n", i));
    
    return i;
}

// Create the journal file from scratch or relocate an existing one. It is
// marked read-only just for clarity --- it cannot be deleted anyway!
// fs_format() calls this function. Note that no data are written in
// object_create() because the journal file is handled specially in that
// function.
iref_t journal_create(iref_t oldi)
{
    iref_t i;

    tw(tr(TR_BEGIN, TrJournal, "journal_create(%d) {\n", oldi));
    tw(tr(TR_FUNC, TrJournal, "journal file size = %d\n", fs.journal_size));

    if (fs.journal_size == 0) {
        tw(tr(TR_FUNC, TrJournal, "Journal file creation aborted because fs.journal_size = 0 (No journal file wanted)\n"));
        tw(tr(TR_END, TrJournal, "} %d\n", 0));
        return 0;
    }

    // If we are working on a write-once file system, we do not need a
    // journal.
    if (fs.blocks_free_min == 0) {
        tw(tr(TR_FUNC, TrJournal, "Journal file creation aborted because fs.blocks_free_min = 0 (write-once system)\n"));
        tw(tr(TR_END, TrJournal, "} %d\n", 0));
        return 0;
    }

    journal_begin(oldi);

    i = object_create(FFS_JOURNAL_NAME, 0, fs.journal_size, -fs.root);
    if (i < 0) {
        tw(tr(TR_END, TrJournal, "} %d\n", i));
        return i;
    }
    fs.journal_ram.flags = BIT_SET(fs.journal_ram.flags, OFE_READONLY);

    // commit the creation or relocation
    if (oldi != 0)
        journal_end(0);
    else {
        journal_commit(OTE_FILE);
        fs.journal_pos = JOURNAL_POS_INITIAL;
    }

    tw(tr(TR_END, TrJournal, "} %d\n", i));

    return i;
}

/******************************************************************************
 * Replacementinode
 ******************************************************************************/

// Validate the replacement inode, mark old diri as replaced and close
// journal entry
void validate_replacementinode(struct journal_s *addr)
{
    struct inode_s *ip, *dir_ip;
    iref_t zero[2] = {0, 0};

    ip = inode_addr(addr->i);

    if (addr->oldi > 0)
        dir_ip = inode_addr(addr->oldi);
    else
        dir_ip = inode_addr(-addr->oldi);

    // Validate replacementinode
    ffsdrv_write_byte(&ip->flags, (OT_VALID & ip->flags));
    // Mark directory inode as replaced (set child and sibling to zero)
    ffsdrv.write(&dir_ip->child, zero, sizeof(zero));
    // Mark the creation of the replacementinode as done
    ffsdrv_write_byte(&addr->state, JOURNAL_IS_DONE); 

    fs.journal_pos++; 
    if (fs.journal_pos == fs.journal_size) 
        ffs_panic(EFFS_JNLFULL);
}

// Create a replacementinode for diri. It is possible that there exist a
// non-complete replacement inode because the previous creation of the inode
// was interrupted. In this case the inode will be finalized (if prevalid)
// or removed so there can be made a new.
void create_replacementinode(struct journal_s *old_addr)
{
    int j;
    struct inode_s *ip, *dir_ip, ib;
    struct journal_s *addr = old_addr;

    tw(tr(TR_BEGIN, TrJournal, "create_repi(0x%x) {\n", old_addr));

    tw(tr(TR_NULL, TrJournal, "Search for next non-complete journal entry:"));
    addr++;  // Advance one journal entry (the current state is READY)
    for (j = 1 + fs.journal_pos / sizeof(fs.journal);/* FIXME: limit to end of journal */; 
         j++, addr++) {
        if (addr->state != (uint8) JOURNAL_IS_DONE)
            break;
    }
    tw(tr(TR_FUNC, TrJournal, " entry %d is in state 0x%x\n", j, addr->state));

    fs.journal_pos += j * sizeof(fs.journal);

    if ((addr->state == (uint8) JOURNAL_IS_READY) && 
        is_object_valid(inode_addr(addr->i))) {
        validate_replacementinode(addr);
        return;
    }

    // If the journal entry not is EMPTY it must be a non completed
    // replacement inode which must be remove before there is created a new
    if (addr->state != (uint8) JOURNAL_IS_EMPTY) {
        tw(tr(TR_FUNC, TrJournal, "Remove old repi\n"));
        ffsdrv_write_byte(&addr->state, JOURNAL_IS_DONE);
        // Advance journal. 
        addr++; 
        fs.journal_pos++; 
        if (fs.journal_pos == fs.journal_size) 
            ffs_panic(EFFS_JNLFULL);
    }

    tw(tr(TR_FUNC, TrJournal, "create replacementinode\n"));

    journal_push();

    journal_begin(0);
    // Alloc an inode. Note fs.inodes_max is temporarily added
    // a margin because this alloc is allowed to use the last inode
    fs.inodes_max += FFS_INODES_MARGIN;
    fs.journal.i = inode_alloc_try();
    fs.inodes_max -= FFS_INODES_MARGIN;

    fs.journal.oldi = get_repi(old_addr->diri);
    fs.journal_ram.location = fs.journal.oldi > 0 ? fs.journal.oldi : -fs.journal.oldi;
    fs.journal_ram.flags = OT_REP;

    ffsdrv_write_byte(&addr->state, JOURNAL_IS_WRITING);
    fs.journal.state = JOURNAL_IS_WRITING;

    // Write ram journal to flash and advance journal to READY
    tw(tr(TR_FUNC, TrJournal, "Write ram journal to flash\n"));
    ffsdrv.write(addr, &fs.journal, sizeof(fs.journal));
    ffsdrv_write_byte(&addr->state, JOURNAL_IS_READY); 

    ip = inode_addr(fs.journal.i);
    // NOTEME: change the macro inode_addr() to handle a negative inode?
    if (addr->oldi > 0)
        dir_ip = inode_addr(addr->oldi);
    else
        dir_ip = inode_addr(-addr->oldi);

    tw(tr(TR_FUNC, TrJournal,"Replace i: %d (%s%s%s%s%s %s) with %d\n", 
          fs.journal.oldi,
          is_object(dir_ip, OTE_DIR)     ? " d" : "",
          is_object(dir_ip, OTE_LINK)    ? " l" : "",
          is_object(dir_ip, OTE_FILE)    ? " f" : "",
          is_object(dir_ip, OTE_SEGMENT) ? " s" : "",
          is_object(dir_ip, OT_REP)     ? "rp" : "",
          (dir_ip->size && !is_object(dir_ip, OTE_SEGMENT) && 
           !is_object_erased(dir_ip) && is_object_valid(dir_ip) ? 
           addr2name(offset2addr(location2offset(dir_ip->location))) : ""),
          fs.journal.i));

    // Init inode buffer
    // Set all elements to 0xFF.. NOTEME: do this in another way?
    memcpy(&ib, ip, sizeof(ib));
    ib.size = ib.sequence = ib.updates = 0;
    ib.flags = fs.journal_ram.flags | OF_MASK; 
    ib.location = fs.journal_ram.location;  

    // Write the replacement inodes Child or Sibling field
    if (fs.journal.oldi < 0) {
        // diri child is maybe invalid thus we keep it as empty and only
        // write sibling
        tw(tr(TR_FUNC, TrJournal, "copy sibling: 0x%x\n", dir_ip->sibling));
        ib.sibling = dir_ip->sibling;
    }
    else {
        // diri sibling is maybe invalid thus we keep it as empty and only
        // write child
        tw(tr(TR_FUNC, TrJournal, "copy child: 0x%x\n", dir_ip->child));
        ib.child = dir_ip->child;
    }

    // Write the inode to flash
    ffsdrv.write(ip, &ib, sizeof(ib));

    journal_pop();

    validate_replacementinode(addr);

    tw(tr(TR_END, TrJournal, "} 0\n"));
}

/******************************************************************************
 * FFS Begin and End
 ******************************************************************************/

// The following two functions should surround the code of every API
// function in ffs.c (except preformat and format). The functions
// ensures that the operation about to be executed can be made without
// race-conditions or other problems.
#if (TARGET == 0)
int debug_suspend = 0;
#endif


// Check if ffs has been initialized. Suspend an erase operation.
effs_t ffs_begin(void)
{
#if (TARGET == 0)  
    if (debug_suspend > 0) {
        tw(tr(TR_FUNC, TrAll, "FATAL: Previous erase_suspend was not resumed\n"));
        return EFFS_CORRUPTED;
    }
//    tw(tr(TR_FUNC, TrHelper, "Set debug_suspend\n"));
    debug_suspend = 1;
#endif

    if (fs.initerror != EFFS_OK)
        return fs.initerror;

    // Suspend an erase in progress (only applicable if we are using a
    // multi-bank device driver)
    if (dev.state == DEV_ERASE) {
        ffsdrv.erase_suspend();
    }
    // Suspend a write in progress (only applicable if we are using a
    // multi-bank device driver)
    else if (dev.state == DEV_WRITE) {
        ffsdrv.write_suspend();
    }
        
    return EFFS_OK;
}

// Resume an erase operation that was in progress.
int ffs_end(int error)
{
#if (TARGET == 1)
    // Resume an erase in progress (only applicable if we are using a
    // multi-bank device driver)
    if (dev.state == DEV_ERASE_SUSPEND) 
        ffsdrv.erase_resume();
    
    // Resume a write in progress (only applicable if we are using a
    // multi-bank device driver)
    else if (dev.state == DEV_WRITE_SUSPEND) 
        ffsdrv.write_resume();
#else
    debug_suspend = 0;
#endif

    return error;
}

/******************************************************************************
 * FFS Statistics functions
 ******************************************************************************/

// Not implemented:
int statistics_file_create(void)
{
    return 0;
}

// Not implemented:
// Rewrite the statistics file if it exists. Otherwise return error
// code. The function is called after each data and inodes reclaim (after
// writing the file that provoked the reclaim).
int statistics_write(void)
{
    return 0;
}

// Read the statistics file if it exists. Otherwise reset all statistics to
// zero and set the magic. This function is called from ffs_init().
void statistics_init(void)
{
	memset(&stats, 0, sizeof(struct ffs_stats_s));
}

void statistics_update_drec(int valid, int lost, int candidate)
{
    unsigned int old;

    switch (candidate) {
    case MOST_LOST:   stats.drec.most_lost++;   break;
    case YOUNGEST:    stats.drec.youngest++;    break;
    }

    // Increment Most Significant Word if overflow is detected
    old = stats.drec.valid[0];
    stats.drec.valid[0] += valid;
    if (old > stats.drec.valid[0])
        stats.drec.valid[1]++;

    old = stats.drec.lost[0];
    stats.drec.lost[0] += lost;
    if (old > stats.drec.lost[0])
        stats.drec.lost[1]++;
}

void statistics_update_irec(int valid, int lost)
{
    stats.irec.num++;
    stats.irec.valid += valid;
    stats.irec.lost += lost;
}
 

⌨️ 快捷键说明

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