aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-table.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2010-08-11 23:14:08 -0400
committerAlasdair G Kergon <agk@redhat.com>2010-08-11 23:14:08 -0400
commit5ae89a8720c28caf35c4e53711d77df2856c404e (patch)
tree712ddc158309d7ad77e3c19e70f0ae9fafb94446 /drivers/md/dm-table.c
parent5ebaee6d290279d1df6ce45d6d54de8cfc473273 (diff)
dm: linear support discard
Allow discards to be passed through to linear mappings if at least one underlying device supports it. Discards will be forwarded only to devices that support them. A target that supports discards should set num_discard_requests to indicate how many times each discard request must be submitted to it. Verify table's underlying devices support discards prior to setting the associated DM device as capable of discards (via QUEUE_FLAG_DISCARD). Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Reviewed-by: Joe Thornber <thornber@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-table.c')
-rw-r--r--drivers/md/dm-table.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index bc60ef77a0d8..f9fc07d7a4b9 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -54,6 +54,8 @@ struct dm_table {
54 sector_t *highs; 54 sector_t *highs;
55 struct dm_target *targets; 55 struct dm_target *targets;
56 56
57 unsigned discards_supported:1;
58
57 /* 59 /*
58 * Indicates the rw permissions for the new logical 60 * Indicates the rw permissions for the new logical
59 * device. This should be a combination of FMODE_READ 61 * device. This should be a combination of FMODE_READ
@@ -203,6 +205,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
203 205
204 INIT_LIST_HEAD(&t->devices); 206 INIT_LIST_HEAD(&t->devices);
205 atomic_set(&t->holders, 0); 207 atomic_set(&t->holders, 0);
208 t->discards_supported = 1;
206 209
207 if (!num_targets) 210 if (!num_targets)
208 num_targets = KEYS_PER_NODE; 211 num_targets = KEYS_PER_NODE;
@@ -770,6 +773,9 @@ int dm_table_add_target(struct dm_table *t, const char *type,
770 773
771 t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; 774 t->highs[t->num_targets++] = tgt->begin + tgt->len - 1;
772 775
776 if (!tgt->num_discard_requests)
777 t->discards_supported = 0;
778
773 return 0; 779 return 0;
774 780
775 bad: 781 bad:
@@ -1135,6 +1141,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1135 else 1141 else
1136 queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); 1142 queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
1137 1143
1144 if (!dm_table_supports_discards(t))
1145 queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
1146 else
1147 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
1148
1138 dm_table_set_integrity(t); 1149 dm_table_set_integrity(t);
1139 1150
1140 /* 1151 /*
@@ -1281,6 +1292,39 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
1281 return t->md; 1292 return t->md;
1282} 1293}
1283 1294
1295static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev,
1296 sector_t start, sector_t len, void *data)
1297{
1298 struct request_queue *q = bdev_get_queue(dev->bdev);
1299
1300 return q && blk_queue_discard(q);
1301}
1302
1303bool dm_table_supports_discards(struct dm_table *t)
1304{
1305 struct dm_target *ti;
1306 unsigned i = 0;
1307
1308 if (!t->discards_supported)
1309 return 0;
1310
1311 /*
1312 * Ensure that at least one underlying device supports discards.
1313 * t->devices includes internal dm devices such as mirror logs
1314 * so we need to use iterate_devices here, which targets
1315 * supporting discard must provide.
1316 */
1317 while (i < dm_table_get_num_targets(t)) {
1318 ti = dm_table_get_target(t, i++);
1319
1320 if (ti->type->iterate_devices &&
1321 ti->type->iterate_devices(ti, device_discard_capable, NULL))
1322 return 1;
1323 }
1324
1325 return 0;
1326}
1327
1284EXPORT_SYMBOL(dm_vcalloc); 1328EXPORT_SYMBOL(dm_vcalloc);
1285EXPORT_SYMBOL(dm_get_device); 1329EXPORT_SYMBOL(dm_get_device);
1286EXPORT_SYMBOL(dm_put_device); 1330EXPORT_SYMBOL(dm_put_device);