aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c26
-rw-r--r--drivers/md/md.h6
2 files changed, 12 insertions, 20 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index fec4abcb9bb4..9ef21d9b8e27 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2088,7 +2088,6 @@ static void sync_sbs(mddev_t * mddev, int nospares)
2088 if (rdev->sb_events == mddev->events || 2088 if (rdev->sb_events == mddev->events ||
2089 (nospares && 2089 (nospares &&
2090 rdev->raid_disk < 0 && 2090 rdev->raid_disk < 0 &&
2091 (rdev->sb_events&1)==0 &&
2092 rdev->sb_events+1 == mddev->events)) { 2091 rdev->sb_events+1 == mddev->events)) {
2093 /* Don't update this superblock */ 2092 /* Don't update this superblock */
2094 rdev->sb_loaded = 2; 2093 rdev->sb_loaded = 2;
@@ -2141,28 +2140,14 @@ repeat:
2141 * and 'events' is odd, we can roll back to the previous clean state */ 2140 * and 'events' is odd, we can roll back to the previous clean state */
2142 if (nospares 2141 if (nospares
2143 && (mddev->in_sync && mddev->recovery_cp == MaxSector) 2142 && (mddev->in_sync && mddev->recovery_cp == MaxSector)
2144 && (mddev->events & 1) 2143 && mddev->can_decrease_events
2145 && mddev->events != 1) 2144 && mddev->events != 1) {
2146 mddev->events--; 2145 mddev->events--;
2147 else { 2146 mddev->can_decrease_events = 0;
2147 } else {
2148 /* otherwise we have to go forward and ... */ 2148 /* otherwise we have to go forward and ... */
2149 mddev->events ++; 2149 mddev->events ++;
2150 if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */ 2150 mddev->can_decrease_events = nospares;
2151 /* .. if the array isn't clean, an 'even' event must also go
2152 * to spares. */
2153 if ((mddev->events&1)==0) {
2154 nospares = 0;
2155 sync_req = 2; /* force a second update to get the
2156 * even/odd in sync */
2157 }
2158 } else {
2159 /* otherwise an 'odd' event must go to spares */
2160 if ((mddev->events&1)) {
2161 nospares = 0;
2162 sync_req = 2; /* force a second update to get the
2163 * even/odd in sync */
2164 }
2165 }
2166 } 2151 }
2167 2152
2168 if (!mddev->events) { 2153 if (!mddev->events) {
@@ -4606,6 +4591,7 @@ static void md_clean(mddev_t *mddev)
4606 mddev->layout = 0; 4591 mddev->layout = 0;
4607 mddev->max_disks = 0; 4592 mddev->max_disks = 0;
4608 mddev->events = 0; 4593 mddev->events = 0;
4594 mddev->can_decrease_events = 0;
4609 mddev->delta_disks = 0; 4595 mddev->delta_disks = 0;
4610 mddev->new_level = LEVEL_NONE; 4596 mddev->new_level = LEVEL_NONE;
4611 mddev->new_layout = 0; 4597 mddev->new_layout = 0;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index a536f5458097..7ab5ea155452 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -150,6 +150,12 @@ struct mddev_s
150 int external_size; /* size managed 150 int external_size; /* size managed
151 * externally */ 151 * externally */
152 __u64 events; 152 __u64 events;
153 /* If the last 'event' was simply a clean->dirty transition, and
154 * we didn't write it to the spares, then it is safe and simple
155 * to just decrement the event count on a dirty->clean transition.
156 * So we record that possibility here.
157 */
158 int can_decrease_events;
153 159
154 char uuid[16]; 160 char uuid[16];
155 161