On newer Linux, fallocate() can more efficiently write zeroes
without punching holes. When this mode is supported, use it
instead of falling back to write (while still gracefully falling
back to the write method if it fails with EOPNOTSUPP).
Also fix a typo in an error message in the previous commit.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
plugins/file/file.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index bd7a9c1..2d32615 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -254,6 +254,7 @@ static int
file_zero (void *handle, uint32_t count, uint64_t offset, int may_trim)
{
struct handle *h = handle;
+ int r = -1;
if (wdelayms > 0) {
const struct timespec ts = {
@@ -265,18 +266,28 @@ file_zero (void *handle, uint32_t count, uint64_t offset, int
may_trim)
#ifdef FALLOC_FL_PUNCH_HOLE
if (may_trim) {
- int r = fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- offset, count);
+ r = fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ offset, count);
if (r == -1 && errno != EOPNOTSUPP) {
- nbdkit_error ("pwrite: %m");
+ nbdkit_error ("zero: %m");
}
+ /* PUNCH_HOLE is older; if it is not supported, it is likely that
+ ZERO_RANGE will not work either, so fall back to write. */
return r;
}
#endif
+#ifdef FALLOC_FL_ZERO_RANGE
+ r = fallocate (h->fd, FALLOC_FL_ZERO_RANGE, offset, count);
+ if (r == -1 && errno != EOPNOTSUPP) {
+ nbdkit_error ("zero: %m");
+ }
+#else
/* Trigger a fall back to writing */
errno = EOPNOTSUPP;
- return -1;
+#endif
+
+ return r;
}
/* Flush the file to disk. */
--
2.9.3