diff options
Diffstat (limited to 'drivers/md/dm-table.c')
-rw-r--r-- | drivers/md/dm-table.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 100368eb7991..daf25d0890b3 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -967,13 +967,22 @@ bool dm_table_request_based(struct dm_table *t) | |||
967 | int dm_table_alloc_md_mempools(struct dm_table *t) | 967 | int dm_table_alloc_md_mempools(struct dm_table *t) |
968 | { | 968 | { |
969 | unsigned type = dm_table_get_type(t); | 969 | unsigned type = dm_table_get_type(t); |
970 | unsigned per_bio_data_size = 0; | ||
971 | struct dm_target *tgt; | ||
972 | unsigned i; | ||
970 | 973 | ||
971 | if (unlikely(type == DM_TYPE_NONE)) { | 974 | if (unlikely(type == DM_TYPE_NONE)) { |
972 | DMWARN("no table type is set, can't allocate mempools"); | 975 | DMWARN("no table type is set, can't allocate mempools"); |
973 | return -EINVAL; | 976 | return -EINVAL; |
974 | } | 977 | } |
975 | 978 | ||
976 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported); | 979 | if (type == DM_TYPE_BIO_BASED) |
980 | for (i = 0; i < t->num_targets; i++) { | ||
981 | tgt = t->targets + i; | ||
982 | per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size); | ||
983 | } | ||
984 | |||
985 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported, per_bio_data_size); | ||
977 | if (!t->mempools) | 986 | if (!t->mempools) |
978 | return -ENOMEM; | 987 | return -ENOMEM; |
979 | 988 | ||
@@ -1414,6 +1423,33 @@ static bool dm_table_all_devices_attribute(struct dm_table *t, | |||
1414 | return 1; | 1423 | return 1; |
1415 | } | 1424 | } |
1416 | 1425 | ||
1426 | static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev, | ||
1427 | sector_t start, sector_t len, void *data) | ||
1428 | { | ||
1429 | struct request_queue *q = bdev_get_queue(dev->bdev); | ||
1430 | |||
1431 | return q && !q->limits.max_write_same_sectors; | ||
1432 | } | ||
1433 | |||
1434 | static bool dm_table_supports_write_same(struct dm_table *t) | ||
1435 | { | ||
1436 | struct dm_target *ti; | ||
1437 | unsigned i = 0; | ||
1438 | |||
1439 | while (i < dm_table_get_num_targets(t)) { | ||
1440 | ti = dm_table_get_target(t, i++); | ||
1441 | |||
1442 | if (!ti->num_write_same_requests) | ||
1443 | return false; | ||
1444 | |||
1445 | if (!ti->type->iterate_devices || | ||
1446 | !ti->type->iterate_devices(ti, device_not_write_same_capable, NULL)) | ||
1447 | return false; | ||
1448 | } | ||
1449 | |||
1450 | return true; | ||
1451 | } | ||
1452 | |||
1417 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | 1453 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, |
1418 | struct queue_limits *limits) | 1454 | struct queue_limits *limits) |
1419 | { | 1455 | { |
@@ -1445,6 +1481,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | |||
1445 | else | 1481 | else |
1446 | queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); | 1482 | queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); |
1447 | 1483 | ||
1484 | if (!dm_table_supports_write_same(t)) | ||
1485 | q->limits.max_write_same_sectors = 0; | ||
1486 | |||
1448 | dm_table_set_integrity(t); | 1487 | dm_table_set_integrity(t); |
1449 | 1488 | ||
1450 | /* | 1489 | /* |