diff options
| -rw-r--r-- | drivers/md/dm-mpath.c | 28 | ||||
| -rw-r--r-- | drivers/md/dm-path-selector.h | 8 | ||||
| -rw-r--r-- | drivers/md/dm-round-robin.c | 2 |
3 files changed, 25 insertions, 13 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; |
diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h index 27357b85d73d..e7d1fa8b0459 100644 --- a/drivers/md/dm-path-selector.h +++ b/drivers/md/dm-path-selector.h | |||
| @@ -56,7 +56,8 @@ struct path_selector_type { | |||
| 56 | * the path fails. | 56 | * the path fails. |
| 57 | */ | 57 | */ |
| 58 | struct dm_path *(*select_path) (struct path_selector *ps, | 58 | struct dm_path *(*select_path) (struct path_selector *ps, |
| 59 | unsigned *repeat_count); | 59 | unsigned *repeat_count, |
| 60 | size_t nr_bytes); | ||
| 60 | 61 | ||
| 61 | /* | 62 | /* |
| 62 | * Notify the selector that a path has failed. | 63 | * Notify the selector that a path has failed. |
| @@ -75,7 +76,10 @@ struct path_selector_type { | |||
| 75 | int (*status) (struct path_selector *ps, struct dm_path *path, | 76 | int (*status) (struct path_selector *ps, struct dm_path *path, |
| 76 | status_type_t type, char *result, unsigned int maxlen); | 77 | status_type_t type, char *result, unsigned int maxlen); |
| 77 | 78 | ||
| 78 | int (*end_io) (struct path_selector *ps, struct dm_path *path); | 79 | int (*start_io) (struct path_selector *ps, struct dm_path *path, |
| 80 | size_t nr_bytes); | ||
| 81 | int (*end_io) (struct path_selector *ps, struct dm_path *path, | ||
| 82 | size_t nr_bytes); | ||
| 79 | }; | 83 | }; |
| 80 | 84 | ||
| 81 | /* Register a path selector */ | 85 | /* Register a path selector */ |
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index cdfbf65b28cb..24752f449bef 100644 --- a/drivers/md/dm-round-robin.c +++ b/drivers/md/dm-round-robin.c | |||
| @@ -161,7 +161,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p) | |||
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static struct dm_path *rr_select_path(struct path_selector *ps, | 163 | static struct dm_path *rr_select_path(struct path_selector *ps, |
| 164 | unsigned *repeat_count) | 164 | unsigned *repeat_count, size_t nr_bytes) |
| 165 | { | 165 | { |
| 166 | struct selector *s = (struct selector *) ps->context; | 166 | struct selector *s = (struct selector *) ps->context; |
| 167 | struct path_info *pi = NULL; | 167 | struct path_info *pi = NULL; |
