aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2014-05-05 17:42:24 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2014-07-10 12:35:14 -0400
commit21ae5d7f95aa1a64f35b03c91f8714ced3ab61a9 (patch)
tree9e5d90197118d8110c9a65f07f639c5eae000044 /drivers/block
parentad3fee790088d36ad862e31535b5b99c25adeef4 (diff)
drbd: track timing details of peer_requests
To be able to present timing details in debugfs, we need to track preparation/submit times of peer requests. Track peer request flags early, before they are put on the epoch_entry lists. Waiting for activity log transactions may be a major latency factor. We want to be able to present the peer_request state accurately in debugfs, and what it is waiting for. Consistently mark/unmark peer requests with EE_CALL_AL_COMPLETE_IO. Set it only *after* calling drbd_al_begin_io(), clear it as soon as we call drbd_al_complete_io(). Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_int.h15
-rw-r--r--drivers/block/drbd/drbd_receiver.c78
-rw-r--r--drivers/block/drbd/drbd_worker.c1
3 files changed, 64 insertions, 30 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 81f4af49b8ac..c7a409f3aaf8 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -422,6 +422,7 @@ struct drbd_peer_request {
422 struct drbd_interval i; 422 struct drbd_interval i;
423 /* see comments on ee flag bits below */ 423 /* see comments on ee flag bits below */
424 unsigned long flags; 424 unsigned long flags;
425 unsigned long submit_jif;
425 union { 426 union {
426 u64 block_id; 427 u64 block_id;
427 struct digest_info *digest; 428 struct digest_info *digest;
@@ -464,6 +465,17 @@ enum {
464 465
465 /* Is set when net_conf had two_primaries set while creating this peer_req */ 466 /* Is set when net_conf had two_primaries set while creating this peer_req */
466 __EE_IN_INTERVAL_TREE, 467 __EE_IN_INTERVAL_TREE,
468
469 /* for debugfs: */
470 /* has this been submitted, or does it still wait for something else? */
471 __EE_SUBMITTED,
472
473 /* this is/was a write request */
474 __EE_WRITE,
475
476 /* this originates from application on peer
477 * (not some resync or verify or other DRBD internal request) */
478 __EE_APPLICATION,
467}; 479};
468#define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO) 480#define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
469#define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC) 481#define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC)
@@ -475,6 +487,9 @@ enum {
475#define EE_RESTART_REQUESTS (1<<__EE_RESTART_REQUESTS) 487#define EE_RESTART_REQUESTS (1<<__EE_RESTART_REQUESTS)
476#define EE_SEND_WRITE_ACK (1<<__EE_SEND_WRITE_ACK) 488#define EE_SEND_WRITE_ACK (1<<__EE_SEND_WRITE_ACK)
477#define EE_IN_INTERVAL_TREE (1<<__EE_IN_INTERVAL_TREE) 489#define EE_IN_INTERVAL_TREE (1<<__EE_IN_INTERVAL_TREE)
490#define EE_SUBMITTED (1<<__EE_SUBMITTED)
491#define EE_WRITE (1<<__EE_WRITE)
492#define EE_APPLICATION (1<<__EE_APPLICATION)
478 493
479/* flag bits per device */ 494/* flag bits per device */
480enum { 495enum {
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 0d3cbd8e4b9c..2f67dc03d403 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -389,11 +389,16 @@ drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t secto
389void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *peer_req, 389void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *peer_req,
390 int is_net) 390 int is_net)
391{ 391{
392 might_sleep();
392 if (peer_req->flags & EE_HAS_DIGEST) 393 if (peer_req->flags & EE_HAS_DIGEST)
393 kfree(peer_req->digest); 394 kfree(peer_req->digest);
394 drbd_free_pages(device, peer_req->pages, is_net); 395 drbd_free_pages(device, peer_req->pages, is_net);
395 D_ASSERT(device, atomic_read(&peer_req->pending_bios) == 0); 396 D_ASSERT(device, atomic_read(&peer_req->pending_bios) == 0);
396 D_ASSERT(device, drbd_interval_empty(&peer_req->i)); 397 D_ASSERT(device, drbd_interval_empty(&peer_req->i));
398 if (!expect(!(peer_req->flags & EE_CALL_AL_COMPLETE_IO))) {
399 peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
400 drbd_al_complete_io(device, &peer_req->i);
401 }
397 mempool_free(peer_req, drbd_ee_mempool); 402 mempool_free(peer_req, drbd_ee_mempool);
398} 403}
399 404
@@ -1372,6 +1377,8 @@ int drbd_submit_peer_request(struct drbd_device *device,
1372 conn_wait_active_ee_empty(first_peer_device(device)->connection); 1377 conn_wait_active_ee_empty(first_peer_device(device)->connection);
1373 /* add it to the active list now, 1378 /* add it to the active list now,
1374 * so we can find it to present it in debugfs */ 1379 * so we can find it to present it in debugfs */
1380 peer_req->submit_jif = jiffies;
1381 peer_req->flags |= EE_SUBMITTED;
1375 spin_lock_irq(&device->resource->req_lock); 1382 spin_lock_irq(&device->resource->req_lock);
1376 list_add_tail(&peer_req->w.list, &device->active_ee); 1383 list_add_tail(&peer_req->w.list, &device->active_ee);
1377 spin_unlock_irq(&device->resource->req_lock); 1384 spin_unlock_irq(&device->resource->req_lock);
@@ -1443,6 +1450,9 @@ submit:
1443 D_ASSERT(device, page == NULL); 1450 D_ASSERT(device, page == NULL);
1444 1451
1445 atomic_set(&peer_req->pending_bios, n_bios); 1452 atomic_set(&peer_req->pending_bios, n_bios);
1453 /* for debugfs: update timestamp, mark as submitted */
1454 peer_req->submit_jif = jiffies;
1455 peer_req->flags |= EE_SUBMITTED;
1446 do { 1456 do {
1447 bio = bios; 1457 bio = bios;
1448 bios = bios->bi_next; 1458 bios = bios->bi_next;
@@ -1624,6 +1634,7 @@ read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
1624 if (!peer_req) 1634 if (!peer_req)
1625 return NULL; 1635 return NULL;
1626 1636
1637 peer_req->flags |= EE_WRITE;
1627 if (trim) 1638 if (trim)
1628 return peer_req; 1639 return peer_req;
1629 1640
@@ -1780,6 +1791,7 @@ static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto
1780 * respective _drbd_clear_done_ee */ 1791 * respective _drbd_clear_done_ee */
1781 1792
1782 peer_req->w.cb = e_end_resync_block; 1793 peer_req->w.cb = e_end_resync_block;
1794 peer_req->submit_jif = jiffies;
1783 1795
1784 spin_lock_irq(&device->resource->req_lock); 1796 spin_lock_irq(&device->resource->req_lock);
1785 list_add_tail(&peer_req->w.list, &device->sync_ee); 1797 list_add_tail(&peer_req->w.list, &device->sync_ee);
@@ -2196,7 +2208,6 @@ static int handle_write_conflicts(struct drbd_device *device,
2196 (unsigned long long)sector, size, 2208 (unsigned long long)sector, size,
2197 superseded ? "local" : "remote"); 2209 superseded ? "local" : "remote");
2198 2210
2199 inc_unacked(device);
2200 peer_req->w.cb = superseded ? e_send_superseded : 2211 peer_req->w.cb = superseded ? e_send_superseded :
2201 e_send_retry_write; 2212 e_send_retry_write;
2202 list_add_tail(&peer_req->w.list, &device->done_ee); 2213 list_add_tail(&peer_req->w.list, &device->done_ee);
@@ -2255,6 +2266,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
2255{ 2266{
2256 struct drbd_peer_device *peer_device; 2267 struct drbd_peer_device *peer_device;
2257 struct drbd_device *device; 2268 struct drbd_device *device;
2269 struct net_conf *nc;
2258 sector_t sector; 2270 sector_t sector;
2259 struct drbd_peer_request *peer_req; 2271 struct drbd_peer_request *peer_req;
2260 struct p_data *p = pi->data; 2272 struct p_data *p = pi->data;
@@ -2294,6 +2306,8 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
2294 } 2306 }
2295 2307
2296 peer_req->w.cb = e_end_block; 2308 peer_req->w.cb = e_end_block;
2309 peer_req->submit_jif = jiffies;
2310 peer_req->flags |= EE_APPLICATION;
2297 2311
2298 dp_flags = be32_to_cpu(p->dp_flags); 2312 dp_flags = be32_to_cpu(p->dp_flags);
2299 rw |= wire_flags_to_bio(dp_flags); 2313 rw |= wire_flags_to_bio(dp_flags);
@@ -2320,9 +2334,36 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
2320 spin_unlock(&connection->epoch_lock); 2334 spin_unlock(&connection->epoch_lock);
2321 2335
2322 rcu_read_lock(); 2336 rcu_read_lock();
2323 tp = rcu_dereference(peer_device->connection->net_conf)->two_primaries; 2337 nc = rcu_dereference(peer_device->connection->net_conf);
2338 tp = nc->two_primaries;
2339 if (peer_device->connection->agreed_pro_version < 100) {
2340 switch (nc->wire_protocol) {
2341 case DRBD_PROT_C:
2342 dp_flags |= DP_SEND_WRITE_ACK;
2343 break;
2344 case DRBD_PROT_B:
2345 dp_flags |= DP_SEND_RECEIVE_ACK;
2346 break;
2347 }
2348 }
2324 rcu_read_unlock(); 2349 rcu_read_unlock();
2350
2351 if (dp_flags & DP_SEND_WRITE_ACK) {
2352 peer_req->flags |= EE_SEND_WRITE_ACK;
2353 inc_unacked(device);
2354 /* corresponding dec_unacked() in e_end_block()
2355 * respective _drbd_clear_done_ee */
2356 }
2357
2358 if (dp_flags & DP_SEND_RECEIVE_ACK) {
2359 /* I really don't like it that the receiver thread
2360 * sends on the msock, but anyways */
2361 drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
2362 }
2363
2325 if (tp) { 2364 if (tp) {
2365 /* two primaries implies protocol C */
2366 D_ASSERT(device, dp_flags & DP_SEND_WRITE_ACK);
2326 peer_req->flags |= EE_IN_INTERVAL_TREE; 2367 peer_req->flags |= EE_IN_INTERVAL_TREE;
2327 err = wait_for_and_update_peer_seq(peer_device, peer_seq); 2368 err = wait_for_and_update_peer_seq(peer_device, peer_seq);
2328 if (err) 2369 if (err)
@@ -2352,38 +2393,12 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
2352 if (device->state.conn == C_SYNC_TARGET) 2393 if (device->state.conn == C_SYNC_TARGET)
2353 wait_event(device->ee_wait, !overlapping_resync_write(device, peer_req)); 2394 wait_event(device->ee_wait, !overlapping_resync_write(device, peer_req));
2354 2395
2355 if (peer_device->connection->agreed_pro_version < 100) {
2356 rcu_read_lock();
2357 switch (rcu_dereference(peer_device->connection->net_conf)->wire_protocol) {
2358 case DRBD_PROT_C:
2359 dp_flags |= DP_SEND_WRITE_ACK;
2360 break;
2361 case DRBD_PROT_B:
2362 dp_flags |= DP_SEND_RECEIVE_ACK;
2363 break;
2364 }
2365 rcu_read_unlock();
2366 }
2367
2368 if (dp_flags & DP_SEND_WRITE_ACK) {
2369 peer_req->flags |= EE_SEND_WRITE_ACK;
2370 inc_unacked(device);
2371 /* corresponding dec_unacked() in e_end_block()
2372 * respective _drbd_clear_done_ee */
2373 }
2374
2375 if (dp_flags & DP_SEND_RECEIVE_ACK) {
2376 /* I really don't like it that the receiver thread
2377 * sends on the msock, but anyways */
2378 drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
2379 }
2380
2381 if (device->state.pdsk < D_INCONSISTENT) { 2396 if (device->state.pdsk < D_INCONSISTENT) {
2382 /* In case we have the only disk of the cluster, */ 2397 /* In case we have the only disk of the cluster, */
2383 drbd_set_out_of_sync(device, peer_req->i.sector, peer_req->i.size); 2398 drbd_set_out_of_sync(device, peer_req->i.sector, peer_req->i.size);
2384 peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
2385 peer_req->flags &= ~EE_MAY_SET_IN_SYNC; 2399 peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
2386 drbd_al_begin_io(device, &peer_req->i); 2400 drbd_al_begin_io(device, &peer_req->i);
2401 peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
2387 } 2402 }
2388 2403
2389 err = drbd_submit_peer_request(device, peer_req, rw, DRBD_FAULT_DT_WR); 2404 err = drbd_submit_peer_request(device, peer_req, rw, DRBD_FAULT_DT_WR);
@@ -2396,8 +2411,10 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
2396 list_del(&peer_req->w.list); 2411 list_del(&peer_req->w.list);
2397 drbd_remove_epoch_entry_interval(device, peer_req); 2412 drbd_remove_epoch_entry_interval(device, peer_req);
2398 spin_unlock_irq(&device->resource->req_lock); 2413 spin_unlock_irq(&device->resource->req_lock);
2399 if (peer_req->flags & EE_CALL_AL_COMPLETE_IO) 2414 if (peer_req->flags & EE_CALL_AL_COMPLETE_IO) {
2415 peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
2400 drbd_al_complete_io(device, &peer_req->i); 2416 drbd_al_complete_io(device, &peer_req->i);
2417 }
2401 2418
2402out_interrupted: 2419out_interrupted:
2403 drbd_may_finish_epoch(connection, peer_req->epoch, EV_PUT + EV_CLEANUP); 2420 drbd_may_finish_epoch(connection, peer_req->epoch, EV_PUT + EV_CLEANUP);
@@ -2561,6 +2578,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
2561 peer_req->w.cb = w_e_end_data_req; 2578 peer_req->w.cb = w_e_end_data_req;
2562 fault_type = DRBD_FAULT_DT_RD; 2579 fault_type = DRBD_FAULT_DT_RD;
2563 /* application IO, don't drbd_rs_begin_io */ 2580 /* application IO, don't drbd_rs_begin_io */
2581 peer_req->flags |= EE_APPLICATION;
2564 goto submit; 2582 goto submit;
2565 2583
2566 case P_RS_DATA_REQUEST: 2584 case P_RS_DATA_REQUEST:
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 48975a264985..b908e9b3f63e 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -132,6 +132,7 @@ void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(l
132 i = peer_req->i; 132 i = peer_req->i;
133 do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO; 133 do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
134 block_id = peer_req->block_id; 134 block_id = peer_req->block_id;
135 peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
135 136
136 spin_lock_irqsave(&device->resource->req_lock, flags); 137 spin_lock_irqsave(&device->resource->req_lock, flags);
137 device->writ_cnt += peer_req->i.size >> 9; 138 device->writ_cnt += peer_req->i.size >> 9;