diff options
Diffstat (limited to 'libbcachefs/buckets.c')
-rw-r--r-- | libbcachefs/buckets.c | 108 |
1 files changed, 80 insertions, 28 deletions
diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c index 072d22ae..dae718dc 100644 --- a/libbcachefs/buckets.c +++ b/libbcachefs/buckets.c @@ -143,6 +143,37 @@ void bch2_fs_usage_initialize(struct bch_fs *c) percpu_up_write(&c->mark_lock); } +void bch2_fs_usage_scratch_put(struct bch_fs *c, struct bch_fs_usage *fs_usage) +{ + if (fs_usage == c->usage_scratch) + mutex_unlock(&c->usage_scratch_lock); + else + kfree(fs_usage); +} + +struct bch_fs_usage *bch2_fs_usage_scratch_get(struct bch_fs *c) +{ + struct bch_fs_usage *ret; + unsigned bytes = fs_usage_u64s(c) * sizeof(u64); + + ret = kzalloc(bytes, GFP_NOWAIT); + if (ret) + return ret; + + if (mutex_trylock(&c->usage_scratch_lock)) + goto out_pool; + + ret = kzalloc(bytes, GFP_NOFS); + if (ret) + return ret; + + mutex_lock(&c->usage_scratch_lock); +out_pool: + ret = c->usage_scratch; + memset(ret, 0, bytes); + return ret; +} + struct bch_dev_usage bch2_dev_usage_read(struct bch_fs *c, struct bch_dev *ca) { struct bch_dev_usage ret; @@ -290,8 +321,10 @@ int bch2_fs_usage_apply(struct bch_fs *c, fs_usage->online_reserved -= added; } + preempt_disable(); acc_u64s((u64 *) this_cpu_ptr(c->usage[0]), (u64 *) fs_usage, fs_usage_u64s(c)); + preempt_enable(); return ret; } @@ -549,7 +582,6 @@ static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca, size_t b, enum bch_data_type type, unsigned sectors, bool gc) { - struct bch_fs_usage *fs_usage = this_cpu_ptr(c->usage[gc]); struct bucket *g = __bucket(ca, b, gc); struct bucket_mark old, new; bool overflow; @@ -568,7 +600,8 @@ static int __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca, old.dirty_sectors, sectors); if (c) - bch2_dev_usage_update(c, ca, fs_usage, old, new, gc); + bch2_dev_usage_update(c, ca, this_cpu_ptr(c->usage[gc]), + old, new, gc); return 0; } @@ -897,31 +930,39 @@ static int __bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, unsigned journal_seq, unsigned flags, bool gc) { + int ret = 0; + + preempt_disable(); + if (!fs_usage || gc) fs_usage = this_cpu_ptr(c->usage[gc]); switch (k.k->type) { case KEY_TYPE_alloc: - return bch2_mark_alloc(c, k, inserting, + ret = bch2_mark_alloc(c, k, inserting, fs_usage, journal_seq, flags, gc); + break; case KEY_TYPE_btree_ptr: - return bch2_mark_extent(c, k, inserting + ret = bch2_mark_extent(c, k, inserting ? c->opts.btree_node_size : -c->opts.btree_node_size, BCH_DATA_BTREE, fs_usage, journal_seq, flags, gc); + break; case KEY_TYPE_extent: - return bch2_mark_extent(c, k, sectors, BCH_DATA_USER, + ret = bch2_mark_extent(c, k, sectors, BCH_DATA_USER, fs_usage, journal_seq, flags, gc); + break; case KEY_TYPE_stripe: - return bch2_mark_stripe(c, k, inserting, + ret = bch2_mark_stripe(c, k, inserting, fs_usage, journal_seq, flags, gc); + break; case KEY_TYPE_inode: if (inserting) fs_usage->nr_inodes++; else fs_usage->nr_inodes--; - return 0; + break; case KEY_TYPE_reservation: { unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas; @@ -931,11 +972,13 @@ static int __bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, fs_usage->reserved += sectors; fs_usage->persistent_reserved[replicas - 1] += sectors; - return 0; + break; } - default: - return 0; } + + preempt_enable(); + + return ret; } int bch2_mark_key_locked(struct bch_fs *c, @@ -966,25 +1009,20 @@ int bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, return ret; } -void bch2_mark_update(struct btree_insert *trans, - struct btree_insert_entry *insert) +void bch2_mark_update(struct btree_trans *trans, + struct btree_insert_entry *insert, + struct bch_fs_usage *fs_usage) { struct bch_fs *c = trans->c; struct btree_iter *iter = insert->iter; struct btree *b = iter->l[0].b; struct btree_node_iter node_iter = iter->l[0].iter; - struct bch_fs_usage *fs_usage; struct gc_pos pos = gc_pos_btree_node(b); struct bkey_packed *_k; - u64 disk_res_sectors = trans->disk_res ? trans->disk_res->sectors : 0; - static int warned_disk_usage = 0; if (!btree_node_type_needs_gc(iter->btree_id)) return; - percpu_down_read_preempt_disable(&c->mark_lock); - fs_usage = bch2_fs_usage_get_scratch(c); - if (!(trans->flags & BTREE_INSERT_NOMARK)) bch2_mark_key_locked(c, bkey_i_to_s_c(insert->k), true, bpos_min(insert->k->k.p, b->key.k.p).offset - @@ -1037,16 +1075,32 @@ void bch2_mark_update(struct btree_insert *trans, bch2_btree_node_iter_advance(&node_iter, b); } +} - if (bch2_fs_usage_apply(c, fs_usage, trans->disk_res) && - !warned_disk_usage && - !xchg(&warned_disk_usage, 1)) { - char buf[200]; +void bch2_trans_fs_usage_apply(struct btree_trans *trans, + struct bch_fs_usage *fs_usage) +{ + struct bch_fs *c = trans->c; + struct btree_insert_entry *i; + static int warned_disk_usage = 0; + u64 disk_res_sectors = trans->disk_res ? trans->disk_res->sectors : 0; + char buf[200]; - pr_err("disk usage increased more than %llu sectors reserved", disk_res_sectors); + if (!bch2_fs_usage_apply(c, fs_usage, trans->disk_res) || + warned_disk_usage || + xchg(&warned_disk_usage, 1)) + return; + + pr_err("disk usage increased more than %llu sectors reserved", disk_res_sectors); + + trans_for_each_update_iter(trans, i) { + struct btree_iter *iter = i->iter; + struct btree *b = iter->l[0].b; + struct btree_node_iter node_iter = iter->l[0].iter; + struct bkey_packed *_k; pr_err("while inserting"); - bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(insert->k)); + bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(i->k)); pr_err("%s", buf); pr_err("overlapping with"); @@ -1059,8 +1113,8 @@ void bch2_mark_update(struct btree_insert *trans, k = bkey_disassemble(b, _k, &unpacked); if (btree_node_is_extents(b) - ? bkey_cmp(insert->k->k.p, bkey_start_pos(k.k)) <= 0 - : bkey_cmp(insert->k->k.p, k.k->p)) + ? bkey_cmp(i->k->k.p, bkey_start_pos(k.k)) <= 0 + : bkey_cmp(i->k->k.p, k.k->p)) break; bch2_bkey_val_to_text(&PBUF(buf), c, k); @@ -1069,8 +1123,6 @@ void bch2_mark_update(struct btree_insert *trans, bch2_btree_node_iter_advance(&node_iter, b); } } - - percpu_up_read_preempt_enable(&c->mark_lock); } /* Disk reservations: */ |