博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
device-mapper 块级重删(dm dedup) <3>代码结构(3)
阅读量:5756 次
发布时间:2019-06-18

本文共 8698 字,大约阅读时间需要 28 分钟。

五、代码结构(3) I/O写流程

上一篇我们来介绍了dm dedup的空间管理

这一篇我们介绍核心流程I/O写流程

device-mapper 块级重删(dm dedup) <3>代码结构(3)

要看的特别清楚这部分的内容,需要结合我之前写过的一起学习。

在块级重删 设计那一篇已经描述了这一系列的过程。

上一篇代码结构已经对kvs_hash和kvs_lbn的lookup和insert有了分析。
接下来我们来看看lookup和insert在写流程中的使用。

首先我们先看一下alloc_pbn_block给lbn的函数,后面都会用用到。

【                            /*因为现在还没有pbn来放置lbn,所以先申请一个pbn_new*/                    static int alloc_pbnblk_and_insert_lbn_pbn(struct dedup_config *dc,                                                     u64 *pbn_new,                                                     struct bio *bio, uint64_t lbn)                        {                            int r = 0;                            struct lbn_pbn_value lbnpbn_value;                            r = allocate_block(dc, pbn_new);/*找到一个新的pbn*/                            lbnpbn_value.pbn = *pbn_new;                            do_io(dc, bio, *pbn_new); /*将bio的数据放置到pbn_new的位置*/                            r = dc->kvs_lbn_pbn->kvs_insert(dc->kvs_lbn_pbn, (void *)&lbn,                                            sizeof(lbn), (void *)&lbnpbn_value,                                            sizeof(lbnpbn_value));                            /*将新的lbn_pbn的关系记录到kvs_lbn_pbn中*/                            return r;                    }             】

1、no hash && no lbn

即:① compute_hash_bio(dc->desc_table, bio, hash); //对bio的data进行hash,获得到hash_pbn
-> ② dc->kvs_hash_pbn->kvs_lookup; //通过hash值,查找对应的hash_pbn_value,也就是pbn。
没有找到pbn ->③ handle_write_no_hash.[dc->kvs_lbn_pbn->kvs_lookup] //寻找bio的lbn是否存在
没有找到lbn -> ④ handle_write_no_hash.[__handle_no_lbn_pbn] //这里到了最终处理函数
这里为了减少篇章,去掉了资源申请错误处理和资源访问错误处理

static int __handle_no_lbn_pbn(struct dedup_config *dc,                   struct bio *bio, uint64_t lbn, u8 *hash){    int r, ret;    u64 pbn_new;    struct hash_pbn_value hashpbn_value;    /* Create a new lbn-pbn mapping for given lbn,注意这里是pbn_new */    r = alloc_pbnblk_and_insert_lbn_pbn(dc, &pbn_new, bio, lbn);    /* Inserts new hash-pbn mapping for given hash.    由于dm_io已经将bio数据放置到pbn中,然后hash_pbn记录*/    hashpbn_value.pbn = pbn_new;    r = dc->kvs_hash_pbn->kvs_insert(dc->kvs_hash_pbn, (void *)hash,                     dc->crypto_key_size,                     (void *)&hashpbn_value,                     sizeof(hashpbn_value));    /* Increments refcount for new pbn entry created. 增加一个引用*/    r = dc->mdops->inc_refcount(dc->bmd, pbn_new);    /* On all successful steps increment new write count. */    dc->newwrites++;/* 在dc中记录下newwrites增加,为了更好的统计和分析行为*/    goto out;/* Error handling code path */inc_refcount_err:    /* Undo actions taken in hash-pbn kvs insert. */    ret = dc->kvs_hash_pbn->kvs_delete(dc->kvs_hash_pbn,                       (void *)hash, dc->crypto_key_size);kvs_insert_err:    /* Undo actions taken in alloc_pbnblk_and_insert_lbn_pbn. */    ret = dc->kvs_lbn_pbn->kvs_delete(dc->kvs_lbn_pbn,                      (void *)&lbn, sizeof(lbn));    ret = dc->mdops->dec_refcount(dc->bmd, pbn_new);out:    return r;}

2、no hash && has lbn

即:① compute_hash_bio(dc->desc_table, bio, hash); //对bio的data进行hash,获得到hash_pbn
-> ② dc->kvs_hash_pbn->kvs_lookup; //通过hash值,查找对应的hash_pbn_value,也就是pbn。
没有找到pbn ->③ handle_write_no_hash.[dc->kvs_lbn_pbn->kvs_lookup] //寻找bio的lbn是否存在
找到lbn -> ④ handle_write_no_hash.[__handle_has_lbn_pbn] //这里到了最终处理函数

static int __handle_has_lbn_pbn(struct dedup_config *dc,                struct bio *bio, uint64_t lbn, u8 *hash,                u64 pbn_old){    int r, ret;    u64 pbn_new;    struct hash_pbn_value hashpbn_value;    /* Allocates a new block for new pbn and inserts lbn-pbn lapping.注意这是覆盖 */    r = alloc_pbnblk_and_insert_lbn_pbn(dc, &pbn_new, bio, lbn);    /* Inserts new hash-pbn entry for given hash. */    hashpbn_value.pbn = pbn_new;    r = dc->kvs_hash_pbn->kvs_insert(dc->kvs_hash_pbn, (void *)hash,                     dc->crypto_key_size,                     (void *)&hashpbn_value,                     sizeof(hashpbn_value));    /* Increments refcount of new pbn. */    r = dc->mdops->inc_refcount(dc->bmd, pbn_new);    /*注意这里需要将pbn_new+,pbn_old-,这样有可能pbn_old减到可回收的可能*/    /* Decrements refcount for old pbn and decrement logical block cnt. */    r = dc->mdops->dec_refcount(dc->bmd, pbn_old);    dc->logical_block_counter--;    /* On all successful steps increment overwrite count. */    dc->overwrites++;  /*这里是overwrites++,和上面的newwrites不一样*/    goto out;/* Error handling code path. */dec_refcount_err:    /* Undo actions taken while incrementing refcount of new pbn. */    ret = dc->mdops->dec_refcount(dc->bmd, pbn_new);inc_refcount_err:    ret = dc->kvs_hash_pbn->kvs_delete(dc->kvs_hash_pbn, (void *)hash,                       dc->crypto_key_size);kvs_insert_err:    /* Undo actions taken in alloc_pbnblk_and_insert_lbn_pbn. */    ret = dc->kvs_lbn_pbn->kvs_delete(dc->kvs_lbn_pbn, (void *)&lbn,                      sizeof(lbn));    ret = dc->mdops->dec_refcount(dc->bmd, pbn_new);out:    return r;}

3、hash && no lbn

即:① compute_hash_bio(dc->desc_table, bio, hash); //对bio的data进行hash,获得到hash_pbn
-> ② dc->kvs_hash_pbn->kvs_lookup; //通过hash值,查找对应的hash_pbn_value,也就是pbn。
找到pbn ->③ handle_write_with_hash.[dc->kvs_lbn_pbn->kvs_lookup] //寻找bio的lbn是否存在
没有找到lbn -> ④ handle_write_no_hash.[__handle_no_lbn_pbn_with_hash] //这里到了最终处理函数
既然找到了hash_pbn,就是pbn可以复用的,直接将lbn将pbn关联就行

static int __handle_no_lbn_pbn_with_hash(struct dedup_config *dc,                     struct bio *bio, uint64_t lbn,                     u64 pbn_this,                     struct lbn_pbn_value lbnpbn_value){    int r = 0, ret;    /* Increments refcount of this passed pbn */    r = dc->mdops->inc_refcount(dc->bmd, pbn_this);    if (r < 0)        goto out;    lbnpbn_value.pbn = pbn_this;    /* Insert lbn->pbn_this entry */    r = dc->kvs_lbn_pbn->kvs_insert(dc->kvs_lbn_pbn, (void *)&lbn,                    sizeof(lbn), (void *)&lbnpbn_value,                    sizeof(lbnpbn_value));    if (r < 0)        goto kvs_insert_error;    dc->logical_block_counter++;    bio->bi_status = BLK_STS_OK;    bio_endio(bio);    /*bio完成*/    dc->newwrites++;    goto out;kvs_insert_error:    /* Undo actions taken while incrementing refcount of this pbn. */    ret = dc->mdops->dec_refcount(dc->bmd, pbn_this);out:    return r;}

4、hash && lbn

即:① compute_hash_bio(dc->desc_table, bio, hash); //对bio的data进行hash,获得到hash_pbn
-> ② dc->kvs_hash_pbn->kvs_lookup; //通过hash值,查找对应的hash_pbn_value,也就是pbn。
找到pbn ->③ handle_write_with_hash.[dc->kvs_lbn_pbn->kvs_lookup] //寻找bio的lbn是否存在
找到lbn -> ④ handle_write_no_hash.[__handle_has_lbn_pbn_with_hash] //这里到了最终处理函数
既然找到了hash_pbn和lbn_pbn,这里存在了两种情况:
一、overwrite,也就是hash_pbn的pbn和lbn_pbn是一个。
二、No relationship,也就是这是将一个pbn的内容写到一个新的lbn位置

static int __handle_has_lbn_pbn_with_hash(struct dedup_config *dc,                      struct bio *bio, uint64_t lbn,                      u64 pbn_this,                      struct lbn_pbn_value lbnpbn_value){    int r = 0, ret;    struct lbn_pbn_value this_lbnpbn_value;    u64 pbn_old;    pbn_old = lbnpbn_value.pbn;    /* special case, overwrite same LBN/PBN with same data */    if (pbn_this == pbn_old)        goto out;  /*如果hash_pbn和lbn_pbn不相等,1、增加pbn引用和新lbn和pbn关联*/    /* Increments refcount of this passed pbn */    r = dc->mdops->inc_refcount(dc->bmd, pbn_this);    if (r < 0)        goto out;    this_lbnpbn_value.pbn = pbn_this;    /* Insert lbn->pbn_this entry */    r = dc->kvs_lbn_pbn->kvs_insert(dc->kvs_lbn_pbn, (void *)&lbn,                    sizeof(lbn),                    (void *)&this_lbnpbn_value,                    sizeof(this_lbnpbn_value));    if (r < 0)        goto kvs_insert_err;  /*减小lbn之前记住的pbn_old的引用,这个pbn_old将可能被回收*/    /* Decrement refcount of old pbn */    r = dc->mdops->dec_refcount(dc->bmd, pbn_old);    if (r < 0)        goto dec_refcount_err;    goto out;   /* all OK */dec_refcount_err:    /* Undo actions taken while decrementing refcount of old pbn */    /* Overwrite lbn->pbn_this entry with lbn->pbn_old entry */    ret = dc->kvs_lbn_pbn->kvs_insert(dc->kvs_lbn_pbn, (void *)&lbn,                          sizeof(lbn), (void *)&lbnpbn_value,                      sizeof(lbnpbn_value));    if (ret < 0)        DMERR("Error in overwriting lbn->pbn_this [%llu] with"              " lbn-pbn_old entry [%llu].", this_lbnpbn_value.pbn,              lbnpbn_value.pbn);kvs_insert_err:    ret = dc->mdops->dec_refcount(dc->bmd, pbn_this);    if (ret < 0)        DMERR("Error in decrementing previously incremented refcount.");out:    if (r == 0) {        bio->bi_status = BLK_STS_OK;        bio_endio(bio);        dc->overwrites++;    }    return r;}

这一篇介绍了,写流程的四种情况,更加清晰了解释了dm dedup设计一文中的流程图。

希望读者看完后,能够对dm dedup这种简单逻辑的方式所吸引,从而喜欢上块重删这个技术。

--------------未完待续--------------

【本文只在51cto博客作者 “底层存储技术” 个人发布,公众号发布:存储之谷】,如需转载,请于本人联系,谢谢。

转载于:https://blog.51cto.com/12580077/2311649

你可能感兴趣的文章
数据结构及算法基础--快速排序(Quick Sort)(二)优化问题
查看>>
你对position的了解到底有多少?
查看>>
随笔2013/2/19
查看>>
Windows Phone的Silverlight Toolkit 安装及其使用
查看>>
DBS:同学录
查看>>
Mysql备份系列(1)--备份方案总结性梳理
查看>>
[CareerCup] 1.6 Rotate Image 翻转图像
查看>>
jQuery中$.fn的用法示例介绍
查看>>
Python中的画图初体验
查看>>
Java程序员的日常 —— 响应式导航Demo
查看>>
objective-c内存管理基础
查看>>
sap关于价值串的说法(转载)
查看>>
采购申请转采购订单错误:在语言EN中没有维护短文本(请重维护物料460300080)
查看>>
Migration to S/4HANA
查看>>
sed 对目录进行操作
查看>>
什么是代码
查看>>
洛谷P2891 [USACO07OPEN]吃饭Dining
查看>>
Web 性能优化
查看>>
webpack最简单的入门教程里bundle.js之运行单步调试的原理解析
查看>>
如何安装Virtual Box的VBox Guest Additions扩展程序
查看>>