aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c65
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 */
1218static 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
1231static 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
1215static int __clone_and_map(struct clone_info *ci) 1262static 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);