Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ac9c1c2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ struct multipath {

	const char *hw_handler_name;
	struct work_struct activate_path;
	struct pgpath *pgpath_to_activate;
	unsigned nr_priority_groups;
	struct list_head priority_groups;
	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)
{
	unsigned long flags;
	struct pgpath *pgpath, *tmp;
	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)
			scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
		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);
	}
}
@@ -421,6 +427,7 @@ static void process_queued_ios(struct work_struct *work)
		__choose_pgpath(m);

	pgpath = m->current_pgpath;
	m->pgpath_to_activate = m->current_pgpath;

	if ((pgpath && !m->queue_io) ||
	    (!pgpath && !m->queue_if_no_path))
@@ -1093,8 +1100,15 @@ static void activate_path(struct work_struct *work)
	int ret;
	struct multipath *m =
		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));
	pg_init_done(path, ret);
}
+8 −4
Original line number Diff line number Diff line
@@ -837,12 +837,14 @@ static int dm_merge_bvec(struct request_queue *q,
	struct dm_table *map = dm_get_table(md);
	struct dm_target *ti;
	sector_t max_sectors;
	int max_size;
	int max_size = 0;

	if (unlikely(!map))
		return 0;
		goto out;

	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
@@ -861,14 +863,16 @@ static int dm_merge_bvec(struct request_queue *q,
	if (max_size && ti->type->merge)
		max_size = ti->type->merge(ti, bvm, biovec, max_size);

out_table:
	dm_table_put(map);

out:
	/*
	 * Always allow an entire first page
	 */
	if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
		max_size = biovec->bv_len;

	dm_table_put(map);

	return max_size;
}