flashcache之创建

在flashcache_conf.c中,可以看到flashcache_target结构体是这样定义的,其中ctr被赋值为flashcache_ctr,所以flashcache的创建函数为flashcache_ctr
static struct target_type flashcache_target = {
    .name   = "flashcache",
    .version= {1, 0, 4},
    .module = THIS_MODULE,
    .ctr    = flashcache_ctr,
    .dtr    = flashcache_dtr,
    .map    = flashcache_map,
    .status = flashcache_status,
    .ioctl  = flashcache_ioctl,
    .iterate_devices = flashcache_iterate_devices,
};

且先不看flashcache_ctr为reload所做的一些操作,直接来看创建writeback模式的flashcache

if (dmc->cache_mode == FLASHCACHE_WRITE_BACK) { 
        if (persistence == CACHE_CREATE) {
            if (flashcache_writeback_create(dmc, 0)) {
                ti->error = "flashcache: Cache Create Failed";
                r = -EINVAL;
                goto bad3;
            }
        } else {
            if (flashcache_writeback_create(dmc, 1)) {
                ti->error = "flashcache: Cache Force Create Failed";
                r = -EINVAL;
                goto bad3;
            }
        }
    } else
        flashcache_writethrough_create(dmc);
注意上面的代码是在dmc处理了用户定义的变量后,才开始执行的。其中flashcache_writeback_create(dmc, 0)是创建写回模式的flashcache函数,具体来看里面的代码:
    where.bdev = dmc->cache_dev->bdev;
    where.sector = 0;
    where.count = dmc->md_block_size;
从这里看出该函数似乎希望从flash的第0块上读到什么东西,也就是说,flashcache的超级块是存在第0块上的,因为该函数是创建函数,所以读出的数据应该无法有意义的对应到flashcache的超级块结构体上。但是如果读到了什么有意义的数据,会报错:
DMERR("flashcache_writeback_create: Existing Cache Detected, use force to re-create");
接下来是对flashcache元数据块和数据区总块数的初始化。
    dmc->md_blocks = INDEX_TO_MD_BLOCK(dmc, dmc->size / dmc->block_size) + 1 + 1;
    dmc->size -= dmc->md_blocks * MD_SECTORS_PER_BLOCK(dmc);    /* total sectors available for cache */
    dmc->size /= dmc->block_size;
    dmc->size = (dmc->size / dmc->assoc) * dmc->assoc;  
    dmc->md_blocks = INDEX_TO_MD_BLOCK(dmc, dmc->size) + 1 + 1;

上面第一行代码执行时,dmc->block_size的大小是总的sector的个数,所以除以一个块的扇区个数,来算该cache的总块数,并计算其应对应的元数据块所在的索引,即约为元数据块的最大索引,注意这里这么算的话,因为flashcache肯定是要把一部分给元数据块,一部分给数据区,这样算出来的数据区肯定是偏大的,但是这么算方便。不然我认为正好要求元数据块对应于数据区,可能有点不好处理,注意这里的两次加一操作,我认为一次是加上超级快,另外一次是把索引变为个数,因为这里md_blocks是指元数据块的个数。接着dmc->size除掉了元数据块所占的大小,且保证数据区每一个组中都有assoc个块。并在最后重新计算了md_blocks.

因为要在内存中对这些数据进行管理,必然要申请相应的空间,代码如下:

    order = dmc->size * sizeof(struct cacheblock);
    dmc->cache = (struct cacheblock *)vmalloc(order);

接着对每一个cacheblock进行了一些初始化工作。
初始化完毕后,因为现在metadata还在内存中,所以需要把同步到SSD上,所以需要进行同步工作。

for (i = 0 ; i < dmc->size ; i++) {
        next_ptr->dbn = dmc->cache[i].dbn;
        next_ptr->cache_state = dmc->cache[i].cache_state & 
            (INVALID | VALID | DIRTY);
        next_ptr++;
        slots_written++;
        j--;
        if (j == 0) {
            /* * Filled the block, write and goto the next metadata block. */
            if (slots_written == MD_SLOTS_PER_BLOCK(dmc) * METADATA_IO_NUM_BLOCKS(dmc)) {
                /* * Wrote out an entire metadata IO block, write the block to the ssd. */
                where.count = (slots_written / MD_SLOTS_PER_BLOCK(dmc)) * MD_SECTORS_PER_BLOCK(dmc);
                slots_written = 0;
                sectors_written += where.count; /* debug */
                error = flashcache_dm_io_sync_vm(dmc, &where, WRITE, 
                                 meta_data_cacheblock);
                if (error) {
                    vfree((void *)header);
                    vfree((void *)meta_data_cacheblock);
                    vfree(dmc->cache);
                    DMERR("flashcache_writeback_create: Could not write cache metadata block %lu error %d !",
                          where.sector, error);
                    return 1;
                }
                where.sector += where.count;    /* Advance offset */
            }
            /* Move next slot pointer into next metadata block */
            next_ptr = (struct flash_cacheblock *)
                ((caddr_t)meta_data_cacheblock + ((slots_written / MD_SLOTS_PER_BLOCK(dmc)) * MD_BLOCK_BYTES(dmc)));
            j = MD_SLOTS_PER_BLOCK(dmc);
        }
    }
这里就进入了一个for循环,即把每一个元数据都要同步到SSD上。虽然j = MD_SLOTS_PER_BLOCK(dmc);但是向SSD一次写入的量为MD_SLOTS_PER_BLOCK(dmc) * METADATA_IO_NUM_BLOCKS(dmc)。所以每次j==0时,并不意味着可以向SSD写了,而是要移动到下一个元数据块上。但是不能简单的靠++,因为一个元数据块的大小无法被flash_cacheblock的大小整除,所以需要进行取整运算。当积累够了一次写入的量后,可以error = flashcache_dm_io_sync_vm(dmc, &where, WRITE, meta_data_cacheblock);这里meta_data_cacheblock会向后移动where.count个字节。因为一次写入的量不与MD_SLOTS_PER_BLOCK(dmc)相等,所以跳出循环后可能出现这样的情况if (next_ptr != meta_data_cacheblock) ,需要处理剩下的部分。
最后一些代码就是对超级快的初始化,并写入SSD.
从中可以看出flashcache上的布局为超级快|元数据块|元数据块|...|数据块|...|数据块|...

你可能感兴趣的:(flashcache之创建)