bcachefs: Can now block journal activity without closing cur entry

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-11-23 16:27:47 -05:00
parent c80f33b752
commit c601e5d7da
3 changed files with 46 additions and 3 deletions

View File

@ -217,6 +217,12 @@ void bch2_journal_buf_put_final(struct journal *j, u64 seq)
if (__bch2_journal_pin_put(j, seq))
bch2_journal_reclaim_fast(j);
bch2_journal_do_writes(j);
/*
* for __bch2_next_write_buffer_flush_journal_buf(), when quiescing an
* open journal entry
*/
wake_up(&j->wait);
}
/*
@ -251,6 +257,9 @@ static void __journal_entry_close(struct journal *j, unsigned closed_val, bool t
if (!__journal_entry_is_open(old))
return;
if (old.cur_entry_offset == JOURNAL_ENTRY_BLOCKED_VAL)
old.cur_entry_offset = j->cur_entry_offset_if_blocked;
/* Close out old buffer: */
buf->data->u64s = cpu_to_le32(old.cur_entry_offset);
@ -868,16 +877,44 @@ int bch2_journal_meta(struct journal *j)
void bch2_journal_unblock(struct journal *j)
{
spin_lock(&j->lock);
j->blocked--;
if (!--j->blocked &&
j->cur_entry_offset_if_blocked < JOURNAL_ENTRY_CLOSED_VAL &&
j->reservations.cur_entry_offset == JOURNAL_ENTRY_BLOCKED_VAL) {
union journal_res_state old, new;
old.v = atomic64_read(&j->reservations.counter);
do {
new.v = old.v;
new.cur_entry_offset = j->cur_entry_offset_if_blocked;
} while (!atomic64_try_cmpxchg(&j->reservations.counter, &old.v, new.v));
}
spin_unlock(&j->lock);
journal_wake(j);
}
static void __bch2_journal_block(struct journal *j)
{
if (!j->blocked++) {
union journal_res_state old, new;
old.v = atomic64_read(&j->reservations.counter);
do {
j->cur_entry_offset_if_blocked = old.cur_entry_offset;
if (j->cur_entry_offset_if_blocked >= JOURNAL_ENTRY_CLOSED_VAL)
break;
new.v = old.v;
new.cur_entry_offset = JOURNAL_ENTRY_BLOCKED_VAL;
} while (!atomic64_try_cmpxchg(&j->reservations.counter, &old.v, new.v));
}
}
void bch2_journal_block(struct journal *j)
{
spin_lock(&j->lock);
j->blocked++;
__bch2_journal_block(j);
spin_unlock(&j->lock);
journal_quiesce(j);
@ -1481,6 +1518,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
case JOURNAL_ENTRY_CLOSED_VAL:
prt_printf(out, "closed\n");
break;
case JOURNAL_ENTRY_BLOCKED_VAL:
prt_printf(out, "blocked\n");
break;
default:
prt_printf(out, "%u/%u\n", s.cur_entry_offset, j->cur_entry_u64s);
break;

View File

@ -285,7 +285,8 @@ static inline void bch2_journal_buf_put(struct journal *j, unsigned idx, u64 seq
spin_lock(&j->lock);
bch2_journal_buf_put_final(j, seq);
spin_unlock(&j->lock);
}
} else if (unlikely(s.cur_entry_offset == JOURNAL_ENTRY_BLOCKED_VAL))
wake_up(&j->wait);
}
/*

View File

@ -112,6 +112,7 @@ union journal_res_state {
*/
#define JOURNAL_ENTRY_OFFSET_MAX ((1U << 20) - 1)
#define JOURNAL_ENTRY_BLOCKED_VAL (JOURNAL_ENTRY_OFFSET_MAX - 2)
#define JOURNAL_ENTRY_CLOSED_VAL (JOURNAL_ENTRY_OFFSET_MAX - 1)
#define JOURNAL_ENTRY_ERROR_VAL (JOURNAL_ENTRY_OFFSET_MAX)
@ -193,6 +194,7 @@ struct journal {
* insufficient devices:
*/
enum journal_errors cur_entry_error;
unsigned cur_entry_offset_if_blocked;
unsigned buf_size_want;
/*