Skip to content

Commit 69ba1ee

Browse files
lgeaxboe
authored andcommitted
drbd: possibly disable discard support, if backend has discard_zeroes_data=0
Now that we have the discard_zeroes_if_aligned setting, we should also check it when setting up our queue parameters on the primary, not only on the receiving side. We announce discard support, UNLESS * we are connected to a peer that does not support TRIM on the DRBD protocol level. Otherwise, it would either discard, or do a fallback to zero-out, depending on its backend and configuration. * our local backend does not support discards, or (discard_zeroes_data=0 AND discard_zeroes_if_aligned=no). Signed-off-by: Philipp Reisner <[email protected]> Signed-off-by: Lars Ellenberg <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent dd4f699 commit 69ba1ee

File tree

1 file changed

+55
-25
lines changed

1 file changed

+55
-25
lines changed

drivers/block/drbd/drbd_nl.c

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,59 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
11541154
return 0;
11551155
}
11561156

1157+
static void blk_queue_discard_granularity(struct request_queue *q, unsigned int granularity)
1158+
{
1159+
q->limits.discard_granularity = granularity;
1160+
}
1161+
static void decide_on_discard_support(struct drbd_device *device,
1162+
struct request_queue *q,
1163+
struct request_queue *b,
1164+
bool discard_zeroes_if_aligned)
1165+
{
1166+
/* q = drbd device queue (device->rq_queue)
1167+
* b = backing device queue (device->ldev->backing_bdev->bd_disk->queue),
1168+
* or NULL if diskless
1169+
*/
1170+
struct drbd_connection *connection = first_peer_device(device)->connection;
1171+
bool can_do = b ? blk_queue_discard(b) : true;
1172+
1173+
if (can_do && b && !b->limits.discard_zeroes_data && !discard_zeroes_if_aligned) {
1174+
can_do = false;
1175+
drbd_info(device, "discard_zeroes_data=0 and discard_zeroes_if_aligned=no: disabling discards\n");
1176+
}
1177+
if (can_do && connection->cstate >= C_CONNECTED && !(connection->agreed_features & FF_TRIM)) {
1178+
can_do = false;
1179+
drbd_info(connection, "peer DRBD too old, does not support TRIM: disabling discards\n");
1180+
}
1181+
if (can_do) {
1182+
/* We don't care for the granularity, really.
1183+
* Stacking limits below should fix it for the local
1184+
* device. Whether or not it is a suitable granularity
1185+
* on the remote device is not our problem, really. If
1186+
* you care, you need to use devices with similar
1187+
* topology on all peers. */
1188+
blk_queue_discard_granularity(q, 512);
1189+
q->limits.max_discard_sectors = DRBD_MAX_DISCARD_SECTORS;
1190+
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
1191+
} else {
1192+
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
1193+
blk_queue_discard_granularity(q, 0);
1194+
q->limits.max_discard_sectors = 0;
1195+
}
1196+
}
1197+
1198+
static void fixup_discard_if_not_supported(struct request_queue *q)
1199+
{
1200+
/* To avoid confusion, if this queue does not support discard, clear
1201+
* max_discard_sectors, which is what lsblk -D reports to the user.
1202+
* Older kernels got this wrong in "stack limits".
1203+
* */
1204+
if (!blk_queue_discard(q)) {
1205+
blk_queue_max_discard_sectors(q, 0);
1206+
blk_queue_discard_granularity(q, 0);
1207+
}
1208+
}
1209+
11571210
static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
11581211
unsigned int max_bio_size)
11591212
{
@@ -1183,26 +1236,8 @@ static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backi
11831236
/* This is the workaround for "bio would need to, but cannot, be split" */
11841237
blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
11851238
blk_queue_segment_boundary(q, PAGE_SIZE-1);
1186-
1239+
decide_on_discard_support(device, q, b, discard_zeroes_if_aligned);
11871240
if (b) {
1188-
struct drbd_connection *connection = first_peer_device(device)->connection;
1189-
1190-
blk_queue_max_discard_sectors(q, DRBD_MAX_DISCARD_SECTORS);
1191-
1192-
if (blk_queue_discard(b) && (b->limits.discard_zeroes_data || discard_zeroes_if_aligned) &&
1193-
(connection->cstate < C_CONNECTED || connection->agreed_features & FF_TRIM)) {
1194-
/* We don't care, stacking below should fix it for the local device.
1195-
* Whether or not it is a suitable granularity on the remote device
1196-
* is not our problem, really. If you care, you need to
1197-
* use devices with similar topology on all peers. */
1198-
q->limits.discard_granularity = 512;
1199-
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
1200-
} else {
1201-
blk_queue_max_discard_sectors(q, 0);
1202-
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
1203-
q->limits.discard_granularity = 0;
1204-
}
1205-
12061241
blk_queue_stack_limits(q, b);
12071242

12081243
if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
@@ -1212,12 +1247,7 @@ static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backi
12121247
q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
12131248
}
12141249
}
1215-
/* To avoid confusion, if this queue does not support discard, clear
1216-
* max_discard_sectors, which is what lsblk -D reports to the user. */
1217-
if (!blk_queue_discard(q)) {
1218-
blk_queue_max_discard_sectors(q, 0);
1219-
q->limits.discard_granularity = 0;
1220-
}
1250+
fixup_discard_if_not_supported(q);
12211251
}
12221252

12231253
void drbd_reconsider_queue_parameters(struct drbd_device *device, struct drbd_backing_dev *bdev)

0 commit comments

Comments
 (0)