xref: /spdk/lib/bdev/part.c (revision 310fc0b5d56fa43b80af869270fcf2758df9c92d)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Common code for partition-like virtual bdevs.
36  */
37 
38 #include "spdk/bdev.h"
39 #include "spdk/log.h"
40 #include "spdk/string.h"
41 
42 #include "spdk/bdev_module.h"
43 
44 struct spdk_bdev_part_base {
45 	struct spdk_bdev		*bdev;
46 	struct spdk_bdev_desc		*desc;
47 	uint32_t			ref;
48 	uint32_t			channel_size;
49 	spdk_bdev_part_base_free_fn	base_free_fn;
50 	void				*ctx;
51 	bool				claimed;
52 	struct spdk_bdev_module		*module;
53 	struct spdk_bdev_fn_table	*fn_table;
54 	struct bdev_part_tailq		*tailq;
55 	spdk_io_channel_create_cb	ch_create_cb;
56 	spdk_io_channel_destroy_cb	ch_destroy_cb;
57 };
58 
59 struct spdk_bdev *
60 spdk_bdev_part_base_get_bdev(struct spdk_bdev_part_base *part_base)
61 {
62 	return part_base->bdev;
63 }
64 
65 struct spdk_bdev_desc *
66 spdk_bdev_part_base_get_desc(struct spdk_bdev_part_base *part_base)
67 {
68 	return part_base->desc;
69 }
70 
71 struct bdev_part_tailq *
72 spdk_bdev_part_base_get_tailq(struct spdk_bdev_part_base *part_base)
73 {
74 	return part_base->tailq;
75 }
76 
77 void *
78 spdk_bdev_part_base_get_ctx(struct spdk_bdev_part_base *part_base)
79 {
80 	return part_base->ctx;
81 }
82 
83 void
84 spdk_bdev_part_base_free(struct spdk_bdev_part_base *base)
85 {
86 	if (base->desc) {
87 		spdk_bdev_close(base->desc);
88 		base->desc = NULL;
89 	}
90 
91 	if (base->base_free_fn != NULL) {
92 		base->base_free_fn(base->ctx);
93 	}
94 
95 	free(base);
96 }
97 
98 static void
99 spdk_bdev_part_free_cb(void *io_device)
100 {
101 	struct spdk_bdev_part *part = io_device;
102 	struct spdk_bdev_part_base *base;
103 
104 	assert(part);
105 	assert(part->internal.base);
106 
107 	base = part->internal.base;
108 
109 	TAILQ_REMOVE(base->tailq, part, tailq);
110 
111 	if (__sync_sub_and_fetch(&base->ref, 1) == 0) {
112 		spdk_bdev_module_release_bdev(base->bdev);
113 		spdk_bdev_part_base_free(base);
114 	}
115 
116 	spdk_bdev_destruct_done(&part->internal.bdev, 0);
117 	free(part->internal.bdev.name);
118 	free(part->internal.bdev.product_name);
119 	free(part);
120 }
121 
122 int
123 spdk_bdev_part_free(struct spdk_bdev_part *part)
124 {
125 	spdk_io_device_unregister(part, spdk_bdev_part_free_cb);
126 
127 	/* Return 1 to indicate that this is an asynchronous operation that isn't complete
128 	 * until spdk_bdev_destruct_done is called */
129 	return 1;
130 }
131 
132 void
133 spdk_bdev_part_base_hotremove(struct spdk_bdev_part_base *part_base, struct bdev_part_tailq *tailq)
134 {
135 	struct spdk_bdev_part *part, *tmp;
136 
137 	TAILQ_FOREACH_SAFE(part, tailq, tailq, tmp) {
138 		if (part->internal.base == part_base) {
139 			spdk_bdev_unregister(&part->internal.bdev, NULL, NULL);
140 		}
141 	}
142 }
143 
144 static bool
145 spdk_bdev_part_io_type_supported(void *_part, enum spdk_bdev_io_type io_type)
146 {
147 	struct spdk_bdev_part *part = _part;
148 
149 	/* We can't decode/modify passthrough NVMe commands, so don't report
150 	 *  that a partition supports these io types, even if the underlying
151 	 *  bdev does.
152 	 */
153 	switch (io_type) {
154 	case SPDK_BDEV_IO_TYPE_NVME_ADMIN:
155 	case SPDK_BDEV_IO_TYPE_NVME_IO:
156 	case SPDK_BDEV_IO_TYPE_NVME_IO_MD:
157 		return false;
158 	default:
159 		break;
160 	}
161 
162 	return part->internal.base->bdev->fn_table->io_type_supported(part->internal.base->bdev->ctxt,
163 			io_type);
164 }
165 
166 static struct spdk_io_channel *
167 spdk_bdev_part_get_io_channel(void *_part)
168 {
169 	struct spdk_bdev_part *part = _part;
170 
171 	return spdk_get_io_channel(part);
172 }
173 
174 struct spdk_bdev *
175 spdk_bdev_part_get_bdev(struct spdk_bdev_part *part)
176 {
177 	return &part->internal.bdev;
178 }
179 
180 struct spdk_bdev_part_base *
181 spdk_bdev_part_get_base(struct spdk_bdev_part *part)
182 {
183 	return part->internal.base;
184 }
185 
186 struct spdk_bdev *
187 spdk_bdev_part_get_base_bdev(struct spdk_bdev_part *part)
188 {
189 	return part->internal.base->bdev;
190 }
191 
192 uint64_t
193 spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part *part)
194 {
195 	return part->internal.offset_blocks;
196 }
197 
198 static void
199 spdk_bdev_part_complete_io(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
200 {
201 	struct spdk_bdev_io *part_io = cb_arg;
202 	int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
203 
204 	spdk_bdev_io_complete(part_io, status);
205 	spdk_bdev_free_io(bdev_io);
206 }
207 
208 int
209 spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io)
210 {
211 	struct spdk_bdev_part *part = ch->part;
212 	struct spdk_io_channel *base_ch = ch->base_ch;
213 	struct spdk_bdev_desc *base_desc = part->internal.base->desc;
214 	uint64_t offset;
215 	int rc = 0;
216 
217 	/* Modify the I/O to adjust for the offset within the base bdev. */
218 	switch (bdev_io->type) {
219 	case SPDK_BDEV_IO_TYPE_READ:
220 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
221 		if (bdev_io->u.bdev.md_buf == NULL) {
222 			rc = spdk_bdev_readv_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs,
223 						    bdev_io->u.bdev.iovcnt, offset,
224 						    bdev_io->u.bdev.num_blocks,
225 						    spdk_bdev_part_complete_io, bdev_io);
226 		} else {
227 			rc = spdk_bdev_readv_blocks_with_md(base_desc, base_ch,
228 							    bdev_io->u.bdev.iovs,
229 							    bdev_io->u.bdev.iovcnt,
230 							    bdev_io->u.bdev.md_buf, offset,
231 							    bdev_io->u.bdev.num_blocks,
232 							    spdk_bdev_part_complete_io, bdev_io);
233 		}
234 		break;
235 	case SPDK_BDEV_IO_TYPE_WRITE:
236 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
237 		if (bdev_io->u.bdev.md_buf == NULL) {
238 			rc = spdk_bdev_writev_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs,
239 						     bdev_io->u.bdev.iovcnt, offset,
240 						     bdev_io->u.bdev.num_blocks,
241 						     spdk_bdev_part_complete_io, bdev_io);
242 		} else {
243 			rc = spdk_bdev_writev_blocks_with_md(base_desc, base_ch,
244 							     bdev_io->u.bdev.iovs,
245 							     bdev_io->u.bdev.iovcnt,
246 							     bdev_io->u.bdev.md_buf, offset,
247 							     bdev_io->u.bdev.num_blocks,
248 							     spdk_bdev_part_complete_io, bdev_io);
249 		}
250 		break;
251 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
252 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
253 		rc = spdk_bdev_write_zeroes_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
254 						   spdk_bdev_part_complete_io, bdev_io);
255 		break;
256 	case SPDK_BDEV_IO_TYPE_UNMAP:
257 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
258 		rc = spdk_bdev_unmap_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
259 					    spdk_bdev_part_complete_io, bdev_io);
260 		break;
261 	case SPDK_BDEV_IO_TYPE_FLUSH:
262 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
263 		rc = spdk_bdev_flush_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
264 					    spdk_bdev_part_complete_io, bdev_io);
265 		break;
266 	case SPDK_BDEV_IO_TYPE_RESET:
267 		rc = spdk_bdev_reset(base_desc, base_ch,
268 				     spdk_bdev_part_complete_io, bdev_io);
269 		break;
270 	default:
271 		SPDK_ERRLOG("unknown I/O type %d\n", bdev_io->type);
272 		return SPDK_BDEV_IO_STATUS_FAILED;
273 	}
274 
275 	return rc;
276 }
277 
278 static int
279 spdk_bdev_part_channel_create_cb(void *io_device, void *ctx_buf)
280 {
281 	struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device;
282 	struct spdk_bdev_part_channel *ch = ctx_buf;
283 
284 	ch->part = part;
285 	ch->base_ch = spdk_bdev_get_io_channel(part->internal.base->desc);
286 	if (ch->base_ch == NULL) {
287 		return -1;
288 	}
289 
290 	if (part->internal.base->ch_create_cb) {
291 		return part->internal.base->ch_create_cb(io_device, ctx_buf);
292 	} else {
293 		return 0;
294 	}
295 }
296 
297 static void
298 spdk_bdev_part_channel_destroy_cb(void *io_device, void *ctx_buf)
299 {
300 	struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device;
301 	struct spdk_bdev_part_channel *ch = ctx_buf;
302 
303 	if (part->internal.base->ch_destroy_cb) {
304 		part->internal.base->ch_destroy_cb(io_device, ctx_buf);
305 	}
306 	spdk_put_io_channel(ch->base_ch);
307 }
308 
309 struct spdk_bdev_part_base *
310 	spdk_bdev_part_base_construct(struct spdk_bdev *bdev,
311 			      spdk_bdev_remove_cb_t remove_cb, struct spdk_bdev_module *module,
312 			      struct spdk_bdev_fn_table *fn_table, struct bdev_part_tailq *tailq,
313 			      spdk_bdev_part_base_free_fn free_fn, void *ctx,
314 			      uint32_t channel_size, spdk_io_channel_create_cb ch_create_cb,
315 			      spdk_io_channel_destroy_cb ch_destroy_cb)
316 {
317 	int rc;
318 	struct spdk_bdev_part_base *base;
319 
320 	base = calloc(1, sizeof(*base));
321 	if (!base) {
322 		SPDK_ERRLOG("Memory allocation failure\n");
323 		return NULL;
324 	}
325 	fn_table->get_io_channel = spdk_bdev_part_get_io_channel;
326 	fn_table->io_type_supported = spdk_bdev_part_io_type_supported;
327 
328 	base->bdev = bdev;
329 	base->desc = NULL;
330 	base->ref = 0;
331 	base->module = module;
332 	base->fn_table = fn_table;
333 	base->tailq = tailq;
334 	base->base_free_fn = free_fn;
335 	base->ctx = ctx;
336 	base->claimed = false;
337 	base->channel_size = channel_size;
338 	base->ch_create_cb = ch_create_cb;
339 	base->ch_destroy_cb = ch_destroy_cb;
340 
341 	rc = spdk_bdev_open(bdev, false, remove_cb, base, &base->desc);
342 	if (rc) {
343 		spdk_bdev_part_base_free(base);
344 		SPDK_ERRLOG("could not open bdev %s: %s\n", spdk_bdev_get_name(bdev),
345 			    spdk_strerror(-rc));
346 		return NULL;
347 	}
348 
349 	return base;
350 }
351 
352 int
353 spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
354 			 char *name, uint64_t offset_blocks, uint64_t num_blocks,
355 			 char *product_name)
356 {
357 	part->internal.bdev.blocklen = base->bdev->blocklen;
358 	part->internal.bdev.blockcnt = num_blocks;
359 	part->internal.offset_blocks = offset_blocks;
360 
361 	part->internal.bdev.write_cache = base->bdev->write_cache;
362 	part->internal.bdev.required_alignment = base->bdev->required_alignment;
363 	part->internal.bdev.ctxt = part;
364 	part->internal.bdev.module = base->module;
365 	part->internal.bdev.fn_table = base->fn_table;
366 
367 	part->internal.bdev.md_interleave = base->bdev->md_interleave;
368 	part->internal.bdev.md_len = base->bdev->md_len;
369 	part->internal.bdev.dif_type = base->bdev->dif_type;
370 	part->internal.bdev.dif_is_head_of_md = base->bdev->dif_is_head_of_md;
371 	part->internal.bdev.dif_check_flags = base->bdev->dif_check_flags;
372 
373 	part->internal.bdev.name = strdup(name);
374 	part->internal.bdev.product_name = strdup(product_name);
375 
376 	if (part->internal.bdev.name == NULL) {
377 		SPDK_ERRLOG("Failed to allocate name for new part of bdev %s\n", spdk_bdev_get_name(base->bdev));
378 		return -1;
379 	} else if (part->internal.bdev.product_name == NULL) {
380 		free(part->internal.bdev.name);
381 		SPDK_ERRLOG("Failed to allocate product name for new part of bdev %s\n",
382 			    spdk_bdev_get_name(base->bdev));
383 		return -1;
384 	}
385 
386 	__sync_fetch_and_add(&base->ref, 1);
387 	part->internal.base = base;
388 
389 	if (!base->claimed) {
390 		int rc;
391 
392 		rc = spdk_bdev_module_claim_bdev(base->bdev, base->desc, base->module);
393 		if (rc) {
394 			SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(base->bdev));
395 			free(part->internal.bdev.name);
396 			free(part->internal.bdev.product_name);
397 			return -1;
398 		}
399 		base->claimed = true;
400 	}
401 
402 	spdk_io_device_register(part, spdk_bdev_part_channel_create_cb,
403 				spdk_bdev_part_channel_destroy_cb,
404 				base->channel_size,
405 				name);
406 
407 	spdk_bdev_register(&part->internal.bdev);
408 	TAILQ_INSERT_TAIL(base->tailq, part, tailq);
409 
410 	return 0;
411 }
412