device-mapper 块级重删(d

发布时间:2019-07-12 10:01:08编辑:auto阅读(1412)

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

    上一篇我们来介绍了dm dedup的空间管理
    这一篇我们介绍核心流程I/O写流程

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

    要看的特别清楚这部分的内容,需要结合我之前写过的《device-mapper 块级重删(dm dedup) <2>设计》请添加链接描述一起学习。

    在块级重删 设计那一篇已经描述了这一系列的过程。
    上一篇代码结构已经对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 个人发布,公众号发布:存储之谷】,如需转载,请于本人联系,谢谢。

关键字

上一篇: Grab RS3gold rs 3 go

下一篇: Earn new rewards & R