Created attachment 208465 [details] Regression test ctime should be updated whenever a file's link count changes. If its destination is multiply-linked, rename(2) will decrease its link count, and therefore should update its ctime. ZFS complies, but as of r353698 UFS does not. I have two test cases demonstrating the problem: a standalone C program (attached), and a pjdfstest test case (https://github.com/pjd/pjdfstest/pull/37). Standalone test's output on UFS: $ /tmp/rename_ctime_link nlink: 2 -> 1 ctime 1571584801.941284000 -> 1571584801.941284000 Renamed failed to update destination's ctime. And on ZFS: $ /tmp/rename_ctime_link nlink: 2 -> 1 ctime 1571584883.332680000 -> 1571584884.384654000 Everything ok! $ uname -a FreeBSD fbsd-head.lauralan.noip.me 13.0-CURRENT FreeBSD 13.0-CURRENT #50 r353698: Thu Oct 17 15:17:38 MDT 2019 somers@fbsd-head.lauralan.noip.me:/usr/obj/usr/home/somers/freebsd/base/head/amd64.amd64/sys/GENERIC amd64 $ mount /dev/vtbd0p2 on / (ufs, local, journaled soft-updates) devfs on /dev (devfs) 192.168.0.2:/home on /usr/home (nfs, nfsv4acls) tank on /tank (zfs, local, nfsv4acls)
Could you bisect to find the specific change that caused this breakage?
Kirk, are you sure that it ever worked? I'm not. In case I wasn't clear, my two test cases are freshly written.
(In reply to Alan Somers from comment #2) OK, I thought that you were reporting that something had stopped working. Do you have access to an older system (11.X say) that you can test?
The oldest VM I have is 11.2-STABLE #0 r339079. I just checked there, and the test still fails.
Created attachment 208490 [details] Version of the test case that also works on 11.2-STABLE
Created attachment 208499 [details] fix to avoid delayed ctime update
Your test passes on a filesystem without soft updates which was my first clue. It also passes if you add to your test program a usleep(1000000) call after the call to rename() which was the second clue. When running with soft updates, the ctime is not updated until the soft updates background process has settled all the needed I/O operations. Your test program stat()s it immediately after the rename() has returned, but soft updates has not finished with the processing, so the ctime has not yet been updated. The attached patch causes the ctime to be updated immediately during the rename() which makes your test happy. The ctime will be updated again when soft updates has finished its processing because that is the time that is correct from the perspective of programs that look at the disk (like dump). This change does not cause any extra I/O to be done, it just ensures that stat() updates the ctime before handing it back to you.
(In reply to Alan Somers from comment #5) Let me know if my patch solves your problem.
Works for me!
A commit references this bug: Author: mckusick Date: Thu Oct 24 21:28:37 UTC 2019 New revision: 354050 URL: https://svnweb.freebsd.org/changeset/base/354050 Log: After the unlink() of one name of a file with multiple links, a stat() of one of the remaining names of the file does not show an updated ctime (inode modification time) until several seconds after the unlink() completes. The problem only occurs when the filesystem is running with soft updates enabled. When running with soft updates, the ctime is not updated until the soft updates background process has settled all the needed I/O operations. This commit causes the ctime to be updated immediately during the unlink(). A side effect of this change is that the ctime is updated again when soft updates has finished its processing because that is the time that is correct from the perspective of programs that look at the disk (like dump). This change does not cause any extra I/O to be done, it just ensures that stat() updates the ctime before handing it back. PR: 241373 Reported by: Alan Somers Tested by: Alan Somers MFC after: 3 days Sponsored by: Netflix Changes: head/sys/ufs/ufs/ufs_lookup.c
MFC'ed to 11-stable and 12-stable