diff options
| -rw-r--r-- | drivers/md/dm.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 561313a7dac2..ac384b2a6a33 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -1193,7 +1193,7 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci, | |||
| 1193 | } | 1193 | } |
| 1194 | 1194 | ||
| 1195 | static void __issue_target_request(struct clone_info *ci, struct dm_target *ti, | 1195 | static void __issue_target_request(struct clone_info *ci, struct dm_target *ti, |
| 1196 | unsigned request_nr) | 1196 | unsigned request_nr, sector_t len) |
| 1197 | { | 1197 | { |
| 1198 | struct dm_target_io *tio = alloc_tio(ci, ti); | 1198 | struct dm_target_io *tio = alloc_tio(ci, ti); |
| 1199 | struct bio *clone; | 1199 | struct bio *clone; |
| @@ -1208,17 +1208,21 @@ static void __issue_target_request(struct clone_info *ci, struct dm_target *ti, | |||
| 1208 | clone = bio_alloc_bioset(GFP_NOIO, ci->bio->bi_max_vecs, ci->md->bs); | 1208 | clone = bio_alloc_bioset(GFP_NOIO, ci->bio->bi_max_vecs, ci->md->bs); |
| 1209 | __bio_clone(clone, ci->bio); | 1209 | __bio_clone(clone, ci->bio); |
| 1210 | clone->bi_destructor = dm_bio_destructor; | 1210 | clone->bi_destructor = dm_bio_destructor; |
| 1211 | if (len) { | ||
| 1212 | clone->bi_sector = ci->sector; | ||
| 1213 | clone->bi_size = to_bytes(len); | ||
| 1214 | } | ||
| 1211 | 1215 | ||
| 1212 | __map_bio(ti, clone, tio); | 1216 | __map_bio(ti, clone, tio); |
| 1213 | } | 1217 | } |
| 1214 | 1218 | ||
| 1215 | static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti, | 1219 | static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti, |
| 1216 | unsigned num_requests) | 1220 | unsigned num_requests, sector_t len) |
| 1217 | { | 1221 | { |
| 1218 | unsigned request_nr; | 1222 | unsigned request_nr; |
| 1219 | 1223 | ||
| 1220 | for (request_nr = 0; request_nr < num_requests; request_nr++) | 1224 | for (request_nr = 0; request_nr < num_requests; request_nr++) |
| 1221 | __issue_target_request(ci, ti, request_nr); | 1225 | __issue_target_request(ci, ti, request_nr, len); |
| 1222 | } | 1226 | } |
| 1223 | 1227 | ||
| 1224 | static int __clone_and_map_empty_barrier(struct clone_info *ci) | 1228 | static int __clone_and_map_empty_barrier(struct clone_info *ci) |
| @@ -1227,7 +1231,7 @@ static int __clone_and_map_empty_barrier(struct clone_info *ci) | |||
| 1227 | struct dm_target *ti; | 1231 | struct dm_target *ti; |
| 1228 | 1232 | ||
| 1229 | while ((ti = dm_table_get_target(ci->map, target_nr++))) | 1233 | while ((ti = dm_table_get_target(ci->map, target_nr++))) |
| 1230 | __issue_target_requests(ci, ti, ti->num_flush_requests); | 1234 | __issue_target_requests(ci, ti, ti->num_flush_requests, 0); |
| 1231 | 1235 | ||
| 1232 | ci->sector_count = 0; | 1236 | ci->sector_count = 0; |
| 1233 | 1237 | ||
| @@ -1253,32 +1257,27 @@ static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti) | |||
| 1253 | static int __clone_and_map_discard(struct clone_info *ci) | 1257 | static int __clone_and_map_discard(struct clone_info *ci) |
| 1254 | { | 1258 | { |
| 1255 | struct dm_target *ti; | 1259 | struct dm_target *ti; |
| 1256 | sector_t max; | 1260 | sector_t len; |
| 1257 | 1261 | ||
| 1258 | ti = dm_table_find_target(ci->map, ci->sector); | 1262 | do { |
| 1259 | if (!dm_target_is_valid(ti)) | 1263 | ti = dm_table_find_target(ci->map, ci->sector); |
| 1260 | return -EIO; | 1264 | if (!dm_target_is_valid(ti)) |
| 1261 | 1265 | return -EIO; | |
| 1262 | /* | ||
| 1263 | * Even though the device advertised discard support, | ||
| 1264 | * reconfiguration might have changed that since the | ||
| 1265 | * check was performed. | ||
| 1266 | */ | ||
| 1267 | 1266 | ||
| 1268 | if (!ti->num_discard_requests) | ||
| 1269 | return -EOPNOTSUPP; | ||
| 1270 | |||
| 1271 | max = max_io_len(ci->sector, ti); | ||
| 1272 | |||
| 1273 | if (ci->sector_count > max) | ||
| 1274 | /* | 1267 | /* |
| 1275 | * FIXME: Handle a discard that spans two or more targets. | 1268 | * Even though the device advertised discard support, |
| 1269 | * reconfiguration might have changed that since the | ||
| 1270 | * check was performed. | ||
| 1276 | */ | 1271 | */ |
| 1277 | return -EOPNOTSUPP; | 1272 | if (!ti->num_discard_requests) |
| 1273 | return -EOPNOTSUPP; | ||
| 1278 | 1274 | ||
| 1279 | __issue_target_requests(ci, ti, ti->num_discard_requests); | 1275 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); |
| 1280 | 1276 | ||
| 1281 | ci->sector_count = 0; | 1277 | __issue_target_requests(ci, ti, ti->num_discard_requests, len); |
| 1278 | |||
| 1279 | ci->sector += len; | ||
| 1280 | } while (ci->sector_count -= len); | ||
| 1282 | 1281 | ||
| 1283 | return 0; | 1282 | return 0; |
| 1284 | } | 1283 | } |
