xref: /spdk/lib/lvol/lvol.c (revision eb8b1e20a9c8a6bc79f32fde8693d2791a74c34d)
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 #include "spdk_internal/lvolstore.h"
35 #include "spdk_internal/log.h"
36 #include "spdk/string.h"
37 #include "spdk/io_channel.h"
38 
39 /* Length of string returned from uuid_unparse() */
40 #define UUID_STRING_LEN 37
41 
42 SPDK_LOG_REGISTER_TRACE_FLAG("lvol", SPDK_TRACE_LVOL)
43 
44 static inline size_t
45 divide_round_up(size_t num, size_t divisor)
46 {
47 	return (num + divisor - 1) / divisor;
48 }
49 
50 static void
51 _spdk_super_create_close_cb(void *cb_arg, int lvolerrno)
52 {
53 	struct spdk_lvs_with_handle_req *req = cb_arg;
54 	struct spdk_lvol_store *lvs = req->lvol_store;
55 
56 	if (lvolerrno < 0) {
57 		SPDK_ERRLOG("Lvol store init failed: could not close super blob\n");
58 		req->cb_fn(req->cb_arg, NULL, lvolerrno);
59 		free(lvs);
60 		free(req);
61 		return;
62 	}
63 
64 	req->cb_fn(req->cb_arg, lvs, lvolerrno);
65 	free(req);
66 }
67 
68 static void
69 _spdk_super_blob_set_cb(void *cb_arg, int lvolerrno)
70 {
71 	struct spdk_lvs_with_handle_req *req = cb_arg;
72 	struct spdk_lvol_store *lvs = req->lvol_store;
73 	struct spdk_blob *blob = lvs->super_blob;
74 
75 	if (lvolerrno < 0) {
76 		req->cb_fn(req->cb_arg, NULL, lvolerrno);
77 		SPDK_ERRLOG("Lvol store init failed: could not set uuid for super blob\n");
78 		free(lvs);
79 		free(req);
80 		return;
81 	}
82 
83 	spdk_bs_md_close_blob(&blob, _spdk_super_create_close_cb, req);
84 }
85 
86 static void
87 _spdk_super_blob_init_cb(void *cb_arg, int lvolerrno)
88 {
89 	struct spdk_lvs_with_handle_req *req = cb_arg;
90 	struct spdk_lvol_store *lvs = req->lvol_store;
91 	struct spdk_blob *blob = lvs->super_blob;
92 	char uuid[UUID_STRING_LEN];
93 
94 	if (lvolerrno < 0) {
95 		req->cb_fn(req->cb_arg, NULL, lvolerrno);
96 		SPDK_ERRLOG("Lvol store init failed: could not set super blob\n");
97 		free(lvs);
98 		free(req);
99 		return;
100 	}
101 
102 	uuid_unparse(lvs->uuid, uuid);
103 
104 	spdk_blob_md_set_xattr(blob, "uuid", uuid, UUID_STRING_LEN);
105 	spdk_bs_md_sync_blob(blob, _spdk_super_blob_set_cb, req);
106 }
107 
108 static void
109 _spdk_super_blob_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
110 {
111 	struct spdk_lvs_with_handle_req *req = cb_arg;
112 	struct spdk_lvol_store *lvs = req->lvol_store;
113 
114 	if (lvolerrno < 0) {
115 		req->cb_fn(req->cb_arg, NULL, lvolerrno);
116 		SPDK_ERRLOG("Lvol store init failed: could not open super blob\n");
117 		free(lvs);
118 		free(req);
119 		return;
120 	}
121 
122 	lvs->super_blob = blob;
123 	lvs->super_blob_id = spdk_blob_get_id(blob);
124 
125 	spdk_bs_set_super(lvs->blobstore, lvs->super_blob_id, _spdk_super_blob_init_cb, req);
126 }
127 
128 static void
129 _spdk_super_blob_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
130 {
131 	struct spdk_lvs_with_handle_req *req = cb_arg;
132 	struct spdk_lvol_store *lvs = req->lvol_store;
133 	struct spdk_blob_store *bs;
134 
135 	if (lvolerrno < 0) {
136 		req->cb_fn(req->cb_arg, NULL, lvolerrno);
137 		SPDK_ERRLOG("Lvol store init failed: could not create super blob\n");
138 		free(lvs);
139 		free(req);
140 		return;
141 	}
142 
143 	bs = req->lvol_store->blobstore;
144 
145 	spdk_bs_md_open_blob(bs, blobid, _spdk_super_blob_create_open_cb, req);
146 }
147 
148 static void
149 _spdk_lvs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int lvserrno)
150 {
151 	struct spdk_lvs_with_handle_req *lvs_req = cb_arg;
152 	struct spdk_lvol_store *lvs = lvs_req->lvol_store;
153 
154 	if (lvserrno != 0) {
155 		assert(bs == NULL);
156 		lvs_req->cb_fn(lvs_req->cb_arg, NULL, lvserrno);
157 		SPDK_ERRLOG("Lvol store init failed: could not initialize blobstore\n");
158 		free(lvs);
159 		free(lvs_req);
160 		return;
161 	}
162 
163 	assert(bs != NULL);
164 	lvs->blobstore = bs;
165 	TAILQ_INIT(&lvs->lvols);
166 	lvs->total_blocks = (spdk_bs_get_cluster_size(bs) * spdk_bs_free_cluster_count(
167 				     bs)) / spdk_bs_get_page_size(bs);
168 
169 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store initialized\n");
170 
171 	/* create super blob */
172 	spdk_bs_md_create_blob(lvs->blobstore, _spdk_super_blob_create_cb, lvs_req);
173 }
174 
175 static void
176 spdk_setup_lvs_opts(struct spdk_bs_opts *bs_opts, struct spdk_lvs_opts *o)
177 {
178 	spdk_bs_opts_init(bs_opts);
179 	if (o) {
180 		bs_opts->cluster_sz = o->cluster_sz;
181 	} else {
182 		bs_opts->cluster_sz = SPDK_LVS_OPTS_CLUSTER_SZ;
183 	}
184 }
185 
186 int
187 spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o,
188 	      spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
189 {
190 	struct spdk_lvol_store *lvs;
191 	struct spdk_lvs_with_handle_req *lvs_req;
192 	struct spdk_bs_opts opts;
193 
194 	if (bs_dev == NULL) {
195 		SPDK_ERRLOG("Blobstore device does not exist\n");
196 		return -ENODEV;
197 	}
198 
199 	spdk_setup_lvs_opts(&opts, o);
200 
201 	lvs = calloc(1, sizeof(*lvs));
202 	if (!lvs) {
203 		SPDK_ERRLOG("Cannot alloc memory for lvol store base pointer\n");
204 		return -ENOMEM;
205 	}
206 
207 	uuid_generate_time(lvs->uuid);
208 
209 	lvs_req = calloc(1, sizeof(*lvs_req));
210 	if (!lvs_req) {
211 		free(lvs);
212 		SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
213 		return -ENOMEM;
214 	}
215 
216 	assert(cb_fn != NULL);
217 	lvs_req->cb_fn = cb_fn;
218 	lvs_req->cb_arg = cb_arg;
219 	lvs_req->lvol_store = lvs;
220 	lvs->bs_dev = bs_dev;
221 
222 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Initializing lvol store\n");
223 	spdk_bs_init(bs_dev, &opts, _spdk_lvs_init_cb, lvs_req);
224 
225 	return 0;
226 }
227 
228 static void
229 _lvs_unload_cb(void *cb_arg, int lvserrno)
230 {
231 	struct spdk_lvs_req *lvs_req = cb_arg;
232 
233 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store unloaded\n");
234 	assert(lvs_req->cb_fn != NULL);
235 	lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
236 	free(lvs_req);
237 }
238 
239 int
240 spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
241 		void *cb_arg)
242 {
243 	struct spdk_lvs_req *lvs_req;
244 
245 	if (lvs == NULL) {
246 		SPDK_ERRLOG("Lvol store is NULL\n");
247 		return -ENODEV;
248 	}
249 
250 	if (!TAILQ_EMPTY(&lvs->lvols)) {
251 		SPDK_ERRLOG("Lvols still open on lvol store\n");
252 		return -EBUSY;
253 	}
254 
255 	lvs_req = calloc(1, sizeof(*lvs_req));
256 	if (!lvs_req) {
257 		SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
258 		return -ENOMEM;
259 	}
260 
261 	lvs_req->cb_fn = cb_fn;
262 	lvs_req->cb_arg = cb_arg;
263 
264 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Unloading lvol store\n");
265 	spdk_bs_unload(lvs->blobstore, _lvs_unload_cb, lvs_req);
266 	free(lvs);
267 
268 	return 0;
269 }
270 
271 static void
272 _spdk_lvol_return_to_caller(void *cb_arg, int lvolerrno)
273 {
274 	struct spdk_lvol_with_handle_req *req = cb_arg;
275 
276 	assert(req->cb_fn != NULL);
277 	req->cb_fn(req->cb_arg, req->lvol, lvolerrno);
278 	free(req);
279 }
280 
281 static void
282 _spdk_lvs_destruct_cb(void *cb_arg, int lvserrno)
283 {
284 	struct spdk_lvs_req *req = cb_arg;
285 
286 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store bdev deleted\n");
287 
288 	if (req->cb_fn != NULL)
289 		req->cb_fn(req->cb_arg, lvserrno);
290 	free(req);
291 }
292 
293 static void
294 _spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno)
295 {
296 	struct spdk_lvol *lvol = cb_arg;
297 
298 	if (lvolerrno < 0) {
299 		SPDK_ERRLOG("Could not close blob on lvol\n");
300 		free(lvol->name);
301 		free(lvol);
302 		return;
303 	}
304 
305 	if (lvol->lvol_store->destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) {
306 		spdk_lvs_unload(lvol->lvol_store, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req);
307 	}
308 
309 	free(lvol->name);
310 	free(lvol);
311 
312 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Blob closed on lvol\n");
313 }
314 
315 static void
316 _spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno)
317 {
318 	struct spdk_lvol *lvol = cb_arg;
319 	struct spdk_blob_store *bs = lvol->lvol_store->blobstore;
320 
321 	if (lvolerrno < 0) {
322 		SPDK_ERRLOG("Could not delete blob on lvol\n");
323 		free(lvol->name);
324 		free(lvol);
325 		return;
326 	}
327 	SPDK_INFOLOG(SPDK_TRACE_LVOL, "Blob closed on lvol\n");
328 	spdk_bs_md_delete_blob(bs, lvol->blob_id, _spdk_lvol_close_blob_cb, lvol);
329 }
330 
331 static void
332 _spdk_lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
333 {
334 	struct spdk_lvol_with_handle_req *req = cb_arg;
335 	spdk_blob_id blob_id = spdk_blob_get_id(blob);
336 	struct spdk_lvol *lvol = req->lvol;
337 	char uuid[UUID_STRING_LEN];
338 
339 	if (lvolerrno < 0) {
340 		free(lvol);
341 		goto invalid;
342 	}
343 
344 	lvol->blob = blob;
345 	lvol->blob_id = blob_id;
346 
347 	uuid_unparse(lvol->lvol_store->uuid, uuid);
348 	lvol->name = spdk_sprintf_alloc("%s_%"PRIu64, uuid, (uint64_t)blob_id);
349 	if (!lvol->name) {
350 		spdk_bs_md_close_blob(&blob, _spdk_lvol_delete_blob_cb, lvol);
351 		SPDK_ERRLOG("Cannot alloc memory for lvol name\n");
352 		lvolerrno = -ENOMEM;
353 		goto invalid;
354 	}
355 
356 	lvolerrno = spdk_bs_md_resize_blob(blob, lvol->num_clusters);
357 	if (lvolerrno < 0) {
358 		spdk_bs_md_close_blob(&blob, _spdk_lvol_delete_blob_cb, lvol);
359 		goto invalid;
360 	}
361 
362 	TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
363 
364 	spdk_bs_md_sync_blob(blob, _spdk_lvol_return_to_caller, req);
365 
366 	return;
367 
368 invalid:
369 	assert(req->cb_fn != NULL);
370 	req->cb_fn(req->cb_arg, NULL, lvolerrno);
371 	free(req);
372 }
373 
374 static void
375 _spdk_lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
376 {
377 	struct spdk_lvol_with_handle_req *req = cb_arg;
378 	struct spdk_blob_store *bs;
379 
380 	if (lvolerrno < 0) {
381 		free(req->lvol);
382 		assert(req->cb_fn != NULL);
383 		req->cb_fn(req->cb_arg, NULL, lvolerrno);
384 		free(req);
385 		return;
386 	}
387 
388 	bs = req->lvol->lvol_store->blobstore;
389 
390 	spdk_bs_md_open_blob(bs, blobid, _spdk_lvol_create_open_cb, req);
391 }
392 
393 int
394 spdk_lvol_create(struct spdk_lvol_store *lvs, uint64_t sz,
395 		 spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
396 {
397 	struct spdk_lvol_with_handle_req *req;
398 	struct spdk_blob_store *bs;
399 	struct spdk_lvol *lvol;
400 	uint64_t num_clusters, free_clusters;
401 
402 	if (lvs == NULL) {
403 		SPDK_ERRLOG("lvol store does not exist\n");
404 		return -ENODEV;
405 	}
406 	bs = lvs->blobstore;
407 
408 	num_clusters = divide_round_up(sz, spdk_bs_get_cluster_size(bs));
409 	free_clusters = spdk_bs_free_cluster_count(bs);
410 	if (num_clusters > free_clusters) {
411 		SPDK_ERRLOG("Not enough free clusters left (%zu) on lvol store to add lvol %zu clusters\n",
412 			    free_clusters, num_clusters);
413 		return -ENOMEM;
414 	}
415 
416 	req = calloc(1, sizeof(*req));
417 	if (!req) {
418 		SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
419 		return -ENOMEM;
420 	}
421 	req->cb_fn = cb_fn;
422 	req->cb_arg = cb_arg;
423 
424 	lvol = calloc(1, sizeof(*lvol));
425 	if (!lvol) {
426 		free(req);
427 		SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
428 		return -ENOMEM;
429 	}
430 
431 	lvol->lvol_store = lvs;
432 	lvol->num_clusters = num_clusters;
433 	lvol->close_only = false;
434 	req->lvol = lvol;
435 
436 	spdk_bs_md_create_blob(lvs->blobstore, _spdk_lvol_create_cb, req);
437 
438 	return 0;
439 }
440 
441 static void
442 _spdk_lvol_resize_cb(void *cb_arg, int lvolerrno)
443 {
444 	struct spdk_lvol_req *req = cb_arg;
445 
446 	req->cb_fn(req->cb_arg,  lvolerrno);
447 	free(req);
448 }
449 
450 int
451 spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz,
452 		 spdk_lvol_op_complete cb_fn, void *cb_arg)
453 {
454 	int rc;
455 	struct spdk_blob *blob = lvol->blob;
456 	struct spdk_lvol_store *lvs = lvol->lvol_store;
457 	struct spdk_lvol_req *req;
458 	uint64_t free_clusters = spdk_bs_free_cluster_count(lvs->blobstore);
459 	uint64_t used_clusters = lvol->num_clusters;
460 	uint64_t new_clusters = divide_round_up(sz, spdk_bs_get_cluster_size(lvs->blobstore));
461 
462 	/* Check if size of lvol increasing */
463 	if (new_clusters > used_clusters) {
464 		/* Check if there is enough clusters left to resize */
465 		if (new_clusters - used_clusters > free_clusters) {
466 			SPDK_ERRLOG("Not enough free clusters left on lvol store to resize lvol to %zu clusters\n", sz);
467 			return -ENOMEM;
468 		}
469 	}
470 
471 	req = calloc(1, sizeof(*req));
472 	if (!req) {
473 		SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
474 		return -ENOMEM;
475 	}
476 	req->cb_fn = cb_fn;
477 	req->cb_arg = cb_arg;
478 
479 	rc = spdk_bs_md_resize_blob(blob, sz);
480 	if (rc < 0) {
481 		goto invalid;
482 	}
483 
484 	lvol->num_clusters = new_clusters;
485 
486 	spdk_blob_md_set_xattr(blob, "length", &sz, sizeof(sz));
487 
488 	spdk_bs_md_sync_blob(blob, _spdk_lvol_resize_cb, req);
489 
490 	return rc;
491 
492 invalid:
493 	req->cb_fn(req->cb_arg, rc);
494 	free(req);
495 	return rc;
496 }
497 
498 void
499 spdk_lvol_destroy(struct spdk_lvol *lvol)
500 {
501 	if (lvol == NULL) {
502 		SPDK_ERRLOG("lvol does not exist\n");
503 		return;
504 	}
505 
506 	TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
507 	spdk_bs_md_close_blob(&(lvol->blob), _spdk_lvol_delete_blob_cb, lvol);
508 }
509 
510 void
511 spdk_lvol_close(struct spdk_lvol *lvol)
512 {
513 	if (lvol == NULL) {
514 		SPDK_ERRLOG("lvol does not exist\n");
515 		return;
516 	}
517 
518 	TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
519 	spdk_bs_md_close_blob(&(lvol->blob), _spdk_lvol_close_blob_cb, lvol);
520 }
521 
522 struct spdk_io_channel *
523 spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
524 {
525 	return spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
526 }
527