diff options
-rw-r--r-- | fs/bcachefs/btree_gc.c | 39 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 37 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 139 | ||||
-rw-r--r-- | fs/bcachefs/buckets.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 5 |
5 files changed, 132 insertions, 93 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index c9a013f43374..0fb89e03fac8 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -212,34 +212,31 @@ static int bch2_gc_mark_key(struct bch_fs *c, enum bkey_type type, struct bkey_s_c k, bool initial) { struct gc_pos pos = { 0 }; - unsigned flags = initial ? BCH_BUCKET_MARK_NOATOMIC : 0; + unsigned flags = + BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE| + BCH_BUCKET_MARK_GC_LOCK_HELD| + (initial ? BCH_BUCKET_MARK_NOATOMIC : 0); int ret = 0; switch (type) { case BKEY_TYPE_BTREE: - if (initial) { - ret = bch2_btree_mark_ptrs_initial(c, type, k); - if (ret < 0) - return ret; - } - - bch2_mark_key(c, k, c->opts.btree_node_size, - BCH_DATA_BTREE, pos, NULL, - 0, flags| - BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE| - BCH_BUCKET_MARK_GC_LOCK_HELD); - break; case BKEY_TYPE_EXTENTS: if (initial) { ret = bch2_btree_mark_ptrs_initial(c, type, k); if (ret < 0) return ret; } + break; + default: + break; + } + + bch2_mark_key(c, type, k, true, k.k->size, + pos, NULL, 0, flags); - bch2_mark_key(c, k, k.k->size, BCH_DATA_USER, pos, NULL, - 0, flags| - BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE| - BCH_BUCKET_MARK_GC_LOCK_HELD); + switch (type) { + case BKEY_TYPE_BTREE: + case BKEY_TYPE_EXTENTS: ret = bch2_btree_key_recalc_oldest_gen(c, k); break; default: @@ -473,10 +470,10 @@ static void bch2_mark_pending_btree_node_frees(struct bch_fs *c) for_each_pending_btree_node_free(c, as, d) if (d->index_update_done) - bch2_mark_key(c, bkey_i_to_s_c(&d->key), - c->opts.btree_node_size, - BCH_DATA_BTREE, pos, - &stats, 0, + bch2_mark_key(c, BKEY_TYPE_BTREE, + bkey_i_to_s_c(&d->key), + true, 0, + pos, &stats, 0, BCH_BUCKET_MARK_MAY_MAKE_UNAVAILABLE| BCH_BUCKET_MARK_GC_LOCK_HELD); /* diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index c9facec494ef..4ec448718fd8 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -211,11 +211,12 @@ found: if (gc_pos_cmp(c->gc_pos, gc_phase(GC_PHASE_PENDING_DELETE)) < 0) { struct bch_fs_usage tmp = { 0 }; - bch2_mark_key(c, bkey_i_to_s_c(&d->key), - -c->opts.btree_node_size, BCH_DATA_BTREE, b - ? gc_pos_btree_node(b) - : gc_pos_btree_root(as->btree_id), - &tmp, 0, 0); + bch2_mark_key(c, BKEY_TYPE_BTREE, + bkey_i_to_s_c(&d->key), + false, 0, b + ? gc_pos_btree_node(b) + : gc_pos_btree_root(as->btree_id), + &tmp, 0, 0); /* * Don't apply tmp - pending deletes aren't tracked in * bch_alloc_stats: @@ -290,10 +291,11 @@ static void bch2_btree_node_free_ondisk(struct bch_fs *c, BUG_ON(!pending->index_update_done); - bch2_mark_key(c, bkey_i_to_s_c(&pending->key), - -c->opts.btree_node_size, BCH_DATA_BTREE, - gc_phase(GC_PHASE_PENDING_DELETE), - &stats, 0, 0); + bch2_mark_key(c, BKEY_TYPE_BTREE, + bkey_i_to_s_c(&pending->key), + false, 0, + gc_phase(GC_PHASE_PENDING_DELETE), + &stats, 0, 0); /* * Don't apply stats - pending deletes aren't tracked in * bch_alloc_stats: @@ -1092,8 +1094,9 @@ static void bch2_btree_set_root_inmem(struct btree_update *as, struct btree *b) __bch2_btree_set_root_inmem(c, b); - bch2_mark_key(c, bkey_i_to_s_c(&b->key), - c->opts.btree_node_size, BCH_DATA_BTREE, + bch2_mark_key(c, BKEY_TYPE_BTREE, + bkey_i_to_s_c(&b->key), + true, 0, gc_pos_btree_root(b->btree_id), &stats, 0, 0); @@ -1180,9 +1183,10 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, struct btree *b BUG_ON(insert->k.u64s > bch_btree_keys_u64s_remaining(c, b)); if (bkey_extent_is_data(&insert->k)) - bch2_mark_key(c, bkey_i_to_s_c(insert), - c->opts.btree_node_size, BCH_DATA_BTREE, - gc_pos_btree_node(b), &stats, 0, 0); + bch2_mark_key(c, BKEY_TYPE_BTREE, + bkey_i_to_s_c(insert), + true, 0, + gc_pos_btree_node(b), &stats, 0, 0); while ((k = bch2_btree_node_iter_peek_all(node_iter, b)) && bkey_iter_pos_cmp(b, &insert->k.p, k) > 0) @@ -1967,8 +1971,9 @@ static void __bch2_btree_node_update_key(struct bch_fs *c, bch2_btree_node_lock_write(b, iter); - bch2_mark_key(c, bkey_i_to_s_c(&new_key->k_i), - c->opts.btree_node_size, BCH_DATA_BTREE, + bch2_mark_key(c, BKEY_TYPE_BTREE, + bkey_i_to_s_c(&new_key->k_i), + true, 0, gc_pos_btree_root(b->btree_id), &stats, 0, 0); bch2_btree_node_free_index(as, NULL, diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 84972b67f193..6f40c4bd16ec 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -539,24 +539,10 @@ static int __disk_sectors(struct bch_extent_crc_unpacked crc, unsigned sectors) crc.uncompressed_size)); } -/* - * Checking against gc's position has to be done here, inside the cmpxchg() - * loop, to avoid racing with the start of gc clearing all the marks - GC does - * that with the gc pos seqlock held. - */ -static void bch2_mark_pointer(struct bch_fs *c, - struct bkey_s_c_extent e, - struct extent_ptr_decoded p, - s64 sectors, enum bch_data_type data_type, - unsigned replicas, - struct bch_fs_usage *fs_usage, - u64 journal_seq, unsigned flags) +static s64 ptr_disk_sectors(struct bkey_s_c_extent e, + struct extent_ptr_decoded p, + s64 sectors) { - struct bucket_mark old, new; - struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); - struct bucket *g = PTR_BUCKET(ca, &p.ptr); - s64 uncompressed_sectors = sectors; - u64 v; if (p.crc.compression_type) { unsigned old_sectors, new_sectors; @@ -573,19 +559,25 @@ static void bch2_mark_pointer(struct bch_fs *c, +__disk_sectors(p.crc, new_sectors); } - /* - * fs level usage (which determines free space) is in uncompressed - * sectors, until copygc + compression is sorted out: - * - * note also that we always update @fs_usage, even when we otherwise - * wouldn't do anything because gc is running - this is because the - * caller still needs to account w.r.t. its disk reservation. It is - * caller's responsibility to not apply @fs_usage if gc is in progress. - */ - fs_usage->replicas - [!p.ptr.cached && replicas ? replicas - 1 : 0].data - [!p.ptr.cached ? data_type : BCH_DATA_CACHED] += - uncompressed_sectors; + return sectors; +} + +/* + * Checking against gc's position has to be done here, inside the cmpxchg() + * loop, to avoid racing with the start of gc clearing all the marks - GC does + * that with the gc pos seqlock held. + */ +static void bch2_mark_pointer(struct bch_fs *c, + struct bkey_s_c_extent e, + struct extent_ptr_decoded p, + s64 sectors, enum bch_data_type data_type, + struct bch_fs_usage *fs_usage, + u64 journal_seq, unsigned flags) +{ + struct bucket_mark old, new; + struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); + struct bucket *g = PTR_BUCKET(ca, &p.ptr); + u64 v; if (flags & BCH_BUCKET_MARK_GC_WILL_VISIT) { if (journal_seq) @@ -644,16 +636,64 @@ static void bch2_mark_pointer(struct bch_fs *c, bucket_became_unavailable(c, old, new)); } -void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, - s64 sectors, enum bch_data_type data_type, - struct gc_pos pos, - struct bch_fs_usage *stats, - u64 journal_seq, unsigned flags) +static void bch2_mark_extent(struct bch_fs *c, struct bkey_s_c k, + s64 sectors, enum bch_data_type data_type, + struct gc_pos pos, + struct bch_fs_usage *stats, + u64 journal_seq, unsigned flags) { unsigned replicas = bch2_extent_nr_dirty_ptrs(k); BUG_ON(replicas && replicas - 1 > ARRAY_SIZE(stats->replicas)); + BUG_ON(!sectors); + + switch (k.k->type) { + case BCH_EXTENT: + case BCH_EXTENT_CACHED: { + struct bkey_s_c_extent e = bkey_s_c_to_extent(k); + const union bch_extent_entry *entry; + struct extent_ptr_decoded p; + + extent_for_each_ptr_decode(e, p, entry) { + s64 disk_sectors = ptr_disk_sectors(e, p, sectors); + + /* + * fs level usage (which determines free space) is in + * uncompressed sectors, until copygc + compression is + * sorted out: + * + * note also that we always update @fs_usage, even when + * we otherwise wouldn't do anything because gc is + * running - this is because the caller still needs to + * account w.r.t. its disk reservation. It is caller's + * responsibility to not apply @fs_usage if gc is in + * progress. + */ + stats->replicas + [!p.ptr.cached && replicas ? replicas - 1 : 0].data + [!p.ptr.cached ? data_type : BCH_DATA_CACHED] += + sectors; + + bch2_mark_pointer(c, e, p, disk_sectors, data_type, + stats, journal_seq, flags); + } + break; + } + case BCH_RESERVATION: + if (replicas) + stats->replicas[replicas - 1].persistent_reserved += + sectors * replicas; + break; + } +} +void bch2_mark_key(struct bch_fs *c, + enum bkey_type type, struct bkey_s_c k, + bool inserting, s64 sectors, + struct gc_pos pos, + struct bch_fs_usage *stats, + u64 journal_seq, unsigned flags) +{ /* * synchronization w.r.t. GC: * @@ -690,24 +730,19 @@ void bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, if (!stats) stats = this_cpu_ptr(c->usage_percpu); - switch (k.k->type) { - case BCH_EXTENT: - case BCH_EXTENT_CACHED: { - struct bkey_s_c_extent e = bkey_s_c_to_extent(k); - const union bch_extent_entry *entry; - struct extent_ptr_decoded p; - - BUG_ON(!sectors); - - extent_for_each_ptr_decode(e, p, entry) - bch2_mark_pointer(c, e, p, sectors, data_type, - replicas, stats, journal_seq, flags); + switch (type) { + case BKEY_TYPE_BTREE: + bch2_mark_extent(c, k, inserting + ? c->opts.btree_node_size + : -c->opts.btree_node_size, + BCH_DATA_BTREE, + pos, stats, journal_seq, flags); break; - } - case BCH_RESERVATION: - if (replicas) - stats->replicas[replicas - 1].persistent_reserved += - sectors * replicas; + case BKEY_TYPE_EXTENTS: + bch2_mark_extent(c, k, sectors, BCH_DATA_USER, + pos, stats, journal_seq, flags); + break; + default: break; } percpu_up_read(&c->usage_lock); diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h index 9aeccbb11d54..e22c51972c31 100644 --- a/fs/bcachefs/buckets.h +++ b/fs/bcachefs/buckets.h @@ -204,8 +204,9 @@ void bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *, #define BCH_BUCKET_MARK_GC_WILL_VISIT (1 << 2) #define BCH_BUCKET_MARK_GC_LOCK_HELD (1 << 3) -void bch2_mark_key(struct bch_fs *, struct bkey_s_c, s64, enum bch_data_type, - struct gc_pos, struct bch_fs_usage *, u64, unsigned); +void bch2_mark_key(struct bch_fs *, enum bkey_type, struct bkey_s_c, + bool, s64, struct gc_pos, + struct bch_fs_usage *, u64, unsigned); void bch2_recalc_sectors_available(struct bch_fs *); diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 4e4918524a77..4a1ec3bba91b 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -1009,8 +1009,9 @@ static void bch2_add_sectors(struct extent_insert_state *s, if (!sectors) return; - bch2_mark_key(c, k, sectors, BCH_DATA_USER, gc_pos_btree_node(b), - &s->stats, s->trans->journal_res.seq, 0); + bch2_mark_key(c, BKEY_TYPE_EXTENTS, k, sectors > 0, sectors, + gc_pos_btree_node(b), &s->stats, + s->trans->journal_res.seq, 0); } static void bch2_subtract_sectors(struct extent_insert_state *s, |