blob: b3e397ba1efcd0fc33fd4e8f20769905086937fc [file] [log] [blame]
bigbiff7b4c7a62015-01-01 19:44:14 -05001/*
2 * Copyright (C) 2013 Rolf Fokkens <rolf@fokkens.nl>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
6 *
7 * Based on code fragments from bcache-tools by Kent Overstreet:
8 * http://evilpiepirate.org/git/bcache-tools.git
9 */
10
11#include <stddef.h>
12#include <stdio.h>
13
14#include "superblocks.h"
15#include "crc64.h"
16
17#define SB_LABEL_SIZE 32
18#define SB_JOURNAL_BUCKETS 256U
19
20#define node(i, j) ((i)->d + (j))
21#define end(i) node(i, (i)->keys)
22
23static const char bcache_magic[] = {
24 0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
25 0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81
26};
27
28struct bcache_super_block {
29 uint64_t csum;
30 uint64_t offset; /* sector where this sb was written */
31 uint64_t version;
32
33 uint8_t magic[16];
34
35 uint8_t uuid[16];
36 union {
37 uint8_t set_uuid[16];
38 uint64_t set_magic;
39 };
40 uint8_t label[SB_LABEL_SIZE];
41
42 uint64_t flags;
43 uint64_t seq;
44 uint64_t pad[8];
45
46 union {
47 struct {
48 /* Cache devices */
49 uint64_t nbuckets; /* device size */
50
51 uint16_t block_size; /* sectors */
52 uint16_t bucket_size; /* sectors */
53
54 uint16_t nr_in_set;
55 uint16_t nr_this_dev;
56 };
57 struct {
58 /* Backing devices */
59 uint64_t data_offset;
60
61 /*
62 * block_size from the cache device section is still used by
63 * backing devices, so don't add anything here until we fix
64 * things to not need it for backing devices anymore
65 */
66 };
67 };
68
69 uint32_t last_mount; /* time_t */
70
71 uint16_t first_bucket;
72 union {
73 uint16_t njournal_buckets;
74 uint16_t keys;
75 };
76 uint64_t d[SB_JOURNAL_BUCKETS]; /* journal buckets */
77};
78
79/* magic string */
80#define BCACHE_SB_MAGIC bcache_magic
81/* magic string len */
82#define BCACHE_SB_MAGIC_LEN sizeof (bcache_magic)
83/* super block offset */
84#define BCACHE_SB_OFF 0x1000
85/* supper block offset in kB */
86#define BCACHE_SB_KBOFF (BCACHE_SB_OFF >> 10)
87/* magic string offset within super block */
88#define BCACHE_SB_MAGIC_OFF offsetof (struct bcache_super_block, magic)
89
90static uint64_t bcache_crc64(struct bcache_super_block *bcs)
91{
92 unsigned char *data = (unsigned char *) bcs;
93 size_t sz;
94
95 data += 8; /* skip csum field */
96 sz = (unsigned char *) end(bcs) - data;
97
98 return crc64(0xFFFFFFFFFFFFFFFFULL, data, sz) ^ 0xFFFFFFFFFFFFFFFFULL;
99}
100
101static int probe_bcache (blkid_probe pr, const struct blkid_idmag *mag)
102{
103 struct bcache_super_block *bcs;
104
105 bcs = blkid_probe_get_sb(pr, mag, struct bcache_super_block);
106 if (!bcs)
107 return errno ? -errno : BLKID_PROBE_NONE;
108
109 if (le64_to_cpu(bcs->offset) != BCACHE_SB_OFF / 512)
110 return BLKID_PROBE_NONE;
111 if (!blkid_probe_verify_csum(pr, bcache_crc64(bcs), le64_to_cpu(bcs->csum)))
112 return BLKID_PROBE_NONE;
113
114 if (blkid_probe_set_uuid(pr, bcs->uuid) < 0)
115 return BLKID_PROBE_NONE;
116
117 return BLKID_PROBE_OK;
118};
119
120const struct blkid_idinfo bcache_idinfo =
121{
122 .name = "bcache",
123 .usage = BLKID_USAGE_OTHER,
124 .probefunc = probe_bcache,
125 .minsz = 8192,
126 .magics =
127 {
128 { .magic = BCACHE_SB_MAGIC
129 , .len = BCACHE_SB_MAGIC_LEN
130 , .kboff = BCACHE_SB_KBOFF
131 , .sboff = BCACHE_SB_MAGIC_OFF
132 } ,
133 { NULL }
134 }
135};
136