diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 12 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 54 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_proc.c | 3 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 7 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 2 |
8 files changed, 80 insertions, 6 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index e3f88d6e1412..fd42832f785b 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -569,7 +569,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits) | |||
569 | * | 569 | * |
570 | * maybe bm_set should be atomic_t ? | 570 | * maybe bm_set should be atomic_t ? |
571 | */ | 571 | */ |
572 | static unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev) | 572 | unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev) |
573 | { | 573 | { |
574 | struct drbd_bitmap *b = mdev->bitmap; | 574 | struct drbd_bitmap *b = mdev->bitmap; |
575 | unsigned long s; | 575 | unsigned long s; |
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 58dc02bd16c2..bb3a488b6fd6 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -863,6 +863,7 @@ enum { | |||
863 | CONN_DRY_RUN, /* Expect disconnect after resync handshake. */ | 863 | CONN_DRY_RUN, /* Expect disconnect after resync handshake. */ |
864 | GOT_PING_ACK, /* set when we receive a ping_ack packet, misc wait gets woken */ | 864 | GOT_PING_ACK, /* set when we receive a ping_ack packet, misc wait gets woken */ |
865 | NEW_CUR_UUID, /* Create new current UUID when thawing IO */ | 865 | NEW_CUR_UUID, /* Create new current UUID when thawing IO */ |
866 | AL_SUSPENDED, /* Activity logging is currently suspended. */ | ||
866 | }; | 867 | }; |
867 | 868 | ||
868 | struct drbd_bitmap; /* opaque for drbd_conf */ | 869 | struct drbd_bitmap; /* opaque for drbd_conf */ |
@@ -1425,6 +1426,7 @@ extern unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_ | |||
1425 | /* bm_find_next variants for use while you hold drbd_bm_lock() */ | 1426 | /* bm_find_next variants for use while you hold drbd_bm_lock() */ |
1426 | extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo); | 1427 | extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo); |
1427 | extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo); | 1428 | extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo); |
1429 | extern unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev); | ||
1428 | extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev); | 1430 | extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev); |
1429 | extern int drbd_bm_rs_done(struct drbd_conf *mdev); | 1431 | extern int drbd_bm_rs_done(struct drbd_conf *mdev); |
1430 | /* for receive_bitmap */ | 1432 | /* for receive_bitmap */ |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 71c4c261573e..23878ffc43c8 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -963,6 +963,12 @@ static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs) | |||
963 | } | 963 | } |
964 | } | 964 | } |
965 | 965 | ||
966 | static void drbd_resume_al(struct drbd_conf *mdev) | ||
967 | { | ||
968 | if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags)) | ||
969 | dev_info(DEV, "Resumed AL updates\n"); | ||
970 | } | ||
971 | |||
966 | /** | 972 | /** |
967 | * __drbd_set_state() - Set a new DRBD state | 973 | * __drbd_set_state() - Set a new DRBD state |
968 | * @mdev: DRBD device. | 974 | * @mdev: DRBD device. |
@@ -1160,6 +1166,10 @@ int __drbd_set_state(struct drbd_conf *mdev, | |||
1160 | ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT) | 1166 | ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT) |
1161 | drbd_thread_restart_nowait(&mdev->receiver); | 1167 | drbd_thread_restart_nowait(&mdev->receiver); |
1162 | 1168 | ||
1169 | /* Resume AL writing if we get a connection */ | ||
1170 | if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) | ||
1171 | drbd_resume_al(mdev); | ||
1172 | |||
1163 | ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); | 1173 | ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); |
1164 | if (ascw) { | 1174 | if (ascw) { |
1165 | ascw->os = os; | 1175 | ascw->os = os; |
@@ -2851,6 +2861,7 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev) | |||
2851 | } | 2861 | } |
2852 | 2862 | ||
2853 | drbd_free_resources(mdev); | 2863 | drbd_free_resources(mdev); |
2864 | clear_bit(AL_SUSPENDED, &mdev->flags); | ||
2854 | 2865 | ||
2855 | /* | 2866 | /* |
2856 | * currently we drbd_init_ee only on module load, so | 2867 | * currently we drbd_init_ee only on module load, so |
@@ -3652,6 +3663,7 @@ int drbd_bmio_clear_n_write(struct drbd_conf *mdev) | |||
3652 | { | 3663 | { |
3653 | int rv = -EIO; | 3664 | int rv = -EIO; |
3654 | 3665 | ||
3666 | drbd_resume_al(mdev); | ||
3655 | if (get_ldev_if_state(mdev, D_ATTACHING)) { | 3667 | if (get_ldev_if_state(mdev, D_ATTACHING)) { |
3656 | drbd_bm_clear_all(mdev); | 3668 | drbd_bm_clear_all(mdev); |
3657 | rv = drbd_bm_write(mdev); | 3669 | rv = drbd_bm_write(mdev); |
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 97fb2c2a7a57..6742652c8abc 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -777,6 +777,29 @@ static void drbd_reconfig_done(struct drbd_conf *mdev) | |||
777 | wake_up(&mdev->state_wait); | 777 | wake_up(&mdev->state_wait); |
778 | } | 778 | } |
779 | 779 | ||
780 | /* Make sure IO is suspended before calling this function(). */ | ||
781 | static void drbd_suspend_al(struct drbd_conf *mdev) | ||
782 | { | ||
783 | int s = 0; | ||
784 | |||
785 | if (lc_try_lock(mdev->act_log)) { | ||
786 | drbd_al_shrink(mdev); | ||
787 | lc_unlock(mdev->act_log); | ||
788 | } else { | ||
789 | dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n"); | ||
790 | return; | ||
791 | } | ||
792 | |||
793 | spin_lock_irq(&mdev->req_lock); | ||
794 | if (mdev->state.conn < C_CONNECTED) | ||
795 | s = !test_and_set_bit(AL_SUSPENDED, &mdev->flags); | ||
796 | |||
797 | spin_unlock_irq(&mdev->req_lock); | ||
798 | |||
799 | if (s) | ||
800 | dev_info(DEV, "Suspended AL updates\n"); | ||
801 | } | ||
802 | |||
780 | /* does always return 0; | 803 | /* does always return 0; |
781 | * interesting return code is in reply->ret_code */ | 804 | * interesting return code is in reply->ret_code */ |
782 | static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | 805 | static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, |
@@ -1113,6 +1136,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1113 | drbd_al_to_on_disk_bm(mdev); | 1136 | drbd_al_to_on_disk_bm(mdev); |
1114 | } | 1137 | } |
1115 | 1138 | ||
1139 | if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev)) | ||
1140 | drbd_suspend_al(mdev); /* IO is still suspended here... */ | ||
1141 | |||
1116 | spin_lock_irq(&mdev->req_lock); | 1142 | spin_lock_irq(&mdev->req_lock); |
1117 | os = mdev->state; | 1143 | os = mdev->state; |
1118 | ns.i = os.i; | 1144 | ns.i = os.i; |
@@ -1792,12 +1818,38 @@ static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl | |||
1792 | return 0; | 1818 | return 0; |
1793 | } | 1819 | } |
1794 | 1820 | ||
1821 | static int drbd_bmio_set_susp_al(struct drbd_conf *mdev) | ||
1822 | { | ||
1823 | int rv; | ||
1824 | |||
1825 | rv = drbd_bmio_set_n_write(mdev); | ||
1826 | drbd_suspend_al(mdev); | ||
1827 | return rv; | ||
1828 | } | ||
1829 | |||
1795 | static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | 1830 | static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, |
1796 | struct drbd_nl_cfg_reply *reply) | 1831 | struct drbd_nl_cfg_reply *reply) |
1797 | { | 1832 | { |
1833 | int retcode; | ||
1798 | 1834 | ||
1799 | reply->ret_code = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S)); | 1835 | retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED); |
1836 | |||
1837 | if (retcode < SS_SUCCESS) { | ||
1838 | if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) { | ||
1839 | /* The peer will get a resync upon connect anyways. Just make that | ||
1840 | into a full resync. */ | ||
1841 | retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT)); | ||
1842 | if (retcode >= SS_SUCCESS) { | ||
1843 | /* open coded drbd_bitmap_io() */ | ||
1844 | if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al, | ||
1845 | "set_n_write from invalidate_peer")) | ||
1846 | retcode = ERR_IO_MD_DISK; | ||
1847 | } | ||
1848 | } else | ||
1849 | retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S)); | ||
1850 | } | ||
1800 | 1851 | ||
1852 | reply->ret_code = retcode; | ||
1801 | return 0; | 1853 | return 0; |
1802 | } | 1854 | } |
1803 | 1855 | ||
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index c159692c3b56..a4a4a06908c5 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c | |||
@@ -203,7 +203,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v) | |||
203 | seq_printf(seq, "%2d: cs:Unconfigured\n", i); | 203 | seq_printf(seq, "%2d: cs:Unconfigured\n", i); |
204 | } else { | 204 | } else { |
205 | seq_printf(seq, | 205 | seq_printf(seq, |
206 | "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c\n" | 206 | "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n" |
207 | " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u " | 207 | " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u " |
208 | "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c", | 208 | "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c", |
209 | i, sn, | 209 | i, sn, |
@@ -218,6 +218,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v) | |||
218 | mdev->state.peer_isp ? 'p' : '-', | 218 | mdev->state.peer_isp ? 'p' : '-', |
219 | mdev->state.user_isp ? 'u' : '-', | 219 | mdev->state.user_isp ? 'u' : '-', |
220 | mdev->congestion_reason ?: '-', | 220 | mdev->congestion_reason ?: '-', |
221 | test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-', | ||
221 | mdev->send_cnt/2, | 222 | mdev->send_cnt/2, |
222 | mdev->recv_cnt/2, | 223 | mdev->recv_cnt/2, |
223 | mdev->writ_cnt/2, | 224 | mdev->writ_cnt/2, |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 3b61d767d9c4..af608b39c4e0 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -94,7 +94,8 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const | |||
94 | */ | 94 | */ |
95 | if (s & RQ_LOCAL_MASK) { | 95 | if (s & RQ_LOCAL_MASK) { |
96 | if (get_ldev_if_state(mdev, D_FAILED)) { | 96 | if (get_ldev_if_state(mdev, D_FAILED)) { |
97 | drbd_al_complete_io(mdev, req->sector); | 97 | if (s & RQ_IN_ACT_LOG) |
98 | drbd_al_complete_io(mdev, req->sector); | ||
98 | put_ldev(mdev); | 99 | put_ldev(mdev); |
99 | } else if (__ratelimit(&drbd_ratelimit_state)) { | 100 | } else if (__ratelimit(&drbd_ratelimit_state)) { |
100 | dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), " | 101 | dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), " |
@@ -802,8 +803,10 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) | |||
802 | * resync extent to finish, and, if necessary, pulls in the target | 803 | * resync extent to finish, and, if necessary, pulls in the target |
803 | * extent into the activity log, which involves further disk io because | 804 | * extent into the activity log, which involves further disk io because |
804 | * of transactional on-disk meta data updates. */ | 805 | * of transactional on-disk meta data updates. */ |
805 | if (rw == WRITE && local) | 806 | if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) { |
807 | req->rq_state |= RQ_IN_ACT_LOG; | ||
806 | drbd_al_begin_io(mdev, sector); | 808 | drbd_al_begin_io(mdev, sector); |
809 | } | ||
807 | 810 | ||
808 | remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || | 811 | remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || |
809 | (mdev->state.pdsk == D_INCONSISTENT && | 812 | (mdev->state.pdsk == D_INCONSISTENT && |
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index f2e45aaa2cd5..181ea0364822 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -189,6 +189,9 @@ enum drbd_req_state_bits { | |||
189 | 189 | ||
190 | /* Set when this is a write, clear for a read */ | 190 | /* Set when this is a write, clear for a read */ |
191 | __RQ_WRITE, | 191 | __RQ_WRITE, |
192 | |||
193 | /* Should call drbd_al_complete_io() for this request... */ | ||
194 | __RQ_IN_ACT_LOG, | ||
192 | }; | 195 | }; |
193 | 196 | ||
194 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) | 197 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) |
@@ -208,6 +211,7 @@ enum drbd_req_state_bits { | |||
208 | #define RQ_NET_MASK (((1UL << __RQ_NET_MAX)-1) & ~RQ_LOCAL_MASK) | 211 | #define RQ_NET_MASK (((1UL << __RQ_NET_MAX)-1) & ~RQ_LOCAL_MASK) |
209 | 212 | ||
210 | #define RQ_WRITE (1UL << __RQ_WRITE) | 213 | #define RQ_WRITE (1UL << __RQ_WRITE) |
214 | #define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG) | ||
211 | 215 | ||
212 | /* For waking up the frozen transfer log mod_req() has to return if the request | 216 | /* For waking up the frozen transfer log mod_req() has to return if the request |
213 | should be counted in the epoch object*/ | 217 | should be counted in the epoch object*/ |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 3d0e14e3ade3..8be983263374 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -1273,7 +1273,7 @@ int w_restart_disk_io(struct drbd_conf *mdev, struct drbd_work *w, int cancel) | |||
1273 | { | 1273 | { |
1274 | struct drbd_request *req = container_of(w, struct drbd_request, w); | 1274 | struct drbd_request *req = container_of(w, struct drbd_request, w); |
1275 | 1275 | ||
1276 | if (bio_data_dir(req->master_bio) == WRITE) | 1276 | if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG) |
1277 | drbd_al_begin_io(mdev, req->sector); | 1277 | drbd_al_begin_io(mdev, req->sector); |
1278 | /* Calling drbd_al_begin_io() out of the worker might deadlocks | 1278 | /* Calling drbd_al_begin_io() out of the worker might deadlocks |
1279 | theoretically. Practically it can not deadlock, since this is | 1279 | theoretically. Practically it can not deadlock, since this is |