]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
Fix truncate(2) mtime and ctime handling
authorLOLi <loli10K@users.noreply.github.com>
Mon, 13 Nov 2017 17:24:26 +0000 (18:24 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 13 Nov 2017 17:24:26 +0000 (09:24 -0800)
commit99834d1950f654d08585b61a1b0b4458d3d9e100
tree0469f2f351adefb974c5202c54a7bdc03d5e0e13
parent13042a6ccdf3450a758511c4b64e800a371bb891
Fix truncate(2) mtime and ctime handling

On Linux, ftruncate(2) always changes the file timestamps, even if the
file size is not changed. However, in case of a successfull
truncate(2), the timestamps are updated only if the file size changes.
This translates to the VFS calling the ZFS Posix Layer "setattr"
function (zpl_setattr) with ATTR_MTIME and ATTR_CTIME unconditionally
set on the iattr mask only when doing a ftruncate(2), while the
truncate(2) is left to the filesystem implementation to be dealt with.

This behaviour is consistent with POSIX:2004/SUSv3 specifications
where there's no explicit requirement for file size changes to update
the timestamps only for ftruncate(2):

http://pubs.opengroup.org/onlinepubs/009695399/functions/truncate.html
http://pubs.opengroup.org/onlinepubs/009695399/functions/ftruncate.html

This has been later updated in POSIX:2008/SUSv4 where, for both
truncate(2)/ftruncate(2), there's no mention of this size change
requirement:

http://austingroupbugs.net/view.php?id=489
http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html
http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html

Unfortunately the Linux VFS is still calling into the ZPL without
ATTR_MTIME/ATTR_CTIME set in the truncate(2) case: we fix this by
explicitly updating the timestamps when detecting the ATTR_SIZE bit,
which is always set in do_truncate(), on the iattr mask.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #6811
Closes #6819
module/zfs/zfs_vnops.c
tests/runfiles/linux.run
tests/zfs-tests/include/math.shlib
tests/zfs-tests/tests/functional/truncate/.gitignore [new file with mode: 0644]
tests/zfs-tests/tests/functional/truncate/Makefile.am
tests/zfs-tests/tests/functional/truncate/truncate_test.c [new file with mode: 0644]
tests/zfs-tests/tests/functional/truncate/truncate_timestamps.ksh [new file with mode: 0755]