Ejemplo n.º 1
0
Archivo: ftl.c Proyecto: ESOS-Lab/VSSIM
int _FTL_READ(int32_t sector_nb, unsigned int length)
{
#ifdef FTL_DEBUG
	printf("[%s] Start\n",__FUNCTION__);
#endif
	if(sector_nb + length > SECTOR_NB){
		printf("Error[FTL_READ] Exceed Sector number\n"); 
		return FAIL;	
	}

	unsigned int remain = length;
	unsigned int lba = sector_nb;
	unsigned int left_skip = sector_nb % SECTORS_PER_PAGE;
	unsigned int right_skip;
	unsigned int read_sects;

	unsigned int phy_flash_nb;
	unsigned int phy_block_nb;
	unsigned int phy_page_nb;

	unsigned int ret = SUCCESS;
	unsigned int ret_seq, ret_ran_hot, ret_ran_cold, ret_data;

	int read_page_offset = 0;
	int io_page_nb;

#ifdef FIRM_IO_BUFFER
	INCREASE_RB_FTL_POINTER(length);
#endif

	while(remain > 0){

		if(remain > SECTORS_PER_PAGE - left_skip){
			right_skip = 0;
		}
		else{
			right_skip = SECTORS_PER_PAGE - left_skip - remain;
		}
		read_sects = SECTORS_PER_PAGE - left_skip - right_skip;

		ret_seq = FIND_PAGE_IN_SEQ_LOG(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);

		if(ret_seq != SUCCESS){
			ret_ran_hot = FIND_PAGE_IN_RAN_HOT_LOG(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);
		}

		if(ret_seq != SUCCESS && ret_ran_hot != SUCCESS){
			ret_ran_cold = FIND_PAGE_IN_RAN_COLD_LOG(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);
		}

		if(ret_seq != SUCCESS && ret_ran_hot != SUCCESS && ret_ran_cold != SUCCESS){
			ret_data = FIND_PAGE_IN_DATA_BLOCK(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);
		}
		
		if(ret_seq != SUCCESS && ret_ran_hot != SUCCESS && ret_ran_cold != SUCCESS && ret_data != SUCCESS){
#ifdef FTL_DEBUG
			printf("Error[FTL_READ] No Mapping info\n");
#endif
#ifdef FIRM_IO_BUFFER
			INCREASE_RB_LIMIT_POINTER();
#endif
			return FAIL;
		}

		lba += read_sects;
		remain -= read_sects;
		left_skip = 0;
	}

	io_alloc_overhead = ALLOC_IO_REQUEST(sector_nb, length, READ, &io_page_nb);

	remain = length;
	lba = sector_nb;
	left_skip = sector_nb % SECTORS_PER_PAGE;

	while(remain > 0){
	
		if(remain > SECTORS_PER_PAGE - left_skip){
			right_skip = 0;
		}
		else{
			right_skip = SECTORS_PER_PAGE - left_skip - remain;
		}
		read_sects = SECTORS_PER_PAGE - left_skip - right_skip;

		ret_seq = FIND_PAGE_IN_SEQ_LOG(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);

		if(ret_seq != SUCCESS){
			ret_ran_hot = FIND_PAGE_IN_RAN_HOT_LOG(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);
		}

		if(ret_seq != SUCCESS && ret_ran_hot != SUCCESS){
			ret_ran_cold = FIND_PAGE_IN_RAN_COLD_LOG(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);
		}

		if(ret_seq != SUCCESS && ret_ran_hot != SUCCESS && ret_ran_cold != SUCCESS){
			ret_data = FIND_PAGE_IN_DATA_BLOCK(lba, &phy_flash_nb, &phy_block_nb, &phy_page_nb);
		}
		

		if(ret_seq != SUCCESS && ret_ran_hot != SUCCESS && ret_ran_cold != SUCCESS && ret_data != SUCCESS){
#ifdef FTL_DEBUG
			printf("Error[FTL_READ] No Mapping info\n");
#endif
		}
		else{
			ret = SSD_PAGE_READ(phy_flash_nb, phy_block_nb, phy_page_nb, read_page_offset, READ, io_page_nb);
		}

		if(ret == SUCCESS){
#ifdef FTL_DEBUG
			printf("[FTL_READ] Complete [%d, %d, %d] from ",phy_flash_nb, phy_block_nb, phy_page_nb);

			if(ret_seq == SUCCESS){
				printf("SEQ Block\n");
			}
			else if(ret_ran_hot == SUCCESS){
				printf("RAN HOT Block\n");
			}
			else if(ret_ran_cold == SUCCESS){
				printf("RAN COLD Block\n");
			}
			else if(ret_data == SUCCESS){
				printf("DATA Block\n");
			}
			else{
				printf("No Map\n");
			}
#endif
		}
		else if(ret == FAIL){
			printf("Error[FTL_READ] %d page read fail \n", phy_page_nb);
		}

		read_page_offset++;

		lba += read_sects;
		remain -= read_sects;
		left_skip = 0;

	}

	INCREASE_IO_REQUEST_SEQ_NB();

#ifdef FIRM_IO_BUFFER
	INCREASE_RB_LIMIT_POINTER();
#endif

#ifdef MONITOR_ON
	char szTemp[1024];
	sprintf(szTemp, "READ PAGE %d ", length);
	WRITE_LOG(szTemp);
#endif

#ifdef FTL_DEBUG
	printf("[%s] End\n",__FUNCTION__);
#endif

	return ret;
}
Ejemplo n.º 2
0
Archivo: ftl.c Proyecto: windsoul/vssim
/* add ratio of newly written page, one by one.
   whenever we dont have enough space to add to bin, split lpn to two parts, 
   dump page, and add overflow to the newly emptied bin*/
int _FTL_BUF(int lpn, double ratio, int is_gc)
{
	int i, bpn_idx, b_lpn, temp_bpn_idx = -1;
	int ret;
	int32_t new_ppn;
	int io_page_nb;
	int length = SECTORS_PER_PAGE; /* write 1 page at most*/
	int bin_idx = 0;
	int max_lpns = 0;
	double overflow_ratio;
	total_compression_ratio += ratio;
	total_lpn_count++;

	//if(fmod(ratio, 0.001) < 0.001)
	//	ratio = ratio - fmod(ratio, 0.001);
	LOG("lpn %d ratio %f", lpn, ratio);
	/* check if already buffered*/
	for(bpn_idx=0; bpn_idx<MAX_COMPRESSED_LPN_PER_PPN*BIN_COUNT; bpn_idx++){ 
		/* already buffered */
		if(bpns[bpn_idx].lpn == lpn){
			LOG("lpn %d already buffered in bpn %d (index %d ratio %f)", lpn, bpn_idx, bpns[bpn_idx].index, bpns[bpn_idx].ratio);
			remove_from_bin(bpn_idx);// remove from bin
			init_bpn(&bpns[bpn_idx]); 
		}
	}

	/* find empty bpn. must find one!*/
	bpn_idx = find_empty_bpn();
	assert(bpn_idx != MAX_COMPRESSED_LPN_PER_PPN*BIN_COUNT);

	//printf("found bpn_idx %d\n", bpn_idx);

	/* put in bin, and invalidate old */
	overflow_ratio = update_bin_bpn(bin_idx, bpn_idx, lpn, ratio, 0);
	LOG("overflow_ratio %f", overflow_ratio);
	//printf("add lpn %d ratio %f to bin %d. new bin count %d\n", bpns[bpn_idx].lpn, ratio, i, bins[i].count);
	LOG("lpn %d invalidate both indexes", lpn);
	UPDATE_OLD_PAGE_MAPPING(lpn, 0);
	UPDATE_OLD_PAGE_MAPPING(lpn, 1);

	/* bin not full */
	if (overflow_ratio == 0.0000)
		return 0;

dump_bin:
	/* bin too full, caused overflow. save ratio of overflow*/
	/* need to dump!*/
	if(!is_gc)
		io_alloc_overhead = ALLOC_IO_REQUEST(0, length, WRITE, &io_page_nb);

	ret = GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &new_ppn);
	if(ret == FAIL){
		printf("ERROR[FTL_WRITE] Get new page fail \n");
		assert(0);
		return -1;
	}
	
	ret = SSD_PAGE_WRITE(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn), CALC_PAGE(new_ppn), 0, (is_gc)?GC_WRITE:WRITE, io_page_nb);
	LOG("dumped bin to new_ppn %d", new_ppn);
#ifdef FTL_DEBUG
	if(ret == FAIL){
		printf("Error[_FTL_BIN_PACK] %d page write fail \n", new_ppn);
		assert(0);
		return -1;
	}
#endif

	/* choose bin to dump*/
	bin_idx = 0;
	max_lpns = bins[0].count;

	LOG("dump bin %d (has %d lpns)\n", bin_idx, bins[bin_idx].count);
	/* Update mappings for all moved compressed LPNs */
	for(i=0;i<MAX_COMPRESSED_LPN_PER_PPN;i++){
		temp_bpn_idx = bins[bin_idx].bpns[i];
		if(temp_bpn_idx <0){
			assert(i>0);
			break;
		}
		b_lpn = bpns[temp_bpn_idx].lpn;

		LOG("b_lpn %d update new index %d", b_lpn, bpns[temp_bpn_idx].index);
		UPDATE_NEW_PAGE_MAPPING(b_lpn, 
					new_ppn, 
					bpns[temp_bpn_idx].ratio,// updates relevant valid_array entry as well
					bpns[temp_bpn_idx].index); // index
		//printf("update mapping for lpn %d raiot %.02f new_ppn %d\n", b_lpn, bpns[temp_bpn_idx].ratio, new_ppn);
		/* dont forget to update reelvant bpn*/
		init_bpn(&bpns[temp_bpn_idx]);
	}

	/* init evicted bin, insert new bpn, and increment bin_idx */
	init_bin(&bins[bin_idx]);
	
	/* insert to bin, this time with the leftover overflow_ratio*/
	bpn_idx = find_empty_bpn();
	assert(bpn_idx < MAX_COMPRESSED_LPN_PER_PPN*BIN_COUNT);
	LOG("update overflow index 1");
	update_bin_bpn(bin_idx, bpn_idx, lpn, overflow_ratio, (overflow_ratio < ratio)?1:0 /*overflow -> index 1*/);

	/* finish writing */
	if(!is_gc)
		INCREASE_IO_REQUEST_SEQ_NB();

#ifdef GC_ON
	if(!is_gc)
		GC_CHECK(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn));
#endif

#ifdef MONITOR_ON
	char szTemp[1024];
	sprintf(szTemp, "WRITE PAGE %d ", length);
	WRITE_LOG(szTemp);
	sprintf(szTemp, "WB CORRECT %d", 1);
	WRITE_LOG(szTemp);
#endif

	return 1;
}
Ejemplo n.º 3
0
Archivo: ftl.c Proyecto: windsoul/vssim
int _FTL_READ(int32_t sector_nb, unsigned int length)
{
#ifdef FTL_DEBUG
	printf("[%s] Start: sector_nb %d length %u\n",__FUNCTION__, sector_nb, length);
#endif

	if(sector_nb + length > SECTOR_NB){
		printf("Error[FTL_READ] Exceed Sector number\n"); 
		return FAIL;	
	}

	int32_t lpn;
	int32_t *ppn;
	int32_t lba = sector_nb;
	unsigned int remain = length;
	unsigned int left_skip = sector_nb % SECTORS_PER_PAGE;
	unsigned int right_skip;
	unsigned int read_sects;
	unsigned int i, real_read_length = 0;

	unsigned int ret = FAIL;
	int read_page_nb = 0;
	int io_page_nb;

	while(remain > 0){

		if(remain > SECTORS_PER_PAGE - left_skip){
			right_skip = 0;
		}
		else{
			right_skip = SECTORS_PER_PAGE - left_skip - remain;
		}
		read_sects = SECTORS_PER_PAGE - left_skip - right_skip;

		lpn = lba / (int32_t)SECTORS_PER_PAGE;
		ppn = GET_MAPPING_INFO(lpn);

		if(ppn[0] == -1){
			return FAIL;
		}

		real_read_length += SECTORS_PER_PAGE;
		if(ppn[1] != -1){
			real_read_length += SECTORS_PER_PAGE;
		}

		lba += read_sects;
		remain -= read_sects;
		left_skip = 0;
	}

	io_alloc_overhead = ALLOC_IO_REQUEST(sector_nb, real_read_length, READ, &io_page_nb);

	remain = length;
	lba = sector_nb;
	left_skip = sector_nb % SECTORS_PER_PAGE;

	while(remain > 0){

		if(remain > SECTORS_PER_PAGE - left_skip){
			right_skip = 0;
		}
		else{
			right_skip = SECTORS_PER_PAGE - left_skip - remain;
		}
		read_sects = SECTORS_PER_PAGE - left_skip - right_skip;

		lpn = lba / (int32_t)SECTORS_PER_PAGE;

		ppn = GET_MAPPING_INFO(lpn);

		for(i=0; i<2; i++){
			if(ppn[i] == -1){
	#ifdef FTL_DEBUG
					printf("Error[%s] No Mapping info\n",__FUNCTION__);
	#endif
				/* its legal for 2nd index to be empty*/
				if(i==1)
					break;
			}

			//LOG("lpn %d ppn %d", lpn, ppn);
			ret = SSD_PAGE_READ(CALC_FLASH(ppn[i]), CALC_BLOCK(ppn[i]), CALC_PAGE(ppn[i]), read_page_nb, READ, io_page_nb);

			if(ret == FAIL){
				printf("Error[%s] %u page read fail \n", __FUNCTION__, ppn[i]);
			}
			read_page_nb++;
		}

		lba += read_sects;
		remain -= read_sects;
		left_skip = 0;
	}

	INCREASE_IO_REQUEST_SEQ_NB();

#ifdef MONITOR_ON
	char szTemp[1024];
	sprintf(szTemp, "READ PAGE %d ", length);
	WRITE_LOG(szTemp);
#endif

#ifdef FTL_DEBUG
	printf("[%s] Complete\n",__FUNCTION__);
#endif

	return ret;
}
Ejemplo n.º 4
0
Archivo: ftl.c Proyecto: windsoul/vssim
int _FTL_WRITE(int32_t sector_nb, unsigned int length)
{
#ifdef FTL_DEBUG
	printf("[%s] Start: sector_nb %d length %u\n",__FUNCTION__, sector_nb, length);
#endif
	int io_page_nb;

	if(sector_nb + length > SECTOR_NB){
		printf("Error[FTL_WRITE] Exceed Sector number\n");
                return FAIL;
        }
	else{
		io_alloc_overhead = ALLOC_IO_REQUEST(sector_nb, length, WRITE, &io_page_nb);
	}

	int32_t lba = sector_nb;
	int32_t lpn;
	int32_t new_ppn;

	unsigned int remain = length;
	unsigned int left_skip = sector_nb % SECTORS_PER_PAGE;
	unsigned int right_skip;
	unsigned int write_sects;

	unsigned int ret = FAIL;
	int write_page_nb=0;

	total_lpn_count += length / SECTORS_PER_PAGE;

	while(remain > 0){

		if(remain > SECTORS_PER_PAGE - left_skip){
			right_skip = 0;
		}
		else{
			right_skip = SECTORS_PER_PAGE - left_skip - remain;
		}

		write_sects = SECTORS_PER_PAGE - left_skip - right_skip;

		ret = GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &new_ppn);
		if(ret == FAIL){
			printf("ERROR[FTL_WRITE] Get new page fail \n");
			return FAIL;
		}

		ret = SSD_PAGE_WRITE(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn), CALC_PAGE(new_ppn), write_page_nb, WRITE, io_page_nb);

		write_page_nb++;

		lpn = lba / (int32_t)SECTORS_PER_PAGE;
		UPDATE_OLD_PAGE_MAPPING(lpn);
		UPDATE_NEW_PAGE_MAPPING(lpn, new_ppn);

#ifdef FTL_DEBUG
                if(ret == FAIL){
                        printf("Error[FTL_WRITE] %d page write fail \n", new_ppn);
                }
#endif
		lba += write_sects;
		remain -= write_sects;
		left_skip = 0;
	}


	INCREASE_IO_REQUEST_SEQ_NB();

#ifdef GC_ON
	GC_CHECK(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn));
#endif

#ifdef MONITOR_ON
	char szTemp[1024];
	sprintf(szTemp, "WRITE PAGE %d ", length);
	WRITE_LOG(szTemp);
	sprintf(szTemp, "WB CORRECT %d", write_page_nb);
	WRITE_LOG(szTemp);
#endif

#ifdef FTL_DEBUG
	printf("[%s] Complete\n",__FUNCTION__);
#endif
	return ret;
}
Ejemplo n.º 5
0
int _FTL_OBJ_READ(object_id_t object_id, unsigned int offset, unsigned int length)
{
    stored_object *object;
    page_node *current_page;
    int io_page_nb;
    int curr_io_page_nb;
    unsigned int ret = FAIL;
    
    object = lookup_object(object_id);
    
    // file not found
    if (object == NULL)
        return FAIL;
    // object not big enough
    if (object->size < (offset + length))
        return FAIL;
    
    if(!(current_page = page_by_offset(object, offset)))
    {
        printf("Error[%s] %u lookup page by offset failed \n", __FUNCTION__, current_page->page_id);
        return FAIL;
    }
    
    // just calculate the overhead of allocating the request. io_page_nb will be the total number of pages we're gonna read
	io_alloc_overhead = ALLOC_IO_REQUEST(current_page->page_id * SECTORS_PER_PAGE, length, READ, &io_page_nb);
    
    for (curr_io_page_nb = 0; curr_io_page_nb < io_page_nb; curr_io_page_nb++)
    {
        // simulate the page read
        ret = SSD_PAGE_READ(CALC_FLASH(current_page->page_id), CALC_BLOCK(current_page->page_id), CALC_PAGE(current_page->page_id), curr_io_page_nb, READ, io_page_nb);
        
		// send a physical read action being done to the statistics gathering
		if (ret == SUCCESS)
		{
			FTL_STATISTICS_GATHERING(current_page->page_id, PHYSICAL_READ);
		}

#ifdef FTL_DEBUG
		if (ret == FAIL)
		{
			printf("Error[%s] %u page read fail \n", __FUNCTION__, current_page->page_id);
		}
#endif
        
        // get the next page
        current_page = current_page->next;
    }
    
    INCREASE_IO_REQUEST_SEQ_NB();

#ifdef MONITOR_ON
	char szTemp[1024];
	sprintf(szTemp, "READ PAGE %d ", length);
	WRITE_LOG(szTemp);
#endif

#ifdef FTL_DEBUG
	printf("[%s] Complete\n",__FUNCTION__);
#endif

	return ret;
}
Ejemplo n.º 6
0
int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int length)
{
    stored_object *object;
    page_node *current_page = NULL,*temp_page;
    uint32_t page_id;
    int io_page_nb;
    int curr_io_page_nb;
    unsigned int ret = FAIL;
    
    object = lookup_object(object_id);
    
    // file not found
    if (object == NULL)
        return FAIL;
    
    // calculate the overhead of allocating the request. io_page_nb will be the total number of pages we're gonna write
    io_alloc_overhead = ALLOC_IO_REQUEST(offset, length, WRITE, &io_page_nb);
    
    // if the offset is past the current size of the stored_object we need to append new pages until we can start writing
    while (offset > object->size)
    {
        if (GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &page_id) == FAIL)
        {
            // not enough memory presumably
            printf("ERROR[FTL_WRITE] Get new page fail \n");
            return FAIL;
        }
        if(!add_page(object, page_id))
            return FAIL;
        
        // mark new page as valid and used
        UPDATE_NEW_PAGE_MAPPING_NO_LOGICAL(page_id);
    }

    for (curr_io_page_nb = 0; curr_io_page_nb < io_page_nb; curr_io_page_nb++)
    {
        // if this is the first iteration we need to find the page by offset, otherwise we can go with the page chain
        if (current_page == NULL)
            current_page = page_by_offset(object, offset);
        else
            current_page = current_page->next;
        
        // get the pge we'll be writing to
        if (GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &page_id) == FAIL)
        {
            printf("ERROR[FTL_WRITE] Get new page fail \n");
            return FAIL;
        }
        if((temp_page=lookup_page(page_id)))
        {
            printf("ERROR[FTL_WRITE] Object %lu already contains page %d\n",temp_page->object_id,page_id);
            return FAIL;
        }
        
        // mark new page as valid and used
        UPDATE_NEW_PAGE_MAPPING_NO_LOGICAL(page_id);
        
        if (current_page == NULL) // writing at the end of the object and need to allocate more space for it
        {
            current_page = add_page(object, page_id);
            if(!current_page)
                return FAIL;
        }
        else // writing over parts of the object
        {
            // invalidate the old physical page and replace the page_node's page
            UPDATE_INVERSE_BLOCK_VALIDITY(CALC_FLASH(current_page->page_id), CALC_BLOCK(current_page->page_id), CALC_PAGE(current_page->page_id), INVALID);
            UPDATE_INVERSE_PAGE_MAPPING(current_page->page_id, -1);            

            HASH_DEL(global_page_table, current_page); 
            current_page->page_id = page_id;
            HASH_ADD_INT(global_page_table, page_id, current_page); 
        }
#ifdef GC_ON
            // must improve this because it is very possible that we will do multiple GCs on the same flash chip and block
            // probably gonna add an array to hold the unique ones and in the end GC all of them
            GC_CHECK(CALC_FLASH(current_page->page_id), CALC_BLOCK(current_page->page_id), false);
#endif
        
        ret = SSD_PAGE_WRITE(CALC_FLASH(page_id), CALC_BLOCK(page_id), CALC_PAGE(page_id), curr_io_page_nb, WRITE, io_page_nb);
        
		// send a physical write action being done to the statistics gathering
		if (ret == SUCCESS)
		{
			FTL_STATISTICS_GATHERING(page_id , PHYSICAL_WRITE);
		}
        
#ifdef FTL_DEBUG
        if (ret == FAIL)
        {
            printf("Error[FTL_WRITE] %d page write fail \n", page_id);
        }
#endif

//        page_node *page;
//        printf("Object page map:{");
//        for(page=object->pages; page; page=page->next)
//            printf("%d->",page->page_id);
//        printf("}\n");

    }

    INCREASE_IO_REQUEST_SEQ_NB();

#ifdef MONITOR_ON
	char szTemp[1024];
	sprintf(szTemp, "WRITE PAGE %d ", length);
	WRITE_LOG(szTemp);
	sprintf(szTemp, "WB CORRECT %d", curr_io_page_nb);
	WRITE_LOG(szTemp);
#endif

#ifdef FTL_DEBUG
	printf("[%s] Complete\n",__FUNCTION__);
#endif

	return ret;
}