When the byte range for copy_file_range(2) doesn't go to EOF on the
output file and there is a hole in the input file, a hole must be
"punched" in the output file. This is done by writing a block of bytes
all set to 0.
Without this patch, the write is done unconditionally which meant that,
if the output file already had a hole in that byte range, a unneeded data block
of all 0 bytes would be allocated.
This patch adds code to check for a hole in the output file, so it can
skip doing the write if there is already a hole in that byte range of
the output file. This avoids unnecessary allocation of blocks to the
output file.
Details
Running the same tests I've already developed for copy_file_range(2) and
checking block allocations for the input and output files via "ls -ls".
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Skipped - Unit
Tests Skipped - Build Status
Buildable 25678
Event Timeline
Replied to kib@'s comments inline.
kern/vfs_vnops.c | ||
---|---|---|
2812 | Yes. And since the NFSv4.2 server takes the rangelocks as well, the NFSv4.2 Slightly off topic, but I have been thinking that the NFS server should take | |
2822 | Good point. I was thinking that it didn't need to panic(), since copy_file_range(2) Do you think a KASSERT()/panic() is better? |
This version of the patch has the INVARIANTS printf() replaced by a KASSERT().
It also has KASSERT()s added for the results of FIOSEEKDATA/FIOSEEKHOLE.
The main change is that it now does a sanity check for dataoff == holeoff,
which I believe could happen if another thread were to do a truncate()
followed by a write() between the two VOP_IOCTL() calls.
(As noted in the comment for it.)
kern/vfs_vnops.c | ||
---|---|---|
2812 | Rangelocks only make sense when the locked ranges correspond to the user-initiated reads and writes. I have no idea about NFSv4.x, but for plain old v3 server I am sure that NFS client' initiated RPCs for reads and writes typically do not match user operations. Instead, they are driven by the buffer caching and clustering. In other words, for NFS server serving the same file to several clients, rangelocking is probably useless. Rangelocking on NFS server might be somewhat useful when the remotely accessed file is also accessed by the local userspace. In this case, I think, local operations would see more consistent results. |
Replied to inline comment.
kern/vfs_vnops.c | ||
---|---|---|
2812 | Yes, agreed with all of that. The reason I was thinking of adding it is that the NFSv4.2 Copy operation will loop on I added the "dataoff == holeoff" check to try and at least make sure no crashes |
This version of the patch adds an additional sanity check for
the results from VOP_IOCTL(). This change can only have an effect
for a non-INVARIANTS kernel where one of the VOP_IOCTL()s
return a bogus offset.
It ensures a reasonable positive value for xfer2 is returned for this case.
Only change is a modified comment explaining how FIOSEEKHOLE might
find the same offset as FIOSEEKDATA already has returned for the file.