Beispiel #1
0
void close_eraseblks(fs_context& fs)
{
    /* TODO: Error handling missing! */

    for (eb_id_t eb_id = 1; eb_id < fs.neraseblocks; ++eb_id)
    {
        if (fs.eb_usage[eb_id].e_type == eraseblock_type::ebin)
            continue; /* can never be "open" */
        if (fs.eb_usage[eb_id].e_type == eraseblock_type::empty)
            continue; /* can never be "open" */

        eraseblock_type eb_type = fs.eb_usage[eb_id].e_type;
        unsigned int writeops = get_be16(fs.eb_usage[eb_id].e_writeops);
        unsigned int max_writeops = fs.erasesize / fs.clustersize;

        if (writeops == max_writeops)
            continue; /* erase block is already finalized/closed */

        fs.eb_usage[eb_id].e_writeops = put_be16(max_writeops);

        if (!summary_required(fs, eb_type))
            continue;

        summary* eb_summary = summary_get(*fs.summary_cache, eb_type);

        summary_write(fs, eb_summary, eb_id);
        summary_close(*fs.summary_cache, eb_summary);

        /* tell gcinfo an erase block of a specific type was written */
        unsigned int write_time = gcinfo_update_writetime(fs, eb_type);
        fs.eb_usage[eb_id].e_lastwrite = put_be16(write_time);
    }
}
Beispiel #2
0
static double point_obs_measure( const point_obs_type * point_obs , const void * state , int iobs , node_id_type node_id) {
  if (point_obs->source_type == SOURCE_FIELD) {
    const field_type * field = field_safe_cast_const( state );
    return field_iget_double(field , point_obs->active_index);
  } else if (point_obs->source_type == SOURCE_SUMMARY) {
    const container_type * container = container_safe_cast_const( state );
    const summary_type * summary = summary_safe_cast_const( container_iget_node( container , iobs ));
    return summary_get( summary , node_id.report_step , node_id.state );    
  } else {
    util_abort("%s: unknown source type: %d \n",__func__, point_obs->source_type );
    return -1;
  }
}
Beispiel #3
0
void commit_write_operation(fs_context& fs, eraseblock_type eb_type,
                            eb_id_t eb_id, be32_t ino_no)
{
    /* TODO: Error handling missing! */

    // This function cannot trigger garbage collection by itself because
    //  calling functions may have to perform further operations to bring
    //  the file system into a consistent state. One (and currently the
    //  only) example is:
    //   This function does not know whether a cluster was just written
    //   that replaces (invalidates) a cluster in the same or another
    //   erase block. In this case the calling function has to decrement
    //   the old erase blocks valid cluster count.
    // To help triggering gc the function will increment fs.eb_written
    //  every time an erase block was finalized.

    if (eb_type == eraseblock_type::ebin)
    {
        // Erase block indirect data is easy to handle.
        // It can never be "open" because it is always completely
        //  written by a single write operation.
        fs.eb_usage[eb_id].e_type = eb_type;
        return;
    }

    /* tell gcinfo that we wrote an erase block of a specific type */
    unsigned int write_time = gcinfo_update_writetime(fs, eb_type);

    // Update the meta data of the erase block that was written to.
    fs.eb_usage[eb_id].e_type = eb_type;
    fs.eb_usage[eb_id].e_lastwrite = put_be16(write_time);
    eb_inc_cvalid(fs, eb_id);
    inc_be16(fs.eb_usage[eb_id].e_writeops);

    int max_writeops = fs.erasesize / fs.clustersize;
    uint16_t writeops = get_be16(fs.eb_usage[eb_id].e_writeops);

    if (!summary_required(fs, eb_type))
    {
        if (writeops == max_writeops)
        {
            // An erase block without summary is implicitly
            //  finalized when its maximum write operations count
            //  is reached.
            gcinfo_inc_writecnt(fs, eb_type);
        }
        return;
    }

    // The erase block still needs a summary if it was just opened.
    summary* eb_summary;
    if (writeops == 1)
    {
        // Create a new erase block summary buffer for the newly
        //  opened erase block and add it to the summary list.
        eb_summary = summary_open(*fs.summary_cache, eb_type);
    }
    else
    {
        // The summary for this erase block should already exist.
        eb_summary = summary_get(*fs.summary_cache, eb_type);
    }
    // The last cluster of a cluster indirect erase block contains the
    //  inode ids of all inodes that have data inside this erase block.
    summary_add_ref(eb_summary, writeops - 1, get_be32(ino_no));

    // The summary information of every open erase block is cached.
    //  It will be written to the end of the erase block when this is full.
    if (writeops == (max_writeops - 1))
    {
        // The last write operation filled the erase block.
        // Write its summary to finalize it.
        summary_write(fs, eb_summary, eb_id);
        summary_close(*fs.summary_cache, eb_summary);

        /* we just performed another write operation;
         * tell gcinfo and update the erase block's usage data */
        write_time = gcinfo_update_writetime(fs, eb_type);

        fs.eb_usage[eb_id].e_lastwrite = put_be16(write_time);
        inc_be16(fs.eb_usage[eb_id].e_writeops);
        gcinfo_inc_writecnt(fs, eb_type);
    }
}