diff options
| author | Song Liu <songliubraving@fb.com> | 2017-01-12 20:22:41 -0500 |
|---|---|---|
| committer | Shaohua Li <shli@fb.com> | 2017-01-24 14:20:14 -0500 |
| commit | 86aa1397ddfde563b3692adadb8b8e32e97b4e5e (patch) | |
| tree | 866e94b5411650b70561ea663ce3680a6d4a364f | |
| parent | d46d29f072accb069cb42b5fbebcc77d9094a785 (diff) | |
md/r5cache: read data into orig_page for prexor of cached data
With write back cache, we use orig_page to do prexor. This patch
makes sure we read data into orig_page for it.
Flag R5_OrigPageUPTDODATE is added to show whether orig_page
has the latest data from raid disk.
We introduce a helper function uptodate_for_rmw() to simplify
the a couple conditions in handle_stripe_dirtying().
Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Shaohua Li <shli@fb.com>
| -rw-r--r-- | drivers/md/raid5-cache.c | 2 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 44 | ||||
| -rw-r--r-- | drivers/md/raid5.h | 5 |
3 files changed, 42 insertions, 9 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index e0d6dd1835d0..95dcaa022e1f 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c | |||
| @@ -2349,6 +2349,8 @@ void r5c_release_extra_page(struct stripe_head *sh) | |||
| 2349 | struct page *p = sh->dev[i].orig_page; | 2349 | struct page *p = sh->dev[i].orig_page; |
| 2350 | 2350 | ||
| 2351 | sh->dev[i].orig_page = sh->dev[i].page; | 2351 | sh->dev[i].orig_page = sh->dev[i].page; |
| 2352 | clear_bit(R5_OrigPageUPTDODATE, &sh->dev[i].flags); | ||
| 2353 | |||
| 2352 | if (!using_disk_info_extra_page) | 2354 | if (!using_disk_info_extra_page) |
| 2353 | put_page(p); | 2355 | put_page(p); |
| 2354 | } | 2356 | } |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 36c13e4be9c9..7780ae44f355 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -1015,7 +1015,17 @@ again: | |||
| 1015 | 1015 | ||
| 1016 | if (test_bit(R5_SkipCopy, &sh->dev[i].flags)) | 1016 | if (test_bit(R5_SkipCopy, &sh->dev[i].flags)) |
| 1017 | WARN_ON(test_bit(R5_UPTODATE, &sh->dev[i].flags)); | 1017 | WARN_ON(test_bit(R5_UPTODATE, &sh->dev[i].flags)); |
| 1018 | sh->dev[i].vec.bv_page = sh->dev[i].page; | 1018 | |
| 1019 | if (!op_is_write(op) && | ||
| 1020 | test_bit(R5_InJournal, &sh->dev[i].flags)) | ||
| 1021 | /* | ||
| 1022 | * issuing read for a page in journal, this | ||
| 1023 | * must be preparing for prexor in rmw; read | ||
| 1024 | * the data into orig_page | ||
| 1025 | */ | ||
| 1026 | sh->dev[i].vec.bv_page = sh->dev[i].orig_page; | ||
| 1027 | else | ||
| 1028 | sh->dev[i].vec.bv_page = sh->dev[i].page; | ||
| 1019 | bi->bi_vcnt = 1; | 1029 | bi->bi_vcnt = 1; |
| 1020 | bi->bi_io_vec[0].bv_len = STRIPE_SIZE; | 1030 | bi->bi_io_vec[0].bv_len = STRIPE_SIZE; |
| 1021 | bi->bi_io_vec[0].bv_offset = 0; | 1031 | bi->bi_io_vec[0].bv_offset = 0; |
| @@ -2380,6 +2390,13 @@ static void raid5_end_read_request(struct bio * bi) | |||
| 2380 | } else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) | 2390 | } else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) |
| 2381 | clear_bit(R5_ReadNoMerge, &sh->dev[i].flags); | 2391 | clear_bit(R5_ReadNoMerge, &sh->dev[i].flags); |
| 2382 | 2392 | ||
| 2393 | if (test_bit(R5_InJournal, &sh->dev[i].flags)) | ||
| 2394 | /* | ||
| 2395 | * end read for a page in journal, this | ||
| 2396 | * must be preparing for prexor in rmw | ||
| 2397 | */ | ||
| 2398 | set_bit(R5_OrigPageUPTDODATE, &sh->dev[i].flags); | ||
| 2399 | |||
| 2383 | if (atomic_read(&rdev->read_errors)) | 2400 | if (atomic_read(&rdev->read_errors)) |
| 2384 | atomic_set(&rdev->read_errors, 0); | 2401 | atomic_set(&rdev->read_errors, 0); |
| 2385 | } else { | 2402 | } else { |
| @@ -3594,6 +3611,21 @@ unhash: | |||
| 3594 | break_stripe_batch_list(head_sh, STRIPE_EXPAND_SYNC_FLAGS); | 3611 | break_stripe_batch_list(head_sh, STRIPE_EXPAND_SYNC_FLAGS); |
| 3595 | } | 3612 | } |
| 3596 | 3613 | ||
| 3614 | /* | ||
| 3615 | * For RMW in write back cache, we need extra page in prexor to store the | ||
| 3616 | * old data. This page is stored in dev->orig_page. | ||
| 3617 | * | ||
| 3618 | * This function checks whether we have data for prexor. The exact logic | ||
| 3619 | * is: | ||
| 3620 | * R5_UPTODATE && (!R5_InJournal || R5_OrigPageUPTDODATE) | ||
| 3621 | */ | ||
| 3622 | static inline bool uptodate_for_rmw(struct r5dev *dev) | ||
| 3623 | { | ||
| 3624 | return (test_bit(R5_UPTODATE, &dev->flags)) && | ||
| 3625 | (!test_bit(R5_InJournal, &dev->flags) || | ||
| 3626 | test_bit(R5_OrigPageUPTDODATE, &dev->flags)); | ||
| 3627 | } | ||
| 3628 | |||
| 3597 | static int handle_stripe_dirtying(struct r5conf *conf, | 3629 | static int handle_stripe_dirtying(struct r5conf *conf, |
| 3598 | struct stripe_head *sh, | 3630 | struct stripe_head *sh, |
| 3599 | struct stripe_head_state *s, | 3631 | struct stripe_head_state *s, |
| @@ -3625,9 +3657,7 @@ static int handle_stripe_dirtying(struct r5conf *conf, | |||
| 3625 | if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx || | 3657 | if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx || |
| 3626 | test_bit(R5_InJournal, &dev->flags)) && | 3658 | test_bit(R5_InJournal, &dev->flags)) && |
| 3627 | !test_bit(R5_LOCKED, &dev->flags) && | 3659 | !test_bit(R5_LOCKED, &dev->flags) && |
| 3628 | !((test_bit(R5_UPTODATE, &dev->flags) && | 3660 | !(uptodate_for_rmw(dev) || |
| 3629 | (!test_bit(R5_InJournal, &dev->flags) || | ||
| 3630 | dev->page != dev->orig_page)) || | ||
| 3631 | test_bit(R5_Wantcompute, &dev->flags))) { | 3661 | test_bit(R5_Wantcompute, &dev->flags))) { |
| 3632 | if (test_bit(R5_Insync, &dev->flags)) | 3662 | if (test_bit(R5_Insync, &dev->flags)) |
| 3633 | rmw++; | 3663 | rmw++; |
| @@ -3639,7 +3669,6 @@ static int handle_stripe_dirtying(struct r5conf *conf, | |||
| 3639 | i != sh->pd_idx && i != sh->qd_idx && | 3669 | i != sh->pd_idx && i != sh->qd_idx && |
| 3640 | !test_bit(R5_LOCKED, &dev->flags) && | 3670 | !test_bit(R5_LOCKED, &dev->flags) && |
| 3641 | !(test_bit(R5_UPTODATE, &dev->flags) || | 3671 | !(test_bit(R5_UPTODATE, &dev->flags) || |
| 3642 | test_bit(R5_InJournal, &dev->flags) || | ||
| 3643 | test_bit(R5_Wantcompute, &dev->flags))) { | 3672 | test_bit(R5_Wantcompute, &dev->flags))) { |
| 3644 | if (test_bit(R5_Insync, &dev->flags)) | 3673 | if (test_bit(R5_Insync, &dev->flags)) |
| 3645 | rcw++; | 3674 | rcw++; |
| @@ -3693,9 +3722,7 @@ static int handle_stripe_dirtying(struct r5conf *conf, | |||
| 3693 | i == sh->pd_idx || i == sh->qd_idx || | 3722 | i == sh->pd_idx || i == sh->qd_idx || |
| 3694 | test_bit(R5_InJournal, &dev->flags)) && | 3723 | test_bit(R5_InJournal, &dev->flags)) && |
| 3695 | !test_bit(R5_LOCKED, &dev->flags) && | 3724 | !test_bit(R5_LOCKED, &dev->flags) && |
| 3696 | !((test_bit(R5_UPTODATE, &dev->flags) && | 3725 | !(uptodate_for_rmw(dev) || |
| 3697 | (!test_bit(R5_InJournal, &dev->flags) || | ||
| 3698 | dev->page != dev->orig_page)) || | ||
| 3699 | test_bit(R5_Wantcompute, &dev->flags)) && | 3726 | test_bit(R5_Wantcompute, &dev->flags)) && |
| 3700 | test_bit(R5_Insync, &dev->flags)) { | 3727 | test_bit(R5_Insync, &dev->flags)) { |
| 3701 | if (test_bit(STRIPE_PREREAD_ACTIVE, | 3728 | if (test_bit(STRIPE_PREREAD_ACTIVE, |
| @@ -3722,7 +3749,6 @@ static int handle_stripe_dirtying(struct r5conf *conf, | |||
| 3722 | i != sh->pd_idx && i != sh->qd_idx && | 3749 | i != sh->pd_idx && i != sh->qd_idx && |
| 3723 | !test_bit(R5_LOCKED, &dev->flags) && | 3750 | !test_bit(R5_LOCKED, &dev->flags) && |
| 3724 | !(test_bit(R5_UPTODATE, &dev->flags) || | 3751 | !(test_bit(R5_UPTODATE, &dev->flags) || |
| 3725 | test_bit(R5_InJournal, &dev->flags) || | ||
| 3726 | test_bit(R5_Wantcompute, &dev->flags))) { | 3752 | test_bit(R5_Wantcompute, &dev->flags))) { |
| 3727 | rcw++; | 3753 | rcw++; |
| 3728 | if (test_bit(R5_Insync, &dev->flags) && | 3754 | if (test_bit(R5_Insync, &dev->flags) && |
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index ed8e1362ab36..461df197d157 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
| @@ -322,6 +322,11 @@ enum r5dev_flags { | |||
| 322 | * data and parity being written are in the journal | 322 | * data and parity being written are in the journal |
| 323 | * device | 323 | * device |
| 324 | */ | 324 | */ |
| 325 | R5_OrigPageUPTDODATE, /* with write back cache, we read old data into | ||
| 326 | * dev->orig_page for prexor. When this flag is | ||
| 327 | * set, orig_page contains latest data in the | ||
| 328 | * raid disk. | ||
| 329 | */ | ||
| 325 | }; | 330 | }; |
| 326 | 331 | ||
| 327 | /* | 332 | /* |
