|
@@ -2689,7 +2689,7 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
|
|
bdevname(rdev->bdev, b),
|
|
bdevname(rdev->bdev, b),
|
|
mdname(mddev),
|
|
mdname(mddev),
|
|
conf->raid_disks - mddev->degraded);
|
|
conf->raid_disks - mddev->degraded);
|
|
- r5c_update_on_rdev_error(mddev);
|
|
|
|
|
|
+ r5c_update_on_rdev_error(mddev, rdev);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -3050,6 +3050,11 @@ sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous)
|
|
* When LOG_CRITICAL, stripes with injournal == 0 will be sent to
|
|
* When LOG_CRITICAL, stripes with injournal == 0 will be sent to
|
|
* no_space_stripes list.
|
|
* no_space_stripes list.
|
|
*
|
|
*
|
|
|
|
+ * 3. during journal failure
|
|
|
|
+ * In journal failure, we try to flush all cached data to raid disks
|
|
|
|
+ * based on data in stripe cache. The array is read-only to upper
|
|
|
|
+ * layers, so we would skip all pending writes.
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
static inline bool delay_towrite(struct r5conf *conf,
|
|
static inline bool delay_towrite(struct r5conf *conf,
|
|
struct r5dev *dev,
|
|
struct r5dev *dev,
|
|
@@ -3063,6 +3068,9 @@ static inline bool delay_towrite(struct r5conf *conf,
|
|
if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
|
|
if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
|
|
s->injournal > 0)
|
|
s->injournal > 0)
|
|
return true;
|
|
return true;
|
|
|
|
+ /* case 3 above */
|
|
|
|
+ if (s->log_failed && s->injournal)
|
|
|
|
+ return true;
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4696,10 +4704,15 @@ static void handle_stripe(struct stripe_head *sh)
|
|
" to_write=%d failed=%d failed_num=%d,%d\n",
|
|
" to_write=%d failed=%d failed_num=%d,%d\n",
|
|
s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
|
|
s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
|
|
s.failed_num[0], s.failed_num[1]);
|
|
s.failed_num[0], s.failed_num[1]);
|
|
- /* check if the array has lost more than max_degraded devices and,
|
|
|
|
|
|
+ /*
|
|
|
|
+ * check if the array has lost more than max_degraded devices and,
|
|
* if so, some requests might need to be failed.
|
|
* if so, some requests might need to be failed.
|
|
|
|
+ *
|
|
|
|
+ * When journal device failed (log_failed), we will only process
|
|
|
|
+ * the stripe if there is data need write to raid disks
|
|
*/
|
|
*/
|
|
- if (s.failed > conf->max_degraded || s.log_failed) {
|
|
|
|
|
|
+ if (s.failed > conf->max_degraded ||
|
|
|
|
+ (s.log_failed && s.injournal == 0)) {
|
|
sh->check_state = 0;
|
|
sh->check_state = 0;
|
|
sh->reconstruct_state = 0;
|
|
sh->reconstruct_state = 0;
|
|
break_stripe_batch_list(sh, 0);
|
|
break_stripe_batch_list(sh, 0);
|
|
@@ -5272,8 +5285,10 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group)
|
|
struct stripe_head *sh, *tmp;
|
|
struct stripe_head *sh, *tmp;
|
|
struct list_head *handle_list = NULL;
|
|
struct list_head *handle_list = NULL;
|
|
struct r5worker_group *wg;
|
|
struct r5worker_group *wg;
|
|
- bool second_try = !r5c_is_writeback(conf->log);
|
|
|
|
- bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state);
|
|
|
|
|
|
+ bool second_try = !r5c_is_writeback(conf->log) &&
|
|
|
|
+ !r5l_log_disk_error(conf);
|
|
|
|
+ bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state) ||
|
|
|
|
+ r5l_log_disk_error(conf);
|
|
|
|
|
|
again:
|
|
again:
|
|
wg = NULL;
|
|
wg = NULL;
|
|
@@ -7521,7 +7536,9 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
|
|
* neilb: there is no locking about new writes here,
|
|
* neilb: there is no locking about new writes here,
|
|
* so this cannot be safe.
|
|
* so this cannot be safe.
|
|
*/
|
|
*/
|
|
- if (atomic_read(&conf->active_stripes)) {
|
|
|
|
|
|
+ if (atomic_read(&conf->active_stripes) ||
|
|
|
|
+ atomic_read(&conf->r5c_cached_full_stripes) ||
|
|
|
|
+ atomic_read(&conf->r5c_cached_partial_stripes)) {
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
log_exit(conf);
|
|
log_exit(conf);
|