diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0d4710175885..44aba29154fc 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1212,6 +1212,53 @@ static int __clone_and_map_empty_barrier(struct clone_info *ci) | |||
1212 | return 0; | 1212 | return 0; |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | /* | ||
1216 | * Perform all io with a single clone. | ||
1217 | */ | ||
1218 | static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti) | ||
1219 | { | ||
1220 | struct bio *clone, *bio = ci->bio; | ||
1221 | struct dm_target_io *tio; | ||
1222 | |||
1223 | tio = alloc_tio(ci, ti); | ||
1224 | clone = clone_bio(bio, ci->sector, ci->idx, | ||
1225 | bio->bi_vcnt - ci->idx, ci->sector_count, | ||
1226 | ci->md->bs); | ||
1227 | __map_bio(ti, clone, tio); | ||
1228 | ci->sector_count = 0; | ||
1229 | } | ||
1230 | |||
1231 | static int __clone_and_map_discard(struct clone_info *ci) | ||
1232 | { | ||
1233 | struct dm_target *ti; | ||
1234 | sector_t max; | ||
1235 | |||
1236 | ti = dm_table_find_target(ci->map, ci->sector); | ||
1237 | if (!dm_target_is_valid(ti)) | ||
1238 | return -EIO; | ||
1239 | |||
1240 | /* | ||
1241 | * Even though the device advertised discard support, | ||
1242 | * reconfiguration might have changed that since the | ||
1243 | * check was performed. | ||
1244 | */ | ||
1245 | |||
1246 | if (!ti->num_discard_requests) | ||
1247 | return -EOPNOTSUPP; | ||
1248 | |||
1249 | max = max_io_len(ci->md, ci->sector, ti); | ||
1250 | |||
1251 | if (ci->sector_count > max) | ||
1252 | /* | ||
1253 | * FIXME: Handle a discard that spans two or more targets. | ||
1254 | */ | ||
1255 | return -EOPNOTSUPP; | ||
1256 | |||
1257 | __clone_and_map_simple(ci, ti); | ||
1258 | |||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1215 | static int __clone_and_map(struct clone_info *ci) | 1262 | static int __clone_and_map(struct clone_info *ci) |
1216 | { | 1263 | { |
1217 | struct bio *clone, *bio = ci->bio; | 1264 | struct bio *clone, *bio = ci->bio; |
@@ -1222,27 +1269,21 @@ static int __clone_and_map(struct clone_info *ci) | |||
1222 | if (unlikely(bio_empty_barrier(bio))) | 1269 | if (unlikely(bio_empty_barrier(bio))) |
1223 | return __clone_and_map_empty_barrier(ci); | 1270 | return __clone_and_map_empty_barrier(ci); |
1224 | 1271 | ||
1272 | if (unlikely(bio->bi_rw & REQ_DISCARD)) | ||
1273 | return __clone_and_map_discard(ci); | ||
1274 | |||
1225 | ti = dm_table_find_target(ci->map, ci->sector); | 1275 | ti = dm_table_find_target(ci->map, ci->sector); |
1226 | if (!dm_target_is_valid(ti)) | 1276 | if (!dm_target_is_valid(ti)) |
1227 | return -EIO; | 1277 | return -EIO; |
1228 | 1278 | ||
1229 | max = max_io_len(ci->md, ci->sector, ti); | 1279 | max = max_io_len(ci->md, ci->sector, ti); |
1230 | 1280 | ||
1231 | /* | ||
1232 | * Allocate a target io object. | ||
1233 | */ | ||
1234 | tio = alloc_tio(ci, ti); | ||
1235 | |||
1236 | if (ci->sector_count <= max) { | 1281 | if (ci->sector_count <= max) { |
1237 | /* | 1282 | /* |
1238 | * Optimise for the simple case where we can do all of | 1283 | * Optimise for the simple case where we can do all of |
1239 | * the remaining io with a single clone. | 1284 | * the remaining io with a single clone. |
1240 | */ | 1285 | */ |
1241 | clone = clone_bio(bio, ci->sector, ci->idx, | 1286 | __clone_and_map_simple(ci, ti); |
1242 | bio->bi_vcnt - ci->idx, ci->sector_count, | ||
1243 | ci->md->bs); | ||
1244 | __map_bio(ti, clone, tio); | ||
1245 | ci->sector_count = 0; | ||
1246 | 1287 | ||
1247 | } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { | 1288 | } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { |
1248 | /* | 1289 | /* |
@@ -1263,6 +1304,7 @@ static int __clone_and_map(struct clone_info *ci) | |||
1263 | len += bv_len; | 1304 | len += bv_len; |
1264 | } | 1305 | } |
1265 | 1306 | ||
1307 | tio = alloc_tio(ci, ti); | ||
1266 | clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, | 1308 | clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, |
1267 | ci->md->bs); | 1309 | ci->md->bs); |
1268 | __map_bio(ti, clone, tio); | 1310 | __map_bio(ti, clone, tio); |
@@ -1286,12 +1328,11 @@ static int __clone_and_map(struct clone_info *ci) | |||
1286 | return -EIO; | 1328 | return -EIO; |
1287 | 1329 | ||
1288 | max = max_io_len(ci->md, ci->sector, ti); | 1330 | max = max_io_len(ci->md, ci->sector, ti); |
1289 | |||
1290 | tio = alloc_tio(ci, ti); | ||
1291 | } | 1331 | } |
1292 | 1332 | ||
1293 | len = min(remaining, max); | 1333 | len = min(remaining, max); |
1294 | 1334 | ||
1335 | tio = alloc_tio(ci, ti); | ||
1295 | clone = split_bvec(bio, ci->sector, ci->idx, | 1336 | clone = split_bvec(bio, ci->sector, ci->idx, |
1296 | bv->bv_offset + offset, len, | 1337 | bv->bv_offset + offset, len, |
1297 | ci->md->bs); | 1338 | ci->md->bs); |