]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fallocate: give up when SEEK_HOLE/DATA misbehaves
authorDavid Timber <dxdt@dev.snart.me>
Fri, 20 Mar 2026 02:30:52 +0000 (11:30 +0900)
committerDavid Timber <dxdt@dev.snart.me>
Fri, 20 Mar 2026 02:30:52 +0000 (11:30 +0900)
There's a bug in Linux kernel that renders fallocate in an infinite
loop.

drivers/char/mem.c:

static loff_t null_lseek(struct file *file, loff_t offset, int orig)
{
       return file->f_pos = 0;
}

This is caused by lseek() of /dev/null and /dev/zero always returning 0
regardless of whence. If fallocate is run on /dev/zero or /dev/null
with the option -d or -z, the length to skip in the main loop logic in
dig_holes() is always calculated as zero.

A conforming VFS never behaves like this so it's safe to assume that the
SEEK_DATA and SEEK_HOLE behaviour is broken.

Signed-off-by: David Timber <dxdt@dev.snart.me>
sys-utils/fallocate.c

index c71dda21413fbc6051580b090310c8e34d8b5274..bb056b7ad9b42d312942191d4f13224a28cadc43 100644 (file)
@@ -298,7 +298,7 @@ static void dig_holes(int fd, off_t file_off, off_t len)
                if (file_end && end > file_end)
                        end = file_end;
 
-               if (off < 0 || end < 0)
+               if (off < 0 || end < 0 || off == end)
                        break;
 
 #if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)