diff options
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 29 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 25 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 29 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_proc.c | 27 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 14 |
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 | ||
2073 | static inline void put_ldev(struct drbd_conf *mdev) | 2081 | static 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 | ||
2794 | void drbd_mdev_cleanup(struct drbd_conf *mdev) | 2801 | void 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 | ||
134 | static void resync_dump_detail(struct seq_file *seq, struct lc_element *e) | 141 | static 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); |