Commit e4c938111f25dbbf2579e65ce4a7cb2d20a59308
1 parent
14fe594d67
Exists in
master
and in
20 other branches
dm: refactor bio cloning
Refactor part of the bio splitting and cloning code to try to make it easier to understand. Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Showing 1 changed file with 96 additions and 68 deletions Side-by-side Diff
drivers/md/dm.c
... | ... | @@ -1087,7 +1087,7 @@ |
1087 | 1087 | */ |
1088 | 1088 | static void clone_bio(struct dm_target_io *tio, struct bio *bio, |
1089 | 1089 | sector_t sector, unsigned short idx, |
1090 | - unsigned short bv_count, unsigned int len) | |
1090 | + unsigned short bv_count, unsigned len) | |
1091 | 1091 | { |
1092 | 1092 | struct bio *clone = &tio->clone; |
1093 | 1093 | unsigned trim = 0; |
1094 | 1094 | |
1095 | 1095 | |
... | ... | @@ -1159,17 +1159,23 @@ |
1159 | 1159 | return 0; |
1160 | 1160 | } |
1161 | 1161 | |
1162 | -static void __clone_and_map_data_bio(struct clone_info *ci, | |
1163 | - struct dm_target *ti) | |
1162 | +static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti, | |
1163 | + sector_t sector, int nr_iovecs, | |
1164 | + unsigned short idx, unsigned short bv_count, | |
1165 | + unsigned offset, unsigned len, | |
1166 | + unsigned split_bvec) | |
1164 | 1167 | { |
1165 | 1168 | struct bio *bio = ci->bio; |
1166 | 1169 | struct dm_target_io *tio; |
1167 | 1170 | |
1168 | - tio = alloc_tio(ci, ti, bio->bi_max_vecs, 0); | |
1169 | - clone_bio(tio, bio, ci->sector, ci->idx, bio->bi_vcnt - ci->idx, | |
1170 | - ci->sector_count); | |
1171 | + tio = alloc_tio(ci, ti, nr_iovecs, 0); | |
1172 | + | |
1173 | + if (split_bvec) | |
1174 | + clone_split_bio(tio, bio, sector, idx, offset, len); | |
1175 | + else | |
1176 | + clone_bio(tio, bio, sector, idx, bv_count, len); | |
1177 | + | |
1171 | 1178 | __map_bio(tio); |
1172 | - ci->sector_count = 0; | |
1173 | 1179 | } |
1174 | 1180 | |
1175 | 1181 | typedef unsigned (*get_num_bios_fn)(struct dm_target *ti); |
1176 | 1182 | |
... | ... | @@ -1238,12 +1244,69 @@ |
1238 | 1244 | return __send_changing_extent_only(ci, get_num_write_same_bios, NULL); |
1239 | 1245 | } |
1240 | 1246 | |
1247 | +/* | |
1248 | + * Find maximum number of sectors / bvecs we can process with a single bio. | |
1249 | + */ | |
1250 | +static sector_t __len_within_target(struct clone_info *ci, sector_t max, int *idx) | |
1251 | +{ | |
1252 | + struct bio *bio = ci->bio; | |
1253 | + sector_t bv_len, total_len = 0; | |
1254 | + | |
1255 | + for (*idx = ci->idx; max && (*idx < bio->bi_vcnt); (*idx)++) { | |
1256 | + bv_len = to_sector(bio->bi_io_vec[*idx].bv_len); | |
1257 | + | |
1258 | + if (bv_len > max) | |
1259 | + break; | |
1260 | + | |
1261 | + max -= bv_len; | |
1262 | + total_len += bv_len; | |
1263 | + } | |
1264 | + | |
1265 | + return total_len; | |
1266 | +} | |
1267 | + | |
1268 | +static int __split_bvec_across_targets(struct clone_info *ci, | |
1269 | + struct dm_target *ti, sector_t max) | |
1270 | +{ | |
1271 | + struct bio *bio = ci->bio; | |
1272 | + struct bio_vec *bv = bio->bi_io_vec + ci->idx; | |
1273 | + sector_t remaining = to_sector(bv->bv_len); | |
1274 | + unsigned offset = 0; | |
1275 | + sector_t len; | |
1276 | + | |
1277 | + do { | |
1278 | + if (offset) { | |
1279 | + ti = dm_table_find_target(ci->map, ci->sector); | |
1280 | + if (!dm_target_is_valid(ti)) | |
1281 | + return -EIO; | |
1282 | + | |
1283 | + max = max_io_len(ci->sector, ti); | |
1284 | + } | |
1285 | + | |
1286 | + len = min(remaining, max); | |
1287 | + | |
1288 | + __clone_and_map_data_bio(ci, ti, ci->sector, 1, ci->idx, 0, | |
1289 | + bv->bv_offset + offset, len, 1); | |
1290 | + | |
1291 | + ci->sector += len; | |
1292 | + ci->sector_count -= len; | |
1293 | + offset += to_bytes(len); | |
1294 | + } while (remaining -= len); | |
1295 | + | |
1296 | + ci->idx++; | |
1297 | + | |
1298 | + return 0; | |
1299 | +} | |
1300 | + | |
1301 | +/* | |
1302 | + * Select the correct strategy for processing a non-flush bio. | |
1303 | + */ | |
1241 | 1304 | static int __split_and_process_non_flush(struct clone_info *ci) |
1242 | 1305 | { |
1243 | 1306 | struct bio *bio = ci->bio; |
1244 | 1307 | struct dm_target *ti; |
1245 | - sector_t len = 0, max; | |
1246 | - struct dm_target_io *tio; | |
1308 | + sector_t len, max; | |
1309 | + int idx; | |
1247 | 1310 | |
1248 | 1311 | if (unlikely(bio->bi_rw & REQ_DISCARD)) |
1249 | 1312 | return __send_discard(ci); |
1250 | 1313 | |
1251 | 1314 | |
1252 | 1315 | |
1253 | 1316 | |
1254 | 1317 | |
1255 | 1318 | |
1256 | 1319 | |
... | ... | @@ -1256,74 +1319,39 @@ |
1256 | 1319 | |
1257 | 1320 | max = max_io_len(ci->sector, ti); |
1258 | 1321 | |
1322 | + /* | |
1323 | + * Optimise for the simple case where we can do all of | |
1324 | + * the remaining io with a single clone. | |
1325 | + */ | |
1259 | 1326 | if (ci->sector_count <= max) { |
1260 | - /* | |
1261 | - * Optimise for the simple case where we can do all of | |
1262 | - * the remaining io with a single clone. | |
1263 | - */ | |
1264 | - __clone_and_map_data_bio(ci, ti); | |
1327 | + __clone_and_map_data_bio(ci, ti, ci->sector, bio->bi_max_vecs, | |
1328 | + ci->idx, bio->bi_vcnt - ci->idx, 0, | |
1329 | + ci->sector_count, 0); | |
1330 | + ci->sector_count = 0; | |
1331 | + return 0; | |
1332 | + } | |
1265 | 1333 | |
1266 | - } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { | |
1267 | - /* | |
1268 | - * There are some bvecs that don't span targets. | |
1269 | - * Do as many of these as possible. | |
1270 | - */ | |
1271 | - int i; | |
1272 | - sector_t remaining = max; | |
1273 | - sector_t bv_len; | |
1334 | + /* | |
1335 | + * There are some bvecs that don't span targets. | |
1336 | + * Do as many of these as possible. | |
1337 | + */ | |
1338 | + if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { | |
1339 | + len = __len_within_target(ci, max, &idx); | |
1274 | 1340 | |
1275 | - for (i = ci->idx; remaining && (i < bio->bi_vcnt); i++) { | |
1276 | - bv_len = to_sector(bio->bi_io_vec[i].bv_len); | |
1341 | + __clone_and_map_data_bio(ci, ti, ci->sector, bio->bi_max_vecs, | |
1342 | + ci->idx, idx - ci->idx, 0, len, 0); | |
1277 | 1343 | |
1278 | - if (bv_len > remaining) | |
1279 | - break; | |
1280 | - | |
1281 | - remaining -= bv_len; | |
1282 | - len += bv_len; | |
1283 | - } | |
1284 | - | |
1285 | - tio = alloc_tio(ci, ti, bio->bi_max_vecs, 0); | |
1286 | - clone_bio(tio, bio, ci->sector, ci->idx, i - ci->idx, len); | |
1287 | - __map_bio(tio); | |
1288 | - | |
1289 | 1344 | ci->sector += len; |
1290 | 1345 | ci->sector_count -= len; |
1291 | - ci->idx = i; | |
1346 | + ci->idx = idx; | |
1292 | 1347 | |
1293 | - } else { | |
1294 | - /* | |
1295 | - * Handle a bvec that must be split between two or more targets. | |
1296 | - */ | |
1297 | - struct bio_vec *bv = bio->bi_io_vec + ci->idx; | |
1298 | - sector_t remaining = to_sector(bv->bv_len); | |
1299 | - unsigned int offset = 0; | |
1300 | - | |
1301 | - do { | |
1302 | - if (offset) { | |
1303 | - ti = dm_table_find_target(ci->map, ci->sector); | |
1304 | - if (!dm_target_is_valid(ti)) | |
1305 | - return -EIO; | |
1306 | - | |
1307 | - max = max_io_len(ci->sector, ti); | |
1308 | - } | |
1309 | - | |
1310 | - len = min(remaining, max); | |
1311 | - | |
1312 | - tio = alloc_tio(ci, ti, 1, 0); | |
1313 | - clone_split_bio(tio, bio, ci->sector, ci->idx, | |
1314 | - bv->bv_offset + offset, len); | |
1315 | - | |
1316 | - __map_bio(tio); | |
1317 | - | |
1318 | - ci->sector += len; | |
1319 | - ci->sector_count -= len; | |
1320 | - offset += to_bytes(len); | |
1321 | - } while (remaining -= len); | |
1322 | - | |
1323 | - ci->idx++; | |
1348 | + return 0; | |
1324 | 1349 | } |
1325 | 1350 | |
1326 | - return 0; | |
1351 | + /* | |
1352 | + * Handle a bvec that must be split between two or more targets. | |
1353 | + */ | |
1354 | + return __split_bvec_across_targets(ci, ti, max); | |
1327 | 1355 | } |
1328 | 1356 | |
1329 | 1357 | /* |