Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drbd: Implemented the disk-timeout option

When the disk-timeout is active, and it expires for a single request,
we consider the local disk as D_FAILED. Note: With this change,
I made both timeout based state transitions HARD state transitions.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>

+31 -14
+5
drivers/block/drbd/drbd_main.c
··· 1404 1404 /* Here we have the actions that are performed after a 1405 1405 state change. This function might sleep */ 1406 1406 1407 + if (os.disk <= D_NEGOTIATING && ns.disk > D_NEGOTIATING) 1408 + mod_timer(&mdev->request_timer, jiffies + HZ); 1409 + 1407 1410 nsm.i = -1; 1408 1411 if (ns.susp_nod) { 1409 1412 if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) ··· 3320 3317 3321 3318 if (!mdev) 3322 3319 return; 3320 + 3321 + del_timer_sync(&mdev->request_timer); 3323 3322 3324 3323 /* paranoia asserts */ 3325 3324 if (mdev->open_cnt != 0)
-2
drivers/block/drbd/drbd_receiver.c
··· 3803 3803 atomic_set(&mdev->rs_pending_cnt, 0); 3804 3804 wake_up(&mdev->misc_wait); 3805 3805 3806 - del_timer(&mdev->request_timer); 3807 - 3808 3806 /* make sure syncer is stopped and w_resume_next_sg queued */ 3809 3807 del_timer_sync(&mdev->resync_timer); 3810 3808 resync_timer_fn((unsigned long)mdev);
+20 -12
drivers/block/drbd/drbd_req.c
··· 1208 1208 struct drbd_conf *mdev = (struct drbd_conf *) data; 1209 1209 struct drbd_request *req; /* oldest request */ 1210 1210 struct list_head *le; 1211 - unsigned long et = 0; /* effective timeout = ko_count * timeout */ 1211 + unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */ 1212 1212 1213 1213 if (get_net_conf(mdev)) { 1214 - et = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count; 1214 + ent = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count; 1215 1215 put_net_conf(mdev); 1216 1216 } 1217 - if (!et || mdev->state.conn < C_WF_REPORT_PARAMS) 1217 + if (get_ldev(mdev)) { 1218 + dt = mdev->ldev->dc.disk_timeout * HZ / 10; 1219 + put_ldev(mdev); 1220 + } 1221 + et = min_not_zero(dt, ent); 1222 + 1223 + if (!et || (mdev->state.conn < C_WF_REPORT_PARAMS && mdev->state.disk <= D_FAILED)) 1218 1224 return; /* Recurring timer stopped */ 1219 1225 1220 1226 spin_lock_irq(&mdev->req_lock); ··· 1233 1227 1234 1228 le = le->prev; 1235 1229 req = list_entry(le, struct drbd_request, tl_requests); 1236 - if (time_is_before_eq_jiffies(req->start_time + et)) { 1237 - if (req->rq_state & RQ_NET_PENDING) { 1230 + if (ent && req->rq_state & RQ_NET_PENDING) { 1231 + if (time_is_before_eq_jiffies(req->start_time + ent)) { 1238 1232 dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n"); 1239 - _drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE, NULL); 1240 - } else { 1241 - dev_warn(DEV, "Local backing block device frozen?\n"); 1242 - mod_timer(&mdev->request_timer, jiffies + et); 1233 + _drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL); 1243 1234 } 1244 - } else { 1245 - mod_timer(&mdev->request_timer, req->start_time + et); 1246 1235 } 1247 - 1236 + if (dt && req->rq_state & RQ_LOCAL_PENDING) { 1237 + if (time_is_before_eq_jiffies(req->start_time + dt)) { 1238 + dev_warn(DEV, "Local backing device failed to meet the disk-timeout\n"); 1239 + __drbd_chk_io_error(mdev, 1); 1240 + } 1241 + } 1242 + nt = (time_is_before_eq_jiffies(req->start_time + et) ? jiffies : req->start_time) + et; 1248 1243 spin_unlock_irq(&mdev->req_lock); 1244 + mod_timer(&mdev->request_timer, nt); 1249 1245 }
+5
include/linux/drbd_limits.h
··· 48 48 #define DRBD_TIMEOUT_MAX 600 49 49 #define DRBD_TIMEOUT_DEF 60 /* 6 seconds */ 50 50 51 + /* If backing disk takes longer than disk_timeout, mark the disk as failed */ 52 + #define DRBD_DISK_TIMEOUT_MIN 0 /* 0 = disabled */ 53 + #define DRBD_DISK_TIMEOUT_MAX 6000 /* 10 Minutes */ 54 + #define DRBD_DISK_TIMEOUT_DEF 0 /* disabled */ 55 + 51 56 /* active connection retries when C_WF_CONNECTION */ 52 57 #define DRBD_CONNECT_INT_MIN 1 53 58 #define DRBD_CONNECT_INT_MAX 120
+1
include/linux/drbd_nl.h
··· 31 31 NL_INTEGER( 56, T_MAY_IGNORE, max_bio_bvecs) 32 32 NL_BIT( 57, T_MAY_IGNORE, no_disk_barrier) 33 33 NL_BIT( 58, T_MAY_IGNORE, no_disk_drain) 34 + NL_INTEGER( 89, T_MAY_IGNORE, disk_timeout) 34 35 ) 35 36 36 37 NL_PACKET(detach, 4,