xref: /linux/fs/bcachefs/disk_accounting_format.h (revision b71817585383d96ddc51ebd126f6253fdb9a8568)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_DISK_ACCOUNTING_FORMAT_H
3 #define _BCACHEFS_DISK_ACCOUNTING_FORMAT_H
4 
5 #include "replicas_format.h"
6 
7 /*
8  * Disk accounting - KEY_TYPE_accounting - on disk format:
9  *
10  * Here, the key has considerably more structure than a typical key (bpos); an
11  * accounting key is 'struct disk_accounting_pos', which is a union of bpos.
12  *
13  * More specifically: a key is just a muliword integer (where word endianness
14  * matches native byte order), so we're treating bpos as an opaque 20 byte
15  * integer and mapping bch_accounting_key to that.
16  *
17  * This is a type-tagged union of all our various subtypes; a disk accounting
18  * key can be device counters, replicas counters, et cetera - it's extensible.
19  *
20  * The value is a list of u64s or s64s; the number of counters is specific to a
21  * given accounting type.
22  *
23  * Unlike with other key types, updates are _deltas_, and the deltas are not
24  * resolved until the update to the underlying btree, done by btree write buffer
25  * flush or journal replay.
26  *
27  * Journal replay in particular requires special handling. The journal tracks a
28  * range of entries which may possibly have not yet been applied to the btree
29  * yet - it does not know definitively whether individual entries are dirty and
30  * still need to be applied.
31  *
32  * To handle this, we use the version field of struct bkey, and give every
33  * accounting update a unique version number - a total ordering in time; the
34  * version number is derived from the key's position in the journal. Then
35  * journal replay can compare the version number of the key from the journal
36  * with the version number of the key in the btree to determine if a key needs
37  * to be replayed.
38  *
39  * For this to work, we must maintain this strict time ordering of updates as
40  * they are flushed to the btree, both via write buffer flush and via journal
41  * replay. This has complications for the write buffer code while journal replay
42  * is still in progress; the write buffer cannot flush any accounting keys to
43  * the btree until journal replay has finished replaying its accounting keys, or
44  * the (newer) version number of the keys from the write buffer will cause
45  * updates from journal replay to be lost.
46  */
47 
48 struct bch_accounting {
49 	struct bch_val		v;
50 	__u64			d[];
51 };
52 
53 #define BCH_ACCOUNTING_MAX_COUNTERS		3
54 
55 #define BCH_DATA_TYPES()		\
56 	x(free,		0)		\
57 	x(sb,		1)		\
58 	x(journal,	2)		\
59 	x(btree,	3)		\
60 	x(user,		4)		\
61 	x(cached,	5)		\
62 	x(parity,	6)		\
63 	x(stripe,	7)		\
64 	x(need_gc_gens,	8)		\
65 	x(need_discard,	9)		\
66 	x(unstriped,	10)
67 
68 enum bch_data_type {
69 #define x(t, n) BCH_DATA_##t,
70 	BCH_DATA_TYPES()
71 #undef x
72 	BCH_DATA_NR
73 };
74 
data_type_is_empty(enum bch_data_type type)75 static inline bool data_type_is_empty(enum bch_data_type type)
76 {
77 	switch (type) {
78 	case BCH_DATA_free:
79 	case BCH_DATA_need_gc_gens:
80 	case BCH_DATA_need_discard:
81 		return true;
82 	default:
83 		return false;
84 	}
85 }
86 
data_type_is_hidden(enum bch_data_type type)87 static inline bool data_type_is_hidden(enum bch_data_type type)
88 {
89 	switch (type) {
90 	case BCH_DATA_sb:
91 	case BCH_DATA_journal:
92 		return true;
93 	default:
94 		return false;
95 	}
96 }
97 
98 #define BCH_DISK_ACCOUNTING_TYPES()		\
99 	x(nr_inodes,		0)		\
100 	x(persistent_reserved,	1)		\
101 	x(replicas,		2)		\
102 	x(dev_data_type,	3)		\
103 	x(compression,		4)		\
104 	x(snapshot,		5)		\
105 	x(btree,		6)		\
106 	x(rebalance_work,	7)		\
107 	x(inum,			8)
108 
109 enum disk_accounting_type {
110 #define x(f, nr)	BCH_DISK_ACCOUNTING_##f	= nr,
111 	BCH_DISK_ACCOUNTING_TYPES()
112 #undef x
113 	BCH_DISK_ACCOUNTING_TYPE_NR,
114 };
115 
116 struct bch_nr_inodes {
117 };
118 
119 struct bch_persistent_reserved {
120 	__u8			nr_replicas;
121 };
122 
123 struct bch_dev_data_type {
124 	__u8			dev;
125 	__u8			data_type;
126 };
127 
128 struct bch_acct_compression {
129 	__u8			type;
130 };
131 
132 struct bch_acct_snapshot {
133 	__u32			id;
134 } __packed;
135 
136 struct bch_acct_btree {
137 	__u32			id;
138 } __packed;
139 
140 struct bch_acct_inum {
141 	__u64			inum;
142 } __packed;
143 
144 struct bch_acct_rebalance_work {
145 };
146 
147 struct disk_accounting_pos {
148 	union {
149 	struct {
150 		__u8				type;
151 		union {
152 		struct bch_nr_inodes		nr_inodes;
153 		struct bch_persistent_reserved	persistent_reserved;
154 		struct bch_replicas_entry_v1	replicas;
155 		struct bch_dev_data_type	dev_data_type;
156 		struct bch_acct_compression	compression;
157 		struct bch_acct_snapshot	snapshot;
158 		struct bch_acct_btree		btree;
159 		struct bch_acct_rebalance_work	rebalance_work;
160 		struct bch_acct_inum		inum;
161 		} __packed;
162 	} __packed;
163 		struct bpos			_pad;
164 	};
165 };
166 
167 #endif /* _BCACHEFS_DISK_ACCOUNTING_FORMAT_H */
168