xref: /spdk/lib/bdev/part.c (revision bcfd6d0fb47bc29d04d5948fa6f1a8bf8e7aa220)
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 
41 #include "spdk/bdev_module.h"
42 
43 struct spdk_bdev_part_base {
44 	struct spdk_bdev		*bdev;
45 	struct spdk_bdev_desc		*desc;
46 	uint32_t			ref;
47 	uint32_t			channel_size;
48 	spdk_bdev_part_base_free_fn	base_free_fn;
49 	void				*ctx;
50 	bool				claimed;
51 	struct spdk_bdev_module		*module;
52 	struct spdk_bdev_fn_table	*fn_table;
53 	struct bdev_part_tailq		*tailq;
54 	spdk_io_channel_create_cb	ch_create_cb;
55 	spdk_io_channel_destroy_cb	ch_destroy_cb;
56 };
57 
58 struct spdk_bdev *
59 spdk_bdev_part_base_get_bdev(struct spdk_bdev_part_base *part_base)
60 {
61 	return part_base->bdev;
62 }
63 
64 struct spdk_bdev_desc *
65 spdk_bdev_part_base_get_desc(struct spdk_bdev_part_base *part_base)
66 {
67 	return part_base->desc;
68 }
69 
70 struct bdev_part_tailq *
71 spdk_bdev_part_base_get_tailq(struct spdk_bdev_part_base *part_base)
72 {
73 	return part_base->tailq;
74 }
75 
76 void *
77 spdk_bdev_part_base_get_ctx(struct spdk_bdev_part_base *part_base)
78 {
79 	return part_base->ctx;
80 }
81 
82 void
83 spdk_bdev_part_base_free(struct spdk_bdev_part_base *base)
84 {
85 	if (base->desc) {
86 		spdk_bdev_close(base->desc);
87 		base->desc = NULL;
88 	}
89 
90 	if (base->base_free_fn != NULL) {
91 		base->base_free_fn(base->ctx);
92 	}
93 
94 	free(base);
95 }
96 
97 static void
98 spdk_bdev_part_free_cb(void *io_device)
99 {
100 	struct spdk_bdev_part *part = io_device;
101 	struct spdk_bdev_part_base *base;
102 
103 	assert(part);
104 	assert(part->internal.base);
105 
106 	base = part->internal.base;
107 
108 	TAILQ_REMOVE(base->tailq, part, tailq);
109 
110 	if (__sync_sub_and_fetch(&base->ref, 1) == 0) {
111 		spdk_bdev_module_release_bdev(base->bdev);
112 		spdk_bdev_part_base_free(base);
113 	}
114 
115 	spdk_bdev_destruct_done(&part->internal.bdev, 0);
116 	free(part->internal.bdev.name);
117 	free(part);
118 }
119 
120 int
121 spdk_bdev_part_free(struct spdk_bdev_part *part)
122 {
123 	spdk_io_device_unregister(part, spdk_bdev_part_free_cb);
124 
125 	/* Return 1 to indicate that this is an asynchronous operation that isn't complete
126 	 * until spdk_bdev_destruct_done is called */
127 	return 1;
128 }
129 
130 void
131 spdk_bdev_part_base_hotremove(struct spdk_bdev *base_bdev, struct bdev_part_tailq *tailq)
132 {
133 	struct spdk_bdev_part *part, *tmp;
134 
135 	TAILQ_FOREACH_SAFE(part, tailq, tailq, tmp) {
136 		if (part->internal.base->bdev == base_bdev) {
137 			spdk_bdev_unregister(&part->internal.bdev, NULL, NULL);
138 		}
139 	}
140 }
141 
142 static bool
143 spdk_bdev_part_io_type_supported(void *_part, enum spdk_bdev_io_type io_type)
144 {
145 	struct spdk_bdev_part *part = _part;
146 
147 	return part->internal.base->bdev->fn_table->io_type_supported(part->internal.base->bdev, io_type);
148 }
149 
150 static struct spdk_io_channel *
151 spdk_bdev_part_get_io_channel(void *_part)
152 {
153 	struct spdk_bdev_part *part = _part;
154 
155 	return spdk_get_io_channel(part);
156 }
157 
158 struct spdk_bdev *
159 spdk_bdev_part_get_bdev(struct spdk_bdev_part *part)
160 {
161 	return &part->internal.bdev;
162 }
163 
164 struct spdk_bdev_part_base *
165 spdk_bdev_part_get_base(struct spdk_bdev_part *part)
166 {
167 	return part->internal.base;
168 }
169 
170 struct spdk_bdev *
171 spdk_bdev_part_get_base_bdev(struct spdk_bdev_part *part)
172 {
173 	return part->internal.base->bdev;
174 }
175 
176 uint64_t
177 spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part *part)
178 {
179 	return part->internal.offset_blocks;
180 }
181 
182 static void
183 spdk_bdev_part_complete_io(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
184 {
185 	struct spdk_bdev_io *part_io = cb_arg;
186 	int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
187 
188 	spdk_bdev_io_complete(part_io, status);
189 	spdk_bdev_free_io(bdev_io);
190 }
191 
192 void
193 spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io)
194 {
195 	struct spdk_bdev_part *part = ch->part;
196 	struct spdk_io_channel *base_ch = ch->base_ch;
197 	struct spdk_bdev_desc *base_desc = part->internal.base->desc;
198 	uint64_t offset;
199 	int rc = 0;
200 
201 	/* Modify the I/O to adjust for the offset within the base bdev. */
202 	switch (bdev_io->type) {
203 	case SPDK_BDEV_IO_TYPE_READ:
204 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
205 		rc = spdk_bdev_readv_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs,
206 					    bdev_io->u.bdev.iovcnt, offset,
207 					    bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io,
208 					    bdev_io);
209 		break;
210 	case SPDK_BDEV_IO_TYPE_WRITE:
211 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
212 		rc = spdk_bdev_writev_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs,
213 					     bdev_io->u.bdev.iovcnt, offset,
214 					     bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io,
215 					     bdev_io);
216 		break;
217 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
218 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
219 		rc = spdk_bdev_write_zeroes_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
220 						   spdk_bdev_part_complete_io, bdev_io);
221 		break;
222 	case SPDK_BDEV_IO_TYPE_UNMAP:
223 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
224 		rc = spdk_bdev_unmap_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
225 					    spdk_bdev_part_complete_io, bdev_io);
226 		break;
227 	case SPDK_BDEV_IO_TYPE_FLUSH:
228 		offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks;
229 		rc = spdk_bdev_flush_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks,
230 					    spdk_bdev_part_complete_io, bdev_io);
231 		break;
232 	case SPDK_BDEV_IO_TYPE_RESET:
233 		rc = spdk_bdev_reset(base_desc, base_ch,
234 				     spdk_bdev_part_complete_io, bdev_io);
235 		break;
236 	default:
237 		SPDK_ERRLOG("split: unknown I/O type %d\n", bdev_io->type);
238 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
239 		return;
240 	}
241 
242 	if (rc != 0) {
243 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
244 	}
245 }
246 static int
247 spdk_bdev_part_channel_create_cb(void *io_device, void *ctx_buf)
248 {
249 	struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device;
250 	struct spdk_bdev_part_channel *ch = ctx_buf;
251 
252 	ch->part = part;
253 	ch->base_ch = spdk_bdev_get_io_channel(part->internal.base->desc);
254 	if (ch->base_ch == NULL) {
255 		return -1;
256 	}
257 
258 	if (part->internal.base->ch_create_cb) {
259 		return part->internal.base->ch_create_cb(io_device, ctx_buf);
260 	} else {
261 		return 0;
262 	}
263 }
264 
265 static void
266 spdk_bdev_part_channel_destroy_cb(void *io_device, void *ctx_buf)
267 {
268 	struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device;
269 	struct spdk_bdev_part_channel *ch = ctx_buf;
270 
271 	if (part->internal.base->ch_destroy_cb) {
272 		part->internal.base->ch_destroy_cb(io_device, ctx_buf);
273 	}
274 	spdk_put_io_channel(ch->base_ch);
275 }
276 
277 struct spdk_bdev_part_base *
278 	spdk_bdev_part_base_construct(struct spdk_bdev *bdev,
279 			      spdk_bdev_remove_cb_t remove_cb, struct spdk_bdev_module *module,
280 			      struct spdk_bdev_fn_table *fn_table, struct bdev_part_tailq *tailq,
281 			      spdk_bdev_part_base_free_fn free_fn, void *ctx,
282 			      uint32_t channel_size, spdk_io_channel_create_cb ch_create_cb,
283 			      spdk_io_channel_destroy_cb ch_destroy_cb)
284 {
285 	int rc;
286 	struct spdk_bdev_part_base *base;
287 
288 	base = calloc(1, sizeof(*base));
289 	if (!base) {
290 		SPDK_ERRLOG("Memory allocation failure\n");
291 		return NULL;
292 	}
293 	fn_table->get_io_channel = spdk_bdev_part_get_io_channel;
294 	fn_table->io_type_supported = spdk_bdev_part_io_type_supported;
295 
296 	base->bdev = bdev;
297 	base->desc = NULL;
298 	base->ref = 0;
299 	base->module = module;
300 	base->fn_table = fn_table;
301 	base->tailq = tailq;
302 	base->base_free_fn = free_fn;
303 	base->ctx = ctx;
304 	base->claimed = false;
305 	base->channel_size = channel_size;
306 	base->ch_create_cb = ch_create_cb;
307 	base->ch_destroy_cb = ch_destroy_cb;
308 
309 	rc = spdk_bdev_open(bdev, false, remove_cb, bdev, &base->desc);
310 	if (rc) {
311 		spdk_bdev_part_base_free(base);
312 		SPDK_ERRLOG("could not open bdev %s\n", spdk_bdev_get_name(bdev));
313 		return NULL;
314 	}
315 
316 	return base;
317 }
318 
319 int
320 spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
321 			 char *name, uint64_t offset_blocks, uint64_t num_blocks,
322 			 char *product_name)
323 {
324 	part->internal.bdev.name = name;
325 	part->internal.bdev.blocklen = base->bdev->blocklen;
326 	part->internal.bdev.blockcnt = num_blocks;
327 	part->internal.offset_blocks = offset_blocks;
328 
329 	part->internal.bdev.write_cache = base->bdev->write_cache;
330 	part->internal.bdev.need_aligned_buffer = base->bdev->need_aligned_buffer;
331 	part->internal.bdev.product_name = product_name;
332 	part->internal.bdev.ctxt = part;
333 	part->internal.bdev.module = base->module;
334 	part->internal.bdev.fn_table = base->fn_table;
335 
336 	__sync_fetch_and_add(&base->ref, 1);
337 	part->internal.base = base;
338 
339 	if (!base->claimed) {
340 		int rc;
341 
342 		rc = spdk_bdev_module_claim_bdev(base->bdev, base->desc, base->module);
343 		if (rc) {
344 			SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(base->bdev));
345 			free(part->internal.bdev.name);
346 			return -1;
347 		}
348 		base->claimed = true;
349 	}
350 
351 	spdk_io_device_register(part, spdk_bdev_part_channel_create_cb,
352 				spdk_bdev_part_channel_destroy_cb,
353 				base->channel_size);
354 	spdk_vbdev_register(&part->internal.bdev, &base->bdev, 1);
355 	TAILQ_INSERT_TAIL(base->tailq, part, tailq);
356 
357 	return 0;
358 }
359