mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
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>
This commit is contained in:
parent
2bd0234525
commit
02ab823fd1
3 changed files with 25 additions and 13 deletions
|
@ -101,6 +101,7 @@ struct multipath {
|
||||||
struct dm_mpath_io {
|
struct dm_mpath_io {
|
||||||
struct pgpath *pgpath;
|
struct pgpath *pgpath;
|
||||||
struct dm_bio_details details;
|
struct dm_bio_details details;
|
||||||
|
size_t nr_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*action_fn) (struct pgpath *pgpath);
|
typedef int (*action_fn) (struct pgpath *pgpath);
|
||||||
|
@ -244,11 +245,12 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
|
||||||
m->pg_init_count = 0;
|
m->pg_init_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
|
static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg,
|
||||||
|
size_t nr_bytes)
|
||||||
{
|
{
|
||||||
struct dm_path *path;
|
struct dm_path *path;
|
||||||
|
|
||||||
path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
|
path = pg->ps.type->select_path(&pg->ps, &m->repeat_count, nr_bytes);
|
||||||
if (!path)
|
if (!path)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
@ -260,7 +262,7 @@ static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __choose_pgpath(struct multipath *m)
|
static void __choose_pgpath(struct multipath *m, size_t nr_bytes)
|
||||||
{
|
{
|
||||||
struct priority_group *pg;
|
struct priority_group *pg;
|
||||||
unsigned bypassed = 1;
|
unsigned bypassed = 1;
|
||||||
|
@ -272,12 +274,12 @@ static void __choose_pgpath(struct multipath *m)
|
||||||
if (m->next_pg) {
|
if (m->next_pg) {
|
||||||
pg = m->next_pg;
|
pg = m->next_pg;
|
||||||
m->next_pg = NULL;
|
m->next_pg = NULL;
|
||||||
if (!__choose_path_in_pg(m, pg))
|
if (!__choose_path_in_pg(m, pg, nr_bytes))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't change PG until it has no remaining paths */
|
/* Don't change PG until it has no remaining paths */
|
||||||
if (m->current_pg && !__choose_path_in_pg(m, m->current_pg))
|
if (m->current_pg && !__choose_path_in_pg(m, m->current_pg, nr_bytes))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -289,7 +291,7 @@ static void __choose_pgpath(struct multipath *m)
|
||||||
list_for_each_entry(pg, &m->priority_groups, list) {
|
list_for_each_entry(pg, &m->priority_groups, list) {
|
||||||
if (pg->bypassed == bypassed)
|
if (pg->bypassed == bypassed)
|
||||||
continue;
|
continue;
|
||||||
if (!__choose_path_in_pg(m, pg))
|
if (!__choose_path_in_pg(m, pg, nr_bytes))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while (bypassed--);
|
} while (bypassed--);
|
||||||
|
@ -320,6 +322,7 @@ static int map_io(struct multipath *m, struct bio *bio,
|
||||||
struct dm_mpath_io *mpio, unsigned was_queued)
|
struct dm_mpath_io *mpio, unsigned was_queued)
|
||||||
{
|
{
|
||||||
int r = DM_MAPIO_REMAPPED;
|
int r = DM_MAPIO_REMAPPED;
|
||||||
|
size_t nr_bytes = bio->bi_size;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct pgpath *pgpath;
|
struct pgpath *pgpath;
|
||||||
|
|
||||||
|
@ -328,7 +331,7 @@ static int map_io(struct multipath *m, struct bio *bio,
|
||||||
/* Do we need to select a new pgpath? */
|
/* Do we need to select a new pgpath? */
|
||||||
if (!m->current_pgpath ||
|
if (!m->current_pgpath ||
|
||||||
(!m->queue_io && (m->repeat_count && --m->repeat_count == 0)))
|
(!m->queue_io && (m->repeat_count && --m->repeat_count == 0)))
|
||||||
__choose_pgpath(m);
|
__choose_pgpath(m, nr_bytes);
|
||||||
|
|
||||||
pgpath = m->current_pgpath;
|
pgpath = m->current_pgpath;
|
||||||
|
|
||||||
|
@ -353,6 +356,11 @@ static int map_io(struct multipath *m, struct bio *bio,
|
||||||
r = -EIO; /* Failed */
|
r = -EIO; /* Failed */
|
||||||
|
|
||||||
mpio->pgpath = pgpath;
|
mpio->pgpath = pgpath;
|
||||||
|
mpio->nr_bytes = nr_bytes;
|
||||||
|
|
||||||
|
if (r == DM_MAPIO_REMAPPED && pgpath->pg->ps.type->start_io)
|
||||||
|
pgpath->pg->ps.type->start_io(&pgpath->pg->ps, &pgpath->path,
|
||||||
|
nr_bytes);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&m->lock, flags);
|
spin_unlock_irqrestore(&m->lock, flags);
|
||||||
|
|
||||||
|
@ -431,7 +439,7 @@ static void process_queued_ios(struct work_struct *work)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!m->current_pgpath)
|
if (!m->current_pgpath)
|
||||||
__choose_pgpath(m);
|
__choose_pgpath(m, 0);
|
||||||
|
|
||||||
pgpath = m->current_pgpath;
|
pgpath = m->current_pgpath;
|
||||||
|
|
||||||
|
@ -1209,7 +1217,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio,
|
||||||
if (pgpath) {
|
if (pgpath) {
|
||||||
ps = &pgpath->pg->ps;
|
ps = &pgpath->pg->ps;
|
||||||
if (ps->type->end_io)
|
if (ps->type->end_io)
|
||||||
ps->type->end_io(ps, &pgpath->path);
|
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
|
||||||
}
|
}
|
||||||
if (r != DM_ENDIO_INCOMPLETE)
|
if (r != DM_ENDIO_INCOMPLETE)
|
||||||
mempool_free(mpio, m->mpio_pool);
|
mempool_free(mpio, m->mpio_pool);
|
||||||
|
@ -1425,7 +1433,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
|
||||||
spin_lock_irqsave(&m->lock, flags);
|
spin_lock_irqsave(&m->lock, flags);
|
||||||
|
|
||||||
if (!m->current_pgpath)
|
if (!m->current_pgpath)
|
||||||
__choose_pgpath(m);
|
__choose_pgpath(m, 0);
|
||||||
|
|
||||||
if (m->current_pgpath) {
|
if (m->current_pgpath) {
|
||||||
bdev = m->current_pgpath->path.dev->bdev;
|
bdev = m->current_pgpath->path.dev->bdev;
|
||||||
|
|
|
@ -56,7 +56,8 @@ struct path_selector_type {
|
||||||
* the path fails.
|
* the path fails.
|
||||||
*/
|
*/
|
||||||
struct dm_path *(*select_path) (struct path_selector *ps,
|
struct dm_path *(*select_path) (struct path_selector *ps,
|
||||||
unsigned *repeat_count);
|
unsigned *repeat_count,
|
||||||
|
size_t nr_bytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify the selector that a path has failed.
|
* Notify the selector that a path has failed.
|
||||||
|
@ -75,7 +76,10 @@ struct path_selector_type {
|
||||||
int (*status) (struct path_selector *ps, struct dm_path *path,
|
int (*status) (struct path_selector *ps, struct dm_path *path,
|
||||||
status_type_t type, char *result, unsigned int maxlen);
|
status_type_t type, char *result, unsigned int maxlen);
|
||||||
|
|
||||||
int (*end_io) (struct path_selector *ps, struct dm_path *path);
|
int (*start_io) (struct path_selector *ps, struct dm_path *path,
|
||||||
|
size_t nr_bytes);
|
||||||
|
int (*end_io) (struct path_selector *ps, struct dm_path *path,
|
||||||
|
size_t nr_bytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Register a path selector */
|
/* Register a path selector */
|
||||||
|
|
|
@ -161,7 +161,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dm_path *rr_select_path(struct path_selector *ps,
|
static struct dm_path *rr_select_path(struct path_selector *ps,
|
||||||
unsigned *repeat_count)
|
unsigned *repeat_count, size_t nr_bytes)
|
||||||
{
|
{
|
||||||
struct selector *s = (struct selector *) ps->context;
|
struct selector *s = (struct selector *) ps->context;
|
||||||
struct path_info *pi = NULL;
|
struct path_info *pi = NULL;
|
||||||
|
|
Loading…
Reference in a new issue