diff options
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 282 |
1 files changed, 219 insertions, 63 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 0bac9c8246bc..f35db29cac76 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -343,7 +343,7 @@ int drbd_khelper(struct drbd_device *device, char *cmd) | |||
343 | (char[20]) { }, /* address family */ | 343 | (char[20]) { }, /* address family */ |
344 | (char[60]) { }, /* address */ | 344 | (char[60]) { }, /* address */ |
345 | NULL }; | 345 | NULL }; |
346 | char mb[12]; | 346 | char mb[14]; |
347 | char *argv[] = {usermode_helper, cmd, mb, NULL }; | 347 | char *argv[] = {usermode_helper, cmd, mb, NULL }; |
348 | struct drbd_connection *connection = first_peer_device(device)->connection; | 348 | struct drbd_connection *connection = first_peer_device(device)->connection; |
349 | struct sib_info sib; | 349 | struct sib_info sib; |
@@ -352,7 +352,7 @@ int drbd_khelper(struct drbd_device *device, char *cmd) | |||
352 | if (current == connection->worker.task) | 352 | if (current == connection->worker.task) |
353 | set_bit(CALLBACK_PENDING, &connection->flags); | 353 | set_bit(CALLBACK_PENDING, &connection->flags); |
354 | 354 | ||
355 | snprintf(mb, 12, "minor-%d", device_to_minor(device)); | 355 | snprintf(mb, 14, "minor-%d", device_to_minor(device)); |
356 | setup_khelper_env(connection, envp); | 356 | setup_khelper_env(connection, envp); |
357 | 357 | ||
358 | /* The helper may take some time. | 358 | /* The helper may take some time. |
@@ -387,7 +387,7 @@ int drbd_khelper(struct drbd_device *device, char *cmd) | |||
387 | return ret; | 387 | return ret; |
388 | } | 388 | } |
389 | 389 | ||
390 | static int conn_khelper(struct drbd_connection *connection, char *cmd) | 390 | enum drbd_peer_state conn_khelper(struct drbd_connection *connection, char *cmd) |
391 | { | 391 | { |
392 | char *envp[] = { "HOME=/", | 392 | char *envp[] = { "HOME=/", |
393 | "TERM=linux", | 393 | "TERM=linux", |
@@ -442,19 +442,17 @@ static enum drbd_fencing_p highest_fencing_policy(struct drbd_connection *connec | |||
442 | } | 442 | } |
443 | rcu_read_unlock(); | 443 | rcu_read_unlock(); |
444 | 444 | ||
445 | if (fp == FP_NOT_AVAIL) { | ||
446 | /* IO Suspending works on the whole resource. | ||
447 | Do it only for one device. */ | ||
448 | vnr = 0; | ||
449 | peer_device = idr_get_next(&connection->peer_devices, &vnr); | ||
450 | drbd_change_state(peer_device->device, CS_VERBOSE | CS_HARD, NS(susp_fen, 0)); | ||
451 | } | ||
452 | |||
453 | return fp; | 445 | return fp; |
454 | } | 446 | } |
455 | 447 | ||
448 | static bool resource_is_supended(struct drbd_resource *resource) | ||
449 | { | ||
450 | return resource->susp || resource->susp_fen || resource->susp_nod; | ||
451 | } | ||
452 | |||
456 | bool conn_try_outdate_peer(struct drbd_connection *connection) | 453 | bool conn_try_outdate_peer(struct drbd_connection *connection) |
457 | { | 454 | { |
455 | struct drbd_resource * const resource = connection->resource; | ||
458 | unsigned int connect_cnt; | 456 | unsigned int connect_cnt; |
459 | union drbd_state mask = { }; | 457 | union drbd_state mask = { }; |
460 | union drbd_state val = { }; | 458 | union drbd_state val = { }; |
@@ -462,21 +460,41 @@ bool conn_try_outdate_peer(struct drbd_connection *connection) | |||
462 | char *ex_to_string; | 460 | char *ex_to_string; |
463 | int r; | 461 | int r; |
464 | 462 | ||
465 | spin_lock_irq(&connection->resource->req_lock); | 463 | spin_lock_irq(&resource->req_lock); |
466 | if (connection->cstate >= C_WF_REPORT_PARAMS) { | 464 | if (connection->cstate >= C_WF_REPORT_PARAMS) { |
467 | drbd_err(connection, "Expected cstate < C_WF_REPORT_PARAMS\n"); | 465 | drbd_err(connection, "Expected cstate < C_WF_REPORT_PARAMS\n"); |
468 | spin_unlock_irq(&connection->resource->req_lock); | 466 | spin_unlock_irq(&resource->req_lock); |
469 | return false; | 467 | return false; |
470 | } | 468 | } |
471 | 469 | ||
472 | connect_cnt = connection->connect_cnt; | 470 | connect_cnt = connection->connect_cnt; |
473 | spin_unlock_irq(&connection->resource->req_lock); | 471 | spin_unlock_irq(&resource->req_lock); |
474 | 472 | ||
475 | fp = highest_fencing_policy(connection); | 473 | fp = highest_fencing_policy(connection); |
476 | switch (fp) { | 474 | switch (fp) { |
477 | case FP_NOT_AVAIL: | 475 | case FP_NOT_AVAIL: |
478 | drbd_warn(connection, "Not fencing peer, I'm not even Consistent myself.\n"); | 476 | drbd_warn(connection, "Not fencing peer, I'm not even Consistent myself.\n"); |
479 | goto out; | 477 | spin_lock_irq(&resource->req_lock); |
478 | if (connection->cstate < C_WF_REPORT_PARAMS) { | ||
479 | _conn_request_state(connection, | ||
480 | (union drbd_state) { { .susp_fen = 1 } }, | ||
481 | (union drbd_state) { { .susp_fen = 0 } }, | ||
482 | CS_VERBOSE | CS_HARD | CS_DC_SUSP); | ||
483 | /* We are no longer suspended due to the fencing policy. | ||
484 | * We may still be suspended due to the on-no-data-accessible policy. | ||
485 | * If that was OND_IO_ERROR, fail pending requests. */ | ||
486 | if (!resource_is_supended(resource)) | ||
487 | _tl_restart(connection, CONNECTION_LOST_WHILE_PENDING); | ||
488 | } | ||
489 | /* Else: in case we raced with a connection handshake, | ||
490 | * let the handshake figure out if we maybe can RESEND, | ||
491 | * and do not resume/fail pending requests here. | ||
492 | * Worst case is we stay suspended for now, which may be | ||
493 | * resolved by either re-establishing the replication link, or | ||
494 | * the next link failure, or eventually the administrator. */ | ||
495 | spin_unlock_irq(&resource->req_lock); | ||
496 | return false; | ||
497 | |||
480 | case FP_DONT_CARE: | 498 | case FP_DONT_CARE: |
481 | return true; | 499 | return true; |
482 | default: ; | 500 | default: ; |
@@ -485,17 +503,17 @@ bool conn_try_outdate_peer(struct drbd_connection *connection) | |||
485 | r = conn_khelper(connection, "fence-peer"); | 503 | r = conn_khelper(connection, "fence-peer"); |
486 | 504 | ||
487 | switch ((r>>8) & 0xff) { | 505 | switch ((r>>8) & 0xff) { |
488 | case 3: /* peer is inconsistent */ | 506 | case P_INCONSISTENT: /* peer is inconsistent */ |
489 | ex_to_string = "peer is inconsistent or worse"; | 507 | ex_to_string = "peer is inconsistent or worse"; |
490 | mask.pdsk = D_MASK; | 508 | mask.pdsk = D_MASK; |
491 | val.pdsk = D_INCONSISTENT; | 509 | val.pdsk = D_INCONSISTENT; |
492 | break; | 510 | break; |
493 | case 4: /* peer got outdated, or was already outdated */ | 511 | case P_OUTDATED: /* peer got outdated, or was already outdated */ |
494 | ex_to_string = "peer was fenced"; | 512 | ex_to_string = "peer was fenced"; |
495 | mask.pdsk = D_MASK; | 513 | mask.pdsk = D_MASK; |
496 | val.pdsk = D_OUTDATED; | 514 | val.pdsk = D_OUTDATED; |
497 | break; | 515 | break; |
498 | case 5: /* peer was down */ | 516 | case P_DOWN: /* peer was down */ |
499 | if (conn_highest_disk(connection) == D_UP_TO_DATE) { | 517 | if (conn_highest_disk(connection) == D_UP_TO_DATE) { |
500 | /* we will(have) create(d) a new UUID anyways... */ | 518 | /* we will(have) create(d) a new UUID anyways... */ |
501 | ex_to_string = "peer is unreachable, assumed to be dead"; | 519 | ex_to_string = "peer is unreachable, assumed to be dead"; |
@@ -505,7 +523,7 @@ bool conn_try_outdate_peer(struct drbd_connection *connection) | |||
505 | ex_to_string = "peer unreachable, doing nothing since disk != UpToDate"; | 523 | ex_to_string = "peer unreachable, doing nothing since disk != UpToDate"; |
506 | } | 524 | } |
507 | break; | 525 | break; |
508 | case 6: /* Peer is primary, voluntarily outdate myself. | 526 | case P_PRIMARY: /* Peer is primary, voluntarily outdate myself. |
509 | * This is useful when an unconnected R_SECONDARY is asked to | 527 | * This is useful when an unconnected R_SECONDARY is asked to |
510 | * become R_PRIMARY, but finds the other peer being active. */ | 528 | * become R_PRIMARY, but finds the other peer being active. */ |
511 | ex_to_string = "peer is active"; | 529 | ex_to_string = "peer is active"; |
@@ -513,7 +531,9 @@ bool conn_try_outdate_peer(struct drbd_connection *connection) | |||
513 | mask.disk = D_MASK; | 531 | mask.disk = D_MASK; |
514 | val.disk = D_OUTDATED; | 532 | val.disk = D_OUTDATED; |
515 | break; | 533 | break; |
516 | case 7: | 534 | case P_FENCING: |
535 | /* THINK: do we need to handle this | ||
536 | * like case 4, or more like case 5? */ | ||
517 | if (fp != FP_STONITH) | 537 | if (fp != FP_STONITH) |
518 | drbd_err(connection, "fence-peer() = 7 && fencing != Stonith !!!\n"); | 538 | drbd_err(connection, "fence-peer() = 7 && fencing != Stonith !!!\n"); |
519 | ex_to_string = "peer was stonithed"; | 539 | ex_to_string = "peer was stonithed"; |
@@ -529,13 +549,11 @@ bool conn_try_outdate_peer(struct drbd_connection *connection) | |||
529 | drbd_info(connection, "fence-peer helper returned %d (%s)\n", | 549 | drbd_info(connection, "fence-peer helper returned %d (%s)\n", |
530 | (r>>8) & 0xff, ex_to_string); | 550 | (r>>8) & 0xff, ex_to_string); |
531 | 551 | ||
532 | out: | ||
533 | |||
534 | /* Not using | 552 | /* Not using |
535 | conn_request_state(connection, mask, val, CS_VERBOSE); | 553 | conn_request_state(connection, mask, val, CS_VERBOSE); |
536 | here, because we might were able to re-establish the connection in the | 554 | here, because we might were able to re-establish the connection in the |
537 | meantime. */ | 555 | meantime. */ |
538 | spin_lock_irq(&connection->resource->req_lock); | 556 | spin_lock_irq(&resource->req_lock); |
539 | if (connection->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &connection->flags)) { | 557 | if (connection->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &connection->flags)) { |
540 | if (connection->connect_cnt != connect_cnt) | 558 | if (connection->connect_cnt != connect_cnt) |
541 | /* In case the connection was established and droped | 559 | /* In case the connection was established and droped |
@@ -544,7 +562,7 @@ bool conn_try_outdate_peer(struct drbd_connection *connection) | |||
544 | else | 562 | else |
545 | _conn_request_state(connection, mask, val, CS_VERBOSE); | 563 | _conn_request_state(connection, mask, val, CS_VERBOSE); |
546 | } | 564 | } |
547 | spin_unlock_irq(&connection->resource->req_lock); | 565 | spin_unlock_irq(&resource->req_lock); |
548 | 566 | ||
549 | return conn_highest_pdsk(connection) <= D_OUTDATED; | 567 | return conn_highest_pdsk(connection) <= D_OUTDATED; |
550 | } | 568 | } |
@@ -1154,51 +1172,160 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc) | |||
1154 | return 0; | 1172 | return 0; |
1155 | } | 1173 | } |
1156 | 1174 | ||
1175 | static void blk_queue_discard_granularity(struct request_queue *q, unsigned int granularity) | ||
1176 | { | ||
1177 | q->limits.discard_granularity = granularity; | ||
1178 | } | ||
1179 | |||
1180 | static unsigned int drbd_max_discard_sectors(struct drbd_connection *connection) | ||
1181 | { | ||
1182 | /* when we introduced REQ_WRITE_SAME support, we also bumped | ||
1183 | * our maximum supported batch bio size used for discards. */ | ||
1184 | if (connection->agreed_features & DRBD_FF_WSAME) | ||
1185 | return DRBD_MAX_BBIO_SECTORS; | ||
1186 | /* before, with DRBD <= 8.4.6, we only allowed up to one AL_EXTENT_SIZE. */ | ||
1187 | return AL_EXTENT_SIZE >> 9; | ||
1188 | } | ||
1189 | |||
1190 | static void decide_on_discard_support(struct drbd_device *device, | ||
1191 | struct request_queue *q, | ||
1192 | struct request_queue *b, | ||
1193 | bool discard_zeroes_if_aligned) | ||
1194 | { | ||
1195 | /* q = drbd device queue (device->rq_queue) | ||
1196 | * b = backing device queue (device->ldev->backing_bdev->bd_disk->queue), | ||
1197 | * or NULL if diskless | ||
1198 | */ | ||
1199 | struct drbd_connection *connection = first_peer_device(device)->connection; | ||
1200 | bool can_do = b ? blk_queue_discard(b) : true; | ||
1201 | |||
1202 | if (can_do && b && !b->limits.discard_zeroes_data && !discard_zeroes_if_aligned) { | ||
1203 | can_do = false; | ||
1204 | drbd_info(device, "discard_zeroes_data=0 and discard_zeroes_if_aligned=no: disabling discards\n"); | ||
1205 | } | ||
1206 | if (can_do && connection->cstate >= C_CONNECTED && !(connection->agreed_features & DRBD_FF_TRIM)) { | ||
1207 | can_do = false; | ||
1208 | drbd_info(connection, "peer DRBD too old, does not support TRIM: disabling discards\n"); | ||
1209 | } | ||
1210 | if (can_do) { | ||
1211 | /* We don't care for the granularity, really. | ||
1212 | * Stacking limits below should fix it for the local | ||
1213 | * device. Whether or not it is a suitable granularity | ||
1214 | * on the remote device is not our problem, really. If | ||
1215 | * you care, you need to use devices with similar | ||
1216 | * topology on all peers. */ | ||
1217 | blk_queue_discard_granularity(q, 512); | ||
1218 | q->limits.max_discard_sectors = drbd_max_discard_sectors(connection); | ||
1219 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1220 | } else { | ||
1221 | queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1222 | blk_queue_discard_granularity(q, 0); | ||
1223 | q->limits.max_discard_sectors = 0; | ||
1224 | } | ||
1225 | } | ||
1226 | |||
1227 | static void fixup_discard_if_not_supported(struct request_queue *q) | ||
1228 | { | ||
1229 | /* To avoid confusion, if this queue does not support discard, clear | ||
1230 | * max_discard_sectors, which is what lsblk -D reports to the user. | ||
1231 | * Older kernels got this wrong in "stack limits". | ||
1232 | * */ | ||
1233 | if (!blk_queue_discard(q)) { | ||
1234 | blk_queue_max_discard_sectors(q, 0); | ||
1235 | blk_queue_discard_granularity(q, 0); | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | static void decide_on_write_same_support(struct drbd_device *device, | ||
1240 | struct request_queue *q, | ||
1241 | struct request_queue *b, struct o_qlim *o) | ||
1242 | { | ||
1243 | struct drbd_peer_device *peer_device = first_peer_device(device); | ||
1244 | struct drbd_connection *connection = peer_device->connection; | ||
1245 | bool can_do = b ? b->limits.max_write_same_sectors : true; | ||
1246 | |||
1247 | if (can_do && connection->cstate >= C_CONNECTED && !(connection->agreed_features & DRBD_FF_WSAME)) { | ||
1248 | can_do = false; | ||
1249 | drbd_info(peer_device, "peer does not support WRITE_SAME\n"); | ||
1250 | } | ||
1251 | |||
1252 | if (o) { | ||
1253 | /* logical block size; queue_logical_block_size(NULL) is 512 */ | ||
1254 | unsigned int peer_lbs = be32_to_cpu(o->logical_block_size); | ||
1255 | unsigned int me_lbs_b = queue_logical_block_size(b); | ||
1256 | unsigned int me_lbs = queue_logical_block_size(q); | ||
1257 | |||
1258 | if (me_lbs_b != me_lbs) { | ||
1259 | drbd_warn(device, | ||
1260 | "logical block size of local backend does not match (drbd:%u, backend:%u); was this a late attach?\n", | ||
1261 | me_lbs, me_lbs_b); | ||
1262 | /* rather disable write same than trigger some BUG_ON later in the scsi layer. */ | ||
1263 | can_do = false; | ||
1264 | } | ||
1265 | if (me_lbs_b != peer_lbs) { | ||
1266 | drbd_warn(peer_device, "logical block sizes do not match (me:%u, peer:%u); this may cause problems.\n", | ||
1267 | me_lbs, peer_lbs); | ||
1268 | if (can_do) { | ||
1269 | drbd_dbg(peer_device, "logical block size mismatch: WRITE_SAME disabled.\n"); | ||
1270 | can_do = false; | ||
1271 | } | ||
1272 | me_lbs = max(me_lbs, me_lbs_b); | ||
1273 | /* We cannot change the logical block size of an in-use queue. | ||
1274 | * We can only hope that access happens to be properly aligned. | ||
1275 | * If not, the peer will likely produce an IO error, and detach. */ | ||
1276 | if (peer_lbs > me_lbs) { | ||
1277 | if (device->state.role != R_PRIMARY) { | ||
1278 | blk_queue_logical_block_size(q, peer_lbs); | ||
1279 | drbd_warn(peer_device, "logical block size set to %u\n", peer_lbs); | ||
1280 | } else { | ||
1281 | drbd_warn(peer_device, | ||
1282 | "current Primary must NOT adjust logical block size (%u -> %u); hope for the best.\n", | ||
1283 | me_lbs, peer_lbs); | ||
1284 | } | ||
1285 | } | ||
1286 | } | ||
1287 | if (can_do && !o->write_same_capable) { | ||
1288 | /* If we introduce an open-coded write-same loop on the receiving side, | ||
1289 | * the peer would present itself as "capable". */ | ||
1290 | drbd_dbg(peer_device, "WRITE_SAME disabled (peer device not capable)\n"); | ||
1291 | can_do = false; | ||
1292 | } | ||
1293 | } | ||
1294 | |||
1295 | blk_queue_max_write_same_sectors(q, can_do ? DRBD_MAX_BBIO_SECTORS : 0); | ||
1296 | } | ||
1297 | |||
1157 | static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev, | 1298 | static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev, |
1158 | unsigned int max_bio_size) | 1299 | unsigned int max_bio_size, struct o_qlim *o) |
1159 | { | 1300 | { |
1160 | struct request_queue * const q = device->rq_queue; | 1301 | struct request_queue * const q = device->rq_queue; |
1161 | unsigned int max_hw_sectors = max_bio_size >> 9; | 1302 | unsigned int max_hw_sectors = max_bio_size >> 9; |
1162 | unsigned int max_segments = 0; | 1303 | unsigned int max_segments = 0; |
1163 | struct request_queue *b = NULL; | 1304 | struct request_queue *b = NULL; |
1305 | struct disk_conf *dc; | ||
1306 | bool discard_zeroes_if_aligned = true; | ||
1164 | 1307 | ||
1165 | if (bdev) { | 1308 | if (bdev) { |
1166 | b = bdev->backing_bdev->bd_disk->queue; | 1309 | b = bdev->backing_bdev->bd_disk->queue; |
1167 | 1310 | ||
1168 | max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); | 1311 | max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9); |
1169 | rcu_read_lock(); | 1312 | rcu_read_lock(); |
1170 | max_segments = rcu_dereference(device->ldev->disk_conf)->max_bio_bvecs; | 1313 | dc = rcu_dereference(device->ldev->disk_conf); |
1314 | max_segments = dc->max_bio_bvecs; | ||
1315 | discard_zeroes_if_aligned = dc->discard_zeroes_if_aligned; | ||
1171 | rcu_read_unlock(); | 1316 | rcu_read_unlock(); |
1172 | 1317 | ||
1173 | blk_set_stacking_limits(&q->limits); | 1318 | blk_set_stacking_limits(&q->limits); |
1174 | blk_queue_max_write_same_sectors(q, 0); | ||
1175 | } | 1319 | } |
1176 | 1320 | ||
1177 | blk_queue_logical_block_size(q, 512); | ||
1178 | blk_queue_max_hw_sectors(q, max_hw_sectors); | 1321 | blk_queue_max_hw_sectors(q, max_hw_sectors); |
1179 | /* This is the workaround for "bio would need to, but cannot, be split" */ | 1322 | /* This is the workaround for "bio would need to, but cannot, be split" */ |
1180 | blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS); | 1323 | blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS); |
1181 | blk_queue_segment_boundary(q, PAGE_SIZE-1); | 1324 | blk_queue_segment_boundary(q, PAGE_SIZE-1); |
1325 | decide_on_discard_support(device, q, b, discard_zeroes_if_aligned); | ||
1326 | decide_on_write_same_support(device, q, b, o); | ||
1182 | 1327 | ||
1183 | if (b) { | 1328 | if (b) { |
1184 | struct drbd_connection *connection = first_peer_device(device)->connection; | ||
1185 | |||
1186 | blk_queue_max_discard_sectors(q, DRBD_MAX_DISCARD_SECTORS); | ||
1187 | |||
1188 | if (blk_queue_discard(b) && | ||
1189 | (connection->cstate < C_CONNECTED || connection->agreed_features & FF_TRIM)) { | ||
1190 | /* We don't care, stacking below should fix it for the local device. | ||
1191 | * Whether or not it is a suitable granularity on the remote device | ||
1192 | * is not our problem, really. If you care, you need to | ||
1193 | * use devices with similar topology on all peers. */ | ||
1194 | q->limits.discard_granularity = 512; | ||
1195 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1196 | } else { | ||
1197 | blk_queue_max_discard_sectors(q, 0); | ||
1198 | queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1199 | q->limits.discard_granularity = 0; | ||
1200 | } | ||
1201 | |||
1202 | blk_queue_stack_limits(q, b); | 1329 | blk_queue_stack_limits(q, b); |
1203 | 1330 | ||
1204 | if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { | 1331 | if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { |
@@ -1208,15 +1335,10 @@ static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backi | |||
1208 | q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages; | 1335 | q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages; |
1209 | } | 1336 | } |
1210 | } | 1337 | } |
1211 | /* To avoid confusion, if this queue does not support discard, clear | 1338 | fixup_discard_if_not_supported(q); |
1212 | * max_discard_sectors, which is what lsblk -D reports to the user. */ | ||
1213 | if (!blk_queue_discard(q)) { | ||
1214 | blk_queue_max_discard_sectors(q, 0); | ||
1215 | q->limits.discard_granularity = 0; | ||
1216 | } | ||
1217 | } | 1339 | } |
1218 | 1340 | ||
1219 | void drbd_reconsider_max_bio_size(struct drbd_device *device, struct drbd_backing_dev *bdev) | 1341 | void drbd_reconsider_queue_parameters(struct drbd_device *device, struct drbd_backing_dev *bdev, struct o_qlim *o) |
1220 | { | 1342 | { |
1221 | unsigned int now, new, local, peer; | 1343 | unsigned int now, new, local, peer; |
1222 | 1344 | ||
@@ -1259,7 +1381,7 @@ void drbd_reconsider_max_bio_size(struct drbd_device *device, struct drbd_backin | |||
1259 | if (new != now) | 1381 | if (new != now) |
1260 | drbd_info(device, "max BIO size = %u\n", new); | 1382 | drbd_info(device, "max BIO size = %u\n", new); |
1261 | 1383 | ||
1262 | drbd_setup_queue_param(device, bdev, new); | 1384 | drbd_setup_queue_param(device, bdev, new, o); |
1263 | } | 1385 | } |
1264 | 1386 | ||
1265 | /* Starts the worker thread */ | 1387 | /* Starts the worker thread */ |
@@ -1348,6 +1470,43 @@ static bool write_ordering_changed(struct disk_conf *a, struct disk_conf *b) | |||
1348 | a->disk_drain != b->disk_drain; | 1470 | a->disk_drain != b->disk_drain; |
1349 | } | 1471 | } |
1350 | 1472 | ||
1473 | static void sanitize_disk_conf(struct drbd_device *device, struct disk_conf *disk_conf, | ||
1474 | struct drbd_backing_dev *nbc) | ||
1475 | { | ||
1476 | struct request_queue * const q = nbc->backing_bdev->bd_disk->queue; | ||
1477 | |||
1478 | if (disk_conf->al_extents < DRBD_AL_EXTENTS_MIN) | ||
1479 | disk_conf->al_extents = DRBD_AL_EXTENTS_MIN; | ||
1480 | if (disk_conf->al_extents > drbd_al_extents_max(nbc)) | ||
1481 | disk_conf->al_extents = drbd_al_extents_max(nbc); | ||
1482 | |||
1483 | if (!blk_queue_discard(q) | ||
1484 | || (!q->limits.discard_zeroes_data && !disk_conf->discard_zeroes_if_aligned)) { | ||
1485 | if (disk_conf->rs_discard_granularity) { | ||
1486 | disk_conf->rs_discard_granularity = 0; /* disable feature */ | ||
1487 | drbd_info(device, "rs_discard_granularity feature disabled\n"); | ||
1488 | } | ||
1489 | } | ||
1490 | |||
1491 | if (disk_conf->rs_discard_granularity) { | ||
1492 | int orig_value = disk_conf->rs_discard_granularity; | ||
1493 | int remainder; | ||
1494 | |||
1495 | if (q->limits.discard_granularity > disk_conf->rs_discard_granularity) | ||
1496 | disk_conf->rs_discard_granularity = q->limits.discard_granularity; | ||
1497 | |||
1498 | remainder = disk_conf->rs_discard_granularity % q->limits.discard_granularity; | ||
1499 | disk_conf->rs_discard_granularity += remainder; | ||
1500 | |||
1501 | if (disk_conf->rs_discard_granularity > q->limits.max_discard_sectors << 9) | ||
1502 | disk_conf->rs_discard_granularity = q->limits.max_discard_sectors << 9; | ||
1503 | |||
1504 | if (disk_conf->rs_discard_granularity != orig_value) | ||
1505 | drbd_info(device, "rs_discard_granularity changed to %d\n", | ||
1506 | disk_conf->rs_discard_granularity); | ||
1507 | } | ||
1508 | } | ||
1509 | |||
1351 | int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | 1510 | int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) |
1352 | { | 1511 | { |
1353 | struct drbd_config_context adm_ctx; | 1512 | struct drbd_config_context adm_ctx; |
@@ -1395,10 +1554,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | |||
1395 | if (!expect(new_disk_conf->resync_rate >= 1)) | 1554 | if (!expect(new_disk_conf->resync_rate >= 1)) |
1396 | new_disk_conf->resync_rate = 1; | 1555 | new_disk_conf->resync_rate = 1; |
1397 | 1556 | ||
1398 | if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN) | 1557 | sanitize_disk_conf(device, new_disk_conf, device->ldev); |
1399 | new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN; | ||
1400 | if (new_disk_conf->al_extents > drbd_al_extents_max(device->ldev)) | ||
1401 | new_disk_conf->al_extents = drbd_al_extents_max(device->ldev); | ||
1402 | 1558 | ||
1403 | if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX) | 1559 | if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX) |
1404 | new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX; | 1560 | new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX; |
@@ -1457,6 +1613,9 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) | |||
1457 | if (write_ordering_changed(old_disk_conf, new_disk_conf)) | 1613 | if (write_ordering_changed(old_disk_conf, new_disk_conf)) |
1458 | drbd_bump_write_ordering(device->resource, NULL, WO_BDEV_FLUSH); | 1614 | drbd_bump_write_ordering(device->resource, NULL, WO_BDEV_FLUSH); |
1459 | 1615 | ||
1616 | if (old_disk_conf->discard_zeroes_if_aligned != new_disk_conf->discard_zeroes_if_aligned) | ||
1617 | drbd_reconsider_queue_parameters(device, device->ldev, NULL); | ||
1618 | |||
1460 | drbd_md_sync(device); | 1619 | drbd_md_sync(device); |
1461 | 1620 | ||
1462 | if (device->state.conn >= C_CONNECTED) { | 1621 | if (device->state.conn >= C_CONNECTED) { |
@@ -1693,10 +1852,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1693 | if (retcode != NO_ERROR) | 1852 | if (retcode != NO_ERROR) |
1694 | goto fail; | 1853 | goto fail; |
1695 | 1854 | ||
1696 | if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN) | 1855 | sanitize_disk_conf(device, new_disk_conf, nbc); |
1697 | new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN; | ||
1698 | if (new_disk_conf->al_extents > drbd_al_extents_max(nbc)) | ||
1699 | new_disk_conf->al_extents = drbd_al_extents_max(nbc); | ||
1700 | 1856 | ||
1701 | if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) { | 1857 | if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) { |
1702 | drbd_err(device, "max capacity %llu smaller than disk size %llu\n", | 1858 | drbd_err(device, "max capacity %llu smaller than disk size %llu\n", |
@@ -1838,7 +1994,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1838 | device->read_cnt = 0; | 1994 | device->read_cnt = 0; |
1839 | device->writ_cnt = 0; | 1995 | device->writ_cnt = 0; |
1840 | 1996 | ||
1841 | drbd_reconsider_max_bio_size(device, device->ldev); | 1997 | drbd_reconsider_queue_parameters(device, device->ldev, NULL); |
1842 | 1998 | ||
1843 | /* If I am currently not R_PRIMARY, | 1999 | /* If I am currently not R_PRIMARY, |
1844 | * but meta data primary indicator is set, | 2000 | * but meta data primary indicator is set, |