diff options
Diffstat (limited to 'drivers/md/dm-mpath.c')
| -rw-r--r-- | drivers/md/dm-mpath.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index f1cf8f7449d6..890c0e8ed13e 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
| @@ -101,6 +101,7 @@ struct multipath { | |||
| 101 | struct dm_mpath_io { | 101 | struct dm_mpath_io { |
| 102 | struct pgpath *pgpath; | 102 | struct pgpath *pgpath; |
| 103 | struct dm_bio_details details; | 103 | struct dm_bio_details details; |
| 104 | size_t nr_bytes; | ||
| 104 | }; | 105 | }; |
| 105 | 106 | ||
| 106 | typedef int (*action_fn) (struct pgpath *pgpath); | 107 | typedef int (*action_fn) (struct pgpath *pgpath); |
| @@ -244,11 +245,12 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath) | |||
| 244 | m->pg_init_count = 0; | 245 | m->pg_init_count = 0; |
| 245 | } | 246 | } |
| 246 | 247 | ||
| 247 | static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) | 248 | static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg, |
| 249 | size_t nr_bytes) | ||
| 248 | { | 250 | { |
| 249 | struct dm_path *path; | 251 | struct dm_path *path; |
| 250 | 252 | ||
| 251 | path = pg->ps.type->select_path(&pg->ps, &m->repeat_count); | 253 | path = pg->ps.type->select_path(&pg->ps, &m->repeat_count, nr_bytes); |
| 252 | if (!path) | 254 | if (!path) |
| 253 | return -ENXIO; | 255 | return -ENXIO; |
| 254 | 256 | ||
| @@ -260,7 +262,7 @@ static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) | |||
| 260 | return 0; | 262 | return 0; |
| 261 | } | 263 | } |
| 262 | 264 | ||
| 263 | static void __choose_pgpath(struct multipath *m) | 265 | static void __choose_pgpath(struct multipath *m, size_t nr_bytes) |
| 264 | { | 266 | { |
| 265 | struct priority_group *pg; | 267 | struct priority_group *pg; |
| 266 | unsigned bypassed = 1; | 268 | unsigned bypassed = 1; |
| @@ -272,12 +274,12 @@ static void __choose_pgpath(struct multipath *m) | |||
| 272 | if (m->next_pg) { | 274 | if (m->next_pg) { |
| 273 | pg = m->next_pg; | 275 | pg = m->next_pg; |
| 274 | m->next_pg = NULL; | 276 | m->next_pg = NULL; |
| 275 | if (!__choose_path_in_pg(m, pg)) | 277 | if (!__choose_path_in_pg(m, pg, nr_bytes)) |
| 276 | return; | 278 | return; |
| 277 | } | 279 | } |
| 278 | 280 | ||
| 279 | /* Don't change PG until it has no remaining paths */ | 281 | /* Don't change PG until it has no remaining paths */ |
| 280 | if (m->current_pg && !__choose_path_in_pg(m, m->current_pg)) | 282 | if (m->current_pg && !__choose_path_in_pg(m, m->current_pg, nr_bytes)) |
| 281 | return; | 283 | return; |
| 282 | 284 | ||
| 283 | /* | 285 | /* |
| @@ -289,7 +291,7 @@ static void __choose_pgpath(struct multipath *m) | |||
| 289 | list_for_each_entry(pg, &m->priority_groups, list) { | 291 | list_for_each_entry(pg, &m->priority_groups, list) { |
| 290 | if (pg->bypassed == bypassed) | 292 | if (pg->bypassed == bypassed) |
| 291 | continue; | 293 | continue; |
| 292 | if (!__choose_path_in_pg(m, pg)) | 294 | if (!__choose_path_in_pg(m, pg, nr_bytes)) |
| 293 | return; | 295 | return; |
| 294 | } | 296 | } |
| 295 | } while (bypassed--); | 297 | } while (bypassed--); |
| @@ -320,6 +322,7 @@ static int map_io(struct multipath *m, struct bio *bio, | |||
| 320 | struct dm_mpath_io *mpio, unsigned was_queued) | 322 | struct dm_mpath_io *mpio, unsigned was_queued) |
| 321 | { | 323 | { |
| 322 | int r = DM_MAPIO_REMAPPED; | 324 | int r = DM_MAPIO_REMAPPED; |
| 325 | size_t nr_bytes = bio->bi_size; | ||
| 323 | unsigned long flags; | 326 | unsigned long flags; |
| 324 | struct pgpath *pgpath; | 327 | struct pgpath *pgpath; |
| 325 | 328 | ||
| @@ -328,7 +331,7 @@ static int map_io(struct multipath *m, struct bio *bio, | |||
| 328 | /* Do we need to select a new pgpath? */ | 331 | /* Do we need to select a new pgpath? */ |
| 329 | if (!m->current_pgpath || | 332 | if (!m->current_pgpath || |
| 330 | (!m->queue_io && (m->repeat_count && --m->repeat_count == 0))) | 333 | (!m->queue_io && (m->repeat_count && --m->repeat_count == 0))) |
| 331 | __choose_pgpath(m); | 334 | __choose_pgpath(m, nr_bytes); |
| 332 | 335 | ||
| 333 | pgpath = m->current_pgpath; | 336 | pgpath = m->current_pgpath; |
| 334 | 337 | ||
| @@ -353,6 +356,11 @@ static int map_io(struct multipath *m, struct bio *bio, | |||
| 353 | r = -EIO; /* Failed */ | 356 | r = -EIO; /* Failed */ |
| 354 | 357 | ||
| 355 | mpio->pgpath = pgpath; | 358 | mpio->pgpath = pgpath; |
| 359 | mpio->nr_bytes = nr_bytes; | ||
| 360 | |||
| 361 | if (r == DM_MAPIO_REMAPPED && pgpath->pg->ps.type->start_io) | ||
| 362 | pgpath->pg->ps.type->start_io(&pgpath->pg->ps, &pgpath->path, | ||
| 363 | nr_bytes); | ||
| 356 | 364 | ||
| 357 | spin_unlock_irqrestore(&m->lock, flags); | 365 | spin_unlock_irqrestore(&m->lock, flags); |
| 358 | 366 | ||
| @@ -431,7 +439,7 @@ static void process_queued_ios(struct work_struct *work) | |||
| 431 | goto out; | 439 | goto out; |
| 432 | 440 | ||
| 433 | if (!m->current_pgpath) | 441 | if (!m->current_pgpath) |
| 434 | __choose_pgpath(m); | 442 | __choose_pgpath(m, 0); |
| 435 | 443 | ||
| 436 | pgpath = m->current_pgpath; | 444 | pgpath = m->current_pgpath; |
| 437 | 445 | ||
| @@ -1209,7 +1217,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio, | |||
| 1209 | if (pgpath) { | 1217 | if (pgpath) { |
| 1210 | ps = &pgpath->pg->ps; | 1218 | ps = &pgpath->pg->ps; |
| 1211 | if (ps->type->end_io) | 1219 | if (ps->type->end_io) |
| 1212 | ps->type->end_io(ps, &pgpath->path); | 1220 | ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes); |
| 1213 | } | 1221 | } |
| 1214 | if (r != DM_ENDIO_INCOMPLETE) | 1222 | if (r != DM_ENDIO_INCOMPLETE) |
| 1215 | mempool_free(mpio, m->mpio_pool); | 1223 | mempool_free(mpio, m->mpio_pool); |
| @@ -1425,7 +1433,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, | |||
| 1425 | spin_lock_irqsave(&m->lock, flags); | 1433 | spin_lock_irqsave(&m->lock, flags); |
| 1426 | 1434 | ||
| 1427 | if (!m->current_pgpath) | 1435 | if (!m->current_pgpath) |
| 1428 | __choose_pgpath(m); | 1436 | __choose_pgpath(m, 0); |
| 1429 | 1437 | ||
| 1430 | if (m->current_pgpath) { | 1438 | if (m->current_pgpath) { |
| 1431 | bdev = m->current_pgpath->path.dev->bdev; | 1439 | bdev = m->current_pgpath->path.dev->bdev; |
