aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-08-11 15:21:50 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 12:38:18 -0400
commit1d7734a0df02ff5068ff8baa1447c7baee601db1 (patch)
tree2b01470ccd1523328c9e243801266aff9e2df391 /drivers/block
parent0bb70bf601579b0d4c56acbb54b8eb0688541e19 (diff)
drbd: use rolling marks for resync speed calculation
The current resync speed as displayed in /proc/drbd fluctuates a lot. Using an array of rolling marks makes this calculation much more stable. We used to have this (a long time ago with 0.7), but it got lost somehow. If "stalled", do not discard the rest of the information, just add a " (stalled)" tag to the progress line. This patch also shortens a spinlock critical section somewhat, and reduces the number of atomic operations in put_ldev. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_actlog.c29
-rw-r--r--drivers/block/drbd/drbd_int.h25
-rw-r--r--drivers/block/drbd/drbd_main.c29
-rw-r--r--drivers/block/drbd/drbd_proc.c27
-rw-r--r--drivers/block/drbd/drbd_worker.c14
5 files changed, 79 insertions, 45 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 9400845d602e..b895470e53d7 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -965,29 +965,30 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
965 * ok, (capacity & 7) != 0 sometimes, but who cares... 965 * ok, (capacity & 7) != 0 sometimes, but who cares...
966 * we count rs_{total,left} in bits, not sectors. 966 * we count rs_{total,left} in bits, not sectors.
967 */ 967 */
968 spin_lock_irqsave(&mdev->al_lock, flags);
969 count = drbd_bm_clear_bits(mdev, sbnr, ebnr); 968 count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
970 if (count) { 969 if (count && get_ldev(mdev)) {
971 /* we need the lock for drbd_try_clear_on_disk_bm */ 970 unsigned long now = jiffies;
972 if (jiffies - mdev->rs_mark_time > HZ*10) { 971 unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
973 /* should be rolling marks, 972 int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
974 * but we estimate only anyways. */ 973 if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
975 if (mdev->rs_mark_left != drbd_bm_total_weight(mdev) && 974 unsigned long tw = drbd_bm_total_weight(mdev);
975 if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
976 mdev->state.conn != C_PAUSED_SYNC_T && 976 mdev->state.conn != C_PAUSED_SYNC_T &&
977 mdev->state.conn != C_PAUSED_SYNC_S) { 977 mdev->state.conn != C_PAUSED_SYNC_S) {
978 mdev->rs_mark_time = jiffies; 978 mdev->rs_mark_time[next] = now;
979 mdev->rs_mark_left = drbd_bm_total_weight(mdev); 979 mdev->rs_mark_left[next] = tw;
980 mdev->rs_last_mark = next;
980 } 981 }
981 } 982 }
982 if (get_ldev(mdev)) { 983 spin_lock_irqsave(&mdev->al_lock, flags);
983 drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE); 984 drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
984 put_ldev(mdev); 985 spin_unlock_irqrestore(&mdev->al_lock, flags);
985 } 986
986 /* just wake_up unconditional now, various lc_chaged(), 987 /* just wake_up unconditional now, various lc_chaged(),
987 * lc_put() in drbd_try_clear_on_disk_bm(). */ 988 * lc_put() in drbd_try_clear_on_disk_bm(). */
988 wake_up = 1; 989 wake_up = 1;
990 put_ldev(mdev);
989 } 991 }
990 spin_unlock_irqrestore(&mdev->al_lock, flags);
991 if (wake_up) 992 if (wake_up)
992 wake_up(&mdev->al_wait); 993 wake_up(&mdev->al_wait);
993} 994}
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 72d204750408..0fce3f36fc1c 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -997,12 +997,16 @@ struct drbd_conf {
997 unsigned long rs_start; 997 unsigned long rs_start;
998 /* cumulated time in PausedSyncX state [unit jiffies] */ 998 /* cumulated time in PausedSyncX state [unit jiffies] */
999 unsigned long rs_paused; 999 unsigned long rs_paused;
1000 /* skipped because csum was equal [unit BM_BLOCK_SIZE] */
1001 unsigned long rs_same_csum;
1002#define DRBD_SYNC_MARKS 8
1003#define DRBD_SYNC_MARK_STEP (3*HZ)
1000 /* block not up-to-date at mark [unit BM_BLOCK_SIZE] */ 1004 /* block not up-to-date at mark [unit BM_BLOCK_SIZE] */
1001 unsigned long rs_mark_left; 1005 unsigned long rs_mark_left[DRBD_SYNC_MARKS];
1002 /* marks's time [unit jiffies] */ 1006 /* marks's time [unit jiffies] */
1003 unsigned long rs_mark_time; 1007 unsigned long rs_mark_time[DRBD_SYNC_MARKS];
1004 /* skipped because csum was equeal [unit BM_BLOCK_SIZE] */ 1008 /* current index into rs_mark_{left,time} */
1005 unsigned long rs_same_csum; 1009 int rs_last_mark;
1006 1010
1007 /* where does the admin want us to start? (sector) */ 1011 /* where does the admin want us to start? (sector) */
1008 sector_t ov_start_sector; 1012 sector_t ov_start_sector;
@@ -1077,8 +1081,12 @@ struct drbd_conf {
1077 u64 ed_uuid; /* UUID of the exposed data */ 1081 u64 ed_uuid; /* UUID of the exposed data */
1078 struct mutex state_mutex; 1082 struct mutex state_mutex;
1079 char congestion_reason; /* Why we where congested... */ 1083 char congestion_reason; /* Why we where congested... */
1080 atomic_t rs_sect_in; /* counter to measure the incoming resync data rate */ 1084 atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
1081 int c_sync_rate; /* current resync rate after delay_probe magic */ 1085 atomic_t rs_sect_ev; /* for submitted resync data rate, both */
1086 int rs_last_sect_ev; /* counter to compare with */
1087 int rs_last_events; /* counter of read or write "events" (unit sectors)
1088 * on the lower level device when we last looked. */
1089 int c_sync_rate; /* current resync rate after syncer throttle magic */
1082 struct fifo_buffer rs_plan_s; /* correction values of resync planer */ 1090 struct fifo_buffer rs_plan_s; /* correction values of resync planer */
1083 int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */ 1091 int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
1084 int rs_planed; /* resync sectors already planed */ 1092 int rs_planed; /* resync sectors already planed */
@@ -2072,10 +2080,11 @@ static inline int get_net_conf(struct drbd_conf *mdev)
2072 2080
2073static inline void put_ldev(struct drbd_conf *mdev) 2081static inline void put_ldev(struct drbd_conf *mdev)
2074{ 2082{
2083 int i = atomic_dec_return(&mdev->local_cnt);
2075 __release(local); 2084 __release(local);
2076 if (atomic_dec_and_test(&mdev->local_cnt)) 2085 D_ASSERT(i >= 0);
2086 if (i == 0)
2077 wake_up(&mdev->misc_wait); 2087 wake_up(&mdev->misc_wait);
2078 D_ASSERT(atomic_read(&mdev->local_cnt) >= 0);
2079} 2088}
2080 2089
2081#ifndef __CHECKER__ 2090#ifndef __CHECKER__
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index ed09a840d838..1ff8418ae0fa 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1064,7 +1064,8 @@ int __drbd_set_state(struct drbd_conf *mdev,
1064 if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) && 1064 if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
1065 (ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)) { 1065 (ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)) {
1066 dev_info(DEV, "Syncer continues.\n"); 1066 dev_info(DEV, "Syncer continues.\n");
1067 mdev->rs_paused += (long)jiffies-(long)mdev->rs_mark_time; 1067 mdev->rs_paused += (long)jiffies
1068 -(long)mdev->rs_mark_time[mdev->rs_last_mark];
1068 if (ns.conn == C_SYNC_TARGET) { 1069 if (ns.conn == C_SYNC_TARGET) {
1069 if (!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags)) 1070 if (!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))
1070 mod_timer(&mdev->resync_timer, jiffies); 1071 mod_timer(&mdev->resync_timer, jiffies);
@@ -1078,27 +1079,33 @@ int __drbd_set_state(struct drbd_conf *mdev,
1078 if ((os.conn == C_SYNC_TARGET || os.conn == C_SYNC_SOURCE) && 1079 if ((os.conn == C_SYNC_TARGET || os.conn == C_SYNC_SOURCE) &&
1079 (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) { 1080 (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
1080 dev_info(DEV, "Resync suspended\n"); 1081 dev_info(DEV, "Resync suspended\n");
1081 mdev->rs_mark_time = jiffies; 1082 mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
1082 if (ns.conn == C_PAUSED_SYNC_T) 1083 if (ns.conn == C_PAUSED_SYNC_T)
1083 set_bit(STOP_SYNC_TIMER, &mdev->flags); 1084 set_bit(STOP_SYNC_TIMER, &mdev->flags);
1084 } 1085 }
1085 1086
1086 if (os.conn == C_CONNECTED && 1087 if (os.conn == C_CONNECTED &&
1087 (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) { 1088 (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) {
1089 unsigned long now = jiffies;
1090 int i;
1091
1088 mdev->ov_position = 0; 1092 mdev->ov_position = 0;
1089 mdev->rs_total = 1093 mdev->rs_total = drbd_bm_bits(mdev);
1090 mdev->rs_mark_left = drbd_bm_bits(mdev);
1091 if (mdev->agreed_pro_version >= 90) 1094 if (mdev->agreed_pro_version >= 90)
1092 set_ov_position(mdev, ns.conn); 1095 set_ov_position(mdev, ns.conn);
1093 else 1096 else
1094 mdev->ov_start_sector = 0; 1097 mdev->ov_start_sector = 0;
1095 mdev->ov_left = mdev->rs_total 1098 mdev->ov_left = mdev->rs_total
1096 - BM_SECT_TO_BIT(mdev->ov_position); 1099 - BM_SECT_TO_BIT(mdev->ov_position);
1097 mdev->rs_start = 1100 mdev->rs_start = now;
1098 mdev->rs_mark_time = jiffies;
1099 mdev->ov_last_oos_size = 0; 1101 mdev->ov_last_oos_size = 0;
1100 mdev->ov_last_oos_start = 0; 1102 mdev->ov_last_oos_start = 0;
1101 1103
1104 for (i = 0; i < DRBD_SYNC_MARKS; i++) {
1105 mdev->rs_mark_left[i] = mdev->rs_total;
1106 mdev->rs_mark_time[i] = now;
1107 }
1108
1102 if (ns.conn == C_VERIFY_S) { 1109 if (ns.conn == C_VERIFY_S) {
1103 dev_info(DEV, "Starting Online Verify from sector %llu\n", 1110 dev_info(DEV, "Starting Online Verify from sector %llu\n",
1104 (unsigned long long)mdev->ov_position); 1111 (unsigned long long)mdev->ov_position);
@@ -2793,6 +2800,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
2793 2800
2794void drbd_mdev_cleanup(struct drbd_conf *mdev) 2801void drbd_mdev_cleanup(struct drbd_conf *mdev)
2795{ 2802{
2803 int i;
2796 if (mdev->receiver.t_state != None) 2804 if (mdev->receiver.t_state != None)
2797 dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n", 2805 dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
2798 mdev->receiver.t_state); 2806 mdev->receiver.t_state);
@@ -2809,9 +2817,12 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
2809 mdev->p_size = 2817 mdev->p_size =
2810 mdev->rs_start = 2818 mdev->rs_start =
2811 mdev->rs_total = 2819 mdev->rs_total =
2812 mdev->rs_failed = 2820 mdev->rs_failed = 0;
2813 mdev->rs_mark_left = 2821 mdev->rs_last_events = 0;
2814 mdev->rs_mark_time = 0; 2822 for (i = 0; i < DRBD_SYNC_MARKS; i++) {
2823 mdev->rs_mark_left[i] = 0;
2824 mdev->rs_mark_time[i] = 0;
2825 }
2815 D_ASSERT(mdev->net_conf == NULL); 2826 D_ASSERT(mdev->net_conf == NULL);
2816 2827
2817 drbd_set_my_capacity(mdev, 0); 2828 drbd_set_my_capacity(mdev, 0);
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index be3374b68460..c159692c3b56 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -57,6 +57,7 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
57 unsigned long db, dt, dbdt, rt, rs_left; 57 unsigned long db, dt, dbdt, rt, rs_left;
58 unsigned int res; 58 unsigned int res;
59 int i, x, y; 59 int i, x, y;
60 int stalled = 0;
60 61
61 drbd_get_syncer_progress(mdev, &rs_left, &res); 62 drbd_get_syncer_progress(mdev, &rs_left, &res);
62 63
@@ -90,18 +91,17 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
90 * db: blocks written from mark until now 91 * db: blocks written from mark until now
91 * rt: remaining time 92 * rt: remaining time
92 */ 93 */
93 dt = (jiffies - mdev->rs_mark_time) / HZ; 94 /* Rolling marks. last_mark+1 may just now be modified. last_mark+2 is
94 95 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
95 if (dt > 20) { 96 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
96 /* if we made no update to rs_mark_time for too long, 97 i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
97 * we are stalled. show that. */ 98 dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
98 seq_printf(seq, "stalled\n"); 99 if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
99 return; 100 stalled = 1;
100 }
101 101
102 if (!dt) 102 if (!dt)
103 dt++; 103 dt++;
104 db = mdev->rs_mark_left - rs_left; 104 db = mdev->rs_mark_left[i] - rs_left;
105 rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */ 105 rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
106 106
107 seq_printf(seq, "finish: %lu:%02lu:%02lu", 107 seq_printf(seq, "finish: %lu:%02lu:%02lu",
@@ -128,7 +128,14 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
128 else 128 else
129 seq_printf(seq, " (%ld)", dbdt); 129 seq_printf(seq, " (%ld)", dbdt);
130 130
131 seq_printf(seq, " K/sec\n"); 131 if (mdev->state.conn == C_SYNC_TARGET) {
132 if (mdev->c_sync_rate > 1000)
133 seq_printf(seq, " want: %d,%03d",
134 mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000);
135 else
136 seq_printf(seq, " want: %d", mdev->c_sync_rate);
137 }
138 seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
132} 139}
133 140
134static void resync_dump_detail(struct seq_file *seq, struct lc_element *e) 141static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 48452fe83603..53b74254b1c2 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1481,13 +1481,19 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
1481 r = SS_UNKNOWN_ERROR; 1481 r = SS_UNKNOWN_ERROR;
1482 1482
1483 if (r == SS_SUCCESS) { 1483 if (r == SS_SUCCESS) {
1484 mdev->rs_total = 1484 unsigned long tw = drbd_bm_total_weight(mdev);
1485 mdev->rs_mark_left = drbd_bm_total_weight(mdev); 1485 unsigned long now = jiffies;
1486 int i;
1487
1486 mdev->rs_failed = 0; 1488 mdev->rs_failed = 0;
1487 mdev->rs_paused = 0; 1489 mdev->rs_paused = 0;
1488 mdev->rs_start =
1489 mdev->rs_mark_time = jiffies;
1490 mdev->rs_same_csum = 0; 1490 mdev->rs_same_csum = 0;
1491 mdev->rs_total = tw;
1492 mdev->rs_start = now;
1493 for (i = 0; i < DRBD_SYNC_MARKS; i++) {
1494 mdev->rs_mark_left[i] = tw;
1495 mdev->rs_mark_time[i] = now;
1496 }
1491 _drbd_pause_after(mdev); 1497 _drbd_pause_after(mdev);
1492 } 1498 }
1493 write_unlock_irq(&global_state_lock); 1499 write_unlock_irq(&global_state_lock);