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

Commit cda6b5ab authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Mike Snitzer
Browse files

dm delay: add flush as a third class of IO



Add a new class for dm-delay that delays flush requests.  Previously,
flushes were delayed as writes, but it caused problems if the user
needed to create a device with one or a few slow sectors for the purpose
of testing - all flushes would be forwarded to this device and delayed,
and that skews the test results.  Fix this by allowing to select 0 delay
for flushes.

Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 3876ac76
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -5,7 +5,8 @@ Device-Mapper's "delay" target delays reads and/or writes
and maps them to different devices.

Parameters:
    <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
    <device> <offset> <delay> [<write_device> <write_offset> <write_delay>
			       [<flush_device> <flush_offset> <flush_delay>]]

With separate write parameters, the first set is only used for reads.
Offsets are specified in sectors.
+30 −4
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ struct delay_c {

	struct delay_class read;
	struct delay_class write;
	struct delay_class flush;

	int argc;
};
@@ -126,6 +127,8 @@ static void delay_dtr(struct dm_target *ti)
		dm_put_device(ti, dc->read.dev);
	if (dc->write.dev)
		dm_put_device(ti, dc->write.dev);
	if (dc->flush.dev)
		dm_put_device(ti, dc->flush.dev);

	mutex_destroy(&dc->timer_lock);

@@ -171,8 +174,8 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
	struct delay_c *dc;
	int ret;

	if (argc != 3 && argc != 6) {
		ti->error = "Requires exactly 3 or 6 arguments";
	if (argc != 3 && argc != 6 && argc != 9) {
		ti->error = "Requires exactly 3, 6 or 9 arguments";
		return -EINVAL;
	}

@@ -196,6 +199,9 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)

	if (argc == 3) {
		ret = delay_class_ctr(ti, &dc->write, argv);
		if (ret)
			goto bad;
		ret = delay_class_ctr(ti, &dc->flush, argv);
		if (ret)
			goto bad;
		goto out;
@@ -204,6 +210,16 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
	ret = delay_class_ctr(ti, &dc->write, argv + 3);
	if (ret)
		goto bad;
	if (argc == 6) {
		ret = delay_class_ctr(ti, &dc->flush, argv + 3);
		if (ret)
			goto bad;
		goto out;
	}

	ret = delay_class_ctr(ti, &dc->flush, argv + 6);
	if (ret)
		goto bad;

out:
	dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
@@ -269,6 +285,9 @@ static int delay_map(struct dm_target *ti, struct bio *bio)
	struct dm_delay_info *delayed = dm_per_bio_data(bio, sizeof(struct dm_delay_info));

	if (bio_data_dir(bio) == WRITE) {
		if (unlikely(bio->bi_opf & REQ_PREFLUSH))
			c = &dc->flush;
		else
			c = &dc->write;
	} else {
		c = &dc->read;
@@ -292,7 +311,7 @@ static void delay_status(struct dm_target *ti, status_type_t type,

	switch (type) {
	case STATUSTYPE_INFO:
		DMEMIT("%u %u", dc->read.ops, dc->write.ops);
		DMEMIT("%u %u %u", dc->read.ops, dc->write.ops, dc->flush.ops);
		break;

	case STATUSTYPE_TABLE:
@@ -301,6 +320,10 @@ static void delay_status(struct dm_target *ti, status_type_t type,
			DMEMIT(" ");
			DMEMIT_DELAY_CLASS(&dc->write);
		}
		if (dc->argc >= 9) {
			DMEMIT(" ");
			DMEMIT_DELAY_CLASS(&dc->flush);
		}
		break;
	}
}
@@ -317,6 +340,9 @@ static int delay_iterate_devices(struct dm_target *ti,
	ret = fn(ti, dc->write.dev, dc->write.start, ti->len, data);
	if (ret)
		goto out;
	ret = fn(ti, dc->flush.dev, dc->flush.start, ti->len, data);
	if (ret)
		goto out;

out:
	return ret;