Commit e4c938111f25dbbf2579e65ce4a7cb2d20a59308

Authored by Alasdair G Kergon
1 parent 14fe594d67

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

... ... @@ -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 /*