filters: Adjust callback API for flags/errors
[nbdkit/ericb.git] / src / filters.c
blob9d821f2bb4d2daf1aa39919e4d0590448446a336
1 /* nbdkit
2 * Copyright (C) 2013-2018 Red Hat Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Red Hat nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <config.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdint.h>
39 #include <string.h>
40 #include <inttypes.h>
41 #include <assert.h>
43 #include <dlfcn.h>
45 #include "internal.h"
47 /* We extend the generic backend struct with extra fields relating
48 * to this filter.
50 struct backend_filter {
51 struct backend backend;
52 char *name; /* copy of filter.name */
53 char *filename;
54 void *dl;
55 struct nbdkit_filter filter;
58 /* Literally a backend + a connection pointer. This is the
59 * implementation of ‘void *nxdata’ in the filter API.
61 struct b_conn {
62 struct backend *b;
63 struct connection *conn;
66 /* Note this frees the whole chain. */
67 static void
68 filter_free (struct backend *b)
70 struct backend_filter *f = container_of (b, struct backend_filter, backend);
72 f->backend.next->free (f->backend.next);
74 /* Acquiring this lock prevents any filter callbacks from running
75 * simultaneously.
77 lock_unload ();
79 debug ("%s: unload", f->filename);
80 if (f->filter.unload)
81 f->filter.unload ();
83 dlclose (f->dl);
84 free (f->filename);
86 unlock_unload ();
88 free (f->name);
89 free (f);
92 static int
93 filter_thread_model (struct backend *b)
95 struct backend_filter *f = container_of (b, struct backend_filter, backend);
96 int filter_thread_model = f->filter._thread_model;
97 int thread_model = f->backend.next->thread_model (f->backend.next);
99 if (filter_thread_model < thread_model) /* more serialized */
100 thread_model = filter_thread_model;
102 return thread_model;
105 /* These are actually passing through to the final plugin, hence
106 * the function names.
108 static const char *
109 plugin_name (struct backend *b)
111 struct backend_filter *f = container_of (b, struct backend_filter, backend);
113 return f->backend.next->name (f->backend.next);
116 static const char *
117 filter_name (struct backend *b)
119 struct backend_filter *f = container_of (b, struct backend_filter, backend);
121 return f->name;
124 static const char *
125 filter_version (struct backend *b)
127 struct backend_filter *f = container_of (b, struct backend_filter, backend);
129 return f->filter.version;
132 static void
133 filter_usage (struct backend *b)
135 struct backend_filter *f = container_of (b, struct backend_filter, backend);
137 printf ("filter: %s", f->name);
138 if (f->filter.longname)
139 printf (" (%s)", f->filter.longname);
140 printf ("\n");
141 printf ("(%s)", f->filename);
142 if (f->filter.description) {
143 printf ("\n");
144 printf ("%s\n", f->filter.description);
146 if (f->filter.config_help) {
147 printf ("\n");
148 printf ("%s\n", f->filter.config_help);
152 static void
153 filter_dump_fields (struct backend *b)
155 struct backend_filter *f = container_of (b, struct backend_filter, backend);
157 f->backend.next->dump_fields (f->backend.next);
160 static int
161 next_config (void *nxdata, const char *key, const char *value)
163 struct backend *b = nxdata;
164 b->config (b, key, value);
165 return 0;
168 static void
169 filter_config (struct backend *b, const char *key, const char *value)
171 struct backend_filter *f = container_of (b, struct backend_filter, backend);
173 debug ("%s: config key=%s, value=%s",
174 f->filename, key, value);
176 if (f->filter.config) {
177 if (f->filter.config (next_config, f->backend.next, key, value) == -1)
178 exit (EXIT_FAILURE);
180 else
181 f->backend.next->config (f->backend.next, key, value);
184 static int
185 next_config_complete (void *nxdata)
187 struct backend *b = nxdata;
188 b->config_complete (b);
189 return 0;
192 static void
193 filter_config_complete (struct backend *b)
195 struct backend_filter *f = container_of (b, struct backend_filter, backend);
197 debug ("%s: config_complete", f->filename);
199 if (f->filter.config_complete) {
200 if (f->filter.config_complete (next_config_complete, f->backend.next) == -1)
201 exit (EXIT_FAILURE);
203 else
204 f->backend.next->config_complete (f->backend.next);
207 static int
208 next_open (void *nxdata, int readonly)
210 struct b_conn *b_conn = nxdata;
212 return b_conn->b->open (b_conn->b, b_conn->conn, readonly);
215 static int
216 filter_open (struct backend *b, struct connection *conn, int readonly)
218 struct backend_filter *f = container_of (b, struct backend_filter, backend);
219 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
220 void *handle;
222 debug ("%s: open readonly=%d", f->filename, readonly);
224 if (f->filter.open) {
225 handle = f->filter.open (next_open, &nxdata, readonly);
226 if (handle == NULL)
227 return -1;
228 connection_set_handle (conn, f->backend.i, handle);
229 return 0;
231 else
232 return f->backend.next->open (f->backend.next, conn, readonly);
235 static void
236 filter_close (struct backend *b, struct connection *conn)
238 struct backend_filter *f = container_of (b, struct backend_filter, backend);
239 void *handle = connection_get_handle (conn, f->backend.i);
241 debug ("close");
243 if (f->filter.close)
244 f->filter.close (handle);
245 f->backend.next->close (f->backend.next, conn);
248 /* The next_functions structure contains pointers to backend
249 * functions. However because these functions are all expecting a
250 * backend and a connection, we cannot call them directly, but must
251 * write some next_* functions that unpack the two parameters from a
252 * single ‘void *nxdata’ struct pointer (‘b_conn’).
255 static int64_t
256 next_get_size (void *nxdata)
258 struct b_conn *b_conn = nxdata;
259 return b_conn->b->get_size (b_conn->b, b_conn->conn);
262 static int
263 next_can_write (void *nxdata)
265 struct b_conn *b_conn = nxdata;
266 return b_conn->b->can_write (b_conn->b, b_conn->conn);
269 static int
270 next_can_flush (void *nxdata)
272 struct b_conn *b_conn = nxdata;
273 return b_conn->b->can_flush (b_conn->b, b_conn->conn);
276 static int
277 next_is_rotational (void *nxdata)
279 struct b_conn *b_conn = nxdata;
280 return b_conn->b->is_rotational (b_conn->b, b_conn->conn);
283 static int
284 next_can_trim (void *nxdata)
286 struct b_conn *b_conn = nxdata;
287 return b_conn->b->can_trim (b_conn->b, b_conn->conn);
290 static int
291 next_pread (void *nxdata, void *buf, uint32_t count, uint64_t offset,
292 uint32_t flags, int *err)
294 struct b_conn *b_conn = nxdata;
295 return b_conn->b->pread (b_conn->b, b_conn->conn, buf, count, offset, flags,
296 err);
299 static int
300 next_pwrite (void *nxdata, const void *buf, uint32_t count, uint64_t offset,
301 uint32_t flags, int *err)
303 struct b_conn *b_conn = nxdata;
304 return b_conn->b->pwrite (b_conn->b, b_conn->conn, buf, count, offset, flags,
305 err);
308 static int
309 next_flush (void *nxdata, uint32_t flags, int *err)
311 struct b_conn *b_conn = nxdata;
312 return b_conn->b->flush (b_conn->b, b_conn->conn, flags, err);
315 static int
316 next_trim (void *nxdata, uint32_t count, uint64_t offset, uint32_t flags,
317 int *err)
319 struct b_conn *b_conn = nxdata;
320 return b_conn->b->trim (b_conn->b, b_conn->conn, count, offset, flags, err);
323 static int
324 next_zero (void *nxdata, uint32_t count, uint64_t offset, uint32_t flags,
325 int *err)
327 struct b_conn *b_conn = nxdata;
328 return b_conn->b->zero (b_conn->b, b_conn->conn, count, offset, flags, err);
331 static struct nbdkit_next_ops next_ops = {
332 .get_size = next_get_size,
333 .can_write = next_can_write,
334 .can_flush = next_can_flush,
335 .is_rotational = next_is_rotational,
336 .can_trim = next_can_trim,
337 .pread = next_pread,
338 .pwrite = next_pwrite,
339 .flush = next_flush,
340 .trim = next_trim,
341 .zero = next_zero,
344 static int
345 filter_prepare (struct backend *b, struct connection *conn)
347 struct backend_filter *f = container_of (b, struct backend_filter, backend);
348 void *handle = connection_get_handle (conn, f->backend.i);
349 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
351 debug ("prepare");
353 if (f->filter.prepare)
354 return f->filter.prepare (&next_ops, &nxdata, handle);
355 else
356 return f->backend.next->prepare (f->backend.next, conn);
359 static int
360 filter_finalize (struct backend *b, struct connection *conn)
362 struct backend_filter *f = container_of (b, struct backend_filter, backend);
363 void *handle = connection_get_handle (conn, f->backend.i);
364 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
366 debug ("finalize");
368 if (f->filter.finalize)
369 return f->filter.finalize (&next_ops, &nxdata, handle);
370 else
371 return f->backend.next->finalize (f->backend.next, conn);
374 static int64_t
375 filter_get_size (struct backend *b, struct connection *conn)
377 struct backend_filter *f = container_of (b, struct backend_filter, backend);
378 void *handle = connection_get_handle (conn, f->backend.i);
379 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
381 debug ("get_size");
383 if (f->filter.get_size)
384 return f->filter.get_size (&next_ops, &nxdata, handle);
385 else
386 return f->backend.next->get_size (f->backend.next, conn);
389 static int
390 filter_can_write (struct backend *b, struct connection *conn)
392 struct backend_filter *f = container_of (b, struct backend_filter, backend);
393 void *handle = connection_get_handle (conn, f->backend.i);
394 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
396 debug ("can_write");
398 if (f->filter.can_write)
399 return f->filter.can_write (&next_ops, &nxdata, handle);
400 else
401 return f->backend.next->can_write (f->backend.next, conn);
404 static int
405 filter_can_flush (struct backend *b, struct connection *conn)
407 struct backend_filter *f = container_of (b, struct backend_filter, backend);
408 void *handle = connection_get_handle (conn, f->backend.i);
409 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
411 debug ("can_flush");
413 if (f->filter.can_flush)
414 return f->filter.can_flush (&next_ops, &nxdata, handle);
415 else
416 return f->backend.next->can_flush (f->backend.next, conn);
419 static int
420 filter_is_rotational (struct backend *b, struct connection *conn)
422 struct backend_filter *f = container_of (b, struct backend_filter, backend);
423 void *handle = connection_get_handle (conn, f->backend.i);
424 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
426 debug ("is_rotational");
428 if (f->filter.is_rotational)
429 return f->filter.is_rotational (&next_ops, &nxdata, handle);
430 else
431 return f->backend.next->is_rotational (f->backend.next, conn);
434 static int
435 filter_can_trim (struct backend *b, struct connection *conn)
437 struct backend_filter *f = container_of (b, struct backend_filter, backend);
438 void *handle = connection_get_handle (conn, f->backend.i);
439 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
441 debug ("can_trim");
443 if (f->filter.can_trim)
444 return f->filter.can_trim (&next_ops, &nxdata, handle);
445 else
446 return f->backend.next->can_trim (f->backend.next, conn);
449 static int
450 filter_pread (struct backend *b, struct connection *conn,
451 void *buf, uint32_t count, uint64_t offset,
452 uint32_t flags, int *err)
454 struct backend_filter *f = container_of (b, struct backend_filter, backend);
455 void *handle = connection_get_handle (conn, f->backend.i);
456 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
458 assert (flags == 0);
460 debug ("pread count=%" PRIu32 " offset=%" PRIu64 " flags=0x%" PRIx32,
461 count, offset, flags);
463 if (f->filter.pread)
464 return f->filter.pread (&next_ops, &nxdata, handle,
465 buf, count, offset, flags, err);
466 else
467 return f->backend.next->pread (f->backend.next, conn,
468 buf, count, offset, flags, err);
471 static int
472 filter_pwrite (struct backend *b, struct connection *conn,
473 const void *buf, uint32_t count, uint64_t offset,
474 uint32_t flags, int *err)
476 struct backend_filter *f = container_of (b, struct backend_filter, backend);
477 void *handle = connection_get_handle (conn, f->backend.i);
478 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
480 assert (!(flags & ~NBDKIT_FLAG_FUA));
482 debug ("pwrite count=%" PRIu32 " offset=%" PRIu64 " flags=0x%" PRIx32,
483 count, offset, flags);
485 if (f->filter.pwrite)
486 return f->filter.pwrite (&next_ops, &nxdata, handle,
487 buf, count, offset, flags, err);
488 else
489 return f->backend.next->pwrite (f->backend.next, conn,
490 buf, count, offset, flags, err);
493 static int
494 filter_flush (struct backend *b, struct connection *conn, uint32_t flags,
495 int *err)
497 struct backend_filter *f = container_of (b, struct backend_filter, backend);
498 void *handle = connection_get_handle (conn, f->backend.i);
499 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
501 assert (flags == 0);
503 debug ("flush flags=0x%" PRIx32, flags);
505 if (f->filter.flush)
506 return f->filter.flush (&next_ops, &nxdata, handle, flags, err);
507 else
508 return f->backend.next->flush (f->backend.next, conn, flags, err);
511 static int
512 filter_trim (struct backend *b, struct connection *conn,
513 uint32_t count, uint64_t offset,
514 uint32_t flags, int *err)
516 struct backend_filter *f = container_of (b, struct backend_filter, backend);
517 void *handle = connection_get_handle (conn, f->backend.i);
518 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
520 assert (flags == 0);
522 debug ("trim count=%" PRIu32 " offset=%" PRIu64 " flags=0x%" PRIx32,
523 count, offset, flags);
525 if (f->filter.trim)
526 return f->filter.trim (&next_ops, &nxdata, handle, count, offset, flags,
527 err);
528 else
529 return f->backend.next->trim (f->backend.next, conn, count, offset, flags,
530 err);
533 static int
534 filter_zero (struct backend *b, struct connection *conn,
535 uint32_t count, uint64_t offset, uint32_t flags, int *err)
537 struct backend_filter *f = container_of (b, struct backend_filter, backend);
538 void *handle = connection_get_handle (conn, f->backend.i);
539 struct b_conn nxdata = { .b = f->backend.next, .conn = conn };
541 assert (!(flags & ~(NBDKIT_FLAG_MAY_TRIM | NBDKIT_FLAG_FUA)));
543 debug ("zero count=%" PRIu32 " offset=%" PRIu64 " flags=0x%" PRIx32,
544 count, offset, flags);
546 if (f->filter.zero)
547 return f->filter.zero (&next_ops, &nxdata, handle,
548 count, offset, flags, err);
549 else
550 return f->backend.next->zero (f->backend.next, conn,
551 count, offset, flags, err);
554 static struct backend filter_functions = {
555 .free = filter_free,
556 .thread_model = filter_thread_model,
557 .name = filter_name,
558 .plugin_name = plugin_name,
559 .usage = filter_usage,
560 .version = filter_version,
561 .dump_fields = filter_dump_fields,
562 .config = filter_config,
563 .config_complete = filter_config_complete,
564 .open = filter_open,
565 .prepare = filter_prepare,
566 .finalize = filter_finalize,
567 .close = filter_close,
568 .get_size = filter_get_size,
569 .can_write = filter_can_write,
570 .can_flush = filter_can_flush,
571 .is_rotational = filter_is_rotational,
572 .can_trim = filter_can_trim,
573 .pread = filter_pread,
574 .pwrite = filter_pwrite,
575 .flush = filter_flush,
576 .trim = filter_trim,
577 .zero = filter_zero,
580 /* Register and load a filter. */
581 struct backend *
582 filter_register (struct backend *next, size_t index, const char *filename,
583 void *dl, struct nbdkit_filter *(*filter_init) (void))
585 struct backend_filter *f;
586 const struct nbdkit_filter *filter;
587 size_t i, len;
589 f = calloc (1, sizeof *f);
590 if (f == NULL) {
591 out_of_memory:
592 perror ("strdup");
593 exit (EXIT_FAILURE);
596 f->backend = filter_functions;
597 f->backend.next = next;
598 f->backend.i = index;
599 f->filename = strdup (filename);
600 if (f->filename == NULL) goto out_of_memory;
601 f->dl = dl;
603 debug ("registering filter %s", f->filename);
605 /* Call the initialization function which returns the address of the
606 * filter's own 'struct nbdkit_filter'.
608 filter = filter_init ();
609 if (!filter) {
610 fprintf (stderr, "%s: %s: filter registration function failed\n",
611 program_name, f->filename);
612 exit (EXIT_FAILURE);
615 /* We do not provide API or ABI guarantees for filters, other than
616 * the ABI position of _api_version that will let us diagnose
617 * mismatch when the API changes.
619 if (filter->_api_version != NBDKIT_FILTER_API_VERSION) {
620 fprintf (stderr, "%s: %s: filter is incompatible with this version of nbdkit (_api_version = %d)\n",
621 program_name, f->filename, filter->_api_version);
622 exit (EXIT_FAILURE);
625 f->filter = *filter;
627 /* Only filter.name is required. */
628 if (f->filter.name == NULL) {
629 fprintf (stderr, "%s: %s: filter must have a .name field\n",
630 program_name, f->filename);
631 exit (EXIT_FAILURE);
634 len = strlen (f->filter.name);
635 if (len == 0) {
636 fprintf (stderr, "%s: %s: filter.name field must not be empty\n",
637 program_name, f->filename);
638 exit (EXIT_FAILURE);
640 for (i = 0; i < len; ++i) {
641 if (!((f->filter.name[i] >= '0' && f->filter.name[i] <= '9') ||
642 (f->filter.name[i] >= 'a' && f->filter.name[i] <= 'z') ||
643 (f->filter.name[i] >= 'A' && f->filter.name[i] <= 'Z'))) {
644 fprintf (stderr, "%s: %s: filter.name ('%s') field must contain only ASCII alphanumeric characters\n",
645 program_name, f->filename, f->filter.name);
646 exit (EXIT_FAILURE);
650 /* Copy the module's name into local storage, so that filter.name
651 * survives past unload.
653 f->name = strdup (f->filter.name);
654 if (f->name == NULL) {
655 perror ("strdup");
656 exit (EXIT_FAILURE);
659 debug ("registered filter %s (name %s)", f->filename, f->name);
661 /* Call the on-load callback if it exists. */
662 debug ("%s: load", f->filename);
663 if (f->filter.load)
664 f->filter.load ();
666 return (struct backend *) f;