xref: /spdk/module/bdev/raid/bdev_raid_sb.c (revision b02581a89058ebaebe03bd0e16e3b58adfe406c1)
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 align_ceil(uint64_t val, uint64_t align)
37 {
38 	return spdk_divide_round_up(val, align) * align;
39 }
40 
41 void
42 raid_bdev_init_superblock(struct raid_bdev *raid_bdev)
43 {
44 	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 	memset(sb, 0, RAID_BDEV_SB_MAX_LENGTH);
49 
50 	memcpy(&sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature));
51 	sb->version.major = RAID_BDEV_SB_VERSION_MAJOR;
52 	sb->version.minor = RAID_BDEV_SB_VERSION_MINOR;
53 	spdk_uuid_copy(&sb->uuid, &raid_bdev->bdev.uuid);
54 	snprintf(sb->name, RAID_BDEV_SB_NAME_SIZE, "%s", raid_bdev->bdev.name);
55 	sb->raid_size = raid_bdev->bdev.blockcnt;
56 	sb->block_size = raid_bdev->bdev.blocklen;
57 	sb->level = raid_bdev->level;
58 	sb->strip_size = raid_bdev->strip_size;
59 	/* TODO: sb->state */
60 	sb->num_base_bdevs = sb->base_bdevs_size = raid_bdev->num_base_bdevs;
61 	sb->length = sizeof(*sb) + sizeof(*sb_base_bdev) * sb->base_bdevs_size;
62 
63 	sb_base_bdev = &sb->base_bdevs[0];
64 	RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
65 		spdk_uuid_copy(&sb_base_bdev->uuid, &base_info->uuid);
66 		sb_base_bdev->data_offset = base_info->data_offset;
67 		sb_base_bdev->data_size = base_info->data_size;
68 		sb_base_bdev->state = RAID_SB_BASE_BDEV_CONFIGURED;
69 		sb_base_bdev->slot = raid_bdev_base_bdev_slot(base_info);
70 		sb_base_bdev++;
71 	}
72 }
73 
74 static void
75 raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb)
76 {
77 	sb->crc = 0;
78 	sb->crc = spdk_crc32c_update(sb, sb->length, 0);
79 }
80 
81 static bool
82 raid_bdev_sb_check_crc(struct raid_bdev_superblock *sb)
83 {
84 	uint32_t crc, prev = sb->crc;
85 
86 	raid_bdev_sb_update_crc(sb);
87 	crc = sb->crc;
88 	sb->crc = prev;
89 
90 	return crc == prev;
91 }
92 
93 static int
94 raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx)
95 {
96 	struct raid_bdev_superblock *sb = ctx->buf;
97 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
98 
99 	if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) {
100 		SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n");
101 		return -EINVAL;
102 	}
103 
104 	if (sb->length > ctx->buf_size) {
105 		if (sb->length > RAID_BDEV_SB_MAX_LENGTH) {
106 			SPDK_WARNLOG("Incorrect superblock length on bdev %s\n",
107 				     spdk_bdev_get_name(bdev));
108 			return -EINVAL;
109 		}
110 
111 		return -EAGAIN;
112 	}
113 
114 	if (!raid_bdev_sb_check_crc(sb)) {
115 		SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev));
116 		return -EINVAL;
117 	}
118 
119 	if (sb->version.major != RAID_BDEV_SB_VERSION_MAJOR) {
120 		SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n",
121 			    sb->version.major, spdk_bdev_get_name(bdev));
122 		return -EINVAL;
123 	}
124 
125 	if (sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) {
126 		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 	}
129 
130 	return 0;
131 }
132 
133 static void
134 raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx)
135 {
136 	spdk_dma_free(ctx->buf);
137 
138 	free(ctx);
139 }
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 raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx)
145 {
146 	struct raid_bdev_superblock *sb = ctx->buf;
147 	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 	buf_size_prev = ctx->buf_size;
153 	ctx->buf_size = align_ceil(sb->length, spdk_bdev_get_block_size(bdev));
154 	buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
155 	if (buf == NULL) {
156 		SPDK_ERRLOG("Failed to reallocate buffer\n");
157 		return -ENOMEM;
158 	}
159 	ctx->buf = buf;
160 
161 	rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev,
162 			    ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx);
163 	if (rc != 0) {
164 		SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n",
165 			    spdk_bdev_get_name(bdev), spdk_strerror(-rc));
166 		return rc;
167 	}
168 
169 	return 0;
170 }
171 
172 static void
173 raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
174 {
175 	struct raid_bdev_read_sb_ctx *ctx = cb_arg;
176 	struct raid_bdev_superblock *sb = NULL;
177 	int status;
178 
179 	spdk_bdev_free_io(bdev_io);
180 
181 	if (!success) {
182 		status = -EIO;
183 		goto out;
184 	}
185 
186 	status = raid_bdev_parse_superblock(ctx);
187 	if (status == -EAGAIN) {
188 		status = raid_bdev_read_sb_remainder(ctx);
189 		if (status == 0) {
190 			return;
191 		}
192 	} else if (status != 0) {
193 		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 	} else {
196 		sb = ctx->buf;
197 	}
198 out:
199 	ctx->cb(sb, status, ctx->cb_ctx);
200 
201 	raid_bdev_read_sb_ctx_free(ctx);
202 }
203 
204 int
205 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 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
209 	struct raid_bdev_read_sb_ctx *ctx;
210 	int rc;
211 
212 	assert(cb != NULL);
213 
214 	ctx = calloc(1, sizeof(*ctx));
215 	if (!ctx) {
216 		return -ENOMEM;
217 	}
218 
219 	ctx->desc = desc;
220 	ctx->ch = ch;
221 	ctx->cb = cb;
222 	ctx->cb_ctx = cb_ctx;
223 	ctx->buf_size = align_ceil(sizeof(struct raid_bdev_superblock), spdk_bdev_get_block_size(bdev));
224 	ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
225 	if (!ctx->buf) {
226 		rc = -ENOMEM;
227 		goto err;
228 	}
229 
230 	rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx);
231 	if (rc) {
232 		goto err;
233 	}
234 
235 	return 0;
236 err:
237 	raid_bdev_read_sb_ctx_free(ctx);
238 
239 	return rc;
240 }
241 
242 static void
243 raid_bdev_write_sb_base_bdev_done(int status, struct raid_bdev_write_sb_ctx *ctx)
244 {
245 	if (status != 0) {
246 		ctx->status = status;
247 	}
248 
249 	if (--ctx->remaining == 0) {
250 		ctx->cb(ctx->status, ctx->raid_bdev, ctx->cb_ctx);
251 		free(ctx);
252 	}
253 }
254 
255 static void
256 raid_bdev_write_superblock_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
257 {
258 	struct raid_bdev_write_sb_ctx *ctx = cb_arg;
259 	int status = 0;
260 
261 	if (!success) {
262 		SPDK_ERRLOG("Failed to save superblock on bdev %s\n", bdev_io->bdev->name);
263 		status = -EIO;
264 	}
265 
266 	spdk_bdev_free_io(bdev_io);
267 
268 	raid_bdev_write_sb_base_bdev_done(status, ctx);
269 }
270 
271 static void
272 _raid_bdev_write_superblock(void *_ctx)
273 {
274 	struct raid_bdev_write_sb_ctx *ctx = _ctx;
275 	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 	for (i = ctx->submitted; i < raid_bdev->num_base_bdevs; i++) {
281 		base_info = &raid_bdev->base_bdev_info[i];
282 
283 		if (base_info->desc == NULL) {
284 			assert(ctx->remaining > 1);
285 			raid_bdev_write_sb_base_bdev_done(0, ctx);
286 			ctx->submitted++;
287 			continue;
288 		}
289 
290 		rc = spdk_bdev_write(base_info->desc, base_info->app_thread_ch,
291 				     (void *)raid_bdev->sb, 0, ctx->nbytes,
292 				     raid_bdev_write_superblock_cb, ctx);
293 		if (rc != 0) {
294 			struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc);
295 
296 			if (rc == -ENOMEM) {
297 				ctx->wait_entry.bdev = bdev;
298 				ctx->wait_entry.cb_fn = _raid_bdev_write_superblock;
299 				ctx->wait_entry.cb_arg = ctx;
300 				spdk_bdev_queue_io_wait(bdev, base_info->app_thread_ch, &ctx->wait_entry);
301 				return;
302 			}
303 
304 			assert(ctx->remaining > 1);
305 			raid_bdev_write_sb_base_bdev_done(rc, ctx);
306 		}
307 
308 		ctx->submitted++;
309 	}
310 
311 	raid_bdev_write_sb_base_bdev_done(0, ctx);
312 }
313 
314 void
315 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 	struct raid_bdev_superblock *sb = raid_bdev->sb;
319 
320 	assert(spdk_get_thread() == spdk_thread_get_app_thread());
321 	assert(sb != NULL);
322 	assert(cb != NULL);
323 
324 	ctx = calloc(1, sizeof(*ctx));
325 	if (!ctx) {
326 		cb(-ENOMEM, raid_bdev, cb_ctx);
327 		return;
328 	}
329 
330 	ctx->raid_bdev = raid_bdev;
331 	ctx->nbytes = align_ceil(sb->length, spdk_bdev_get_block_size(&raid_bdev->bdev));
332 	ctx->remaining = raid_bdev->num_base_bdevs + 1;
333 	ctx->cb = cb;
334 	ctx->cb_ctx = cb_ctx;
335 
336 	sb->seq_number++;
337 	raid_bdev_sb_update_crc(sb);
338 
339 	_raid_bdev_write_superblock(ctx);
340 }
341 
342 SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb)
343