]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_fs.c
Update bcachefs sources to f638850417 bcachefs: bch2_trans_log_msg()
[bcachefs-tools-debian] / cmd_fs.c
1
2 #include <stdio.h>
3 #include <sys/ioctl.h>
4
5 #include <uuid/uuid.h>
6
7 #include "linux/sort.h"
8
9 #include "libbcachefs/bcachefs_ioctl.h"
10 #include "libbcachefs/darray.h"
11 #include "libbcachefs/opts.h"
12
13 #include "cmds.h"
14 #include "libbcachefs.h"
15
16 static void dev_usage_type_to_text(struct printbuf *out,
17                                    const char *type,
18                                    unsigned bucket_size,
19                                    u64 buckets, u64 sectors)
20 {
21         u64 frag = max((s64) buckets * bucket_size - (s64) sectors, 0LL);
22
23         pr_buf(out, "%s:", type);
24         pr_tab(out);
25         pr_sectors(out, sectors);
26         pr_tab_rjust(out);
27         pr_buf(out, "%llu", buckets);
28         pr_tab_rjust(out);
29         pr_sectors(out, frag);
30         pr_tab_rjust(out);
31         pr_newline(out);
32 }
33
34 static void dev_usage_to_text(struct printbuf *out,
35                               struct bchfs_handle fs,
36                               struct dev_name *d)
37 {
38         struct bch_ioctl_dev_usage u = bchu_dev_usage(fs, d->idx);
39         unsigned i;
40
41         pr_newline(out);
42         pr_buf(out, "%s (device %u):", d->label ?: "(no label)", d->idx);
43         pr_tab(out);
44         pr_buf(out, "%s", d->dev ?: "(device not found)");
45         pr_tab_rjust(out);
46
47         pr_buf(out, "%s", bch2_member_states[u.state]);
48         pr_tab_rjust(out);
49
50         pr_newline(out);
51
52         pr_indent_push(out, 2);
53         pr_tab(out);
54
55         pr_buf(out, "data");
56         pr_tab_rjust(out);
57
58         pr_buf(out, "buckets");
59         pr_tab_rjust(out);
60
61         pr_buf(out, "fragmented");
62         pr_tab_rjust(out);
63
64         pr_newline(out);
65
66         for (i = BCH_DATA_sb; i < BCH_DATA_NR; i++)
67                 dev_usage_type_to_text(out,
68                                        bch2_data_types[i],
69                                        u.bucket_size,
70                                        u.buckets[i],
71                                        u.sectors[i]);
72
73         dev_usage_type_to_text(out,
74                                "erasure coded",
75                                u.bucket_size,
76                                u.ec_buckets,
77                                u.ec_sectors);
78
79         pr_buf(out, "available:");
80         pr_tab(out);
81
82         pr_sectors(out, u.available_buckets * u.bucket_size);
83         pr_tab_rjust(out);
84
85         pr_buf(out, "%llu", u.available_buckets);
86         pr_tab_rjust(out);
87         pr_newline(out);
88
89         pr_buf(out, "capacity:");
90         pr_tab(out);
91
92         pr_sectors(out, u.nr_buckets * u.bucket_size);
93         pr_tab_rjust(out);
94         pr_buf(out, "%llu", u.nr_buckets);
95         pr_tab_rjust(out);
96
97         pr_indent_pop(out, 2);
98
99         pr_newline(out);
100 }
101
102 static int dev_by_label_cmp(const void *_l, const void *_r)
103 {
104         const struct dev_name *l = _l, *r = _r;
105
106         return  (l->label && r->label
107                  ? strcmp(l->label, r->label) : 0) ?:
108                 (l->dev && r->dev
109                  ? strcmp(l->dev, r->dev) : 0) ?:
110                 cmp_int(l->idx, r->idx);
111 }
112
113 static struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx)
114 {
115         struct dev_name *dev;
116
117         darray_for_each(*dev_names, dev)
118                 if (dev->idx == idx)
119                         return dev;
120
121         return NULL;
122 }
123
124 static void replicas_usage_to_text(struct printbuf *out,
125                                    const struct bch_replicas_usage *r,
126                                    dev_names *dev_names)
127 {
128         unsigned i;
129
130         if (!r->sectors)
131                 return;
132
133         char devs[4096], *d = devs;
134         *d++ = '[';
135
136         for (i = 0; i < r->r.nr_devs; i++) {
137                 unsigned dev_idx = r->r.devs[i];
138                 struct dev_name *dev = dev_idx_to_name(dev_names, dev_idx);
139
140                 if (i)
141                         *d++ = ' ';
142
143                 d += dev && dev->dev
144                         ? sprintf(d, "%s", dev->dev)
145                         : sprintf(d, "%u", dev_idx);
146         }
147         *d++ = ']';
148         *d++ = '\0';
149
150         pr_buf(out, "%s: ", bch2_data_types[r->r.data_type]);
151         pr_tab(out);
152
153         pr_buf(out, "%u/%u ", r->r.nr_required, r->r.nr_devs);
154         pr_tab(out);
155
156         pr_buf(out, "%s ", devs);
157         pr_tab(out);
158
159         pr_sectors(out, r->sectors);
160         pr_tab_rjust(out);
161         pr_newline(out);
162 }
163
164 #define for_each_usage_replica(_u, _r)                                  \
165         for (_r = (_u)->replicas;                                       \
166              _r != (void *) (_u)->replicas + (_u)->replica_entries_bytes;\
167              _r = replicas_usage_next(_r),                              \
168              BUG_ON((void *) _r > (void *) (_u)->replicas + (_u)->replica_entries_bytes))
169
170 static void fs_usage_to_text(struct printbuf *out, const char *path)
171 {
172         unsigned i;
173
174         struct bchfs_handle fs = bcache_fs_open(path);
175
176         struct dev_name *dev;
177         dev_names dev_names = bchu_fs_get_devices(fs);
178
179         struct bch_ioctl_fs_usage *u = bchu_fs_usage(fs);
180
181         pr_buf(out, "Filesystem: ");
182         pr_uuid(out, fs.uuid.b);
183         pr_newline(out);
184
185         out->tabstops[0] = 20;
186         out->tabstops[1] = 36;
187
188         pr_buf(out, "Size:");
189         pr_tab(out);
190         pr_sectors(out, u->capacity);
191         pr_tab_rjust(out);
192         pr_newline(out);
193
194         pr_buf(out, "Used:");
195         pr_tab(out);
196         pr_sectors(out, u->used);
197         pr_tab_rjust(out);
198         pr_newline(out);
199
200         pr_buf(out, "Online reserved:");
201         pr_tab(out);
202         pr_sectors(out, u->online_reserved);
203         pr_tab_rjust(out);
204         pr_newline(out);
205
206         pr_newline(out);
207
208         out->tabstops[0] = 16;
209         out->tabstops[1] = 32;
210         out->tabstops[2] = 50;
211         out->tabstops[3] = 68;
212
213         pr_buf(out, "Data type");
214         pr_tab(out);
215
216         pr_buf(out, "Required/total");
217         pr_tab(out);
218
219         pr_buf(out, "Devices");
220         pr_newline(out);
221
222         for (i = 0; i < BCH_REPLICAS_MAX; i++) {
223                 if (!u->persistent_reserved[i])
224                         continue;
225
226                 pr_buf(out, "reserved:");
227                 pr_tab(out);
228                 pr_buf(out, "%u/%u ", 1, i);
229                 pr_tab(out);
230                 pr_buf(out, "[] ");
231                 pr_sectors(out, u->persistent_reserved[i]);
232                 pr_tab_rjust(out);
233                 pr_newline(out);
234         }
235
236         struct bch_replicas_usage *r;
237
238         for_each_usage_replica(u, r)
239                 if (r->r.data_type < BCH_DATA_user)
240                         replicas_usage_to_text(out, r, &dev_names);
241
242         for_each_usage_replica(u, r)
243                 if (r->r.data_type == BCH_DATA_user &&
244                     r->r.nr_required <= 1)
245                         replicas_usage_to_text(out, r, &dev_names);
246
247         for_each_usage_replica(u, r)
248                 if (r->r.data_type == BCH_DATA_user &&
249                     r->r.nr_required > 1)
250                         replicas_usage_to_text(out, r, &dev_names);
251
252         for_each_usage_replica(u, r)
253                 if (r->r.data_type > BCH_DATA_user)
254                         replicas_usage_to_text(out, r, &dev_names);
255
256         free(u);
257
258         sort(dev_names.data, dev_names.nr,
259              sizeof(dev_names.data[0]), dev_by_label_cmp, NULL);
260
261         out->tabstops[0] = 16;
262         out->tabstops[1] = 36;
263         out->tabstops[2] = 52;
264         out->tabstops[3] = 68;
265
266         darray_for_each(dev_names, dev)
267                 dev_usage_to_text(out, fs, dev);
268
269         darray_for_each(dev_names, dev) {
270                 free(dev->dev);
271                 free(dev->label);
272         }
273         darray_exit(dev_names);
274
275         bcache_fs_close(fs);
276 }
277
278 int fs_usage(void)
279 {
280        puts("bcachefs fs - manage a running filesystem\n"
281             "Usage: bcachefs fs <CMD> [OPTION]... path\n"
282             "\n"
283             "Commands:\n"
284             "  usage                      show disk usage\n"
285             "\n"
286             "Report bugs to <linux-bcachefs@vger.kernel.org>");
287        return 0;
288 }
289
290 int cmd_fs_usage(int argc, char *argv[])
291 {
292         enum printbuf_units units = PRINTBUF_UNITS_BYTES;
293         struct printbuf buf = PRINTBUF;
294         char *fs;
295         int opt;
296
297         while ((opt = getopt(argc, argv, "h")) != -1)
298                 switch (opt) {
299                 case 'h':
300                         units = PRINTBUF_UNITS_HUMAN_READABLE;
301                         break;
302                 }
303         args_shift(optind);
304
305         if (!argc) {
306                 printbuf_reset(&buf);
307                 buf.units = units;
308                 fs_usage_to_text(&buf, ".");
309                 printf("%s", buf.buf);
310         } else {
311                 while ((fs = arg_pop())) {
312                         printbuf_reset(&buf);
313                         buf.units = units;
314                         fs_usage_to_text(&buf, fs);
315                         printf("%s", buf.buf);
316                 }
317         }
318
319         printbuf_exit(&buf);
320         return 0;
321 }