diff options
-rw-r--r-- | drivers/md/md.c | 26 | ||||
-rw-r--r-- | drivers/md/md.h | 6 |
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 | ||