Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fat: ignore ctime updates, and keep ctime identical to mtime in memory

FAT supports creation time but not change time, and there was no
corresponding timestamp for creation time in previous VFS. The original
implementation took the compromise of saving the in-memory change time
into the on-disk creation time field, but this would lead to compatibility
issues with non-linux systems.

To address this issue, this patch changes the behavior of ctime. It will
no longer be loaded and stored from the creation time on disk. Instead of
that, it'll be consistent with the in-memory mtime and share the same
on-disk field. All updates to mtime will also be applied to ctime in
memory, while all updates to ctime will be ignored.

Link: https://lkml.kernel.org/r/20220503152536.2503003-2-cccheng@synology.com
Signed-off-by: Chung-Chiang Cheng <cccheng@synology.com>
Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Chung-Chiang Cheng and committed by
akpm
0f9d1481 4dcc3f96

+10 -10
+4 -7
fs/fat/inode.c
··· 567 567 & ~((loff_t)sbi->cluster_size - 1)) >> 9; 568 568 569 569 fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0); 570 - if (sbi->options.isvfat) { 571 - fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime, 572 - de->cdate, de->ctime_cs); 570 + inode->i_ctime = inode->i_mtime; 571 + if (sbi->options.isvfat) 573 572 fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0); 574 - } else 575 - fat_truncate_time(inode, &inode->i_mtime, S_ATIME|S_CTIME); 573 + else 574 + inode->i_atime = fat_truncate_atime(sbi, &inode->i_mtime); 576 575 577 576 return 0; 578 577 } ··· 887 888 &raw_entry->date, NULL); 888 889 if (sbi->options.isvfat) { 889 890 __le16 atime; 890 - fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime, 891 - &raw_entry->cdate, &raw_entry->ctime_cs); 892 891 fat_time_unix2fat(sbi, &inode->i_atime, &atime, 893 892 &raw_entry->adate, NULL); 894 893 }
+6 -3
fs/fat/misc.c
··· 347 347 348 348 if (flags & S_ATIME) 349 349 inode->i_atime = fat_truncate_atime(sbi, now); 350 - if (flags & S_CTIME) 351 - inode->i_ctime = fat_truncate_crtime(sbi, now); 350 + /* 351 + * ctime and mtime share the same on-disk field, and should be 352 + * identical in memory. all mtime updates will be applied to ctime, 353 + * but ctime updates are ignored. 354 + */ 352 355 if (flags & S_MTIME) 353 - inode->i_mtime = fat_truncate_mtime(sbi, now); 356 + inode->i_mtime = inode->i_ctime = fat_truncate_mtime(sbi, now); 354 357 355 358 return 0; 356 359 }