// SPDX-License-Identifier: GPL-2.0 #include "bcachefs.h" #include "bcachefs_ioctl.h" #include "btree_cache.h" #include "btree_journal_iter.h" #include "btree_update.h" #include "btree_write_buffer.h" #include "buckets.h" #include "compress.h" #include "disk_accounting.h" #include "error.h" #include "journal_io.h" #include "replicas.h" /* * Notes on disk accounting: * * We have two parallel sets of counters to be concerned with, and both must be * kept in sync. * * - Persistent/on disk accounting, stored in the accounting btree and updated * via btree write buffer updates that treat new accounting keys as deltas to * apply to existing values. But reading from a write buffer btree is * expensive, so we also have * * - In memory accounting, where accounting is stored as an array of percpu * counters, indexed by an eytzinger array of disk acounting keys/bpos (which * are the same thing, excepting byte swabbing on big endian). * * Cheap to read, but non persistent. * * Disk accounting updates are generated by transactional triggers; these run as * keys enter and leave the btree, and can compare old and new versions of keys; * the output of these triggers are deltas to the various counters. * * Disk accounting updates are done as btree write buffer updates, where the * counters in the disk accounting key are deltas that will be applied to the * counter in the btree when the key is flushed by the write buffer (or journal * replay). * * To do a disk accounting update: * - initialize a disk_accounting_pos, to specify which counter is being update * - initialize counter deltas, as an array of 1-3 s64s * - call bch2_disk_accounting_mod() * * This queues up the accounting update to be done at transaction commit time. * Underneath, it's a normal btree write buffer update. * * The transaction commit path is responsible for propagating updates to the in * memory counters, with bch2_accounting_mem_mod(). * * The commit path also assigns every disk accounting update a unique version * number, based on the journal sequence number and offset within that journal * buffer; this is used by journal replay to determine which updates have been * done. * * The transaction commit path also ensures that replicas entry accounting * updates are properly marked in the superblock (so that we know whether we can * mount without data being unavailable); it will update the superblock if * bch2_accounting_mem_mod() tells it to. */ static const char * const disk_accounting_type_strs[] = …; static inline void accounting_key_init(struct bkey_i *k, struct disk_accounting_pos *pos, s64 *d, unsigned nr) { … } int bch2_disk_accounting_mod(struct btree_trans *trans, struct disk_accounting_pos *k, s64 *d, unsigned nr, bool gc) { … } int bch2_mod_dev_cached_sectors(struct btree_trans *trans, unsigned dev, s64 sectors, bool gc) { … } int bch2_accounting_invalid(struct bch_fs *c, struct bkey_s_c k, enum bch_validate_flags flags, struct printbuf *err) { … } void bch2_accounting_key_to_text(struct printbuf *out, struct disk_accounting_pos *k) { … } void bch2_accounting_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k) { … } void bch2_accounting_swab(struct bkey_s k) { … } static inline bool accounting_to_replicas(struct bch_replicas_entry_v1 *r, struct bpos p) { … } static int bch2_accounting_update_sb_one(struct bch_fs *c, struct bpos p) { … } /* * Ensure accounting keys being updated are present in the superblock, when * applicable (i.e. replicas updates) */ int bch2_accounting_update_sb(struct btree_trans *trans) { … } static int __bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a) { … } int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a, bool gc) { … } static bool accounting_mem_entry_is_zero(struct accounting_mem_entry *e) { … } void bch2_accounting_mem_gc(struct bch_fs *c) { … } /* * Read out accounting keys for replicas entries, as an array of * bch_replicas_usage entries. * * Note: this may be deprecated/removed at smoe point in the future and replaced * with something more general, it exists to support the ioctl used by the * 'bcachefs fs usage' command. */ int bch2_fs_replicas_usage_read(struct bch_fs *c, darray_char *usage) { … } int bch2_fs_accounting_read(struct bch_fs *c, darray_char *out_buf, unsigned accounting_types_mask) { … } void bch2_fs_accounting_to_text(struct printbuf *out, struct bch_fs *c) { … } static void bch2_accounting_free_counters(struct bch_accounting_mem *acc, bool gc) { … } int bch2_gc_accounting_start(struct bch_fs *c) { … } int bch2_gc_accounting_done(struct bch_fs *c) { … } static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k) { … } /* * At startup time, initialize the in memory accounting from the btree (and * journal) */ int bch2_accounting_read(struct bch_fs *c) { … } int bch2_dev_usage_remove(struct bch_fs *c, unsigned dev) { … } int bch2_dev_usage_init(struct bch_dev *ca, bool gc) { … } void bch2_verify_accounting_clean(struct bch_fs *c) { … } void bch2_accounting_gc_free(struct bch_fs *c) { … } void bch2_fs_accounting_exit(struct bch_fs *c) { … }