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
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
44 /* We extend the generic backend struct with extra fields relating
47 struct backend_filter
{
48 struct backend backend
;
49 struct nbdkit_filter filter
;
52 /* Literally a backend + a connection pointer. This is the
53 * implementation of ‘void *nxdata’ in the filter API.
57 struct connection
*conn
;
60 /* Note this frees the whole chain. */
62 filter_free (struct backend
*b
)
64 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
66 b
->next
->free (b
->next
);
68 backend_unload (b
, f
->filter
.unload
);
73 filter_thread_model (struct backend
*b
)
75 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
76 int filter_thread_model
= NBDKIT_THREAD_MODEL_PARALLEL
;
77 int thread_model
= b
->next
->thread_model (b
->next
);
79 if (f
->filter
.thread_model
) {
80 filter_thread_model
= f
->filter
.thread_model ();
81 if (filter_thread_model
== -1)
85 if (filter_thread_model
< thread_model
) /* more serialized */
86 thread_model
= filter_thread_model
;
91 /* This is actually passing the request through to the final plugin,
92 * hence the function name.
95 plugin_name (struct backend
*b
)
97 return b
->next
->plugin_name (b
->next
);
101 filter_version (struct backend
*b
)
103 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
105 return f
->filter
._version
;
109 filter_usage (struct backend
*b
)
111 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
114 printf ("filter: %s", b
->name
);
115 if (f
->filter
.longname
)
116 printf (" (%s)", f
->filter
.longname
);
118 printf ("(%s)\n", b
->filename
);
119 if (f
->filter
.description
) {
120 printf ("%s", f
->filter
.description
);
121 if ((p
= strrchr (f
->filter
.description
, '\n')) == NULL
|| p
[1])
124 if (f
->filter
.config_help
) {
125 printf ("%s", f
->filter
.config_help
);
126 if ((p
= strrchr (f
->filter
.config_help
, '\n')) == NULL
|| p
[1])
132 filter_dump_fields (struct backend
*b
)
134 b
->next
->dump_fields (b
->next
);
138 next_config (void *nxdata
, const char *key
, const char *value
)
140 struct backend
*b
= nxdata
;
141 b
->config (b
, key
, value
);
146 filter_config (struct backend
*b
, const char *key
, const char *value
)
148 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
150 debug ("%s: config key=%s, value=%s",
151 b
->name
, key
, value
);
153 if (f
->filter
.config
) {
154 if (f
->filter
.config (next_config
, b
->next
, key
, value
) == -1)
158 b
->next
->config (b
->next
, key
, value
);
162 next_config_complete (void *nxdata
)
164 struct backend
*b
= nxdata
;
165 b
->config_complete (b
);
170 filter_config_complete (struct backend
*b
)
172 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
174 debug ("%s: config_complete", b
->name
);
176 if (f
->filter
.config_complete
) {
177 if (f
->filter
.config_complete (next_config_complete
, b
->next
) == -1)
181 b
->next
->config_complete (b
->next
);
185 next_preconnect (void *nxdata
, int readonly
)
187 struct b_conn
*b_conn
= nxdata
;
188 return b_conn
->b
->preconnect (b_conn
->b
, b_conn
->conn
, readonly
);
192 filter_preconnect (struct backend
*b
, struct connection
*conn
, int readonly
)
194 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
195 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
197 debug ("%s: preconnect", b
->name
);
199 if (f
->filter
.preconnect
)
200 return f
->filter
.preconnect (next_preconnect
, &nxdata
, readonly
);
202 return b
->next
->preconnect (b
->next
, conn
, readonly
);
205 /* magic_config_key only applies to plugins, so this passes the
206 * request through to the plugin (hence the name).
209 plugin_magic_config_key (struct backend
*b
)
211 return b
->next
->magic_config_key (b
->next
);
215 next_open (void *nxdata
, int readonly
)
217 struct b_conn
*b_conn
= nxdata
;
219 return backend_open (b_conn
->b
, b_conn
->conn
, readonly
);
223 filter_open (struct backend
*b
, struct connection
*conn
, int readonly
)
225 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
226 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
228 /* Most filters will call next_open first, resulting in
229 * inner-to-outer ordering.
232 return f
->filter
.open (next_open
, &nxdata
, readonly
);
233 else if (backend_open (b
->next
, conn
, readonly
) == -1)
236 return NBDKIT_HANDLE_NOT_NEEDED
;
240 filter_close (struct backend
*b
, struct connection
*conn
, void *handle
)
242 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
244 if (handle
&& f
->filter
.close
)
245 f
->filter
.close (handle
);
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’).
256 next_reopen (void *nxdata
, int readonly
)
258 struct b_conn
*b_conn
= nxdata
;
259 return backend_reopen (b_conn
->b
, b_conn
->conn
, readonly
);
263 next_get_size (void *nxdata
)
265 struct b_conn
*b_conn
= nxdata
;
266 return backend_get_size (b_conn
->b
, b_conn
->conn
);
270 next_can_write (void *nxdata
)
272 struct b_conn
*b_conn
= nxdata
;
273 return backend_can_write (b_conn
->b
, b_conn
->conn
);
277 next_can_flush (void *nxdata
)
279 struct b_conn
*b_conn
= nxdata
;
280 return backend_can_flush (b_conn
->b
, b_conn
->conn
);
284 next_is_rotational (void *nxdata
)
286 struct b_conn
*b_conn
= nxdata
;
287 return backend_is_rotational (b_conn
->b
, b_conn
->conn
);
291 next_can_trim (void *nxdata
)
293 struct b_conn
*b_conn
= nxdata
;
294 return backend_can_trim (b_conn
->b
, b_conn
->conn
);
298 next_can_zero (void *nxdata
)
300 struct b_conn
*b_conn
= nxdata
;
301 return backend_can_zero (b_conn
->b
, b_conn
->conn
);
305 next_can_fast_zero (void *nxdata
)
307 struct b_conn
*b_conn
= nxdata
;
308 return backend_can_fast_zero (b_conn
->b
, b_conn
->conn
);
312 next_can_extents (void *nxdata
)
314 struct b_conn
*b_conn
= nxdata
;
315 return backend_can_extents (b_conn
->b
, b_conn
->conn
);
319 next_can_fua (void *nxdata
)
321 struct b_conn
*b_conn
= nxdata
;
322 return backend_can_fua (b_conn
->b
, b_conn
->conn
);
326 next_can_multi_conn (void *nxdata
)
328 struct b_conn
*b_conn
= nxdata
;
329 return backend_can_multi_conn (b_conn
->b
, b_conn
->conn
);
333 next_can_cache (void *nxdata
)
335 struct b_conn
*b_conn
= nxdata
;
336 return backend_can_cache (b_conn
->b
, b_conn
->conn
);
340 next_pread (void *nxdata
, void *buf
, uint32_t count
, uint64_t offset
,
341 uint32_t flags
, int *err
)
343 struct b_conn
*b_conn
= nxdata
;
344 return backend_pread (b_conn
->b
, b_conn
->conn
, buf
, count
, offset
, flags
,
349 next_pwrite (void *nxdata
, const void *buf
, uint32_t count
, uint64_t offset
,
350 uint32_t flags
, int *err
)
352 struct b_conn
*b_conn
= nxdata
;
353 return backend_pwrite (b_conn
->b
, b_conn
->conn
, buf
, count
, offset
, flags
,
358 next_flush (void *nxdata
, uint32_t flags
, int *err
)
360 struct b_conn
*b_conn
= nxdata
;
361 return backend_flush (b_conn
->b
, b_conn
->conn
, flags
, err
);
365 next_trim (void *nxdata
, uint32_t count
, uint64_t offset
, uint32_t flags
,
368 struct b_conn
*b_conn
= nxdata
;
369 return backend_trim (b_conn
->b
, b_conn
->conn
, count
, offset
, flags
, err
);
373 next_zero (void *nxdata
, uint32_t count
, uint64_t offset
, uint32_t flags
,
376 struct b_conn
*b_conn
= nxdata
;
377 return backend_zero (b_conn
->b
, b_conn
->conn
, count
, offset
, flags
, err
);
381 next_extents (void *nxdata
, uint32_t count
, uint64_t offset
, uint32_t flags
,
382 struct nbdkit_extents
*extents
, int *err
)
384 struct b_conn
*b_conn
= nxdata
;
385 return backend_extents (b_conn
->b
, b_conn
->conn
, count
, offset
, flags
,
390 next_cache (void *nxdata
, uint32_t count
, uint64_t offset
,
391 uint32_t flags
, int *err
)
393 struct b_conn
*b_conn
= nxdata
;
394 return backend_cache (b_conn
->b
, b_conn
->conn
, count
, offset
, flags
, err
);
397 static struct nbdkit_next_ops next_ops
= {
398 .reopen
= next_reopen
,
399 .get_size
= next_get_size
,
400 .can_write
= next_can_write
,
401 .can_flush
= next_can_flush
,
402 .is_rotational
= next_is_rotational
,
403 .can_trim
= next_can_trim
,
404 .can_zero
= next_can_zero
,
405 .can_fast_zero
= next_can_fast_zero
,
406 .can_extents
= next_can_extents
,
407 .can_fua
= next_can_fua
,
408 .can_multi_conn
= next_can_multi_conn
,
409 .can_cache
= next_can_cache
,
411 .pwrite
= next_pwrite
,
415 .extents
= next_extents
,
420 filter_prepare (struct backend
*b
, struct connection
*conn
, void *handle
,
423 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
424 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
426 if (f
->filter
.prepare
&&
427 f
->filter
.prepare (&next_ops
, &nxdata
, handle
, readonly
) == -1)
434 filter_finalize (struct backend
*b
, struct connection
*conn
, void *handle
)
436 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
437 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
439 if (f
->filter
.finalize
&&
440 f
->filter
.finalize (&next_ops
, &nxdata
, handle
) == -1)
446 filter_get_size (struct backend
*b
, struct connection
*conn
, void *handle
)
448 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
449 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
451 if (f
->filter
.get_size
)
452 return f
->filter
.get_size (&next_ops
, &nxdata
, handle
);
454 return backend_get_size (b
->next
, conn
);
458 filter_can_write (struct backend
*b
, struct connection
*conn
, void *handle
)
460 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
461 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
463 if (f
->filter
.can_write
)
464 return f
->filter
.can_write (&next_ops
, &nxdata
, handle
);
466 return backend_can_write (b
->next
, conn
);
470 filter_can_flush (struct backend
*b
, struct connection
*conn
, void *handle
)
472 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
473 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
475 if (f
->filter
.can_flush
)
476 return f
->filter
.can_flush (&next_ops
, &nxdata
, handle
);
478 return backend_can_flush (b
->next
, conn
);
482 filter_is_rotational (struct backend
*b
, struct connection
*conn
, void *handle
)
484 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
485 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
487 if (f
->filter
.is_rotational
)
488 return f
->filter
.is_rotational (&next_ops
, &nxdata
, handle
);
490 return backend_is_rotational (b
->next
, conn
);
494 filter_can_trim (struct backend
*b
, struct connection
*conn
, void *handle
)
496 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
497 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
499 if (f
->filter
.can_trim
)
500 return f
->filter
.can_trim (&next_ops
, &nxdata
, handle
);
502 return backend_can_trim (b
->next
, conn
);
506 filter_can_zero (struct backend
*b
, struct connection
*conn
, void *handle
)
508 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
509 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
511 if (f
->filter
.can_zero
)
512 return f
->filter
.can_zero (&next_ops
, &nxdata
, handle
);
514 return backend_can_zero (b
->next
, conn
);
518 filter_can_fast_zero (struct backend
*b
, struct connection
*conn
, void *handle
)
520 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
521 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
523 if (f
->filter
.can_fast_zero
)
524 return f
->filter
.can_fast_zero (&next_ops
, &nxdata
, handle
);
526 return backend_can_fast_zero (b
->next
, conn
);
530 filter_can_extents (struct backend
*b
, struct connection
*conn
, void *handle
)
532 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
533 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
535 if (f
->filter
.can_extents
)
536 return f
->filter
.can_extents (&next_ops
, &nxdata
, handle
);
538 return backend_can_extents (b
->next
, conn
);
542 filter_can_fua (struct backend
*b
, struct connection
*conn
, void *handle
)
544 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
545 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
547 if (f
->filter
.can_fua
)
548 return f
->filter
.can_fua (&next_ops
, &nxdata
, handle
);
550 return backend_can_fua (b
->next
, conn
);
554 filter_can_multi_conn (struct backend
*b
, struct connection
*conn
, void *handle
)
556 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
557 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
559 if (f
->filter
.can_multi_conn
)
560 return f
->filter
.can_multi_conn (&next_ops
, &nxdata
, handle
);
562 return backend_can_multi_conn (b
->next
, conn
);
566 filter_can_cache (struct backend
*b
, struct connection
*conn
, void *handle
)
568 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
569 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
571 if (f
->filter
.can_cache
)
572 return f
->filter
.can_cache (&next_ops
, &nxdata
, handle
);
574 return backend_can_cache (b
->next
, conn
);
578 filter_pread (struct backend
*b
, struct connection
*conn
, void *handle
,
579 void *buf
, uint32_t count
, uint64_t offset
,
580 uint32_t flags
, int *err
)
582 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
583 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
586 return f
->filter
.pread (&next_ops
, &nxdata
, handle
,
587 buf
, count
, offset
, flags
, err
);
589 return backend_pread (b
->next
, conn
, buf
, count
, offset
, flags
, err
);
593 filter_pwrite (struct backend
*b
, struct connection
*conn
, void *handle
,
594 const void *buf
, uint32_t count
, uint64_t offset
,
595 uint32_t flags
, int *err
)
597 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
598 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
600 if (f
->filter
.pwrite
)
601 return f
->filter
.pwrite (&next_ops
, &nxdata
, handle
,
602 buf
, count
, offset
, flags
, err
);
604 return backend_pwrite (b
->next
, conn
, buf
, count
, offset
, flags
, err
);
608 filter_flush (struct backend
*b
, struct connection
*conn
, void *handle
,
609 uint32_t flags
, int *err
)
611 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
612 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
615 return f
->filter
.flush (&next_ops
, &nxdata
, handle
, flags
, err
);
617 return backend_flush (b
->next
, conn
, flags
, err
);
621 filter_trim (struct backend
*b
, struct connection
*conn
, void *handle
,
622 uint32_t count
, uint64_t offset
,
623 uint32_t flags
, int *err
)
625 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
626 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
629 return f
->filter
.trim (&next_ops
, &nxdata
, handle
, count
, offset
, flags
,
632 return backend_trim (b
->next
, conn
, count
, offset
, flags
, err
);
636 filter_zero (struct backend
*b
, struct connection
*conn
, void *handle
,
637 uint32_t count
, uint64_t offset
, uint32_t flags
, int *err
)
639 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
640 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
643 return f
->filter
.zero (&next_ops
, &nxdata
, handle
,
644 count
, offset
, flags
, err
);
646 return backend_zero (b
->next
, conn
, count
, offset
, flags
, err
);
650 filter_extents (struct backend
*b
, struct connection
*conn
, void *handle
,
651 uint32_t count
, uint64_t offset
, uint32_t flags
,
652 struct nbdkit_extents
*extents
, int *err
)
654 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
655 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
657 if (f
->filter
.extents
)
658 return f
->filter
.extents (&next_ops
, &nxdata
, handle
,
659 count
, offset
, flags
,
662 return backend_extents (b
->next
, conn
, count
, offset
, flags
,
667 filter_cache (struct backend
*b
, struct connection
*conn
, void *handle
,
668 uint32_t count
, uint64_t offset
,
669 uint32_t flags
, int *err
)
671 struct backend_filter
*f
= container_of (b
, struct backend_filter
, backend
);
672 struct b_conn nxdata
= { .b
= b
->next
, .conn
= conn
};
676 return f
->filter
.cache (&next_ops
, &nxdata
, handle
,
677 count
, offset
, flags
, err
);
679 return backend_cache (b
->next
, conn
, count
, offset
, flags
, err
);
682 static struct backend filter_functions
= {
684 .thread_model
= filter_thread_model
,
685 .plugin_name
= plugin_name
,
686 .usage
= filter_usage
,
687 .version
= filter_version
,
688 .dump_fields
= filter_dump_fields
,
689 .config
= filter_config
,
690 .config_complete
= filter_config_complete
,
691 .magic_config_key
= plugin_magic_config_key
,
692 .preconnect
= filter_preconnect
,
694 .prepare
= filter_prepare
,
695 .finalize
= filter_finalize
,
696 .close
= filter_close
,
697 .get_size
= filter_get_size
,
698 .can_write
= filter_can_write
,
699 .can_flush
= filter_can_flush
,
700 .is_rotational
= filter_is_rotational
,
701 .can_trim
= filter_can_trim
,
702 .can_zero
= filter_can_zero
,
703 .can_fast_zero
= filter_can_fast_zero
,
704 .can_extents
= filter_can_extents
,
705 .can_fua
= filter_can_fua
,
706 .can_multi_conn
= filter_can_multi_conn
,
707 .can_cache
= filter_can_cache
,
708 .pread
= filter_pread
,
709 .pwrite
= filter_pwrite
,
710 .flush
= filter_flush
,
713 .extents
= filter_extents
,
714 .cache
= filter_cache
,
717 /* Register and load a filter. */
719 filter_register (struct backend
*next
, size_t index
, const char *filename
,
720 void *dl
, struct nbdkit_filter
*(*filter_init
) (void))
722 struct backend_filter
*f
;
723 const struct nbdkit_filter
*filter
;
725 f
= calloc (1, sizeof *f
);
731 f
->backend
= filter_functions
;
732 backend_init (&f
->backend
, next
, index
, filename
, dl
, "filter");
734 /* Call the initialization function which returns the address of the
735 * filter's own 'struct nbdkit_filter'.
737 filter
= filter_init ();
739 fprintf (stderr
, "%s: %s: filter registration function failed\n",
740 program_name
, filename
);
744 /* We do not provide API or ABI guarantees for filters, other than
745 * the ABI position and API contents of _api_version and _version to
746 * diagnose mismatch from the current nbdkit version.
748 if (filter
->_api_version
!= NBDKIT_FILTER_API_VERSION
) {
750 "%s: %s: filter is incompatible with this version of nbdkit "
751 "(_api_version = %d, need %d)\n",
752 program_name
, filename
, filter
->_api_version
,
753 NBDKIT_FILTER_API_VERSION
);
756 if (filter
->_version
== NULL
||
757 strcmp (filter
->_version
, PACKAGE_VERSION
) != 0) {
759 "%s: %s: filter is incompatible with this version of nbdkit "
760 "(_version = %s, need %s)\n",
761 program_name
, filename
, filter
->_version
?: "<null>",
768 backend_load (&f
->backend
, f
->filter
.name
, f
->filter
.load
);
770 return (struct backend
*) f
;