/* * Copyright (C) 2018 Tony Asleson * * This file may be redistributed under the terms of the * GNU Lesser General Public License. */ /* * Specification for on disk format * https://stratis-storage.github.io/StratisSoftwareDesign.pdf */ #include #include #include #include #include #include #include "superblocks.h" #include "crc32c.h" struct stratis_sb { uint32_t crc32; uint8_t magic[16]; uint64_t sectors; uint8_t reserved[4]; uint8_t pool_uuid[32]; uint8_t dev_uuid[32]; uint64_t mda_size; uint64_t reserved_size; uint64_t flags; uint64_t initialization_time; } __attribute__ ((__packed__)); #define BS 512 #define FIRST_COPY_OFFSET BS #define SECOND_COPY_OFFSET (BS * 9) #define SB_AREA_SIZE (BS * 16) const char STRATIS_MAGIC[] = "!Stra0tis\x86\xff\x02^\x41rh"; #define MAGIC_LEN (sizeof(STRATIS_MAGIC) - 1) #define _MAGIC_OFFSET (offsetof(const struct stratis_sb, magic)) #define MAGIC_OFFSET_COPY_1 (FIRST_COPY_OFFSET + _MAGIC_OFFSET) #define MAGIC_OFFSET_COPY_2 (SECOND_COPY_OFFSET + _MAGIC_OFFSET) static int stratis_valid_sb(uint8_t *p) { const struct stratis_sb *stratis = (const struct stratis_sb *)p; uint32_t crc = 0; /* generate CRC from byte position 4 for length 508 == 512 byte sector */ crc = crc32c(~0L, p + sizeof(stratis->crc32), BS - sizeof(stratis->crc32)); crc ^= ~0L; return crc == le32_to_cpu(stratis->crc32); } static int probe_stratis(blkid_probe pr, const struct blkid_idmag *mag __attribute__((__unused__))) { const struct stratis_sb *stratis = NULL; uint8_t *buf = blkid_probe_get_buffer(pr, 0, SB_AREA_SIZE); if (!buf) return errno ? -errno : 1; if (stratis_valid_sb(buf + FIRST_COPY_OFFSET)) { stratis = (const struct stratis_sb *)(buf + FIRST_COPY_OFFSET); } else { if (!stratis_valid_sb(buf + SECOND_COPY_OFFSET)) return 1; stratis = (const struct stratis_sb *) (buf + SECOND_COPY_OFFSET); } blkid_probe_strncpy_uuid(pr, (unsigned char *)stratis->dev_uuid, sizeof(stratis->dev_uuid)); blkid_probe_set_value(pr, "POOL_UUID", (unsigned char *)stratis->pool_uuid, sizeof(stratis->pool_uuid)); blkid_probe_sprintf_value(pr, "BLOCKDEV_SECTORS", "%" PRIu64, stratis->sectors); blkid_probe_sprintf_value(pr, "BLOCKDEV_INITTIME", "%" PRIu64, stratis->initialization_time); return 0; } const struct blkid_idinfo stratis_idinfo = { .name = "stratis", .usage = BLKID_USAGE_RAID, .probefunc = probe_stratis, .minsz = SB_AREA_SIZE, .magics = { { .magic = STRATIS_MAGIC, .len = MAGIC_LEN, .sboff = MAGIC_OFFSET_COPY_1}, { .magic = STRATIS_MAGIC, .len = MAGIC_LEN, .sboff = MAGIC_OFFSET_COPY_2}, { NULL } } };