mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-21 08:53:41 +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 resync_timer;
|
||||||
struct timer_list md_sync_timer;
|
struct timer_list md_sync_timer;
|
||||||
struct timer_list start_resync_timer;
|
struct timer_list start_resync_timer;
|
||||||
|
struct timer_list request_timer;
|
||||||
#ifdef DRBD_DEBUG_MD_SYNC
|
#ifdef DRBD_DEBUG_MD_SYNC
|
||||||
struct {
|
struct {
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
|
@ -3017,12 +3017,15 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
|
|||||||
init_timer(&mdev->resync_timer);
|
init_timer(&mdev->resync_timer);
|
||||||
init_timer(&mdev->md_sync_timer);
|
init_timer(&mdev->md_sync_timer);
|
||||||
init_timer(&mdev->start_resync_timer);
|
init_timer(&mdev->start_resync_timer);
|
||||||
|
init_timer(&mdev->request_timer);
|
||||||
mdev->resync_timer.function = resync_timer_fn;
|
mdev->resync_timer.function = resync_timer_fn;
|
||||||
mdev->resync_timer.data = (unsigned long) mdev;
|
mdev->resync_timer.data = (unsigned long) mdev;
|
||||||
mdev->md_sync_timer.function = md_sync_timer_fn;
|
mdev->md_sync_timer.function = md_sync_timer_fn;
|
||||||
mdev->md_sync_timer.data = (unsigned long) mdev;
|
mdev->md_sync_timer.data = (unsigned long) mdev;
|
||||||
mdev->start_resync_timer.function = start_resync_timer_fn;
|
mdev->start_resync_timer.function = start_resync_timer_fn;
|
||||||
mdev->start_resync_timer.data = (unsigned long) mdev;
|
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->misc_wait);
|
||||||
init_waitqueue_head(&mdev->state_wait);
|
init_waitqueue_head(&mdev->state_wait);
|
||||||
|
@ -912,6 +912,7 @@ retry:
|
|||||||
drbd_send_state(mdev);
|
drbd_send_state(mdev);
|
||||||
clear_bit(USE_DEGR_WFC_T, &mdev->flags);
|
clear_bit(USE_DEGR_WFC_T, &mdev->flags);
|
||||||
clear_bit(RESIZE_PENDING, &mdev->flags);
|
clear_bit(RESIZE_PENDING, &mdev->flags);
|
||||||
|
mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -3822,6 +3823,8 @@ static void drbd_disconnect(struct drbd_conf *mdev)
|
|||||||
atomic_set(&mdev->rs_pending_cnt, 0);
|
atomic_set(&mdev->rs_pending_cnt, 0);
|
||||||
wake_up(&mdev->misc_wait);
|
wake_up(&mdev->misc_wait);
|
||||||
|
|
||||||
|
del_timer(&mdev->request_timer);
|
||||||
|
|
||||||
/* make sure syncer is stopped and w_resume_next_sg queued */
|
/* make sure syncer is stopped and w_resume_next_sg queued */
|
||||||
del_timer_sync(&mdev->resync_timer);
|
del_timer_sync(&mdev->resync_timer);
|
||||||
resync_timer_fn((unsigned long)mdev);
|
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;
|
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);
|
struct bio_and_error *m);
|
||||||
extern void complete_master_bio(struct drbd_conf *mdev,
|
extern void complete_master_bio(struct drbd_conf *mdev,
|
||||||
struct bio_and_error *m);
|
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()
|
/* 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. */
|
* outside the spinlock, e.g. when walking some list on cleanup. */
|
||||||
|
Loading…
Reference in New Issue
Block a user