|
@@ -2951,12 +2951,36 @@ sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous)
|
|
* like to flush data in journal to RAID disks first, so complex rmw
|
|
* like to flush data in journal to RAID disks first, so complex rmw
|
|
* is handled in the write patch (handle_stripe_dirtying).
|
|
* is handled in the write patch (handle_stripe_dirtying).
|
|
*
|
|
*
|
|
|
|
+ * 2. when journal space is critical (R5C_LOG_CRITICAL=1)
|
|
|
|
+ *
|
|
|
|
+ * It is important to be able to flush all stripes in raid5-cache.
|
|
|
|
+ * Therefore, we need reserve some space on the journal device for
|
|
|
|
+ * these flushes. If flush operation includes pending writes to the
|
|
|
|
+ * stripe, we need to reserve (conf->raid_disk + 1) pages per stripe
|
|
|
|
+ * for the flush out. If we exclude these pending writes from flush
|
|
|
|
+ * operation, we only need (conf->max_degraded + 1) pages per stripe.
|
|
|
|
+ * Therefore, excluding pending writes in these cases enables more
|
|
|
|
+ * efficient use of the journal device.
|
|
|
|
+ *
|
|
|
|
+ * Note: To make sure the stripe makes progress, we only delay
|
|
|
|
+ * towrite for stripes with data already in journal (injournal > 0).
|
|
|
|
+ * When LOG_CRITICAL, stripes with injournal == 0 will be sent to
|
|
|
|
+ * no_space_stripes list.
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
-static inline bool delay_towrite(struct r5dev *dev,
|
|
|
|
- struct stripe_head_state *s)
|
|
|
|
|
|
+static inline bool delay_towrite(struct r5conf *conf,
|
|
|
|
+ struct r5dev *dev,
|
|
|
|
+ struct stripe_head_state *s)
|
|
{
|
|
{
|
|
- return !test_bit(R5_OVERWRITE, &dev->flags) &&
|
|
|
|
- !test_bit(R5_Insync, &dev->flags) && s->injournal;
|
|
|
|
|
|
+ /* case 1 above */
|
|
|
|
+ if (!test_bit(R5_OVERWRITE, &dev->flags) &&
|
|
|
|
+ !test_bit(R5_Insync, &dev->flags) && s->injournal)
|
|
|
|
+ return true;
|
|
|
|
+ /* case 2 above */
|
|
|
|
+ if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
|
|
|
|
+ s->injournal > 0)
|
|
|
|
+ return true;
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -2979,7 +3003,7 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
|
|
for (i = disks; i--; ) {
|
|
for (i = disks; i--; ) {
|
|
struct r5dev *dev = &sh->dev[i];
|
|
struct r5dev *dev = &sh->dev[i];
|
|
|
|
|
|
- if (dev->towrite && !delay_towrite(dev, s)) {
|
|
|
|
|
|
+ if (dev->towrite && !delay_towrite(conf, dev, s)) {
|
|
set_bit(R5_LOCKED, &dev->flags);
|
|
set_bit(R5_LOCKED, &dev->flags);
|
|
set_bit(R5_Wantdrain, &dev->flags);
|
|
set_bit(R5_Wantdrain, &dev->flags);
|
|
if (!expand)
|
|
if (!expand)
|
|
@@ -3731,7 +3755,7 @@ static int handle_stripe_dirtying(struct r5conf *conf,
|
|
} else for (i = disks; i--; ) {
|
|
} else for (i = disks; i--; ) {
|
|
/* would I have to read this buffer for read_modify_write */
|
|
/* would I have to read this buffer for read_modify_write */
|
|
struct r5dev *dev = &sh->dev[i];
|
|
struct r5dev *dev = &sh->dev[i];
|
|
- if (((dev->towrite && !delay_towrite(dev, s)) ||
|
|
|
|
|
|
+ if (((dev->towrite && !delay_towrite(conf, dev, s)) ||
|
|
i == sh->pd_idx || i == sh->qd_idx ||
|
|
i == sh->pd_idx || i == sh->qd_idx ||
|
|
test_bit(R5_InJournal, &dev->flags)) &&
|
|
test_bit(R5_InJournal, &dev->flags)) &&
|
|
!test_bit(R5_LOCKED, &dev->flags) &&
|
|
!test_bit(R5_LOCKED, &dev->flags) &&
|
|
@@ -3755,8 +3779,8 @@ static int handle_stripe_dirtying(struct r5conf *conf,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- pr_debug("for sector %llu, rmw=%d rcw=%d\n",
|
|
|
|
- (unsigned long long)sh->sector, rmw, rcw);
|
|
|
|
|
|
+ pr_debug("for sector %llu state 0x%lx, rmw=%d rcw=%d\n",
|
|
|
|
+ (unsigned long long)sh->sector, sh->state, rmw, rcw);
|
|
set_bit(STRIPE_HANDLE, &sh->state);
|
|
set_bit(STRIPE_HANDLE, &sh->state);
|
|
if ((rmw < rcw || (rmw == rcw && conf->rmw_level == PARITY_PREFER_RMW)) && rmw > 0) {
|
|
if ((rmw < rcw || (rmw == rcw && conf->rmw_level == PARITY_PREFER_RMW)) && rmw > 0) {
|
|
/* prefer read-modify-write, but need to get some data */
|
|
/* prefer read-modify-write, but need to get some data */
|
|
@@ -3796,7 +3820,7 @@ static int handle_stripe_dirtying(struct r5conf *conf,
|
|
|
|
|
|
for (i = disks; i--; ) {
|
|
for (i = disks; i--; ) {
|
|
struct r5dev *dev = &sh->dev[i];
|
|
struct r5dev *dev = &sh->dev[i];
|
|
- if (((dev->towrite && !delay_towrite(dev, s)) ||
|
|
|
|
|
|
+ if (((dev->towrite && !delay_towrite(conf, dev, s)) ||
|
|
i == sh->pd_idx || i == sh->qd_idx ||
|
|
i == sh->pd_idx || i == sh->qd_idx ||
|
|
test_bit(R5_InJournal, &dev->flags)) &&
|
|
test_bit(R5_InJournal, &dev->flags)) &&
|
|
!test_bit(R5_LOCKED, &dev->flags) &&
|
|
!test_bit(R5_LOCKED, &dev->flags) &&
|