Update Red Hat Copyright Notices
[nbdkit.git] / filters / nozero / nozero.c
blob09fd517f76f062e593974113d98c09be1cb0cd45
1 /* nbdkit
2 * Copyright Red Hat
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 <stdbool.h>
40 #include <assert.h>
41 #include <errno.h>
43 #include <nbdkit-filter.h>
45 #include "minmax.h"
47 /* IGNORE is defined as a macro in Windows headers files ... */
48 #ifdef IGNORE
49 #undef IGNORE
50 #endif
52 static enum ZeroMode {
53 NONE,
54 EMULATE,
55 NOTRIM,
56 PLUGIN,
57 } zeromode;
59 static enum FastZeroMode {
60 DEFAULT,
61 SLOW,
62 IGNORE,
63 NOFAST,
64 } fastzeromode;
66 static int
67 nozero_config (nbdkit_next_config *next, nbdkit_backend *nxdata,
68 const char *key, const char *value)
70 if (strcmp (key, "zeromode") == 0) {
71 if (strcmp (value, "emulate") == 0)
72 zeromode = EMULATE;
73 else if (strcmp (value, "notrim") == 0)
74 zeromode = NOTRIM;
75 else if (strcmp (value, "plugin") == 0)
76 zeromode = PLUGIN;
77 else if (strcmp (value, "none") != 0) {
78 nbdkit_error ("unknown zeromode '%s'", value);
79 return -1;
81 return 0;
84 if (strcmp (key, "fastzeromode") == 0) {
85 if (strcmp (value, "none") == 0)
86 fastzeromode = NOFAST;
87 else if (strcmp (value, "ignore") == 0)
88 fastzeromode = IGNORE;
89 else if (strcmp (value, "slow") == 0)
90 fastzeromode = SLOW;
91 else if (strcmp (value, "default") != 0) {
92 nbdkit_error ("unknown fastzeromode '%s'", value);
93 return -1;
95 return 0;
98 return next (nxdata, key, value);
101 #define nozero_config_help \
102 "zeromode=<MODE> One of 'none' (default), 'emulate', 'notrim', 'plugin'.\n" \
103 "fastzeromode=<MODE> One of 'default', 'none', 'slow', 'ignore'.\n"
105 /* Check that desired mode is supported by plugin. */
106 static int
107 nozero_prepare (nbdkit_next *next, void *handle,
108 int readonly)
110 int r;
112 /* If we are opened readonly, this filter has no impact */
113 if (readonly)
114 return 0;
116 if (zeromode == NOTRIM || zeromode == PLUGIN) {
117 r = next->can_zero (next);
118 if (r == -1)
119 return -1;
120 if (!r) {
121 nbdkit_error ("zeromode '%s' requires plugin zero support",
122 zeromode == NOTRIM ? "notrim" : "plugin");
123 return -1;
126 return 0;
129 /* Advertise desired WRITE_ZEROES mode. */
130 static int
131 nozero_can_zero (nbdkit_next *next, void *handle)
133 switch (zeromode) {
134 case NONE:
135 return NBDKIT_ZERO_NONE;
136 case EMULATE:
137 return NBDKIT_ZERO_EMULATE;
138 default:
139 return next->can_zero (next);
143 /* Advertise desired FAST_ZERO mode. */
144 static int
145 nozero_can_fast_zero (nbdkit_next *next,
146 void *handle)
148 if (zeromode == NONE)
149 return 0;
150 if (zeromode != EMULATE && fastzeromode == DEFAULT)
151 return next->can_fast_zero (next);
152 return fastzeromode != NOFAST;
155 static int
156 nozero_zero (nbdkit_next *next,
157 void *handle, uint32_t count, uint64_t offs, uint32_t flags,
158 int *err)
160 assert (zeromode != NONE && zeromode != EMULATE);
161 if (flags & NBDKIT_FLAG_FAST_ZERO) {
162 assert (fastzeromode != NOFAST);
163 if (fastzeromode == SLOW) {
164 *err = ENOTSUP;
165 return -1;
167 if (fastzeromode == IGNORE)
168 flags &= ~NBDKIT_FLAG_FAST_ZERO;
171 if (zeromode == NOTRIM)
172 flags &= ~NBDKIT_FLAG_MAY_TRIM;
174 return next->zero (next, count, offs, flags, err);
177 static struct nbdkit_filter filter = {
178 .name = "nozero",
179 .longname = "nbdkit nozero filter",
180 .config = nozero_config,
181 .config_help = nozero_config_help,
182 .prepare = nozero_prepare,
183 .can_zero = nozero_can_zero,
184 .can_fast_zero = nozero_can_fast_zero,
185 .zero = nozero_zero,
188 NBDKIT_REGISTER_FILTER (filter)