]> git.sesse.net Git - bcachefs-tools-debian/blob - bcache-super-show.c
Better usage message.
[bcachefs-tools-debian] / bcache-super-show.c
1 /*
2  * Author: Gabriel de Perthuis <g2p.code@gmail.com>
3  *
4  * GPLv2
5  */
6
7
8 #define _FILE_OFFSET_BITS       64
9 #define __USE_FILE_OFFSET64
10 #define _XOPEN_SOURCE 500
11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <inttypes.h>
15 #include <linux/fs.h>
16 #include <stdbool.h>
17 #include <stdint.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <uuid/uuid.h>
26
27 #include "bcache.h"
28
29
30 static void usage()
31 {
32         fprintf(stderr, "Usage: bcache-super-show [-f] <device>\n");
33 }
34
35
36 static bool accepted_char(char c)
37 {
38         if ('0' <= c && c <= '9')
39                 return true;
40         if ('A' <= c && c <= 'Z')
41                 return true;
42         if ('a' <= c && c <= 'z')
43                 return true;
44         if (strchr(".-_", c))
45                 return true;
46         return false;
47 }
48
49 static void print_encode(char* in)
50 {
51         for (char* pos = in; *pos; pos++)
52                 if (accepted_char(*pos))
53                         putchar(*pos);
54                 else
55                         printf("%%%x", *pos);
56 }
57
58
59 int main(int argc, char **argv)
60 {
61         bool force_csum = false;
62         int o;
63         extern char *optarg;
64         struct cache_sb sb;
65         char uuid[40];
66         uint64_t expected_csum;
67
68         while ((o = getopt(argc, argv, "f")) != EOF)
69                 switch (o) {
70                         case 'f':
71                                 force_csum = 1;
72                                 break;
73
74                         default:
75                                 usage();
76                                 exit(1);
77                 }
78
79         argv += optind;
80         argc -= optind;
81
82         if (argc != 1) {
83                 usage();
84                 exit(1);
85         }
86
87         int fd = open(argv[0], O_RDONLY);
88         if (fd < 0) {
89                 printf("Can't open dev %s: %s\n", argv[0], strerror(errno));
90                 exit(2);
91         }
92
93         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
94                 fprintf(stderr, "Couldn't read\n");
95                 exit(2);
96         }
97
98         printf("sb.magic\t\t");
99         if (!memcmp(sb.magic, bcache_magic, 16)) {
100                 printf("ok\n");
101         } else {
102                 printf("bad magic\n");
103                 fprintf(stderr, "Invalid superblock (bad magic)\n");
104                 exit(2);
105         }
106
107         printf("sb.first_sector\t\t%" PRIu64, sb.offset);
108         if (sb.offset == SB_SECTOR) {
109                 printf(" [match]\n");
110         } else {
111                 printf(" [expected %ds]\n", SB_SECTOR);
112                 fprintf(stderr, "Invalid superblock (bad sector)\n");
113                 exit(2);
114         }
115
116         printf("sb.csum\t\t\t%" PRIX64, sb.csum);
117         expected_csum = csum_set(&sb);
118         if (sb.csum == expected_csum) {
119                 printf(" [match]\n");
120         } else {
121                 printf(" [expected %" PRIX64 "]\n", expected_csum);
122                 if (!force_csum) {
123                         fprintf(stderr, "Corrupt superblock (bad csum)\n");
124                         exit(2);
125                 }
126         }
127
128         printf("sb.version\t\t%" PRIu64, sb.version);
129         switch (sb.version) {
130                 // These are handled the same by the kernel
131                 case BCACHE_SB_VERSION_CDEV:
132                 case BCACHE_SB_VERSION_CDEV_WITH_UUID:
133                         printf(" [cache device]\n");
134                         break;
135
136                 // The second adds data offset support
137                 case BCACHE_SB_VERSION_BDEV:
138                 case BCACHE_SB_VERSION_BDEV_WITH_OFFSET:
139                         printf(" [backing device]\n");
140                         break;
141
142                 default:
143                         printf(" [unknown]\n");
144                         // exit code?
145                         return 0;
146         }
147
148         putchar('\n');
149
150         char label[SB_LABEL_SIZE + 1];
151         strncpy(label, (char*)sb.label, SB_LABEL_SIZE);
152         label[SB_LABEL_SIZE] = '\0';
153         printf("dev.label\t\t");
154         if (*label)
155                 print_encode(label);
156         else
157                 printf("(empty)");
158         putchar('\n');
159
160         uuid_unparse(sb.uuid, uuid);
161         printf("dev.uuid\t\t%s\n", uuid);
162
163         printf("dev.sectors_per_block\t%u\n"
164                "dev.sectors_per_bucket\t%u\n",
165                sb.block_size,
166                sb.bucket_size);
167
168         if (!SB_IS_BDEV(&sb)) {
169                 // total_sectors includes the superblock;
170                 printf("dev.cache.first_sector\t%u\n"
171                        "dev.cache.cache_sectors\t%ju\n"
172                        "dev.cache.total_sectors\t%ju\n"
173                        "dev.cache.ordered\t%s\n"
174                        "dev.cache.discard\t%s\n"
175                        "dev.cache.pos\t\t%u\n"
176                        "dev.cache.setsize\t\t%u\n"
177                        "dev.cache.replacement\t%ju",
178                        sb.bucket_size * sb.first_bucket,
179                        sb.bucket_size * (sb.nbuckets - sb.first_bucket),
180                        sb.bucket_size * sb.nbuckets,
181                        CACHE_SYNC(&sb) ? "yes" : "no",
182                        CACHE_DISCARD(&sb) ? "yes" : "no",
183                        sb.nr_this_dev,
184                        sb.nr_in_set,
185                            CACHE_REPLACEMENT(&sb));
186                 switch (CACHE_REPLACEMENT(&sb)) {
187                         case CACHE_REPLACEMENT_LRU:
188                                 printf(" [lru]\n");
189                                 break;
190                         case CACHE_REPLACEMENT_FIFO:
191                                 printf(" [fifo]\n");
192                                 break;
193                         case CACHE_REPLACEMENT_RANDOM:
194                                 printf(" [random]\n");
195                                 break;
196                         default:
197                                 putchar('\n');
198                 }
199
200         } else {
201                 uint64_t first_sector;
202                 if (sb.version == BCACHE_SB_VERSION_BDEV) {
203                         first_sector = BDEV_DATA_START_DEFAULT;
204                 } else {
205                         if (sb.keys == 1 || sb.d[0]) {
206                                 fprintf(stderr,
207                                         "Possible experimental format detected, bailing\n");
208                                 exit(3);
209                         }
210                         first_sector = sb.data_offset;
211                 }
212
213                 printf("dev.data.first_sector\t%ju\n"
214                        "dev.data.cache_mode\t%ju",
215                        first_sector,
216                        BDEV_CACHE_MODE(&sb));
217                 switch (BDEV_CACHE_MODE(&sb)) {
218                         case CACHE_MODE_WRITETHROUGH:
219                                 printf(" [writethrough]\n");
220                                 break;
221                         case CACHE_MODE_WRITEBACK:
222                                 printf(" [writeback]\n");
223                                 break;
224                         case CACHE_MODE_WRITEAROUND:
225                                 printf(" [writearound]\n");
226                                 break;
227                         case CACHE_MODE_NONE:
228                                 printf(" [no caching]\n");
229                                 break;
230                         default:
231                                 putchar('\n');
232                 }
233
234                 printf("dev.data.cache_state\t%ju",
235                        BDEV_STATE(&sb));
236                 switch (BDEV_STATE(&sb)) {
237                         case BDEV_STATE_NONE:
238                                 printf(" [detached]\n");
239                                 break;
240                         case BDEV_STATE_CLEAN:
241                                 printf(" [clean]\n");
242                                 break;
243                         case BDEV_STATE_DIRTY:
244                                 printf(" [dirty]\n");
245                                 break;
246                         case BDEV_STATE_STALE:
247                                 printf(" [inconsistent]\n");
248                                 break;
249                         default:
250                                 putchar('\n');
251                 }
252         }
253         putchar('\n');
254
255         uuid_unparse(sb.set_uuid, uuid);
256         printf("cset.uuid\t\t%s\n", uuid);
257
258         return 0;
259 }