Пример #1
0
/*
 * reads the data out of a page and writes it back the active page.
 */
static double ssd_clean_one_page
(int lp_num, int pp_index, int blk, int plane_num, int elem_num, ssd_element_metadata *metadata, ssd_t *s)
{
    double cost = 0;
    double xfer_cost = 0;

    cost += s->params.page_read_latency;
    cost += ssd_move_page(lp_num, blk, plane_num, elem_num, s);

    // if the write is within the same plane, then the data need
    // not cross the pins. but if not, add the cost of transferring
    // the bytes across the pins
    xfer_cost = ssd_crossover_cost(s, metadata, blk, SSD_PAGE_TO_BLOCK(metadata->active_page, s));

    cost += xfer_cost;

    ssd_assert_valid_pages(plane_num, metadata, s);
    ASSERT(metadata->block_usage[blk].page[pp_index] == -1);

    // stat -- we move 'valid_pages' out of this block
    s->elements[elem_num].stat.pages_moved ++;
    s->elements[elem_num].stat.tot_xfer_cost += xfer_cost;

    return cost;
}
Пример #2
0
/*
 * updates the status of erased blocks
 */
void ssd_update_free_block_status(int blk, int plane_num, ssd_element_metadata *metadata, ssd_t *s)
{
    int bitpos;

    // clear the bit corresponding to this block in the
    // free blocks list for future use
    bitpos = ssd_block_to_bitpos(s, blk);
    ssd_clear_bit(metadata->free_blocks, bitpos);
    metadata->block_usage[blk].state = SSD_BLOCK_CLEAN;
    metadata->block_usage[blk].bsn = 0;
    metadata->tot_free_blocks ++;
    metadata->plane_meta[plane_num].free_blocks ++;
    ssd_assert_free_blocks(s, metadata);

    // there must be no valid pages in the erased block
    ASSERT(metadata->block_usage[blk].num_valid == 0);
    ssd_assert_valid_pages(plane_num, metadata, s);
}
Пример #3
0
/*
 * writes a single page into the active block of a ssd element.
 * this code assumes that there is a valid active page where the write can go
 * without invoking new cleaning.
 */
double _ssd_write_page_osr(ssd_t *s, ssd_element_metadata *metadata, int lpn)
{
    double cost;
    unsigned int active_page = metadata->active_page;
    unsigned int active_block = SSD_PAGE_TO_BLOCK(active_page, s);
    unsigned int pagepos_in_block = active_page % s->params.pages_per_block;
    unsigned int active_plane = metadata->block_usage[active_block].plane_num;

    // see if this logical page no is already mapped.
    if (metadata->lba_table[lpn] != -1) {

        // since the lpn is going to be written to a new location,
        // its previous copy is invalid now. therefore reduce the block
        // usage of the previous copy's block.

        unsigned int prev_page = metadata->lba_table[lpn];
        unsigned int prev_block = SSD_PAGE_TO_BLOCK(prev_page, s);
        unsigned int pagepos_in_prev_block = prev_page % s->params.pages_per_block;
        unsigned int prev_plane = metadata->block_usage[prev_block].plane_num;

        // make sure the version numbers are correct
        ssd_assert_page_version(prev_page, active_page, metadata, s);

        if (metadata->block_usage[prev_block].page[pagepos_in_prev_block] != lpn) {
            fprintf(stderr, "Error: lpn %d not found in prev block %d pos %d\n",
                lpn, prev_block, pagepos_in_prev_block);
            ASSERT(0);
        } else {
            metadata->block_usage[prev_block].page[pagepos_in_prev_block] = -1;
            metadata->block_usage[prev_block].num_valid --;
            metadata->plane_meta[prev_plane].valid_pages --;
            ssd_assert_valid_pages(prev_plane, metadata, s);
        }
    } else {
        fprintf(stderr, "Error: This case should not be executed\n");
    }

    // add the entry to the lba table
    metadata->lba_table[lpn] = active_page;

    // increment the usage count on the active block
    metadata->block_usage[active_block].page[pagepos_in_block] = lpn;
    metadata->block_usage[active_block].num_valid ++;
    metadata->plane_meta[active_plane].valid_pages ++;
    ssd_assert_valid_pages(active_plane, metadata, s);

    // some sanity checking
    if (metadata->block_usage[active_block].num_valid >= s->params.pages_per_block) {
        fprintf(stderr, "Error: len %d of block %d is greater than or equal to pages per block %d\n",
            metadata->block_usage[active_block].num_valid, active_block, s->params.pages_per_block);
        exit(1);
    }

    // add the cost of the write
    cost = s->params.page_write_latency;
    //printf("lpn %d active pg %d\n", lpn, active_page);

    // go to the next free page
    metadata->active_page = active_page + 1;
    metadata->plane_meta[active_plane].active_page = metadata->active_page;

    // if this is the last data page on the block, let us write the
    // summary page also
    if (ssd_last_page_in_block(metadata->active_page, s)) {
        // cost of transferring the summary page data
        cost += ssd_data_transfer_cost(s, SSD_SECTORS_PER_SUMMARY_PAGE);

        // cost of writing the summary page data
        cost += s->params.page_write_latency;

        // seal the last summary page. since we use the summary page
        // as a metadata, we don't count it as a valid data page.
        metadata->block_usage[active_block].page[s->params.pages_per_block - 1] = -1;
        metadata->block_usage[active_block].state = SSD_BLOCK_SEALED;
        //printf("SUMMARY: lpn %d active pg %d\n", lpn, active_page);
    }

    return cost;
}
Пример #4
0
/*
 * writes a single page into the active block of a ssd element.
 * this code assumes that there is a valid active page where the write can go
 * without invoking new cleaning.
 */
double _ssd_write_page_osr(ssd_t *s, ssd_element_metadata *metadata, int lbn, ssd_power_element_stat *power_stat, int blkno)
{
    double cost;
    //unsigned int active_page = metadata->active_page;
    unsigned int active_block = metadata->active_block;
    //unsigned int pagepos_in_block = active_page % s->params.pages_per_block;
    unsigned int active_plane = metadata->block_usage[active_block].plane_num;
    unsigned int p_index = (blkno/s->params.page_size)%s->params.pages_per_block;

	int prev_num_valid = 0;
	int i;
	int elem_num = ssd_choose_element(s->user_params, blkno);

    // see if this logical page no is already mapped.
    if (metadata->lba_table[lbn] != -1) {

        // since the lpn is going to be written to a new location,
        // its previous copy is invalid now. therefore reduce the block
        // usage of the previous copy's block.

        unsigned int prev_block = metadata->lba_table[lbn];
        //unsigned int prev_block = SSD_PAGE_TO_BLOCK(prev_page, s);
        //unsigned int pagepos_in_prev_block = prev_page % s->params.pages_per_block;
        unsigned int prev_plane = metadata->block_usage[prev_block].plane_num;

        // make sure the version numbers are correct
        //ssd_assert_page_version(prev_page, active_page, metadata, s);

//        if (metadata->block_usage[prev_block].page[0] != lpn) {
//            fprintf(stderr, "Error: lpn %d not found in prev block %d pos %d\n",
//                lpn, prev_block, pagepos_in_prev_block);
//            ASSERT(0);
//        } else {
		for( i = 0 ; i < (s->params.pages_per_block-1) ; i++) {
		metadata->block_usage[active_block].page[i] = metadata->block_usage[prev_block].page[i];
		metadata->block_usage[prev_block].page[i] = -1;
		}
		prev_num_valid = metadata->block_usage[prev_block].num_valid;
		metadata->block_usage[prev_block].num_valid = 0;
		metadata->plane_meta[prev_plane].valid_pages -= prev_num_valid;
		ssd_assert_valid_pages(prev_plane, metadata, s);
 //       }
    } else {
        fprintf(stderr, "Error: This case should not be executed\n");
    }

    // add the entry to the lba table
    metadata->lba_table[lbn] = active_block;

    // increment the usage count on the active block
    if(metadata->block_usage[active_block].page[p_index] == 1) {
    	int temp = 0;
        metadata->block_usage[active_block].num_valid = prev_num_valid;
        metadata->plane_meta[active_plane].valid_pages += prev_num_valid;
        
        //add cost
        cost = s->params.page_write_latency * prev_num_valid;
        ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, cost, power_stat, s);
        temp = prev_num_valid - 1;
        cost += ssd_data_transfer_cost(s, temp * 8);
    	ssd_power_flash_calculate(SSD_POWER_FLASH_BUS_DATA_TRANSFER, ssd_data_transfer_cost(s, temp * 8), power_stat, s);
      //ssd_assert_valid_pages(active_plane, metadata, s);
    }
    else {
    	// add the cost of the write
    	cost = s->params.page_write_latency * (prev_num_valid +1);
    	//printf("lpn %d active pg %d\n", lpn, active_page);
    	//@20090831-Micky:add the power consumption of the write
    	ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, cost, power_stat, s);

	cost += ssd_data_transfer_cost(s, prev_num_valid * 8);
    	ssd_power_flash_calculate(SSD_POWER_FLASH_BUS_DATA_TRANSFER, ssd_data_transfer_cost(s, prev_num_valid * 8), power_stat, s);
    }
	
    // some sanity checking
    if (metadata->block_usage[active_block].num_valid >= s->params.pages_per_block) {
        fprintf(stderr, "Error: len %d of block %d is greater than or equal to pages per block %d\n",
            metadata->block_usage[active_block].num_valid, active_block, s->params.pages_per_block);
        exit(1);
    }
    	
	// seal the last summary page. since we use the summary page
    // as a metadata, we don't count it as a valid data page.
    metadata->block_usage[active_block].page[s->params.pages_per_block - 1] = -1;
    metadata->block_usage[active_block].state = SSD_BLOCK_SEALED;

	// cost of transferring the summary page data
    cost += ssd_data_transfer_cost(s, SSD_SECTORS_PER_SUMMARY_PAGE);
    ssd_power_flash_calculate(SSD_POWER_FLASH_BUS_DATA_TRANSFER, ssd_data_transfer_cost(s, SSD_SECTORS_PER_SUMMARY_PAGE), power_stat, s);

    // cost of writing the summary page data
    cost += s->params.page_write_latency;
    //@20090831-Micky:add the power consumption of the write
	ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, s->params.page_write_latency, power_stat, s);
    
    return cost;
}