server: Use GCC hints to move debug and error handling code out of hot paths.
[nbdkit/ericb.git] / server / plugins.c
blob65f6817672bd576cfce516b988881202e87fe968
1 /* nbdkit
2 * Copyright (C) 2013-2019 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
33 #include <config.h>
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>
44 #include "internal.h"
45 #include "minmax.h"
47 /* We extend the generic backend struct with extra fields relating
48 * to this plugin.
50 struct backend_plugin {
51 struct backend backend;
52 struct nbdkit_plugin plugin;
55 static void
56 plugin_free (struct backend *b)
58 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
60 backend_unload (b, p->plugin.unload);
61 free (p);
64 static int
65 plugin_thread_model (struct backend *b)
67 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
68 int thread_model = p->plugin._thread_model;
69 int r;
71 #if !(defined SOCK_CLOEXEC && defined HAVE_MKOSTEMP && defined HAVE_PIPE2 && \
72 defined HAVE_ACCEPT4)
73 if (thread_model > NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS) {
74 debug ("system lacks atomic CLOEXEC, serializing to avoid fd leaks");
75 thread_model = NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS;
77 #endif
79 if (p->plugin.thread_model) {
80 r = p->plugin.thread_model ();
81 if (r == -1)
82 exit (EXIT_FAILURE);
83 if (r < thread_model)
84 thread_model = r;
87 return thread_model;
90 static const char *
91 plugin_name (struct backend *b)
93 return b->name;
96 static void
97 plugin_usage (struct backend *b)
99 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
100 const char *t;
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");
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");
119 static const char *
120 plugin_version (struct backend *b)
122 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
124 return p->plugin.version;
127 /* This implements the --dump-plugin option. */
128 static void
129 plugin_dump_fields (struct backend *b)
131 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
132 char *path;
134 path = nbdkit_realpath (b->filename);
135 printf ("path=%s\n", path);
136 free (path);
138 printf ("name=%s\n", b->name);
139 if (p->plugin.version)
140 printf ("version=%s\n", p->plugin.version);
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 (backend->thread_model (backend)));
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);
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 (open);
162 HAS (close);
163 HAS (get_size);
164 HAS (can_write);
165 HAS (can_flush);
166 HAS (is_rotational);
167 HAS (can_trim);
168 HAS (_pread_old);
169 HAS (_pwrite_old);
170 HAS (_flush_old);
171 HAS (_trim_old);
172 HAS (_zero_old);
173 HAS (can_zero);
174 HAS (can_fua);
175 HAS (pread);
176 HAS (pwrite);
177 HAS (flush);
178 HAS (trim);
179 HAS (zero);
180 HAS (can_multi_conn);
181 HAS (can_extents);
182 HAS (extents);
183 HAS (can_cache);
184 HAS (cache);
185 HAS (thread_model);
186 HAS (can_fast_zero);
187 #undef HAS
189 /* Custom fields. */
190 if (p->plugin.dump_plugin)
191 p->plugin.dump_plugin ();
194 static void
195 plugin_config (struct backend *b, const char *key, const char *value)
197 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
199 debug ("%s: config key=%s, value=%s", b->name, key, value);
201 if (p->plugin.config == NULL) {
202 fprintf (stderr,
203 "%s: %s: this plugin does not need command line configuration\n"
204 "Try using: %s --help %s\n",
205 program_name, b->filename,
206 program_name, b->filename);
207 exit (EXIT_FAILURE);
210 if (p->plugin.config (key, value) == -1)
211 exit (EXIT_FAILURE);
214 static void
215 plugin_config_complete (struct backend *b)
217 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
219 debug ("%s: config_complete", b->name);
221 if (!p->plugin.config_complete)
222 return;
224 if (p->plugin.config_complete () == -1)
225 exit (EXIT_FAILURE);
228 static const char *
229 plugin_magic_config_key (struct backend *b)
231 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
233 return p->plugin.magic_config_key;
236 static void *
237 plugin_open (struct backend *b, struct connection *conn, int readonly)
239 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
241 assert (p->plugin.open != NULL);
243 return p->plugin.open (readonly);
246 /* We don't expose .prepare and .finalize to plugins since they aren't
247 * necessary. Plugins can easily do the same work in .open and
248 * .close.
250 static int
251 plugin_prepare (struct backend *b, struct connection *conn, void *handle,
252 int readonly)
254 return 0;
257 static int
258 plugin_finalize (struct backend *b, struct connection *conn, void *handle)
260 return 0;
263 static void
264 plugin_close (struct backend *b, struct connection *conn, void *handle)
266 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
268 if (handle && p->plugin.close)
269 p->plugin.close (handle);
272 static int64_t
273 plugin_get_size (struct backend *b, struct connection *conn, void *handle)
275 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
277 assert (p->plugin.get_size != NULL);
279 return p->plugin.get_size (handle);
282 static int
283 plugin_can_write (struct backend *b, struct connection *conn, void *handle)
285 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
287 if (p->plugin.can_write)
288 return p->plugin.can_write (handle);
289 else
290 return p->plugin.pwrite || p->plugin._pwrite_old;
293 static int
294 plugin_can_flush (struct backend *b, struct connection *conn, void *handle)
296 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
298 if (p->plugin.can_flush)
299 return p->plugin.can_flush (handle);
300 else
301 return p->plugin.flush || p->plugin._flush_old;
304 static int
305 plugin_is_rotational (struct backend *b, struct connection *conn, void *handle)
307 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
309 if (p->plugin.is_rotational)
310 return p->plugin.is_rotational (handle);
311 else
312 return 0; /* assume false */
315 static int
316 plugin_can_trim (struct backend *b, struct connection *conn, void *handle)
318 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
320 if (p->plugin.can_trim)
321 return p->plugin.can_trim (handle);
322 else
323 return p->plugin.trim || p->plugin._trim_old;
326 static int
327 plugin_can_zero (struct backend *b, struct connection *conn, void *handle)
329 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
330 int r;
332 /* Note the special case here: the plugin's .can_zero returns a bool
333 * which controls only whether we call .zero; while the backend
334 * expects .can_zero to return a tri-state on level of support.
336 if (p->plugin.can_zero) {
337 r = p->plugin.can_zero (handle);
338 if (r == -1)
339 return -1;
340 return r ? NBDKIT_ZERO_NATIVE : NBDKIT_ZERO_EMULATE;
342 if (p->plugin.zero || p->plugin._zero_old)
343 return NBDKIT_ZERO_NATIVE;
344 return NBDKIT_ZERO_EMULATE;
347 static int
348 plugin_can_fast_zero (struct backend *b, struct connection *conn, void *handle)
350 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
351 int r;
353 if (p->plugin.can_fast_zero)
354 return p->plugin.can_fast_zero (handle);
355 /* Advertise support for fast zeroes if no .zero or .can_zero is
356 * false: in those cases, we fail fast instead of using .pwrite.
357 * This also works when v1 plugin has only ._zero_old.
359 if (p->plugin.zero == NULL)
360 return 1;
361 r = backend_can_zero (b, conn);
362 if (r == -1)
363 return -1;
364 return !r;
367 static int
368 plugin_can_extents (struct backend *b, struct connection *conn, void *handle)
370 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
372 if (p->plugin.can_extents)
373 return p->plugin.can_extents (handle);
374 else
375 return p->plugin.extents != NULL;
378 static int
379 plugin_can_fua (struct backend *b, struct connection *conn, void *handle)
381 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
382 int r;
384 /* The plugin must use API version 2 and have .can_fua return
385 NBDKIT_FUA_NATIVE before we will pass the FUA flag on. */
386 if (p->plugin.can_fua) {
387 r = p->plugin.can_fua (handle);
388 if (r > NBDKIT_FUA_EMULATE && p->plugin._api_version == 1)
389 r = NBDKIT_FUA_EMULATE;
390 return r;
392 /* We intend to call .flush even if .can_flush returns false. */
393 if (p->plugin.flush || p->plugin._flush_old)
394 return NBDKIT_FUA_EMULATE;
395 return NBDKIT_FUA_NONE;
398 static int
399 plugin_can_multi_conn (struct backend *b, struct connection *conn, void *handle)
401 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
403 if (p->plugin.can_multi_conn)
404 return p->plugin.can_multi_conn (handle);
405 else
406 return 0; /* assume false */
409 static int
410 plugin_can_cache (struct backend *b, struct connection *conn, void *handle)
412 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
414 if (p->plugin.can_cache)
415 return p->plugin.can_cache (handle);
416 if (p->plugin.cache)
417 return NBDKIT_CACHE_NATIVE;
418 return NBDKIT_CACHE_NONE;
421 /* Plugins and filters can call this to set the true errno, in cases
422 * where !errno_is_preserved.
424 void
425 nbdkit_set_error (int err)
427 threadlocal_set_error (err);
430 /* Grab the appropriate error value.
432 static int
433 get_error (struct backend_plugin *p)
435 int ret = threadlocal_get_error ();
437 if (!ret && p->plugin.errno_is_preserved != 0)
438 ret = errno;
439 return ret ? ret : EIO;
442 static int
443 plugin_pread (struct backend *b, struct connection *conn, void *handle,
444 void *buf, uint32_t count, uint64_t offset, uint32_t flags,
445 int *err)
447 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
448 int r;
450 assert (p->plugin.pread || p->plugin._pread_old);
452 if (p->plugin.pread)
453 r = p->plugin.pread (handle, buf, count, offset, 0);
454 else
455 r = p->plugin._pread_old (handle, buf, count, offset);
456 if (r == -1)
457 *err = get_error (p);
458 return r;
461 static int
462 plugin_flush (struct backend *b, struct connection *conn, void *handle,
463 uint32_t flags, int *err)
465 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
466 int r;
468 if (p->plugin.flush)
469 r = p->plugin.flush (handle, 0);
470 else if (p->plugin._flush_old)
471 r = p->plugin._flush_old (handle);
472 else {
473 *err = EINVAL;
474 return -1;
476 if (r == -1)
477 *err = get_error (p);
478 return r;
481 static int
482 plugin_pwrite (struct backend *b, struct connection *conn, void *handle,
483 const void *buf, uint32_t count, uint64_t offset, uint32_t flags,
484 int *err)
486 int r;
487 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
488 bool fua = flags & NBDKIT_FLAG_FUA;
489 bool need_flush = false;
491 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
492 flags &= ~NBDKIT_FLAG_FUA;
493 need_flush = true;
495 if (p->plugin.pwrite)
496 r = p->plugin.pwrite (handle, buf, count, offset, flags);
497 else if (p->plugin._pwrite_old)
498 r = p->plugin._pwrite_old (handle, buf, count, offset);
499 else {
500 *err = EROFS;
501 return -1;
503 if (r != -1 && need_flush)
504 r = plugin_flush (b, conn, handle, 0, err);
505 if (r == -1 && !*err)
506 *err = get_error (p);
507 return r;
510 static int
511 plugin_trim (struct backend *b, struct connection *conn, void *handle,
512 uint32_t count, uint64_t offset, uint32_t flags, int *err)
514 int r;
515 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
516 bool fua = flags & NBDKIT_FLAG_FUA;
517 bool need_flush = false;
519 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
520 flags &= ~NBDKIT_FLAG_FUA;
521 need_flush = true;
523 if (p->plugin.trim)
524 r = p->plugin.trim (handle, count, offset, flags);
525 else if (p->plugin._trim_old)
526 r = p->plugin._trim_old (handle, count, offset);
527 else {
528 *err = EINVAL;
529 return -1;
531 if (r != -1 && need_flush)
532 r = plugin_flush (b, conn, handle, 0, err);
533 if (r == -1 && !*err)
534 *err = get_error (p);
535 return r;
538 static int
539 plugin_zero (struct backend *b, struct connection *conn, void *handle,
540 uint32_t count, uint64_t offset, uint32_t flags, int *err)
542 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
543 int r = -1;
544 bool may_trim = flags & NBDKIT_FLAG_MAY_TRIM;
545 bool fua = flags & NBDKIT_FLAG_FUA;
546 bool fast_zero = flags & NBDKIT_FLAG_FAST_ZERO;
547 bool emulate = false;
548 bool need_flush = false;
550 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
551 flags &= ~NBDKIT_FLAG_FUA;
552 need_flush = true;
554 if (!count)
555 return 0;
557 if (backend_can_zero (b, conn) == NBDKIT_ZERO_NATIVE) {
558 errno = 0;
559 if (p->plugin.zero)
560 r = p->plugin.zero (handle, count, offset, flags);
561 else if (p->plugin._zero_old) {
562 if (fast_zero) {
563 *err = EOPNOTSUPP;
564 return -1;
566 r = p->plugin._zero_old (handle, count, offset, may_trim);
568 else
569 emulate = true;
570 if (r == -1)
571 *err = emulate ? EOPNOTSUPP : get_error (p);
572 if (r == 0 || (*err != EOPNOTSUPP && *err != ENOTSUP))
573 goto done;
576 if (fast_zero) {
577 assert (r == -1);
578 *err = EOPNOTSUPP;
579 goto done;
582 assert (p->plugin.pwrite || p->plugin._pwrite_old);
583 flags &= ~NBDKIT_FLAG_MAY_TRIM;
584 threadlocal_set_error (0);
585 *err = 0;
587 while (count) {
588 /* Always contains zeroes, but we can't use const or else gcc 9
589 * will use .rodata instead of .bss and inflate the binary size.
591 static /* const */ char buf[MAX_REQUEST_SIZE];
592 uint32_t limit = MIN (count, sizeof buf);
594 r = plugin_pwrite (b, conn, handle, buf, limit, offset, flags, err);
595 if (r == -1)
596 break;
597 count -= limit;
600 done:
601 if (r != -1 && need_flush)
602 r = plugin_flush (b, conn, handle, 0, err);
603 if (r == -1 && !*err)
604 *err = get_error (p);
605 return r;
608 static int
609 plugin_extents (struct backend *b, struct connection *conn, void *handle,
610 uint32_t count, uint64_t offset, uint32_t flags,
611 struct nbdkit_extents *extents, int *err)
613 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
614 int r;
616 /* This should be true because plugin_can_extents checks it. */
617 assert (p->plugin.extents);
619 r = p->plugin.extents (handle, count, offset, flags, extents);
620 if (r >= 0 && nbdkit_extents_count (extents) < 1) {
621 nbdkit_error ("extents: plugin must return at least one extent");
622 nbdkit_set_error (EINVAL);
623 r = -1;
625 if (r == -1)
626 *err = get_error (p);
627 return r;
630 static int
631 plugin_cache (struct backend *b, struct connection *conn, void *handle,
632 uint32_t count, uint64_t offset, uint32_t flags,
633 int *err)
635 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
636 int r;
638 /* A plugin may advertise caching but not provide .cache; in that
639 * case, caching is explicitly a no-op. */
640 if (!p->plugin.cache)
641 return 0;
643 r = p->plugin.cache (handle, count, offset, flags);
644 if (r == -1)
645 *err = get_error (p);
646 return r;
649 static struct backend plugin_functions = {
650 .free = plugin_free,
651 .thread_model = plugin_thread_model,
652 .plugin_name = plugin_name,
653 .usage = plugin_usage,
654 .version = plugin_version,
655 .dump_fields = plugin_dump_fields,
656 .config = plugin_config,
657 .config_complete = plugin_config_complete,
658 .magic_config_key = plugin_magic_config_key,
659 .open = plugin_open,
660 .prepare = plugin_prepare,
661 .finalize = plugin_finalize,
662 .close = plugin_close,
663 .get_size = plugin_get_size,
664 .can_write = plugin_can_write,
665 .can_flush = plugin_can_flush,
666 .is_rotational = plugin_is_rotational,
667 .can_trim = plugin_can_trim,
668 .can_zero = plugin_can_zero,
669 .can_fast_zero = plugin_can_fast_zero,
670 .can_extents = plugin_can_extents,
671 .can_fua = plugin_can_fua,
672 .can_multi_conn = plugin_can_multi_conn,
673 .can_cache = plugin_can_cache,
674 .pread = plugin_pread,
675 .pwrite = plugin_pwrite,
676 .flush = plugin_flush,
677 .trim = plugin_trim,
678 .zero = plugin_zero,
679 .extents = plugin_extents,
680 .cache = plugin_cache,
683 /* Register and load a plugin. */
684 struct backend *
685 plugin_register (size_t index, const char *filename,
686 void *dl, struct nbdkit_plugin *(*plugin_init) (void))
688 struct backend_plugin *p;
689 const struct nbdkit_plugin *plugin;
690 size_t size;
692 p = malloc (sizeof *p);
693 if (p == NULL) {
694 perror ("strdup");
695 exit (EXIT_FAILURE);
698 p->backend = plugin_functions;
699 backend_init (&p->backend, NULL, index, filename, dl, "plugin");
701 /* Call the initialization function which returns the address of the
702 * plugin's own 'struct nbdkit_plugin'.
704 plugin = plugin_init ();
705 if (!plugin) {
706 fprintf (stderr, "%s: %s: plugin registration function failed\n",
707 program_name, filename);
708 exit (EXIT_FAILURE);
711 /* Check for incompatible future versions. */
712 if (plugin->_api_version < 0 || plugin->_api_version > 2) {
713 fprintf (stderr,
714 "%s: %s: plugin is incompatible with this version of nbdkit "
715 "(_api_version = %d)\n",
716 program_name, filename, plugin->_api_version);
717 exit (EXIT_FAILURE);
720 /* Since the plugin might be much older than the current version of
721 * nbdkit, only copy up to the self-declared _struct_size of the
722 * plugin and zero out the rest. If the plugin is much newer then
723 * we'll only call the "old" fields.
725 size = sizeof p->plugin; /* our struct */
726 memset (&p->plugin, 0, size);
727 if (size > plugin->_struct_size)
728 size = plugin->_struct_size;
729 memcpy (&p->plugin, plugin, size);
731 /* Check for the minimum fields which must exist in the
732 * plugin struct.
734 if (p->plugin.open == NULL) {
735 fprintf (stderr, "%s: %s: plugin must have a .open callback\n",
736 program_name, filename);
737 exit (EXIT_FAILURE);
739 if (p->plugin.get_size == NULL) {
740 fprintf (stderr, "%s: %s: plugin must have a .get_size callback\n",
741 program_name, filename);
742 exit (EXIT_FAILURE);
744 if (p->plugin.pread == NULL && p->plugin._pread_old == NULL) {
745 fprintf (stderr, "%s: %s: plugin must have a .pread callback\n",
746 program_name, filename);
747 exit (EXIT_FAILURE);
750 backend_load (&p->backend, p->plugin.name, p->plugin.load);
752 return (struct backend *) p;