diff options
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/data_update.c | 30 | ||||
-rw-r--r-- | fs/bcachefs/disk_accounting.c | 18 | ||||
-rw-r--r-- | fs/bcachefs/ec.c | 55 | ||||
-rw-r--r-- | fs/bcachefs/ec.h | 9 | ||||
-rw-r--r-- | fs/bcachefs/move.c | 81 | ||||
-rw-r--r-- | fs/bcachefs/nocow_locking.c | 9 |
7 files changed, 41 insertions, 162 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 933c5a68eff9..3673290586e2 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -1062,7 +1062,6 @@ struct bch_fs { GENRADIX(struct gc_stripe) gc_stripes; struct hlist_head ec_stripes_new[32]; - struct hlist_head ec_stripes_new_buckets[64]; spinlock_t ec_stripes_new_lock; /* ERASURE CODING */ diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index 02997b061ce5..31afbbe320fb 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -35,7 +35,8 @@ static void bkey_put_dev_refs(struct bch_fs *c, struct bkey_s_c k) struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); bkey_for_each_ptr(ptrs, ptr) - bch2_dev_put(bch2_dev_have_ref(c, ptr->dev)); + if (ptr->dev != BCH_SB_MEMBER_INVALID) + bch2_dev_put(bch2_dev_have_ref(c, ptr->dev)); } static bool bkey_get_dev_refs(struct bch_fs *c, struct bkey_s_c k) @@ -43,7 +44,8 @@ static bool bkey_get_dev_refs(struct bch_fs *c, struct bkey_s_c k) struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); bkey_for_each_ptr(ptrs, ptr) { - if (unlikely(!bch2_dev_tryget(c, ptr->dev))) { + if (ptr->dev != BCH_SB_MEMBER_INVALID && + unlikely(!bch2_dev_tryget(c, ptr->dev))) { bkey_for_each_ptr(ptrs, ptr2) { if (ptr2 == ptr) break; @@ -86,15 +88,18 @@ static void trace_io_move_fail2(struct data_update *m, struct bkey_i *insert, const char *msg) { + if (!trace_io_move_fail_enabled()) + return; + struct bch_fs *c = m->op.c; struct bkey_s_c old = bkey_i_to_s_c(m->k.k); - CLASS(printbuf, buf)(); unsigned rewrites_found = 0; - if (!trace_io_move_fail_enabled()) - return; + CLASS(printbuf, buf)(); + printbuf_indent_add_nextline(&buf, 2); prt_str(&buf, msg); + prt_newline(&buf); if (insert) { const union bch_extent_entry *entry; @@ -117,17 +122,17 @@ static void trace_io_move_fail2(struct data_update *m, bch2_data_update_opts_to_text(&buf, c, &m->op.opts, &m->data_opts); - prt_str(&buf, "\nold: "); + prt_str_indented(&buf, "\nold: "); bch2_bkey_val_to_text(&buf, c, old); - prt_str(&buf, "\nnew: "); + prt_str_indented(&buf, "\nnew: "); bch2_bkey_val_to_text(&buf, c, new); - prt_str(&buf, "\nwrote: "); + prt_str_indented(&buf, "\nwrote: "); bch2_bkey_val_to_text(&buf, c, wrote); if (insert) { - prt_str(&buf, "\ninsert: "); + prt_str_indented(&buf, "\ninsert: "); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(insert)); } @@ -282,7 +287,9 @@ restart_drop_conflicting_replicas: } if (!bkey_val_u64s(&new->k)) { - trace_io_move_fail2(m, k, bkey_i_to_s_c(&new->k_i), insert, "new replicas conflicted:"); + trace_io_move_fail2(m, k, + bkey_i_to_s_c(bch2_keylist_front(&op->insert_keys)), + insert, "new replicas conflicted:"); goto nowork; } @@ -719,7 +726,8 @@ static int can_write_extent(struct bch_fs *c, struct data_update *m) struct bch_devs_mask devs = target_rw_devs(c, BCH_DATA_user, target); darray_for_each(m->op.devs_have, i) - __clear_bit(*i, devs.d); + if (*i != BCH_SB_MEMBER_INVALID) + __clear_bit(*i, devs.d); CLASS(printbuf, buf)(); diff --git a/fs/bcachefs/disk_accounting.c b/fs/bcachefs/disk_accounting.c index ddd7a5427801..73f50e5489b4 100644 --- a/fs/bcachefs/disk_accounting.c +++ b/fs/bcachefs/disk_accounting.c @@ -669,10 +669,11 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k) BCH_ACCOUNTING_read, false); } -static int bch2_disk_accounting_validate_late(struct bch_fs *c, +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; CLASS(printbuf, buf)(); int ret = 0, invalid_dev = -1; @@ -695,7 +696,7 @@ static int bch2_disk_accounting_validate_late(struct bch_fs *c, BUG_ON(bch2_replicas_entry_validate(&r.e, c, &buf)); if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e), - c, accounting_replicas_not_marked, + trans, accounting_replicas_not_marked, "accounting not marked in superblock replicas\n%s", (printbuf_reset(&buf), bch2_accounting_key_to_text(&buf, acc), @@ -724,7 +725,7 @@ static int bch2_disk_accounting_validate_late(struct bch_fs *c, fsck_err: return ret; invalid_device: - if (fsck_err(c, accounting_to_invalid_device, + if (fsck_err(trans, accounting_to_invalid_device, "accounting entry points to invalid device %i\n%s", invalid_dev, (printbuf_reset(&buf), @@ -733,7 +734,7 @@ invalid_device: for (unsigned i = 0; i < nr; i++) v[i] = -v[i]; - ret = bch2_trans_commit_do(c, NULL, NULL, 0, + ret = commit_do(trans, NULL, NULL, 0, bch2_disk_accounting_mod(trans, acc, v, nr, false)) ?: -BCH_ERR_remove_disk_accounting_entry; } else { @@ -788,8 +789,9 @@ static struct journal_key *accumulate_and_read_journal_accounting(struct btree_t return ret ? ERR_PTR(ret) : next; } -static int accounting_read_mem_fixups(struct bch_fs *c) +static int accounting_read_mem_fixups(struct btree_trans *trans) { + struct bch_fs *c = trans->c; struct bch_accounting_mem *acc = &c->accounting; CLASS(printbuf, underflow_err)(); @@ -813,7 +815,7 @@ static int accounting_read_mem_fixups(struct bch_fs *c) */ int ret = bch2_is_zero(v, sizeof(v[0]) * i->nr_counters) ? -BCH_ERR_remove_disk_accounting_entry - : bch2_disk_accounting_validate_late(c, &acc_k, v, i->nr_counters); + : bch2_disk_accounting_validate_late(trans, &acc_k, v, i->nr_counters); if (ret == -BCH_ERR_remove_disk_accounting_entry) { free_percpu(i->v[0]); @@ -996,13 +998,15 @@ int bch2_accounting_read(struct bch_fs *c) while (jk < end) jk = accumulate_and_read_journal_accounting(trans, jk); + bch2_trans_unlock(trans); + struct journal_key *dst = keys->data; darray_for_each(*keys, i) if (!i->overwritten) *dst++ = *i; keys->gap = keys->nr = dst - keys->data; - return accounting_read_mem_fixups(c); + return accounting_read_mem_fixups(trans); } int bch2_dev_usage_remove(struct bch_fs *c, struct bch_dev *ca) diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 78afd44a7a3f..103719a76c81 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -895,60 +895,8 @@ static int ec_stripe_mem_alloc(struct btree_trans *trans, * Hash table of open stripes: * Stripes that are being created or modified are kept in a hash table, so that * stripe deletion can skip them. - * - * Additionally, we have a hash table for buckets that have stripes being - * created, to avoid racing with rebalance: */ -static bool __bch2_bucket_has_new_stripe(struct bch_fs *c, u64 dev_bucket) -{ - unsigned hash = hash_64(dev_bucket, ilog2(ARRAY_SIZE(c->ec_stripes_new_buckets))); - struct ec_stripe_new_bucket *s; - - hlist_for_each_entry(s, &c->ec_stripes_new_buckets[hash], hash) - if (s->dev_bucket == dev_bucket) - return true; - return false; -} - -bool bch2_bucket_has_new_stripe(struct bch_fs *c, u64 dev_bucket) -{ - guard(spinlock)(&c->ec_stripes_new_lock); - return __bch2_bucket_has_new_stripe(c, dev_bucket); -} - -static void stripe_new_bucket_add(struct bch_fs *c, struct ec_stripe_new_bucket *s, u64 dev_bucket) -{ - s->dev_bucket = dev_bucket; - - unsigned hash = hash_64(dev_bucket, ilog2(ARRAY_SIZE(c->ec_stripes_new_buckets))); - hlist_add_head(&s->hash, &c->ec_stripes_new_buckets[hash]); -} - -static void stripe_new_buckets_add(struct bch_fs *c, struct ec_stripe_new *s) -{ - unsigned nr_blocks = s->nr_data + s->nr_parity; - - guard(spinlock)(&c->ec_stripes_new_lock); - for (unsigned i = 0; i < nr_blocks; i++) { - if (!s->blocks[i]) - continue; - - struct open_bucket *ob = c->open_buckets + s->blocks[i]; - struct bpos bucket = POS(ob->dev, ob->bucket); - - stripe_new_bucket_add(c, &s->buckets[i], bucket_to_u64(bucket)); - } -} - -static void stripe_new_buckets_del(struct bch_fs *c, struct ec_stripe_new *s) -{ - struct bch_stripe *v = &bkey_i_to_stripe(&s->new_stripe.key)->v; - - for (unsigned i = 0; i < v->nr_blocks; i++) - hlist_del_init(&s->buckets[i].hash); -} - static bool __bch2_stripe_is_open(struct bch_fs *c, u64 idx) { unsigned hash = hash_64(idx, ilog2(ARRAY_SIZE(c->ec_stripes_new))); @@ -989,8 +937,6 @@ static void bch2_stripe_close(struct bch_fs *c, struct ec_stripe_new *s) hlist_del_init(&s->hash); s->idx = 0; - - stripe_new_buckets_del(c, s); } /* stripe deletion */ @@ -2081,7 +2027,6 @@ allocate_buf: if (ret) goto err; - stripe_new_buckets_add(c, s); s->allocated = true; allocated: BUG_ON(!s->idx); diff --git a/fs/bcachefs/ec.h b/fs/bcachefs/ec.h index 85598448c7e1..cc778da99030 100644 --- a/fs/bcachefs/ec.h +++ b/fs/bcachefs/ec.h @@ -191,11 +191,6 @@ enum ec_stripe_ref { STRIPE_REF_NR }; -struct ec_stripe_new_bucket { - struct hlist_node hash; - u64 dev_bucket; -}; - struct ec_stripe_new { struct bch_fs *c; struct ec_stripe_head *h; @@ -222,8 +217,6 @@ struct ec_stripe_new { open_bucket_idx_t blocks[BCH_BKEY_PTRS_MAX]; struct disk_reservation res; - struct ec_stripe_new_bucket buckets[BCH_BKEY_PTRS_MAX]; - struct ec_stripe_buf new_stripe; struct ec_stripe_buf existing_stripe; }; @@ -255,8 +248,6 @@ struct ec_stripe_head { int bch2_ec_read_extent(struct btree_trans *, struct bch_read_bio *, struct bkey_s_c); -bool bch2_bucket_has_new_stripe(struct bch_fs *, u64); - void *bch2_writepoint_ec_buf(struct bch_fs *, struct write_point *); void bch2_ec_bucket_cancel(struct bch_fs *, struct open_bucket *, int); diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index 63c8f57b444e..6612564e044e 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -959,37 +959,6 @@ next: return ret; } -static bool rereplicate_pred(struct bch_fs *c, void *arg, - enum btree_id btree, struct bkey_s_c k, - struct bch_inode_opts *io_opts, - struct data_update_opts *data_opts) -{ - unsigned nr_good = bch2_bkey_durability(c, k); - unsigned replicas = bkey_is_btree_ptr(k.k) - ? c->opts.metadata_replicas - : io_opts->data_replicas; - - guard(rcu)(); - struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); - unsigned i = 0; - bkey_for_each_ptr(ptrs, ptr) { - struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev); - if (!ptr->cached && - (!ca || !ca->mi.durability)) - data_opts->kill_ptrs |= BIT(i); - i++; - } - - if (!data_opts->kill_ptrs && - (!nr_good || nr_good >= replicas)) - return false; - - data_opts->target = 0; - data_opts->extra_replicas = replicas - nr_good; - data_opts->btree_insert_flags = 0; - return true; -} - static bool migrate_pred(struct bch_fs *c, void *arg, enum btree_id btree, struct bkey_s_c k, struct bch_inode_opts *io_opts, @@ -1064,44 +1033,6 @@ int bch2_scan_old_btree_nodes(struct bch_fs *c, struct bch_move_stats *stats) return ret; } -static bool drop_extra_replicas_pred(struct bch_fs *c, void *arg, - enum btree_id btree, struct bkey_s_c k, - struct bch_inode_opts *io_opts, - struct data_update_opts *data_opts) -{ - unsigned durability = bch2_bkey_durability(c, k); - unsigned replicas = bkey_is_btree_ptr(k.k) - ? c->opts.metadata_replicas - : io_opts->data_replicas; - const union bch_extent_entry *entry; - struct extent_ptr_decoded p; - unsigned i = 0; - - guard(rcu)(); - bkey_for_each_ptr_decode(k.k, bch2_bkey_ptrs_c(k), p, entry) { - unsigned d = bch2_extent_ptr_durability(c, &p); - - if (d && durability - d >= replicas) { - data_opts->kill_ptrs |= BIT(i); - durability -= d; - } - - i++; - } - - i = 0; - bkey_for_each_ptr_decode(k.k, bch2_bkey_ptrs_c(k), p, entry) { - if (p.has_ec && durability - p.ec.redundancy >= replicas) { - data_opts->kill_ec_ptrs |= BIT(i); - durability -= p.ec.redundancy; - } - - i++; - } - - return (data_opts->kill_ptrs|data_opts->kill_ec_ptrs) != 0; -} - static bool scrub_pred(struct bch_fs *c, void *_arg, enum btree_id btree, struct bkey_s_c k, struct bch_inode_opts *io_opts, @@ -1130,8 +1061,6 @@ int bch2_data_job(struct bch_fs *c, struct bch_move_stats *stats, struct bch_ioctl_data *op) { - struct bbpos start = BBPOS(op->start_btree, op->start_pos); - struct bbpos end = BBPOS(op->end_btree, op->end_pos); int ret = 0; if (op->op >= BCH_DATA_OP_NR) @@ -1159,11 +1088,8 @@ int bch2_data_job(struct bch_fs *c, case BCH_DATA_OP_rereplicate: stats->data_type = BCH_DATA_journal; ret = bch2_journal_flush_device_pins(&c->journal, -1); - ret = bch2_move_data(c, start, end, 0, NULL, stats, - writepoint_hashed((unsigned long) current), - true, - rereplicate_pred, c) ?: ret; bch2_btree_interior_updates_flush(c); + /* XXX: how do we make this happen automatically? */ ret = bch2_replicas_gc2(c) ?: ret; break; case BCH_DATA_OP_migrate: @@ -1186,10 +1112,7 @@ int bch2_data_job(struct bch_fs *c, ret = bch2_scan_old_btree_nodes(c, stats); break; case BCH_DATA_OP_drop_extra_replicas: - ret = bch2_move_data(c, start, end, 0, NULL, stats, - writepoint_hashed((unsigned long) current), - true, - drop_extra_replicas_pred, c) ?: ret; + /* XXX: how do we make this happen automatically? */ ret = bch2_replicas_gc2(c) ?: ret; break; default: diff --git a/fs/bcachefs/nocow_locking.c b/fs/bcachefs/nocow_locking.c index c8907070796f..73e1429979c2 100644 --- a/fs/bcachefs/nocow_locking.c +++ b/fs/bcachefs/nocow_locking.c @@ -95,6 +95,9 @@ void bch2_bkey_nocow_unlock(struct bch_fs *c, struct bkey_s_c k, int flags) struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); bkey_for_each_ptr(ptrs, ptr) { + if (ptr->dev == BCH_SB_MEMBER_INVALID) + continue; + struct bch_dev *ca = bch2_dev_have_ref(c, ptr->dev); struct bpos bucket = PTR_BUCKET_POS(ca, ptr); @@ -105,6 +108,9 @@ void bch2_bkey_nocow_unlock(struct bch_fs *c, struct bkey_s_c k, int flags) bool bch2_bkey_nocow_trylock(struct bch_fs *c, struct bkey_ptrs_c ptrs, int flags) { bkey_for_each_ptr(ptrs, ptr) { + if (ptr->dev == BCH_SB_MEMBER_INVALID) + continue; + struct bch_dev *ca = bch2_dev_have_ref(c, ptr->dev); struct bpos bucket = PTR_BUCKET_POS(ca, ptr); @@ -144,6 +150,9 @@ void bch2_bkey_nocow_lock(struct bch_fs *c, struct bkey_ptrs_c ptrs, int flags) darray_init(&buckets); bkey_for_each_ptr(ptrs, ptr) { + if (ptr->dev == BCH_SB_MEMBER_INVALID) + continue; + struct bch_dev *ca = bch2_dev_have_ref(c, ptr->dev); u64 b = bucket_to_u64(PTR_BUCKET_POS(ca, ptr)); struct nocow_lock_bucket *l = |