summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshli@kernel.org <shli@kernel.org>2014-12-15 12:57:04 +1100
committerNeilBrown <neilb@suse.de>2015-04-22 08:00:41 +1000
commitdabc4ec6ba72418ebca6bf1884f344bba40c8709 (patch)
tree7860792d9a7b5043c043eea983d218591bbe06f5
parent72ac733015bbdc0356ba3e92c52137a265910a91 (diff)
raid5: handle expansion/resync case with stripe batching
expansion/resync can grab a stripe when the stripe is in batch list. Since all stripes in batch list must be in the same state, we can't allow some stripes run into expansion/resync. So we delay expansion/resync for stripe in batch list. Signed-off-by: Shaohua Li <shli@fusionio.com> Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/raid5.c24
-rw-r--r--drivers/md/raid5.h5
2 files changed, 21 insertions, 8 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 54f3cb312b42..3ae097d50b51 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3440,8 +3440,10 @@ unhash:
struct stripe_head, batch_list);
list_del_init(&sh->batch_list);
- sh->state = head_sh->state & (~((1 << STRIPE_ACTIVE) |
- (1 << STRIPE_PREREAD_ACTIVE)));
+ set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG,
+ head_sh->state & ~((1 << STRIPE_ACTIVE) |
+ (1 << STRIPE_PREREAD_ACTIVE) |
+ STRIPE_EXPAND_SYNC_FLAG));
sh->check_state = head_sh->check_state;
sh->reconstruct_state = head_sh->reconstruct_state;
for (i = 0; i < sh->disks; i++) {
@@ -3453,6 +3455,8 @@ unhash:
spin_lock_irq(&sh->stripe_lock);
sh->batch_head = NULL;
spin_unlock_irq(&sh->stripe_lock);
+ if (sh->state & STRIPE_EXPAND_SYNC_FLAG)
+ set_bit(STRIPE_HANDLE, &sh->state);
release_stripe(sh);
}
@@ -3460,6 +3464,8 @@ unhash:
head_sh->batch_head = NULL;
spin_unlock_irq(&head_sh->stripe_lock);
wake_up_nr(&conf->wait_for_overlap, wakeup_nr);
+ if (head_sh->state & STRIPE_EXPAND_SYNC_FLAG)
+ set_bit(STRIPE_HANDLE, &head_sh->state);
}
static void handle_stripe_dirtying(struct r5conf *conf,
@@ -3927,8 +3933,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
memset(s, 0, sizeof(*s));
- s->expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
- s->expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+ s->expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state) && !sh->batch_head;
+ s->expanded = test_bit(STRIPE_EXPAND_READY, &sh->state) && !sh->batch_head;
s->failed_num[0] = -1;
s->failed_num[1] = -1;
@@ -4150,9 +4156,11 @@ static void check_break_stripe_batch_list(struct stripe_head *sh)
struct stripe_head, batch_list);
list_del_init(&sh->batch_list);
- sh->state = head_sh->state & ~((1 << STRIPE_ACTIVE) |
- (1 << STRIPE_PREREAD_ACTIVE) |
- (1 << STRIPE_DEGRADED));
+ set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG,
+ head_sh->state & ~((1 << STRIPE_ACTIVE) |
+ (1 << STRIPE_PREREAD_ACTIVE) |
+ (1 << STRIPE_DEGRADED) |
+ STRIPE_EXPAND_SYNC_FLAG));
sh->check_state = head_sh->check_state;
sh->reconstruct_state = head_sh->reconstruct_state;
for (i = 0; i < sh->disks; i++)
@@ -4194,7 +4202,7 @@ static void handle_stripe(struct stripe_head *sh)
check_break_stripe_batch_list(sh);
- if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+ if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) && !sh->batch_head) {
spin_lock(&sh->stripe_lock);
/* Cannot process 'sync' concurrently with 'discard' */
if (!test_bit(STRIPE_DISCARD, &sh->state) &&
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index cf3562e99440..ee65ed844d3f 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -339,6 +339,11 @@ enum {
STRIPE_BATCH_ERR,
};
+#define STRIPE_EXPAND_SYNC_FLAG \
+ ((1 << STRIPE_EXPAND_SOURCE) |\
+ (1 << STRIPE_EXPAND_READY) |\
+ (1 << STRIPE_EXPANDING) |\
+ (1 << STRIPE_SYNC_REQUESTED))
/*
* Operation request flags
*/