]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/sb-members.c
Update bcachefs sources to a8115093df bcachefs: Fix divide by zero in rebalance_work()
[bcachefs-tools-debian] / libbcachefs / sb-members.c
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
11 static 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
61 static 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
170 const 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 };