Skip to content

Commit cda6b5a

Browse files
Mikulas Patockasnitm
authored andcommitted
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: Mikulas Patocka <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 3876ac7 commit cda6b5a

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

Documentation/device-mapper/delay.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ Device-Mapper's "delay" target delays reads and/or writes
55
and maps them to different devices.
66

77
Parameters:
8-
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
8+
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>
9+
[<flush_device> <flush_offset> <flush_delay>]]
910

1011
With separate write parameters, the first set is only used for reads.
1112
Offsets are specified in sectors.

drivers/md/dm-delay.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct delay_c {
3434

3535
struct delay_class read;
3636
struct delay_class write;
37+
struct delay_class flush;
3738

3839
int argc;
3940
};
@@ -126,6 +127,8 @@ static void delay_dtr(struct dm_target *ti)
126127
dm_put_device(ti, dc->read.dev);
127128
if (dc->write.dev)
128129
dm_put_device(ti, dc->write.dev);
130+
if (dc->flush.dev)
131+
dm_put_device(ti, dc->flush.dev);
129132

130133
mutex_destroy(&dc->timer_lock);
131134

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

174-
if (argc != 3 && argc != 6) {
175-
ti->error = "Requires exactly 3 or 6 arguments";
177+
if (argc != 3 && argc != 6 && argc != 9) {
178+
ti->error = "Requires exactly 3, 6 or 9 arguments";
176179
return -EINVAL;
177180
}
178181

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

197200
if (argc == 3) {
198201
ret = delay_class_ctr(ti, &dc->write, argv);
202+
if (ret)
203+
goto bad;
204+
ret = delay_class_ctr(ti, &dc->flush, argv);
199205
if (ret)
200206
goto bad;
201207
goto out;
@@ -204,6 +210,16 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
204210
ret = delay_class_ctr(ti, &dc->write, argv + 3);
205211
if (ret)
206212
goto bad;
213+
if (argc == 6) {
214+
ret = delay_class_ctr(ti, &dc->flush, argv + 3);
215+
if (ret)
216+
goto bad;
217+
goto out;
218+
}
219+
220+
ret = delay_class_ctr(ti, &dc->flush, argv + 6);
221+
if (ret)
222+
goto bad;
207223

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

271287
if (bio_data_dir(bio) == WRITE) {
272-
c = &dc->write;
288+
if (unlikely(bio->bi_opf & REQ_PREFLUSH))
289+
c = &dc->flush;
290+
else
291+
c = &dc->write;
273292
} else {
274293
c = &dc->read;
275294
}
@@ -292,7 +311,7 @@ static void delay_status(struct dm_target *ti, status_type_t type,
292311

293312
switch (type) {
294313
case STATUSTYPE_INFO:
295-
DMEMIT("%u %u", dc->read.ops, dc->write.ops);
314+
DMEMIT("%u %u %u", dc->read.ops, dc->write.ops, dc->flush.ops);
296315
break;
297316

298317
case STATUSTYPE_TABLE:
@@ -301,6 +320,10 @@ static void delay_status(struct dm_target *ti, status_type_t type,
301320
DMEMIT(" ");
302321
DMEMIT_DELAY_CLASS(&dc->write);
303322
}
323+
if (dc->argc >= 9) {
324+
DMEMIT(" ");
325+
DMEMIT_DELAY_CLASS(&dc->flush);
326+
}
304327
break;
305328
}
306329
}
@@ -317,6 +340,9 @@ static int delay_iterate_devices(struct dm_target *ti,
317340
ret = fn(ti, dc->write.dev, dc->write.start, ti->len, data);
318341
if (ret)
319342
goto out;
343+
ret = fn(ti, dc->flush.dev, dc->flush.start, ti->len, data);
344+
if (ret)
345+
goto out;
320346

321347
out:
322348
return ret;

0 commit comments

Comments
 (0)