RAID5 IO處理之replace代碼詳解( 二 )

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); }}至此一個條帶的同步流程分析完畢 。

推薦閱讀