Coverage Report

Created: 2025-06-13 06:36

/src/util-linux/libblkid/src/superblocks/drbd.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2009 by Bastian Friedrich <bastian.friedrich@collax.com>
3
 *
4
 * This file may be redistributed under the terms of the
5
 * GNU Lesser General Public License.
6
 *
7
 * defines, structs taken from drbd source; file names represent drbd source
8
 * files.
9
 */
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <unistd.h>
13
#include <string.h>
14
#include <errno.h>
15
#include <ctype.h>
16
#include <inttypes.h>
17
#include <stddef.h>
18
19
#include "superblocks.h"
20
21
enum {
22
  DRBD_VERSION_08,
23
  DRBD_VERSION_09,
24
};
25
26
/*
27
 * drbd/drbd_int.h
28
 */
29
0
#define BM_BLOCK_SHIFT  12       /* 4k per bit */
30
0
#define BM_BLOCK_SIZE  (1<<BM_BLOCK_SHIFT)
31
32
/*
33
 * user/drbdmeta.c
34
 * We support v08 and v09
35
 */
36
#define DRBD_MD_MAGIC_08    "\x83\x74\x02\x6b"
37
#define DRBD_MD_MAGIC_84_UNCLEAN  "\x83\x74\x02\x6c"
38
#define DRBD_MD_MAGIC_09    "\x83\x74\x02\x6d"
39
/* there is no DRBD_MD_MAGIC_09_UNCLEAN */
40
41
/*
42
 * drbd/linux/drbd.h
43
 */
44
enum drbd_uuid_index {
45
  UI_CURRENT,
46
  UI_BITMAP,
47
  UI_HISTORY_START,
48
  UI_HISTORY_END,
49
  UI_SIZE,    /* nl-packet: number of dirty bits */
50
  UI_FLAGS,   /* nl-packet: flags */
51
  UI_EXTENDED_SIZE  /* Everything. */
52
};
53
54
55
/*
56
 * Used by libblkid to avoid unnecessary padding at the end of the structs and
57
 * too large unused structs in memory.
58
 */
59
#define DRBD_MD_OFFSET 4096
60
61
/*
62
 * user/shared/drbdmeta.c
63
 * Minor modifications wrt. types
64
 */
65
struct md_on_disk_08 {
66
  uint64_t la_sect;         /* last agreed size. */
67
  uint64_t uuid[UI_SIZE];   /* UUIDs */
68
  uint64_t device_uuid;
69
  uint64_t reserved_u64_1;
70
  uint32_t flags;
71
  uint32_t magic;
72
  uint32_t md_size_sect;
73
  int32_t  al_offset;       /* signed sector offset to this block */
74
  uint32_t al_nr_extents;   /* important for restoring the AL */
75
  int32_t  bm_offset;       /* signed sector offset to the bitmap, from here */
76
  uint32_t bm_bytes_per_bit;
77
  uint32_t reserved_u32[4];
78
79
  unsigned char padding_start[0];
80
  unsigned char padding_end[0] __attribute__((aligned(4096)));
81
};
82
83
/*
84
 * linux/drbd.h, v9 only
85
 */
86
#define DRBD_PEERS_MAX 32
87
#define HISTORY_UUIDS DRBD_PEERS_MAX
88
89
/*
90
 * drbd-headers/drbd_meta_data.h
91
 * Minor modifications wrt. types
92
 */
93
struct peer_dev_md_on_disk_9 {
94
  uint64_t bitmap_uuid;
95
  uint64_t bitmap_dagtag;
96
  uint32_t flags;
97
  int32_t bitmap_index;
98
  uint32_t reserved_u32[2];
99
} __attribute__((packed));
100
101
struct meta_data_on_disk_9 {
102
  uint64_t effective_size;    /* last agreed size */
103
  uint64_t current_uuid;
104
  uint64_t reserved_u64[4];   /* to have the magic at the same position as in v07, and v08 */
105
  uint64_t device_uuid;
106
  uint32_t flags;             /* MDF */
107
  uint32_t magic;
108
  uint32_t md_size_sect;
109
  uint32_t al_offset;         /* offset to this block */
110
  uint32_t al_nr_extents;     /* important for restoring the AL */
111
  uint32_t bm_offset;         /* offset to the bitmap, from here */
112
  uint32_t bm_bytes_per_bit;  /* BM_BLOCK_SIZE */
113
  uint32_t la_peer_max_bio_size;   /* last peer max_bio_size */
114
  uint32_t bm_max_peers;
115
  int32_t node_id;
116
117
  /* see al_tr_number_to_on_disk_sector() */
118
  uint32_t al_stripes;
119
  uint32_t al_stripe_size_4k;
120
121
  uint32_t reserved_u32[2];
122
123
  struct peer_dev_md_on_disk_9 peers[DRBD_PEERS_MAX];
124
  uint64_t history_uuids[HISTORY_UUIDS];
125
126
  unsigned char padding_start[0];
127
  unsigned char padding_end[0] __attribute__((aligned(4096)));
128
} __attribute__((packed));
129
130
131
static int is_zero_padded(const unsigned char *padding_start,
132
        const unsigned char *padding_end)
133
0
{
134
0
  for (; padding_start < padding_end; padding_start++) {
135
0
    if (*padding_start != 0)
136
0
      return 0;
137
0
  }
138
0
  return 1;
139
0
}
140
141
static int probe_drbd_84(blkid_probe pr, const struct blkid_idmag *mag)
142
0
{
143
0
  const struct md_on_disk_08 *md;
144
145
0
  md = blkid_probe_get_sb(pr, mag, struct md_on_disk_08);
146
0
  if (!md)
147
0
    return errno ? -errno : 1;
148
149
0
  if (be32_to_cpu(read_unaligned_member(md, bm_bytes_per_bit)) != BM_BLOCK_SIZE)
150
0
    return 1;
151
152
0
  if (!is_zero_padded(member_ptr(md, padding_start),
153
0
          member_ptr(md, padding_end)))
154
0
    return 1;
155
156
  /*
157
   * DRBD does not have "real" uuids; the following resembles DRBD's
158
   * notion of uuids (64 bit, see struct above)
159
   */
160
0
  blkid_probe_sprintf_uuid(pr,
161
0
    member_ptr(md, device_uuid), sizeof(md->device_uuid),
162
0
    "%" PRIx64, be64_to_cpu(read_unaligned_member(md, device_uuid)));
163
164
0
  blkid_probe_set_version(pr, "v08");
165
166
0
  return 0;
167
0
}
168
169
static int probe_drbd_90(blkid_probe pr, const struct blkid_idmag *mag)
170
0
{
171
0
  const struct meta_data_on_disk_9 *md;
172
173
0
  md = blkid_probe_get_sb(pr, mag, struct meta_data_on_disk_9);
174
0
  if (!md)
175
0
    return errno ? -errno : 1;
176
177
0
  if (be32_to_cpu(read_unaligned_member(md, bm_bytes_per_bit)) != BM_BLOCK_SIZE)
178
0
    return 1;
179
180
0
  if (!is_zero_padded(member_ptr(md, padding_start),
181
0
          member_ptr(md, padding_end)))
182
0
    return 1;
183
184
  /*
185
   * DRBD does not have "real" uuids; the following resembles DRBD's
186
   * notion of uuids (64 bit, see struct above)
187
   */
188
0
  blkid_probe_sprintf_uuid(pr,
189
0
    member_ptr(md, device_uuid), sizeof(md->device_uuid),
190
0
    "%" PRIx64, be64_to_cpu(read_unaligned_member(md, device_uuid)));
191
192
0
  blkid_probe_set_version(pr, "v09");
193
194
0
  return 0;
195
0
}
196
197
static int probe_drbd(blkid_probe pr, const struct blkid_idmag *mag)
198
0
{
199
0
  if (mag->hint == DRBD_VERSION_08)
200
0
    return probe_drbd_84(pr, mag);
201
202
0
  if (mag->hint == DRBD_VERSION_09)
203
0
    return probe_drbd_90(pr, mag);
204
205
0
  return 1;
206
0
}
207
208
const struct blkid_idinfo drbd_idinfo =
209
{
210
  .name   = "drbd",
211
  .usage    = BLKID_USAGE_RAID,
212
  .probefunc  = probe_drbd,
213
  /*
214
   * Smaller ones are certainly not DRBD9 devices.
215
   * Recent utils even refuse to generate larger ones,
216
   * keep this as a sufficient lower bound.
217
   */
218
  .minsz    = 0x10000,
219
  .magics   = {
220
    {
221
      .magic = DRBD_MD_MAGIC_08,
222
      .len   = sizeof(DRBD_MD_MAGIC_08) - 1,
223
      .hint  = DRBD_VERSION_08,
224
      .kboff = -(DRBD_MD_OFFSET >> 10),
225
      .sboff = offsetof(struct md_on_disk_08, magic),
226
    },
227
    {
228
      .magic = DRBD_MD_MAGIC_84_UNCLEAN,
229
      .len   = sizeof(DRBD_MD_MAGIC_84_UNCLEAN) - 1,
230
      .hint  = DRBD_VERSION_08,
231
      .kboff = -(DRBD_MD_OFFSET >> 10),
232
      .sboff = offsetof(struct md_on_disk_08, magic),
233
    },
234
    {
235
      .magic = DRBD_MD_MAGIC_09,
236
      .len   = sizeof(DRBD_MD_MAGIC_09) - 1,
237
      .hint  = DRBD_VERSION_09,
238
      .kboff = -(DRBD_MD_OFFSET >> 10),
239
      .sboff = offsetof(struct meta_data_on_disk_9, magic),
240
    },
241
    { NULL }
242
  }
243
};
244