summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-05-15 15:47:43 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2019-05-15 17:42:35 -0400
commitf61b91d886c23af61ac26972fb38ad0184675f64 (patch)
tree942453463c7cbaead1557c9e8af45a6092b22d67
parent157b20bcf08ee067c953e1e12f738c1a826d289a (diff)
bcachefs: Don't use a fixed size buffer for fs_usage_deltas
-rw-r--r--fs/bcachefs/btree_iter.c2
-rw-r--r--fs/bcachefs/btree_types.h2
-rw-r--r--fs/bcachefs/btree_update_leaf.c16
-rw-r--r--fs/bcachefs/buckets.c82
-rw-r--r--fs/bcachefs/buckets.h6
-rw-r--r--fs/bcachefs/buckets_types.h5
-rw-r--r--fs/bcachefs/recovery.c7
7 files changed, 69 insertions, 51 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index be3e9a8e43e7..e78c6cadeb96 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1947,6 +1947,7 @@ void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
trans->size = ARRAY_SIZE(trans->iters_onstack);
trans->iters = trans->iters_onstack;
trans->updates = trans->updates_onstack;
+ trans->fs_usage_deltas = NULL;
if (expected_nr_iters > trans->size)
bch2_trans_realloc_iters(trans, expected_nr_iters);
@@ -1959,6 +1960,7 @@ int bch2_trans_exit(struct btree_trans *trans)
{
bch2_trans_unlock(trans);
+ kfree(trans->fs_usage_deltas);
kfree(trans->mem);
if (trans->used_mempool)
mempool_free(trans->iters, &trans->c->btree_iters_pool);
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 945877e3c036..f2641d564e49 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -301,7 +301,7 @@ struct btree_trans {
struct btree_iter iters_onstack[2];
struct btree_insert_entry updates_onstack[6];
- struct replicas_delta_list fs_usage_deltas;
+ struct replicas_delta_list *fs_usage_deltas;
};
#define BTREE_FLAG(flag) \
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index db506053200d..33e785763358 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -543,10 +543,11 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
struct btree_insert_entry *i;
int ret;
- if (likely(!(trans->flags & BTREE_INSERT_NO_CLEAR_REPLICAS))) {
- memset(&trans->fs_usage_deltas.fs_usage, 0,
- sizeof(trans->fs_usage_deltas.fs_usage));
- trans->fs_usage_deltas.top = trans->fs_usage_deltas.d;
+ if (likely(!(trans->flags & BTREE_INSERT_NO_CLEAR_REPLICAS)) &&
+ trans->fs_usage_deltas) {
+ memset(&trans->fs_usage_deltas->fs_usage, 0,
+ sizeof(trans->fs_usage_deltas->fs_usage));
+ trans->fs_usage_deltas->used = 0;
}
trans_for_each_update_iter(trans, i)
@@ -555,8 +556,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
trans_for_each_update_iter(trans, i)
if (update_has_triggers(trans, i) &&
update_triggers_transactional(trans, i)) {
- ret = bch2_trans_mark_update(trans, i,
- &trans->fs_usage_deltas);
+ ret = bch2_trans_mark_update(trans, i);
if (ret == -EINTR)
trace_trans_restart_mark(trans->ip);
if (ret)
@@ -626,9 +626,9 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
!update_triggers_transactional(trans, i))
bch2_mark_update(trans, i, fs_usage, 0);
- if (fs_usage) {
+ if (fs_usage && trans->fs_usage_deltas) {
bch2_replicas_delta_list_apply(c, fs_usage,
- &trans->fs_usage_deltas);
+ trans->fs_usage_deltas);
bch2_trans_fs_usage_apply(trans, fs_usage);
}
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index af358fc16afb..4235d7d5eb4d 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -1251,26 +1251,45 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans,
/* trans_mark: */
-static inline void update_replicas_list(struct replicas_delta_list *d,
+static void replicas_deltas_realloc(struct btree_trans *trans)
+{
+ struct replicas_delta_list *d = trans->fs_usage_deltas;
+ unsigned new_size = d ? d->size * 2 : 128;
+
+ d = krealloc(d, sizeof(*d) + new_size, GFP_NOIO|__GFP_ZERO);
+ BUG_ON(!d);
+
+ d->size = new_size;
+ trans->fs_usage_deltas = d;
+}
+
+static inline void update_replicas_list(struct btree_trans *trans,
struct bch_replicas_entry *r,
s64 sectors)
{
- d->top->delta = sectors;
- memcpy(&d->top->r, r, replicas_entry_bytes(r));
+ struct replicas_delta_list *d = trans->fs_usage_deltas;
+ struct replicas_delta *n;
+ unsigned b = replicas_entry_bytes(r) + 8;
- d->top = (void *) d->top + replicas_entry_bytes(r) + 8;
+ if (!d || d->used + b > d->size) {
+ replicas_deltas_realloc(trans);
+ d = trans->fs_usage_deltas;
+ }
- BUG_ON((void *) d->top > (void *) d->d + sizeof(d->pad));
+ n = (void *) d->d + d->used;
+ n->delta = sectors;
+ memcpy(&n->r, r, replicas_entry_bytes(r));
+ d->used += b;
}
-static inline void update_cached_sectors_list(struct replicas_delta_list *d,
+static inline void update_cached_sectors_list(struct btree_trans *trans,
unsigned dev, s64 sectors)
{
struct bch_replicas_padded r;
bch2_replicas_entry_cached(&r.e, dev);
- update_replicas_list(d, &r.e, sectors);
+ update_replicas_list(trans, &r.e, sectors);
}
void bch2_replicas_delta_list_apply(struct bch_fs *c,
@@ -1278,12 +1297,13 @@ void bch2_replicas_delta_list_apply(struct bch_fs *c,
struct replicas_delta_list *r)
{
struct replicas_delta *d = r->d;
+ struct replicas_delta *top = (void *) r->d + r->used;
acc_u64s((u64 *) fs_usage,
(u64 *) &r->fs_usage, sizeof(*fs_usage) / sizeof(u64));
- while (d != r->top) {
- BUG_ON((void *) d > (void *) r->top);
+ while (d != top) {
+ BUG_ON((void *) d > (void *) top);
update_replicas(c, fs_usage, &d->r, d->delta);
@@ -1352,8 +1372,7 @@ static int trans_update_key(struct btree_trans *trans,
static int bch2_trans_mark_pointer(struct btree_trans *trans,
struct extent_ptr_decoded p,
- s64 sectors, enum bch_data_type data_type,
- struct replicas_delta_list *d)
+ s64 sectors, enum bch_data_type data_type)
{
struct bch_fs *c = trans->c;
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
@@ -1414,8 +1433,7 @@ out:
static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
struct bch_extent_stripe_ptr p,
- s64 sectors, enum bch_data_type data_type,
- struct replicas_delta_list *d)
+ s64 sectors, enum bch_data_type data_type)
{
struct bch_replicas_padded r;
struct btree_insert_entry *insert;
@@ -1460,7 +1478,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
bch2_bkey_to_replicas(&r.e, s.s_c);
- update_replicas_list(d, &r.e, sectors);
+ update_replicas_list(trans, &r.e, sectors);
out:
bch2_trans_iter_put(trans, iter);
return ret;
@@ -1468,8 +1486,7 @@ out:
static int bch2_trans_mark_extent(struct btree_trans *trans,
struct bkey_s_c k,
- s64 sectors, enum bch_data_type data_type,
- struct replicas_delta_list *d)
+ s64 sectors, enum bch_data_type data_type)
{
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const union bch_extent_entry *entry;
@@ -1492,7 +1509,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
: ptr_disk_sectors_delta(p, sectors);
ret = bch2_trans_mark_pointer(trans, p, disk_sectors,
- data_type, d);
+ data_type);
if (ret < 0)
return ret;
@@ -1500,7 +1517,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
if (p.ptr.cached) {
if (disk_sectors && !stale)
- update_cached_sectors_list(d, p.ptr.dev,
+ update_cached_sectors_list(trans, p.ptr.dev,
disk_sectors);
} else if (!p.ec_nr) {
dirty_sectors += disk_sectors;
@@ -1508,7 +1525,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
} else {
for (i = 0; i < p.ec_nr; i++) {
ret = bch2_trans_mark_stripe_ptr(trans, p.ec[i],
- disk_sectors, data_type, d);
+ disk_sectors, data_type);
if (ret)
return ret;
}
@@ -1518,16 +1535,16 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
}
if (dirty_sectors)
- update_replicas_list(d, &r.e, dirty_sectors);
+ update_replicas_list(trans, &r.e, dirty_sectors);
return 0;
}
int bch2_trans_mark_key(struct btree_trans *trans,
struct bkey_s_c k,
- bool inserting, s64 sectors,
- struct replicas_delta_list *d)
+ bool inserting, s64 sectors)
{
+ struct replicas_delta_list *d;
struct bch_fs *c = trans->c;
switch (k.k->type) {
@@ -1535,11 +1552,15 @@ int bch2_trans_mark_key(struct btree_trans *trans,
return bch2_trans_mark_extent(trans, k, inserting
? c->opts.btree_node_size
: -c->opts.btree_node_size,
- BCH_DATA_BTREE, d);
+ BCH_DATA_BTREE);
case KEY_TYPE_extent:
return bch2_trans_mark_extent(trans, k,
- sectors, BCH_DATA_USER, d);
+ sectors, BCH_DATA_USER);
case KEY_TYPE_inode:
+ if (!trans->fs_usage_deltas)
+ replicas_deltas_realloc(trans);
+ d = trans->fs_usage_deltas;
+
if (inserting)
d->fs_usage.nr_inodes++;
else
@@ -1548,6 +1569,10 @@ int bch2_trans_mark_key(struct btree_trans *trans,
case KEY_TYPE_reservation: {
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
+ if (!trans->fs_usage_deltas)
+ replicas_deltas_realloc(trans);
+ d = trans->fs_usage_deltas;
+
sectors *= replicas;
replicas = clamp_t(unsigned, replicas, 1,
ARRAY_SIZE(d->fs_usage.persistent_reserved));
@@ -1562,8 +1587,7 @@ int bch2_trans_mark_key(struct btree_trans *trans,
}
int bch2_trans_mark_update(struct btree_trans *trans,
- struct btree_insert_entry *insert,
- struct replicas_delta_list *d)
+ struct btree_insert_entry *insert)
{
struct btree_iter *iter = insert->iter;
struct btree *b = iter->l[0].b;
@@ -1577,7 +1601,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
ret = bch2_trans_mark_key(trans,
bkey_i_to_s_c(insert->k), true,
bpos_min(insert->k->k.p, b->key.k.p).offset -
- bkey_start_offset(&insert->k->k), d);
+ bkey_start_offset(&insert->k->k));
if (ret)
return ret;
@@ -1612,7 +1636,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
BUG_ON(sectors <= 0);
ret = bch2_trans_mark_key(trans, k, true,
- sectors, d);
+ sectors);
if (ret)
return ret;
@@ -1624,7 +1648,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
BUG_ON(sectors >= 0);
}
- ret = bch2_trans_mark_key(trans, k, false, sectors, d);
+ ret = bch2_trans_mark_key(trans, k, false, sectors);
if (ret)
return ret;
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h
index 43b2b5bf3c31..e31fe3149a2d 100644
--- a/fs/bcachefs/buckets.h
+++ b/fs/bcachefs/buckets.h
@@ -270,11 +270,9 @@ int bch2_mark_update(struct btree_trans *, struct btree_insert_entry *,
void bch2_replicas_delta_list_apply(struct bch_fs *,
struct bch_fs_usage *,
struct replicas_delta_list *);
-int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c,
- bool, s64, struct replicas_delta_list *);
+int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, bool, s64);
int bch2_trans_mark_update(struct btree_trans *,
- struct btree_insert_entry *,
- struct replicas_delta_list *);
+ struct btree_insert_entry *);
void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage *);
/* disk reservations: */
diff --git a/fs/bcachefs/buckets_types.h b/fs/bcachefs/buckets_types.h
index a333b9ec9302..309a5fb61e98 100644
--- a/fs/bcachefs/buckets_types.h
+++ b/fs/bcachefs/buckets_types.h
@@ -100,11 +100,10 @@ struct replicas_delta {
} __packed;
struct replicas_delta_list {
+ unsigned size;
+ unsigned used;
struct bch_fs_usage fs_usage;
-
- struct replicas_delta *top;
struct replicas_delta d[0];
- u8 pad[256];
};
/*
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index afa7e9ee0fd4..5baf002cb156 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -257,13 +257,8 @@ retry:
} while (bkey_cmp(iter->pos, k->k.p) < 0);
if (split_compressed) {
- memset(&trans.fs_usage_deltas.fs_usage, 0,
- sizeof(trans.fs_usage_deltas.fs_usage));
- trans.fs_usage_deltas.top = trans.fs_usage_deltas.d;
-
ret = bch2_trans_mark_key(&trans, bkey_i_to_s_c(k), false,
- -((s64) k->k.size),
- &trans.fs_usage_deltas) ?:
+ -((s64) k->k.size)) ?:
bch2_trans_commit(&trans, &disk_res, NULL,
BTREE_INSERT_ATOMIC|
BTREE_INSERT_NOFAIL|