Re: [PATCH v7 05/13] fat: make fat_update_time get its own timestamp
From: Jeff Layton <jlayton@kernel.org>
Date: 2023-08-09 17:59:39
Also in:
ceph-devel, linux-btrfs, linux-cifs, linux-f2fs-devel, linux-fsdevel, linux-mm, linux-nfs, linux-unionfs, linux-xfs, lkml, ntfs3, ocfs2-devel, v9fs
On Thu, 2023-08-10 at 02:44 +0900, OGAWA Hirofumi wrote:
Jeff Layton [off-list ref] writes:quoted
On Thu, 2023-08-10 at 00:17 +0900, OGAWA Hirofumi wrote:quoted
Jan Kara [off-list ref] writes:[...]quoted
My mistake re: lazytime vs. relatime, but Jan is correct that this shouldn't break anything there.Actually breaks ("break" means not corrupt fs, means it breaks lazytime optimization). It is just not always, but it should be always for some userspaces.quoted
The logic in the revised generic_update_time is different because FAT is is a bit strange. fat_update_time does extra truncation on the timestamp that it is handed beyond what timestamp_truncate() does. fat_truncate_time is called in many different places too, so I don't feel comfortable making big changes to how that works. In the case of generic_update_time, it calls inode_update_timestamps which returns a mask that shows which timestamps got updated. It then marks the dirty_flags appropriately for what was actually changed. generic_update_time is used across many filesystems so we need to ensure that it's OK to use even when multigrain timestamps are enabled. Those haven't been enabled in FAT though, so I didn't bother, and left it to dirtying the inode in the same way it was before, even though it now fetches its own timestamps from the clock. Given the way that the mtime and ctime are smooshed together in FAT, that seemed reasonable. Is there a particular case or flag combination you're concerned about here?Yes. Because FAT has strange timestamps that different granularity on disk . This is why generic time truncation doesn't work for FAT. Well anyway, my concern is the only following part. In generic_update_time(), S_[CM]TIME are not the cause of I_DIRTY_SYNC if lazytime mode. - if ((flags & S_VERSION) && inode_maybe_inc_iversion(inode, false)) + if ((flags & (S_VERSION|S_CTIME|S_MTIME)) && inode_maybe_inc_iversion(inode, false)) dirty_flags |= I_DIRTY_SYNC;
That would be wrong. The problem is that we're changing how update_time works: Previously, update_time was given a timestamp and a set of S_* flags to indicate which fields should be updated. Now, update_time is not given a timestamp. It needs to fetch it itself, but that subtly changes the meaning of the flags field. It now means "these fields needed to be updated when I last checked". The timestamp and i_version may now be different from when the flags field was set. This means that if any of S_CTIME/S_MTIME/S_VERSION were set that we need to attempt to update all 3 of them. They may now be different from the timestamp or version that we ultimately end up with. The above may look to you like it would always cause I_DIRTY_SYNC to be set on any ctime or mtime update, but inode_maybe_inc_iversion only returns true if it actually updated i_version, and it only does that if someone issued a ->getattr against the file since the last time it was updated. So, this shouldn't generate any more DIRTY_SYNC updates than it did before. -- Jeff Layton [off-list ref]