diff options
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 48 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_proc.c | 103 |
2 files changed, 75 insertions, 76 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index e306a22a60f1..abf5aefd9790 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -1982,54 +1982,6 @@ static inline int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_ | |||
1982 | extern int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins); | 1982 | extern int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins); |
1983 | #endif | 1983 | #endif |
1984 | 1984 | ||
1985 | /* you must have an "get_ldev" reference */ | ||
1986 | static inline void drbd_get_syncer_progress(struct drbd_device *device, | ||
1987 | unsigned long *bits_left, unsigned int *per_mil_done) | ||
1988 | { | ||
1989 | /* this is to break it at compile time when we change that, in case we | ||
1990 | * want to support more than (1<<32) bits on a 32bit arch. */ | ||
1991 | typecheck(unsigned long, device->rs_total); | ||
1992 | |||
1993 | /* note: both rs_total and rs_left are in bits, i.e. in | ||
1994 | * units of BM_BLOCK_SIZE. | ||
1995 | * for the percentage, we don't care. */ | ||
1996 | |||
1997 | if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T) | ||
1998 | *bits_left = device->ov_left; | ||
1999 | else | ||
2000 | *bits_left = drbd_bm_total_weight(device) - device->rs_failed; | ||
2001 | /* >> 10 to prevent overflow, | ||
2002 | * +1 to prevent division by zero */ | ||
2003 | if (*bits_left > device->rs_total) { | ||
2004 | /* doh. maybe a logic bug somewhere. | ||
2005 | * may also be just a race condition | ||
2006 | * between this and a disconnect during sync. | ||
2007 | * for now, just prevent in-kernel buffer overflow. | ||
2008 | */ | ||
2009 | smp_rmb(); | ||
2010 | drbd_warn(device, "cs:%s rs_left=%lu > rs_total=%lu (rs_failed %lu)\n", | ||
2011 | drbd_conn_str(device->state.conn), | ||
2012 | *bits_left, device->rs_total, device->rs_failed); | ||
2013 | *per_mil_done = 0; | ||
2014 | } else { | ||
2015 | /* Make sure the division happens in long context. | ||
2016 | * We allow up to one petabyte storage right now, | ||
2017 | * at a granularity of 4k per bit that is 2**38 bits. | ||
2018 | * After shift right and multiplication by 1000, | ||
2019 | * this should still fit easily into a 32bit long, | ||
2020 | * so we don't need a 64bit division on 32bit arch. | ||
2021 | * Note: currently we don't support such large bitmaps on 32bit | ||
2022 | * arch anyways, but no harm done to be prepared for it here. | ||
2023 | */ | ||
2024 | unsigned int shift = device->rs_total > UINT_MAX ? 16 : 10; | ||
2025 | unsigned long left = *bits_left >> shift; | ||
2026 | unsigned long total = 1UL + (device->rs_total >> shift); | ||
2027 | unsigned long tmp = 1000UL - left * 1000UL/total; | ||
2028 | *per_mil_done = tmp; | ||
2029 | } | ||
2030 | } | ||
2031 | |||
2032 | |||
2033 | /* this throttles on-the-fly application requests | 1985 | /* this throttles on-the-fly application requests |
2034 | * according to max_buffers settings; | 1986 | * according to max_buffers settings; |
2035 | * maybe re-implement using semaphores? */ | 1987 | * maybe re-implement using semaphores? */ |
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 886f6bef70dc..9059d7bf8a36 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c | |||
@@ -60,20 +60,65 @@ static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v) | |||
60 | seq_printf(seq, "%ld", v); | 60 | seq_printf(seq, "%ld", v); |
61 | } | 61 | } |
62 | 62 | ||
63 | static void drbd_get_syncer_progress(struct drbd_device *device, | ||
64 | union drbd_dev_state state, unsigned long *rs_total, | ||
65 | unsigned long *bits_left, unsigned int *per_mil_done) | ||
66 | { | ||
67 | /* this is to break it at compile time when we change that, in case we | ||
68 | * want to support more than (1<<32) bits on a 32bit arch. */ | ||
69 | typecheck(unsigned long, device->rs_total); | ||
70 | *rs_total = device->rs_total; | ||
71 | |||
72 | /* note: both rs_total and rs_left are in bits, i.e. in | ||
73 | * units of BM_BLOCK_SIZE. | ||
74 | * for the percentage, we don't care. */ | ||
75 | |||
76 | if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T) | ||
77 | *bits_left = device->ov_left; | ||
78 | else | ||
79 | *bits_left = drbd_bm_total_weight(device) - device->rs_failed; | ||
80 | /* >> 10 to prevent overflow, | ||
81 | * +1 to prevent division by zero */ | ||
82 | if (*bits_left > *rs_total) { | ||
83 | /* D'oh. Maybe a logic bug somewhere. More likely just a race | ||
84 | * between state change and reset of rs_total. | ||
85 | */ | ||
86 | *bits_left = *rs_total; | ||
87 | *per_mil_done = *rs_total ? 0 : 1000; | ||
88 | } else { | ||
89 | /* Make sure the division happens in long context. | ||
90 | * We allow up to one petabyte storage right now, | ||
91 | * at a granularity of 4k per bit that is 2**38 bits. | ||
92 | * After shift right and multiplication by 1000, | ||
93 | * this should still fit easily into a 32bit long, | ||
94 | * so we don't need a 64bit division on 32bit arch. | ||
95 | * Note: currently we don't support such large bitmaps on 32bit | ||
96 | * arch anyways, but no harm done to be prepared for it here. | ||
97 | */ | ||
98 | unsigned int shift = *rs_total > UINT_MAX ? 16 : 10; | ||
99 | unsigned long left = *bits_left >> shift; | ||
100 | unsigned long total = 1UL + (*rs_total >> shift); | ||
101 | unsigned long tmp = 1000UL - left * 1000UL/total; | ||
102 | *per_mil_done = tmp; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
63 | /*lge | 107 | /*lge |
64 | * progress bars shamelessly adapted from driver/md/md.c | 108 | * progress bars shamelessly adapted from driver/md/md.c |
65 | * output looks like | 109 | * output looks like |
66 | * [=====>..............] 33.5% (23456/123456) | 110 | * [=====>..............] 33.5% (23456/123456) |
67 | * finish: 2:20:20 speed: 6,345 (6,456) K/sec | 111 | * finish: 2:20:20 speed: 6,345 (6,456) K/sec |
68 | */ | 112 | */ |
69 | static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq) | 113 | static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq, |
114 | union drbd_dev_state state) | ||
70 | { | 115 | { |
71 | unsigned long db, dt, dbdt, rt, rs_left; | 116 | unsigned long db, dt, dbdt, rt, rs_total, rs_left; |
72 | unsigned int res; | 117 | unsigned int res; |
73 | int i, x, y; | 118 | int i, x, y; |
74 | int stalled = 0; | 119 | int stalled = 0; |
75 | 120 | ||
76 | drbd_get_syncer_progress(device, &rs_left, &res); | 121 | drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res); |
77 | 122 | ||
78 | x = res/50; | 123 | x = res/50; |
79 | y = 20-x; | 124 | y = 20-x; |
@@ -85,21 +130,21 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se | |||
85 | seq_printf(seq, "."); | 130 | seq_printf(seq, "."); |
86 | seq_printf(seq, "] "); | 131 | seq_printf(seq, "] "); |
87 | 132 | ||
88 | if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T) | 133 | if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T) |
89 | seq_printf(seq, "verified:"); | 134 | seq_printf(seq, "verified:"); |
90 | else | 135 | else |
91 | seq_printf(seq, "sync'ed:"); | 136 | seq_printf(seq, "sync'ed:"); |
92 | seq_printf(seq, "%3u.%u%% ", res / 10, res % 10); | 137 | seq_printf(seq, "%3u.%u%% ", res / 10, res % 10); |
93 | 138 | ||
94 | /* if more than a few GB, display in MB */ | 139 | /* if more than a few GB, display in MB */ |
95 | if (device->rs_total > (4UL << (30 - BM_BLOCK_SHIFT))) | 140 | if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT))) |
96 | seq_printf(seq, "(%lu/%lu)M", | 141 | seq_printf(seq, "(%lu/%lu)M", |
97 | (unsigned long) Bit2KB(rs_left >> 10), | 142 | (unsigned long) Bit2KB(rs_left >> 10), |
98 | (unsigned long) Bit2KB(device->rs_total >> 10)); | 143 | (unsigned long) Bit2KB(rs_total >> 10)); |
99 | else | 144 | else |
100 | seq_printf(seq, "(%lu/%lu)K\n\t", | 145 | seq_printf(seq, "(%lu/%lu)K\n\t", |
101 | (unsigned long) Bit2KB(rs_left), | 146 | (unsigned long) Bit2KB(rs_left), |
102 | (unsigned long) Bit2KB(device->rs_total)); | 147 | (unsigned long) Bit2KB(rs_total)); |
103 | 148 | ||
104 | /* see drivers/md/md.c | 149 | /* see drivers/md/md.c |
105 | * We do not want to overflow, so the order of operands and | 150 | * We do not want to overflow, so the order of operands and |
@@ -150,13 +195,13 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se | |||
150 | dt = (jiffies - device->rs_start - device->rs_paused) / HZ; | 195 | dt = (jiffies - device->rs_start - device->rs_paused) / HZ; |
151 | if (dt == 0) | 196 | if (dt == 0) |
152 | dt = 1; | 197 | dt = 1; |
153 | db = device->rs_total - rs_left; | 198 | db = rs_total - rs_left; |
154 | dbdt = Bit2KB(db/dt); | 199 | dbdt = Bit2KB(db/dt); |
155 | seq_printf_with_thousands_grouping(seq, dbdt); | 200 | seq_printf_with_thousands_grouping(seq, dbdt); |
156 | seq_printf(seq, ")"); | 201 | seq_printf(seq, ")"); |
157 | 202 | ||
158 | if (device->state.conn == C_SYNC_TARGET || | 203 | if (state.conn == C_SYNC_TARGET || |
159 | device->state.conn == C_VERIFY_S) { | 204 | state.conn == C_VERIFY_S) { |
160 | seq_printf(seq, " want: "); | 205 | seq_printf(seq, " want: "); |
161 | seq_printf_with_thousands_grouping(seq, device->c_sync_rate); | 206 | seq_printf_with_thousands_grouping(seq, device->c_sync_rate); |
162 | } | 207 | } |
@@ -168,8 +213,8 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se | |||
168 | unsigned long bm_bits = drbd_bm_bits(device); | 213 | unsigned long bm_bits = drbd_bm_bits(device); |
169 | unsigned long bit_pos; | 214 | unsigned long bit_pos; |
170 | unsigned long long stop_sector = 0; | 215 | unsigned long long stop_sector = 0; |
171 | if (device->state.conn == C_VERIFY_S || | 216 | if (state.conn == C_VERIFY_S || |
172 | device->state.conn == C_VERIFY_T) { | 217 | state.conn == C_VERIFY_T) { |
173 | bit_pos = bm_bits - device->ov_left; | 218 | bit_pos = bm_bits - device->ov_left; |
174 | if (verify_can_do_stop_sector(device)) | 219 | if (verify_can_do_stop_sector(device)) |
175 | stop_sector = device->ov_stop_sector; | 220 | stop_sector = device->ov_stop_sector; |
@@ -194,6 +239,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v) | |||
194 | const char *sn; | 239 | const char *sn; |
195 | struct drbd_device *device; | 240 | struct drbd_device *device; |
196 | struct net_conf *nc; | 241 | struct net_conf *nc; |
242 | union drbd_dev_state state; | ||
197 | char wp; | 243 | char wp; |
198 | 244 | ||
199 | static char write_ordering_chars[] = { | 245 | static char write_ordering_chars[] = { |
@@ -231,11 +277,12 @@ static int drbd_seq_show(struct seq_file *seq, void *v) | |||
231 | seq_printf(seq, "\n"); | 277 | seq_printf(seq, "\n"); |
232 | prev_i = i; | 278 | prev_i = i; |
233 | 279 | ||
234 | sn = drbd_conn_str(device->state.conn); | 280 | state = device->state; |
281 | sn = drbd_conn_str(state.conn); | ||
235 | 282 | ||
236 | if (device->state.conn == C_STANDALONE && | 283 | if (state.conn == C_STANDALONE && |
237 | device->state.disk == D_DISKLESS && | 284 | state.disk == D_DISKLESS && |
238 | device->state.role == R_SECONDARY) { | 285 | state.role == R_SECONDARY) { |
239 | seq_printf(seq, "%2d: cs:Unconfigured\n", i); | 286 | seq_printf(seq, "%2d: cs:Unconfigured\n", i); |
240 | } else { | 287 | } else { |
241 | /* reset device->congestion_reason */ | 288 | /* reset device->congestion_reason */ |
@@ -248,15 +295,15 @@ static int drbd_seq_show(struct seq_file *seq, void *v) | |||
248 | " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u " | 295 | " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u " |
249 | "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c", | 296 | "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c", |
250 | i, sn, | 297 | i, sn, |
251 | drbd_role_str(device->state.role), | 298 | drbd_role_str(state.role), |
252 | drbd_role_str(device->state.peer), | 299 | drbd_role_str(state.peer), |
253 | drbd_disk_str(device->state.disk), | 300 | drbd_disk_str(state.disk), |
254 | drbd_disk_str(device->state.pdsk), | 301 | drbd_disk_str(state.pdsk), |
255 | wp, | 302 | wp, |
256 | drbd_suspended(device) ? 's' : 'r', | 303 | drbd_suspended(device) ? 's' : 'r', |
257 | device->state.aftr_isp ? 'a' : '-', | 304 | state.aftr_isp ? 'a' : '-', |
258 | device->state.peer_isp ? 'p' : '-', | 305 | state.peer_isp ? 'p' : '-', |
259 | device->state.user_isp ? 'u' : '-', | 306 | state.user_isp ? 'u' : '-', |
260 | device->congestion_reason ?: '-', | 307 | device->congestion_reason ?: '-', |
261 | test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-', | 308 | test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-', |
262 | device->send_cnt/2, | 309 | device->send_cnt/2, |
@@ -277,11 +324,11 @@ static int drbd_seq_show(struct seq_file *seq, void *v) | |||
277 | Bit2KB((unsigned long long) | 324 | Bit2KB((unsigned long long) |
278 | drbd_bm_total_weight(device))); | 325 | drbd_bm_total_weight(device))); |
279 | } | 326 | } |
280 | if (device->state.conn == C_SYNC_SOURCE || | 327 | if (state.conn == C_SYNC_SOURCE || |
281 | device->state.conn == C_SYNC_TARGET || | 328 | state.conn == C_SYNC_TARGET || |
282 | device->state.conn == C_VERIFY_S || | 329 | state.conn == C_VERIFY_S || |
283 | device->state.conn == C_VERIFY_T) | 330 | state.conn == C_VERIFY_T) |
284 | drbd_syncer_progress(device, seq); | 331 | drbd_syncer_progress(device, seq, state); |
285 | 332 | ||
286 | if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) { | 333 | if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) { |
287 | lc_seq_printf_stats(seq, device->resync); | 334 | lc_seq_printf_stats(seq, device->resync); |