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
42 #include <nbdkit-filter.h>
54 fua_config (nbdkit_next_config
*next
, nbdkit_backend
*nxdata
,
55 const char *key
, const char *value
)
57 if (strcmp (key
, "fuamode") == 0) {
58 if (strcmp (value
, "none") == 0)
60 if (strcmp (value
, "emulate") == 0)
62 else if (strcmp (value
, "native") == 0)
64 else if (strcmp (value
, "force") == 0)
66 else if (strcmp (value
, "pass") == 0)
68 else if (strcmp (value
, "discard") == 0)
71 nbdkit_error ("unknown fuamode '%s'", value
);
76 return next (nxdata
, key
, value
);
79 #define fua_config_help \
80 "fuamode=<MODE> One of 'none' (default), 'emulate', 'native',\n" \
83 /* Check that desired mode is supported by plugin. */
85 fua_prepare (nbdkit_next
*next
, void *handle
,
90 /* If we are opened readonly, this filter has no impact */
100 r
= next
->can_flush (next
);
104 nbdkit_error ("fuamode 'emulate' requires plugin flush support");
110 r
= next
->can_fua (next
);
113 if (r
== NBDKIT_FUA_NONE
) {
114 nbdkit_error ("fuamode '%s' requires plugin fua support",
115 fuamode
== EMULATE
? "emulate" : "force");
123 /* Advertise proper flush support. */
125 fua_can_flush (nbdkit_next
*next
, void *handle
)
130 return 1; /* Advertise our no-op flush, even if plugin lacks it */
135 return next
->can_flush (next
);
140 /* Advertise desired fua mode. */
142 fua_can_fua (nbdkit_next
*next
, void *handle
)
146 return NBDKIT_FUA_NONE
;
148 return NBDKIT_FUA_EMULATE
;
152 return NBDKIT_FUA_NATIVE
;
154 return next
->can_fua (next
);
160 fua_pwrite (nbdkit_next
*next
,
161 void *handle
, const void *buf
, uint32_t count
, uint64_t offs
,
162 uint32_t flags
, int *err
)
165 bool need_flush
= false;
169 assert (!(flags
& NBDKIT_FLAG_FUA
));
172 if (flags
& NBDKIT_FLAG_FUA
) {
174 flags
&= ~NBDKIT_FLAG_FUA
;
181 flags
|= NBDKIT_FLAG_FUA
;
184 flags
&= ~NBDKIT_FLAG_FUA
;
187 r
= next
->pwrite (next
, buf
, count
, offs
, flags
, err
);
188 if (r
!= -1 && need_flush
)
189 r
= next
->flush (next
, 0, err
);
194 fua_flush (nbdkit_next
*next
,
195 void *handle
, uint32_t flags
, int *err
)
199 return 0; /* Nothing to flush, since all writes already used FUA */
201 return 0; /* Drop flushes! */
206 return next
->flush (next
, flags
, err
);
212 fua_trim (nbdkit_next
*next
,
213 void *handle
, uint32_t count
, uint64_t offs
, uint32_t flags
,
217 bool need_flush
= false;
221 assert (!(flags
& NBDKIT_FLAG_FUA
));
224 if (flags
& NBDKIT_FLAG_FUA
) {
226 flags
&= ~NBDKIT_FLAG_FUA
;
233 flags
|= NBDKIT_FLAG_FUA
;
236 flags
&= ~NBDKIT_FLAG_FUA
;
239 r
= next
->trim (next
, count
, offs
, flags
, err
);
240 if (r
!= -1 && need_flush
)
241 r
= next
->flush (next
, 0, err
);
246 fua_zero (nbdkit_next
*next
,
247 void *handle
, uint32_t count
, uint64_t offs
, uint32_t flags
,
251 bool need_flush
= false;
255 assert (!(flags
& NBDKIT_FLAG_FUA
));
258 if (flags
& NBDKIT_FLAG_FUA
) {
260 flags
&= ~NBDKIT_FLAG_FUA
;
267 flags
|= NBDKIT_FLAG_FUA
;
270 flags
&= ~NBDKIT_FLAG_FUA
;
273 r
= next
->zero (next
, count
, offs
, flags
, err
);
274 if (r
!= -1 && need_flush
)
275 r
= next
->flush (next
, 0, err
);
279 static struct nbdkit_filter filter
= {
281 .longname
= "nbdkit fua filter",
282 .config
= fua_config
,
283 .config_help
= fua_config_help
,
284 .prepare
= fua_prepare
,
285 .can_flush
= fua_can_flush
,
286 .can_fua
= fua_can_fua
,
287 .pwrite
= fua_pwrite
,
293 NBDKIT_REGISTER_FILTER (filter
)