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