xref: /spdk/lib/bdev/part.c (revision bb488d2829a9b7863daab45917dd2174905cc0ae)
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 	return part->internal.base->bdev->fn_table->io_type_supported(part->internal.base->bdev->ctxt,
150 			io_type);
151 }
152 
153 static struct spdk_io_channel *
154 spdk_bdev_part_get_io_channel(void *_part)
155 {
156 	struct spdk_bdev_part *part = _part;
157 
158 	return spdk_get_io_channel(part);
159 }
160 
161 struct spdk_bdev *
162 spdk_bdev_part_get_bdev(struct spdk_bdev_part *part)
163 {
164 	return &part->internal.bdev;
165 }
166 
167 struct spdk_bdev_part_base *
168 spdk_bdev_part_get_base(struct spdk_bdev_part *part)
169 {
170 	return part->internal.base;
171 }
172 
173 struct spdk_bdev *
174 spdk_bdev_part_get_base_bdev(struct spdk_bdev_part *part)
175 {
176 	return part->internal.base->bdev;
177 }
178 
179 uint64_t
180 spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part *part)
181 {
182 	return part->internal.offset_blocks;
183 }
184 
185 static void
186 spdk_bdev_part_complete_io(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
187 {
188 	struct spdk_bdev_io *part_io = cb_arg;
189 	int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
190 
191 	spdk_bdev_io_complete(part_io, status);
192 	spdk_bdev_free_io(bdev_io);
193 }
194 
195 int
196 spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io)
197 {
198 	struct spdk_bdev_part *part = ch->part;
199 	struct spdk_io_channel *base_ch = ch->base_ch;
200 	struct spdk_bdev_desc *base_desc = part->internal.base->desc;
201 	uint64_t offset;
202 	int rc = 0;
203 
204 	/* Modify the I/O to adjust for the offset within the base bdev. */
205 	switch (bdev_io->type) {
206 	case SPDK_BDEV_IO_TYPE_READ:
207 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
208 		rc = spdk_bdev_readv_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs,
209 					    bdev_io->u.bdev.iovcnt, offset,
210 					    bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io,
211 					    bdev_io);
212 		break;
213 	case SPDK_BDEV_IO_TYPE_WRITE:
214 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
215 		rc = spdk_bdev_writev_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs,
216 					     bdev_io->u.bdev.iovcnt, offset,
217 					     bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io,
218 					     bdev_io);
219 		break;
220 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
221 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
222 		rc = spdk_bdev_write_zeroes_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
223 						   spdk_bdev_part_complete_io, bdev_io);
224 		break;
225 	case SPDK_BDEV_IO_TYPE_UNMAP:
226 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
227 		rc = spdk_bdev_unmap_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
228 					    spdk_bdev_part_complete_io, bdev_io);
229 		break;
230 	case SPDK_BDEV_IO_TYPE_FLUSH:
231 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
232 		rc = spdk_bdev_flush_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
233 					    spdk_bdev_part_complete_io, bdev_io);
234 		break;
235 	case SPDK_BDEV_IO_TYPE_RESET:
236 		rc = spdk_bdev_reset(base_desc, base_ch,
237 				     spdk_bdev_part_complete_io, bdev_io);
238 		break;
239 	default:
240 		SPDK_ERRLOG("split: unknown I/O type %d\n", bdev_io->type);
241 		return SPDK_BDEV_IO_STATUS_FAILED;
242 	}
243 
244 	return rc;
245 }
246 
247 static int
248 spdk_bdev_part_channel_create_cb(void *io_device, void *ctx_buf)
249 {
250 	struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device;
251 	struct spdk_bdev_part_channel *ch = ctx_buf;
252 
253 	ch->part = part;
254 	ch->base_ch = spdk_bdev_get_io_channel(part->internal.base->desc);
255 	if (ch->base_ch == NULL) {
256 		return -1;
257 	}
258 
259 	if (part->internal.base->ch_create_cb) {
260 		return part->internal.base->ch_create_cb(io_device, ctx_buf);
261 	} else {
262 		return 0;
263 	}
264 }
265 
266 static void
267 spdk_bdev_part_channel_destroy_cb(void *io_device, void *ctx_buf)
268 {
269 	struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device;
270 	struct spdk_bdev_part_channel *ch = ctx_buf;
271 
272 	if (part->internal.base->ch_destroy_cb) {
273 		part->internal.base->ch_destroy_cb(io_device, ctx_buf);
274 	}
275 	spdk_put_io_channel(ch->base_ch);
276 }
277 
278 struct spdk_bdev_part_base *
279 	spdk_bdev_part_base_construct(struct spdk_bdev *bdev,
280 			      spdk_bdev_remove_cb_t remove_cb, struct spdk_bdev_module *module,
281 			      struct spdk_bdev_fn_table *fn_table, struct bdev_part_tailq *tailq,
282 			      spdk_bdev_part_base_free_fn free_fn, void *ctx,
283 			      uint32_t channel_size, spdk_io_channel_create_cb ch_create_cb,
284 			      spdk_io_channel_destroy_cb ch_destroy_cb)
285 {
286 	int rc;
287 	struct spdk_bdev_part_base *base;
288 
289 	base = calloc(1, sizeof(*base));
290 	if (!base) {
291 		SPDK_ERRLOG("Memory allocation failure\n");
292 		return NULL;
293 	}
294 	fn_table->get_io_channel = spdk_bdev_part_get_io_channel;
295 	fn_table->io_type_supported = spdk_bdev_part_io_type_supported;
296 
297 	base->bdev = bdev;
298 	base->desc = NULL;
299 	base->ref = 0;
300 	base->module = module;
301 	base->fn_table = fn_table;
302 	base->tailq = tailq;
303 	base->base_free_fn = free_fn;
304 	base->ctx = ctx;
305 	base->claimed = false;
306 	base->channel_size = channel_size;
307 	base->ch_create_cb = ch_create_cb;
308 	base->ch_destroy_cb = ch_destroy_cb;
309 
310 	rc = spdk_bdev_open(bdev, false, remove_cb, base, &base->desc);
311 	if (rc) {
312 		spdk_bdev_part_base_free(base);
313 		SPDK_ERRLOG("could not open bdev %s: %s\n", spdk_bdev_get_name(bdev),
314 			    spdk_strerror(-rc));
315 		return NULL;
316 	}
317 
318 	return base;
319 }
320 
321 int
322 spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
323 			 char *name, uint64_t offset_blocks, uint64_t num_blocks,
324 			 char *product_name)
325 {
326 	part->internal.bdev.blocklen = base->bdev->blocklen;
327 	part->internal.bdev.blockcnt = num_blocks;
328 	part->internal.offset_blocks = offset_blocks;
329 
330 	part->internal.bdev.write_cache = base->bdev->write_cache;
331 	part->internal.bdev.required_alignment = base->bdev->required_alignment;
332 	part->internal.bdev.ctxt = part;
333 	part->internal.bdev.module = base->module;
334 	part->internal.bdev.fn_table = base->fn_table;
335 
336 	part->internal.bdev.name = strdup(name);
337 	part->internal.bdev.product_name = strdup(product_name);
338 
339 	if (part->internal.bdev.name == NULL) {
340 		SPDK_ERRLOG("Failed to allocate name for new part of bdev %s\n", spdk_bdev_get_name(base->bdev));
341 		return -1;
342 	} else if (part->internal.bdev.product_name == NULL) {
343 		free(part->internal.bdev.name);
344 		SPDK_ERRLOG("Failed to allocate product name for new part of bdev %s\n",
345 			    spdk_bdev_get_name(base->bdev));
346 		return -1;
347 	}
348 
349 	__sync_fetch_and_add(&base->ref, 1);
350 	part->internal.base = base;
351 
352 	if (!base->claimed) {
353 		int rc;
354 
355 		rc = spdk_bdev_module_claim_bdev(base->bdev, base->desc, base->module);
356 		if (rc) {
357 			SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(base->bdev));
358 			free(part->internal.bdev.name);
359 			free(part->internal.bdev.product_name);
360 			return -1;
361 		}
362 		base->claimed = true;
363 	}
364 
365 	spdk_io_device_register(part, spdk_bdev_part_channel_create_cb,
366 				spdk_bdev_part_channel_destroy_cb,
367 				base->channel_size,
368 				name);
369 
370 	spdk_bdev_register(&part->internal.bdev);
371 	TAILQ_INSERT_TAIL(base->tailq, part, tailq);
372 
373 	return 0;
374 }
375