Coverage Report

Created: 2025-06-13 06:36

/src/util-linux/libblkid/src/superblocks/stratis.c
Line
Count
Source (jump to first uncovered line)
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
/* Macro to avoid error in struct declaration. */
23
0
#define STRATIS_UUID_LEN 32
24
/* Contains 4 hyphens and trailing null byte. */
25
#define STRATIS_UUID_STR_LEN 37
26
27
struct stratis_sb {
28
  uint32_t crc32;
29
  uint8_t magic[16];
30
  uint64_t sectors;
31
  uint8_t reserved[4];
32
  uint8_t pool_uuid[STRATIS_UUID_LEN];
33
  uint8_t dev_uuid[STRATIS_UUID_LEN];
34
  uint64_t mda_size;
35
  uint64_t reserved_size;
36
  uint64_t flags;
37
  uint64_t initialization_time;
38
} __attribute__ ((__packed__));
39
40
2.63k
#define BS 512
41
526
#define FIRST_COPY_OFFSET BS
42
526
#define SECOND_COPY_OFFSET (BS * 9)
43
526
#define SB_AREA_SIZE (BS * 16)
44
45
const char STRATIS_MAGIC[] = "!Stra0tis\x86\xff\x02^\x41rh";
46
#define MAGIC_LEN (sizeof(STRATIS_MAGIC) - 1)
47
48
#define _MAGIC_OFFSET (offsetof(const struct stratis_sb, magic))
49
#define MAGIC_OFFSET_COPY_1 (FIRST_COPY_OFFSET + _MAGIC_OFFSET)
50
#define MAGIC_OFFSET_COPY_2 (SECOND_COPY_OFFSET + _MAGIC_OFFSET)
51
52
static int stratis_valid_sb(const uint8_t *p)
53
1.05k
{
54
1.05k
  const struct stratis_sb *stratis = (const struct stratis_sb *)p;
55
1.05k
  uint32_t crc = 0;
56
57
  /* generate CRC from byte position 4 for length 508 == 512 byte sector */
58
1.05k
  crc = crc32c(~0L, p + sizeof(stratis->crc32),
59
1.05k
      BS - sizeof(stratis->crc32));
60
1.05k
  crc ^= ~0L;
61
62
1.05k
  return crc == le32_to_cpu(stratis->crc32);
63
1.05k
}
64
65
/*
66
 * Format UUID string representation to include hyphens given that Stratis stores
67
 * UUIDs without hyphens in the superblock to keep the UUID length a power of 2.
68
 */
69
static void stratis_format_uuid(const unsigned char *src_uuid,
70
        unsigned char *dst_uuid)
71
0
{
72
0
  int i;
73
74
0
  for (i = 0; i < STRATIS_UUID_LEN; i++) {
75
0
    *dst_uuid++ = *src_uuid++;
76
0
    if (i == 7 || i == 11 || i == 15 || i == 19)
77
0
      *dst_uuid ++ = '-';
78
0
  }
79
0
  *dst_uuid = '\0';
80
0
}
81
82
static int probe_stratis(blkid_probe pr,
83
    const struct blkid_idmag *mag __attribute__((__unused__)))
84
526
{
85
526
  const struct stratis_sb *stratis = NULL;
86
526
  const uint8_t *buf = blkid_probe_get_buffer(pr, 0, SB_AREA_SIZE);
87
526
  unsigned char uuid[STRATIS_UUID_STR_LEN];
88
89
526
  if (!buf)
90
0
    return errno ? -errno : 1;
91
92
526
  if (stratis_valid_sb(buf + FIRST_COPY_OFFSET)) {
93
0
    stratis = (const struct stratis_sb *)(buf + FIRST_COPY_OFFSET);
94
526
  } else {
95
526
    if (!stratis_valid_sb(buf + SECOND_COPY_OFFSET))
96
526
      return 1;
97
98
0
    stratis = (const struct stratis_sb *)
99
0
        (buf + SECOND_COPY_OFFSET);
100
0
  }
101
102
0
  stratis_format_uuid(stratis->dev_uuid, uuid);
103
0
  blkid_probe_strncpy_uuid(pr, uuid, sizeof(uuid));
104
105
0
  stratis_format_uuid(stratis->pool_uuid, uuid);
106
0
  blkid_probe_set_value(pr, "POOL_UUID", uuid, sizeof(uuid));
107
108
0
  blkid_probe_sprintf_value(pr, "BLOCKDEV_SECTORS", "%" PRIu64,
109
0
        le64_to_cpu(stratis->sectors));
110
0
  blkid_probe_sprintf_value(pr, "BLOCKDEV_INITTIME", "%" PRIu64,
111
0
        le64_to_cpu(stratis->initialization_time));
112
0
  return 0;
113
526
}
114
115
const struct blkid_idinfo stratis_idinfo = {
116
  .name   = "stratis",
117
  .usage    = BLKID_USAGE_RAID,
118
  .probefunc  = probe_stratis,
119
  .minsz    = SB_AREA_SIZE,
120
  .magics   = {
121
    { .magic = STRATIS_MAGIC, .len = MAGIC_LEN,
122
      .sboff = MAGIC_OFFSET_COPY_1},
123
    { .magic = STRATIS_MAGIC, .len = MAGIC_LEN,
124
      .sboff = MAGIC_OFFSET_COPY_2},
125
    { NULL }
126
  }
127
};