Skip to content

Commit 95b88f4

Browse files
Mikulas Patockasnitm
authored andcommitted
dm writecache: pause writeback if cache full and origin being written directly
Implementation reuses dm_io_tracker, that until now was only used by dm-cache, to track if any writes were issued directly to the origin (due to cache being full) within the last second. If so writeback is paused for a second. This change improves performance for when the cache is full and IO is issued directly to the origin device (rather than through the cache). Depends-on: d53f1fa ("dm writecache: do direct write if the cache is full") Suggested-by: Joe Thornber <[email protected]> Signed-off-by: Mikulas Patocka <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent dc4fa29 commit 95b88f4

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

drivers/md/dm-writecache.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <linux/dax.h>
1616
#include <linux/pfn_t.h>
1717
#include <linux/libnvdimm.h>
18+
#include <linux/delay.h>
19+
#include "dm-io-tracker.h"
1820

1921
#define DM_MSG_PREFIX "writecache"
2022

@@ -183,6 +185,8 @@ struct dm_writecache {
183185
struct work_struct writeback_work;
184186
struct work_struct flush_work;
185187

188+
struct dm_io_tracker iot;
189+
186190
struct dm_io_client *dm_io;
187191

188192
raw_spinlock_t endio_list_lock;
@@ -1466,6 +1470,10 @@ static int writecache_map(struct dm_target *ti, struct bio *bio)
14661470
}
14671471

14681472
unlock_remap_origin:
1473+
if (bio_data_dir(bio) != READ) {
1474+
dm_iot_io_begin(&wc->iot, 1);
1475+
bio->bi_private = (void *)2;
1476+
}
14691477
bio_set_dev(bio, wc->dev->bdev);
14701478
wc_unlock(wc);
14711479
return DM_MAPIO_REMAPPED;
@@ -1496,11 +1504,13 @@ static int writecache_end_io(struct dm_target *ti, struct bio *bio, blk_status_t
14961504
{
14971505
struct dm_writecache *wc = ti->private;
14981506

1499-
if (bio->bi_private != NULL) {
1507+
if (bio->bi_private == (void *)1) {
15001508
int dir = bio_data_dir(bio);
15011509
if (atomic_dec_and_test(&wc->bio_in_progress[dir]))
15021510
if (unlikely(waitqueue_active(&wc->bio_in_progress_wait[dir])))
15031511
wake_up(&wc->bio_in_progress_wait[dir]);
1512+
} else if (bio->bi_private == (void *)2) {
1513+
dm_iot_io_end(&wc->iot, 1);
15041514
}
15051515
return 0;
15061516
}
@@ -1827,6 +1837,13 @@ static void writecache_writeback(struct work_struct *work)
18271837
dm_kcopyd_client_flush(wc->dm_kcopyd);
18281838
}
18291839

1840+
if (!wc->writeback_all && !dm_suspended(wc->ti)) {
1841+
while (!dm_iot_idle_for(&wc->iot, HZ)) {
1842+
cond_resched();
1843+
msleep(1000);
1844+
}
1845+
}
1846+
18301847
wc_lock(wc);
18311848
restart:
18321849
if (writecache_has_error(wc)) {
@@ -2140,6 +2157,8 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
21402157
INIT_WORK(&wc->writeback_work, writecache_writeback);
21412158
INIT_WORK(&wc->flush_work, writecache_flush_work);
21422159

2160+
dm_iot_init(&wc->iot);
2161+
21432162
raw_spin_lock_init(&wc->endio_list_lock);
21442163
INIT_LIST_HEAD(&wc->endio_list);
21452164
wc->endio_thread = kthread_create(writecache_endio_thread, wc, "writecache_endio");

0 commit comments

Comments
 (0)