aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2014-04-28 12:43:31 -0400
committerJens Axboe <axboe@fb.com>2014-04-30 15:46:55 -0400
commit08535466bce6bd91320990b9a614d52a3dc0f21d (patch)
treef42c7cffbb916a9b29c51bb281f9d070bb3633e6 /drivers/block/drbd
parent67cca286caa6e33f3134bd36834d2484538f4f78 (diff)
drbd: evaluate disk and network timeout on different requests
Just because it is the oldest not yet completed request does not make it the oldest request waiting for disk. Or waiting for the peer. And we completely missed already completed requests that would still hold references to activity log extents, waiting only for the barrier ack. Find two oldest not yet completely processed requests, one that is still waiting for local completion, and one that is still waiting for some response from the peer. These may or may not be the same request object. Then separately apply the network and disk timeouts, respectively. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_req.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 99411bf9d901..09803d0d5207 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1353,23 +1353,35 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
1353 return limit; 1353 return limit;
1354} 1354}
1355 1355
1356static struct drbd_request *find_oldest_request(struct drbd_connection *connection) 1356static void find_oldest_requests(
1357 struct drbd_connection *connection,
1358 struct drbd_device *device,
1359 struct drbd_request **oldest_req_waiting_for_peer,
1360 struct drbd_request **oldest_req_waiting_for_disk)
1357{ 1361{
1358 /* Walk the transfer log,
1359 * and find the oldest not yet completed request */
1360 struct drbd_request *r; 1362 struct drbd_request *r;
1363 *oldest_req_waiting_for_peer = NULL;
1364 *oldest_req_waiting_for_disk = NULL;
1361 list_for_each_entry(r, &connection->transfer_log, tl_requests) { 1365 list_for_each_entry(r, &connection->transfer_log, tl_requests) {
1362 if (atomic_read(&r->completion_ref)) 1366 const unsigned s = r->rq_state;
1363 return r; 1367 if (!*oldest_req_waiting_for_peer
1368 && ((s & RQ_NET_MASK) && !(s & RQ_NET_DONE)))
1369 *oldest_req_waiting_for_peer = r;
1370
1371 if (!*oldest_req_waiting_for_disk
1372 && (s & RQ_LOCAL_PENDING) && r->device == device)
1373 *oldest_req_waiting_for_disk = r;
1374
1375 if (*oldest_req_waiting_for_peer && *oldest_req_waiting_for_disk)
1376 break;
1364 } 1377 }
1365 return NULL;
1366} 1378}
1367 1379
1368void request_timer_fn(unsigned long data) 1380void request_timer_fn(unsigned long data)
1369{ 1381{
1370 struct drbd_device *device = (struct drbd_device *) data; 1382 struct drbd_device *device = (struct drbd_device *) data;
1371 struct drbd_connection *connection = first_peer_device(device)->connection; 1383 struct drbd_connection *connection = first_peer_device(device)->connection;
1372 struct drbd_request *req; /* oldest request */ 1384 struct drbd_request *req_disk, *req_peer; /* oldest request */
1373 struct net_conf *nc; 1385 struct net_conf *nc;
1374 unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */ 1386 unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */
1375 unsigned long now; 1387 unsigned long now;
@@ -1393,8 +1405,8 @@ void request_timer_fn(unsigned long data)
1393 now = jiffies; 1405 now = jiffies;
1394 1406
1395 spin_lock_irq(&device->resource->req_lock); 1407 spin_lock_irq(&device->resource->req_lock);
1396 req = find_oldest_request(connection); 1408 find_oldest_requests(connection, device, &req_peer, &req_disk);
1397 if (!req) { 1409 if (req_peer == NULL && req_disk == NULL) {
1398 spin_unlock_irq(&device->resource->req_lock); 1410 spin_unlock_irq(&device->resource->req_lock);
1399 mod_timer(&device->request_timer, now + et); 1411 mod_timer(&device->request_timer, now + et);
1400 return; 1412 return;
@@ -1416,19 +1428,26 @@ void request_timer_fn(unsigned long data)
1416 * ~198 days with 250 HZ, we have a window where the timeout would need 1428 * ~198 days with 250 HZ, we have a window where the timeout would need
1417 * to expire twice (worst case) to become effective. Good enough. 1429 * to expire twice (worst case) to become effective. Good enough.
1418 */ 1430 */
1419 if (ent && req->rq_state & RQ_NET_PENDING && 1431 if (ent && req_peer &&
1420 time_after(now, req->start_time + ent) && 1432 time_after(now, req_peer->start_time + ent) &&
1421 !time_in_range(now, connection->last_reconnect_jif, connection->last_reconnect_jif + ent)) { 1433 !time_in_range(now, connection->last_reconnect_jif, connection->last_reconnect_jif + ent)) {
1422 drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n"); 1434 drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n");
1423 _drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL); 1435 _drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
1424 } 1436 }
1425 if (dt && req->rq_state & RQ_LOCAL_PENDING && req->device == device && 1437 if (dt && req_disk &&
1426 time_after(now, req->start_time + dt) && 1438 time_after(now, req_disk->start_time + dt) &&
1427 !time_in_range(now, device->last_reattach_jif, device->last_reattach_jif + dt)) { 1439 !time_in_range(now, device->last_reattach_jif, device->last_reattach_jif + dt)) {
1428 drbd_warn(device, "Local backing device failed to meet the disk-timeout\n"); 1440 drbd_warn(device, "Local backing device failed to meet the disk-timeout\n");
1429 __drbd_chk_io_error(device, DRBD_FORCE_DETACH); 1441 __drbd_chk_io_error(device, DRBD_FORCE_DETACH);
1430 } 1442 }
1431 nt = (time_after(now, req->start_time + et) ? now : req->start_time) + et; 1443
1444 /* Reschedule timer for the nearest not already expired timeout.
1445 * Fallback to now + min(effective network timeout, disk timeout). */
1446 ent = (ent && req_peer && time_before(now, req_peer->start_time + ent))
1447 ? req_peer->start_time + ent : now + et;
1448 dt = (dt && req_disk && time_before(now, req_disk->start_time + dt))
1449 ? req_disk->start_time + dt : now + et;
1450 nt = time_before(ent, dt) ? ent : dt;
1432 spin_unlock_irq(&connection->resource->req_lock); 1451 spin_unlock_irq(&connection->resource->req_lock);
1433 mod_timer(&device->request_timer, nt); 1452 mod_timer(&device->request_timer, nt);
1434} 1453}