From d4e2076b5c658b73e5a876815ccacbb6889bcbd0 Mon Sep 17 00:00:00 2001 From: Akira Hayakawa Date: Fri, 10 Jan 2025 09:17:51 +0900 Subject: [PATCH 1/5] Use atomic_t instead of bool as cell->cancelled When cache cells are fulfilled, injection work is queued. Before cells are injected, they may be cancelled by the foreground path. Therefore, atomic type should be used. Signed-off-by: Akira Hayakawa --- src/dm-writeboost-target.c | 16 ++++++++-------- src/dm-writeboost.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dm-writeboost-target.c b/src/dm-writeboost-target.c index bb6dd3f9..520e7ae2 100644 --- a/src/dm-writeboost-target.c +++ b/src/dm-writeboost-target.c @@ -760,7 +760,7 @@ static void read_cache_cancel_cells(struct read_cache_cells *cells, u32 n) last = cells->size; for (i = cells->cursor; i < last; i++) { struct read_cache_cell *cell = cells->array + i; - cell->cancelled = true; + atomic_set(&cell->cancelled, 1); } } @@ -780,7 +780,7 @@ static void read_cache_cancel_foreground(struct read_cache_cells *cells, if (cells->seqcount > cells->threshold) { if (cells->over_threshold) - new_cell->cancelled = true; + atomic_set(&new_cell->cancelled, 1); else { cells->over_threshold = true; read_cache_cancel_cells(cells, cells->seqcount); @@ -839,7 +839,7 @@ static void might_cancel_read_cache_cell(struct wb_device *wb, struct bio *bio) struct read_cache_cell *found; found = lookup_read_cache_cell(wb, calc_cache_alignment(bi_sector(bio))); if (found) - found->cancelled = true; + atomic_set(&found->cancelled, 1); } static void read_cache_cell_copy_data(struct wb_device *wb, struct bio *bio, unsigned long error) @@ -852,13 +852,13 @@ static void read_cache_cell_copy_data(struct wb_device *wb, struct bio *bio, uns /* Data can be broken. So don't stage. */ if (error) - cell->cancelled = true; + atomic_set(&cell->cancelled, 1); /* * We can omit copying if the cell is cancelled but * copying for a non-cancelled cell isn't problematic. */ - if (!cell->cancelled) + if (!atomic_read(&cell->cancelled)) copy_bio_payload(cell->data, bio); if (atomic_dec_and_test(&cells->ack_count)) @@ -884,7 +884,7 @@ static void inject_read_cache(struct wb_device *wb, struct read_cache_cell *cell * if might_cancel_read_cache_cell() on the foreground * cancelled this cell, the data is now stale. */ - if (cell->cancelled) { + if (atomic_read(&cell->cancelled)) { mutex_unlock(&wb->io_lock); return; } @@ -986,7 +986,7 @@ static void reinit_read_cache_cells(struct wb_device *wb) atomic_set(&cells->ack_count, cells->size); for (i = 0; i < cells->size; i++) { struct read_cache_cell *cell = cells->array + i; - cell->cancelled = false; + atomic_set(&cell->cancelled, 0); } cur_threshold = read_once(wb->read_cache_threshold); if (cur_threshold && (cur_threshold != cells->threshold)) { @@ -1004,7 +1004,7 @@ static void visit_and_cancel_cells(struct rb_node *first, struct rb_node *last) struct rb_node *rbp = first; while (rbp != last) { struct read_cache_cell *cell = read_cache_cell_from_node(rbp); - cell->cancelled = true; + atomic_set(&cell->cancelled, 1); rbp = rb_next(rbp); } } diff --git a/src/dm-writeboost.h b/src/dm-writeboost.h index 37a3a423..29ccf812 100644 --- a/src/dm-writeboost.h +++ b/src/dm-writeboost.h @@ -207,7 +207,7 @@ struct writeback_segment { struct read_cache_cell { sector_t sector; void *data; /* 4KB data read */ - bool cancelled; /* Don't include this */ + atomic_t cancelled; /* Don't include this */ struct rb_node rb_node; }; From 5644eb99f1dbf5f31992e90ca099e7e269864373 Mon Sep 17 00:00:00 2001 From: Akira Hayakawa Date: Fri, 10 Jan 2025 10:43:24 +0900 Subject: [PATCH 2/5] optimize: Need not to cancel cache cell on cache-hit A cache cell is reserved only when it is cache-miss (and the bio is 4KB large) and if there were some writes on the block, it is cancelled. Therefore, we can't find any valid cache cell on cache-hit. Signed-off-by: Akira Hayakawa --- src/dm-writeboost-target.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dm-writeboost-target.c b/src/dm-writeboost-target.c index 520e7ae2..2663f940 100644 --- a/src/dm-writeboost-target.c +++ b/src/dm-writeboost-target.c @@ -1260,9 +1260,8 @@ static int process_write_wa(struct wb_device *wb, struct bio *bio) if (res.found) { dec_inflight_ios(wb, res.found_seg); ht_del(wb, res.found_mb); - } - - might_cancel_read_cache_cell(wb, bio); + } else + might_cancel_read_cache_cell(wb, bio); mutex_unlock(&wb->io_lock); bio_remap(bio, wb->backing_dev, bi_sector(bio)); From d836a7c06c9aa9927b03cd595d07f3e09e52189b Mon Sep 17 00:00:00 2001 From: Akira Hayakawa Date: Fri, 10 Jan 2025 20:02:56 +0900 Subject: [PATCH 3/5] read cache: reinit function need not to take lock on initialization Signed-off-by: Akira Hayakawa --- src/dm-writeboost-target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dm-writeboost-target.c b/src/dm-writeboost-target.c index 2663f940..b2673a58 100644 --- a/src/dm-writeboost-target.c +++ b/src/dm-writeboost-target.c @@ -980,7 +980,6 @@ static void reinit_read_cache_cells(struct wb_device *wb) struct read_cache_cells *cells = wb->read_cache_cells; u32 i, cur_threshold; - mutex_lock(&wb->io_lock); cells->rb_root = RB_ROOT; cells->cursor = cells->size; atomic_set(&cells->ack_count, cells->size); @@ -993,7 +992,6 @@ static void reinit_read_cache_cells(struct wb_device *wb) cells->threshold = cur_threshold; cells->over_threshold = false; } - mutex_unlock(&wb->io_lock); } /* @@ -1049,7 +1047,9 @@ static void read_cache_proc(struct work_struct *work) inject_read_cache(wb, cell); } + mutex_lock(&wb->io_lock); reinit_read_cache_cells(wb); + mutex_unlock(&wb->io_lock); } static int init_read_cache_cells(struct wb_device *wb) From c7c6dc2bc7d2f39556a9acbbd314444bf2c9402f Mon Sep 17 00:00:00 2001 From: Akira Hayakawa Date: Fri, 10 Jan 2025 20:14:04 +0900 Subject: [PATCH 4/5] Add .gitignore Signed-off-by: Akira Hayakawa --- src/.gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/.gitignore diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 00000000..d38a03cf --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,8 @@ +* +!.gitignore +!dm-writeboost.h +!dm-writeboost-target.[c] +!dm-writeboost-metadata.[ch] +!dm-writeboost-daemon.[ch] +!dkms.conf +!Makefile \ No newline at end of file From e956cc82980889108970da85fd466dabece145ed Mon Sep 17 00:00:00 2001 From: Akira Hayakawa Date: Sat, 11 Jan 2025 09:28:44 +0900 Subject: [PATCH 5/5] refactor: Remove unused variable n in read_cache_cancel_cells Signed-off-by: Akira Hayakawa --- src/dm-writeboost-target.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dm-writeboost-target.c b/src/dm-writeboost-target.c index b2673a58..51c9df16 100644 --- a/src/dm-writeboost-target.c +++ b/src/dm-writeboost-target.c @@ -752,7 +752,10 @@ static struct read_cache_cell *lookup_read_cache_cell(struct wb_device *wb, sect return NULL; } -static void read_cache_cancel_cells(struct read_cache_cells *cells, u32 n) +/* + * Cancel all cells in [cursor, cursor + seqcount). + */ +static void read_cache_cancel_seq_cells(struct read_cache_cells *cells) { u32 i; u32 last = cells->cursor + cells->seqcount; @@ -783,7 +786,7 @@ static void read_cache_cancel_foreground(struct read_cache_cells *cells, atomic_set(&new_cell->cancelled, 1); else { cells->over_threshold = true; - read_cache_cancel_cells(cells, cells->seqcount); + read_cache_cancel_seq_cells(cells); } } cells->last_sector = new_cell->sector;