Creat_sub_request()函数的功能主要是根据传输参数lpn、size、state和IO请求项req创建一个子请求sub_req。
每一个创建出来的sub_req的操作区域都是当前lpn的区域,也就是说,可能存在创建出来的子请求sub_req的size是小于当前的lpn的大小的(通常大多数与随机4KIO相关),但是每一个sub_req的操作目标区域都是在当前lpn所在的区域之中。相当于说,对于pagemap机制的FTL,在底层处理的过程中,都会依据每个IO request的操作LPN与size参数,按照闪存页级规格的大小平均划分分布成多个子请求,分别挂载到指定的channel上进行处理。
这个函数可谓在初始化处理IO请求项的过程中是非常重要的模块。对于读IO而言,这个函数主要是在distribute()函数中被调用,为那些在buffer_management()函数中读未命中(可能某部分子页未命中也可能全部子页都未命中)的IO请求项分布读子请求到SSD中读取数据所用。
对于写IO而言,这个函数是在insert2buffer()函数中被调用,但是需要注意的是,创建的写回子请求的数据其实都与当前IO写请求毫无关系,这些写回子请求是在buffer中被腾空出来的数据,因为写优先被buffer服务,因此对于每一个写IO,都必须要先写到buffer中,一旦buffer空闲容量不足则会腾空写回其他数据到SSD中,因此这个函数对于写IO而言,实质上就是为了腾空空间。所以,在这种缓存管理的机制下,所有的IO处理过程其实绝大多数伴随着其他LPN的写回操作。
下面我们先看源码:
struct sub_request * creat_sub_request(struct ssd_info * ssd,unsigned int lpn,int size,unsigned int state,struct request * req,unsigned int operation)
{
struct sub_request* sub=NULL,* sub_r=NULL;
struct channel_info * p_ch=NULL;
struct local * loc=NULL;
unsigned int flag=0;
sub = (struct sub_request*)malloc(sizeof(struct sub_request)); /*申请一个子请求的结构*/
alloc_assert(sub,"sub_request");
memset(sub,0, sizeof(struct sub_request));
if(sub==NULL)
{
return NULL;
}
sub->location=NULL;
sub->next_node=NULL;
sub->next_subs=NULL;
sub->update=NULL;
if(req!=NULL)
{
sub->next_subs = req->subs;
req->subs = sub;
}
/************************