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