}
}
- fat_truncate_time(dir, NULL, S_ATIME|S_MTIME);
+ fat_truncate_time(dir, NULL, FAT_UPDATE_ATIME | FAT_UPDATE_CMTIME);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
__le16 *time, __le16 *date, u8 *time_cs);
extern struct timespec64 fat_truncate_atime(const struct msdos_sb_info *sbi,
const struct timespec64 *ts);
-extern struct timespec64 fat_truncate_mtime(const struct msdos_sb_info *sbi,
- const struct timespec64 *ts);
-extern int fat_truncate_time(struct inode *inode, struct timespec64 *now,
- int flags);
+#define FAT_UPDATE_ATIME (1u << 0)
+#define FAT_UPDATE_CMTIME (1u << 1)
+void fat_truncate_time(struct inode *inode, struct timespec64 *now,
+ unsigned int flags);
extern int fat_update_time(struct inode *inode, int flags);
extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
if (err)
goto out;
- fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
+ fat_truncate_time(inode, NULL, FAT_UPDATE_CMTIME);
mark_inode_dirty(inode);
if (IS_SYNC(inode)) {
int err2;
MSDOS_I(inode)->i_logstart = 0;
}
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
- fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
+ fat_truncate_time(inode, NULL, FAT_UPDATE_CMTIME);
if (wait) {
err = fat_sync_inode(inode);
if (err) {
}
/*
- * setattr_copy can't truncate these appropriately, so we'll
- * copy them ourselves
+ * setattr_copy can't truncate these appropriately, so we'll copy them
+ * ourselves. See fat_truncate_time for the c/mtime logic on fat.
*/
if (attr->ia_valid & ATTR_ATIME)
- fat_truncate_time(inode, &attr->ia_atime, S_ATIME);
- if (attr->ia_valid & ATTR_CTIME)
- fat_truncate_time(inode, &attr->ia_ctime, S_CTIME);
+ fat_truncate_time(inode, &attr->ia_atime, FAT_UPDATE_ATIME);
if (attr->ia_valid & ATTR_MTIME)
- fat_truncate_time(inode, &attr->ia_mtime, S_MTIME);
+ fat_truncate_time(inode, &attr->ia_mtime, FAT_UPDATE_CMTIME);
attr->ia_valid &= ~(ATTR_ATIME|ATTR_CTIME|ATTR_MTIME);
setattr_copy(idmap, inode, attr);
if (err < len)
fat_write_failed(mapping, pos + len);
if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
- fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
+ fat_truncate_time(inode, NULL, FAT_UPDATE_CMTIME);
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
mark_inode_dirty(inode);
}
}
/*
- * truncate mtime to 2 second granularity
- */
-struct timespec64 fat_truncate_mtime(const struct msdos_sb_info *sbi,
- const struct timespec64 *ts)
-{
- return fat_timespec64_trunc_2secs(*ts);
-}
-
-/*
- * truncate the various times with appropriate granularity:
- * all times in root node are always 0
+ * Update the in-inode atime and/or mtime after truncating the timestamp to the
+ * granularity. All timestamps in root inode are always 0.
+ *
+ * ctime and mtime share the same on-disk field, and should be identical in
+ * memory. All mtime updates will be applied to ctime, but ctime updates are
+ * ignored.
*/
-int fat_truncate_time(struct inode *inode, struct timespec64 *now, int flags)
+void fat_truncate_time(struct inode *inode, struct timespec64 *now,
+ unsigned int flags)
{
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
struct timespec64 ts;
if (inode->i_ino == MSDOS_ROOT_INO)
- return 0;
+ return;
if (now == NULL) {
now = &ts;
ts = current_time(inode);
}
- if (flags & S_ATIME)
+ if (flags & FAT_UPDATE_ATIME)
inode_set_atime_to_ts(inode, fat_truncate_atime(sbi, now));
- /*
- * ctime and mtime share the same on-disk field, and should be
- * identical in memory. all mtime updates will be applied to ctime,
- * but ctime updates are ignored.
- */
- if (flags & S_MTIME)
- inode_set_mtime_to_ts(inode,
- inode_set_ctime_to_ts(inode, fat_truncate_mtime(sbi, now)));
+ if (flags & FAT_UPDATE_CMTIME) {
+ /* truncate mtime to 2 second granularity */
+ struct timespec64 mtime = fat_timespec64_trunc_2secs(*now);
- return 0;
+ inode_set_mtime_to_ts(inode, mtime);
+ inode_set_ctime_to_ts(inode, mtime);
+ }
}
EXPORT_SYMBOL_GPL(fat_truncate_time);
int fat_update_time(struct inode *inode, int flags)
{
+ unsigned int fat_flags = 0;
int dirty_flags = 0;
if (inode->i_ino == MSDOS_ROOT_INO)
return 0;
- if (flags & (S_ATIME | S_CTIME | S_MTIME)) {
+ if (flags & S_ATIME)
+ fat_flags |= FAT_UPDATE_ATIME;
+ if (flags & (S_CTIME | S_MTIME))
+ fat_flags |= FAT_UPDATE_CMTIME;
+
+ if (fat_flags) {
fat_truncate_time(inode, NULL, flags);
if (inode->i_sb->s_flags & SB_LAZYTIME)
dirty_flags |= I_DIRTY_TIME;
if (err)
return err;
- fat_truncate_time(dir, ts, S_CTIME|S_MTIME);
+ fat_truncate_time(dir, ts, FAT_UPDATE_CMTIME);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
err = PTR_ERR(inode);
goto out;
}
- fat_truncate_time(inode, &ts, S_ATIME|S_CTIME|S_MTIME);
+ fat_truncate_time(inode, &ts, FAT_UPDATE_ATIME | FAT_UPDATE_CMTIME);
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
d_instantiate(dentry, inode);
drop_nlink(dir);
clear_nlink(inode);
- fat_truncate_time(inode, NULL, S_CTIME);
fat_detach(inode);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
goto out;
}
set_nlink(inode, 2);
- fat_truncate_time(inode, &ts, S_ATIME|S_CTIME|S_MTIME);
+ fat_truncate_time(inode, &ts, FAT_UPDATE_ATIME | FAT_UPDATE_CMTIME);
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
d_instantiate(dentry, inode);
if (err)
goto out;
clear_nlink(inode);
- fat_truncate_time(inode, NULL, S_CTIME);
fat_detach(inode);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
mark_inode_dirty(old_inode);
inode_inc_iversion(old_dir);
- fat_truncate_time(old_dir, NULL, S_CTIME|S_MTIME);
+ fat_truncate_time(old_dir, NULL, FAT_UPDATE_CMTIME);
if (IS_DIRSYNC(old_dir))
(void)fat_sync_inode(old_dir);
else
if (err)
goto error_dotdot;
inode_inc_iversion(old_dir);
- fat_truncate_time(old_dir, &ts, S_CTIME|S_MTIME);
+ fat_truncate_time(old_dir, &ts, FAT_UPDATE_CMTIME);
if (IS_DIRSYNC(old_dir))
(void)fat_sync_inode(old_dir);
else
drop_nlink(new_inode);
if (is_dir)
drop_nlink(new_inode);
- fat_truncate_time(new_inode, &ts, S_CTIME);
}
out:
brelse(sinfo.bh);
goto cleanup;
/* update timestamp */
- fat_truncate_time(dir, ts, S_CTIME|S_MTIME);
+ fat_truncate_time(dir, ts, FAT_UPDATE_CMTIME);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
drop_nlink(dir);
clear_nlink(inode);
- fat_truncate_time(inode, NULL, S_ATIME|S_MTIME);
+ fat_truncate_time(inode, NULL, FAT_UPDATE_ATIME | FAT_UPDATE_CMTIME);
fat_detach(inode);
vfat_d_version_set(dentry, inode_query_iversion(dir));
out:
if (err)
goto out;
clear_nlink(inode);
- fat_truncate_time(inode, NULL, S_ATIME|S_MTIME);
+ fat_truncate_time(inode, NULL, FAT_UPDATE_ATIME | FAT_UPDATE_CMTIME);
fat_detach(inode);
vfat_d_version_set(dentry, inode_query_iversion(dir));
out:
static void vfat_update_dir_metadata(struct inode *dir, struct timespec64 *ts)
{
inode_inc_iversion(dir);
- fat_truncate_time(dir, ts, S_CTIME | S_MTIME);
+ fat_truncate_time(dir, ts, FAT_UPDATE_CMTIME);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
drop_nlink(new_inode);
if (is_dir)
drop_nlink(new_inode);
- fat_truncate_time(new_inode, &ts, S_CTIME);
}
out:
brelse(sinfo.bh);