xref: /spdk/module/bdev/raid/bdev_raid_sb.c (revision 9b8579e4af16f0826736c09db858e0737f7556c5)
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 	uint8_t submitted;
19 	uint8_t remaining;
20 	raid_bdev_write_sb_cb cb;
21 	void *cb_ctx;
22 	struct spdk_bdev_io_wait_entry wait_entry;
23 };
24 
25 struct raid_bdev_read_sb_ctx {
26 	struct spdk_bdev_desc *desc;
27 	struct spdk_io_channel *ch;
28 	raid_bdev_load_sb_cb cb;
29 	void *cb_ctx;
30 	void *buf;
31 	uint32_t buf_size;
32 };
33 
34 int
35 raid_bdev_alloc_superblock(struct raid_bdev *raid_bdev, uint32_t block_size)
36 {
37 	struct raid_bdev_superblock *sb;
38 
39 	assert(raid_bdev->sb == NULL);
40 
41 	sb = spdk_dma_zmalloc(SPDK_ALIGN_CEIL(RAID_BDEV_SB_MAX_LENGTH, block_size), 0x1000, NULL);
42 	if (!sb) {
43 		SPDK_ERRLOG("Failed to allocate raid bdev sb buffer\n");
44 		return -ENOMEM;
45 	}
46 
47 	raid_bdev->sb = sb;
48 
49 	return 0;
50 }
51 
52 void
53 raid_bdev_free_superblock(struct raid_bdev *raid_bdev)
54 {
55 	if (raid_bdev->sb_io_buf != NULL && raid_bdev->sb_io_buf != raid_bdev->sb) {
56 		assert(spdk_bdev_is_md_interleaved(&raid_bdev->bdev));
57 		spdk_dma_free(raid_bdev->sb_io_buf);
58 		raid_bdev->sb_io_buf = NULL;
59 	}
60 	spdk_dma_free(raid_bdev->sb);
61 	raid_bdev->sb = NULL;
62 }
63 
64 void
65 raid_bdev_init_superblock(struct raid_bdev *raid_bdev)
66 {
67 	struct raid_bdev_superblock *sb = raid_bdev->sb;
68 	struct raid_base_bdev_info *base_info;
69 	struct raid_bdev_sb_base_bdev *sb_base_bdev;
70 
71 	memcpy(&sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature));
72 	sb->version.major = RAID_BDEV_SB_VERSION_MAJOR;
73 	sb->version.minor = RAID_BDEV_SB_VERSION_MINOR;
74 	spdk_uuid_copy(&sb->uuid, &raid_bdev->bdev.uuid);
75 	snprintf(sb->name, RAID_BDEV_SB_NAME_SIZE, "%s", raid_bdev->bdev.name);
76 	sb->raid_size = raid_bdev->bdev.blockcnt;
77 	sb->block_size = spdk_bdev_get_data_block_size(&raid_bdev->bdev);
78 	sb->level = raid_bdev->level;
79 	sb->strip_size = raid_bdev->strip_size;
80 	/* TODO: sb->state */
81 	sb->num_base_bdevs = sb->base_bdevs_size = raid_bdev->num_base_bdevs;
82 	sb->length = sizeof(*sb) + sizeof(*sb_base_bdev) * sb->base_bdevs_size;
83 
84 	sb_base_bdev = &sb->base_bdevs[0];
85 	RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
86 		spdk_uuid_copy(&sb_base_bdev->uuid, &base_info->uuid);
87 		sb_base_bdev->data_offset = base_info->data_offset;
88 		sb_base_bdev->data_size = base_info->data_size;
89 		sb_base_bdev->state = RAID_SB_BASE_BDEV_CONFIGURED;
90 		sb_base_bdev->slot = raid_bdev_base_bdev_slot(base_info);
91 		sb_base_bdev++;
92 	}
93 }
94 
95 static int
96 raid_bdev_alloc_sb_io_buf(struct raid_bdev *raid_bdev)
97 {
98 	struct raid_bdev_superblock *sb = raid_bdev->sb;
99 
100 	if (spdk_bdev_is_md_interleaved(&raid_bdev->bdev)) {
101 		raid_bdev->sb_io_buf_size = spdk_divide_round_up(sb->length,
102 					    sb->block_size) * raid_bdev->bdev.blocklen;
103 		raid_bdev->sb_io_buf = spdk_dma_zmalloc(raid_bdev->sb_io_buf_size, 0x1000, NULL);
104 		if (!raid_bdev->sb_io_buf) {
105 			SPDK_ERRLOG("Failed to allocate raid bdev sb io buffer\n");
106 			return -ENOMEM;
107 		}
108 	} else {
109 		raid_bdev->sb_io_buf_size = SPDK_ALIGN_CEIL(sb->length, raid_bdev->bdev.blocklen);
110 		raid_bdev->sb_io_buf = raid_bdev->sb;
111 	}
112 
113 	return 0;
114 }
115 
116 static void
117 raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb)
118 {
119 	sb->crc = 0;
120 	sb->crc = spdk_crc32c_update(sb, sb->length, 0);
121 }
122 
123 static bool
124 raid_bdev_sb_check_crc(struct raid_bdev_superblock *sb)
125 {
126 	uint32_t crc, prev = sb->crc;
127 
128 	raid_bdev_sb_update_crc(sb);
129 	crc = sb->crc;
130 	sb->crc = prev;
131 
132 	return crc == prev;
133 }
134 
135 static int
136 raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx)
137 {
138 	struct raid_bdev_superblock *sb = ctx->buf;
139 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
140 
141 	if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) {
142 		SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n");
143 		return -EINVAL;
144 	}
145 
146 	if (spdk_divide_round_up(sb->length, spdk_bdev_get_data_block_size(bdev)) >
147 	    spdk_divide_round_up(ctx->buf_size, bdev->blocklen)) {
148 		if (sb->length > RAID_BDEV_SB_MAX_LENGTH) {
149 			SPDK_WARNLOG("Incorrect superblock length on bdev %s\n",
150 				     spdk_bdev_get_name(bdev));
151 			return -EINVAL;
152 		}
153 
154 		return -EAGAIN;
155 	}
156 
157 	if (!raid_bdev_sb_check_crc(sb)) {
158 		SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev));
159 		return -EINVAL;
160 	}
161 
162 	if (sb->version.major != RAID_BDEV_SB_VERSION_MAJOR) {
163 		SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n",
164 			    sb->version.major, spdk_bdev_get_name(bdev));
165 		return -EINVAL;
166 	}
167 
168 	if (sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) {
169 		SPDK_WARNLOG("Superblock minor version %d on bdev %s is higher than the currently supported: %d\n",
170 			     sb->version.minor, spdk_bdev_get_name(bdev), RAID_BDEV_SB_VERSION_MINOR);
171 	}
172 
173 	return 0;
174 }
175 
176 static void
177 raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx)
178 {
179 	spdk_dma_free(ctx->buf);
180 
181 	free(ctx);
182 }
183 
184 static void raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
185 
186 static int
187 raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx)
188 {
189 	struct raid_bdev_superblock *sb = ctx->buf;
190 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
191 	uint32_t buf_size_prev;
192 	void *buf;
193 	int rc;
194 
195 	buf_size_prev = ctx->buf_size;
196 	ctx->buf_size = spdk_divide_round_up(spdk_min(sb->length, RAID_BDEV_SB_MAX_LENGTH),
197 					     spdk_bdev_get_data_block_size(bdev)) * bdev->blocklen;
198 	buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
199 	if (buf == NULL) {
200 		SPDK_ERRLOG("Failed to reallocate buffer\n");
201 		return -ENOMEM;
202 	}
203 	ctx->buf = buf;
204 
205 	rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev,
206 			    ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx);
207 	if (rc != 0) {
208 		SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n",
209 			    spdk_bdev_get_name(bdev), spdk_strerror(-rc));
210 		return rc;
211 	}
212 
213 	return 0;
214 }
215 
216 static void
217 raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
218 {
219 	struct spdk_bdev *bdev = bdev_io->bdev;
220 	struct raid_bdev_read_sb_ctx *ctx = cb_arg;
221 	struct raid_bdev_superblock *sb = NULL;
222 	int status;
223 
224 	if (spdk_bdev_is_md_interleaved(bdev_io->bdev) && ctx->buf_size > bdev->blocklen) {
225 		const uint32_t data_block_size = spdk_bdev_get_data_block_size(bdev);
226 		uint32_t i;
227 
228 		for (i = 1; i < ctx->buf_size / bdev->blocklen; i++) {
229 			memmove(ctx->buf + (i * data_block_size),
230 				ctx->buf + (i * bdev->blocklen),
231 				data_block_size);
232 		}
233 	}
234 
235 	spdk_bdev_free_io(bdev_io);
236 
237 	if (!success) {
238 		status = -EIO;
239 		goto out;
240 	}
241 
242 	status = raid_bdev_parse_superblock(ctx);
243 	if (status == -EAGAIN) {
244 		status = raid_bdev_read_sb_remainder(ctx);
245 		if (status == 0) {
246 			return;
247 		}
248 	} else if (status != 0) {
249 		SPDK_DEBUGLOG(bdev_raid_sb, "failed to parse bdev %s superblock\n",
250 			      spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ctx->desc)));
251 	} else {
252 		sb = ctx->buf;
253 	}
254 out:
255 	ctx->cb(sb, status, ctx->cb_ctx);
256 
257 	raid_bdev_read_sb_ctx_free(ctx);
258 }
259 
260 int
261 raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
262 				    raid_bdev_load_sb_cb cb, void *cb_ctx)
263 {
264 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
265 	struct raid_bdev_read_sb_ctx *ctx;
266 	int rc;
267 
268 	assert(cb != NULL);
269 
270 	ctx = calloc(1, sizeof(*ctx));
271 	if (!ctx) {
272 		return -ENOMEM;
273 	}
274 
275 	ctx->desc = desc;
276 	ctx->ch = ch;
277 	ctx->cb = cb;
278 	ctx->cb_ctx = cb_ctx;
279 	ctx->buf_size = spdk_divide_round_up(sizeof(struct raid_bdev_superblock),
280 					     spdk_bdev_get_data_block_size(bdev)) * bdev->blocklen;
281 	ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
282 	if (!ctx->buf) {
283 		rc = -ENOMEM;
284 		goto err;
285 	}
286 
287 	rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx);
288 	if (rc) {
289 		goto err;
290 	}
291 
292 	return 0;
293 err:
294 	raid_bdev_read_sb_ctx_free(ctx);
295 
296 	return rc;
297 }
298 
299 static void
300 raid_bdev_write_sb_base_bdev_done(int status, struct raid_bdev_write_sb_ctx *ctx)
301 {
302 	if (status != 0) {
303 		ctx->status = status;
304 	}
305 
306 	if (--ctx->remaining == 0) {
307 		ctx->cb(ctx->status, ctx->raid_bdev, ctx->cb_ctx);
308 		free(ctx);
309 	}
310 }
311 
312 static void
313 raid_bdev_write_superblock_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
314 {
315 	struct raid_bdev_write_sb_ctx *ctx = cb_arg;
316 	int status = 0;
317 
318 	if (!success) {
319 		SPDK_ERRLOG("Failed to save superblock on bdev %s\n", bdev_io->bdev->name);
320 		status = -EIO;
321 	}
322 
323 	spdk_bdev_free_io(bdev_io);
324 
325 	raid_bdev_write_sb_base_bdev_done(status, ctx);
326 }
327 
328 static void
329 _raid_bdev_write_superblock(void *_ctx)
330 {
331 	struct raid_bdev_write_sb_ctx *ctx = _ctx;
332 	struct raid_bdev *raid_bdev = ctx->raid_bdev;
333 	struct raid_base_bdev_info *base_info;
334 	uint8_t i;
335 	int rc;
336 
337 	for (i = ctx->submitted; i < raid_bdev->num_base_bdevs; i++) {
338 		base_info = &raid_bdev->base_bdev_info[i];
339 
340 		if (base_info->desc == NULL) {
341 			assert(ctx->remaining > 1);
342 			raid_bdev_write_sb_base_bdev_done(0, ctx);
343 			ctx->submitted++;
344 			continue;
345 		}
346 
347 		rc = spdk_bdev_write(base_info->desc, base_info->app_thread_ch,
348 				     raid_bdev->sb_io_buf, 0, raid_bdev->sb_io_buf_size,
349 				     raid_bdev_write_superblock_cb, ctx);
350 		if (rc != 0) {
351 			struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc);
352 
353 			if (rc == -ENOMEM) {
354 				ctx->wait_entry.bdev = bdev;
355 				ctx->wait_entry.cb_fn = _raid_bdev_write_superblock;
356 				ctx->wait_entry.cb_arg = ctx;
357 				spdk_bdev_queue_io_wait(bdev, base_info->app_thread_ch, &ctx->wait_entry);
358 				return;
359 			}
360 
361 			assert(ctx->remaining > 1);
362 			raid_bdev_write_sb_base_bdev_done(rc, ctx);
363 		}
364 
365 		ctx->submitted++;
366 	}
367 
368 	raid_bdev_write_sb_base_bdev_done(0, ctx);
369 }
370 
371 void
372 raid_bdev_write_superblock(struct raid_bdev *raid_bdev, raid_bdev_write_sb_cb cb, void *cb_ctx)
373 {
374 	struct raid_bdev_write_sb_ctx *ctx;
375 	struct raid_bdev_superblock *sb = raid_bdev->sb;
376 	int rc;
377 
378 	assert(spdk_get_thread() == spdk_thread_get_app_thread());
379 	assert(sb != NULL);
380 	assert(cb != NULL);
381 
382 	if (raid_bdev->sb_io_buf == NULL) {
383 		rc = raid_bdev_alloc_sb_io_buf(raid_bdev);
384 		if (rc != 0) {
385 			goto err;
386 		}
387 	}
388 
389 	ctx = calloc(1, sizeof(*ctx));
390 	if (!ctx) {
391 		rc = -ENOMEM;
392 		goto err;
393 	}
394 
395 	ctx->raid_bdev = raid_bdev;
396 	ctx->remaining = raid_bdev->num_base_bdevs + 1;
397 	ctx->cb = cb;
398 	ctx->cb_ctx = cb_ctx;
399 
400 	sb->seq_number++;
401 	raid_bdev_sb_update_crc(sb);
402 
403 	if (spdk_bdev_is_md_interleaved(&raid_bdev->bdev)) {
404 		void *sb_buf = sb;
405 		uint32_t i;
406 
407 		for (i = 0; i < raid_bdev->sb_io_buf_size / raid_bdev->bdev.blocklen; i++) {
408 			memcpy(raid_bdev->sb_io_buf + (i * raid_bdev->bdev.blocklen),
409 			       sb_buf + (i * sb->block_size), sb->block_size);
410 		}
411 	}
412 
413 	_raid_bdev_write_superblock(ctx);
414 	return;
415 err:
416 	cb(rc, raid_bdev, cb_ctx);
417 }
418 
419 SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb)
420