]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libblkid/src/superblocks/stratis.c
libblkid: Add support for stratis
[thirdparty/util-linux.git] / libblkid / src / superblocks / stratis.c
1 /*
2 * Copyright (C) 2018 Tony Asleson <tasleson@redhat.com>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
6 */
7
8 /*
9 * Specification for on disk format
10 * https://stratis-storage.github.io/StratisSoftwareDesign.pdf
11 */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <stdint.h>
17 #include <inttypes.h>
18
19 #include "superblocks.h"
20 #include "crc32c.h"
21
22 struct stratis_sb {
23 uint32_t crc32;
24 uint8_t magic[16];
25 uint64_t sectors;
26 uint8_t reserved[4];
27 uint8_t pool_uuid[32];
28 uint8_t dev_uuid[32];
29 uint64_t mda_size;
30 uint64_t reserved_size;
31 uint64_t flags;
32 uint64_t initialization_time;
33 } __attribute__ ((__packed__));
34
35 #define BS 512
36 #define FIRST_COPY_OFFSET BS
37 #define SECOND_COPY_OFFSET (BS * 9)
38 #define SB_AREA_SIZE (BS * 16)
39
40 const char STRATIS_MAGIC[] = "!Stra0tis\x86\xff\x02^\x41rh";
41 #define MAGIC_LEN (sizeof(STRATIS_MAGIC) - 1)
42
43 #define _MAGIC_OFFSET (offsetof(const struct stratis_sb, magic))
44 #define MAGIC_OFFSET_COPY_1 (FIRST_COPY_OFFSET + _MAGIC_OFFSET)
45 #define MAGIC_OFFSET_COPY_2 (SECOND_COPY_OFFSET + _MAGIC_OFFSET)
46
47 static int stratis_valid_sb(uint8_t *p)
48 {
49 const struct stratis_sb *stratis = (const struct stratis_sb *)p;
50 uint32_t crc = 0;
51
52 /* generate CRC from byte position 4 for length 508 == 512 byte sector */
53 crc = crc32c(~0L, p + sizeof(stratis->crc32),
54 BS - sizeof(stratis->crc32));
55 crc ^= ~0L;
56
57 return crc == le32_to_cpu(stratis->crc32);
58 }
59
60 static int probe_stratis(blkid_probe pr,
61 const struct blkid_idmag *mag __attribute__((__unused__)))
62 {
63 const struct stratis_sb *stratis = NULL;
64 uint8_t *buf = blkid_probe_get_buffer(pr, 0, SB_AREA_SIZE);
65
66 if (!buf)
67 return errno ? -errno : 1;
68
69 if (stratis_valid_sb(buf + FIRST_COPY_OFFSET)) {
70 stratis = (const struct stratis_sb *)(buf + FIRST_COPY_OFFSET);
71 } else {
72 if (!stratis_valid_sb(buf + SECOND_COPY_OFFSET))
73 return 1;
74
75 stratis = (const struct stratis_sb *)
76 (buf + SECOND_COPY_OFFSET);
77 }
78
79 blkid_probe_strncpy_uuid(pr, (unsigned char *)stratis->dev_uuid,
80 sizeof(stratis->dev_uuid));
81 blkid_probe_set_value(pr, "POOL_UUID",
82 (unsigned char *)stratis->pool_uuid,
83 sizeof(stratis->pool_uuid));
84
85 blkid_probe_sprintf_value(pr, "BLOCKDEV_SECTORS", "%" PRIu64,
86 stratis->sectors);
87 blkid_probe_sprintf_value(pr, "BLOCKDEV_INITTIME", "%" PRIu64,
88 stratis->initialization_time);
89
90 return 0;
91 }
92
93 const struct blkid_idinfo stratis_idinfo = {
94 .name = "stratis",
95 .usage = BLKID_USAGE_RAID,
96 .probefunc = probe_stratis,
97 .minsz = SB_AREA_SIZE,
98 .magics = {
99 { .magic = STRATIS_MAGIC, .len = MAGIC_LEN,
100 .sboff = MAGIC_OFFSET_COPY_1},
101 { .magic = STRATIS_MAGIC, .len = MAGIC_LEN,
102 .sboff = MAGIC_OFFSET_COPY_2},
103 { NULL }
104 }
105 };