summaryrefslogtreecommitdiff
path: root/fs/bcachefs/journal.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-02-25 10:28:20 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:26 -0400
commitfbec3b8800ac8244ce751d0ba5b83d94ee48fc76 (patch)
tree7dc294ade316a64524431c7917c62e79e3185699 /fs/bcachefs/journal.c
parent506bac7e59d93cfd883dab0697ed91850f319be6 (diff)
bcachefs: Kill JOURNAL_NEED_WRITE
This replaces the journal flag JOURNAL_NEED_WRITE with per-journal buf state - more explicit, and solving a race in the old code that would lead to entries being opened and written unnecessarily. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/journal.c')
-rw-r--r--fs/bcachefs/journal.c63
1 files changed, 45 insertions, 18 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 64875c8150f7..880ca2061012 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -86,6 +86,7 @@ static void bch2_journal_buf_init(struct journal *j)
buf->noflush = false;
buf->must_flush = false;
buf->separate_flush = false;
+ buf->flush_time = 0;
memset(buf->data, 0, sizeof(*buf->data));
buf->data->seq = cpu_to_le64(journal_cur_seq(j));
@@ -152,11 +153,6 @@ static bool __journal_entry_close(struct journal *j)
return true;
}
- if (!test_bit(JOURNAL_NEED_WRITE, &j->flags)) {
- set_bit(JOURNAL_NEED_WRITE, &j->flags);
- j->need_write_time = local_clock();
- }
-
new.cur_entry_offset = JOURNAL_ENTRY_CLOSED_VAL;
new.idx++;
@@ -205,7 +201,6 @@ static bool __journal_entry_close(struct journal *j)
bch2_journal_buf_init(j);
cancel_delayed_work(&j->write_work);
- clear_bit(JOURNAL_NEED_WRITE, &j->flags);
bch2_journal_space_available(j);
@@ -216,15 +211,16 @@ static bool __journal_entry_close(struct journal *j)
static bool journal_entry_want_write(struct journal *j)
{
union journal_res_state s = READ_ONCE(j->reservations);
+ struct journal_buf *buf = journal_cur_buf(j);
bool ret = false;
- /*
- * Don't close it yet if we already have a write in flight, but do set
- * NEED_WRITE:
- */
- if (s.idx != s.unwritten_idx)
- set_bit(JOURNAL_NEED_WRITE, &j->flags);
- else
+ if (!buf->flush_time) {
+ buf->flush_time = local_clock() ?: 1;
+ buf->expires = jiffies;
+ }
+
+ /* Don't close it yet if we already have a write in flight: */
+ if (s.idx == s.unwritten_idx)
ret = __journal_entry_close(j);
return ret;
@@ -278,6 +274,8 @@ static int journal_entry_open(struct journal *j)
*/
BUG_ON(buf->data->u64s);
+ buf->expires = jiffies +
+ msecs_to_jiffies(c->opts.journal_flush_delay);
buf->u64s_reserved = j->entry_u64s_reserved;
buf->disk_sectors = j->cur_entry_sectors;
buf->sectors = min(buf->disk_sectors, buf->buf_size >> 9);
@@ -337,8 +335,19 @@ static void journal_quiesce(struct journal *j)
static void journal_write_work(struct work_struct *work)
{
struct journal *j = container_of(work, struct journal, write_work.work);
+ struct bch_fs *c = container_of(j, struct bch_fs, journal);
+ struct journal_buf *buf;
+ long delta;
- journal_entry_close(j);
+ spin_lock(&j->lock);
+ buf = journal_cur_buf(j);
+ delta = buf->expires - jiffies;
+
+ if (delta > 0)
+ mod_delayed_work(c->io_complete_wq, &j->write_work, delta);
+ else
+ __journal_entry_close(j);
+ spin_unlock(&j->lock);
}
static int __journal_res_get(struct journal *j, struct journal_res *res,
@@ -591,7 +600,11 @@ recheck_need_open:
seq = res.seq;
buf = j->buf + (seq & JOURNAL_BUF_MASK);
buf->must_flush = true;
- set_bit(JOURNAL_NEED_WRITE, &j->flags);
+
+ if (!buf->flush_time) {
+ buf->flush_time = local_clock() ?: 1;
+ buf->expires = jiffies;
+ }
if (parent && !closure_wait(&buf->wait, parent))
BUG();
@@ -657,7 +670,11 @@ int bch2_journal_meta(struct journal *j)
buf = j->buf + (res.seq & JOURNAL_BUF_MASK);
buf->must_flush = true;
- set_bit(JOURNAL_NEED_WRITE, &j->flags);
+
+ if (!buf->flush_time) {
+ buf->flush_time = local_clock() ?: 1;
+ buf->expires = jiffies;
+ }
bch2_journal_res_put(j, &res);
@@ -1233,12 +1250,22 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
pr_buf(out, "unwritten entry:\tidx %u refcount %u sectors %u\n",
i, journal_state_count(s, i), j->buf[i].sectors);
+ pr_indent_push(out, 2);
+
+ pr_buf(out, "refcount %u", journal_state_count(s, i));
+ pr_newline(out);
+
+ pr_buf(out, "sectors %u", j->buf[i].sectors);
+ pr_newline(out);
+
+ pr_buf(out, "expires %li ms", jiffies_to_msecs(j->buf[i].expires - jiffies));
+ pr_newline(out);
+
+ pr_indent_pop(out, 2);
}
pr_buf(out,
- "need write:\t\t%i\n"
"replay done:\t\t%i\n",
- test_bit(JOURNAL_NEED_WRITE, &j->flags),
test_bit(JOURNAL_REPLAY_DONE, &j->flags));
pr_buf(out, "space:\n");