Skip to content

Commit

Permalink
Update bcachefs sources to 3b80552e7057 bcachefs: __wait_for_freeing_…
Browse files Browse the repository at this point in the history
…inode: Switch to wait_bit_queue_entry
  • Loading branch information
Kent Overstreet committed Oct 9, 2024
1 parent f6e4cd2 commit a9e1597
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .bcachefs_revision
Original file line number Diff line number Diff line change
@@ -1 +1 @@
895d5e67afdccd7c9262630f5e7972721885284b
3b80552e70573764bbf38b89c58749aef9dd8753
6 changes: 3 additions & 3 deletions include/linux/closure.h
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,10 @@ do { \
while (1) { \
closure_wait(waitlist, &cl); \
if (_cond) { \
_t = max(1, _until - jiffies); \
_t = max_t(long, 1L, _until - jiffies); \
break; \
} \
_t = max(0, _until - jiffies); \
_t = max_t(long, 0L, _until - jiffies); \
if (!_t) \
break; \
closure_sync_timeout(&cl, _t); \
Expand All @@ -485,7 +485,7 @@ do { \
({ \
unsigned long _until = jiffies + _timeout; \
(_cond) \
? max(1, _until - jiffies) \
? max_t(long, 1L, _until - jiffies) \
: __closure_wait_event_timeout(waitlist, _cond, _until);\
})

Expand Down
15 changes: 9 additions & 6 deletions libbcachefs/btree_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1224,17 +1224,20 @@ int bch2_gc_gens(struct bch_fs *c)
u64 b, start_time = local_clock();
int ret;

/*
* Ideally we would be using state_lock and not gc_gens_lock here, but that
* introduces a deadlock in the RO path - we currently take the state
* lock at the start of going RO, thus the gc thread may get stuck:
*/
if (!mutex_trylock(&c->gc_gens_lock))
return 0;

trace_and_count(c, gc_gens_start, c);

down_read(&c->state_lock);
/*
* We have to use trylock here. Otherwise, we would
* introduce a deadlock in the RO path - we take the
* state lock at the start of going RO.
*/
if (!down_read_trylock(&c->state_lock)) {
mutex_unlock(&c->gc_gens_lock);
return 0;
}

for_each_member_device(c, ca) {
struct bucket_gens *gens = bucket_gens(ca);
Expand Down
5 changes: 3 additions & 2 deletions libbcachefs/btree_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1838,10 +1838,11 @@ static void btree_node_write_done(struct bch_fs *c, struct btree *b)
struct btree_trans *trans = bch2_trans_get(c);

btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
__btree_node_write_done(c, b);
six_unlock_read(&b->c.lock);

/* we don't need transaction context anymore after we got the lock. */
bch2_trans_put(trans);
__btree_node_write_done(c, b);
six_unlock_read(&b->c.lock);
}

static void btree_node_write_work(struct work_struct *work)
Expand Down
2 changes: 1 addition & 1 deletion libbcachefs/btree_update.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ int __bch2_insert_snapshot_whiteouts(struct btree_trans *trans,
!(ret = bkey_err(old_k)) &&
bkey_eq(old_pos, old_k.k->p)) {
struct bpos whiteout_pos =
SPOS(new_pos.inode, new_pos.offset, old_k.k->p.snapshot);
SPOS(new_pos.inode, new_pos.offset, old_k.k->p.snapshot);;

if (!bch2_snapshot_is_ancestor(c, old_k.k->p.snapshot, old_pos.snapshot) ||
snapshot_list_has_ancestor(c, &s, old_k.k->p.snapshot))
Expand Down
149 changes: 114 additions & 35 deletions libbcachefs/disk_accounting.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,16 +242,22 @@ void bch2_accounting_swab(struct bkey_s k)
*p = swab64(*p);
}

static inline void __accounting_to_replicas(struct bch_replicas_entry_v1 *r,
struct disk_accounting_pos acc)
{
unsafe_memcpy(r, &acc.replicas,
replicas_entry_bytes(&acc.replicas),
"variable length struct");
}

static inline bool accounting_to_replicas(struct bch_replicas_entry_v1 *r, struct bpos p)
{
struct disk_accounting_pos acc_k;
bpos_to_disk_accounting_pos(&acc_k, p);

switch (acc_k.type) {
case BCH_DISK_ACCOUNTING_replicas:
unsafe_memcpy(r, &acc_k.replicas,
replicas_entry_bytes(&acc_k.replicas),
"variable length struct");
__accounting_to_replicas(r, acc_k);
return true;
default:
return false;
Expand Down Expand Up @@ -608,6 +614,81 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k)
return ret;
}

static int bch2_disk_accounting_validate_late(struct btree_trans *trans,
struct disk_accounting_pos acc,
u64 *v, unsigned nr)
{
struct bch_fs *c = trans->c;
struct printbuf buf = PRINTBUF;
int ret = 0, invalid_dev = -1;

switch (acc.type) {
case BCH_DISK_ACCOUNTING_replicas: {
struct bch_replicas_padded r;
__accounting_to_replicas(&r.e, acc);

for (unsigned i = 0; i < r.e.nr_devs; i++)
if (r.e.devs[i] != BCH_SB_MEMBER_INVALID &&
!bch2_dev_exists(c, r.e.devs[i])) {
invalid_dev = r.e.devs[i];
goto invalid_device;
}

/*
* All replicas entry checks except for invalid device are done
* in bch2_accounting_validate
*/
BUG_ON(bch2_replicas_entry_validate(&r.e, c, &buf));

if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e),
trans, accounting_replicas_not_marked,
"accounting not marked in superblock replicas\n %s",
(printbuf_reset(&buf),
bch2_accounting_key_to_text(&buf, &acc),
buf.buf))) {
/*
* We're not RW yet and still single threaded, dropping
* and retaking lock is ok:
*/
percpu_up_write(&c->mark_lock);
ret = bch2_mark_replicas(c, &r.e);
if (ret)
goto fsck_err;
percpu_down_write(&c->mark_lock);
}
break;
}

case BCH_DISK_ACCOUNTING_dev_data_type:
if (!bch2_dev_exists(c, acc.dev_data_type.dev)) {
invalid_dev = acc.dev_data_type.dev;
goto invalid_device;
}
break;
}

fsck_err:
printbuf_exit(&buf);
return ret;
invalid_device:
if (fsck_err(trans, accounting_to_invalid_device,
"accounting entry points to invalid device %i\n %s",
invalid_dev,
(printbuf_reset(&buf),
bch2_accounting_key_to_text(&buf, &acc),
buf.buf))) {
for (unsigned i = 0; i < nr; i++)
v[i] = -v[i];

ret = commit_do(trans, NULL, NULL, 0,
bch2_disk_accounting_mod(trans, &acc, v, nr, false)) ?:
-BCH_ERR_remove_disk_accounting_entry;
} else {
ret = -BCH_ERR_remove_disk_accounting_entry;
}
goto fsck_err;
}

/*
* At startup time, initialize the in memory accounting from the btree (and
* journal)
Expand Down Expand Up @@ -666,44 +747,42 @@ int bch2_accounting_read(struct bch_fs *c)
}
keys->gap = keys->nr = dst - keys->data;

percpu_down_read(&c->mark_lock);
for (unsigned i = 0; i < acc->k.nr; i++) {
u64 v[BCH_ACCOUNTING_MAX_COUNTERS];
bch2_accounting_mem_read_counters(acc, i, v, ARRAY_SIZE(v), false);
percpu_down_write(&c->mark_lock);
unsigned i = 0;
while (i < acc->k.nr) {
unsigned idx = inorder_to_eytzinger0(i, acc->k.nr);

if (bch2_is_zero(v, sizeof(v[0]) * acc->k.data[i].nr_counters))
continue;
struct disk_accounting_pos acc_k;
bpos_to_disk_accounting_pos(&acc_k, acc->k.data[idx].pos);

struct bch_replicas_padded r;
if (!accounting_to_replicas(&r.e, acc->k.data[i].pos))
continue;
u64 v[BCH_ACCOUNTING_MAX_COUNTERS];
bch2_accounting_mem_read_counters(acc, idx, v, ARRAY_SIZE(v), false);

/*
* If the replicas entry is invalid it'll get cleaned up by
* check_allocations:
* If the entry counters are zeroed, it should be treated as
* nonexistent - it might point to an invalid device.
*
* Remove it, so that if it's re-added it gets re-marked in the
* superblock:
*/
if (bch2_replicas_entry_validate(&r.e, c, &buf))
ret = bch2_is_zero(v, sizeof(v[0]) * acc->k.data[idx].nr_counters)
? -BCH_ERR_remove_disk_accounting_entry
: bch2_disk_accounting_validate_late(trans, acc_k,
v, acc->k.data[idx].nr_counters);

if (ret == -BCH_ERR_remove_disk_accounting_entry) {
free_percpu(acc->k.data[idx].v[0]);
free_percpu(acc->k.data[idx].v[1]);
darray_remove_item(&acc->k, &acc->k.data[idx]);
eytzinger0_sort(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]),
accounting_pos_cmp, NULL);
ret = 0;
continue;

struct disk_accounting_pos k;
bpos_to_disk_accounting_pos(&k, acc->k.data[i].pos);

if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e),
trans, accounting_replicas_not_marked,
"accounting not marked in superblock replicas\n %s",
(printbuf_reset(&buf),
bch2_accounting_key_to_text(&buf, &k),
buf.buf))) {
/*
* We're not RW yet and still single threaded, dropping
* and retaking lock is ok:
*/
percpu_up_read(&c->mark_lock);
ret = bch2_mark_replicas(c, &r.e);
if (ret)
goto fsck_err;
percpu_down_read(&c->mark_lock);
}

if (ret)
goto fsck_err;
i++;
}

preempt_disable();
Expand Down Expand Up @@ -742,7 +821,7 @@ int bch2_accounting_read(struct bch_fs *c)
}
preempt_enable();
fsck_err:
percpu_up_read(&c->mark_lock);
percpu_up_write(&c->mark_lock);
err:
printbuf_exit(&buf);
bch2_trans_put(trans);
Expand Down
2 changes: 1 addition & 1 deletion libbcachefs/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ int bch2_ec_read_extent(struct btree_trans *trans, struct bch_read_bio *rbio,
bch2_bkey_val_to_text(&msgbuf, c, orig_k);
bch_err_ratelimited(c,
"error doing reconstruct read: %s\n %s", msg, msgbuf.buf);
printbuf_exit(&msgbuf);
printbuf_exit(&msgbuf);;
ret = -BCH_ERR_stripe_reconstruct;
goto out;
}
Expand Down
3 changes: 2 additions & 1 deletion libbcachefs/errcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@
x(BCH_ERR_nopromote, nopromote_no_writes) \
x(BCH_ERR_nopromote, nopromote_enomem) \
x(0, invalid_snapshot_node) \
x(0, option_needs_open_fs)
x(0, option_needs_open_fs) \
x(0, remove_disk_accounting_entry)

enum bch_errcode {
BCH_ERR_START = 2048,
Expand Down
Loading

0 comments on commit a9e1597

Please sign in to comment.