1 /* nbdkit
2 * Copyright (C) 2013-2020 Red Hat Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <config.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <inttypes.h>
40 #include <assert.h>
41 #include <errno.h>
42 #include <sys/socket.h>
43
44 #include "internal.h"
45 #include "minmax.h"
46
47 /* We extend the generic backend struct with extra fields relating
48 * to this plugin.
49 */
50 struct backend_plugin {
51 struct backend backend;
52 struct nbdkit_plugin plugin;
53 };
54
55 static void
plugin_free(struct backend * b)56 plugin_free (struct backend *b)
57 {
58 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
59
60 backend_unload (b, p->plugin.unload);
61 free (p);
62 }
63
64 static int
plugin_thread_model(struct backend * b)65 plugin_thread_model (struct backend *b)
66 {
67 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
68 int model = p->plugin._thread_model;
69 int r;
70
71 #if !(defined SOCK_CLOEXEC && defined HAVE_MKOSTEMP && defined HAVE_PIPE2 && \
72 defined HAVE_ACCEPT4)
73 if (model > NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS) {
74 debug ("system lacks atomic CLOEXEC, serializing to avoid fd leaks");
75 model = NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS;
76 }
77 #endif
78
79 if (p->plugin.thread_model) {
80 r = p->plugin.thread_model ();
81 if (r == -1)
82 exit (EXIT_FAILURE);
83 if (r < model)
84 model = r;
85 }
86
87 return model;
88 }
89
90 static const char *
plugin_name(struct backend * b)91 plugin_name (struct backend *b)
92 {
93 return b->name;
94 }
95
96 static void
plugin_usage(struct backend * b)97 plugin_usage (struct backend *b)
98 {
99 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
100 const char *t;
101
102 printf ("plugin: %s", b->name);
103 if (p->plugin.longname)
104 printf (" (%s)", p->plugin.longname);
105 printf ("\n");
106 printf ("(%s)\n", b->filename);
107 if (p->plugin.description) {
108 printf ("%s", p->plugin.description);
109 if ((t = strrchr (p->plugin.description, '\n')) == NULL || t[1])
110 printf ("\n");
111 }
112 if (p->plugin.config_help) {
113 printf ("%s", p->plugin.config_help);
114 if ((t = strrchr (p->plugin.config_help, '\n')) == NULL || t[1])
115 printf ("\n");
116 }
117 }
118
119 static const char *
plugin_version(struct backend * b)120 plugin_version (struct backend *b)
121 {
122 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
123
124 return p->plugin.version;
125 }
126
127 /* This implements the --dump-plugin option. */
128 static void
plugin_dump_fields(struct backend * b)129 plugin_dump_fields (struct backend *b)
130 {
131 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
132 char *path;
133
134 path = nbdkit_realpath (b->filename);
135 printf ("path=%s\n", path);
136 free (path);
137
138 printf ("name=%s\n", b->name);
139 if (p->plugin.version)
140 printf ("version=%s\n", p->plugin.version);
141
142 printf ("api_version=%d\n", p->plugin._api_version);
143 printf ("struct_size=%" PRIu64 "\n", p->plugin._struct_size);
144 printf ("max_thread_model=%s\n",
145 name_of_thread_model (p->plugin._thread_model));
146 printf ("thread_model=%s\n",
147 name_of_thread_model (top->thread_model (top)));
148 printf ("errno_is_preserved=%d\n", !!p->plugin.errno_is_preserved);
149 if (p->plugin.magic_config_key)
150 printf ("magic_config_key=%s\n", p->plugin.magic_config_key);
151
152 #define HAS(field) if (p->plugin.field) printf ("has_%s=1\n", #field)
153 HAS (longname);
154 HAS (description);
155 HAS (load);
156 HAS (unload);
157 HAS (dump_plugin);
158 HAS (config);
159 HAS (config_complete);
160 HAS (config_help);
161 HAS (get_ready);
162 HAS (preconnect);
163 HAS (open);
164 HAS (close);
165 HAS (get_size);
166 HAS (can_write);
167 HAS (can_flush);
168 HAS (is_rotational);
169 HAS (can_trim);
170 HAS (_pread_v1);
171 HAS (_pwrite_v1);
172 HAS (_flush_v1);
173 HAS (_trim_v1);
174 HAS (_zero_v1);
175 HAS (can_zero);
176 HAS (can_fua);
177 HAS (pread);
178 HAS (pwrite);
179 HAS (flush);
180 HAS (trim);
181 HAS (zero);
182 HAS (can_multi_conn);
183 HAS (can_extents);
184 HAS (extents);
185 HAS (can_cache);
186 HAS (cache);
187 HAS (thread_model);
188 HAS (can_fast_zero);
189 #undef HAS
190
191 /* Custom fields. */
192 if (p->plugin.dump_plugin)
193 p->plugin.dump_plugin ();
194 }
195
196 static void
plugin_config(struct backend * b,const char * key,const char * value)197 plugin_config (struct backend *b, const char *key, const char *value)
198 {
199 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
200
201 debug ("%s: config key=%s, value=%s", b->name, key, value);
202
203 if (p->plugin.config == NULL) {
204 fprintf (stderr,
205 "%s: %s: this plugin does not need command line configuration\n"
206 "Try using: %s --help %s\n",
207 program_name, b->filename,
208 program_name, b->filename);
209 exit (EXIT_FAILURE);
210 }
211
212 if (p->plugin.config (key, value) == -1)
213 exit (EXIT_FAILURE);
214 }
215
216 static void
plugin_config_complete(struct backend * b)217 plugin_config_complete (struct backend *b)
218 {
219 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
220
221 debug ("%s: config_complete", b->name);
222
223 if (!p->plugin.config_complete)
224 return;
225
226 if (p->plugin.config_complete () == -1)
227 exit (EXIT_FAILURE);
228 }
229
230 static const char *
plugin_magic_config_key(struct backend * b)231 plugin_magic_config_key (struct backend *b)
232 {
233 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
234
235 return p->plugin.magic_config_key;
236 }
237
238 static void
plugin_get_ready(struct backend * b)239 plugin_get_ready (struct backend *b)
240 {
241 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
242
243 debug ("%s: get_ready", b->name);
244
245 if (!p->plugin.get_ready)
246 return;
247
248 if (p->plugin.get_ready () == -1)
249 exit (EXIT_FAILURE);
250 }
251
252 static int
plugin_preconnect(struct backend * b,int readonly)253 plugin_preconnect (struct backend *b, int readonly)
254 {
255 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
256
257 debug ("%s: preconnect", b->name);
258
259 if (!p->plugin.preconnect)
260 return 0;
261
262 return p->plugin.preconnect (readonly);
263 }
264
265 static void *
plugin_open(struct backend * b,int readonly)266 plugin_open (struct backend *b, int readonly)
267 {
268 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
269
270 assert (p->plugin.open != NULL);
271
272 return p->plugin.open (readonly);
273 }
274
275 /* We don't expose .prepare and .finalize to plugins since they aren't
276 * necessary. Plugins can easily do the same work in .open and
277 * .close.
278 */
279 static int
plugin_prepare(struct backend * b,void * handle,int readonly)280 plugin_prepare (struct backend *b, void *handle,
281 int readonly)
282 {
283 return 0;
284 }
285
286 static int
plugin_finalize(struct backend * b,void * handle)287 plugin_finalize (struct backend *b, void *handle)
288 {
289 return 0;
290 }
291
292 static void
plugin_close(struct backend * b,void * handle)293 plugin_close (struct backend *b, void *handle)
294 {
295 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
296
297 if (handle && p->plugin.close)
298 p->plugin.close (handle);
299 }
300
301 static int64_t
plugin_get_size(struct backend * b,void * handle)302 plugin_get_size (struct backend *b, void *handle)
303 {
304 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
305
306 assert (p->plugin.get_size != NULL);
307
308 return p->plugin.get_size (handle);
309 }
310
311 static int
normalize_bool(int value)312 normalize_bool (int value)
313 {
314 if (value == -1 || value == 0)
315 return value;
316 /* Normalize all other non-zero values to true */
317 return 1;
318 }
319
320 static int
plugin_can_write(struct backend * b,void * handle)321 plugin_can_write (struct backend *b, void *handle)
322 {
323 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
324
325 if (p->plugin.can_write)
326 return normalize_bool (p->plugin.can_write (handle));
327 else
328 return p->plugin.pwrite || p->plugin._pwrite_v1;
329 }
330
331 static int
plugin_can_flush(struct backend * b,void * handle)332 plugin_can_flush (struct backend *b, void *handle)
333 {
334 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
335
336 if (p->plugin.can_flush)
337 return normalize_bool (p->plugin.can_flush (handle));
338 else
339 return p->plugin.flush || p->plugin._flush_v1;
340 }
341
342 static int
plugin_is_rotational(struct backend * b,void * handle)343 plugin_is_rotational (struct backend *b, void *handle)
344 {
345 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
346
347 if (p->plugin.is_rotational)
348 return normalize_bool (p->plugin.is_rotational (handle));
349 else
350 return 0; /* assume false */
351 }
352
353 static int
plugin_can_trim(struct backend * b,void * handle)354 plugin_can_trim (struct backend *b, void *handle)
355 {
356 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
357
358 if (p->plugin.can_trim)
359 return normalize_bool (p->plugin.can_trim (handle));
360 else
361 return p->plugin.trim || p->plugin._trim_v1;
362 }
363
364 static int
plugin_can_zero(struct backend * b,void * handle)365 plugin_can_zero (struct backend *b, void *handle)
366 {
367 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
368 int r;
369
370 /* Note the special case here: the plugin's .can_zero returns a bool
371 * which controls only whether we call .zero; while the backend
372 * expects .can_zero to return a tri-state on level of support.
373 */
374 if (p->plugin.can_zero) {
375 r = p->plugin.can_zero (handle);
376 if (r == -1)
377 return -1;
378 return r ? NBDKIT_ZERO_NATIVE : NBDKIT_ZERO_EMULATE;
379 }
380 if (p->plugin.zero || p->plugin._zero_v1)
381 return NBDKIT_ZERO_NATIVE;
382 return NBDKIT_ZERO_EMULATE;
383 }
384
385 static int
plugin_can_fast_zero(struct backend * b,void * handle)386 plugin_can_fast_zero (struct backend *b, void *handle)
387 {
388 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
389 int r;
390
391 if (p->plugin.can_fast_zero)
392 return normalize_bool (p->plugin.can_fast_zero (handle));
393 /* Advertise support for fast zeroes if no .zero or .can_zero is
394 * false: in those cases, we fail fast instead of using .pwrite.
395 * This also works when v1 plugin has only ._zero_v1.
396 */
397 if (p->plugin.zero == NULL)
398 return 1;
399 r = backend_can_zero (b);
400 if (r == -1)
401 return -1;
402 return !r;
403 }
404
405 static int
plugin_can_extents(struct backend * b,void * handle)406 plugin_can_extents (struct backend *b, void *handle)
407 {
408 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
409
410 if (p->plugin.can_extents)
411 return normalize_bool (p->plugin.can_extents (handle));
412 else
413 return p->plugin.extents != NULL;
414 }
415
416 static int
plugin_can_fua(struct backend * b,void * handle)417 plugin_can_fua (struct backend *b, void *handle)
418 {
419 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
420 int r;
421
422 /* The plugin must use API version 2 and have .can_fua return
423 NBDKIT_FUA_NATIVE before we will pass the FUA flag on. */
424 if (p->plugin.can_fua) {
425 r = p->plugin.can_fua (handle);
426 if (r > NBDKIT_FUA_EMULATE && p->plugin._api_version == 1)
427 r = NBDKIT_FUA_EMULATE;
428 return r;
429 }
430 /* We intend to call .flush even if .can_flush returns false. */
431 if (p->plugin.flush || p->plugin._flush_v1)
432 return NBDKIT_FUA_EMULATE;
433 return NBDKIT_FUA_NONE;
434 }
435
436 static int
plugin_can_multi_conn(struct backend * b,void * handle)437 plugin_can_multi_conn (struct backend *b, void *handle)
438 {
439 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
440
441 if (p->plugin.can_multi_conn)
442 return normalize_bool (p->plugin.can_multi_conn (handle));
443 else
444 return 0; /* assume false */
445 }
446
447 static int
plugin_can_cache(struct backend * b,void * handle)448 plugin_can_cache (struct backend *b, void *handle)
449 {
450 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
451
452 if (p->plugin.can_cache)
453 return p->plugin.can_cache (handle);
454 if (p->plugin.cache)
455 return NBDKIT_CACHE_NATIVE;
456 return NBDKIT_CACHE_NONE;
457 }
458
459 /* Plugins and filters can call this to set the true errno, in cases
460 * where !errno_is_preserved.
461 */
462 void
nbdkit_set_error(int err)463 nbdkit_set_error (int err)
464 {
465 threadlocal_set_error (err);
466 }
467
468 /* Grab the appropriate error value.
469 */
470 static int
get_error(struct backend_plugin * p)471 get_error (struct backend_plugin *p)
472 {
473 int ret = threadlocal_get_error ();
474
475 if (!ret && p->plugin.errno_is_preserved != 0)
476 ret = errno;
477 return ret ? ret : EIO;
478 }
479
480 static int
plugin_pread(struct backend * b,void * handle,void * buf,uint32_t count,uint64_t offset,uint32_t flags,int * err)481 plugin_pread (struct backend *b, void *handle,
482 void *buf, uint32_t count, uint64_t offset, uint32_t flags,
483 int *err)
484 {
485 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
486 int r;
487
488 assert (p->plugin.pread || p->plugin._pread_v1);
489
490 if (p->plugin.pread)
491 r = p->plugin.pread (handle, buf, count, offset, 0);
492 else
493 r = p->plugin._pread_v1 (handle, buf, count, offset);
494 if (r == -1)
495 *err = get_error (p);
496 return r;
497 }
498
499 static int
plugin_flush(struct backend * b,void * handle,uint32_t flags,int * err)500 plugin_flush (struct backend *b, void *handle,
501 uint32_t flags, int *err)
502 {
503 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
504 int r;
505
506 if (p->plugin.flush)
507 r = p->plugin.flush (handle, 0);
508 else if (p->plugin._flush_v1)
509 r = p->plugin._flush_v1 (handle);
510 else {
511 *err = EINVAL;
512 return -1;
513 }
514 if (r == -1)
515 *err = get_error (p);
516 return r;
517 }
518
519 static int
plugin_pwrite(struct backend * b,void * handle,const void * buf,uint32_t count,uint64_t offset,uint32_t flags,int * err)520 plugin_pwrite (struct backend *b, void *handle,
521 const void *buf, uint32_t count, uint64_t offset, uint32_t flags,
522 int *err)
523 {
524 int r;
525 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
526 bool fua = flags & NBDKIT_FLAG_FUA;
527 bool need_flush = false;
528
529 if (fua && backend_can_fua (b) != NBDKIT_FUA_NATIVE) {
530 flags &= ~NBDKIT_FLAG_FUA;
531 need_flush = true;
532 }
533 if (p->plugin.pwrite)
534 r = p->plugin.pwrite (handle, buf, count, offset, flags);
535 else if (p->plugin._pwrite_v1)
536 r = p->plugin._pwrite_v1 (handle, buf, count, offset);
537 else {
538 *err = EROFS;
539 return -1;
540 }
541 if (r != -1 && need_flush)
542 r = plugin_flush (b, handle, 0, err);
543 if (r == -1 && !*err)
544 *err = get_error (p);
545 return r;
546 }
547
548 static int
plugin_trim(struct backend * b,void * handle,uint32_t count,uint64_t offset,uint32_t flags,int * err)549 plugin_trim (struct backend *b, void *handle,
550 uint32_t count, uint64_t offset, uint32_t flags, int *err)
551 {
552 int r;
553 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
554 bool fua = flags & NBDKIT_FLAG_FUA;
555 bool need_flush = false;
556
557 if (fua && backend_can_fua (b) != NBDKIT_FUA_NATIVE) {
558 flags &= ~NBDKIT_FLAG_FUA;
559 need_flush = true;
560 }
561 if (p->plugin.trim)
562 r = p->plugin.trim (handle, count, offset, flags);
563 else if (p->plugin._trim_v1)
564 r = p->plugin._trim_v1 (handle, count, offset);
565 else {
566 *err = EINVAL;
567 return -1;
568 }
569 if (r != -1 && need_flush)
570 r = plugin_flush (b, handle, 0, err);
571 if (r == -1 && !*err)
572 *err = get_error (p);
573 return r;
574 }
575
576 static int
plugin_zero(struct backend * b,void * handle,uint32_t count,uint64_t offset,uint32_t flags,int * err)577 plugin_zero (struct backend *b, void *handle,
578 uint32_t count, uint64_t offset, uint32_t flags, int *err)
579 {
580 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
581 int r = -1;
582 bool may_trim = flags & NBDKIT_FLAG_MAY_TRIM;
583 bool fua = flags & NBDKIT_FLAG_FUA;
584 bool fast_zero = flags & NBDKIT_FLAG_FAST_ZERO;
585 bool emulate = false;
586 bool need_flush = false;
587
588 if (fua && backend_can_fua (b) != NBDKIT_FUA_NATIVE) {
589 flags &= ~NBDKIT_FLAG_FUA;
590 need_flush = true;
591 }
592 if (!count)
593 return 0;
594
595 if (backend_can_zero (b) == NBDKIT_ZERO_NATIVE) {
596 errno = 0;
597 if (p->plugin.zero)
598 r = p->plugin.zero (handle, count, offset, flags);
599 else if (p->plugin._zero_v1) {
600 if (fast_zero) {
601 *err = EOPNOTSUPP;
602 return -1;
603 }
604 r = p->plugin._zero_v1 (handle, count, offset, may_trim);
605 }
606 else
607 emulate = true;
608 if (r == -1)
609 *err = emulate ? EOPNOTSUPP : get_error (p);
610 if (r == 0 || (*err != EOPNOTSUPP && *err != ENOTSUP))
611 goto done;
612 }
613
614 if (fast_zero) {
615 assert (r == -1);
616 *err = EOPNOTSUPP;
617 goto done;
618 }
619
620 assert (p->plugin.pwrite || p->plugin._pwrite_v1);
621 flags &= ~NBDKIT_FLAG_MAY_TRIM;
622 threadlocal_set_error (0);
623 *err = 0;
624
625 while (count) {
626 /* Always contains zeroes, but we can't use const or else gcc 9
627 * will use .rodata instead of .bss and inflate the binary size.
628 */
629 static /* const */ char buf[MAX_REQUEST_SIZE];
630 uint32_t limit = MIN (count, sizeof buf);
631
632 r = plugin_pwrite (b, handle, buf, limit, offset, flags, err);
633 if (r == -1)
634 break;
635 count -= limit;
636 }
637
638 done:
639 if (r != -1 && need_flush)
640 r = plugin_flush (b, handle, 0, err);
641 if (r == -1 && !*err)
642 *err = get_error (p);
643 return r;
644 }
645
646 static int
plugin_extents(struct backend * b,void * handle,uint32_t count,uint64_t offset,uint32_t flags,struct nbdkit_extents * extents,int * err)647 plugin_extents (struct backend *b, void *handle,
648 uint32_t count, uint64_t offset, uint32_t flags,
649 struct nbdkit_extents *extents, int *err)
650 {
651 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
652 int r;
653
654 /* This should be true because plugin_can_extents checks it. */
655 assert (p->plugin.extents);
656
657 r = p->plugin.extents (handle, count, offset, flags, extents);
658 if (r >= 0 && nbdkit_extents_count (extents) < 1) {
659 nbdkit_error ("extents: plugin must return at least one extent");
660 nbdkit_set_error (EINVAL);
661 r = -1;
662 }
663 if (r == -1)
664 *err = get_error (p);
665 return r;
666 }
667
668 static int
plugin_cache(struct backend * b,void * handle,uint32_t count,uint64_t offset,uint32_t flags,int * err)669 plugin_cache (struct backend *b, void *handle,
670 uint32_t count, uint64_t offset, uint32_t flags,
671 int *err)
672 {
673 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
674 int r;
675
676 /* A plugin may advertise caching but not provide .cache; in that
677 * case, caching is explicitly a no-op. */
678 if (!p->plugin.cache)
679 return 0;
680
681 r = p->plugin.cache (handle, count, offset, flags);
682 if (r == -1)
683 *err = get_error (p);
684 return r;
685 }
686
687 static struct backend plugin_functions = {
688 .free = plugin_free,
689 .thread_model = plugin_thread_model,
690 .plugin_name = plugin_name,
691 .usage = plugin_usage,
692 .version = plugin_version,
693 .dump_fields = plugin_dump_fields,
694 .config = plugin_config,
695 .config_complete = plugin_config_complete,
696 .magic_config_key = plugin_magic_config_key,
697 .get_ready = plugin_get_ready,
698 .preconnect = plugin_preconnect,
699 .open = plugin_open,
700 .prepare = plugin_prepare,
701 .finalize = plugin_finalize,
702 .close = plugin_close,
703 .get_size = plugin_get_size,
704 .can_write = plugin_can_write,
705 .can_flush = plugin_can_flush,
706 .is_rotational = plugin_is_rotational,
707 .can_trim = plugin_can_trim,
708 .can_zero = plugin_can_zero,
709 .can_fast_zero = plugin_can_fast_zero,
710 .can_extents = plugin_can_extents,
711 .can_fua = plugin_can_fua,
712 .can_multi_conn = plugin_can_multi_conn,
713 .can_cache = plugin_can_cache,
714 .pread = plugin_pread,
715 .pwrite = plugin_pwrite,
716 .flush = plugin_flush,
717 .trim = plugin_trim,
718 .zero = plugin_zero,
719 .extents = plugin_extents,
720 .cache = plugin_cache,
721 };
722
723 /* Register and load a plugin. */
724 struct backend *
plugin_register(size_t index,const char * filename,void * dl,struct nbdkit_plugin * (* plugin_init)(void))725 plugin_register (size_t index, const char *filename,
726 void *dl, struct nbdkit_plugin *(*plugin_init) (void))
727 {
728 struct backend_plugin *p;
729 const struct nbdkit_plugin *plugin;
730 size_t size;
731
732 p = malloc (sizeof *p);
733 if (p == NULL) {
734 perror ("strdup");
735 exit (EXIT_FAILURE);
736 }
737
738 p->backend = plugin_functions;
739 backend_init (&p->backend, NULL, index, filename, dl, "plugin");
740
741 /* Call the initialization function which returns the address of the
742 * plugin's own 'struct nbdkit_plugin'.
743 */
744 plugin = plugin_init ();
745 if (!plugin) {
746 fprintf (stderr, "%s: %s: plugin registration function failed\n",
747 program_name, filename);
748 exit (EXIT_FAILURE);
749 }
750
751 /* Check for incompatible future versions. */
752 if (plugin->_api_version < 0 || plugin->_api_version > 2) {
753 fprintf (stderr,
754 "%s: %s: plugin is incompatible with this version of nbdkit "
755 "(_api_version = %d)\n",
756 program_name, filename, plugin->_api_version);
757 exit (EXIT_FAILURE);
758 }
759
760 /* Since the plugin might be much older than the current version of
761 * nbdkit, only copy up to the self-declared _struct_size of the
762 * plugin and zero out the rest. If the plugin is much newer then
763 * we'll only call the "old" fields.
764 */
765 size = sizeof p->plugin; /* our struct */
766 memset (&p->plugin, 0, size);
767 if (size > plugin->_struct_size)
768 size = plugin->_struct_size;
769 memcpy (&p->plugin, plugin, size);
770
771 /* Check for the minimum fields which must exist in the
772 * plugin struct.
773 */
774 if (p->plugin.open == NULL) {
775 fprintf (stderr, "%s: %s: plugin must have a .open callback\n",
776 program_name, filename);
777 exit (EXIT_FAILURE);
778 }
779 if (p->plugin.get_size == NULL) {
780 fprintf (stderr, "%s: %s: plugin must have a .get_size callback\n",
781 program_name, filename);
782 exit (EXIT_FAILURE);
783 }
784 if (p->plugin.pread == NULL && p->plugin._pread_v1 == NULL) {
785 fprintf (stderr, "%s: %s: plugin must have a .pread callback\n",
786 program_name, filename);
787 exit (EXIT_FAILURE);
788 }
789
790 backend_load (&p->backend, p->plugin.name, p->plugin.load);
791
792 return (struct backend *) p;
793 }
794