Commit 7ac9c1c2 authored by Linus Torvalds's avatar Linus Torvalds

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
parents ae1cfb11 7253a334
...@@ -63,6 +63,7 @@ struct multipath { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment