From c3b9cecd89b806e14544af596396e18abd00f145 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jun 2018 10:15:13 +0200 Subject: [PATCH 1/2] udf: convert inode stamps to timespec64 The VFS structures are finally converted to always use 64-bit timestamps, and this file system can represent a long range of on-disk timestamps already, so now let's fit in the missing bits for udf. Signed-off-by: Arnd Bergmann Signed-off-by: Jan Kara --- fs/udf/ialloc.c | 2 +- fs/udf/inode.c | 45 ++++++++++++++++----------------------------- fs/udf/super.c | 8 ++++---- fs/udf/udf_i.h | 2 +- fs/udf/udf_sb.h | 2 +- fs/udf/udfdecl.h | 4 ++-- fs/udf/udftime.c | 6 +++--- 7 files changed, 28 insertions(+), 41 deletions(-) diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 56569023783b..f8e5872f7cc2 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -125,7 +125,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) else iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); - iinfo->i_crtime = timespec64_to_timespec(inode->i_mtime); + iinfo->i_crtime = inode->i_mtime; if (unlikely(insert_inode_locked(inode) < 0)) { make_bad_inode(inode); iput(inode); diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 9915a58fbabd..5df554a9f9c9 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1270,7 +1270,6 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) struct udf_inode_info *iinfo = UDF_I(inode); struct udf_sb_info *sbi = UDF_SB(inode->i_sb); struct kernel_lb_addr *iloc = &iinfo->i_location; - struct timespec ts; unsigned int link_count; unsigned int indirections = 0; int bs = inode->i_sb->s_blocksize; @@ -1443,12 +1442,9 @@ reread: inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); - udf_disk_stamp_to_time(&ts, fe->accessTime); - inode->i_atime = timespec_to_timespec64(ts); - udf_disk_stamp_to_time(&ts, fe->modificationTime); - inode->i_mtime = timespec_to_timespec64(ts); - udf_disk_stamp_to_time(&ts, fe->attrTime); - inode->i_ctime = timespec_to_timespec64(ts); + udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime); + udf_disk_stamp_to_time(&inode->i_mtime, fe->modificationTime); + udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime); iinfo->i_unique = le64_to_cpu(fe->uniqueID); iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); @@ -1458,13 +1454,10 @@ reread: inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); - udf_disk_stamp_to_time(&ts, efe->accessTime); - inode->i_atime = timespec_to_timespec64(ts); - udf_disk_stamp_to_time(&ts, efe->modificationTime); - inode->i_mtime = timespec_to_timespec64(ts); + udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime); + udf_disk_stamp_to_time(&inode->i_mtime, efe->modificationTime); udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime); - udf_disk_stamp_to_time(&ts, efe->attrTime); - inode->i_ctime = timespec_to_timespec64(ts); + udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime); iinfo->i_unique = le64_to_cpu(efe->uniqueID); iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); @@ -1601,7 +1594,7 @@ static int udf_sync_inode(struct inode *inode) return udf_update_inode(inode, 1); } -static void udf_adjust_time(struct udf_inode_info *iinfo, struct timespec time) +static void udf_adjust_time(struct udf_inode_info *iinfo, struct timespec64 time) { if (iinfo->i_crtime.tv_sec > time.tv_sec || (iinfo->i_crtime.tv_sec == time.tv_sec && @@ -1714,12 +1707,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) inode->i_sb->s_blocksize - sizeof(struct fileEntry)); fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); - udf_time_to_disk_stamp(&fe->accessTime, - timespec64_to_timespec(inode->i_atime)); - udf_time_to_disk_stamp(&fe->modificationTime, - timespec64_to_timespec(inode->i_mtime)); - udf_time_to_disk_stamp(&fe->attrTime, - timespec64_to_timespec(inode->i_ctime)); + udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime); + udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime); + udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime); memset(&(fe->impIdent), 0, sizeof(struct regid)); strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; @@ -1738,17 +1728,14 @@ static int udf_update_inode(struct inode *inode, int do_sync) efe->objectSize = cpu_to_le64(inode->i_size); efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); - udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_atime)); - udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_mtime)); - udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_ctime)); + udf_adjust_time(iinfo, inode->i_atime); + udf_adjust_time(iinfo, inode->i_mtime); + udf_adjust_time(iinfo, inode->i_ctime); - udf_time_to_disk_stamp(&efe->accessTime, - timespec64_to_timespec(inode->i_atime)); - udf_time_to_disk_stamp(&efe->modificationTime, - timespec64_to_timespec(inode->i_mtime)); + udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime); + udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime); udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime); - udf_time_to_disk_stamp(&efe->attrTime, - timespec64_to_timespec(inode->i_ctime)); + udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime); memset(&(efe->impIdent), 0, sizeof(efe->impIdent)); strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); diff --git a/fs/udf/super.c b/fs/udf/super.c index 0c504c8031d3..3040dc2a32f6 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1980,7 +1980,7 @@ static void udf_open_lvid(struct super_block *sb) struct buffer_head *bh = sbi->s_lvid_bh; struct logicalVolIntegrityDesc *lvid; struct logicalVolIntegrityDescImpUse *lvidiu; - struct timespec ts; + struct timespec64 ts; if (!bh) return; @@ -1992,7 +1992,7 @@ static void udf_open_lvid(struct super_block *sb) mutex_lock(&sbi->s_alloc_mutex); lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - ktime_get_real_ts(&ts); + ktime_get_real_ts64(&ts); udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts); if (le32_to_cpu(lvid->integrityType) == LVID_INTEGRITY_TYPE_CLOSE) lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); @@ -2017,7 +2017,7 @@ static void udf_close_lvid(struct super_block *sb) struct buffer_head *bh = sbi->s_lvid_bh; struct logicalVolIntegrityDesc *lvid; struct logicalVolIntegrityDescImpUse *lvidiu; - struct timespec ts; + struct timespec64 ts; if (!bh) return; @@ -2029,7 +2029,7 @@ static void udf_close_lvid(struct super_block *sb) mutex_lock(&sbi->s_alloc_mutex); lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - ktime_get_real_ts(&ts); + ktime_get_real_ts64(&ts); udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts); if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev)) lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION); diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index 630426ffb775..2ef0e212f08a 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h @@ -28,7 +28,7 @@ struct udf_ext_cache { */ struct udf_inode_info { - struct timespec i_crtime; + struct timespec64 i_crtime; /* Physical address of inode */ struct kernel_lb_addr i_location; __u64 i_unique; diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 9dd3e1b9619e..9424d7cab790 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -138,7 +138,7 @@ struct udf_sb_info { rwlock_t s_cred_lock; /* Root Info */ - struct timespec s_record_time; + struct timespec64 s_record_time; /* Fileset Info */ __u16 s_serial_number; diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 84c47dde4d26..ee246769dee4 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -258,8 +258,8 @@ extern struct long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); extern struct short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); /* udftime.c */ -extern void udf_disk_stamp_to_time(struct timespec *dest, +extern void udf_disk_stamp_to_time(struct timespec64 *dest, struct timestamp src); -extern void udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src); +extern void udf_time_to_disk_stamp(struct timestamp *dest, struct timespec64 src); #endif /* __UDF_DECL_H */ diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index 67b33ac5d41b..fce4ad976c8c 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c @@ -41,7 +41,7 @@ #include void -udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src) +udf_disk_stamp_to_time(struct timespec64 *dest, struct timestamp src) { u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone); u16 year = le16_to_cpu(src.year); @@ -70,9 +70,9 @@ udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src) } void -udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts) +udf_time_to_disk_stamp(struct timestamp *dest, struct timespec64 ts) { - long seconds; + time64_t seconds; int16_t offset; struct tm tm; From fe2c32545bfc281122cb8b66572949a366ad747e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jun 2018 16:31:40 +0200 Subject: [PATCH 2/2] ext2: use ktime_get_real_seconds for timestamps get_seconds() is deprecated because of the y2038 overflow, so users should migrate to 64-bit timestamps using ktime_get_real_seconds(). In ext2, the timestamps in the superblock and in the inode are all limited to 32-bit, and this won't get fixed, so let's just stop using the deprecated interface and keep truncating. All users of ext2 should migrate to ext4 before 2038 to prevent this from causing problems. Signed-off-by: Arnd Bergmann Signed-off-by: Jan Kara --- fs/ext2/inode.c | 2 +- fs/ext2/super.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 71635909df3b..7f7ee18fe179 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -86,7 +86,7 @@ void ext2_evict_inode(struct inode * inode) if (want_delete) { sb_start_intwrite(inode->i_sb); /* set dtime */ - EXT2_I(inode)->i_dtime = get_seconds(); + EXT2_I(inode)->i_dtime = ktime_get_real_seconds(); mark_inode_dirty(inode); __ext2_write_inode(inode, inode_needs_sync(inode)); /* truncate to 0 */ diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 8ff53f8da3bc..73bd58fa13de 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -682,7 +682,8 @@ static int ext2_setup_super (struct super_block * sb, "running e2fsck is recommended"); else if (le32_to_cpu(es->s_checkinterval) && (le32_to_cpu(es->s_lastcheck) + - le32_to_cpu(es->s_checkinterval) <= get_seconds())) + le32_to_cpu(es->s_checkinterval) <= + ktime_get_real_seconds())) ext2_msg(sb, KERN_WARNING, "warning: checktime reached, " "running e2fsck is recommended"); @@ -1248,7 +1249,7 @@ void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es, spin_lock(&EXT2_SB(sb)->s_lock); es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb)); es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb)); - es->s_wtime = cpu_to_le32(get_seconds()); + es->s_wtime = cpu_to_le32(ktime_get_real_seconds()); /* unlock before we do IO */ spin_unlock(&EXT2_SB(sb)->s_lock); mark_buffer_dirty(EXT2_SB(sb)->s_sbh); @@ -1360,7 +1361,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) * the rdonly flag and then mark the partition as valid again. */ es->s_state = cpu_to_le16(sbi->s_mount_state); - es->s_mtime = cpu_to_le32(get_seconds()); + es->s_mtime = cpu_to_le32(ktime_get_real_seconds()); spin_unlock(&sbi->s_lock); err = dquot_suspend(sb, -1);