]>
Commit | Line | Data |
---|---|---|
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 |
10 | static struct bch_member *members_v1_get_mut(struct bch_sb_field_members *mi, int i) |
11 | { | |
12 | return mi->members + i; | |
13 | } | |
14 | ||
15 | static 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 | ||
22 | struct 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 | |
28 | static 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 | ||
78 | static 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 | ||
187 | const 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 | }; |