]> git.ipfire.org Git - thirdparty/linux.git/blame - fs/bcachefs/sb-members.c
bcachefs: Add new helper to retrieve bch_member from sb
[thirdparty/linux.git] / fs / bcachefs / sb-members.c
CommitLineData
fb8e5b4c
KO
1// SPDX-License-Identifier: GPL-2.0
2
3#include "bcachefs.h"
4#include "disk_groups.h"
5#include "replicas.h"
6#include "sb-members.h"
7#include "super-io.h"
8
9/* Code for bch_sb_field_members: */
1241df58
HS
10static struct bch_member *members_v1_get_mut(struct bch_sb_field_members *mi, int i)
11{
12 return mi->members + i;
13}
14
15static struct bch_member members_v1_get(struct bch_sb_field_members *mi, int i)
16{
17 struct bch_member ret, *p = members_v1_get_mut(mi, i);
18 memset(&ret, 0, sizeof(ret));
19 memcpy(&ret, p, min_t(size_t, sizeof(struct bch_member), sizeof(ret))); return ret;
20}
21
22struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i)
23{
24 struct bch_sb_field_members *mi1 = bch2_sb_get_members(sb);
25 return members_v1_get(mi1, i);
26}
fb8e5b4c
KO
27
28static int bch2_sb_members_validate(struct bch_sb *sb,
29 struct bch_sb_field *f,
30 struct printbuf *err)
31{
32 struct bch_sb_field_members *mi = field_to_type(f, members);
33 unsigned i;
34
35 if ((void *) (mi->members + sb->nr_devices) >
36 vstruct_end(&mi->field)) {
37 prt_printf(err, "too many devices for section size");
38 return -BCH_ERR_invalid_sb_members;
39 }
40
41 for (i = 0; i < sb->nr_devices; i++) {
42 struct bch_member *m = mi->members + i;
43
44 if (!bch2_member_exists(m))
45 continue;
46
47 if (le64_to_cpu(m->nbuckets) > LONG_MAX) {
48 prt_printf(err, "device %u: too many buckets (got %llu, max %lu)",
49 i, le64_to_cpu(m->nbuckets), LONG_MAX);
50 return -BCH_ERR_invalid_sb_members;
51 }
52
53 if (le64_to_cpu(m->nbuckets) -
54 le16_to_cpu(m->first_bucket) < BCH_MIN_NR_NBUCKETS) {
55 prt_printf(err, "device %u: not enough buckets (got %llu, max %u)",
56 i, le64_to_cpu(m->nbuckets), BCH_MIN_NR_NBUCKETS);
57 return -BCH_ERR_invalid_sb_members;
58 }
59
60 if (le16_to_cpu(m->bucket_size) <
61 le16_to_cpu(sb->block_size)) {
62 prt_printf(err, "device %u: bucket size %u smaller than block size %u",
63 i, le16_to_cpu(m->bucket_size), le16_to_cpu(sb->block_size));
64 return -BCH_ERR_invalid_sb_members;
65 }
66
67 if (le16_to_cpu(m->bucket_size) <
68 BCH_SB_BTREE_NODE_SIZE(sb)) {
69 prt_printf(err, "device %u: bucket size %u smaller than btree node size %llu",
70 i, le16_to_cpu(m->bucket_size), BCH_SB_BTREE_NODE_SIZE(sb));
71 return -BCH_ERR_invalid_sb_members;
72 }
73 }
74
75 return 0;
76}
77
78static void bch2_sb_members_to_text(struct printbuf *out, struct bch_sb *sb,
79 struct bch_sb_field *f)
80{
81 struct bch_sb_field_members *mi = field_to_type(f, members);
82 struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb);
83 unsigned i;
84
85 for (i = 0; i < sb->nr_devices; i++) {
86 struct bch_member *m = mi->members + i;
87 unsigned data_have = bch2_sb_dev_has_data(sb, i);
88 u64 bucket_size = le16_to_cpu(m->bucket_size);
89 u64 device_size = le64_to_cpu(m->nbuckets) * bucket_size;
90
91 if (!bch2_member_exists(m))
92 continue;
93
94 prt_printf(out, "Device:");
95 prt_tab(out);
96 prt_printf(out, "%u", i);
97 prt_newline(out);
98
99 printbuf_indent_add(out, 2);
100
101 prt_printf(out, "UUID:");
102 prt_tab(out);
103 pr_uuid(out, m->uuid.b);
104 prt_newline(out);
105
106 prt_printf(out, "Size:");
107 prt_tab(out);
108 prt_units_u64(out, device_size << 9);
109 prt_newline(out);
110
111 prt_printf(out, "Bucket size:");
112 prt_tab(out);
113 prt_units_u64(out, bucket_size << 9);
114 prt_newline(out);
115
116 prt_printf(out, "First bucket:");
117 prt_tab(out);
118 prt_printf(out, "%u", le16_to_cpu(m->first_bucket));
119 prt_newline(out);
120
121 prt_printf(out, "Buckets:");
122 prt_tab(out);
123 prt_printf(out, "%llu", le64_to_cpu(m->nbuckets));
124 prt_newline(out);
125
126 prt_printf(out, "Last mount:");
127 prt_tab(out);
128 if (m->last_mount)
129 pr_time(out, le64_to_cpu(m->last_mount));
130 else
131 prt_printf(out, "(never)");
132 prt_newline(out);
133
134 prt_printf(out, "State:");
135 prt_tab(out);
136 prt_printf(out, "%s",
137 BCH_MEMBER_STATE(m) < BCH_MEMBER_STATE_NR
138 ? bch2_member_states[BCH_MEMBER_STATE(m)]
139 : "unknown");
140 prt_newline(out);
141
142 prt_printf(out, "Label:");
143 prt_tab(out);
144 if (BCH_MEMBER_GROUP(m)) {
145 unsigned idx = BCH_MEMBER_GROUP(m) - 1;
146
147 if (idx < disk_groups_nr(gi))
148 prt_printf(out, "%s (%u)",
149 gi->entries[idx].label, idx);
150 else
151 prt_printf(out, "(bad disk labels section)");
152 } else {
153 prt_printf(out, "(none)");
154 }
155 prt_newline(out);
156
157 prt_printf(out, "Data allowed:");
158 prt_tab(out);
159 if (BCH_MEMBER_DATA_ALLOWED(m))
160 prt_bitflags(out, bch2_data_types, BCH_MEMBER_DATA_ALLOWED(m));
161 else
162 prt_printf(out, "(none)");
163 prt_newline(out);
164
165 prt_printf(out, "Has data:");
166 prt_tab(out);
167 if (data_have)
168 prt_bitflags(out, bch2_data_types, data_have);
169 else
170 prt_printf(out, "(none)");
171 prt_newline(out);
172
173 prt_printf(out, "Discard:");
174 prt_tab(out);
175 prt_printf(out, "%llu", BCH_MEMBER_DISCARD(m));
176 prt_newline(out);
177
178 prt_printf(out, "Freespace initialized:");
179 prt_tab(out);
180 prt_printf(out, "%llu", BCH_MEMBER_FREESPACE_INITIALIZED(m));
181 prt_newline(out);
182
183 printbuf_indent_sub(out, 2);
184 }
185}
186
187const struct bch_sb_field_ops bch_sb_field_ops_members = {
188 .validate = bch2_sb_members_validate,
189 .to_text = bch2_sb_members_to_text,
190};