summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/bcachefs.h1
-rw-r--r--fs/bcachefs/data_update.c30
-rw-r--r--fs/bcachefs/disk_accounting.c18
-rw-r--r--fs/bcachefs/ec.c55
-rw-r--r--fs/bcachefs/ec.h9
-rw-r--r--fs/bcachefs/move.c81
-rw-r--r--fs/bcachefs/nocow_locking.c9
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 =