在阅读drivers/md/raid5.c时发现关于stripe_head的管理,做的很好,值得借鉴。
释放stripe_head时:
static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
{
BUG_ON(!list_empty(&sh->lru));
BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
..............
} else {
BUG_ON(stripe_operations_active(sh));
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
if (atomic_dec_return(&conf->preread_active_stripes)
< IO_THRESHOLD)
md_wakeup_thread(conf->mddev->thread);
atomic_dec(&conf->active_stripes);
if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
list_add_tail(&sh->lru, &conf->inactive_list);
wake_up(&conf->wait_for_stripe);
if (conf->retry_read_aligned)
md_wakeup_thread(conf->mddev->thread);
}
}
}
最开始时,我还想在list_add_tail 后下加remove_hash。但是重新阅读get_active_stripe时发现这里的用处。
get_active_stripe(struct r5conf *conf, sector_t sector,
int previous, int noblock, int noquiesce)
{
struct stripe_head *sh;
pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
spin_lock_irq(&conf->device_lock);
do {
wait_event_lock_irq(conf->wait_for_stripe,
conf->quiesce == 0 || noquiesce,
conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector, conf->generation - previous);
if (!sh) {
if (!conf->inactive_blocked)
sh = get_free_stripe(conf);
if (noblock && sh == NULL)
>>__find_stripe函数就搜寻hash表中是否曾经有stripe,如果有那么,可以使用就直接使用,而找不到从inactive_list中分配。
当然__find_stripe得到的stripe是从active_list和inactive_list中得到。
如果在释放时,remove_hash,那么find_stripe就不会获取到。这里不光会浪费有些属性的配置,而是某些数据。
举例:对某个文件的元数据经常写,但是又不满条写,如果按照这种情况。就可以命中,不需要额外去其他磁盘相关数据。这样性能就会提高。
>>或许可以展开,对某些stripe进行pin。保证这些stripe不会被释放出去,从而保证性能。后续会进行研究下,特别对文件系统的metadata。