Example #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;
}
Example #2
0
double ssd_fullmerge(ssd_t *s, ssd_element_metadata *metadata, ssd_power_element_stat *power_stat, int lbn, int elem_num)
{
	int prev_block = metadata->lba_table[lbn];
	int log_index = metadata->block_usage[prev_block].log_index;
	int log_block = metadata->log_data[log_index].bsn;
	int num_valid = 0;
	int num_valid_d = metadata->block_usage[prev_block].num_valid;
	int num_valid_u = metadata->block_usage[log_block].num_valid;
	int prev_plane_num = metadata->block_usage[prev_block].plane_num;
	int log_plane_num = metadata->block_usage[log_block].plane_num;
	int plane_num;

	int active_block;
	int i;
	double cost = 0.0;
	double r_cost, w_cost, xfer_cost;

	//set active_block
	metadata->active_block = metadata->plane_meta[prev_plane_num].active_block;
	active_block = metadata->active_block;
	_ssd_alloc_active_block(prev_plane_num, elem_num, s);
	plane_num = metadata->block_usage[active_block].plane_num;
	metadata->plane_meta[prev_plane_num].clean_in_block = prev_block;
	metadata->plane_meta[prev_plane_num].clean_in_progress = 1;
	metadata->plane_meta[log_plane_num].clean_in_block = prev_block;
	metadata->plane_meta[log_plane_num].clean_in_progress = 1;

	//page state copy & init page state
	for( i = 0 ; i < s->params.pages_per_block ; i++) {
		if((metadata->block_usage[prev_block].page[i] == 1) || (metadata->log_data[log_index].page[i] != -1)){
			metadata->block_usage[active_block].page[i] = 1;
		}
		metadata->block_usage[prev_block].page[i] = -1;
		metadata->log_data[log_index].page[i] = -1;
		metadata->block_usage[log_block].page[i] = -1;
	}
	metadata->lba_table[lbn] = active_block;

	//update stat
	//update log_table
	metadata->block_usage[prev_block].log_index = -1;
	metadata->log_data[log_index].bsn = -1;
	metadata->log_data[log_index].data_block = -1;
	metadata->log_pos = log_index;
	metadata->num_log--;
	//update block usage
	metadata->block_usage[prev_block].num_valid = 0;
	metadata->block_usage[log_block].num_valid = 0;
	//update plane data
	metadata->plane_meta[prev_plane_num].valid_pages -= num_valid_d;
	metadata->plane_meta[log_plane_num].valid_pages -= num_valid_u;
	num_valid += num_valid_d;
	num_valid += num_valid_u;
	if(num_valid > s->params.pages_per_block) {
		fprintf(outputfile3, "Error number of pages : valid_page %d, Real_page %d\n", num_valid, s->params.pages_per_block);
		fprintf(outputfile3, "Error elem_num %d, lbn %d, original block %d, log block %d\n", elem_num, lbn, prev_block, log_block);
		exit(-1);
	}
	metadata->block_usage[active_block].num_valid = num_valid;
	metadata->plane_meta[plane_num].valid_pages += num_valid;


	//data tranfer cost
	//read
	r_cost = s->params.page_read_latency * num_valid;
	cost += r_cost;
	ssd_power_flash_calculate(SSD_POWER_FLASH_READ, r_cost, power_stat, s);

	//write
	w_cost = s->params.page_write_latency * num_valid;
	cost += w_cost;
	ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, w_cost, power_stat, s);

	//transfer cost
	for( i = 0 ; i < num_valid ; i++) {
		double xfer_cost;
		xfer_cost = ssd_crossover_cost(s, metadata, power_stat, prev_block, active_block);
		cost += xfer_cost;
		s->elements[elem_num].stat.tot_xfer_cost += xfer_cost;
	}

	//erase two block(D)
	cost += s->params.block_erase_latency;
	ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s);
	ssd_update_free_block_status(prev_block, prev_plane_num, metadata, s);
	ssd_update_block_lifetime(simtime+cost, prev_block, metadata);
	metadata->plane_meta[prev_plane_num].num_cleans++;
	metadata->plane_meta[prev_plane_num].clean_in_block = 0;
	metadata->plane_meta[prev_plane_num].clean_in_progress = -1;

	//erase two block(U)
	cost += s->params.block_erase_latency;
	ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s);
	ssd_update_free_block_status(log_block, log_plane_num, metadata, s);
	ssd_update_block_lifetime(simtime+cost, log_block, metadata);
	metadata->plane_meta[log_plane_num].num_cleans++;
	metadata->plane_meta[log_plane_num].clean_in_block = 0;
	metadata->plane_meta[log_plane_num].clean_in_progress = -1;

	//erase stat update
	s->elements[elem_num].stat.pages_moved += num_valid;
	s->elements[elem_num].stat.num_clean += 2;
	s->elements[elem_num].stat.num_fullmerge++;

	return cost;
}
Example #3
0
/*
 * migrate data from a cold block to "to_blk"
 */
int ssd_migrate_cold_data(int to_blk, double *mcost, int plane_num, int elem_num, ssd_t *s)
{
    int i;
    int from_blk = -1;
    double oldest_erase_time = simtime;
    double cost = 0;
    int bitpos;

#if SSD_ASSERT_ALL
    int f1;
    int f2;
#endif

    ssd_element_metadata *metadata = &(s->elements[elem_num].metadata);

    // first select the coldest of all blocks.
    // one way to select is to find the one that has the oldest
    // erasure time.
    if (plane_num == -1) {
        for (i = 0; i < s->params.blocks_per_element; i ++) {
            if (metadata->block_usage[i].num_valid > 0) {
                if (metadata->block_usage[i].time_of_last_erasure < oldest_erase_time) {
                    oldest_erase_time = metadata->block_usage[i].time_of_last_erasure;
                    from_blk = i;
                }
            }
        }
    } else {

#if SSD_ASSERT_ALL
        f1 = ssd_free_bits(plane_num, elem_num, metadata, s);
        ASSERT(f1 == metadata->plane_meta[metadata->block_usage[to_blk].plane_num].free_blocks);
#endif

        bitpos = plane_num * s->params.blocks_per_plane;
        for (i = bitpos; i < bitpos + (int)s->params.blocks_per_plane; i ++) {
            int block = ssd_bitpos_to_block(i, s);
            ASSERT(metadata->block_usage[block].plane_num == plane_num);

            if (metadata->block_usage[block].num_valid > 0) {
                if (metadata->block_usage[block].time_of_last_erasure < oldest_erase_time) {
                    oldest_erase_time = metadata->block_usage[block].time_of_last_erasure;
                    from_blk = block;
                }
            }
        }
    }

    ASSERT(from_blk != -1);
    if (plane_num != -1) {
        ASSERT(metadata->block_usage[from_blk].plane_num == metadata->block_usage[to_blk].plane_num);
    }

    // next, clean the block to which we'll transfer the
    // cold data
    cost += _ssd_clean_block_fully(to_blk, metadata->block_usage[to_blk].plane_num, elem_num, metadata, s);

#if SSD_ASSERT_ALL
    if (plane_num != -1) {
        f2 = ssd_free_bits(plane_num, elem_num, metadata, s);
        ASSERT(f2 == metadata->plane_meta[metadata->block_usage[to_blk].plane_num].free_blocks);
    }
#endif

    // then, migrate the cold data to the worn out block.
    // for which, we first read all the valid data
    cost += metadata->block_usage[from_blk].num_valid * s->params.page_read_latency;
    // include the write cost
    cost += metadata->block_usage[from_blk].num_valid * s->params.page_write_latency;
    // if the src and dest blocks are on different planes
    // include the transfer cost also
    cost += ssd_crossover_cost(s, metadata, from_blk, to_blk);

    // the cost of erasing the cold block (represented by from_blk)
    // will be added later ...

    // finally, update the metadata
    metadata->block_usage[to_blk].bsn = metadata->block_usage[from_blk].bsn;
    metadata->block_usage[to_blk].num_valid = metadata->block_usage[from_blk].num_valid;
    metadata->block_usage[from_blk].num_valid = 0;

    for (i = 0; i < s->params.pages_per_block; i ++) {
        int lpn = metadata->block_usage[from_blk].page[i];
        if (lpn != -1) {
            ASSERT(metadata->lba_table[lpn] == (from_blk * s->params.pages_per_block + i));
            metadata->lba_table[lpn] = to_blk * s->params.pages_per_block + i;
        }
        metadata->block_usage[to_blk].page[i] = metadata->block_usage[from_blk].page[i];
    }
    metadata->block_usage[to_blk].state = metadata->block_usage[from_blk].state;

    bitpos = ssd_block_to_bitpos(s, to_blk);
    ssd_set_bit(metadata->free_blocks, bitpos);
    metadata->tot_free_blocks --;
    metadata->plane_meta[metadata->block_usage[to_blk].plane_num].free_blocks --;

#if SSD_ASSERT_ALL
    if (plane_num != -1) {
        f2 = ssd_free_bits(plane_num, elem_num, metadata, s);
        ASSERT(f2 == metadata->plane_meta[metadata->block_usage[to_blk].plane_num].free_blocks);
    }
#endif

    ssd_assert_free_blocks(s, metadata);
    ASSERT(metadata->block_usage[from_blk].num_valid == 0);

#if ASSERT_FREEBITS
    if (plane_num != -1) {
        f2 = ssd_free_bits(plane_num, elem_num, metadata, s);
        ASSERT(f1 == f2);
    }
#endif

    *mcost = cost;

    // stat
    metadata->tot_migrations ++;
    metadata->tot_pgs_migrated += metadata->block_usage[to_blk].num_valid;
    metadata->mig_cost += cost;

    return from_blk;
}
Example #4
0
double ssd_replacement(ssd_t *s, int elem_num, int lbn)
{
	ssd_element_metadata *metadata;
	ssd_power_element_stat *power_stat;
	int block;
	int log_index;
	int prev_log_block;
	int prev_plane_num;
	int log_block;
	int plane_num;
	int num_valid;
	double cost = 0.0;
	double r_cost, w_cost, xfer_cost;
	int i,j;

	metadata = &(s->elements[elem_num].metadata);
	power_stat = &(s->elements[elem_num].power_stat);

	block = metadata->lba_table[lbn];
	log_index = metadata->block_usage[block].log_index;
	prev_log_block = metadata->log_data[log_index].bsn;
	prev_plane_num = metadata->block_usage[prev_log_block].plane_num;
	num_valid = metadata->block_usage[prev_log_block].num_valid;

	//alloc new logblock and erase old logblock
	log_block = metadata->plane_meta[prev_plane_num].active_block;
	_ssd_alloc_active_block(prev_plane_num, elem_num, s);
	plane_num = metadata->block_usage[log_block].plane_num;
	metadata->log_data[log_index].bsn = log_block; 
	//move page old to new 
	j = 0;
	for( i = 0 ; i < s->params.pages_per_block ; i++) {
		if( metadata->log_data[log_index].page[i] != -1) {
			metadata->log_data[log_index].page[i] = j;
			metadata->block_usage[log_block].page[j] = 1;
			metadata->block_usage[log_block].num_valid++;
			j++;
		}
		metadata->block_usage[prev_log_block].page[i] = -1;
	}
	metadata->block_usage[prev_log_block].num_valid = 0;

	//plane metadata update
	metadata->plane_meta[prev_plane_num].valid_pages -= metadata->block_usage[log_block].num_valid;
	metadata->plane_meta[plane_num].valid_pages += metadata->block_usage[log_block].num_valid;

	//cost
	//read
	r_cost = s->params.page_read_latency * num_valid;
	cost += r_cost;
	ssd_power_flash_calculate(SSD_POWER_FLASH_READ, r_cost, power_stat, s);

	//write
	w_cost = s->params.page_write_latency * num_valid;
	cost += w_cost;
	ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, w_cost, power_stat, s);

	//transfer cost
	for( i = 0 ; i < num_valid ; i++) {
		double xfer_cost;
		xfer_cost = ssd_crossover_cost(s, metadata, power_stat, prev_log_block, log_block);
		cost += xfer_cost;
		s->elements[elem_num].stat.tot_xfer_cost += xfer_cost;
	}

	//erase U block
	cost += s->params.block_erase_latency;
	ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s);
	ssd_update_free_block_status(prev_log_block, prev_plane_num, metadata, s);
	ssd_update_block_lifetime(simtime+cost, prev_log_block, metadata);
	s->elements[elem_num].stat.pages_moved += num_valid;
	s->elements[elem_num].stat.num_clean ++;
	s->elements[elem_num].stat.num_replacement++;
	metadata->plane_meta[prev_plane_num].num_cleans++;

	return cost;

}