aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);