aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2013-10-23 04:59:19 -0400
committerJens Axboe <axboe@kernel.dk>2013-11-08 11:10:29 -0500
commit35f47ef1a1f069cd2f346314fb8212bb49571eac (patch)
tree78ff95a7c082c0a7a2d3d87bbdfea47773321f74
parentd2da5b0cb522c48f8e2f311e6e9b212535371b56 (diff)
drbd: avoid to shrink max_bio_size due to peer re-configuration
For a long time, the receiving side has spread "too large" incoming requests over multiple bios. No need to shrink our max_bio_size (max_hw_sectors) if the peer is reconfigured to use a different storage. The problem manifests itself if we are not the top of the device stack (DRBD is used a LVM PV). A hardware reconfiguration on the peer may cause the supported max_bio_size to shrink, and the connection handshake would now unnecessarily shrink the max_bio_size on the active node. There is no way to notify upper layers that they have to "re-stack" their limits. So they won't notice at all, and may keep submitting bios that are suddenly considered "too large for device". We already check for compatibility and ignore changes on the peer, the code only was masked out unless we have a fully established connection. We just need to allow it a bit earlier during the handshake. Also consider max_hw_sectors in our merge bvec function, just in case. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/drbd/drbd_nl.c4
-rw-r--r--drivers/block/drbd/drbd_req.c3
2 files changed, 5 insertions, 2 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 37dad18ba153..c706d50a8b06 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1132,9 +1132,9 @@ void drbd_reconsider_max_bio_size(struct drbd_conf *mdev)
1132 /* We may ignore peer limits if the peer is modern enough. 1132 /* We may ignore peer limits if the peer is modern enough.
1133 Because new from 8.3.8 onwards the peer can use multiple 1133 Because new from 8.3.8 onwards the peer can use multiple
1134 BIOs for a single peer_request */ 1134 BIOs for a single peer_request */
1135 if (mdev->state.conn >= C_CONNECTED) { 1135 if (mdev->state.conn >= C_WF_REPORT_PARAMS) {
1136 if (mdev->tconn->agreed_pro_version < 94) 1136 if (mdev->tconn->agreed_pro_version < 94)
1137 peer = min( mdev->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET); 1137 peer = min(mdev->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
1138 /* Correct old drbd (up to 8.3.7) if it believes it can do more than 32KiB */ 1138 /* Correct old drbd (up to 8.3.7) if it believes it can do more than 32KiB */
1139 else if (mdev->tconn->agreed_pro_version == 94) 1139 else if (mdev->tconn->agreed_pro_version == 94)
1140 peer = DRBD_MAX_SIZE_H80_PACKET; 1140 peer = DRBD_MAX_SIZE_H80_PACKET;
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index c24379ffd4e3..fec7bef44994 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1306,6 +1306,7 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
1306 int backing_limit; 1306 int backing_limit;
1307 1307
1308 if (bio_size && get_ldev(mdev)) { 1308 if (bio_size && get_ldev(mdev)) {
1309 unsigned int max_hw_sectors = queue_max_hw_sectors(q);
1309 struct request_queue * const b = 1310 struct request_queue * const b =
1310 mdev->ldev->backing_bdev->bd_disk->queue; 1311 mdev->ldev->backing_bdev->bd_disk->queue;
1311 if (b->merge_bvec_fn) { 1312 if (b->merge_bvec_fn) {
@@ -1313,6 +1314,8 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
1313 limit = min(limit, backing_limit); 1314 limit = min(limit, backing_limit);
1314 } 1315 }
1315 put_ldev(mdev); 1316 put_ldev(mdev);
1317 if ((limit >> 9) > max_hw_sectors)
1318 limit = max_hw_sectors << 9;
1316 } 1319 }
1317 return limit; 1320 return limit;
1318} 1321}