flashcache之hash

flashcache用到了很多hash函数,比如:

flashcache之hash_block

dmc->size表示flashcache中block的数目,而在flashcache_ctr中:
    dmc->assoc_shift = ffs(dmc->assoc) - 1;
因为dmc->assoc表示一个set中块的数目,那么dmc->assoc_shift则表示dmc->assoc二进制形式中0的个数。这样可以使用位运算加快除法速度。也就是说: 
num_cache_sets = dmc->size >> dmc->assoc_shift;是flashcache中的set数目。
因为我使用的版本是flashcache 3.1.1,所以来看else子句
    value = (unsigned long) (dbn >> dmc->disk_assoc_shift);
    /* Then place it in a random set */
    value = jhash_1word(value, 0xbeef);
这里的value = (unsigned long) (dbn >> dmc->disk_assoc_shift);相当于
value = (unsigned long) (dbn / dmc->disk_assoc);所以来看看jhash_1word做了啥:
170 static inline u32 jhash_1word(u32 a, u32 initval)
171 {
172         return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2));
173 }
其中调用了__jhash_nwords(value, 0, 0, 0xbeef + JHASH_INITVAL + (1 << 2)); 其中JHASH_INITVAL被初始化为任意值:
 57 /* An arbitrary initial parameter */
 58 #define JHASH_INITVAL           0xdeadbeef
而在__jhash_nwords函数中,
149 static inline u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval)
150 {
151         a += initval;
152         b += initval;
153         c += initval;
154 
155         __jhash_final(a, b, c);
156 
157         return c;
158 }
又调用了 __jhash_final(value+initval, initval, initval); 在该函数中,进行了奇怪的运算:
 45 /* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
 46 #define __jhash_final(a, b, c)                  \
 47 {                                               \
 48         c ^= b; c -= rol32(b, 14);              \
 49         a ^= c; a -= rol32(c, 11);              \
 50         b ^= a; b -= rol32(a, 25);              \
 51         c ^= b; c -= rol32(b, 16);              \
 52         a ^= c; a -= rol32(c, 4);               \
 53         b ^= a; b -= rol32(a, 14);              \
 54         c ^= b; c -= rol32(b, 24);              \
 55 }
好吧,来看看rol32函数,应该是不会用到随机函数,不然以后每次相同的dbn找的cache block岂不是不相同:
103 /**
104  * rol32 - rotate a 32-bit value left
105  * @word: value to rotate
106  * @shift: bits to roll
107  */
108 static inline __u32 rol32(__u32 word, unsigned int shift)
109 {
110         return (word << shift) | (word >> ((-shift) & 31));
111 }
112 
113 /**
果然不是什么随机函数,只是一些位运算罢了,从这里可以印证出每次相同的dbn找的cache block是相同的。
注意hash_block末尾的这句话set_number = value % num_cache_sets;
加上前面的value = (unsigned long) (dbn >> dmc->disk_assoc_shift);印证了flashcache-doc.txt的这句话: 
target set = (dbn / block size / set size) mod (number of sets),但是好像这句话有点老,因为在if语句里面才是完全符合这句话:
value = (unsigned long)(dbn >> (dmc->block_shift + dmc->assoc_shift));

flashcache之flashcache_hash_insert

flashcache在每个cache_set内部还维护了一个hash表,这个hash表上存的都是有效cache block,
为了方便以后的查找,在flashcache_ctr函数中有这么几句代码:

    for (i = 0 ; i < dmc->size ; i++) {
        dmc->cache[i].hash_prev = FLASHCACHE_NULL;
        dmc->cache[i].hash_next = FLASHCACHE_NULL;
        if (dmc->cache[i].cache_state & VALID) {
            flashcache_hash_insert(dmc, i);
            atomic_inc(&dmc->cached_blocks);
        }
        if (dmc->cache[i].cache_state & DIRTY) {
            dmc->cache_sets[i / dmc->assoc].nr_dirty++;
            atomic_inc(&dmc->nr_dirty);
        }
        if (dmc->cache[i].cache_state & INVALID)
            flashcache_invalid_insert(dmc, i);
    }

其中来看看flashcache_hash_insert(dmc, i);当然,这个函数在别的地方也有调用。因为这个函数是为了
把Cache的块放入到hash表中。再来看看该函数:(删掉了无关紧要的VERIFY)

    void
flashcache_hash_insert(struct cache_c *dmc, 
               int index)
{
    struct cache_set *cache_set = &dmc->cache_sets[index / dmc->assoc];
    struct cacheblock *cacheblk;
    u_int16_t *hash_bucket;
    u_int16_t set_ix = index % dmc->assoc;
    int start_index = (index / dmc->assoc) * dmc->assoc;
    cacheblk = &dmc->cache[index];
    hash_bucket = flashcache_get_hash_bucket(dmc, cache_set, cacheblk->dbn);
    cacheblk->hash_prev = FLASHCACHE_NULL;
    cacheblk->hash_next = *hash_bucket;
    if (*hash_bucket != FLASHCACHE_NULL)
        dmc->cache[start_index + *hash_bucket].hash_prev = set_ix;
    *hash_bucket = set_ix;
}

后续如果有对应的hash值,hash到某个hash_buckets内的元素的链表上,就需要把该block的set内的index值进行记录。而该block也以头插法插入到该链表上,即hash_bucket = set_ix;整个就是一个hash避免冲突的拉链法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值