aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2010-08-31 06:00:50 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 12:38:26 -0400
commit0778286a133d2d3f81861a4e5db308e359583006 (patch)
tree14bdfe375481d8954ada1ddaa0bc84fcaba4e23d /drivers/block
parentd53733893dc43f4ebb5be510863c5debf0f8990b (diff)
drbd: Disable activity log updates when the whole device is out of sync
When the complete device is marked as out of sync, we can disable updates of the on disk AL. Currently AL updates are only disabled if one uses the "invalidate-remote" command on an unconnected, primary device, or when at attach time all bits in the bitmap are set. As of now, AL updated do not get disabled when a all bits becomes set due to application writes to an unconnected DRBD device. While this is a missing feature, it is not considered important, and might get added later. BTW, after initializing a "one legged" DRBD device drbdadm create-md resX drbdadm -- --force primary resX AL updates also get disabled, until the first connect. 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_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