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

Commit 23508a96 authored by Mike Snitzer's avatar Mike Snitzer Committed by Alasdair G Kergon
Browse files

dm: add WRITE SAME support



WRITE SAME bios have a payload that contain a single page.  When
cloning WRITE SAME bios DM has no need to modify the bi_io_vec
attributes (and doing so would be detrimental).  DM need only alter the
start and end of the WRITE SAME bio accordingly.

Rather than duplicate __clone_and_map_discard, factor out a common
function that is also used by __clone_and_map_write_same.

Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent d54eaa5a
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -1174,7 +1174,28 @@ static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti)
	ci->sector_count = 0;
}

static int __clone_and_map_discard(struct clone_info *ci)
typedef unsigned (*get_num_requests_fn)(struct dm_target *ti);

static unsigned get_num_discard_requests(struct dm_target *ti)
{
	return ti->num_discard_requests;
}

static unsigned get_num_write_same_requests(struct dm_target *ti)
{
	return ti->num_write_same_requests;
}

typedef bool (*is_split_required_fn)(struct dm_target *ti);

static bool is_split_required_for_discard(struct dm_target *ti)
{
	return ti->split_discard_requests;
}

static int __clone_and_map_changing_extent_only(struct clone_info *ci,
						get_num_requests_fn get_num_requests,
						is_split_required_fn is_split_required)
{
	struct dm_target *ti;
	sector_t len;
@@ -1185,15 +1206,15 @@ static int __clone_and_map_discard(struct clone_info *ci)
			return -EIO;

		/*
		 * Even though the device advertised discard support,
		 * that does not mean every target supports it, and
		 * Even though the device advertised support for this type of
		 * request, that does not mean every target supports it, and
		 * reconfiguration might also have changed that since the
		 * check was performed.
		 */
		if (!ti->num_discard_requests)
		if (!get_num_requests || !get_num_requests(ti))
			return -EOPNOTSUPP;

		if (!ti->split_discard_requests)
		if (is_split_required && !is_split_required(ti))
			len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti));
		else
			len = min(ci->sector_count, max_io_len(ci->sector, ti));
@@ -1206,6 +1227,17 @@ static int __clone_and_map_discard(struct clone_info *ci)
	return 0;
}

static int __clone_and_map_discard(struct clone_info *ci)
{
	return __clone_and_map_changing_extent_only(ci, get_num_discard_requests,
						    is_split_required_for_discard);
}

static int __clone_and_map_write_same(struct clone_info *ci)
{
	return __clone_and_map_changing_extent_only(ci, get_num_write_same_requests, NULL);
}

static int __clone_and_map(struct clone_info *ci)
{
	struct bio *bio = ci->bio;
@@ -1215,6 +1247,8 @@ static int __clone_and_map(struct clone_info *ci)

	if (unlikely(bio->bi_rw & REQ_DISCARD))
		return __clone_and_map_discard(ci);
	else if (unlikely(bio->bi_rw & REQ_WRITE_SAME))
		return __clone_and_map_write_same(ci);

	ti = dm_table_find_target(ci->map, ci->sector);
	if (!dm_target_is_valid(ti))