fallocate: fix for --dig-holes at end of files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

I discovered that making a file sparse with "fallocate -d filename"
fails on the last block of a file, because - usually being partial - the
system call only zeroes that part instead of deallocating the block. See
man fallocate(2) - section "Deallocating file space".

The expected call is punching the whole block beyond eof, which doesn't
change the file length because of flag FALLOC_FL_KEEP_SIZE.


The following commands illustrate this (all on Debian buster with a real
existing file).


Behaviour with fallocate from system: file gets fragmented

user:~/dev/util-linux$ cp /usr/lib/locale/C.UTF-8/LC_CTYPE .
user:~/dev/util-linux$ /usr/sbin/filefrag -e ./LC_CTYPE
Filesystem type is: 9123683e
File size of ./LC_CTYPE is 200752 (50 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected:
flags:
   0:        0..      49:   22403653..  22403702:     50:
last,eof
./LC_CTYPE: 1 extent found
user:~/dev/util-linux$ fallocate -v -d ./LC_CTYPE 
./LC_CTYPE: 48 B (48 bytes) converted to sparse holes.
user:~/dev/util-linux$ /usr/sbin/filefrag -e ./LC_CTYPE
Filesystem type is: 9123683e
File size of ./LC_CTYPE is 200752 (50 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected:
flags:
   0:        0..      48:   22403653..  22403701:     49:            
   1:       49..      49:   22385666..  22385666:      1:   22403702:
last,eof
./LC_CTYPE: 2 extents found
user:~/dev/util-linux$ du -s ./LC_CTYPE 
200     ./LC_CTYPE


Behaviour with fixed fallocate: file becomes sparse

user:~/dev/util-linux$ cp /usr/lib/locale/C.UTF-8/LC_CTYPE .
user:~/dev/util-linux$ ./fallocate -v -d ./LC_CTYPE 
./LC_CTYPE: 48 B (48 bytes) converted to sparse holes.
user:~/dev/util-linux$ /usr/sbin/filefrag -e ./LC_CTYPE
Filesystem type is: 9123683e
File size of ./LC_CTYPE is 200752 (50 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected:
flags:
   0:        0..      48:   22346286..  22346334:     49:
last
./LC_CTYPE: 1 extent found
user:~/dev/util-linux$ du -s ./LC_CTYPE 
196     ./LC_CTYPE


Please consider the attached patch. I also tested with other files
containing real holes (instead of a notch) that function is preserved.


Kind regards,
   Gero
>From 7b3e0a3921ca7c84fa3913b2bb916be938dfe04a Mon Sep 17 00:00:00 2001
From: Gero Treuner <gero@xxxxxx>
Date: Thu, 10 Sep 2020 21:43:03 +0200
Subject: [PATCH] fallocate: fix --dig-holes at end of files

---
 sys-utils/fallocate.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c
index 014b94624..ba97092fc 100644
--- a/sys-utils/fallocate.c
+++ b/sys-utils/fallocate.c
@@ -264,8 +264,11 @@ static void dig_holes(int fd, off_t file_off, off_t len)
 			off += rsz;
 		}
 		if (hole_sz) {
+			off_t alloc_sz = hole_sz;
+			if (off >= end)
+				alloc_sz += st.st_blksize;		/* meet block boundary */
 			xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
-					hole_start, hole_sz);
+					hole_start, alloc_sz);
 			ct += hole_sz;
 		}
 		file_off = off;
-- 
2.20.1


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux