mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
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>
This commit is contained in:
parent
c5a9161979
commit
7fde2be930
@ -990,6 +990,7 @@ struct drbd_conf {
|
||||
struct timer_list resync_timer;
|
||||
struct timer_list md_sync_timer;
|
||||
struct timer_list start_resync_timer;
|
||||
struct timer_list request_timer;
|
||||
#ifdef DRBD_DEBUG_MD_SYNC
|
||||
struct {
|
||||
unsigned int line;
|
||||
|
@ -3017,12 +3017,15 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
|
||||
init_timer(&mdev->resync_timer);
|
||||
init_timer(&mdev->md_sync_timer);
|
||||
init_timer(&mdev->start_resync_timer);
|
||||
init_timer(&mdev->request_timer);
|
||||
mdev->resync_timer.function = resync_timer_fn;
|
||||
mdev->resync_timer.data = (unsigned long) mdev;
|
||||
mdev->md_sync_timer.function = md_sync_timer_fn;
|
||||
mdev->md_sync_timer.data = (unsigned long) mdev;
|
||||
mdev->start_resync_timer.function = start_resync_timer_fn;
|
||||
mdev->start_resync_timer.data = (unsigned long) mdev;
|
||||
mdev->request_timer.function = request_timer_fn;
|
||||
mdev->request_timer.data = (unsigned long) mdev;
|
||||
|
||||
init_waitqueue_head(&mdev->misc_wait);
|
||||
init_waitqueue_head(&mdev->state_wait);
|
||||
|
@ -912,6 +912,7 @@ retry:
|
||||
drbd_send_state(mdev);
|
||||
clear_bit(USE_DEGR_WFC_T, &mdev->flags);
|
||||
clear_bit(RESIZE_PENDING, &mdev->flags);
|
||||
mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
|
||||
|
||||
return 1;
|
||||
|
||||
@ -3822,6 +3823,8 @@ static void drbd_disconnect(struct drbd_conf *mdev)
|
||||
atomic_set(&mdev->rs_pending_cnt, 0);
|
||||
wake_up(&mdev->misc_wait);
|
||||
|
||||
del_timer(&mdev->request_timer);
|
||||
|
||||
/* make sure syncer is stopped and w_resume_next_sg queued */
|
||||
del_timer_sync(&mdev->resync_timer);
|
||||
resync_timer_fn((unsigned long)mdev);
|
||||
|
@ -1194,3 +1194,42 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
void request_timer_fn(unsigned long data)
|
||||
{
|
||||
struct drbd_conf *mdev = (struct drbd_conf *) data;
|
||||
struct drbd_request *req; /* oldest request */
|
||||
struct list_head *le;
|
||||
unsigned long et = 0; /* effective timeout = ko_count * timeout */
|
||||
|
||||
if (get_net_conf(mdev)) {
|
||||
et = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count;
|
||||
put_net_conf(mdev);
|
||||
}
|
||||
if (!et || mdev->state.conn < C_WF_REPORT_PARAMS)
|
||||
return; /* Recurring timer stopped */
|
||||
|
||||
spin_lock_irq(&mdev->req_lock);
|
||||
le = &mdev->oldest_tle->requests;
|
||||
if (list_empty(le)) {
|
||||
spin_unlock_irq(&mdev->req_lock);
|
||||
mod_timer(&mdev->request_timer, jiffies + et);
|
||||
return;
|
||||
}
|
||||
|
||||
le = le->prev;
|
||||
req = list_entry(le, struct drbd_request, tl_requests);
|
||||
if (time_is_before_eq_jiffies(req->start_time + et)) {
|
||||
if (req->rq_state & RQ_NET_PENDING) {
|
||||
dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n");
|
||||
_drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE, NULL);
|
||||
} else {
|
||||
dev_warn(DEV, "Local backing block device frozen?\n");
|
||||
mod_timer(&mdev->request_timer, jiffies + et);
|
||||
}
|
||||
} else {
|
||||
mod_timer(&mdev->request_timer, req->start_time + et);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&mdev->req_lock);
|
||||
}
|
||||
|
@ -322,6 +322,7 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
|
||||
struct bio_and_error *m);
|
||||
extern void complete_master_bio(struct drbd_conf *mdev,
|
||||
struct bio_and_error *m);
|
||||
extern void request_timer_fn(unsigned long data);
|
||||
|
||||
/* use this if you don't want to deal with calling complete_master_bio()
|
||||
* outside the spinlock, e.g. when walking some list on cleanup. */
|
||||
|
Loading…
Reference in New Issue
Block a user