]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From eea1bf384e05b5ab747f8530c4fba9e9e6907fff Mon Sep 17 00:00:00 2001 |
2 | From: NeilBrown <neilb@suse.de> | |
3 | Date: Tue, 31 Mar 2009 14:27:02 +1100 | |
4 | Subject: [PATCH] md: Fix is_mddev_idle test (again). | |
5 | ||
6 | There are two problems with is_mddev_idle. | |
7 | ||
8 | 1/ sync_io is 'atomic_t' and hence 'int'. curr_events and all the | |
9 | rest are 'long'. | |
10 | So if sync_io were to wrap on a 64bit host, the value of | |
11 | curr_events would go very negative suddenly, and take a very | |
12 | long time to return to positive. | |
13 | ||
14 | So do all calculations as 'int'. That gives us plenty of precision | |
15 | for what we need. | |
16 | ||
17 | 2/ To initialise rdev->last_events we simply call is_mddev_idle, on | |
18 | the assumption that it will make sure that last_events is in a | |
19 | suitable range. It used to do this, but now it does not. | |
20 | So now we need to be more explicit about initialisation. | |
21 | ||
22 | NOTE: to avoid kabi issues in SLES11, we leave 'last_events' as | |
23 | long and cast it to (int) where used. | |
24 | ||
25 | Signed-off-by: NeilBrown <neilb@suse.de> | |
26 | --- | |
27 | drivers/md/md.c | 10 +++++----- | |
28 | 1 file changed, 5 insertions(+), 5 deletions(-) | |
29 | ||
30 | --- a/drivers/md/md.c | |
31 | +++ b/drivers/md/md.c | |
32 | @@ -5580,11 +5580,11 @@ int unregister_md_personality(struct mdk | |
33 | return 0; | |
34 | } | |
35 | ||
36 | -static int is_mddev_idle(mddev_t *mddev) | |
37 | +static int is_mddev_idle(mddev_t *mddev, int init) | |
38 | { | |
39 | mdk_rdev_t * rdev; | |
40 | int idle; | |
41 | - long curr_events; | |
42 | + int curr_events; | |
43 | ||
44 | idle = 1; | |
45 | rcu_read_lock(); | |
46 | @@ -5615,7 +5615,7 @@ static int is_mddev_idle(mddev_t *mddev) | |
47 | * always make curr_events less than last_events. | |
48 | * | |
49 | */ | |
50 | - if (curr_events - rdev->last_events > 4096) { | |
51 | + if (init || curr_events - (int)rdev->last_events > 64) { | |
52 | rdev->last_events = curr_events; | |
53 | idle = 0; | |
54 | } | |
55 | @@ -5859,7 +5859,7 @@ void md_do_sync(mddev_t *mddev) | |
56 | "(but not more than %d KB/sec) for %s.\n", | |
57 | speed_max(mddev), desc); | |
58 | ||
59 | - is_mddev_idle(mddev); /* this also initializes IO event counters */ | |
60 | + is_mddev_idle(mddev, 1); /* this initializes IO event counters */ | |
61 | ||
62 | io_sectors = 0; | |
63 | for (m = 0; m < SYNC_MARKS; m++) { | |
64 | @@ -5961,7 +5961,7 @@ void md_do_sync(mddev_t *mddev) | |
65 | ||
66 | if (currspeed > speed_min(mddev)) { | |
67 | if ((currspeed > speed_max(mddev)) || | |
68 | - !is_mddev_idle(mddev)) { | |
69 | + !is_mddev_idle(mddev, 0)) { | |
70 | msleep(500); | |
71 | goto repeat; | |
72 | } |