Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm
* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm: dm mpath: add missing path switching locking dm: cope with access beyond end of device in dm_merge_bvec dm: always allow one page in dm_merge_bvec
This commit is contained in:
@@ -63,6 +63,7 @@ struct multipath {
|
|||||||
|
|
||||||
const char *hw_handler_name;
|
const char *hw_handler_name;
|
||||||
struct work_struct activate_path;
|
struct work_struct activate_path;
|
||||||
|
struct pgpath *pgpath_to_activate;
|
||||||
unsigned nr_priority_groups;
|
unsigned nr_priority_groups;
|
||||||
struct list_head priority_groups;
|
struct list_head priority_groups;
|
||||||
unsigned pg_init_required; /* pg_init needs calling? */
|
unsigned pg_init_required; /* pg_init needs calling? */
|
||||||
@@ -146,6 +147,7 @@ static struct priority_group *alloc_priority_group(void)
|
|||||||
|
|
||||||
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
|
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct pgpath *pgpath, *tmp;
|
struct pgpath *pgpath, *tmp;
|
||||||
struct multipath *m = ti->private;
|
struct multipath *m = ti->private;
|
||||||
|
|
||||||
@@ -154,6 +156,10 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
|
|||||||
if (m->hw_handler_name)
|
if (m->hw_handler_name)
|
||||||
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
|
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
|
||||||
dm_put_device(ti, pgpath->path.dev);
|
dm_put_device(ti, pgpath->path.dev);
|
||||||
|
spin_lock_irqsave(&m->lock, flags);
|
||||||
|
if (m->pgpath_to_activate == pgpath)
|
||||||
|
m->pgpath_to_activate = NULL;
|
||||||
|
spin_unlock_irqrestore(&m->lock, flags);
|
||||||
free_pgpath(pgpath);
|
free_pgpath(pgpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,6 +427,7 @@ static void process_queued_ios(struct work_struct *work)
|
|||||||
__choose_pgpath(m);
|
__choose_pgpath(m);
|
||||||
|
|
||||||
pgpath = m->current_pgpath;
|
pgpath = m->current_pgpath;
|
||||||
|
m->pgpath_to_activate = m->current_pgpath;
|
||||||
|
|
||||||
if ((pgpath && !m->queue_io) ||
|
if ((pgpath && !m->queue_io) ||
|
||||||
(!pgpath && !m->queue_if_no_path))
|
(!pgpath && !m->queue_if_no_path))
|
||||||
@@ -1093,8 +1100,15 @@ static void activate_path(struct work_struct *work)
|
|||||||
int ret;
|
int ret;
|
||||||
struct multipath *m =
|
struct multipath *m =
|
||||||
container_of(work, struct multipath, activate_path);
|
container_of(work, struct multipath, activate_path);
|
||||||
struct dm_path *path = &m->current_pgpath->path;
|
struct dm_path *path;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&m->lock, flags);
|
||||||
|
path = &m->pgpath_to_activate->path;
|
||||||
|
m->pgpath_to_activate = NULL;
|
||||||
|
spin_unlock_irqrestore(&m->lock, flags);
|
||||||
|
if (!path)
|
||||||
|
return;
|
||||||
ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
|
ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
|
||||||
pg_init_done(path, ret);
|
pg_init_done(path, ret);
|
||||||
}
|
}
|
||||||
|
@@ -837,12 +837,14 @@ static int dm_merge_bvec(struct request_queue *q,
|
|||||||
struct dm_table *map = dm_get_table(md);
|
struct dm_table *map = dm_get_table(md);
|
||||||
struct dm_target *ti;
|
struct dm_target *ti;
|
||||||
sector_t max_sectors;
|
sector_t max_sectors;
|
||||||
int max_size;
|
int max_size = 0;
|
||||||
|
|
||||||
if (unlikely(!map))
|
if (unlikely(!map))
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
ti = dm_table_find_target(map, bvm->bi_sector);
|
ti = dm_table_find_target(map, bvm->bi_sector);
|
||||||
|
if (!dm_target_is_valid(ti))
|
||||||
|
goto out_table;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find maximum amount of I/O that won't need splitting
|
* Find maximum amount of I/O that won't need splitting
|
||||||
@@ -861,14 +863,16 @@ static int dm_merge_bvec(struct request_queue *q,
|
|||||||
if (max_size && ti->type->merge)
|
if (max_size && ti->type->merge)
|
||||||
max_size = ti->type->merge(ti, bvm, biovec, max_size);
|
max_size = ti->type->merge(ti, bvm, biovec, max_size);
|
||||||
|
|
||||||
|
out_table:
|
||||||
|
dm_table_put(map);
|
||||||
|
|
||||||
|
out:
|
||||||
/*
|
/*
|
||||||
* Always allow an entire first page
|
* Always allow an entire first page
|
||||||
*/
|
*/
|
||||||
if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
|
if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
|
||||||
max_size = biovec->bv_len;
|
max_size = biovec->bv_len;
|
||||||
|
|
||||||
dm_table_put(map);
|
|
||||||
|
|
||||||
return max_size;
|
return max_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user