名为块级重删(dm dedup) & lt; 3祝辞代码结构(2)

  

四、代码结构(2)空间管理器

  

这一篇和下一篇我们来介绍dm dedup的空间管理的部分和核心流程的I/O写流程

  

在此之前,我们先分析一下用到的资源有哪些,和了解dm dedup的空间管理器空间管理器
名为块级重删(dm dedup) & lt; 3祝辞代码结构(2)

  

空间管理器,是一个巨型的数组,以allocptr申请指针为标,对整个空间进行扫描一周(回到当前allocptr)。
用来找到空闲的块(白色),并把它分配给一个散列的要求,把它变成一个绿色的块,并把这个信息hash_pbn,放到kvs_hash_pbn的表内。

  

kvs_lbn_pbn和kvs_hash_pbn的空间是预先分配好的,所以这两个表的索引都是有确定的含义,非常利于查找。

  
 <代码>直流→kvs_hash_pbn=直流→mdops→kvs_create_sparse(医学博士,crypto_key_size, sizeof (struct hash_pbn_value),直流→pblocks,无格式);
  
  直流→kvs_lbn_pbn=直流→mdops→kvs_create_linear(医学博士,8,sizeof (struct lbn_pbn_value),直流→lblocks,无格式), 
  

在创建变电站(键值空间)的时候,有两种选择,一种是按线性就照是一一映射的lbn-pbn的方式,还有一种是散列索引的方式。

  

其中都会将ksize和vsize会在两种空间类型不同而会以不同的方式保存。

  

①kvs-lbn-pbn,线性的创造空间方式inram

  
 <代码>静态结构kvstore * kvs_create_linear_inram (* md结构元数据,u32 ksize, u32 vsize, u32 kmax, bool无格式)
  {
  struct kvstore_inram *变电站;
  u64 kvstore_size tmp;
  
  变电站=kmalloc (sizeof(*变电站),GFP_NOIO);
  如果变电站(!)
  返回ERR_PTR (-ENOMEM);
  
  kvstore_size=(kmax + 1) * vsize;
  变电站→存储=vmalloc (kvstore_size);/*确定变电站→存储的大小,这里的思想很简单,
  就是64位的lbn寻址到一个ksize的pbn上面,一般的pbn也是64位*//* kmax是逻辑设备的大小,这个映射表的含义就是lbn-pbn的映射关系*/tmp=kvstore_size;
  (空白)do_div (tmp (1024 * 1024));
  
  memset(变电站→存储、EMPTY_ENTRY kvstore_size);
  
  变电站→ckvs。vsize=vsize;
  变电站→ckvs。ksize=ksize;
  变电站→kmax=kmax;
  
  变电站→ckvs。kvs_insert=kvs_insert_linear_inram;*//*插入api
  变电站→ckvs。kvs_lookup=kvs_lookup_linear_inram;*//*查找api
  变电站→ckvs。kvs_delete=kvs_delete_linear_inram;*//*删除api
  变电站→ckvs。kvs_iterate=kvs_iterate_linear_inram;*//*迭代api
  md→kvs_linear=变电站;
  
  返回,(变电站→ckvs);
  } 
  

我们简单看一看kvs_insert_linear_inram和kvs_lookup_linear_inram,删除和迭代留在垃圾回收的部分介绍。

  
 <代码>静态int kvs_insert_linear_inram (struct kvstore *变电站,void *键,s32 ksize, void *价值,int32_t vsize)
  {
  u64 idx;
  char * ptr;
  struct kvstore_inram * kvinram=零;
  
  kvinram=container_of(变电站、结构kvstore_inram ckvs);
  
  idx=* ((uint64_t *)键);
  ptr=kvinram→存储+变电站→vsize * idx;/*以lbn为关键,pbn为价值的地图*/memcpy (ptr、价值、变电站→vsize);
  
  返回0;
  } 
  

插入的代码非常简单,就可以理解成线性是个u64变电站[kmax]这样的数组,lbn是数组下标,而价值是数组内容。

  
 <代码>静态int kvs_lookup_linear_inram (struct kvstore *变电站,void *键,
  s32 ksize, void *价值,
  int32_t * vsize)
  {
  u64 idx;
  char * ptr;
  int r=-ENODATA;
  struct kvstore_inram * kvinram=零;
  
  kvinram=container_of(变电站、结构kvstore_inram ckvs);
  
  idx=* ((uint64_t *)键);
  ptr=kvinram→存储+变电站→vsize * idx;
  
  如果(is_empty (ptr,变电站→vsize))
  返回r;
  
  memcpy(价值、ptr、变电站→vsize);
  * vsize=变电站→vsize;
  
  返回0;
  } 
  

②kvs-hash-pbn,稀疏的创造空间方式inram
稀疏的方式和线性不太一样,它的组织形式会更加复杂一些
他要存键和值两个,key_size是采用哈希算法的大小,如:md5是128位,价值是pbn是64位

  
 <代码>静态结构kvstore * kvs_create_sparse_inram (* md结构元数据,
  u32 ksize, u32 vsize,
  u32 knummax bool无格式)
  {
  struct kvstore_inram *变电站;
  u64 kvstore_size tmp;
  
  变电站=kmalloc (sizeof(*变电站),GFP_NOIO);/* knummax关键的最大值这里是按照pbn的最大值申请的,物理设备的大小*/knummax +=(knummax * HASHTABLE_OVERPROV)/100/*额外申请了十分之一的空间*/kvstore_size=(knummax * (vsize + ksize));/*申请单位是vsize (pbn) 64位ksize (hash_size) 128位*/变电站→存储=vmalloc (kvstore_size);
  
  tmp=kvstore_size;
  (空白)do_div (tmp (1024 * 1024));
  
  memset(变电站→存储、EMPTY_ENTRY kvstore_size);/*将所有的关键都预先变成EMPTY_ENTRY=0 xfb(最新的代码4.13是0 xff) */变电站→ckvs。vsize=vsize;
  变电站→ckvs。ksize=ksize;
  变电站→kmax=knummax;
  
  变电站→ckvs。kvs_insert=kvs_insert_sparse_inram;*//*插入api
  变电站→ckvs。kvs_lookup=kvs_lookup_sparse_inram;*//*查找api
  变电站→ckvs。kvs_delete=kvs_delete_sparse_inram;*//*删除api
  变电站→ckvs。kvs_iterate=kvs_iterate_sparse_inram;*//*迭代api
  
  md→kvs_sparse=变电站;
  
  返回,(变电站→ckvs);
  }
  

名为块级重删(dm dedup) & lt; 3祝辞代码结构(2)