Skip to content

Commit 5c0de3d

Browse files
Mikulas Patockasnitm
authored andcommitted
dm writecache: make writeback pause configurable
Commit 95b88f4 ("dm writecache: pause writeback if cache full and origin being written directly") introduced a code that pauses cache flushing if we are issuing writes directly to the origin. Improve that initial commit by making the timeout code configurable (via the option "pause_writeback"). Also change the default from 1s to 3s because it performed better. Signed-off-by: Mikulas Patocka <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 95b88f4 commit 5c0de3d

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

Documentation/admin-guide/device-mapper/writecache.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ first sector should contain valid superblock from previous invocation.
1212
Constructor parameters:
1313

1414
1. type of the cache device - "p" or "s"
15-
1615
- p - persistent memory
1716
- s - SSD
1817
2. the underlying device that will be cached
@@ -21,7 +20,6 @@ Constructor parameters:
2120
size)
2221
5. the number of optional parameters (the parameters with an argument
2322
count as two)
24-
2523
start_sector n (default: 0)
2624
offset from the start of cache device in 512-byte sectors
2725
high_watermark n (default: 50)
@@ -71,6 +69,9 @@ Constructor parameters:
7169
metadata_only
7270
only metadata is promoted to the cache. This option
7371
improves performance for heavier REQ_META workloads.
72+
pause_writeback n (default: 3000)
73+
pause writeback if there was some write I/O redirected to
74+
the origin volume in the last n milliseconds
7475

7576
Status:
7677
1. error indicator - 0 if there was no error, otherwise error number

drivers/md/dm-io-tracker.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ static inline bool dm_iot_idle_for(struct dm_io_tracker *iot, unsigned long j)
4545
return r;
4646
}
4747

48+
static inline unsigned long dm_iot_idle_time(struct dm_io_tracker *iot)
49+
{
50+
unsigned long r = 0;
51+
52+
spin_lock_irq(&iot->lock);
53+
if (!iot->in_flight)
54+
r = jiffies - iot->idle_time;
55+
spin_unlock_irq(&iot->lock);
56+
57+
return r;
58+
}
59+
4860
static inline void dm_iot_io_begin(struct dm_io_tracker *iot, sector_t len)
4961
{
5062
spin_lock_irq(&iot->lock);

drivers/md/dm-writecache.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define AUTOCOMMIT_MSEC 1000
3131
#define MAX_AGE_DIV 16
3232
#define MAX_AGE_UNSPECIFIED -1UL
33+
#define PAUSE_WRITEBACK (HZ * 3)
3334

3435
#define BITMAP_GRANULARITY 65536
3536
#if BITMAP_GRANULARITY < PAGE_SIZE
@@ -125,6 +126,7 @@ struct dm_writecache {
125126
size_t freelist_high_watermark;
126127
size_t freelist_low_watermark;
127128
unsigned long max_age;
129+
unsigned long pause;
128130

129131
unsigned uncommitted_blocks;
130132
unsigned autocommit_blocks;
@@ -174,11 +176,13 @@ struct dm_writecache {
174176
bool cleaner:1;
175177
bool cleaner_set:1;
176178
bool metadata_only:1;
179+
bool pause_set:1;
177180

178181
unsigned high_wm_percent_value;
179182
unsigned low_wm_percent_value;
180183
unsigned autocommit_time_value;
181184
unsigned max_age_value;
185+
unsigned pause_value;
182186

183187
unsigned writeback_all;
184188
struct workqueue_struct *writeback_wq;
@@ -1470,9 +1474,11 @@ static int writecache_map(struct dm_target *ti, struct bio *bio)
14701474
}
14711475

14721476
unlock_remap_origin:
1473-
if (bio_data_dir(bio) != READ) {
1474-
dm_iot_io_begin(&wc->iot, 1);
1475-
bio->bi_private = (void *)2;
1477+
if (likely(wc->pause != 0)) {
1478+
if (bio_op(bio) == REQ_OP_WRITE) {
1479+
dm_iot_io_begin(&wc->iot, 1);
1480+
bio->bi_private = (void *)2;
1481+
}
14761482
}
14771483
bio_set_dev(bio, wc->dev->bdev);
14781484
wc_unlock(wc);
@@ -1837,10 +1843,19 @@ static void writecache_writeback(struct work_struct *work)
18371843
dm_kcopyd_client_flush(wc->dm_kcopyd);
18381844
}
18391845

1840-
if (!wc->writeback_all && !dm_suspended(wc->ti)) {
1841-
while (!dm_iot_idle_for(&wc->iot, HZ)) {
1842-
cond_resched();
1843-
msleep(1000);
1846+
if (likely(wc->pause != 0)) {
1847+
while (1) {
1848+
unsigned long idle;
1849+
if (unlikely(wc->cleaner) || unlikely(wc->writeback_all) ||
1850+
unlikely(dm_suspended(wc->ti)))
1851+
break;
1852+
idle = dm_iot_idle_time(&wc->iot);
1853+
if (idle >= wc->pause)
1854+
break;
1855+
idle = wc->pause - idle;
1856+
if (idle > HZ)
1857+
idle = HZ;
1858+
schedule_timeout_idle(idle);
18441859
}
18451860
}
18461861

@@ -2113,7 +2128,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
21132128
struct wc_memory_superblock s;
21142129

21152130
static struct dm_arg _args[] = {
2116-
{0, 17, "Invalid number of feature args"},
2131+
{0, 18, "Invalid number of feature args"},
21172132
};
21182133

21192134
as.argc = argc;
@@ -2206,6 +2221,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
22062221
goto bad;
22072222
}
22082223
} else {
2224+
wc->pause = PAUSE_WRITEBACK;
22092225
r = mempool_init_kmalloc_pool(&wc->copy_pool, 1, sizeof(struct copy_struct));
22102226
if (r) {
22112227
ti->error = "Could not allocate mempool";
@@ -2344,6 +2360,18 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
23442360
} else goto invalid_optional;
23452361
} else if (!strcasecmp(string, "metadata_only")) {
23462362
wc->metadata_only = true;
2363+
} else if (!strcasecmp(string, "pause_writeback") && opt_params >= 1) {
2364+
unsigned pause_msecs;
2365+
if (WC_MODE_PMEM(wc))
2366+
goto invalid_optional;
2367+
string = dm_shift_arg(&as), opt_params--;
2368+
if (sscanf(string, "%u%c", &pause_msecs, &dummy) != 1)
2369+
goto invalid_optional;
2370+
if (pause_msecs > 60000)
2371+
goto invalid_optional;
2372+
wc->pause = msecs_to_jiffies(pause_msecs);
2373+
wc->pause_set = true;
2374+
wc->pause_value = pause_msecs;
23472375
} else {
23482376
invalid_optional:
23492377
r = -EINVAL;
@@ -2569,6 +2597,8 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
25692597
extra_args++;
25702598
if (wc->metadata_only)
25712599
extra_args++;
2600+
if (wc->pause_set)
2601+
extra_args += 2;
25722602

25732603
DMEMIT("%u", extra_args);
25742604
if (wc->start_sector_set)
@@ -2591,6 +2621,8 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
25912621
DMEMIT(" %sfua", wc->writeback_fua ? "" : "no");
25922622
if (wc->metadata_only)
25932623
DMEMIT(" metadata_only");
2624+
if (wc->pause_set)
2625+
DMEMIT(" pause_writeback %u", wc->pause_value);
25942626
break;
25952627
}
25962628
}

0 commit comments

Comments
 (0)