aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-mpath.c28
-rw-r--r--drivers/md/dm-path-selector.h8
-rw-r--r--drivers/md/dm-round-robin.c2
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 {
101struct dm_mpath_io { 101struct 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
106typedef int (*action_fn) (struct pgpath *pgpath); 107typedef 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
247static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) 248static 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
263static void __choose_pgpath(struct multipath *m) 265static 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
163static struct dm_path *rr_select_path(struct path_selector *ps, 163static 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;