All of lore.kernel.org
 help / color / mirror / Atom feed
* fallocate: fix for --dig-holes at end of files
@ 2020-09-10 20:16 Gero Treuner
  2020-09-14 10:06 ` Karel Zak
  0 siblings, 1 reply; 2+ messages in thread
From: Gero Treuner @ 2020-09-10 20:16 UTC (permalink / raw)
  To: util-linux

[-- Attachment #1: Type: text/plain, Size: 2265 bytes --]

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

[-- Attachment #2: 0001-fallocate-fix-dig-holes-at-end-of-files.patch --]
[-- Type: text/x-diff, Size: 837 bytes --]

From 7b3e0a3921ca7c84fa3913b2bb916be938dfe04a Mon Sep 17 00:00:00 2001
From: Gero Treuner <gero@70t.de>
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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: fallocate: fix for --dig-holes at end of files
  2020-09-10 20:16 fallocate: fix for --dig-holes at end of files Gero Treuner
@ 2020-09-14 10:06 ` Karel Zak
  0 siblings, 0 replies; 2+ messages in thread
From: Karel Zak @ 2020-09-14 10:06 UTC (permalink / raw)
  To: Gero Treuner; +Cc: util-linux

On Thu, Sep 10, 2020 at 10:16:09PM +0200, Gero Treuner wrote:
> 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.

Good catch. Applied, thanks.

(Please, use Signed-off-by: line in your commit message next time.)

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-09-14 10:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-10 20:16 fallocate: fix for --dig-holes at end of files Gero Treuner
2020-09-14 10:06 ` Karel Zak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.