diff --git a/eVSSIM/CONFIG/ssd.conf b/eVSSIM/CONFIG/ssd.conf index a96f3487e..b7de8e6eb 100755 --- a/eVSSIM/CONFIG/ssd.conf +++ b/eVSSIM/CONFIG/ssd.conf @@ -2,7 +2,7 @@ FILE_NAME ./data/ssd.img PAGE_SIZE 4096 PAGE_NB 10 SECTOR_SIZE 1 -FLASH_NB 4 +FLASH_NB 32 BLOCK_NB 4096 PLANES_PER_FLASH 1 REG_WRITE_DELAY 82 @@ -16,4 +16,5 @@ CHANNEL_NB 4 STAT_TYPE 15 STAT_SCOPE 62 STAT_PATH /tmp/stat.csv +OSD_PATH /tmp/osd/ STORAGE_STRATEGY 1 diff --git a/eVSSIM/CONFIG/vssim_config_manager.c b/eVSSIM/CONFIG/vssim_config_manager.c index fe90caee7..59d03952e 100755 --- a/eVSSIM/CONFIG/vssim_config_manager.c +++ b/eVSSIM/CONFIG/vssim_config_manager.c @@ -6,8 +6,8 @@ #include "common.h" /* SSD Configuration */ -int SECTOR_SIZE; -int PAGE_SIZE; +int eVSSIM_SECTOR_SIZE; +int eVSSIM_PAGE_SIZE; int64_t SECTOR_NB; int PAGE_NB; @@ -59,10 +59,10 @@ double GC_L2_THRESHOLD; int GC_L2_THRESHOLD_BLOCK_NB; #endif -/* Storage strategy (1 = address-based, 2 = object-based */ int STORAGE_STRATEGY; char gFile_Name[PATH_MAX] = {0,}; +char OSD_PATH[PATH_MAX] = {0,}; char STAT_PATH[PATH_MAX] = {0,}; void INIT_SSD_CONFIG(void) @@ -83,10 +83,16 @@ void INIT_SSD_CONFIG(void) if(fscanf(pfData, "%s", gFile_Name) == EOF) printf("ERROR[%s] Cannot read filename\n",__FUNCTION__); + } + else if(strcmp(szCommand, "OSD_PATH") == 0) + { + if(fscanf(pfData, "%s", OSD_PATH) == EOF) + printf("ERROR[%s] Cannot read temp OSD path\n",__FUNCTION__); + } else if(strcmp(szCommand, "PAGE_SIZE") == 0) { - if(fscanf(pfData, "%d", &PAGE_SIZE) == EOF) + if(fscanf(pfData, "%d", &eVSSIM_PAGE_SIZE) == EOF) printf("ERROR[%s] Wrong PAGE_SIZE\n",__FUNCTION__); } else if(strcmp(szCommand, "PAGE_NB") == 0) @@ -96,7 +102,7 @@ void INIT_SSD_CONFIG(void) } else if(strcmp(szCommand, "SECTOR_SIZE") == 0) { - if(fscanf(pfData, "%d", &SECTOR_SIZE) == EOF) + if(fscanf(pfData, "%d", &eVSSIM_SECTOR_SIZE) == EOF) printf("ERROR[%s] Wrong SECTOR_SIZE\n",__FUNCTION__); } else if(strcmp(szCommand, "FLASH_NB") == 0) @@ -207,12 +213,10 @@ void INIT_SSD_CONFIG(void) } #endif else if(strcmp(szCommand, "STORAGE_STRATEGY") == 0) - { - if(fscanf(pfData, "%d", &STORAGE_STRATEGY) == EOF) - printf("ERROR[%s] Wrong STORAGE_STRATEGY\n",__FUNCTION__); - - - } + { + if(fscanf(pfData, "%d", &STORAGE_STRATEGY) == EOF) + printf("ERROR[%s] Wrong STORAGE_STRATEGY\n",__FUNCTION__); + } memset(szCommand, 0x00, 1024); } fclose(pfData); @@ -232,7 +236,7 @@ void INIT_SSD_CONFIG(void) } /* SSD Configuration */ - SECTORS_PER_PAGE = PAGE_SIZE / SECTOR_SIZE; + SECTORS_PER_PAGE = eVSSIM_PAGE_SIZE / eVSSIM_SECTOR_SIZE; PAGES_PER_FLASH = PAGE_NB * BLOCK_NB; SECTOR_NB = (int64_t)SECTORS_PER_PAGE * (int64_t)PAGE_NB * (int64_t)BLOCK_NB * (int64_t)FLASH_NB; diff --git a/eVSSIM/CONFIG/vssim_config_manager.h b/eVSSIM/CONFIG/vssim_config_manager.h index 2336b726f..b3e315bea 100755 --- a/eVSSIM/CONFIG/vssim_config_manager.h +++ b/eVSSIM/CONFIG/vssim_config_manager.h @@ -6,12 +6,11 @@ #ifndef _CONFIG_MANAGER_H_ #define _CONFIG_MANAGER_H_ -#include "common.h" #include /* SSD Configuration */ -extern int SECTOR_SIZE; -extern int PAGE_SIZE; +extern int eVSSIM_SECTOR_SIZE; +extern int eVSSIM_PAGE_SIZE; extern int64_t SECTOR_NB; extern int PAGE_NB; @@ -63,10 +62,12 @@ extern int GC_L2_THRESHOLD_BLOCK_NB; extern int STAT_TYPE; extern int STAT_SCOPE; extern char STAT_PATH[PATH_MAX]; -void INIT_SSD_CONFIG(void); -char* GET_FILE_NAME(void); +extern char OSD_PATH[PATH_MAX]; -/* Storage strategy (1 = address-based, 2 = object-based */ +/* Storage strategy (0 = Sector based, 1 = Object based */ extern int STORAGE_STRATEGY; +void INIT_SSD_CONFIG(void); +char* GET_FILE_NAME(void); + #endif diff --git a/eVSSIM/FTL_SOURCE/COMMON/common.h b/eVSSIM/FTL_SOURCE/COMMON/common.h index 24bb7b303..52cf748fd 100755 --- a/eVSSIM/FTL_SOURCE/COMMON/common.h +++ b/eVSSIM/FTL_SOURCE/COMMON/common.h @@ -14,9 +14,10 @@ #include #include #include "ftl_type.h" +#include /* FTL */ -//#define FTL_DEBUG 1 +#define FTL_DEBUG 1 /* VSSIM Function */ #define MONITOR_ON @@ -31,20 +32,23 @@ #include "ftl_inverse_mapping_manager.h" #include "ftl_perf_manager.h" -#include "ftl_sect_strategy.h" -#include "ftl_obj_strategy.h" - -#include "ssd_util.h" #include "ssd_io_manager.h" #include "ssd_log_manager.h" +#ifdef VSSIMDEBUG +#define LOG_VSSIMDBG(fmt, ...) \ + printf("DBG|: " fmt "\n",## __VA_ARGS__) +#else +#define LOG_VSSIMDBG(fmt, ...) +#endif + #ifdef PAGE_MAP #include "ftl_gc_manager.h" #include "ftl_mapping_manager.h" #endif -#define SUCCESS 1 -#define FAIL 0 +#define SUCCESSFUL 1 +#define FAILURE 0 /* Block Type */ #define EMPTY_BLOCK 30 diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.c b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.c index 5a2eb035c..bff8fa61d 100755 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.c +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.c @@ -3,7 +3,10 @@ // Hanyang University, Seoul, Korea // Embedded Software Systems Lab. All right reserved + #include "common.h" +#include "ftl_sect_strategy.h" +#include "ftl_obj_strategy.h" #include #include @@ -16,7 +19,6 @@ extern double ssd_util; int gatherStats = 0; //Hold statistics information uint32_t** mapping_stats_table; -storage_strategy_functions* storage_strategy; void FTL_INIT(void) { @@ -31,7 +33,6 @@ void FTL_INIT(void) INIT_EMPTY_BLOCK_LIST(); INIT_VICTIM_BLOCK_LIST(); INIT_PERF_CHECKER(); - FTL_INIT_STRATEGY(); //Initialize The Statistics gathering component. FTL_INIT_STATS(); @@ -59,69 +60,10 @@ void FTL_TERM(void) printf("[%s] complete\n",__FUNCTION__); } -void FTL_INIT_STRATEGY(void) -{ - storage_strategy = malloc(sizeof(storage_strategy_functions)); - - if (STORAGE_STRATEGY == STORAGE_STRATEGY_OBJECT) - { - storage_strategy->FTL_READ = _FTL_OBJ_READ; - storage_strategy->FTL_WRITE = _FTL_OBJ_WRITE; - storage_strategy->FTL_COPYBACK = _FTL_OBJ_COPYBACK; - storage_strategy->FTL_CREATE = _FTL_OBJ_CREATE; - storage_strategy->FTL_DELETE = _FTL_OBJ_DELETE; - - // object strategy needs initializing, unlike current other strategies - INIT_OBJ_STRATEGY(); - } - else // default behaviour, if strategy was not defined or is invalid or whatever - { - storage_strategy->FTL_READ = _FTL_READ; - storage_strategy->FTL_WRITE = _FTL_WRITE; - storage_strategy->FTL_COPYBACK = _FTL_COPYBACK; - storage_strategy->FTL_CREATE = _FTL_CREATE; - storage_strategy->FTL_DELETE = _FTL_DELETE; - } -} - void FTL_TERM_STRATEGY(void) { - if(STORAGE_STRATEGY == STORAGE_STRATEGY_OBJECT) - TERM_OBJ_STRATEGY(); - free(storage_strategy); -} - -void FTL_READ(uint64_t id, unsigned int offset, unsigned int length) -{ - int ret; - - ret = storage_strategy->FTL_READ(id, offset, length); -} - -void FTL_WRITE(uint64_t id, unsigned int offset, unsigned int length) -{ - int ret; - - ret = storage_strategy->FTL_WRITE(id, offset, length); -} - -int FTL_COPYBACK(uint32_t source, uint32_t destination) -{ - return storage_strategy->FTL_COPYBACK(source, destination); -} - -void FTL_CREATE(size_t size) -{ - int ret; - - ret = storage_strategy->FTL_CREATE(size); -} - -void FTL_DELETE(uint64_t id) -{ - int ret; - - ret = storage_strategy->FTL_DELETE(id); + //As we can't figure out the storage strategy at this point, We can terminate the object strategy anyway... at the worst case where we're actually using the sector strtegy, it won't do anything and return + TERM_OBJ_STRATEGY(); } void FTL_INIT_STATS(void) @@ -201,17 +143,17 @@ int FTL_STATISTICS_GATHERING(uint32_t address , int type){ if (gatherStats == 0) { - return SUCCESS; + return SUCCESSFUL; } if (address > PAGE_MAPPING_ENTRY_NB){ - return FAIL; + return FAILURE; } //Increase the count of the action that was done. mapping_stats_table[type][address] = mapping_stats_table[type][address] + 1; - return SUCCESS; + return SUCCESSFUL; } uint32_t FTL_STATISTICS_QUERY (uint32_t address, int scope , int type){ diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.h b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.h index 16fcf8cd0..bc4ff6936 100755 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.h +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl.h @@ -6,20 +6,12 @@ #ifndef _FTL_H_ #define _FTL_H_ -#include "common.h" extern uint32_t** mapping_stats_table; void FTL_INIT(void); void FTL_TERM(void); -void FTL_INIT_STRATEGY(void); void FTL_TERM_STRATEGY(void); -void FTL_READ(uint64_t id, unsigned int offset, unsigned int length); -void FTL_WRITE(uint64_t id, unsigned int offset, unsigned int length); -int FTL_COPYBACK(uint32_t source, uint32_t destination); -void FTL_CREATE(size_t size); -void FTL_DELETE(uint64_t id); - void FTL_INIT_STATS(void); int FTL_STATISTICS_GATHERING(uint32_t page_nb , int type); uint32_t FTL_STATISTICS_QUERY(uint32_t address, int scope , int type); @@ -29,16 +21,4 @@ void FTL_TERM_STATS(void); void FTL_RECORD_SCOPE_STAT(FILE* fp , int scope); void *STAT_LISTEN(void *socket); -/* Storage strategy function pointers' struct */ -typedef struct { - int (* FTL_READ)(uint64_t, unsigned int, unsigned int); - int (* FTL_WRITE)(uint64_t, unsigned int, unsigned int); - int (* FTL_COPYBACK)(int, int); - int (* FTL_CREATE)(size_t); - int (* FTL_DELETE)(uint64_t); -} storage_strategy_functions; - -#define STORAGE_STRATEGY_SECTOR 1 -#define STORAGE_STRATEGY_OBJECT 2 - #endif diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.c b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.c index 51b98c0f8..141e67198 100755 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.c +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.c @@ -4,13 +4,18 @@ // Embedded Software Systems Lab. All right reserved #include "common.h" +#include "ftl_sect_strategy.h" +#include "ftl_obj_strategy.h" unsigned int gc_count = 0; int fail_cnt = 0; extern double ssd_util; -void GC_CHECK(unsigned int phy_flash_nb, unsigned int phy_block_nb, bool force) +write_amplification_counters wa_counters; + + +void GC_CHECK(unsigned int phy_flash_nb, unsigned int phy_block_nb, bool force, bool isObjectStrategy) { int i, ret; int plane_nb = phy_block_nb % PLANES_PER_FLASH; @@ -19,15 +24,15 @@ void GC_CHECK(unsigned int phy_flash_nb, unsigned int phy_block_nb, bool force) if(force || total_empty_block_nb < GC_THRESHOLD_BLOCK_NB){ int l2 = total_empty_block_nb < GC_L2_THRESHOLD_BLOCK_NB; for(i=0; i meaning, we wrote to that new block so we need to update the relevant counter + wa_counters.physical_block_write_counter++; + } } if(copy_page_nb != valid_page_nb){ printf("ERROR[GARBAGE_COLLECTION] The number of valid page is not correct copy_page_nb (%d) != valid_page_nb (%d)\n", copy_page_nb, valid_page_nb); - return FAIL; + return FAILURE; } SSD_BLOCK_ERASE(victim_phy_flash_nb, victim_phy_block_nb); + //update the physical block write counter as we're deleting the victim block which we're freeing during the GC procedure + wa_counters.physical_block_write_counter++; UPDATE_INVERSE_BLOCK_MAPPING(victim_phy_flash_nb, victim_phy_block_nb, EMPTY_BLOCK); INSERT_EMPTY_BLOCK(victim_phy_flash_nb, victim_phy_block_nb); @@ -128,11 +142,11 @@ int GARBAGE_COLLECTION(int mapping_index, int l2) char szTemp[1024]; sprintf(szTemp, "GC "); WRITE_LOG(szTemp); - sprintf(szTemp, "WB AMP %d", copy_page_nb); + sprintf(szTemp, "WB AMP %f", (float)wa_counters.physical_block_write_counter / (float)wa_counters.logical_block_write_counter); WRITE_LOG(szTemp); #endif - return SUCCESS; + return SUCCESSFUL; } /* Greedy Garbage Collection Algorithm */ @@ -149,7 +163,7 @@ int SELECT_VICTIM_BLOCK(unsigned int* phy_flash_nb, unsigned int* phy_block_nb) #ifdef FTL_DEBUG printf("ERROR[SELECT_VICTIM_BLOCK] There is no victim block\n"); #endif //FTL_DEBUG - return FAIL; + return FAILURE; } /* if GC_TRIGGER_OVERALL is defined, then */ @@ -178,12 +192,12 @@ int SELECT_VICTIM_BLOCK(unsigned int* phy_flash_nb, unsigned int* phy_block_nb) } if(*(victim_block->valid_page_nb) == PAGE_NB){ fail_cnt++; - return FAIL; + return FAILURE; } *phy_flash_nb = victim_block->phy_flash_nb; *phy_block_nb = victim_block->phy_block_nb; EJECT_VICTIM_BLOCK(victim_block); - return SUCCESS; + return SUCCESSFUL; } diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.h b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.h index eda466751..839db292f 100755 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.h +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_gc_manager.h @@ -8,9 +8,17 @@ extern unsigned int gc_count; -void GC_CHECK(unsigned int phy_flash_nb, unsigned int phy_block_nb, bool force); +void GC_CHECK(unsigned int phy_flash_nb, unsigned int phy_block_nb, bool force, bool isObjectStrategy); -int GARBAGE_COLLECTION(int mapping_index, int l2); +int GARBAGE_COLLECTION(int mapping_index, int l2, bool isObjectStrategy); int SELECT_VICTIM_BLOCK(unsigned int* phy_flash_nb, unsigned int* phy_block_nb); +typedef struct write_amplification_counters +{ + unsigned long logical_block_write_counter; + unsigned long physical_block_write_counter; +}write_amplification_counters; + +extern write_amplification_counters wa_counters; + #endif diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_inverse_mapping_manager.c b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_inverse_mapping_manager.c index 918cc0639..fa08a65f1 100755 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_inverse_mapping_manager.c +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_inverse_mapping_manager.c @@ -400,6 +400,8 @@ void TERM_VICTIM_BLOCK_LIST(void) fclose(fp); } +//If we're using the VICTIM_OVERALL option, then a candidate block (one with an empty page available) is returned from a different +//flash plane each time, sequentially (wraps at the end and starts all over again) empty_block_entry* GET_EMPTY_BLOCK(int mode, int mapping_index) { if(total_empty_block_nb == 0){ @@ -561,7 +563,7 @@ int INSERT_EMPTY_BLOCK(unsigned int phy_flash_nb, unsigned int phy_block_nb) new_empty_block = (empty_block_entry*)calloc(1, sizeof(empty_block_entry)); if(new_empty_block == NULL){ printf("ERROR[%s] Alloc new empty block fail\n",__FUNCTION__); - return FAIL; + return FAILURE; } /* Init New empty block */ @@ -586,7 +588,7 @@ int INSERT_EMPTY_BLOCK(unsigned int phy_flash_nb, unsigned int phy_block_nb) } total_empty_block_nb++; - return SUCCESS; + return SUCCESSFUL; } int INSERT_VICTIM_BLOCK(empty_block_entry* full_block){ @@ -604,7 +606,7 @@ int INSERT_VICTIM_BLOCK(empty_block_entry* full_block){ new_victim_block = (victim_block_entry*)calloc(1, sizeof(victim_block_entry)); if(new_victim_block == NULL){ printf("ERROR[%s] Calloc fail\n",__FUNCTION__); - return FAIL; + return FAILURE; } /* Copy the full block address */ @@ -638,7 +640,7 @@ int INSERT_VICTIM_BLOCK(empty_block_entry* full_block){ /* Update the total number of victim block */ total_victim_block_nb++; - return SUCCESS; + return SUCCESSFUL; } int EJECT_VICTIM_BLOCK(victim_block_entry* victim_block){ @@ -679,7 +681,7 @@ int EJECT_VICTIM_BLOCK(victim_block_entry* victim_block){ /* Free the victim block */ free(victim_block); - return SUCCESS; + return SUCCESSFUL; } inverse_block_mapping_entry* GET_INVERSE_BLOCK_MAPPING_ENTRY(unsigned int phy_flash_nb, unsigned int phy_block_nb){ @@ -702,7 +704,7 @@ int UPDATE_INVERSE_PAGE_MAPPING(uint32_t ppn, uint32_t lpn) { inverse_page_mapping_table[ppn] = lpn; - return SUCCESS; + return SUCCESSFUL; } int UPDATE_INVERSE_BLOCK_MAPPING(unsigned int phy_flash_nb, unsigned int phy_block_nb, int type) @@ -718,14 +720,14 @@ int UPDATE_INVERSE_BLOCK_MAPPING(unsigned int phy_flash_nb, unsigned int phy_blo } } - return SUCCESS; + return SUCCESSFUL; } int UPDATE_INVERSE_BLOCK_VALIDITY(unsigned int phy_flash_nb, unsigned int phy_block_nb, unsigned int phy_page_nb, int valid) { if(phy_flash_nb >= FLASH_NB || phy_block_nb >= BLOCK_NB || phy_page_nb >= PAGE_NB){ printf("ERROR[%s] Wrong physical address\n",__FUNCTION__); - return FAIL; + return FAILURE; } int i; @@ -755,5 +757,5 @@ int UPDATE_INVERSE_BLOCK_VALIDITY(unsigned int phy_flash_nb, unsigned int phy_bl } mapping_entry->valid_page_nb = valid_count; - return SUCCESS; + return SUCCESSFUL; } diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_mapping_manager.c b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_mapping_manager.c index dbd4ff762..9e3d7fa20 100755 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_mapping_manager.c +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_mapping_manager.c @@ -64,16 +64,24 @@ int GET_NEW_PAGE(int mode, int mapping_index, uint32_t* ppn) if(curr_empty_block == NULL){ printf("ERROR[%s] fail\n",__FUNCTION__); - return FAIL; + return FAILURE; } + + //In order to understand what is the SYSTEM WIDE index number of the next available page (this is actually the physical page number) + //we need to count the number of pages from the beginning of the disk, up until the location of the empty block we received from the "GET_EMPTY_BLOCK" + //method above: + // + //We count the number of pages in all flash chips before us + //We add to it the number of pages in all blocks before our current block (which was returned by the GET_EMPTY_BLOCK method) + //and then we add to it the amount of blocks which are already used in our current block *ppn = curr_empty_block->phy_flash_nb*BLOCK_NB*PAGE_NB \ + curr_empty_block->phy_block_nb*PAGE_NB \ + curr_empty_block->curr_phy_page_nb; curr_empty_block->curr_phy_page_nb += 1; - return SUCCESS; + return SUCCESSFUL; } int UPDATE_OLD_PAGE_MAPPING(uint32_t lpn) @@ -86,14 +94,14 @@ int UPDATE_OLD_PAGE_MAPPING(uint32_t lpn) #ifdef FTL_DEBUG printf("[%s] New page \n",__FUNCTION__); #endif - return SUCCESS; + return SUCCESSFUL; } else{ UPDATE_INVERSE_BLOCK_VALIDITY(CALC_FLASH(old_ppn), CALC_BLOCK(old_ppn), CALC_PAGE(old_ppn), INVALID); UPDATE_INVERSE_PAGE_MAPPING(old_ppn, -1); } - return SUCCESS; + return SUCCESSFUL; } int UPDATE_NEW_PAGE_MAPPING(uint32_t lpn, uint32_t ppn) @@ -106,7 +114,7 @@ int UPDATE_NEW_PAGE_MAPPING(uint32_t lpn, uint32_t ppn) UPDATE_INVERSE_BLOCK_MAPPING(CALC_FLASH(ppn), CALC_BLOCK(ppn), DATA_BLOCK); UPDATE_INVERSE_PAGE_MAPPING(ppn, lpn); - return SUCCESS; + return SUCCESSFUL; } int UPDATE_NEW_PAGE_MAPPING_NO_LOGICAL(uint32_t ppn) @@ -115,7 +123,7 @@ int UPDATE_NEW_PAGE_MAPPING_NO_LOGICAL(uint32_t ppn) UPDATE_INVERSE_BLOCK_VALIDITY(CALC_FLASH(ppn), CALC_BLOCK(ppn), CALC_PAGE(ppn), VALID); UPDATE_INVERSE_BLOCK_MAPPING(CALC_FLASH(ppn), CALC_BLOCK(ppn), DATA_BLOCK); - return SUCCESS; + return SUCCESSFUL; } unsigned int CALC_FLASH(uint32_t ppn) diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.c b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.c old mode 100644 new mode 100755 index 75b850d0e..1be18ca85 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.c +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.c @@ -1,13 +1,30 @@ #include "ftl_obj_strategy.h" -stored_object *objects_table; -page_node *global_page_table; +#include "osd.h" +#include "osd-util/osd-util.h" +#include "osd-util/osd-defs.h" + +#ifndef COMPLIANCE_TESTS +#include "hw.h" +#endif + +uint8_t *osd_sense; +static const uint32_t cdb_cont_len = 0; +struct osd_device osd; + +stored_object *objects_table = NULL; +object_map *objects_mapping = NULL; +partition_map *partitions_mapping = NULL; +page_node *global_page_table = NULL; object_id_t current_id; + void INIT_OBJ_STRATEGY(void) { current_id = 1; objects_table = NULL; + objects_mapping = NULL; + partitions_mapping = NULL; global_page_table = NULL; } @@ -20,6 +37,24 @@ void free_obj_table(void) } } +void free_obj_mapping(void) +{ + object_map *curr,*next; + for (curr = objects_mapping; curr; curr=next) { + next=curr->hh.next; + free(curr); + } +} + +void free_part_mapping(void) +{ + partition_map *curr,*next; + for (curr = partitions_mapping; curr; curr=next) { + next=curr->hh.next; + free(curr); + } +} + void free_page_table(void) { page_node *curr,*next; @@ -32,6 +67,8 @@ void free_page_table(void) void TERM_OBJ_STRATEGY(void) { free_obj_table(); + free_obj_mapping(); + free_part_mapping(); free_page_table(); } @@ -41,21 +78,21 @@ int _FTL_OBJ_READ(object_id_t object_id, unsigned int offset, unsigned int lengt page_node *current_page; int io_page_nb; int curr_io_page_nb; - unsigned int ret = FAIL; + unsigned int ret = FAILURE; object = lookup_object(object_id); // file not found if (object == NULL) - return FAIL; + return FAILURE; // object not big enough if (object->size < (offset + length)) - return FAIL; + return FAILURE; 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; + LOG_VSSIMDBG("Error[%s] %u lookup page by offset failed \n", __FUNCTION__, current_page->page_id); + return FAILURE; } // just calculate the overhead of allocating the request. io_page_nb will be the total number of pages we're gonna read @@ -67,15 +104,15 @@ int _FTL_OBJ_READ(object_id_t object_id, unsigned int offset, unsigned int lengt 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) + if (ret == SUCCESSFUL) { FTL_STATISTICS_GATHERING(current_page->page_id, PHYSICAL_READ); } #ifdef FTL_DEBUG - if (ret == FAIL) + if (ret == FAILURE) { - printf("Error[%s] %u page read fail \n", __FUNCTION__, current_page->page_id); + LOG_VSSIMDBG("Error[%s] %u page read fail \n", __FUNCTION__, current_page->page_id); } #endif @@ -92,7 +129,7 @@ int _FTL_OBJ_READ(object_id_t object_id, unsigned int offset, unsigned int lengt #endif #ifdef FTL_DEBUG - printf("[%s] Complete\n",__FUNCTION__); + LOG_VSSIMDBG("[%s] Complete\n",__FUNCTION__); #endif return ret; @@ -105,13 +142,16 @@ int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int leng uint32_t page_id; int io_page_nb; int curr_io_page_nb; - unsigned int ret = FAIL; + unsigned int ret = FAILURE; object = lookup_object(object_id); // file not found if (object == NULL) - return FAIL; + { + LOG_VSSIMDBG("[%s] failed lookup\n", __FUNCTION__); + return FAILURE; + } // 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); @@ -119,14 +159,14 @@ int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int leng // 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) + if (GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &page_id) == FAILURE) { // not enough memory presumably - printf("ERROR[FTL_WRITE] Get new page fail \n"); - return FAIL; + LOG_VSSIMDBG("ERROR[FTL_WRITE] Get new page fail \n"); + return FAILURE; } if(!add_page(object, page_id)) - return FAIL; + return FAILURE; // mark new page as valid and used UPDATE_NEW_PAGE_MAPPING_NO_LOGICAL(page_id); @@ -141,15 +181,15 @@ int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int leng 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) + if (GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &page_id) == FAILURE) { - printf("ERROR[FTL_WRITE] Get new page fail \n"); - return FAIL; + LOG_VSSIMDBG("ERROR[FTL_WRITE] Get new page fail \n"); + return FAILURE; } 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; + LOG_VSSIMDBG("ERROR[FTL_WRITE] Object %lu already contains page %d\n",temp_page->object_id,page_id); + return FAILURE; } // mark new page as valid and used @@ -159,7 +199,7 @@ int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int leng { current_page = add_page(object, page_id); if(!current_page) - return FAIL; + return FAILURE; } else // writing over parts of the object { @@ -174,21 +214,21 @@ int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int leng #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); + GC_CHECK(CALC_FLASH(current_page->page_id), CALC_BLOCK(current_page->page_id), false, true); #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) + if (ret == SUCCESSFUL) { FTL_STATISTICS_GATHERING(page_id , PHYSICAL_WRITE); } #ifdef FTL_DEBUG - if (ret == FAIL) + if (ret == FAILURE) { - printf("Error[FTL_WRITE] %d page write fail \n", page_id); + LOG_VSSIMDBG("Error[FTL_WRITE] %d page write fail \n", page_id); } #endif @@ -211,7 +251,7 @@ int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int leng #endif #ifdef FTL_DEBUG - printf("[%s] Complete\n",__FUNCTION__); + LOG_VSSIMDBG("[%s] Complete\n",__FUNCTION__); #endif return ret; @@ -240,38 +280,44 @@ int _FTL_OBJ_COPYBACK(int32_t source, int32_t destination) #ifdef FTL_DEBUG else { - printf("Warning[%s] %u copyback page not mapped to an object \n", __FUNCTION__, source); + LOG_VSSIMDBG("Warning[%s] %u copyback page not mapped to an object \n", __FUNCTION__, source); } #endif - return SUCCESS; + return SUCCESSFUL; } -int _FTL_OBJ_CREATE(size_t size) +bool _FTL_OBJ_CREATE(object_id_t obj_id, size_t size) { stored_object *new_object; - new_object = create_object(size); + new_object = create_object(obj_id, size); if (new_object == NULL) { - return FAIL; + return false; } - // need to return the new id so the os will know how to talk to us about it - return new_object->id; + return true; } int _FTL_OBJ_DELETE(object_id_t object_id) { stored_object *object; + object_map *obj_map; object = lookup_object(object_id); // object not found if (object == NULL) - return FAIL; + return FAILURE; - return remove_object(object); + obj_map = lookup_object_mapping(object_id); + + // object_map not found + if (obj_map == NULL) + return FAILURE; + + return remove_object(object, obj_map); } stored_object *lookup_object(object_id_t object_id) @@ -284,13 +330,42 @@ stored_object *lookup_object(object_id_t object_id) return object; } -stored_object *create_object(size_t size) +object_map *lookup_object_mapping(object_id_t object_id) { + object_map *obj_map; + + // try to find it in our hashtable. NULL will be returned if key not found + HASH_FIND_INT(objects_mapping, &object_id, obj_map); + + return obj_map; +} + +stored_object *create_object(object_id_t obj_id, size_t size) +{ + stored_object *obj = malloc(sizeof(stored_object)); uint32_t page_id; + object_map *obj_map; + + HASH_FIND_INT(objects_mapping, &obj_id, obj_map); + //if the requested id was not found, let's add it + if (obj_map == NULL) + { + object_map *new_obj_id = (object_map*)malloc(sizeof(object_map)); + new_obj_id->id = obj_id; + new_obj_id->exists = true; + HASH_ADD_INT(objects_mapping, id, new_obj_id); + } + else + { + LOG_VSSIMDBG("[%s] Object %lu already exists, cannot create it !\n", __FUNCTION__, obj_id); + return NULL; + } + + // initialize to stored_object struct with size and initial pages - obj->id = current_id++; + obj->id = obj_id; obj->size = 0; obj->pages = NULL; @@ -299,10 +374,10 @@ stored_object *create_object(size_t size) while(size > obj->size) { - if (GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &page_id) == FAIL) + if (GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &page_id) == FAILURE) { // cleanup just in case we managed to do anything up until now - remove_object(obj); + remove_object(obj, obj_map); return NULL; } @@ -316,7 +391,7 @@ stored_object *create_object(size_t size) return obj; } -int remove_object(stored_object *object) +int remove_object(stored_object *object, object_map *obj_map) { page_node *current_page; page_node *invalidated_page; @@ -326,6 +401,9 @@ int remove_object(stored_object *object) if (object->hh.tbl != NULL) HASH_DEL(objects_table, object); + if (obj_map->hh.tbl != NULL) + HASH_DEL(objects_mapping, obj_map); + current_page = object->pages; while (current_page != NULL) { @@ -334,7 +412,7 @@ int remove_object(stored_object *object) #ifdef GC_ON // should we really perform GC for every page? we know we are invalidating a lot of them now... - GC_CHECK(CALC_FLASH(current_page->page_id), CALC_BLOCK(current_page->page_id), true); + GC_CHECK(CALC_FLASH(current_page->page_id), CALC_BLOCK(current_page->page_id), true, true); #endif // get next page and free the current one @@ -350,7 +428,7 @@ int remove_object(stored_object *object) // free the object's memory free(object); - return SUCCESS; + return SUCCESSFUL; } page_node *allocate_new_page(object_id_t object_id, uint32_t page_id) @@ -369,11 +447,11 @@ page_node *add_page(stored_object *object, uint32_t page_id) HASH_FIND_INT(global_page_table,&page_id,page); if(page) { - printf("ERROR[add_page] Object %lu already contains page %d\n",page->object_id,page_id); + LOG_VSSIMDBG("ERROR[add_page] Object %lu already contains page %d\n",page->object_id,page_id); return NULL; } - object->size += PAGE_SIZE; + object->size += eVSSIM_PAGE_SIZE; if(object->pages == NULL) { page = allocate_new_page(object->id,page_id); @@ -385,7 +463,7 @@ page_node *add_page(stored_object *object, uint32_t page_id) ; if(page) { - printf("ERROR[add_page] Object %lu already contains page %d\n",page->object_id,page_id); + LOG_VSSIMDBG("ERROR[add_page] Object %lu already contains page %d\n",page->object_id,page_id); return NULL; } @@ -395,6 +473,194 @@ page_node *add_page(stored_object *object, uint32_t page_id) return curr->next; } + void _FTL_OBJ_WRITECREATE(object_location obj_loc, size_t size) +{ + + //If that's the first prp, we need to create the object + if (obj_loc.create_object) + { + LOG_VSSIMDBG("[%s] about to create an object in the SIMULATOR -> obj id: %lu size: %lu\n", __FUNCTION__, obj_loc.object_id, size); + bool created = _FTL_OBJ_CREATE(obj_loc.object_id, size); + LOG_VSSIMDBG("[%s] created the SIMULATOR object !\n", __FUNCTION__); + + if (!created) + { + LOG_VSSIMDBG("[%s] could not create the SIMULATOR object. Aborting !\n", __FUNCTION__); + return; + } + } + + LOG_VSSIMDBG("[%s] about to write an object to the SIMULATOR -> obj id: %lu size: %lu\n", __FUNCTION__, obj_loc.object_id, size); + _FTL_OBJ_WRITE(obj_loc.object_id, 0, size); + //LOG_VSSIMDBG("[%s] object written to the SIMULATOR with res:%d\n", __FUNCTION__, res); + + return; +} + + bool osd_init(void) { + const char *rm_command = "rm -rf "; + char *rm_tmp_osd_command = malloc(strlen(OSD_PATH)+strlen(rm_command)+1); + + if (rm_tmp_osd_command != NULL) + { + rm_tmp_osd_command[0] = '\0'; + strcat(rm_tmp_osd_command, rm_command); + strcat(rm_tmp_osd_command, OSD_PATH); + } + else + { + LOG_VSSIMDBG("malloc failed !\n"); + return false; + } + + if (system(rm_tmp_osd_command)) + return false; + if (osd_open(OSD_PATH, &osd)) + return false; + LOG_VSSIMDBG("[%s] osd_init() finished successfully !\n", __FUNCTION__); + return true; + + } + + bool create_partition(partition_id_t part_id) + { + + const char *root = "/tmp/osd/"; + if (osd_open(root, &osd)) + return false; + osd_sense = (uint8_t*)Calloc(1, 1024); + if (osd_create_partition(&osd, part_id, cdb_cont_len, osd_sense)) + return false; + LOG_VSSIMDBG("[%s] created partition: %lu finished successfully !\n", __FUNCTION__, part_id); + return true; + } + +void OSD_WRITE_OBJ(object_location obj_loc, unsigned int length, uint8_t *buf) +{ + int ret; + partition_id_t part_id = USEROBJECT_PID_LB + obj_loc.partition_id; + object_id_t obj_id = USEROBJECT_OID_LB + obj_loc.object_id; + + if (obj_loc.create_object) + { + partition_map *part_map; + + HASH_FIND_INT(partitions_mapping, &part_id, part_map); + //if the requested id was not found, let's add it + if (part_map == NULL) + { + LOG_VSSIMDBG("[%s] osd partition %lu does not exist - trying to create it!\n", __FUNCTION__, part_id); + bool created = create_partition(part_id); + if (created) + { + partition_map *new_partition_id = (partition_map*)malloc(sizeof(partition_map)); + new_partition_id->id = part_id; + new_partition_id->exists = true; + HASH_ADD_INT(partitions_mapping, id, new_partition_id); + LOG_VSSIMDBG("[%s] osd partition %lu created successfully!\n", __FUNCTION__, part_id); + + } + else + { + LOG_VSSIMDBG("[%s] Could not create an osd partition !\n", __FUNCTION__); + return; + } + + } + else + { + LOG_VSSIMDBG("partition %lu already exists, no need to create it !\n", part_id); + } + + LOG_VSSIMDBG("[%s] creating an writing object to OSD with partition id: %lu and object id: %lu of size: %d\n", __FUNCTION__, part_id, obj_id, length); + ret = osd_create_and_write(&osd, part_id, obj_id, length, 0, buf, cdb_cont_len, 0, osd_sense, DDT_CONTIG); + if (ret) { + LOG_VSSIMDBG("[%s] FAILED ! ret for osd_create_and_write() is: %d\n", __FUNCTION__, ret); + return; + } + LOG_VSSIMDBG("[%s] object was created and written to osd !\n", __FUNCTION__); + } + + else{ + LOG_VSSIMDBG("[%s] updating OSD object id: %lu of size: %d\n", __FUNCTION__, obj_id, length); + ret = osd_append(&osd,part_id, obj_id, length, buf, cdb_cont_len, osd_sense, DDT_CONTIG); + if (ret) { + LOG_VSSIMDBG("[%s] FAIL! ret for osd_append() is: %d\n", __FUNCTION__, ret); + + return; + } + LOG_VSSIMDBG("[%s] OSD object was updated successfully\n", __FUNCTION__); + } +} + +void printMemoryDump(uint8_t *buffer, unsigned int bufferLength) +{ + unsigned int* start_p = (unsigned int*)buffer; + unsigned int* end_p = (unsigned int*)buffer + bufferLength / sizeof(unsigned int); + LOG_VSSIMDBG("code dump length: %ld\n", end_p - start_p); + int i =0,iall = 0; + char msgBuf[512]; + char* msg = (char*)msgBuf; + int gotSomething = 0; + LOG_VSSIMDBG("---------------------------------------\nDUMP MEMORY START\n0x%016lX - 0x%016lX\n---------------------------------------\n",(uint64_t)start_p,(uint64_t)end_p); + + while (start_p < end_p){ + char* asCharArray = (char*)start_p; + if (*start_p != 0){ + gotSomething = 1; + } + + if (i == 0){ + msg += sprintf(msg, "#%d: 0x%016lX | ", iall, (uint64_t)start_p); + } + msg += sprintf(msg, "0x%X %c%c%c%c | ", *start_p, asCharArray[0], asCharArray[1], asCharArray[2], asCharArray[3]); + if (i == 3) { + if (gotSomething){ + LOG_VSSIMDBG("%s\n",msgBuf); + } + i = 0; + gotSomething = 0; + msg = (char*)msgBuf; + }else{ + msg += sprintf(msg, " "); + i++; + } + start_p++; + iall++; + + } + LOG_VSSIMDBG("---------------------------------------\nDUMP MEMORY END\n---------------------------------------\n"); +} + +void OSD_READ_OBJ(object_location obj_loc, unsigned int length, uint64_t addr, uint64_t offset) +{ + object_id_t obj_id = USEROBJECT_OID_LB + obj_loc.object_id; + partition_id_t part_id = USEROBJECT_PID_LB + obj_loc.partition_id; + + + LOG_VSSIMDBG("[%s] READING %d bytes from OSD OBJECT: %lu %lu\n", __FUNCTION__, length, part_id, obj_id); + uint64_t len; + + uint8_t *rdbuf = malloc(length); + + //we should also get the offset here, for cases where there's more than one prp + + if(osd_read(&osd, part_id, obj_id, length, offset, NULL, rdbuf, &len, 0, osd_sense, DDT_CONTIG)) + LOG_VSSIMDBG("[%s] failed in osd_read()\n", __FUNCTION__); + else + { + LOG_VSSIMDBG("[%s] osd_read() was successful. %lu bytes were read !\n", __FUNCTION__, len); + +#ifndef COMPLIANCE_TESTS + cpu_physical_memory_rw(addr, rdbuf, len, 1); +#endif + + printMemoryDump(rdbuf, length); + + } + free(rdbuf); +} + page_node *page_by_offset(stored_object *object, unsigned int offset) { page_node *page; @@ -404,7 +670,7 @@ page_node *page_by_offset(stored_object *object, unsigned int offset) return NULL; // skim through pages until offset is less than a page's size - for(page = object->pages; page && offset >= PAGE_SIZE; offset -= PAGE_SIZE, page = page->next) + for(page = object->pages; page && offset >= eVSSIM_PAGE_SIZE; offset -= eVSSIM_PAGE_SIZE, page = page->next) ; // if page==NULL then page collection < size - report error? or assume it's valid? - this technically shouldn't happen after the if at the beginning. just return NULL if it does diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.h b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.h index 6c38bdc8f..ba644c762 100644 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.h +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_obj_strategy.h @@ -6,6 +6,7 @@ #include "uthash.h" typedef uint64_t object_id_t; +typedef uint64_t partition_id_t; /* A page node in the linked list of object-mapped pages */ typedef struct page_node { @@ -23,6 +24,31 @@ typedef struct stored_object { UT_hash_handle hh; /* makes this structure hashable */ } stored_object; +/* struct which will hold the ids of existing objects. We don't really need the value field (exists) but we add it for brevity */ +typedef struct object_map { + object_id_t id; + bool exists; + UT_hash_handle hh; /* makes this structure hashable */ +} object_map; + +/* struct which will hold the ids of existing partitions. We don't really need the value field (exists) but we add it for brevity */ +typedef struct partition_map { + partition_id_t id; + bool exists; + UT_hash_handle hh; /* makes this structure hashable */ +} partition_map; + +typedef struct { + uint64_t partition_id; + uint64_t object_id; + bool create_object; +} object_location; + +typedef struct { + uint8_t *metadata_mapping_addr; + unsigned int metadata_size; +} metadata_info; + void INIT_OBJ_STRATEGY(void); void TERM_OBJ_STRATEGY(void); @@ -30,13 +56,22 @@ void TERM_OBJ_STRATEGY(void); int _FTL_OBJ_READ(object_id_t object_id, unsigned int offset, unsigned int length); int _FTL_OBJ_WRITE(object_id_t object_id, unsigned int offset, unsigned int length); int _FTL_OBJ_COPYBACK(int32_t source, int32_t destination); -int _FTL_OBJ_CREATE(size_t size); +bool _FTL_OBJ_CREATE(object_id_t obj_id, size_t size); +void _FTL_OBJ_WRITECREATE(object_location obj_loc, size_t size); int _FTL_OBJ_DELETE(object_id_t object_id); + +/* Persistent OSD storge */ +bool osd_init(void); +bool create_partition(partition_id_t part_id); +void OSD_WRITE_OBJ(object_location obj_loc, unsigned int length, uint8_t *buf); +void OSD_READ_OBJ(object_location obj_loc, unsigned int length, uint64_t addr, uint64_t offset); + /* Helper functions */ stored_object *lookup_object(object_id_t object_id); -stored_object *create_object(size_t size); -int remove_object(stored_object *object); +object_map *lookup_object_mapping(object_id_t object_id); +stored_object *create_object(object_id_t obj_id, size_t size); +int remove_object(stored_object *object, object_map *obj_map); page_node *allocate_new_page(object_id_t object_id, uint32_t page_id); page_node *add_page(stored_object *object, uint32_t page_id); @@ -45,4 +80,9 @@ page_node *lookup_page(uint32_t page_id); page_node *next_page(stored_object *object,page_node *current); void free_obj_table(void); void free_page_table(void); +void free_obj_mapping(void); +void free_part_mapping(void); + +void printMemoryDump(uint8_t *buffer, unsigned int bufferLength); + #endif diff --git a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_sect_strategy.c b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_sect_strategy.c index 8544465fe..b9c76f5b9 100644 --- a/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_sect_strategy.c +++ b/eVSSIM/FTL_SOURCE/PAGE_MAP/ftl_sect_strategy.c @@ -1,20 +1,15 @@ #include "ftl_sect_strategy.h" -int _FTL_READ(uint64_t sector_nb, unsigned int offset, unsigned int length) -{ - return _FTL_READ_SECT(sector_nb, length); -} - int _FTL_READ_SECT(uint64_t sector_nb, unsigned int length) { #ifdef FTL_DEBUG - printf("[%s] Start: sector_nb %ld length %u\n",__FUNCTION__, sector_nb, length); + LOG_VSSIMDBG("[%s] Start: sector_nb %ld length %u\n",__FUNCTION__, sector_nb, length); #endif if (sector_nb + length > SECTOR_NB) { - printf("Error[FTL_READ] Exceed Sector number\n"); - return FAIL; + LOG_VSSIMDBG("Error[FTL_READ] Exceed Sector number\n"); + return FAILURE; } int32_t lpn; @@ -25,7 +20,7 @@ int _FTL_READ_SECT(uint64_t sector_nb, unsigned int length) unsigned long right_skip; unsigned int read_sects; - unsigned int ret = FAIL; + unsigned int ret = FAILURE; int read_page_nb = 0; int io_page_nb; @@ -57,22 +52,22 @@ int _FTL_READ_SECT(uint64_t sector_nb, unsigned int length) if(ppn == -1){ #ifdef FTL_DEBUG - printf("Error[%s] No Mapping info\n",__FUNCTION__); + LOG_VSSIMDBG("Error[%s] No Mapping info\n",__FUNCTION__); #endif - return FAIL; + return FAILURE; } ret = SSD_PAGE_READ(CALC_FLASH(ppn), CALC_BLOCK(ppn), CALC_PAGE(ppn), read_page_nb, READ, io_page_nb); //Send a physical read action being done to the statistics gathering - if (ret == SUCCESS) + if (ret == SUCCESSFUL) { FTL_STATISTICS_GATHERING(ppn , PHYSICAL_READ); } #ifdef FTL_DEBUG - if (ret == FAIL) + if (ret == FAILURE) { - printf("Error[%s] %u page read fail \n", __FUNCTION__, ppn); + LOG_VSSIMDBG("Error[%s] %u page read fail \n", __FUNCTION__, ppn); } #endif read_page_nb++; @@ -91,7 +86,7 @@ int _FTL_READ_SECT(uint64_t sector_nb, unsigned int length) #endif #ifdef FTL_DEBUG - printf("[%s] Complete\n",__FUNCTION__); + LOG_VSSIMDBG("[%s] Complete\n",__FUNCTION__); #endif return ret; @@ -105,15 +100,15 @@ int _FTL_WRITE(uint64_t sector_nb, unsigned int offset, unsigned int length) int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) { #ifdef FTL_DEBUG - printf("[%s] Start: sector_nb %d length %u\n",__FUNCTION__, sector_nb, length); + LOG_VSSIMDBG("[%s] Start: sector_nb %" PRIu64 "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; + LOG_VSSIMDBG("Error[FTL_WRITE] Exceed Sector number\n"); + return FAILURE; } else { @@ -129,7 +124,7 @@ int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) unsigned int right_skip; unsigned int write_sects; - unsigned int ret = FAIL; + unsigned int ret = FAILURE; int write_page_nb=0; while (remain > 0) @@ -146,20 +141,25 @@ int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) write_sects = SECTORS_PER_PAGE - left_skip - right_skip; ret = GET_NEW_PAGE(VICTIM_OVERALL, EMPTY_TABLE_ENTRY_NB, &new_ppn); - if (ret == FAIL) + if (ret == FAILURE) { - printf("ERROR[FTL_WRITE] Get new page fail \n"); - return FAIL; + LOG_VSSIMDBG("ERROR[FTL_WRITE] Get new page fail \n"); + return FAILURE; } ret = SSD_PAGE_WRITE(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn), CALC_PAGE(new_ppn), write_page_nb, WRITE, io_page_nb); + + //we caused a block write -> update the logical block_write counter + update the physical block write counter + wa_counters.logical_block_write_counter++; + wa_counters.physical_block_write_counter++; //Send a physical write action being done to the statistics gathering - if (ret == SUCCESS) + if (ret == SUCCESSFUL) { FTL_STATISTICS_GATHERING(new_ppn , PHYSICAL_WRITE); } write_page_nb++; + //Calculate the logical page number -> the current sector_number / amount_of_sectors_per_page lpn = lba / (int32_t)SECTORS_PER_PAGE; //Send a logical write action being done to the statistics gathering FTL_STATISTICS_GATHERING(lpn , LOGICAL_WRITE); @@ -169,9 +169,9 @@ int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) UPDATE_NEW_PAGE_MAPPING(lpn, new_ppn); #ifdef FTL_DEBUG - if (ret == FAIL) + if (ret == FAILURE) { - printf("Error[FTL_WRITE] %d page write fail \n", new_ppn); + LOG_VSSIMDBG("Error[FTL_WRITE] %d page write fail \n", new_ppn); } #endif lba += write_sects; @@ -182,7 +182,7 @@ int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) INCREASE_IO_REQUEST_SEQ_NB(); #ifdef GC_ON - GC_CHECK(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn), false); // is this a bug? gc will only happen on the last page's flash and block + GC_CHECK(CALC_FLASH(new_ppn), CALC_BLOCK(new_ppn), false, false); // is this a bug? gc will only happen on the last page's flash and block #endif #ifdef MONITOR_ON @@ -191,10 +191,13 @@ int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) WRITE_LOG(szTemp); sprintf(szTemp, "WB CORRECT %d", write_page_nb); WRITE_LOG(szTemp); + //also update the write amplifications status here + sprintf(szTemp, "WB AMP %f", (float)wa_counters.physical_block_write_counter / (float)wa_counters.logical_block_write_counter); + WRITE_LOG(szTemp); #endif #ifdef FTL_DEBUG - printf("[%s] Complete\n",__FUNCTION__); + LOG_VSSIMDBG("[%s] Complete\n",__FUNCTION__); #endif return ret; } @@ -203,7 +206,7 @@ int _FTL_WRITE_SECT(uint64_t sector_nb, unsigned int length) int _FTL_COPYBACK(int32_t source, int32_t destination) { int32_t lpn; //The logical page address, the page that being moved. - unsigned int ret = FAIL; + unsigned int ret = FAILURE; //Handle copyback delays ret = SSD_PAGE_COPYBACK(source, destination, COPYBACK); @@ -214,13 +217,13 @@ int _FTL_COPYBACK(int32_t source, int32_t destination) lpn = GET_INVERSE_MAPPING_INFO(source); UPDATE_NEW_PAGE_MAPPING(lpn, destination);*/ - if (ret == FAIL) + if (ret == FAILURE) { #ifdef FTL_DEBUG - printf("Error[%s] %u page copyback fail \n", __FUNCTION__, source); + LOG_VSSIMDBG("Error[%s] %u page copyback fail \n", __FUNCTION__, source); #endif - return FAIL; + return FAILURE; } //Handle page map @@ -238,11 +241,11 @@ int _FTL_COPYBACK(int32_t source, int32_t destination) int _FTL_CREATE(size_t size) { // no "creation" in address-based storage - return SUCCESS; + return SUCCESSFUL; } int _FTL_DELETE(uint64_t id) { // no "deletion" in address-based storage - return SUCCESS; + return SUCCESSFUL; } diff --git a/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.c b/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.c index 6afcc75f0..b5ca59df5 100755 --- a/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.c +++ b/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.c @@ -194,7 +194,7 @@ double GET_IO_BANDWIDTH(double delay) double bw; if(delay != 0) - bw = ((double)PAGE_SIZE*1000000)/(delay*1024*1024); + bw = ((double)eVSSIM_PAGE_SIZE*MEGABYTE_IN_BYTES)/(delay*SECOND_IN_USEC); else bw = 0; diff --git a/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.h b/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.h index 5b4345ca2..8322fffed 100755 --- a/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.h +++ b/eVSSIM/FTL_SOURCE/PERF_MODULE/ftl_perf_manager.h @@ -6,6 +6,8 @@ #ifndef _PERF_MANAGER_H_ #define _PERF_MANAGER_H_ +#define MEGABYTE_IN_BYTES 1024*1024 +#define SECOND_IN_USEC 1000000 /* IO Latency */ typedef struct io_request { diff --git a/eVSSIM/Kernel/drivers/block/nvme-core.c.diff b/eVSSIM/Kernel/drivers/block/nvme-core.c.diff new file mode 100644 index 000000000..2904afbfb --- /dev/null +++ b/eVSSIM/Kernel/drivers/block/nvme-core.c.diff @@ -0,0 +1,109 @@ +diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c +index 02351e2..060456e 100644 +--- a/drivers/block/nvme-core.c ++++ b/drivers/block/nvme-core.c +@@ -62,6 +62,11 @@ static unsigned char retry_time = 30; + module_param(retry_time, byte, 0644); + MODULE_PARM_DESC(retry_time, "time in seconds to retry failed I/O"); + ++static int strategy = 0; // 0-> sector 1-> object ++module_param(strategy, int, 0644); ++MODULE_PARM_DESC(strategy, "nvme strategy to be used -> 0 for sector or 1 for object"); ++ ++ + static int nvme_major; + module_param(nvme_major, int, 0); + +@@ -1575,6 +1580,11 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) + if (copy_from_user(&io, uio, sizeof(io))) + return -EFAULT; + length = (io.nblocks + 1) << ns->lba_shift; ++ ++ ++ printk(KERN_NOTICE "metadata address is:%llu\n", io.metadata); ++ printk(KERN_NOTICE "io.nblocks is:%d ns->ms is:%d\n", io.nblocks, ns->ms); ++ + meta_len = (io.nblocks + 1) * ns->ms; + + if (meta_len && ((io.metadata & 3) || !io.metadata)) +@@ -1605,7 +1615,10 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) + c.rw.apptag = cpu_to_le16(io.apptag); + c.rw.appmask = cpu_to_le16(io.appmask); + ++ printk(KERN_NOTICE "meta_len is: %d\n", meta_len); ++ + if (meta_len) { ++ //map the userspace memory pages which belong to the datameta data to meta_iod + meta_iod = nvme_map_user_pages(dev, io.opcode & 1, io.metadata, + meta_len); + if (IS_ERR(meta_iod)) { +@@ -1614,16 +1627,18 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) + goto unmap; + } + ++ //allocate dma memory and return the virtual address of the cpu region (meta_mem) and the corresponding ++ //device dma address handle (meta_dma_addr) + meta_mem = dma_alloc_coherent(&dev->pci_dev->dev, meta_len, + &meta_dma_addr, GFP_KERNEL); + if (!meta_mem) { + status = -ENOMEM; + goto unmap; + } +- +- if (io.opcode & 1) { ++ if ( ( strategy == 1 && (io.opcode & 1 || io.opcode & 2) ) || ( strategy == 0 && io.opcode & 1 ) ) { + int meta_offset = 0; +- ++ //for each metadata sg page inside meta_iod, map its address to the meta pointer and ++ //then copy it to the cpu dma memory region at an increasing offset + for (i = 0; i < meta_iod->nents; i++) { + meta = kmap_atomic(sg_page(&meta_iod->sg[i])) + + meta_iod->sg[i].offset; +@@ -1634,19 +1649,26 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) + } + } + ++ //printk(KERN_NOTICE "meta_dma_addr: %pad\n", &meta_dma_addr); ++ //set the metadata dma address's handle so it can be sent to the device + c.rw.metadata = cpu_to_le64(meta_dma_addr); ++ printk(KERN_NOTICE "meta_dma_addr handle is: %llX\n", c.rw.metadata); + } + + length = nvme_setup_prps(dev, iod, length, GFP_KERNEL); + c.rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg)); + c.rw.prp2 = cpu_to_le64(iod->first_dma); ++ printk(KERN_NOTICE "c.rw.prp1: %llX\n" ,c.rw.prp1); ++ printk(KERN_NOTICE "c.rw.prp2: %llX\n", c.rw.prp2); + + if (length != (io.nblocks + 1) << ns->lba_shift) + status = -ENOMEM; + else + status = nvme_submit_io_cmd(dev, &c, NULL); + +- if (meta_len) { ++ //if strategy is sector strategy and we're reading -> then also read the metadata buffer, if it exists ++ //don't do this for object strategy, as we're writing to the metadata buffer, and not reading from it ++ if (strategy == 0 && meta_len) { + if (status == NVME_SC_SUCCESS && !(io.opcode & 1)) { + int meta_offset = 0; + +@@ -1926,8 +1948,11 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid, + ns->ns_id = nsid; + ns->disk = disk; + lbaf = id->flbas & 0xf; ++ printk(KERN_NOTICE "id->flbas is:%d lbaf is:%d\n", id->flbas,lbaf); + ns->lba_shift = id->lbaf[lbaf].ds; + ns->ms = le16_to_cpu(id->lbaf[lbaf].ms); ++ //ns->ms = 1; ++ printk(KERN_NOTICE "ns->ms is:%d\n", ns->ms); + blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift); + if (dev->max_hw_sectors) + blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors); +@@ -2949,6 +2974,7 @@ static int __init nvme_init(void) + result = pci_register_driver(&nvme_driver); + if (result) + goto unregister_hotcpu; ++ printk(KERN_NOTICE "strategy is: %d\n", strategy); + return 0; + + unregister_hotcpu: diff --git a/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui b/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui index b9ecea102..8cd705469 100755 --- a/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui +++ b/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui @@ -733,7 +733,7 @@ long int GC_NB; int GCStarted; long int ReadSectorCount; - long int WriteAmpCount; + float WriteAmpCount; long int WrittenCorrectCount; long int WriteSectorCount; int TrimEffect; diff --git a/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui.h b/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui.h index de498d7b9..afc7abc3b 100755 --- a/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui.h +++ b/eVSSIM/MONITOR/SSD_MONITOR_PM/form1.ui.h @@ -164,18 +164,16 @@ void Form1::onReceive() /* WB인 소켓을 받았을 경우 */ else if(szCmdList[0] == "WB") { - long long int wb = 0; - sscanf(szCmdList[2], "%lld", &wb); + sscanf(szCmdList[2], "%f", &WriteAmpCount); if(szCmdList[1] == "CORRECT") { - WrittenCorrectCount += wb; + WrittenCorrectCount += WriteAmpCount; sprintf(szTemp, "%ld", WrittenCorrectCount); txtWrittenBlockCount->setText(szTemp); } else { - WriteAmpCount += wb; - sprintf(szTemp, "%ld", WriteAmpCount); + sprintf(szTemp, "%f", WriteAmpCount); txtWriteAmpCount->setText(szTemp); } } diff --git a/eVSSIM/NvmeCli/nvme.c.diff b/eVSSIM/NvmeCli/nvme.c.diff new file mode 100644 index 000000000..6fb7ea1a7 --- /dev/null +++ b/eVSSIM/NvmeCli/nvme.c.diff @@ -0,0 +1,52 @@ +diff --git a/nvme.c b/nvme.c +index c72e6eb..b093cd3 100644 +--- a/nvme.c ++++ b/nvme.c +@@ -2704,6 +2704,7 @@ static int submit_io(int opcode, char *command, const char *desc, + int err = 0; + int dfd, mfd; + int flags = opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT; ++ int metadata_flags = O_RDONLY; + int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; + + const char *start_block = "64-bit addr of first block to access"; +@@ -2788,7 +2789,9 @@ static int submit_io(int opcode, char *command, const char *desc, + {0} + }; + +- dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO; ++ dfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO; ++ mfd = STDIN_FILENO; ++ + argconfig_parse(argc, argv, desc, command_line_options, + &defaults, &cfg, sizeof(cfg)); + +@@ -2815,7 +2818,7 @@ static int submit_io(int opcode, char *command, const char *desc, + mfd = dfd; + } + if (strlen(cfg.metadata)){ +- mfd = open(cfg.metadata, flags, mode); ++ mfd = open(cfg.metadata, metadata_flags, mode); + if (mfd < 0) { + perror(cfg.data); + return EINVAL; +@@ -2834,7 +2837,7 @@ static int submit_io(int opcode, char *command, const char *desc, + fprintf(stderr, "failed to read data buffer from input file\n"); + return EINVAL; + } +- if ((opcode & 1) && cfg.metadata_size && ++ if (cfg.metadata_size && + read(mfd, (void *)mbuffer, cfg.metadata_size) < 0) { + fprintf(stderr, "failed to read meta-data buffer from input file\n"); + return EINVAL; +@@ -2875,10 +2878,6 @@ static int submit_io(int opcode, char *command, const char *desc, + if (!(opcode & 1) && write(dfd, (void *)buffer, cfg.data_size) < 0) { + fprintf(stderr, "failed to write buffer to output file\n"); + return EINVAL; +- } else if (!(opcode & 1) && cfg.metadata_size && +- write(mfd, (void *)mbuffer, cfg.metadata_size) < 0) { +- fprintf(stderr, "failed to write meta-data buffer to output file\n"); +- return EINVAL; + } else + fprintf(stderr, "%s: Success\n", command); + } diff --git a/eVSSIM/QEMU/Makefile b/eVSSIM/QEMU/Makefile index 38fee13c9..18e599e9b 100755 --- a/eVSSIM/QEMU/Makefile +++ b/eVSSIM/QEMU/Makefile @@ -19,7 +19,7 @@ config-host.mak: @exit 1 endif -QEMU_CFLAGS += -g +QEMU_CFLAGS += -g -Wno-deprecated-declarations # Don't try to regenerate Makefile or configure # We don't generate any of them diff --git a/eVSSIM/QEMU/Makefile.hw b/eVSSIM/QEMU/Makefile.hw index b9181ab12..b8566f8e8 100755 --- a/eVSSIM/QEMU/Makefile.hw +++ b/eVSSIM/QEMU/Makefile.hw @@ -9,7 +9,11 @@ include $(SRC_PATH)/rules.mak $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw) -QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu +# use the VSSIMDEBUG and NVMEDEBUG flags for additional debug logging output +# VSSIMDEBUG for ftl_obj and ftl_sect debug output +# NVMEDEBUG for nvme_storage debug output +#QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu -DVSSIMDEBUG -DNVMEDEBUG +QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu include $(SRC_PATH)/Makefile.objs diff --git a/eVSSIM/QEMU/Makefile.objs b/eVSSIM/QEMU/Makefile.objs index 449bc1fbd..b1d33dab7 100755 --- a/eVSSIM/QEMU/Makefile.objs +++ b/eVSSIM/QEMU/Makefile.objs @@ -304,7 +304,7 @@ hw-obj-$(CONFIG_VSSIM) += vssim_config_manager.o hw-obj-$(CONFIG_VSSIM) += ftl.o ftl_mapping_manager.o ftl_inverse_mapping_manager.o hw-obj-$(CONFIG_VSSIM) += ftl_obj_strategy.o ftl_sect_strategy.o hw-obj-$(CONFIG_VSSIM) += ftl_gc_manager.o ftl_perf_manager.o -hw-obj-$(CONFIG_VSSIM) += ssd.o ssd_log_manager.o ssd_io_manager.o +hw-obj-$(CONFIG_VSSIM) += ssd_log_manager.o ssd_io_manager.o ###################################################################### # libdis diff --git a/eVSSIM/QEMU/configure b/eVSSIM/QEMU/configure index efc0e6bb7..a5df41d05 100755 --- a/eVSSIM/QEMU/configure +++ b/eVSSIM/QEMU/configure @@ -233,8 +233,9 @@ QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS" -QEMU_INCLUDES="-I. -I\$(SRC_PATH)" -LDFLAGS="-g $LDFLAGS" +QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/../osc-osd -I\$(SRC_PATH)/../osc-osd/osd-target" +LDFLAGS="-g $LDFLAGS -L\$(SRC_PATH)/../osc-osd/osd-util -L\$(SRC_PATH)/../osc-osd/osd-target" +LIBS="-losdutil -losdtgt -lsqlite3 $LIBS" # make source path absolute source_path=`cd "$source_path"; pwd` diff --git a/eVSSIM/QEMU/hw/nvme.c b/eVSSIM/QEMU/hw/nvme.c index a35cdd72e..4ba465d24 100755 --- a/eVSSIM/QEMU/hw/nvme.c +++ b/eVSSIM/QEMU/hw/nvme.c @@ -544,7 +544,7 @@ static uint32_t nvme_mmio_readl(void *opaque, target_phys_addr_t addr) uint32_t rd_val = 0; NVMEState *nvme_dev = (NVMEState *) opaque; - LOG_DBG("%s(): addr = 0x%08x", __func__, (unsigned)addr); + //LOG_DBG("%s(): addr = 0x%08x", __func__, (unsigned)addr); /* Check if NVME controller Capabilities was written */ if (addr < NVME_SQ0TDBL) { diff --git a/eVSSIM/QEMU/hw/nvme.h b/eVSSIM/QEMU/hw/nvme.h index a766a88f5..0fbde8060 100755 --- a/eVSSIM/QEMU/hw/nvme.h +++ b/eVSSIM/QEMU/hw/nvme.h @@ -101,7 +101,8 @@ /* Definitions regarding Identify Controller Datastructure */ #define NO_LBA_FORMATS 15 /* 0 BASED */ -#define LBA_FORMAT_INUSE 0 /* 0 BASED */ +//modified the lba format to "3" so the ms field is not zero but 128 (i can write 128 bytes of metadata) -> this also affects the nvme block size. 3 -> 512bytes +#define LBA_FORMAT_INUSE 3 /* 0 BASED */ #define NVME_SPARE_THRESH 20 #define NVME_TEMPERATURE 0x143 diff --git a/eVSSIM/QEMU/hw/nvme_debug.h b/eVSSIM/QEMU/hw/nvme_debug.h index a1931fc1e..cd70ec6b0 100755 --- a/eVSSIM/QEMU/hw/nvme_debug.h +++ b/eVSSIM/QEMU/hw/nvme_debug.h @@ -3,12 +3,14 @@ #define CHOP_FILE(str) (strstr(str, "nvmeqemu") == 0 ? str : strstr(str, "nvmeqemu") + 9) +//#define DEBUG + #define LOG_NORM(fmt, ...) \ printf("%s: " fmt "\n", LEVEL, ## __VA_ARGS__) #define LOG_ERR(fmt, ...) \ printf("%s-ERR:%s:%d: " fmt "\n", LEVEL, CHOP_FILE(__FILE__), \ __LINE__, ## __VA_ARGS__) -#ifdef DEBUG +#ifdef NVMEDEBUG #define LOG_DBG(fmt, ...) \ printf("DBG|:%s:%d: " fmt "\n", CHOP_FILE(__FILE__), \ __LINE__, ## __VA_ARGS__) diff --git a/eVSSIM/QEMU/hw/nvme_storage.c b/eVSSIM/QEMU/hw/nvme_storage.c index 93d5b81f2..c62a489dc 100755 --- a/eVSSIM/QEMU/hw/nvme_storage.c +++ b/eVSSIM/QEMU/hw/nvme_storage.c @@ -25,17 +25,20 @@ #include "nvme.h" #include "nvme_debug.h" - #ifdef CONFIG_VSSIM -#include "ssd.h" -extern char* GET_FILE_NAME(void); +#include "vssim_config_manager.h" +#include "ftl_obj_strategy.h" +#include "ftl_sect_strategy.h" + +//extern char* GET_FILE_NAME(void); //TODO: review SECTOR_SIZE vs. page_size of the NVME -extern int SECTOR_SIZE; // SSD configuration. See CONFIG/vssim_config_manager +//extern int SECTOR_SIZE; // SSD configuration. See CONFIG/vssim_config_manager #endif /* CONFIG_VSSIM */ #include #include + #define MASK_AD 0x4 #define MASK_IDW 0x2 #define MASK_IDR 0x1 @@ -45,6 +48,50 @@ static uint8_t read_dsm_ranges(uint64_t range_prp1, uint64_t range_prp2, static void dsm_dealloc(DiskInfo *disk, uint64_t slba, uint64_t nlb); +static void parse_metadata(uint8_t *metadata_mapping_address, unsigned int metadata_size, object_location *obj_loc) +{ + + char MAGIC[] = "eVSSIM_MAGIC"; + int MAGIC_LENGTH = 12; + + char* asACharArray = (char*)metadata_mapping_address; + char* magicSuffixPtr = NULL; + + + LOG_DBG("metadata size is: %d\n", metadata_size); + LOG_DBG("metadata addr is: %p\n", asACharArray); + + if (!memcmp(MAGIC, asACharArray,MAGIC_LENGTH)) + { + asACharArray += MAGIC_LENGTH; + LOG_DBG("Found magic at %p\n", asACharArray); + magicSuffixPtr = strchr(asACharArray, '!'); + if (magicSuffixPtr) + { + LOG_DBG("Found suffix!\n"); + char* seperatorPtr = strchr(asACharArray, '_'); + + if (seperatorPtr != NULL) + { + LOG_DBG("Found seperator !\n"); + + *seperatorPtr = '\x00'; + *magicSuffixPtr = '\x00'; + + obj_loc->partition_id = atoi(asACharArray); + obj_loc->object_id = atoi(seperatorPtr+1); + + *seperatorPtr = '_'; + *magicSuffixPtr = '!'; + } + + LOG_DBG("partition id is: %lu object id is: %lu\n", obj_loc->partition_id, obj_loc->object_id); + } + + } + +} + void nvme_dma_mem_read(target_phys_addr_t addr, uint8_t *buf, int len) { cpu_physical_memory_rw(addr, buf, len, 0); @@ -56,43 +103,118 @@ void nvme_dma_mem_write(target_phys_addr_t addr, uint8_t *buf, int len) } #ifdef CONFIG_VSSIM +//nvme_dma_mem_read2() -> READ what's inside the prp (addr) and write it to the hw (buf + relevant offset according to how the prps were divided) --> in this case, the prp (addr) is the dma memory we read from ? static void nvme_dma_mem_read2(target_phys_addr_t addr, uint8_t *buf, int len, - uint8_t *mapping_addr) + uint8_t *mapping_addr, unsigned int partition_id, unsigned int object_id, bool should_create_obj) { - if((len % SECTOR_SIZE) != 0){ + if((len % eVSSIM_SECTOR_SIZE) != 0){ LOG_ERR("nvme_dma_mem_read2: len (=%d) %% %d == %d (should be 0)", - len, SECTOR_SIZE, (len % SECTOR_SIZE)); + len, eVSSIM_SECTOR_SIZE, (len % eVSSIM_SECTOR_SIZE)); } - if((buf - mapping_addr) % SECTOR_SIZE != 0){ + if((buf - mapping_addr) % eVSSIM_SECTOR_SIZE != 0){ LOG_ERR("nvme_dma_mem_read2: (buf - mapping_addr) (=%ld) %% %d == %ld " "(should be 0)", - buf - mapping_addr, SECTOR_SIZE, - (buf - mapping_addr) % SECTOR_SIZE); + buf - mapping_addr, eVSSIM_SECTOR_SIZE, + (buf - mapping_addr) % eVSSIM_SECTOR_SIZE); + } + + if (partition_id != 0 && object_id != 0) + { + + LOG_DBG("object strategy\n"); + object_location obj_loc = { + .object_id = object_id, + .partition_id = partition_id, + .create_object = should_create_obj + }; + + //We don't need to specify the parition_id + object id + //as they're determined automatically by the + //simulator methods. However, I'm leaving this here + //as infrastructure if we'd like to change this in the future + //and set the IDs ourselves + _FTL_OBJ_WRITECREATE(obj_loc, len); + + //write the object data to the persistent osd storage + // + //We DO use the obj_loc IDs here... they're NOT auto-determined + // + //In order to write the data to the OSD object, we need to go over the prp data at addr and write it to the + //object (quite the same as it's written to buf in the sector strategy below -> we might be able to just read buf, as it'll be easier to read than reading addr, which is a physical address) + + //Following the comment above, Trying to read from addr to buf and then writing buf + cpu_physical_memory_rw(addr, buf, len, 0); + OSD_WRITE_OBJ(obj_loc, len, buf); + } + else + { + LOG_DBG("sector strategy\n"); + //sector strategy -> continue normally + _FTL_WRITE_SECT( (buf - mapping_addr) / eVSSIM_SECTOR_SIZE, len / eVSSIM_SECTOR_SIZE); + //read from dma memory (prp) and write to qemu's volatile memory + cpu_physical_memory_rw(addr, buf, len, 0); } - SSD_WRITE(len / SECTOR_SIZE, (buf - mapping_addr) / SECTOR_SIZE); - cpu_physical_memory_rw(addr, buf, len, 0); + } +//nvme_dma_mem_write2() -> read from the hw (buf + relevant offset according to the current prp number we're reading ?) and WRITE to the prp (dma addr) static void nvme_dma_mem_write2(target_phys_addr_t addr, uint8_t *buf, int len, - uint8_t *mapping_addr) + uint8_t *mapping_addr, unsigned int partition_id, unsigned int object_id) { - if((len % SECTOR_SIZE) != 0){ + //the buf pointer is actually -> buf = mapping_addr + offset so: + uint64_t offset = buf - mapping_addr; + + if((len % eVSSIM_SECTOR_SIZE) != 0){ LOG_ERR("nvme_dma_mem_write2: len (=%d) %% %d == %d (should be 0)", - len, SECTOR_SIZE, (len % SECTOR_SIZE)); + len, eVSSIM_SECTOR_SIZE, (len % eVSSIM_SECTOR_SIZE)); } - if((buf - mapping_addr) % SECTOR_SIZE != 0){ - LOG_ERR("nvme_dma_mem_write2: (buf - mapping_addr) (=%ld) %% %d == %ld " + if((offset) % eVSSIM_SECTOR_SIZE != 0){ + LOG_ERR("nvme_dma_mem_write2: (offset) (=%ld) %% %d == %ld " "(should be 0)", - buf - mapping_addr, SECTOR_SIZE, - (buf - mapping_addr) % SECTOR_SIZE); + offset, eVSSIM_SECTOR_SIZE, + (offset) % eVSSIM_SECTOR_SIZE); + } + + if (partition_id != 0 && object_id != 0) + { + + LOG_DBG("object strategy\n"); + object_location obj_loc = { + .object_id = object_id, + .partition_id = partition_id, + }; + + //perform a simulator READ + // + //We have a problem here as we have no idea what object id was created in the simulator object write (auto incremented) -> so this should fail as it's not the same as the + //object id we're about to read from the osd later + int ret = _FTL_OBJ_READ(obj_loc.object_id, 0, len); + if (!ret) + { + LOG_DBG("FTL_OBJ_READ failed with ret: %d\n", ret); + } + else + { + LOG_DBG("Successfully read object from simulator\n"); + } + + //read from persistent OSD storage + OSD_READ_OBJ(obj_loc, len, addr, offset); + } + else + { + LOG_DBG("sector strategy\n"); + //sector strategy -> continue normally + _FTL_READ_SECT((buf - mapping_addr) / eVSSIM_SECTOR_SIZE, len / eVSSIM_SECTOR_SIZE); + //_FTL_READ_SECT(len / eVSSIM_SECTOR_SIZE, (buf - mapping_addr) / eVSSIM_SECTOR_SIZE); + //read from qemu's volatile memory and write to dma memory (prp) + cpu_physical_memory_rw(addr, buf, len, 1); } - SSD_READ(len / SECTOR_SIZE, (buf - mapping_addr) / SECTOR_SIZE); - cpu_physical_memory_rw(addr, buf, len, 1); } #endif /* CONFIG_VSSIM */ static uint8_t do_rw_prp(NVMEState *n, uint64_t mem_addr, uint64_t *data_size_p, - uint64_t *file_offset_p, uint8_t *mapping_addr, uint8_t rw) + uint64_t *file_offset_p, uint8_t *mapping_addr, uint8_t rw, object_location obj_loc) { uint64_t data_len; @@ -101,7 +223,13 @@ static uint8_t do_rw_prp(NVMEState *n, uint64_t mem_addr, uint64_t *data_size_p, } /* Data Len to be written per page basis */ + // + //the data_len is affected by the prp memory address - according to its alignment to page size + //this calculation of data_len appears to be simulating the mechanism in the kernel which sets up the data size for each prp prps -> it does that according to prp alignment to a page size + // + //if the calculated data_len is bigger than the provided data_size(which is a multplication of block size), then we'll use the provided data_size as the value of data_len (as there's no point in writing more data than provided) data_len = PAGE_SIZE - (mem_addr % PAGE_SIZE); + LOG_DBG("data_len: %lu mem_addr mod PAGE_SIZE: %lu data_size: %lu\n", data_len, mem_addr % PAGE_SIZE, *data_size_p); if (data_len > *data_size_p) { data_len = *data_size_p; } @@ -114,7 +242,7 @@ static uint8_t do_rw_prp(NVMEState *n, uint64_t mem_addr, uint64_t *data_size_p, case NVME_CMD_READ: LOG_DBG("Read cmd called"); #ifdef CONFIG_VSSIM - nvme_dma_mem_write2(mem_addr, (mapping_addr + *file_offset_p), data_len, mapping_addr); + nvme_dma_mem_write2(mem_addr, (mapping_addr + *file_offset_p), data_len, mapping_addr, obj_loc.partition_id, obj_loc.object_id); #else nvme_dma_mem_write(mem_addr, (mapping_addr + *file_offset_p), data_len); #endif @@ -122,7 +250,7 @@ static uint8_t do_rw_prp(NVMEState *n, uint64_t mem_addr, uint64_t *data_size_p, case NVME_CMD_WRITE: LOG_DBG("Write cmd called"); #ifdef CONFIG_VSSIM - nvme_dma_mem_read2(mem_addr, (mapping_addr + *file_offset_p), data_len, mapping_addr); + nvme_dma_mem_read2(mem_addr, (mapping_addr + *file_offset_p), data_len, mapping_addr, obj_loc.partition_id, obj_loc.object_id, obj_loc.create_object); #else nvme_dma_mem_read(mem_addr, (mapping_addr + *file_offset_p), data_len); #endif @@ -131,42 +259,8 @@ static uint8_t do_rw_prp(NVMEState *n, uint64_t mem_addr, uint64_t *data_size_p, LOG_ERR("Error- wrong opcode: %d", rw); return FAIL; } - /*{ // DEBUG CODE DUMP - unsigned int* start_p = (unsigned int*)(mapping_addr + *file_offset_p); - unsigned int* end_p = (unsigned int*)(mapping_addr + *file_offset_p) + data_len / sizeof(unsigned int); - int i =0,iall = 0; - char msgBuf[512]; - char* msg = (char*)msgBuf; - int gotSomething = 0; - printf("---------------------------------------\nDUMP MEMORY START\n0x%016lX - 0x%016lX\n---------------------------------------\n",(uint64_t)start_p,(uint64_t)end_p); - - while (start_p < end_p){ - char* asCharArray = (char*)start_p; - if (*start_p != 0){ - gotSomething = 1; - } - - if (i == 0){ - msg += sprintf(msg, "#%d: 0x%016lX | ", iall, (uint64_t)start_p); - } - msg += sprintf(msg, "0x%X %c%c%c%c | ", *start_p, asCharArray[0], asCharArray[1], asCharArray[2], asCharArray[3]); - if (i == 3) { - if (gotSomething){ - printf("%s\n",msgBuf); - } - i = 0; - gotSomething = 0; - msg = (char*)msgBuf; - }else{ - msg += sprintf(msg, " "); - i++; - } - start_p++; - iall++; - } - printf("---------------------------------------\nDUMP MEMORY END\n---------------------------------------\n"); - }//*/ + printMemoryDump(mapping_addr + *file_offset_p,data_len); *file_offset_p = *file_offset_p + data_len; *data_size_p = *data_size_p - data_len; @@ -174,7 +268,7 @@ static uint8_t do_rw_prp(NVMEState *n, uint64_t mem_addr, uint64_t *data_size_p, } static uint8_t do_rw_prp_list(NVMEState *n, NVMECmd *command, - uint64_t *data_size_p, uint64_t *file_offset_p, uint8_t *mapping_addr) + uint64_t *data_size_p, uint64_t *file_offset_p, uint8_t *mapping_addr, object_location obj_loc) { uint64_t prp_list[512], prp_entries; uint16_t i = 0; @@ -185,32 +279,20 @@ static uint8_t do_rw_prp_list(NVMEState *n, NVMECmd *command, /* Logic to find the number of PRP Entries */ prp_entries = (uint64_t) ((*data_size_p + PAGE_SIZE - 1) / PAGE_SIZE); -#ifdef CONFIG_VSSIM - nvme_dma_mem_read2(cmd->prp2, (uint8_t *)prp_list, - min(sizeof(prp_list), prp_entries * sizeof(uint64_t)), mapping_addr); -#else - nvme_dma_mem_read(cmd->prp2, (uint8_t *)prp_list, - min(sizeof(prp_list), prp_entries * sizeof(uint64_t))); -#endif + //no need for nvme_dma_mem_read2 here as it's only reading prp2 (dma memory) into prp_list -> it's not writing to the qemu simulated hw + nvme_dma_mem_read(cmd->prp2, (uint8_t *)prp_list, min(sizeof(prp_list), prp_entries * sizeof(uint64_t))); /* Read/Write on PRPList */ while (*data_size_p != 0) { if (i == 511 && *data_size_p > PAGE_SIZE) { /* Calculate the actual number of remaining entries */ - prp_entries = (uint64_t) ((*data_size_p + PAGE_SIZE - 1) / - PAGE_SIZE); -#ifdef CONFIG_VSSIM - nvme_dma_mem_read2(prp_list[511], (uint8_t *)prp_list, - min(sizeof(prp_list), prp_entries * sizeof(uint64_t)), mapping_addr); -#else - nvme_dma_mem_read(prp_list[511], (uint8_t *)prp_list, - min(sizeof(prp_list), prp_entries * sizeof(uint64_t))); -#endif + prp_entries = (uint64_t) ((*data_size_p + PAGE_SIZE - 1) / PAGE_SIZE); + //reading the last item in the prp_list to prp_list (not the qemu simulated hw, so no need for nvme_dma_mem_read2) + nvme_dma_mem_read(prp_list[511], (uint8_t *)prp_list, min(sizeof(prp_list), prp_entries * sizeof(uint64_t))); i = 0; } - res = do_rw_prp(n, prp_list[i], data_size_p, - file_offset_p, mapping_addr, cmd->opcode); + res = do_rw_prp(n, prp_list[i], data_size_p, file_offset_p, mapping_addr, cmd->opcode, obj_loc); LOG_DBG("Data Size remaining for read/write:%ld", *data_size_p); if (res == FAIL) { break; @@ -218,6 +300,7 @@ static uint8_t do_rw_prp_list(NVMEState *n, NVMECmd *command, i++; } return res; + } /********************************************************************* @@ -319,6 +402,8 @@ uint8_t nvme_io_command(NVMEState *n, NVMECmd *sqe, NVMECQE *cqe) DiskInfo *disk; uint8_t lba_idx; + + sf->sc = NVME_SC_SUCCESS; LOG_DBG("%s(): called", __func__); @@ -335,18 +420,69 @@ uint8_t nvme_io_command(NVMEState *n, NVMECmd *sqe, NVMECQE *cqe) lba_idx = disk->idtfy_ns.flbas & 0xf; if ((e->mptr == 0) && /* if NOT supplying separate meta buffer */ - (disk->idtfy_ns.lbafx[lba_idx].ms != 0) && /* if using metadata */ - ((disk->idtfy_ns.flbas & 0x10) == 0)) { /* if using separate buffer */ - + (disk->idtfy_ns.lbafx[lba_idx].ms != 0) /* if using metadata */ + //This AND calculation will always yield "0" as the format cannot be 16 but only 0 to 15 (is this a bug?) and will cause sector based access to fail + //&& ((disk->idtfy_ns.flbas & 0x10) == 0)) /* if using separate buffer */ { + && ((disk->idtfy_ns.flbas & 0xf) == 0)) { LOG_ERR("%s(): invalid meta-data for extended lba", __func__); sf->sc = NVME_SC_INVALID_FIELD; return FAIL; } + object_location obj_loc = { + .partition_id = 0, + .object_id = 0 + }; + + /* Spec states that non-zero meta data buffers shall be ignored, i.e. no + * error reported, when the DW4&5 (MPTR) field is not in use */ + if ((e->mptr != 0) && /* if supplying separate meta buffer */ + (disk->idtfy_ns.lbafx[lba_idx].ms != 0) && /* if using metadata */ + ((disk->idtfy_ns.flbas & 0x10) == 0)) { /* if using separate buffer */ + + /* Then go ahead and use the separate meta data buffer */ + unsigned int ms, meta_offset, meta_size; + uint8_t *meta_mapping_addr; + + ms = disk->idtfy_ns.lbafx[lba_idx].ms; + meta_offset = e->slba * ms; + + meta_size = (e->nlb + 1) * ms; //metadata size should be set according to the lba format and not according to the block size as it leads to sizes which are bigger than 128 and thus to memory corruption + //meta_size = ms; + meta_mapping_addr = disk->meta_mapping_addr + meta_offset; + + LOG_DBG("e->mptr (%lu) is: %p\n", e->mptr, (void*)e->mptr); + + if (STORAGE_STRATEGY == 1 && (e->opcode == NVME_CMD_READ || e->opcode == NVME_CMD_WRITE)) { + //When writing, we're using the metadata's contents, which contain the partition and object ids, so we know where to write to. + //In order to get the metadata's contents, we first read it from the prp, straight to qemu's emulated storage (in memory) and then parse it. + // + //When reading, we do the exact same, as we want to know what object to read from later on -> we don't want to read the metadata from the "physical" (emulated in memory) storage + LOG_DBG("object strategy - writing metadata\n"); + uint8_t* meta_buf = qemu_mallocz(meta_size); + LOG_DBG("meta_buf is: %p\n", meta_buf); + nvme_dma_mem_read(e->mptr, meta_buf, meta_size); + parse_metadata(meta_buf, meta_size, &obj_loc); + qemu_free(meta_buf); + } + else if(STORAGE_STRATEGY == 0) + { + if (e->opcode == NVME_CMD_READ) { + LOG_DBG("sector strategy - reading metadata\n"); + nvme_dma_mem_write(e->mptr, meta_mapping_addr, meta_size); + } else if (e->opcode == NVME_CMD_WRITE) { + LOG_DBG("sector strategy - writing metadata\n"); + nvme_dma_mem_read(e->mptr, meta_mapping_addr, meta_size); + } + } + + } + /* Read in the command */ nvme_blk_sz = NVME_BLOCK_SIZE(disk->idtfy_ns.lbafx[lba_idx].lbads); LOG_DBG("NVME Block size: %u", nvme_blk_sz); data_size = (e->nlb + 1) * nvme_blk_sz; + LOG_DBG("e->nlb is: %" PRIu32 " data_size (%lu)\n", e->nlb, data_size); if (disk->idtfy_ns.flbas & 0x10) { data_size += (disk->idtfy_ns.lbafx[lba_idx].ms * (e->nlb + 1)); @@ -370,49 +506,39 @@ uint8_t nvme_io_command(NVMEState *n, NVMECmd *sqe, NVMECQE *cqe) return FAIL; } + LOG_DBG("mapping_addr is: %p\n", mapping_addr); + /* Writing/Reading PRP1 */ LOG_DBG("Writing/Reading PRP1"); + //first prp will always require creating an object + obj_loc.create_object=true; res = do_rw_prp(n, e->prp1, &data_size, &file_offset, mapping_addr, - e->opcode); + e->opcode, obj_loc); if (res == FAIL) { return FAIL; } + + //every prp is of one page size. + //if the total data is more than 2 pages, we store the first page in prp1 and the rest of the data in a LIST of pages in prp2. + //in any case, the file offset and mapping address is advanced as we continue writing / reading if (data_size > 0) { + //need to pass another parameter to do_rw_prp, which specifies that we're updating (appending) the object here(we'll refer to it only in case of object strategy) + obj_loc.create_object=false; if (data_size <= PAGE_SIZE) { LOG_DBG("Writing/Reading PRP2"); res = do_rw_prp(n, e->prp2, &data_size, &file_offset, mapping_addr, - e->opcode); + e->opcode, obj_loc); } else { LOG_DBG("Writing/Reading do_rw_prp_list!"); res = do_rw_prp_list(n, sqe, &data_size, &file_offset, - mapping_addr); + mapping_addr, obj_loc); } if (res == FAIL) { return FAIL; } } - /* Spec states that non-zero meta data buffers shall be ignored, i.e. no - * error reported, when the DW4&5 (MPTR) field is not in use */ - if ((e->mptr != 0) && /* if supplying separate meta buffer */ - (disk->idtfy_ns.lbafx[lba_idx].ms != 0) && /* if using metadata */ - ((disk->idtfy_ns.flbas & 0x10) == 0)) { /* if using separate buffer */ - - /* Then go ahead and use the separate meta data buffer */ - unsigned int ms, meta_offset, meta_size; - uint8_t *meta_mapping_addr; - - ms = disk->idtfy_ns.lbafx[lba_idx].ms; - meta_offset = e->slba * ms; - meta_size = (e->nlb + 1) * ms; - meta_mapping_addr = disk->meta_mapping_addr + meta_offset; - - if (e->opcode == NVME_CMD_READ) { - nvme_dma_mem_write(e->mptr, meta_mapping_addr, meta_size); - } else if (e->opcode == NVME_CMD_WRITE) { - nvme_dma_mem_read(e->mptr, meta_mapping_addr, meta_size); - } - } + nvme_update_stats(n, disk, e->opcode, e->slba, e->nlb); return res; @@ -696,7 +822,14 @@ int nvme_create_storage_disks(NVMEState *n) int ret = SUCCESS; #ifdef CONFIG_VSSIM - SSD_INIT(); + FTL_INIT(); + if (!osd_init()) + { + LOG_DBG("Could not init osd !\n"); + } + #ifdef MONITOR_ON + INIT_LOG_MANAGER(); + #endif #endif for (i = 0; i < n->num_namespaces; i++) { diff --git a/eVSSIM/QEMU/vl.c b/eVSSIM/QEMU/vl.c index 36b8bd9cb..61138b710 100755 --- a/eVSSIM/QEMU/vl.c +++ b/eVSSIM/QEMU/vl.c @@ -124,7 +124,7 @@ int main(int argc, char **argv) #include "hw/xen.h" #include "hw/qdev.h" #include "hw/loader.h" -#include "hw/ssd.h" +#include "hw/ftl.h" #include "bt-host.h" #include "net.h" #include "net/slirp.h" @@ -3321,7 +3321,12 @@ int main(int argc, char **argv, char **envp) net_cleanup(); #ifdef CONFIG_VSSIM - SSD_TERM(); //TODO: this should be called from nvme_close_storage_disks() + FTL_TERM(); + +#ifdef MONITOR_ON + TERM_LOG_MANAGER(); +#endif + #endif return 0; diff --git a/eVSSIM/README b/eVSSIM/README index e78a21f7f..0895616c3 100755 --- a/eVSSIM/README +++ b/eVSSIM/README @@ -4,19 +4,25 @@ 4. QEMU distclean 5. Ubuntu installation (14.04.1-server-amd64) - -VSSIM talking NVMe +============================================================ 1. Build + + gcc version to build the code is gcc-4.4 + a. Build ssd_monitor - cd MONITOR/SSD_MONITOR_PM - qmake -o Makefile ssd_monitor_p.pro - make - - b. Build qemu - cd QEMU - ./configure --enable-io-thread --enable-linux-aio --target-list=x86_64-softmmu --enable-sdl --enable-vssim - make + cd MONITOR/SSD_MONITOR_PM + qmake -o Makefile ssd_monitor_p.pro + make + + b. Build osd-util + cd osc-osd + make target + + c. Build qemu + cd QEMU + ./configure --enable-io-thread --enable-linux-aio --target-list=x86_64-softmmu --enable-sdl --enable-vssim + make 2. Setup VSSIM runtime a. Setup data directory diff --git a/eVSSIM/SSD_MODULE/ssd.c b/eVSSIM/SSD_MODULE/ssd.c deleted file mode 100755 index d92a7946e..000000000 --- a/eVSSIM/SSD_MODULE/ssd.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "ssd.h" -#include "common.h" - -#ifdef GET_WORKLOAD -#include -#include -#endif - -void SSD_INIT(void) -{ - FTL_INIT(); -#ifdef MONITOR_ON - INIT_LOG_MANAGER(); -#endif -} - -void SSD_TERM(void) -{ - FTL_TERM(); - -#ifdef MONITOR_ON - TERM_LOG_MANAGER(); -#endif -} - -void SSD_WRITE(unsigned int length, uint32_t sector_nb) -{ - FTL_WRITE((uint64_t)sector_nb, 0, length); -} - -void SSD_READ(unsigned int length, uint32_t sector_nb) -{ - FTL_READ((uint64_t)sector_nb, 0, length); -} - diff --git a/eVSSIM/SSD_MODULE/ssd.h b/eVSSIM/SSD_MODULE/ssd.h deleted file mode 100755 index 3ed451919..000000000 --- a/eVSSIM/SSD_MODULE/ssd.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * QEMU SSD Emulator - * - * Copyright (c) 2009 Kim, Joo Hyun - * Copyright (c) 2009 Hanyang Univ. - * Copyright (c) 2009 Samsung Electronics. - * - */ - -#ifndef _SSD_H_ -#define _SSD_H_ - -#include - -void SSD_INIT(void); -void SSD_TERM(void); - -void SSD_WRITE(unsigned int length, uint32_t sector_nb); -void SSD_READ(unsigned int length, uint32_t sector_nb); - -#endif diff --git a/eVSSIM/SSD_MODULE/ssd_io_manager.c b/eVSSIM/SSD_MODULE/ssd_io_manager.c index dded13077..0cca94326 100755 --- a/eVSSIM/SSD_MODULE/ssd_io_manager.c +++ b/eVSSIM/SSD_MODULE/ssd_io_manager.c @@ -96,7 +96,7 @@ int SSD_IO_INIT(void){ int SSD_PAGE_WRITE(unsigned int flash_nb, unsigned int block_nb, unsigned int page_nb, int offset, int type, int io_page_nb) { int channel, reg; - int ret = FAIL; + int ret = FAILURE; int delay_ret; /* Calculate ch & reg */ @@ -114,7 +114,7 @@ int SSD_PAGE_WRITE(unsigned int flash_nb, unsigned int block_nb, unsigned int pa } /* Check Channel Operation */ - while(ret == FAIL){ + while(ret == FAILURE){ ret = SSD_CH_ACCESS(channel); } @@ -129,7 +129,7 @@ int SSD_PAGE_WRITE(unsigned int flash_nb, unsigned int block_nb, unsigned int pa } #endif - return SUCCESS; + return SUCCESSFUL; } int SSD_PAGE_READ(unsigned int flash_nb, unsigned int block_nb, unsigned int page_nb, int offset, int type, int io_page_nb) @@ -162,7 +162,7 @@ int SSD_PAGE_READ(unsigned int flash_nb, unsigned int block_nb, unsigned int pag SSD_REMAIN_IO_DELAY(reg); } #endif - return SUCCESS; + return SUCCESSFUL; } int SSD_BLOCK_ERASE(unsigned int flash_nb, unsigned int block_nb) @@ -185,7 +185,7 @@ int SSD_BLOCK_ERASE(unsigned int flash_nb, unsigned int block_nb) SSD_REG_RECORD(reg, ERASE, ERASE, -1, channel); SSD_CELL_RECORD(reg, ERASE); - return SUCCESS; + return SUCCESSFUL; } int SSD_FLASH_ACCESS(unsigned int flash_nb, int reg) @@ -244,13 +244,13 @@ int SSD_CH_ENABLE(int channel) int64_t do_delay = 0; if(CHANNEL_SWITCH_DELAY_R == 0 && CHANNEL_SWITCH_DELAY_W == 0) - return SUCCESS; + return SUCCESSFUL; if(old_channel_nb != channel){ do_delay = SSD_CH_SWITCH_DELAY(channel); } - return SUCCESS; + return SUCCESSFUL; } int SSD_CH_RECORD(int channel, int cmd, int offset, int ret) @@ -268,7 +268,7 @@ int SSD_CH_RECORD(int channel, int cmd, int offset, int ret) old_channel_time = get_usec(); } - return SUCCESS; + return SUCCESSFUL; } int SSD_REG_RECORD(int reg, int cmd, int type, int offset, int channel) @@ -319,7 +319,7 @@ int SSD_REG_RECORD(int reg, int cmd, int type, int offset, int channel) SSD_UPDATE_IO_OVERHEAD(reg, io_update_overhead); } - return SUCCESS; + return SUCCESSFUL; } int SSD_CELL_RECORD(int reg, int cmd) @@ -334,13 +334,13 @@ int SSD_CELL_RECORD(int reg, int cmd) cell_io_time[reg] = get_usec(); } - return SUCCESS; + return SUCCESSFUL; } int SSD_CH_ACCESS(int channel) { int i, j; - int ret = SUCCESS; + int ret = SUCCESSFUL; int r_num; for(i=0;i $curr_res_filename extract_iops $curr_res_filename $test_type curr_result -#echo "extract_iops curr res = $curr_result" +echo "extract_iops curr res = $curr_result" if [ $reference_result -lt 1 ]; then echo "ERROR failed to find reference result" diff --git a/eVSSIM/fio_tests/perf_test_rec_results.sh b/eVSSIM/fio_tests/perf_test_rec_results.sh index 2e48ce1d3..e79704a06 100755 --- a/eVSSIM/fio_tests/perf_test_rec_results.sh +++ b/eVSSIM/fio_tests/perf_test_rec_results.sh @@ -16,13 +16,13 @@ if [ ! -f $curr_fio_test_filename ]; then fi #zero the device -if [ 1 -eq `grep -v '#filename' $curr_fio_test_filename | grep -c filename=/dev/sdb` ]; +if [ 1 -eq `grep -v '#filename' $curr_fio_test_filename | grep -c filename=/dev/nvme0n1` ]; then # find test size and device test_size=`grep size= $curr_fio_test_filename` test_size=${test_size//[!0-9]/} #remove non digits - device=/dev/sdb #todo parse from file + device=/dev/nvme0n1 #todo parse from file echo "zeroing "$test_size"m on $device " echo time dd if=/dev/zero of=$device bs=1M count=$test_size else diff --git a/eVSSIM/osc-osd/osd-target/osd.c b/eVSSIM/osc-osd/osd-target/osd.c index 4b2238b7b..65ddfcd33 100755 --- a/eVSSIM/osc-osd/osd-target/osd.c +++ b/eVSSIM/osc-osd/osd-target/osd.c @@ -1626,10 +1626,8 @@ int osd_create(struct osd_device *osd, uint64_t pid, uint64_t requested_oid, ret = obj_ispresent(osd->dbc, pid, PARTITION_OID, &present); if (ret != OSD_OK || !present) goto out_illegal_req; - if (numoid > 1 && requested_oid != 0) goto out_illegal_req; - if (requested_oid == 0) { /* * XXX: there should be a better way of getting next maximum @@ -1651,6 +1649,7 @@ int osd_create(struct osd_device *osd, uint64_t pid, uint64_t requested_oid, } } else { ret = obj_ispresent(osd->dbc, pid, requested_oid, &present); + osd_debug("ret: %d, present: %d", ret, present); if (ret != OSD_OK || present) goto out_illegal_req; /* requested_oid exists! */ oid = requested_oid; /* requested_oid works! */ diff --git a/eVSSIM/osc-osd/tgt b/eVSSIM/osc-osd/tgt deleted file mode 160000 index dba9c76a4..000000000 --- a/eVSSIM/osc-osd/tgt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dba9c76a4e7514f9cbda477b2545dbc1fb332ef6 diff --git a/eVSSIM/tests/Makefile b/eVSSIM/tests/Makefile index db3c9de02..1eeb176a1 100644 --- a/eVSSIM/tests/Makefile +++ b/eVSSIM/tests/Makefile @@ -1,18 +1,16 @@ -OBJ = system_tests.o object_tests.o sector_tests.o - VSSIM_OBJ = vssim_config_manager.o \ ftl.o ftl_mapping_manager.o ftl_inverse_mapping_manager.o \ ftl_gc_manager.o ftl_perf_manager.o \ - ssd.o ssd_log_manager.o ssd_io_manager.o \ + ssd_log_manager.o ssd_io_manager.o \ ftl_sect_strategy.o ftl_obj_strategy.o -#CFLAGS = -I/opt/gtest/include -I../osc-osd -I../osc-osd/osd-target -g -DGTEST -DFTL_DEBUG -DNO_OSD -CFLAGS = -I/opt/gtest/include -I../osc-osd -I../osc-osd/osd-target -g -DGTEST -L/opt/gtest/lib +CFLAGS = -I/opt/gtest/include -I../osc-osd -I../osc-osd/osd-target -I../QEMU -g -DGTEST -DCOMPLIANCE_TESTS -L/opt/gtest/ -L../osc-osd/osd-util -L../osc-osd/osd-target all: sector_tests object_tests +#all: sector_tests sector_tests: sector_tests.o $(VSSIM_OBJ) - g++ $(CFLAGS) -Wall -o sector_tests sector_tests.o $(VSSIM_OBJ) -lpthread -lgtest -lgtest_main + g++ $(CFLAGS) -Wall -o sector_tests sector_tests.o $(VSSIM_OBJ) -lpthread -lgtest -lgtest_main -losdutil -losdtgt -lsqlite3 object_tests: object_tests.o $(VSSIM_OBJ) g++ $(CFLAGS) -Wall -o object_tests object_tests.o $(VSSIM_OBJ) -Wl,-Bstatic -L../osc-osd/osd-util -L../osc-osd/osd-target -losdutil -losdtgt -Wl,-Bdynamic -lsqlite3 -lm -lpthread -lgtest -lgtest_main @@ -35,8 +33,6 @@ distclean: clean ssd_monitor uthash.h mklink: - ln -s ../SSD_MODULE/ssd.h - ln -s ../SSD_MODULE/ssd.c ln -s ../SSD_MODULE/ssd_io_manager.h ln -s ../SSD_MODULE/ssd_io_manager.c ln -s ../SSD_MODULE/ssd_log_manager.h diff --git a/eVSSIM/tests/nvme-cli-testsWrapper.py b/eVSSIM/tests/nvme-cli-testsWrapper.py new file mode 100644 index 000000000..d52fa4151 --- /dev/null +++ b/eVSSIM/tests/nvme-cli-testsWrapper.py @@ -0,0 +1,76 @@ +# +# This short script is intended to check the nvme-cli's ability to read written data and verify its integrity. +# There are a total of 5 tests, where each test performs several iterations of the same write / read / compare action sequence, but with different object sizes (and IDs) +# The script should be run from inside the directory where the patched nvme util is installed. +# + +import os +import sys +from random import randint + +write_command_template = "./nvme write /dev/nvme0n1 --block-count=%d --data-size=%d --data=%s --metadata-size=%d --metadata=%s" #--show-command" +read_command_template = "./nvme read /dev/nvme0n1 --block-count=%d --data-size=%d --data=%s --metadata-size=%d --metadata=%s" #--show-command" +nvme_block_size=512 + +def calculate_block_count(dataSize): + initialCount = dataSize / nvme_block_size + remainder = dataSize % nvme_block_size + + if initialCount == 0: # smaller than block size -> use one block only (0 indicates we will use 1 block, as qemu adds 1 to the block count) + return 0 + elif remainder == 0: + return initialCount - 1 # size is a precise multiplication of block size + else: + return initialCount # size is at initialCount blocks + 1 + +def executeSingleTest(data_size, count, partition_id): + + block_count = calculate_block_count(data_size) + + for object_id in xrange(1,count+1): + #we're generating random data for EACH object + random_data = os.urandom(data_size) + tmpInFile = 'tmp_%d.in' % data_size + with open(tmpInFile,'w') as data_file: + data_file.write(random_data) + + metadata_data = 'eVSSIM_MAGIC%s_%d!' % (partition_id, object_id) + metadata_size = len(metadata_data) + metadata_file = 'metadata.md' + with open(metadata_file,'wb') as metadata_fileHandler: + metadata_fileHandler.write(metadata_data) + + write_command = write_command_template % (block_count, data_size, tmpInFile, metadata_size, metadata_file) + print '[%d/%d] writing object of size %d' % (object_id, count, data_size) + os.system(write_command) + + tmpOutFile = 'tmp_%d.out' % data_size + read_command = read_command_template % (block_count, data_size, tmpOutFile, metadata_size, metadata_file) + print '[%d/%d] reading object of size %d' % (object_id, count, data_size) + os.system(read_command) + + with open(tmpOutFile,'rb') as tmpOutFileHandle: + inputByteArray = tmpOutFileHandle.read() + os.remove(tmpOutFile) + os.remove(tmpInFile) + os.remove(metadata_file) + + if inputByteArray == random_data: + print '[%d/%d] write + read %d bytes SUCCESSFUL' % (object_id, count, data_size) + else: + print '[%d/%d] write + read %d bytes FAILED - terminating!' % (object_id, count, data_size) + return False + + return True + + #perform total time + avg time for each run (by dividing at the end) + +#we're using a random partition id as we want to avoid a situtation where this util fails in different executions because of using the same partition id -> this minimizes the chance of that happening +part_id = randint(100,9999999) +print "partition id is: " + str(part_id) + +if executeSingleTest(10,10,part_id) and executeSingleTest(512,10,part_id+1) and executeSingleTest(1000,100,part_id+2) and executeSingleTest(10000,100,part_id+3) and executeSingleTest(10000,1000,part_id+4): + print "Finished all tests successfully!" + + + diff --git a/eVSSIM/tests/object_tests.cc b/eVSSIM/tests/object_tests.cc index 8c0243185..c05f1606b 100644 --- a/eVSSIM/tests/object_tests.cc +++ b/eVSSIM/tests/object_tests.cc @@ -1,9 +1,7 @@ extern "C" { -#include "ssd.h" -#include "ftl.h" +#include "common.h" #include "ftl_obj_strategy.h" -#include "ftl_sect_strategy.h" #include "uthash.h" #include "osd.h" @@ -51,16 +49,23 @@ namespace { "STAT_PATH /tmp/stat.csv\n" "STORAGE_STRATEGY 2\n"; // object strategy ssd_conf.close(); - SSD_INIT(); + FTL_INIT(); + INIT_OBJ_STRATEGY(); + #ifdef MONITOR_ON + INIT_LOG_MANAGER(); + #endif object_size_ = GetParam(); - int object_pages = (int)ceil(1.0 * object_size_ / PAGE_SIZE); // ceil because we can't have a page belong to 2 objects + int object_pages = (int)ceil(1.0 * object_size_ / eVSSIM_PAGE_SIZE); // ceil because we can't have a page belong to 2 objects objects_in_ssd_ = (unsigned int)((PAGES_IN_SSD - BLOCK_NB)/ object_pages); //over-provisioning of exactly one block #ifndef NO_OSD osd_init(); #endif } virtual void TearDown() { - SSD_TERM(); + FTL_TERM(); + #ifdef MONITOR_ON + TERM_LOG_MANAGER(); + #endif remove("data/empty_block_list.dat"); remove("data/inverse_block_mapping.dat"); remove("data/inverse_page_mapping.dat"); @@ -96,30 +101,26 @@ namespace { }; // OccupySpaceStressTest INSTANTIATE_TEST_CASE_P(DiskSize, ObjectUnitTest, ::testing::Values(2048, // 1/2 page - 6144, // 1 1/2 pages 2 * 1024 * 1024, // 2 MB 6 * 1024 * 1024)); // 6 MB TEST_P(ObjectUnitTest, SimpleObjectCreate) { printf("SimpleObjectCreate test started\n"); - printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,PAGE_SIZE); + printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,eVSSIM_PAGE_SIZE); printf("Object size: %d bytes\n",object_size_); - #ifndef NO_OSD char *wrbuf = (char *)Calloc(1, object_size_); #endif - // Fill the disk with objects - for(unsigned int p=0; p < objects_in_ssd_; p++){ - int new_obj = _FTL_OBJ_CREATE(object_size_); - ASSERT_LT(0, new_obj); + for(unsigned long p=1; p < objects_in_ssd_; p++){ + bool res = _FTL_OBJ_CREATE(p, object_size_); + ASSERT_TRUE(res); #ifndef NO_OSD - ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + new_obj, object_size_, 0, + ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + p, object_size_, 0, (uint8_t *)wrbuf, cdb_cont_len, 0, osd_sense, DDT_CONTIG)); #endif } - #ifndef NO_OSD free(wrbuf); #endif @@ -132,7 +133,7 @@ namespace { TEST_P(ObjectUnitTest, SimpleObjectCreateWrite) { printf("SimpleObjectCreateWrite test started\n"); - printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,PAGE_SIZE); + printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,eVSSIM_PAGE_SIZE); printf("Object size: %d bytes\n",object_size_); // used to keep all the assigned ids @@ -143,30 +144,30 @@ namespace { #endif // Fill 50% of the disk with objects - for(unsigned int p=0; p < objects_in_ssd_ / 2; p++){ - int new_obj = _FTL_OBJ_CREATE(object_size_); - ASSERT_LT(0, new_obj); - objects[p] = new_obj; + for(unsigned long p=1; p < objects_in_ssd_ / 2; p++){ + bool res = _FTL_OBJ_CREATE(p, object_size_); + ASSERT_TRUE(res); + objects[p] = p; #ifndef NO_OSD - ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + new_obj, object_size_, 0, + ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + p, object_size_, 0, (uint8_t *)wrbuf, cdb_cont_len, 0, osd_sense, DDT_CONTIG)); #endif } - + #ifndef NO_OSD free(wrbuf); - wrbuf = (char *)Calloc(1, PAGE_SIZE); + wrbuf = (char *)Calloc(1, eVSSIM_PAGE_SIZE); #endif // Write PAGE_SIZE data to each one - for(unsigned int p=0; p < objects_in_ssd_/2; p++){ - ASSERT_EQ(SUCCESS, _FTL_OBJ_WRITE(objects[p],0,PAGE_SIZE)); + for(unsigned long p=1; p < objects_in_ssd_/2; p++){ + ASSERT_EQ(SUCCESSFUL, _FTL_OBJ_WRITE(objects[p],0,eVSSIM_PAGE_SIZE)); #ifndef NO_OSD ASSERT_EQ(0, osd_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + objects[p], - PAGE_SIZE, 0, (uint8_t *)wrbuf, 0, osd_sense, DDT_CONTIG)); + eVSSIM_PAGE_SIZE, 0, (uint8_t *)wrbuf, 0, osd_sense, DDT_CONTIG)); #endif } - + #ifndef NO_OSD free(wrbuf); #endif @@ -176,47 +177,44 @@ namespace { TEST_P(ObjectUnitTest, SimpleObjectCreateRead) { printf("SimpleObjectCreateRead test started\n"); - printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,PAGE_SIZE); + printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,eVSSIM_PAGE_SIZE); printf("Object size: %d bytes\n",object_size_); // used to keep all the assigned ids int objects[objects_in_ssd_]; - + #ifndef NO_OSD char *wrbuf = (char *)Calloc(1, object_size_); #endif - // Fill 50% of the disk with objects - for(unsigned int p=0; p < objects_in_ssd_/2; p++){ - int new_obj = _FTL_OBJ_CREATE(object_size_); - ASSERT_LT(0, new_obj); - objects[p] = new_obj; + for(unsigned long p=1; p < objects_in_ssd_/2; p++){ + bool res = _FTL_OBJ_CREATE(p, object_size_); + ASSERT_TRUE(res); + objects[p] = p; #ifndef NO_OSD // insert unique data to the object - sprintf(wrbuf,"%u", new_obj); - ASSERT_EQ(0 ,osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + new_obj, object_size_, 0, + sprintf(wrbuf,"%lu", p); + ASSERT_EQ(0 ,osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + p, object_size_, 0, (uint8_t *)wrbuf,cdb_cont_len, 0, osd_sense, DDT_CONTIG)); #endif } -#ifndef NO_OSD // length and read buffer uint64_t len; - char *rdbuf = (char *)Calloc(1, PAGE_SIZE/2); -#endif + char *rdbuf = (char *)Calloc(1, eVSSIM_PAGE_SIZE/2); // Read PAGE_SIZE/2 data from each one - for(unsigned int p=0; p < objects_in_ssd_/2; p++){ - ASSERT_EQ(SUCCESS, _FTL_OBJ_READ(objects[p],0,PAGE_SIZE)); + for(unsigned long p=1; p < objects_in_ssd_/2; p++){ + ASSERT_EQ(SUCCESSFUL, _FTL_OBJ_READ(objects[p],0,eVSSIM_PAGE_SIZE)); #ifndef NO_OSD // read and compare with the expected unique data ASSERT_EQ(0, osd_read(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + objects[p], - PAGE_SIZE/2, 0, NULL, (uint8_t *)rdbuf, &len, 0, osd_sense, DDT_CONTIG)); + eVSSIM_PAGE_SIZE/2, 0, NULL, (uint8_t *)rdbuf, &len, 0, osd_sense, DDT_CONTIG)); sprintf(wrbuf, "%u", objects[p]); ASSERT_EQ(0, strcmp(rdbuf, wrbuf)); #endif } - + #ifndef NO_OSD free(rdbuf); free(wrbuf); @@ -227,23 +225,23 @@ namespace { TEST_P(ObjectUnitTest, SimpleObjectCreateDelete) { printf("SimpleObjectCreateDelete test started\n"); - printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,PAGE_SIZE); + printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,eVSSIM_PAGE_SIZE); printf("Object size: %d bytes\n",object_size_); // used to keep all the assigned ids int objects[objects_in_ssd_]; - + #ifndef NO_OSD char *wrbuf = (char *)Calloc(1, object_size_); #endif - + // Fill the disk with objects - for(unsigned int p=0; p < objects_in_ssd_; p++){ - int new_obj = _FTL_OBJ_CREATE(object_size_); - ASSERT_LT(0, new_obj); - objects[p] = new_obj; + for(unsigned long p=1; p < objects_in_ssd_; p++){ + bool res = _FTL_OBJ_CREATE(p, object_size_); + ASSERT_TRUE(res); + objects[p] = p; #ifndef NO_OSD - ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + new_obj, object_size_, 0, + ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + p, object_size_, 0, (uint8_t *)wrbuf, cdb_cont_len, 0, osd_sense, DDT_CONTIG)); #endif } @@ -251,23 +249,22 @@ namespace { // ASSERT_EQ(FAIL, _FTL_OBJ_CREATE(object_size_)); // Delete all objects - for (unsigned int p=0; p < objects_in_ssd_; p++) { - ASSERT_EQ(SUCCESS, _FTL_OBJ_DELETE(objects[p])); + for (unsigned long p=1; p < objects_in_ssd_; p++) { + ASSERT_EQ(SUCCESSFUL, _FTL_OBJ_DELETE(objects[p])); #ifndef NO_OSD ASSERT_EQ(0, osd_remove(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + objects[p], cdb_cont_len, osd_sense)); #endif } // And try to fill the disk again with the same number of sized objects - for(unsigned int p=0; p < objects_in_ssd_; p++){ - int new_obj = _FTL_OBJ_CREATE(object_size_); - ASSERT_LT(0, new_obj); + for(unsigned long p=1; p < objects_in_ssd_; p++){ + bool res = _FTL_OBJ_CREATE(p, object_size_); + ASSERT_TRUE(res); #ifndef NO_OSD - ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + new_obj, object_size_, 0, + ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + p, object_size_, 0, (uint8_t *)wrbuf, cdb_cont_len, 0, osd_sense, DDT_CONTIG)); #endif } - #ifndef NO_OSD free(wrbuf); #endif @@ -278,34 +275,34 @@ namespace { TEST_P(ObjectUnitTest, ObjectGrowthTest) { unsigned int final_object_size = objects_in_ssd_ * object_size_; printf("ObjectGrowth test started\n"); - printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,PAGE_SIZE); + printf("Page no.:%ld\nPage size:%d\n",PAGES_IN_SSD,eVSSIM_PAGE_SIZE); printf("Initial object size: %d bytes\n",object_size_); printf("Final object size: %d bytes\n",final_object_size); + int tempObj = 1000; // create an object_size_bytes_ - sized object - int obj_id = _FTL_OBJ_CREATE(object_size_); - ASSERT_LT(0, obj_id); + bool res = _FTL_OBJ_CREATE(tempObj, object_size_); + ASSERT_TRUE(res); #ifndef NO_OSD char *wrbuf = (char *)Calloc(1, object_size_); - ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + obj_id, object_size_, 0, + ASSERT_EQ(0, osd_create_and_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + tempObj, object_size_, 0, (uint8_t *)wrbuf, cdb_cont_len, 0, osd_sense, DDT_CONTIG)); #endif unsigned int size = object_size_; // continuously extend it with object_size_bytes_ chunks while (size < final_object_size) { - ASSERT_EQ(SUCCESS, _FTL_OBJ_WRITE(obj_id, size, object_size_)); + ASSERT_EQ(SUCCESSFUL, _FTL_OBJ_WRITE(tempObj, size, object_size_)); size += object_size_; #ifndef NO_OSD - ASSERT_EQ(0, osd_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + obj_id, + ASSERT_EQ(0, osd_write(&osd, USEROBJECT_PID_LB, USEROBJECT_OID_LB + tempObj, object_size_, size, (uint8_t *)wrbuf, 0, osd_sense, DDT_CONTIG)); #endif } // we should've covered the whole disk by now, so another write should fail //ASSERT_EQ(FAIL, _FTL_OBJ_WRITE(obj_id, size, object_size_)); - #ifndef NO_OSD free(wrbuf); #endif diff --git a/eVSSIM/tests/sector_tests.cc b/eVSSIM/tests/sector_tests.cc index 1d4603130..03effae8b 100644 --- a/eVSSIM/tests/sector_tests.cc +++ b/eVSSIM/tests/sector_tests.cc @@ -1,7 +1,7 @@ extern "C" { -#include "ssd.h" -#include "ftl.h" +#include "common.h" +#include "ftl_sect_strategy.h" } extern "C" int g_init; extern "C" int g_server_create; @@ -22,16 +22,16 @@ namespace { public: virtual void SetUp() { size_t mb = GetParam(); - pages_= mb * (1048576 / 4096); // number_of_pages = disk_size (in MB) * 1048576 / page_size + pages_= (mb * 1024 * 1024) / 4096; // number_of_pages = disk_size (in bytes) / page_size in bytes size_t block_x_flash = pages_ / 8; // all_blocks_on_all_flashes = number_of_pages / pages_in_block size_t flash = block_x_flash / 4096; // number_of_flashes = all_blocks_on_all_flashes / number_of_blocks_in_flash ofstream ssd_conf("data/ssd.conf", ios_base::out | ios_base::trunc); ssd_conf << "FILE_NAME ./data/ssd.img\n" - "PAGE_SIZE 4096\n" + "PAGE_SIZE 4096\n" // page size in bytes "PAGE_NB 10\n" // 8 pages per block +2 pages over-provision = 125% of disk size "SECTOR_SIZE 1\n" - "FLASH_NB " << flash << "\n" // see calculations above - "BLOCK_NB 4096\n" + "FLASH_NB 32\n" // << flash << "\n" // see calculations above + "BLOCK_NB 4096\n" // amount of blocks per flash "PLANES_PER_FLASH 1\n" "REG_WRITE_DELAY 82\n" "CELL_PROGRAM_DELAY 900\n" @@ -46,10 +46,16 @@ namespace { "STAT_PATH /tmp/stat.csv\n" "STORAGE_STRATEGY 1\n"; // sector strategy ssd_conf.close(); - SSD_INIT(); + FTL_INIT(); + #ifdef MONITOR_ON + INIT_LOG_MANAGER(); + #endif } virtual void TearDown() { - SSD_TERM(); + FTL_TERM(); + #ifdef MONITOR_ON + TERM_LOG_MANAGER(); + #endif remove("data/empty_block_list.dat"); remove("data/inverse_block_mapping.dat"); remove("data/inverse_page_mapping.dat"); @@ -70,7 +76,7 @@ namespace { TEST_P(SectorUnitTest, SequentialOnePageAtTimeWrite) { for(int x=0; x<8; x++){ for(size_t p=0; p < pages_; p++){ - ASSERT_EQ(SUCCESS, _FTL_WRITE_SECT(p * 4096, 1)); + ASSERT_EQ(SUCCESSFUL, _FTL_WRITE_SECT(p * 4096, 1)); } } } @@ -78,7 +84,7 @@ namespace { TEST_P(SectorUnitTest, RandomOnePageAtTimeWrite) { for(int x=0; x<8; x++){ for(size_t p=0; p < pages_; p++){ - ASSERT_EQ(SUCCESS, _FTL_WRITE_SECT((rand() % pages_) * 4096, 1)); + ASSERT_EQ(SUCCESSFUL, _FTL_WRITE_SECT((rand() % pages_) * 4096, 1)); } } } @@ -86,10 +92,10 @@ namespace { TEST_P(SectorUnitTest, MixSequentialAndRandomOnePageAtTimeWrite) { for(int x=0; x<2; x++){ for(size_t p=0; p < pages_; p++){ - ASSERT_EQ(SUCCESS, _FTL_WRITE_SECT((rand() % pages_) * 4096, 1)); + ASSERT_EQ(SUCCESSFUL, _FTL_WRITE_SECT((rand() % pages_) * 4096, 1)); } for(size_t p=0; p < pages_; p++){ - ASSERT_EQ(SUCCESS, _FTL_WRITE_SECT(p * 4096, 1)); + ASSERT_EQ(SUCCESSFUL, _FTL_WRITE_SECT(p * 4096, 1)); } } }