此函数是在所给的channel,chip,die,plane里面找到一个active_block然后再在这个block里面找到一个页,再利用find_ppn()函数找到ppn。(可能产生擦除节点挂载plane上,可能产生GC节点挂载channel上)。
当要写入的页没有相应的映射关系时,直接为该写子请求利用find_ppn()函数找到一个空闲页获得ppn,并更新映射表。当要写入的页有相应的映射关系时,首先会将该映射关系所对应的ppn置为失效页,并设置好相关属性,然后会判断该ppn所在的block是否都是失效页,如果都是失效页的话则说明该block需要进行擦除之后才能再利用了,所以此时会产生一个可擦除节点(会开辟内存空间),该可擦除节点会挂载在此时所在的plane上,最后再利用find_ppn()函数找到一个新的ppn并更新映射表。然后修改该写子请求的ppn以及location相关变量属性以及修改ssd因一次写操作而产生的相关属性变化。最后如果没有主动策略,只采用gc_hard_threshold,并且无法中断GC过程,如果plane中的free_page的数目少于gc_hard_threshold所设定的阈值就产生gc操作,此时会产生一个gc_node(会开辟内存空间),设置该gc_node相关属性(next_node、chip、die、plane、block、page、state、priority),最后将该gc_node挂载到该gc_node所在的channel的gc_command上。gc_node属性只会精确到plane,然后从plane寻找可擦除节点,因为由失效页过多而产生的必须擦除才可用的现象发生在plane内部的block上,所以可擦除节点挂载到了plane上,故gc_node只需要精确到plane号就行,然后从plane寻找擦除节点,而该gc_noed挂载在响应的channel上。
struct ssd_info *get_ppn(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,struct sub_request *sub)
{
unsigned int ppn,lpn,full_page,active_block,block,page;
struct local *location;
struct direct_erase *direct_erase_node,*new_direct_erase;
struct gc_operation *gc_node;
#ifdef DEBUG
printf("enter get_ppn,channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
#endif
full_page=~(0xffffffff<<(ssd->parameter->subpage_page));
lpn=sub->lpn;
/*************************************************************************************
*利用函数find_active_block在channel,chip,die,plane找到活跃block
*并且修改这个channel,chip,die,plane,active_block下的last_write_page和free_page_num
**************************************************************************************/
if(find_active_block(ssd,channel,chip,die,plane)==FAILURE){ //寻找活跃块
printf("ERROR :there is no free page in channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
return ssd;
}
active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num--;
if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page>63){
printf("error! the last write page larger than 64!!\n");
while(1){}
}
block=active_block;
page=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page;
if(ssd->dram->map->map_entry[lpn].state==0){ /*this is the first logical page*/
if(ssd->dram->map->map_entry[lpn].pn!=0)
printf("Error in get_ppn()\n");
ssd->dram->map->map_entry[lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
ssd->dram->map->map_entry[lpn].state=sub->state;
}else{ /*这个逻辑页进行了更新,需要将原来的页置为失效*/
ppn=ssd->dram->map->map_entry[lpn].pn;
location=find_location(ssd,ppn);
if(ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn!=lpn)
printf("\nError in get_ppn()\n");
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state=0; /*表示某一页失效,同时标记valid和free状态都为0*/
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state=0; /*表示某一页失效,同时标记valid和free状态都为0*/
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn=0;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num++;
/*该block中全是invalid的页,可以直接删除,就在创建一个可擦除的节点,挂在location下的plane下面*/
if(ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num==ssd->parameter->page_block){
new_direct_erase=(struct direct_erase *)malloc(sizeof(struct direct_erase));
alloc_assert(new_direct_erase,"new_direct_erase");
memset(new_direct_erase,0, sizeof(struct direct_erase));
new_direct_erase->block=location->block;
new_direct_erase->next_node=NULL;
direct_erase_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
if(direct_erase_node==NULL)
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
else{
new_direct_erase->next_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
}
}
free(location);
location=NULL;
ssd->dram->map->map_entry[lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
ssd->dram->map->map_entry[lpn].state=(ssd->dram->map->map_entry[lpn].state|sub->state);
}
sub->ppn=ssd->dram->map->map_entry[lpn].pn; /*修改sub子请求的ppn,location等变量*/
sub->location->channel=channel;
sub->location->chip=chip;
sub->location->die=die;
sub->location->plane=plane;
sub->location->block=active_block;
sub->location->page=page;
ssd->program_count++; /*修改ssd的program_count,free_page等变量*/
ssd->channel_head[channel].program_count++;
ssd->channel_head[channel].chip_head[chip].program_count++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].lpn=lpn;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].valid_state=sub->state;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].free_state=((~(sub->state))&full_page);
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].written_count++;
ssd->write_flash_count++;
if(ssd->parameter->active_write==0) /*如果没有主动策略,只采用gc_hard_threshold,并且无法中断GC过程*/
{ /*如果plane中的free_page的数目少于gc_hard_threshold所设定的阈值就产生gc操作*/
if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page<(ssd->parameter->page_block*ssd->parameter->block_plane*ssd->parameter->gc_hard_threshold))
{
gc_node=(struct gc_operation *)malloc(sizeof(struct gc_operation));
alloc_assert(gc_node,"gc_node");
memset(gc_node,0, sizeof(struct gc_operation));
gc_node->next_node=NULL;
gc_node->chip=chip;
gc_node->die=die;
gc_node->plane=plane;
gc_node->block=0xffffffff;
gc_node->page=0;
gc_node->state=GC_WAIT;
gc_node->priority=GC_UNINTERRUPT; //不可中断的GC节点
gc_node->next_node=ssd->channel_head[channel].gc_command;
ssd->channel_head[channel].gc_command=gc_node;
ssd->gc_request++;
}
}
return ssd;
}