aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-03-01 05:08:28 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-03-10 05:48:16 -0500
commit7fde2be93080c028c20078a2d6abec8a95891192 (patch)
tree47993e3c52d550d22ab8035de94d526d226bc2e6
parentc5a91619793d444e5103ec5841045bf878718398 (diff)
drbd: Implemented real timeout checking for request processing time
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r--drivers/block/drbd/drbd_int.h1
-rw-r--r--drivers/block/drbd/drbd_main.c3
-rw-r--r--drivers/block/drbd/drbd_receiver.c3
-rw-r--r--drivers/block/drbd/drbd_req.c39
-rw-r--r--drivers/block/drbd/drbd_req.h1
5 files changed, 47 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 267d9897ca8c..81030d8d654b 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -990,6 +990,7 @@ struct drbd_conf {
990 struct timer_list resync_timer; 990 struct timer_list resync_timer;
991 struct timer_list md_sync_timer; 991 struct timer_list md_sync_timer;
992 struct timer_list start_resync_timer; 992 struct timer_list start_resync_timer;
993 struct timer_list request_timer;
993#ifdef DRBD_DEBUG_MD_SYNC 994#ifdef DRBD_DEBUG_MD_SYNC
994 struct { 995 struct {
995 unsigned int line; 996 unsigned int line;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 9043772de400..dfc85f32d317 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -3017,12 +3017,15 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
3017 init_timer(&mdev->resync_timer); 3017 init_timer(&mdev->resync_timer);
3018 init_timer(&mdev->md_sync_timer); 3018 init_timer(&mdev->md_sync_timer);
3019 init_timer(&mdev->start_resync_timer); 3019 init_timer(&mdev->start_resync_timer);
3020 init_timer(&mdev->request_timer);
3020 mdev->resync_timer.function = resync_timer_fn; 3021 mdev->resync_timer.function = resync_timer_fn;
3021 mdev->resync_timer.data = (unsigned long) mdev; 3022 mdev->resync_timer.data = (unsigned long) mdev;
3022 mdev->md_sync_timer.function = md_sync_timer_fn; 3023 mdev->md_sync_timer.function = md_sync_timer_fn;
3023 mdev->md_sync_timer.data = (unsigned long) mdev; 3024 mdev->md_sync_timer.data = (unsigned long) mdev;
3024 mdev->start_resync_timer.function = start_resync_timer_fn; 3025 mdev->start_resync_timer.function = start_resync_timer_fn;
3025 mdev->start_resync_timer.data = (unsigned long) mdev; 3026 mdev->start_resync_timer.data = (unsigned long) mdev;
3027 mdev->request_timer.function = request_timer_fn;
3028 mdev->request_timer.data = (unsigned long) mdev;
3026 3029
3027 init_waitqueue_head(&mdev->misc_wait); 3030 init_waitqueue_head(&mdev->misc_wait);
3028 init_waitqueue_head(&mdev->state_wait); 3031 init_waitqueue_head(&mdev->state_wait);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 3d62ac7cdc4a..fe1564c7d8b6 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -912,6 +912,7 @@ retry:
912 drbd_send_state(mdev); 912 drbd_send_state(mdev);
913 clear_bit(USE_DEGR_WFC_T, &mdev->flags); 913 clear_bit(USE_DEGR_WFC_T, &mdev->flags);
914 clear_bit(RESIZE_PENDING, &mdev->flags); 914 clear_bit(RESIZE_PENDING, &mdev->flags);
915 mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
915 916
916 return 1; 917 return 1;
917 918
@@ -3822,6 +3823,8 @@ static void drbd_disconnect(struct drbd_conf *mdev)
3822 atomic_set(&mdev->rs_pending_cnt, 0); 3823 atomic_set(&mdev->rs_pending_cnt, 0);
3823 wake_up(&mdev->misc_wait); 3824 wake_up(&mdev->misc_wait);
3824 3825
3826 del_timer(&mdev->request_timer);
3827
3825 /* make sure syncer is stopped and w_resume_next_sg queued */ 3828 /* make sure syncer is stopped and w_resume_next_sg queued */
3826 del_timer_sync(&mdev->resync_timer); 3829 del_timer_sync(&mdev->resync_timer);
3827 resync_timer_fn((unsigned long)mdev); 3830 resync_timer_fn((unsigned long)mdev);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 94fd5a2be559..c2cc28a55907 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1194,3 +1194,42 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
1194 } 1194 }
1195 return limit; 1195 return limit;
1196} 1196}
1197
1198void request_timer_fn(unsigned long data)
1199{
1200 struct drbd_conf *mdev = (struct drbd_conf *) data;
1201 struct drbd_request *req; /* oldest request */
1202 struct list_head *le;
1203 unsigned long et = 0; /* effective timeout = ko_count * timeout */
1204
1205 if (get_net_conf(mdev)) {
1206 et = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count;
1207 put_net_conf(mdev);
1208 }
1209 if (!et || mdev->state.conn < C_WF_REPORT_PARAMS)
1210 return; /* Recurring timer stopped */
1211
1212 spin_lock_irq(&mdev->req_lock);
1213 le = &mdev->oldest_tle->requests;
1214 if (list_empty(le)) {
1215 spin_unlock_irq(&mdev->req_lock);
1216 mod_timer(&mdev->request_timer, jiffies + et);
1217 return;
1218 }
1219
1220 le = le->prev;
1221 req = list_entry(le, struct drbd_request, tl_requests);
1222 if (time_is_before_eq_jiffies(req->start_time + et)) {
1223 if (req->rq_state & RQ_NET_PENDING) {
1224 dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n");
1225 _drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE, NULL);
1226 } else {
1227 dev_warn(DEV, "Local backing block device frozen?\n");
1228 mod_timer(&mdev->request_timer, jiffies + et);
1229 }
1230 } else {
1231 mod_timer(&mdev->request_timer, req->start_time + et);
1232 }
1233
1234 spin_unlock_irq(&mdev->req_lock);
1235}
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 32c1f2a31266..32e2c3e6a813 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -322,6 +322,7 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
322 struct bio_and_error *m); 322 struct bio_and_error *m);
323extern void complete_master_bio(struct drbd_conf *mdev, 323extern void complete_master_bio(struct drbd_conf *mdev,
324 struct bio_and_error *m); 324 struct bio_and_error *m);
325extern void request_timer_fn(unsigned long data);
325 326
326/* use this if you don't want to deal with calling complete_master_bio() 327/* use this if you don't want to deal with calling complete_master_bio()
327 * outside the spinlock, e.g. when walking some list on cleanup. */ 328 * outside the spinlock, e.g. when walking some list on cleanup. */