aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_bitmap.c2
-rw-r--r--drivers/block/drbd/drbd_int.h2
-rw-r--r--drivers/block/drbd/drbd_main.c12
-rw-r--r--drivers/block/drbd/drbd_nl.c54
-rw-r--r--drivers/block/drbd/drbd_proc.c3
-rw-r--r--drivers/block/drbd/drbd_req.c7
-rw-r--r--drivers/block/drbd/drbd_req.h4
-rw-r--r--drivers/block/drbd/drbd_worker.c2
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 */
572static unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev) 572unsigned 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
868struct drbd_bitmap; /* opaque for drbd_conf */ 869struct 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() */
1426extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo); 1427extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
1427extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo); 1428extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo);
1429extern unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev);
1428extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev); 1430extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev);
1429extern int drbd_bm_rs_done(struct drbd_conf *mdev); 1431extern 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
966static 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(). */
781static 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 */
782static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, 805static 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
1821static 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
1795static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, 1830static 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