diff options
author | Kiyoshi Ueda <k-ueda@ct.jp.nec.com> | 2009-06-22 05:12:27 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-06-22 05:12:27 -0400 |
commit | 02ab823fd1a27d193bda06b74fdad685a20a3e5e (patch) | |
tree | 04b3db6e494f483fef34a55e487e88f6d7c585a5 | |
parent | 2bd023452592e5f5cf90dd426cc39b7632b15b76 (diff) |
dm mpath: add start_io and nr_bytes to path selectors
This patch makes two additions to the dm path selector interface for
dynamic load balancers:
o a new hook, start_io()
o a new parameter 'nr_bytes' to select_path()/start_io()/end_io()
to pass the size of the I/O
start_io() is called when a target driver actually submits I/O
to the selected path.
Path selectors can use it to start accounting of the I/O.
(e.g. counting the number of in-flight I/Os.)
The start_io hook is based on the patch posted by Stefan Bader:
https://www.redhat.com/archives/dm-devel/2005-October/msg00050.html
nr_bytes, the size of the I/O, is so path selectors can take the
size of the I/O into account when deciding which path to use.
dm-service-time uses it to estimate service time, for example.
(Added the nr_bytes member to dm_mpath_io instead of using existing
details.bi_size, since request-based dm patch deletes it.)
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-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; |