2.3.2 下发写请求【RAID5 IO处理之replace代码详解】函数调用关系:
handle_stripe() \_ analyse_stripe() \_ ops_run_io()
代码逻辑如下:
static void handle_stripe(struct stripe_head *sh){ /* 解析条带状态 */ analyse_stripe(sh, &s); /* 在fetch_block中设置了replacement的条带已经是最新数据* R5_UPTODATE条件为真,所以不会设置任何新的需要读取*/ if (s.to_read || s.non_overwrite|| (conf->level == 6 && s.to_write && s.failed)|| (s.syncing && (s.uptodate + s.compute < disks))|| s.replacing|| s.expanding)handle_stripe_fill(sh, &s, disks); /* replacing在analyse_stripe设置* 未下发新的读请求locked为真* 条带同步状态再第一轮中清除* 进入if*/ if (s.replacing && s.locked == 0&& !test_bit(STRIPE_INSYNC, &sh->state)) {for (i = 0; i < conf->raid_disks; i++)/* 读成功后R5_UPTODATE为真,R5_WantReplace在analyse_stripe中设置 */if (test_bit(R5_UPTODATE, &sh->dev[i].flags) &&test_bit(R5_NeedReplace, &sh->dev[i].flags)) {/* 设置R5_WantReplace标记在下发写请求时判断 */set_bit(R5_WantReplace, &sh->dev[i].flags);/* 设置R5_LOCKED标记表明条带/设备准备调度IO */set_bit(R5_LOCKED, &sh->dev[i].flags);/* 自增locked计数 */s.locked++;}/* 将条带设置为同步状态 */set_bit(STRIPE_INSYNC, &sh->state); } /* 上个if中locked自增不进入if */ if ((s.syncing || s.replacing) && s.locked == 0 &&test_bit(STRIPE_INSYNC, &sh->state)) {md_done_sync(conf->mddev, STRIPE_SECTORS, 1);clear_bit(STRIPE_SYNCING, &sh->state);if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags))wake_up(&conf->wait_for_overlap); } /* 下发写请求 */ ops_run_io(sh, &s);}/* 和上轮一轮不在赘述 */analyse_stripe()static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s){ struct r5conf *conf = sh->raid_conf; int i, disks = sh->disks; might_sleep(); /* 遍历所有条带/设备 */ for (i = disks; i--; ) {if (test_and_clear_bit(R5_WantReplace, &sh->dev[i].flags)) {rw = WRITE;replace_only = 1;}bi = &sh->dev[i].req;rbi = &sh->dev[i].rreq; /* For writing to replacement */rcu_read_lock();rrdev = rcu_dereference(conf->disks[i].replacement);smp_mb(); /* Ensure that if rrdev is NULL, rdev won't be */rdev = rcu_dereference(conf->disks[i].rdev);if (rw & WRITE) {/* 将rdev标空后只能使用rrdev */if (replace_only)rdev = NULL;}rcu_read_unlock();/* 使用rbi向rrdev下发写请求 */if (rrdev) {set_bit(STRIPE_IO_STARTED, &sh->state);bio_reset(rbi);rbi->bi_bdev = rrdev->bdev;rbi->bi_rw = rw;BUG_ON(!(rw & WRITE));rbi->bi_end_io = raid5_end_write_request;rbi->bi_private = sh;atomic_inc(&sh->count);if (use_new_offset(conf, sh))rbi->bi_sector = (sh->sector + rrdev->new_data_offset);elserbi->bi_sector = (sh->sector + rrdev->data_offset);rbi->bi_vcnt = 1;rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;rbi->bi_io_vec[0].bv_offset = 0;rbi->bi_size = STRIPE_SIZE;generic_make_request(rbi);} }}
2.3.3 完成函数调用关系:
handle_stripe() \_ md_done_sync()
代码逻辑如下:
static void handle_stripe(struct stripe_head *sh){ /* 解析条带状态 */ analyse_stripe(sh, &s); /* 在fetch_block中设置了replacement的条带已经是最新数据* R5_UPTODATE条件为真,所以不会设置任何新的需要读取*/ if (s.to_read || s.non_overwrite|| (conf->level == 6 && s.to_write && s.failed)|| (s.syncing && (s.uptodate + s.compute < disks))|| s.replacing|| s.expanding)handle_stripe_fill(sh, &s, disks); /* replacing在analyse_stripe设置* 未下发新的读请求locked为真* STRIPE_INSYNC在上轮处理中设置,本轮不在进入if*/ if (s.replacing && s.locked == 0&& !test_bit(STRIPE_INSYNC, &sh->state)) {/* Write out to replacement devices where possible */for (i = 0; i < conf->raid_disks; i++)if (test_bit(R5_UPTODATE, &sh->dev[i].flags) &&test_bit(R5_NeedReplace, &sh->dev[i].flags)) {set_bit(R5_WantReplace, &sh->dev[i].flags);set_bit(R5_LOCKED, &sh->dev[i].flags);s.locked++;}set_bit(STRIPE_INSYNC, &sh->state); } /* replacing、locked、STRIPE_INSYNC条件都成立 */ if ((s.syncing || s.replacing) && s.locked == 0 &&test_bit(STRIPE_INSYNC, &sh->state)) {md_done_sync(conf->mddev, STRIPE_SECTORS, 1);clear_bit(STRIPE_SYNCING, &sh->state); }}void md_done_sync(struct mddev *mddev, int blocks, int ok){ /* 自增完成计数 */ atomic_sub(blocks, &mddev->recovery_active); /* 通知同步前程继续进行 */ wake_up(&mddev->recovery_wait); if (!ok) {set_bit(MD_RECOVERY_INTR, &mddev->recovery);set_bit(MD_RECOVERY_ERROR, &mddev->recovery);md_wakeup_thread(mddev->thread); }}
至此一个条带的同步流程分析完毕 。
推荐阅读
- RAID5 IO处理之重构代码详解
- Linux Block模块之deadline调度算法代码解析
- Linux Block模块之IO合并代码解析
- 【强烈推荐】用glob库的一行命令显著加速批量读取处理数据
- redis bitmap数据结构之java对等操作
- 一加9r参数_一加9r搭载什么处理器
- 苹果处理器a11a12区别_苹果处理器a11和a12区别大吗
- 奔腾处理器和i5哪个好-英特尔奔腾处理器和酷睿i5处理器哪个好
- 云原生时代的DevOps平台设计之道
- 猫之城剧情全结局怎么做