mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02: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