Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/bdev_module.h"
7 : : #include "spdk/crc32.h"
8 : : #include "spdk/env.h"
9 : : #include "spdk/log.h"
10 : : #include "spdk/string.h"
11 : : #include "spdk/util.h"
12 : :
13 : : #include "bdev_raid.h"
14 : :
15 : : struct raid_bdev_write_sb_ctx {
16 : : struct raid_bdev *raid_bdev;
17 : : int status;
18 : : uint64_t nbytes;
19 : : uint8_t submitted;
20 : : uint8_t remaining;
21 : : raid_bdev_write_sb_cb cb;
22 : : void *cb_ctx;
23 : : struct spdk_bdev_io_wait_entry wait_entry;
24 : : };
25 : :
26 : : struct raid_bdev_read_sb_ctx {
27 : : struct spdk_bdev_desc *desc;
28 : : struct spdk_io_channel *ch;
29 : : raid_bdev_load_sb_cb cb;
30 : : void *cb_ctx;
31 : : void *buf;
32 : : uint32_t buf_size;
33 : : };
34 : :
35 : : static inline uint64_t
36 : 6376 : align_ceil(uint64_t val, uint64_t align)
37 : : {
38 : 6376 : return spdk_divide_round_up(val, align) * align;
39 : : }
40 : :
41 : : void
42 : 100 : raid_bdev_init_superblock(struct raid_bdev *raid_bdev)
43 : : {
44 [ # # # # ]: 100 : struct raid_bdev_superblock *sb = raid_bdev->sb;
45 : : struct raid_base_bdev_info *base_info;
46 : : struct raid_bdev_sb_base_bdev *sb_base_bdev;
47 : :
48 [ - + ]: 100 : memset(sb, 0, RAID_BDEV_SB_MAX_LENGTH);
49 : :
50 [ - + - + : 100 : memcpy(&sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature));
# # ]
51 [ # # # # : 100 : sb->version.major = RAID_BDEV_SB_VERSION_MAJOR;
# # ]
52 [ # # # # : 100 : sb->version.minor = RAID_BDEV_SB_VERSION_MINOR;
# # ]
53 [ # # # # : 100 : spdk_uuid_copy(&sb->uuid, &raid_bdev->bdev.uuid);
# # ]
54 [ - + # # : 100 : snprintf(sb->name, RAID_BDEV_SB_NAME_SIZE, "%s", raid_bdev->bdev.name);
# # # # ]
55 [ # # # # : 100 : sb->raid_size = raid_bdev->bdev.blockcnt;
# # # # #
# ]
56 [ # # # # : 100 : sb->block_size = raid_bdev->bdev.blocklen;
# # # # #
# ]
57 [ # # # # : 100 : sb->level = raid_bdev->level;
# # # # ]
58 [ # # # # : 100 : sb->strip_size = raid_bdev->strip_size;
# # # # ]
59 : : /* TODO: sb->state */
60 [ # # # # : 100 : sb->num_base_bdevs = sb->base_bdevs_size = raid_bdev->num_base_bdevs;
# # # # #
# # # ]
61 [ # # # # : 100 : sb->length = sizeof(*sb) + sizeof(*sb_base_bdev) * sb->base_bdevs_size;
# # # # ]
62 : :
63 [ # # # # ]: 100 : sb_base_bdev = &sb->base_bdevs[0];
64 [ + + # # : 406 : RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
# # # # #
# # # # #
# # # # ]
65 [ # # # # ]: 306 : spdk_uuid_copy(&sb_base_bdev->uuid, &base_info->uuid);
66 [ # # # # : 306 : sb_base_bdev->data_offset = base_info->data_offset;
# # # # ]
67 [ # # # # : 306 : sb_base_bdev->data_size = base_info->data_size;
# # # # ]
68 [ # # # # ]: 306 : sb_base_bdev->state = RAID_SB_BASE_BDEV_CONFIGURED;
69 [ # # # # ]: 306 : sb_base_bdev->slot = raid_bdev_base_bdev_slot(base_info);
70 [ # # ]: 306 : sb_base_bdev++;
71 : 0 : }
72 : 100 : }
73 : :
74 : : static void
75 : 750 : raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb)
76 : : {
77 [ # # # # ]: 750 : sb->crc = 0;
78 [ # # # # : 750 : sb->crc = spdk_crc32c_update(sb, sb->length, 0);
# # # # ]
79 : 750 : }
80 : :
81 : : static bool
82 : 446 : raid_bdev_sb_check_crc(struct raid_bdev_superblock *sb)
83 : : {
84 [ # # # # ]: 446 : uint32_t crc, prev = sb->crc;
85 : :
86 : 446 : raid_bdev_sb_update_crc(sb);
87 [ # # # # ]: 446 : crc = sb->crc;
88 [ # # # # ]: 446 : sb->crc = prev;
89 : :
90 : 446 : return crc == prev;
91 : : }
92 : :
93 : : static int
94 : 6114 : raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx)
95 : : {
96 [ + - + - ]: 6114 : struct raid_bdev_superblock *sb = ctx->buf;
97 [ + - + - ]: 6114 : struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
98 : :
99 [ + + + + : 6114 : if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) {
+ - + - ]
100 [ + + + + : 5659 : SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n");
+ - ]
101 : 5659 : return -EINVAL;
102 : : }
103 : :
104 [ + + # # : 455 : if (sb->length > ctx->buf_size) {
# # # # #
# ]
105 [ - + # # : 9 : if (sb->length > RAID_BDEV_SB_MAX_LENGTH) {
# # ]
106 : 0 : SPDK_WARNLOG("Incorrect superblock length on bdev %s\n",
107 : : spdk_bdev_get_name(bdev));
108 : 0 : return -EINVAL;
109 : : }
110 : :
111 : 9 : return -EAGAIN;
112 : : }
113 : :
114 [ + + ]: 446 : if (!raid_bdev_sb_check_crc(sb)) {
115 : 9 : SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev));
116 : 9 : return -EINVAL;
117 : : }
118 : :
119 [ + + # # : 437 : if (sb->version.major != RAID_BDEV_SB_VERSION_MAJOR) {
# # # # ]
120 [ # # # # : 3 : SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n",
# # ]
121 : : sb->version.major, spdk_bdev_get_name(bdev));
122 : 3 : return -EINVAL;
123 : : }
124 : :
125 [ - + # # : 434 : if (sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) {
# # # # ]
126 [ # # # # : 0 : SPDK_WARNLOG("Superblock minor version %d on bdev %s is higher than the currently supported: %d\n",
# # ]
127 : : sb->version.minor, spdk_bdev_get_name(bdev), RAID_BDEV_SB_VERSION_MINOR);
128 : 0 : }
129 : :
130 : 434 : return 0;
131 : 47 : }
132 : :
133 : : static void
134 : 6087 : raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx)
135 : : {
136 [ + - + - ]: 6087 : spdk_dma_free(ctx->buf);
137 : :
138 : 6087 : free(ctx);
139 : 6087 : }
140 : :
141 : : static void raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
142 : :
143 : : static int
144 : 6 : raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx)
145 : : {
146 [ # # # # ]: 6 : struct raid_bdev_superblock *sb = ctx->buf;
147 [ # # # # ]: 6 : struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
148 : : uint32_t buf_size_prev;
149 : : void *buf;
150 : : int rc;
151 : :
152 [ # # # # ]: 6 : buf_size_prev = ctx->buf_size;
153 [ # # # # : 6 : ctx->buf_size = align_ceil(sb->length, spdk_bdev_get_block_size(bdev));
# # # # ]
154 [ # # # # : 6 : buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
# # # # ]
155 [ - + ]: 6 : if (buf == NULL) {
156 : 0 : SPDK_ERRLOG("Failed to reallocate buffer\n");
157 : 0 : return -ENOMEM;
158 : : }
159 [ # # # # ]: 6 : ctx->buf = buf;
160 : :
161 [ # # # # : 6 : rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev,
# # # # #
# # # ]
162 [ # # # # ]: 6 : ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx);
163 [ - + ]: 6 : if (rc != 0) {
164 [ # # ]: 0 : SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n",
165 : : spdk_bdev_get_name(bdev), spdk_strerror(-rc));
166 : 0 : return rc;
167 : : }
168 : :
169 : 6 : return 0;
170 : 0 : }
171 : :
172 : : static void
173 : 6093 : raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
174 : : {
175 : 6093 : struct raid_bdev_read_sb_ctx *ctx = cb_arg;
176 : 6093 : struct raid_bdev_superblock *sb = NULL;
177 : : int status;
178 : :
179 : 6093 : spdk_bdev_free_io(bdev_io);
180 : :
181 [ + + + - ]: 6093 : if (!success) {
182 : 0 : status = -EIO;
183 : 0 : goto out;
184 : : }
185 : :
186 : 6093 : status = raid_bdev_parse_superblock(ctx);
187 [ + + ]: 6140 : if (status == -EAGAIN) {
188 : 6 : status = raid_bdev_read_sb_remainder(ctx);
189 [ + - ]: 6 : if (status == 0) {
190 : 6 : return;
191 : : }
192 [ + + ]: 6087 : } else if (status != 0) {
193 [ + + + + : 5659 : SPDK_DEBUGLOG(bdev_raid_sb, "failed to parse bdev %s superblock\n",
+ - # # #
# ]
194 : : spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ctx->desc)));
195 : 47 : } else {
196 [ # # # # ]: 428 : sb = ctx->buf;
197 : : }
198 : 6040 : out:
199 [ + - + - : 6087 : ctx->cb(sb, status, ctx->cb_ctx);
- + + - +
- + - ]
200 : :
201 : 6087 : raid_bdev_read_sb_ctx_free(ctx);
202 : 47 : }
203 : :
204 : : int
205 : 6087 : raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
206 : : raid_bdev_load_sb_cb cb, void *cb_ctx)
207 : : {
208 : 6087 : struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
209 : : struct raid_bdev_read_sb_ctx *ctx;
210 : : int rc;
211 : :
212 [ + + # # ]: 6087 : assert(cb != NULL);
213 : :
214 : 6087 : ctx = calloc(1, sizeof(*ctx));
215 [ + + ]: 6087 : if (!ctx) {
216 : 0 : return -ENOMEM;
217 : : }
218 : :
219 [ + - + - ]: 6087 : ctx->desc = desc;
220 [ + - + - ]: 6087 : ctx->ch = ch;
221 [ + - + - ]: 6087 : ctx->cb = cb;
222 [ + - + - ]: 6087 : ctx->cb_ctx = cb_ctx;
223 [ + - + - ]: 6087 : ctx->buf_size = align_ceil(sizeof(struct raid_bdev_superblock), spdk_bdev_get_block_size(bdev));
224 [ + - + - : 6087 : ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
+ - + - ]
225 [ + + + - : 6087 : if (!ctx->buf) {
+ - ]
226 : 0 : rc = -ENOMEM;
227 : 0 : goto err;
228 : : }
229 : :
230 [ + - + - : 6087 : rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx);
+ - + - ]
231 [ + + ]: 6087 : if (rc) {
232 : 0 : goto err;
233 : : }
234 : :
235 : 6087 : return 0;
236 : 0 : err:
237 : 0 : raid_bdev_read_sb_ctx_free(ctx);
238 : :
239 : 0 : return rc;
240 : 47 : }
241 : :
242 : : static void
243 : 1174 : raid_bdev_write_sb_base_bdev_done(int status, struct raid_bdev_write_sb_ctx *ctx)
244 : : {
245 [ - + ]: 1174 : if (status != 0) {
246 [ # # # # ]: 0 : ctx->status = status;
247 : 0 : }
248 : :
249 [ + + # # ]: 1174 : if (--ctx->remaining == 0) {
250 [ # # # # : 283 : ctx->cb(ctx->status, ctx->raid_bdev, ctx->cb_ctx);
# # # # #
# # # # #
# # # # #
# ]
251 : 283 : free(ctx);
252 : 0 : }
253 : 1174 : }
254 : :
255 : : static void
256 : 756 : raid_bdev_write_superblock_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
257 : : {
258 : 756 : struct raid_bdev_write_sb_ctx *ctx = cb_arg;
259 : 756 : int status = 0;
260 : :
261 [ - + # # ]: 756 : if (!success) {
262 [ # # # # : 0 : SPDK_ERRLOG("Failed to save superblock on bdev %s\n", bdev_io->bdev->name);
# # # # ]
263 : 0 : status = -EIO;
264 : 0 : }
265 : :
266 : 756 : spdk_bdev_free_io(bdev_io);
267 : :
268 : 756 : raid_bdev_write_sb_base_bdev_done(status, ctx);
269 : 756 : }
270 : :
271 : : static void
272 : 283 : _raid_bdev_write_superblock(void *_ctx)
273 : : {
274 : 283 : struct raid_bdev_write_sb_ctx *ctx = _ctx;
275 [ # # # # ]: 283 : struct raid_bdev *raid_bdev = ctx->raid_bdev;
276 : : struct raid_base_bdev_info *base_info;
277 : : uint8_t i;
278 : : int rc;
279 : :
280 [ + + # # : 1174 : for (i = ctx->submitted; i < raid_bdev->num_base_bdevs; i++) {
# # # # #
# ]
281 [ # # # # : 891 : base_info = &raid_bdev->base_bdev_info[i];
# # ]
282 : :
283 [ + + # # : 891 : if (base_info->desc == NULL) {
# # ]
284 [ - + # # : 135 : assert(ctx->remaining > 1);
# # # # ]
285 : 135 : raid_bdev_write_sb_base_bdev_done(0, ctx);
286 [ # # ]: 135 : ctx->submitted++;
287 : 135 : continue;
288 : : }
289 : :
290 [ # # # # : 1356 : rc = spdk_bdev_write(base_info->desc, base_info->app_thread_ch,
# # # # ]
291 [ # # # # : 756 : (void *)raid_bdev->sb, 0, ctx->nbytes,
# # # # ]
292 : 0 : raid_bdev_write_superblock_cb, ctx);
293 [ - + ]: 756 : if (rc != 0) {
294 [ # # # # ]: 0 : struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc);
295 : :
296 [ # # ]: 0 : if (rc == -ENOMEM) {
297 [ # # # # : 0 : ctx->wait_entry.bdev = bdev;
# # ]
298 [ # # # # : 0 : ctx->wait_entry.cb_fn = _raid_bdev_write_superblock;
# # ]
299 [ # # # # : 0 : ctx->wait_entry.cb_arg = ctx;
# # ]
300 [ # # # # : 0 : spdk_bdev_queue_io_wait(bdev, base_info->app_thread_ch, &ctx->wait_entry);
# # ]
301 : 0 : return;
302 : : }
303 : :
304 [ # # # # : 0 : assert(ctx->remaining > 1);
# # # # ]
305 : 0 : raid_bdev_write_sb_base_bdev_done(rc, ctx);
306 : 0 : }
307 : :
308 [ # # ]: 756 : ctx->submitted++;
309 : 0 : }
310 : :
311 : 283 : raid_bdev_write_sb_base_bdev_done(0, ctx);
312 : 0 : }
313 : :
314 : : void
315 : 283 : raid_bdev_write_superblock(struct raid_bdev *raid_bdev, raid_bdev_write_sb_cb cb, void *cb_ctx)
316 : : {
317 : : struct raid_bdev_write_sb_ctx *ctx;
318 [ # # # # ]: 283 : struct raid_bdev_superblock *sb = raid_bdev->sb;
319 : :
320 [ - + # # ]: 283 : assert(spdk_get_thread() == spdk_thread_get_app_thread());
321 [ - + # # ]: 283 : assert(sb != NULL);
322 [ - + # # ]: 283 : assert(cb != NULL);
323 : :
324 : 283 : ctx = calloc(1, sizeof(*ctx));
325 [ - + ]: 283 : if (!ctx) {
326 [ # # # # ]: 0 : cb(-ENOMEM, raid_bdev, cb_ctx);
327 : 0 : return;
328 : : }
329 : :
330 [ # # # # ]: 283 : ctx->raid_bdev = raid_bdev;
331 [ # # # # : 283 : ctx->nbytes = align_ceil(sb->length, spdk_bdev_get_block_size(&raid_bdev->bdev));
# # # # #
# ]
332 [ # # # # : 283 : ctx->remaining = raid_bdev->num_base_bdevs + 1;
# # # # #
# ]
333 [ # # # # ]: 283 : ctx->cb = cb;
334 [ # # # # ]: 283 : ctx->cb_ctx = cb_ctx;
335 : :
336 [ # # ]: 283 : sb->seq_number++;
337 : 283 : raid_bdev_sb_update_crc(sb);
338 : :
339 : 283 : _raid_bdev_write_superblock(ctx);
340 : 0 : }
341 : :
342 : 1813 : SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb)
|