Fix issues Eric found in the original patch:
https://www.redhat.com/archives/libguestfs/2018-July/msg00072.html
- When handling ENODEV, the caller is expecting ENOTSUPP to trigger
fallback.
- ENODEV should be ignored in file_trim.
Tested only on Fedora 28.
---
plugins/file/file.c | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/plugins/file/file.c b/plugins/file/file.c
index a7c07fb..4210adb 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -50,6 +50,21 @@
static char *filename = NULL;
+#if defined(FALLOC_FL_PUNCH_HOLE) || defined(FALLOC_FL_ZERO_RANGE)
+static int
+do_fallocate(int fd, int mode, off_t offset, off_t len)
+{
+ int r = -1;
+ r = fallocate (fd, mode, offset, len);
+ /* kernel 3.10 fails with ENODEV for block device. Kernel >= 4.9 fails
+ with EOPNOTSUPP in this case. Normlize errno to simplify callers. */
+ if (r == -1 && errno == ENODEV) {
+ errno = EOPNOTSUPP;
+ }
+ return r;
+}
+#endif
+
static void
file_unload (void)
{
@@ -241,9 +256,9 @@ file_zero (void *handle, uint32_t count, uint64_t offset, int
may_trim)
#ifdef FALLOC_FL_PUNCH_HOLE
if (may_trim) {
- r = fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- offset, count);
- if (r == -1 && errno != EOPNOTSUPP && errno != ENODEV) {
+ r = do_fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ offset, count);
+ if (r == -1 && errno != EOPNOTSUPP) {
nbdkit_error ("zero: %m");
}
/* PUNCH_HOLE is older; if it is not supported, it is likely that
@@ -253,8 +268,8 @@ file_zero (void *handle, uint32_t count, uint64_t offset, int
may_trim)
#endif
#ifdef FALLOC_FL_ZERO_RANGE
- r = fallocate (h->fd, FALLOC_FL_ZERO_RANGE, offset, count);
- if (r == -1 && errno != EOPNOTSUPP && errno != ENODEV) {
+ r = do_fallocate (h->fd, FALLOC_FL_ZERO_RANGE, offset, count);
+ if (r == -1 && errno != EOPNOTSUPP) {
nbdkit_error ("zero: %m");
}
#else
@@ -288,11 +303,11 @@ file_trim (void *handle, uint32_t count, uint64_t offset)
struct handle *h = handle;
/* Trim is advisory; we don't care if it fails for anything other
- * than EIO, EPERM, or ENODEV (kernel 3.10) */
- r = fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- offset, count);
+ * than EIO or EPERM. */
+ r = do_fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ offset, count);
if (r < 0) {
- if (errno != EPERM && errno != EIO && errno != ENODEV) {
+ if (errno != EPERM && errno != EIO) {
nbdkit_debug ("ignoring failed fallocate during trim: %m");
r = 0;
}
--
2.17.1