aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-05-17 19:28:43 -0400
committerNeilBrown <neilb@suse.de>2010-05-18 01:28:01 -0400
commita8707c08f4f718bb0ed65499d3f43201f6e41455 (patch)
tree8fc3ea9ea924ebc4f28012c11f3c1e70ad60bcb2
parent7b0bb5368a7195606eca475d9f4e291ab7227052 (diff)
md: simplify updating of event count to sometimes avoid updating spares.
When updating the event count for a simple clean <-> dirty transition, we try to avoid updating the spares so they can safely spin-down. As the event_counts across an array must be +/- 1, this means decrementing the event_count on a dirty->clean transition. This is not always safe and we have to avoid the unsafe time. We current do this with a misguided idea about it being safe or not depending on whether the event_count is odd or even. This approach only works reliably in a few common instances, but easily falls down. So instead, simply keep internal state concerning whether it is safe or not, and always assume it is not safe when an array is first assembled. Signed-off-by: NeilBrown <neilb@suse.de>
-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