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