summaryrefslogtreecommitdiff
path: root/libbcachefs/buckets.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/buckets.c')
-rw-r--r--libbcachefs/buckets.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c
index 8481c707..c4183982 100644
--- a/libbcachefs/buckets.c
+++ b/libbcachefs/buckets.c
@@ -499,14 +499,18 @@ void bch2_dev_usage_from_buckets(struct bch_fs *c)
}
}
-static inline void update_replicas(struct bch_fs *c,
- struct bch_fs_usage *fs_usage,
- struct bch_replicas_entry *r,
- s64 sectors)
+static inline int update_replicas(struct bch_fs *c,
+ struct bch_fs_usage *fs_usage,
+ struct bch_replicas_entry *r,
+ s64 sectors)
{
int idx = bch2_replicas_entry_idx(c, r);
- BUG_ON(idx < 0);
+ if (idx < 0)
+ return -1;
+
+ if (!fs_usage)
+ return 0;
switch (r->data_type) {
case BCH_DATA_BTREE:
@@ -520,6 +524,7 @@ static inline void update_replicas(struct bch_fs *c,
break;
}
fs_usage->replicas[idx] += sectors;
+ return 0;
}
static inline void update_cached_sectors(struct bch_fs *c,
@@ -579,23 +584,41 @@ static inline void update_cached_sectors_list(struct btree_trans *trans,
update_replicas_list(trans, &r.e, sectors);
}
-void bch2_replicas_delta_list_apply(struct bch_fs *c,
- struct bch_fs_usage *fs_usage,
- struct replicas_delta_list *r)
+static inline struct replicas_delta *
+replicas_delta_next(struct replicas_delta *d)
+{
+ return (void *) d + replicas_entry_bytes(&d->r) + 8;
+}
+
+int bch2_replicas_delta_list_apply(struct bch_fs *c,
+ struct bch_fs_usage *fs_usage,
+ struct replicas_delta_list *r)
{
struct replicas_delta *d = r->d;
struct replicas_delta *top = (void *) r->d + r->used;
+ unsigned i;
- acc_u64s((u64 *) fs_usage,
- (u64 *) &r->fs_usage, sizeof(*fs_usage) / sizeof(u64));
+ for (d = r->d; d != top; d = replicas_delta_next(d))
+ if (update_replicas(c, fs_usage, &d->r, d->delta)) {
+ top = d;
+ goto unwind;
+ }
- while (d != top) {
- BUG_ON((void *) d > (void *) top);
+ if (!fs_usage)
+ return 0;
- update_replicas(c, fs_usage, &d->r, d->delta);
+ fs_usage->nr_inodes += r->nr_inodes;
- d = (void *) d + replicas_entry_bytes(&d->r) + 8;
+ for (i = 0; i < BCH_REPLICAS_MAX; i++) {
+ fs_usage->reserved += r->persistent_reserved[i];
+ fs_usage->persistent_reserved[i] += r->persistent_reserved[i];
}
+
+ return 0;
+unwind:
+ for (d = r->d; d != top; d = replicas_delta_next(d))
+ update_replicas(c, fs_usage, &d->r, -d->delta);
+ return -1;
}
#define do_mark_fn(fn, c, pos, flags, ...) \
@@ -1451,7 +1474,7 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
if (ret < 0)
return ret;
- if (!ret) {
+ if (!ret && unlikely(!test_bit(BCH_FS_ALLOC_WRITTEN, &c->flags))) {
/*
* During journal replay, and if gc repairs alloc info at
* runtime, the alloc info in the btree might not be up to date
@@ -1739,9 +1762,9 @@ int bch2_trans_mark_key(struct btree_trans *trans, struct bkey_s_c k,
d = replicas_deltas_realloc(trans, 0);
if (!(flags & BCH_BUCKET_MARK_OVERWRITE))
- d->fs_usage.nr_inodes++;
+ d->nr_inodes++;
else
- d->fs_usage.nr_inodes--;
+ d->nr_inodes--;
return 0;
case KEY_TYPE_reservation: {
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
@@ -1750,10 +1773,9 @@ int bch2_trans_mark_key(struct btree_trans *trans, struct bkey_s_c k,
sectors *= replicas;
replicas = clamp_t(unsigned, replicas, 1,
- ARRAY_SIZE(d->fs_usage.persistent_reserved));
+ ARRAY_SIZE(d->persistent_reserved));
- d->fs_usage.reserved += sectors;
- d->fs_usage.persistent_reserved[replicas - 1] += sectors;
+ d->persistent_reserved[replicas - 1] += sectors;
return 0;
}
case KEY_TYPE_reflink_p: