diff options
47 files changed, 294 insertions, 72 deletions
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 08112fbcaece..ca243e658d71 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -69,8 +69,12 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
69 | if (v9fs_proto_dotl(v9ses)) { | 69 | if (v9fs_proto_dotl(v9ses)) { |
70 | sb->s_op = &v9fs_super_ops_dotl; | 70 | sb->s_op = &v9fs_super_ops_dotl; |
71 | sb->s_xattr = v9fs_xattr_handlers; | 71 | sb->s_xattr = v9fs_xattr_handlers; |
72 | } else | 72 | } else { |
73 | sb->s_op = &v9fs_super_ops; | 73 | sb->s_op = &v9fs_super_ops; |
74 | sb->s_time_max = U32_MAX; | ||
75 | } | ||
76 | |||
77 | sb->s_time_min = 0; | ||
74 | 78 | ||
75 | ret = super_setup_bdi(sb); | 79 | ret = super_setup_bdi(sb); |
76 | if (ret) | 80 | if (ret) |
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 14a6c1b90c9f..f708c45d5f66 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c | |||
@@ -375,7 +375,7 @@ affs_secs_to_datestamp(time64_t secs, struct affs_date *ds) | |||
375 | u32 minute; | 375 | u32 minute; |
376 | s32 rem; | 376 | s32 rem; |
377 | 377 | ||
378 | secs -= sys_tz.tz_minuteswest * 60 + ((8 * 365 + 2) * 24 * 60 * 60); | 378 | secs -= sys_tz.tz_minuteswest * 60 + AFFS_EPOCH_DELTA; |
379 | if (secs < 0) | 379 | if (secs < 0) |
380 | secs = 0; | 380 | secs = 0; |
381 | days = div_s64_rem(secs, 86400, &rem); | 381 | days = div_s64_rem(secs, 86400, &rem); |
diff --git a/fs/affs/amigaffs.h b/fs/affs/amigaffs.h index f9bef9056659..81fb396d4dfa 100644 --- a/fs/affs/amigaffs.h +++ b/fs/affs/amigaffs.h | |||
@@ -32,6 +32,9 @@ | |||
32 | 32 | ||
33 | #define AFFS_ROOT_BMAPS 25 | 33 | #define AFFS_ROOT_BMAPS 25 |
34 | 34 | ||
35 | /* Seconds since Amiga epoch of 1978/01/01 to UNIX */ | ||
36 | #define AFFS_EPOCH_DELTA ((8 * 365 + 2) * 86400LL) | ||
37 | |||
35 | struct affs_date { | 38 | struct affs_date { |
36 | __be32 days; | 39 | __be32 days; |
37 | __be32 mins; | 40 | __be32 mins; |
diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 73598bff8506..a346cf7659f1 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c | |||
@@ -150,10 +150,10 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) | |||
150 | } | 150 | } |
151 | 151 | ||
152 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec | 152 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec |
153 | = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) + | 153 | = (be32_to_cpu(tail->change.days) * 86400LL + |
154 | be32_to_cpu(tail->change.mins) * 60 + | 154 | be32_to_cpu(tail->change.mins) * 60 + |
155 | be32_to_cpu(tail->change.ticks) / 50 + | 155 | be32_to_cpu(tail->change.ticks) / 50 + |
156 | ((8 * 365 + 2) * 24 * 60 * 60)) + | 156 | AFFS_EPOCH_DELTA) + |
157 | sys_tz.tz_minuteswest * 60; | 157 | sys_tz.tz_minuteswest * 60; |
158 | inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0; | 158 | inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0; |
159 | affs_brelse(bh); | 159 | affs_brelse(bh); |
diff --git a/fs/affs/super.c b/fs/affs/super.c index e7d036efbaa1..cc463ae47c12 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -355,6 +355,10 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) | |||
355 | sb->s_op = &affs_sops; | 355 | sb->s_op = &affs_sops; |
356 | sb->s_flags |= SB_NODIRATIME; | 356 | sb->s_flags |= SB_NODIRATIME; |
357 | 357 | ||
358 | sb->s_time_gran = NSEC_PER_SEC; | ||
359 | sb->s_time_min = sys_tz.tz_minuteswest * 60 + AFFS_EPOCH_DELTA; | ||
360 | sb->s_time_max = 86400LL * U32_MAX + 86400 + sb->s_time_min; | ||
361 | |||
358 | sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL); | 362 | sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL); |
359 | if (!sbi) | 363 | if (!sbi) |
360 | return -ENOMEM; | 364 | return -ENOMEM; |
@@ -183,15 +183,18 @@ void setattr_copy(struct inode *inode, const struct iattr *attr) | |||
183 | inode->i_uid = attr->ia_uid; | 183 | inode->i_uid = attr->ia_uid; |
184 | if (ia_valid & ATTR_GID) | 184 | if (ia_valid & ATTR_GID) |
185 | inode->i_gid = attr->ia_gid; | 185 | inode->i_gid = attr->ia_gid; |
186 | if (ia_valid & ATTR_ATIME) | 186 | if (ia_valid & ATTR_ATIME) { |
187 | inode->i_atime = timespec64_trunc(attr->ia_atime, | 187 | inode->i_atime = timestamp_truncate(attr->ia_atime, |
188 | inode->i_sb->s_time_gran); | 188 | inode); |
189 | if (ia_valid & ATTR_MTIME) | 189 | } |
190 | inode->i_mtime = timespec64_trunc(attr->ia_mtime, | 190 | if (ia_valid & ATTR_MTIME) { |
191 | inode->i_sb->s_time_gran); | 191 | inode->i_mtime = timestamp_truncate(attr->ia_mtime, |
192 | if (ia_valid & ATTR_CTIME) | 192 | inode); |
193 | inode->i_ctime = timespec64_trunc(attr->ia_ctime, | 193 | } |
194 | inode->i_sb->s_time_gran); | 194 | if (ia_valid & ATTR_CTIME) { |
195 | inode->i_ctime = timestamp_truncate(attr->ia_ctime, | ||
196 | inode); | ||
197 | } | ||
195 | if (ia_valid & ATTR_MODE) { | 198 | if (ia_valid & ATTR_MODE) { |
196 | umode_t mode = attr->ia_mode; | 199 | umode_t mode = attr->ia_mode; |
197 | 200 | ||
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 462d096ff3e9..64cdf4d8e424 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -893,6 +893,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent) | |||
893 | sb_set_blocksize(sb, (ulong) befs_sb->block_size); | 893 | sb_set_blocksize(sb, (ulong) befs_sb->block_size); |
894 | sb->s_op = &befs_sops; | 894 | sb->s_op = &befs_sops; |
895 | sb->s_export_op = &befs_export_operations; | 895 | sb->s_export_op = &befs_export_operations; |
896 | sb->s_time_min = 0; | ||
897 | sb->s_time_max = 0xffffffffffffll; | ||
896 | root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir))); | 898 | root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir))); |
897 | if (IS_ERR(root)) { | 899 | if (IS_ERR(root)) { |
898 | ret = PTR_ERR(root); | 900 | ret = PTR_ERR(root); |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 5e97bed073d7..f8ce1368218b 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
@@ -324,6 +324,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
324 | return -ENOMEM; | 324 | return -ENOMEM; |
325 | mutex_init(&info->bfs_lock); | 325 | mutex_init(&info->bfs_lock); |
326 | s->s_fs_info = info; | 326 | s->s_fs_info = info; |
327 | s->s_time_min = 0; | ||
328 | s->s_time_max = U32_MAX; | ||
327 | 329 | ||
328 | sb_set_blocksize(s, BFS_BSIZE); | 330 | sb_set_blocksize(s, BFS_BSIZE); |
329 | 331 | ||
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index ab4868c7308e..377fafc76f20 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -979,6 +979,8 @@ static int ceph_set_super(struct super_block *s, void *data) | |||
979 | s->s_export_op = &ceph_export_ops; | 979 | s->s_export_op = &ceph_export_ops; |
980 | 980 | ||
981 | s->s_time_gran = 1; | 981 | s->s_time_gran = 1; |
982 | s->s_time_min = 0; | ||
983 | s->s_time_max = U32_MAX; | ||
982 | 984 | ||
983 | ret = set_anon_super(s, NULL); /* what is that second arg for? */ | 985 | ret = set_anon_super(s, NULL); /* what is that second arg for? */ |
984 | if (ret != 0) | 986 | if (ret != 0) |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4e2f74894e9b..e8afff702bb8 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -56,6 +56,15 @@ | |||
56 | #include "dfs_cache.h" | 56 | #include "dfs_cache.h" |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | /* | ||
60 | * DOS dates from 1980/1/1 through 2107/12/31 | ||
61 | * Protocol specifications indicate the range should be to 119, which | ||
62 | * limits maximum year to 2099. But this range has not been checked. | ||
63 | */ | ||
64 | #define SMB_DATE_MAX (127<<9 | 12<<5 | 31) | ||
65 | #define SMB_DATE_MIN (0<<9 | 1<<5 | 1) | ||
66 | #define SMB_TIME_MAX (23<<11 | 59<<5 | 29) | ||
67 | |||
59 | int cifsFYI = 0; | 68 | int cifsFYI = 0; |
60 | bool traceSMB; | 69 | bool traceSMB; |
61 | bool enable_oplocks = true; | 70 | bool enable_oplocks = true; |
@@ -142,6 +151,7 @@ cifs_read_super(struct super_block *sb) | |||
142 | struct inode *inode; | 151 | struct inode *inode; |
143 | struct cifs_sb_info *cifs_sb; | 152 | struct cifs_sb_info *cifs_sb; |
144 | struct cifs_tcon *tcon; | 153 | struct cifs_tcon *tcon; |
154 | struct timespec64 ts; | ||
145 | int rc = 0; | 155 | int rc = 0; |
146 | 156 | ||
147 | cifs_sb = CIFS_SB(sb); | 157 | cifs_sb = CIFS_SB(sb); |
@@ -161,6 +171,18 @@ cifs_read_super(struct super_block *sb) | |||
161 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | 171 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
162 | sb->s_time_gran = 100; | 172 | sb->s_time_gran = 100; |
163 | 173 | ||
174 | if (tcon->unix_ext) { | ||
175 | ts = cifs_NTtimeToUnix(0); | ||
176 | sb->s_time_min = ts.tv_sec; | ||
177 | ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX)); | ||
178 | sb->s_time_max = ts.tv_sec; | ||
179 | } else { | ||
180 | ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0); | ||
181 | sb->s_time_min = ts.tv_sec; | ||
182 | ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), cpu_to_le16(SMB_TIME_MAX), 0); | ||
183 | sb->s_time_max = ts.tv_sec; | ||
184 | } | ||
185 | |||
164 | sb->s_magic = CIFS_MAGIC_NUMBER; | 186 | sb->s_magic = CIFS_MAGIC_NUMBER; |
165 | sb->s_op = &cifs_super_ops; | 187 | sb->s_op = &cifs_super_ops; |
166 | sb->s_xattr = cifs_xattr_handlers; | 188 | sb->s_xattr = cifs_xattr_handlers; |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index ed92958e842d..49c17ee18254 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -949,8 +949,8 @@ static const int total_days_of_prev_months[] = { | |||
949 | struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) | 949 | struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) |
950 | { | 950 | { |
951 | struct timespec64 ts; | 951 | struct timespec64 ts; |
952 | time64_t sec; | 952 | time64_t sec, days; |
953 | int min, days, month, year; | 953 | int min, day, month, year; |
954 | u16 date = le16_to_cpu(le_date); | 954 | u16 date = le16_to_cpu(le_date); |
955 | u16 time = le16_to_cpu(le_time); | 955 | u16 time = le16_to_cpu(le_time); |
956 | SMB_TIME *st = (SMB_TIME *)&time; | 956 | SMB_TIME *st = (SMB_TIME *)&time; |
@@ -966,15 +966,15 @@ struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) | |||
966 | sec += 60 * 60 * st->Hours; | 966 | sec += 60 * 60 * st->Hours; |
967 | if (st->Hours > 24) | 967 | if (st->Hours > 24) |
968 | cifs_dbg(VFS, "illegal hours %d\n", st->Hours); | 968 | cifs_dbg(VFS, "illegal hours %d\n", st->Hours); |
969 | days = sd->Day; | 969 | day = sd->Day; |
970 | month = sd->Month; | 970 | month = sd->Month; |
971 | if (days < 1 || days > 31 || month < 1 || month > 12) { | 971 | if (day < 1 || day > 31 || month < 1 || month > 12) { |
972 | cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, days); | 972 | cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, day); |
973 | days = clamp(days, 1, 31); | 973 | day = clamp(day, 1, 31); |
974 | month = clamp(month, 1, 12); | 974 | month = clamp(month, 1, 12); |
975 | } | 975 | } |
976 | month -= 1; | 976 | month -= 1; |
977 | days += total_days_of_prev_months[month]; | 977 | days = day + total_days_of_prev_months[month]; |
978 | days += 3652; /* account for difference in days between 1980 and 1970 */ | 978 | days += 3652; /* account for difference in days between 1980 and 1970 */ |
979 | year = sd->Year; | 979 | year = sd->Year; |
980 | days += year * 365; | 980 | days += year * 365; |
diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 321f56e487cb..b1c70e2b9b1e 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c | |||
@@ -188,6 +188,9 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) | |||
188 | sb->s_magic = CODA_SUPER_MAGIC; | 188 | sb->s_magic = CODA_SUPER_MAGIC; |
189 | sb->s_op = &coda_super_operations; | 189 | sb->s_op = &coda_super_operations; |
190 | sb->s_d_op = &coda_dentry_operations; | 190 | sb->s_d_op = &coda_dentry_operations; |
191 | sb->s_time_gran = 1; | ||
192 | sb->s_time_min = S64_MIN; | ||
193 | sb->s_time_max = S64_MAX; | ||
191 | 194 | ||
192 | error = super_setup_bdi(sb); | 195 | error = super_setup_bdi(sb); |
193 | if (error) | 196 | if (error) |
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index ab0284321912..884dcf06cfbe 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c | |||
@@ -76,14 +76,14 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr) | |||
76 | if (ia_valid & ATTR_GID) | 76 | if (ia_valid & ATTR_GID) |
77 | sd_iattr->ia_gid = iattr->ia_gid; | 77 | sd_iattr->ia_gid = iattr->ia_gid; |
78 | if (ia_valid & ATTR_ATIME) | 78 | if (ia_valid & ATTR_ATIME) |
79 | sd_iattr->ia_atime = timespec64_trunc(iattr->ia_atime, | 79 | sd_iattr->ia_atime = timestamp_truncate(iattr->ia_atime, |
80 | inode->i_sb->s_time_gran); | 80 | inode); |
81 | if (ia_valid & ATTR_MTIME) | 81 | if (ia_valid & ATTR_MTIME) |
82 | sd_iattr->ia_mtime = timespec64_trunc(iattr->ia_mtime, | 82 | sd_iattr->ia_mtime = timestamp_truncate(iattr->ia_mtime, |
83 | inode->i_sb->s_time_gran); | 83 | inode); |
84 | if (ia_valid & ATTR_CTIME) | 84 | if (ia_valid & ATTR_CTIME) |
85 | sd_iattr->ia_ctime = timespec64_trunc(iattr->ia_ctime, | 85 | sd_iattr->ia_ctime = timestamp_truncate(iattr->ia_ctime, |
86 | inode->i_sb->s_time_gran); | 86 | inode); |
87 | if (ia_valid & ATTR_MODE) { | 87 | if (ia_valid & ATTR_MODE) { |
88 | umode_t mode = iattr->ia_mode; | 88 | umode_t mode = iattr->ia_mode; |
89 | 89 | ||
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 9352487bd0fc..4d1d8b7761ed 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -597,6 +597,8 @@ static int cramfs_finalize_super(struct super_block *sb, | |||
597 | 597 | ||
598 | /* Set it all up.. */ | 598 | /* Set it all up.. */ |
599 | sb->s_flags |= SB_RDONLY; | 599 | sb->s_flags |= SB_RDONLY; |
600 | sb->s_time_min = 0; | ||
601 | sb->s_time_max = 0; | ||
600 | sb->s_op = &cramfs_ops; | 602 | sb->s_op = &cramfs_ops; |
601 | root = get_cramfs_inode(sb, cramfs_root, 0); | 603 | root = get_cramfs_inode(sb, cramfs_root, 0); |
602 | if (IS_ERR(root)) | 604 | if (IS_ERR(root)) |
diff --git a/fs/efs/super.c b/fs/efs/super.c index 867fc24dee20..4a6ebff2af76 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
@@ -257,6 +257,8 @@ static int efs_fill_super(struct super_block *s, void *d, int silent) | |||
257 | if (!sb) | 257 | if (!sb) |
258 | return -ENOMEM; | 258 | return -ENOMEM; |
259 | s->s_fs_info = sb; | 259 | s->s_fs_info = sb; |
260 | s->s_time_min = 0; | ||
261 | s->s_time_max = U32_MAX; | ||
260 | 262 | ||
261 | s->s_magic = EFS_SUPER_MAGIC; | 263 | s->s_magic = EFS_SUPER_MAGIC; |
262 | if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) { | 264 | if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) { |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 44eb6e7eb492..baa36c6fb71e 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -1002,6 +1002,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
1002 | 1002 | ||
1003 | sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits); | 1003 | sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits); |
1004 | sb->s_max_links = EXT2_LINK_MAX; | 1004 | sb->s_max_links = EXT2_LINK_MAX; |
1005 | sb->s_time_min = S32_MIN; | ||
1006 | sb->s_time_max = S32_MAX; | ||
1005 | 1007 | ||
1006 | if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) { | 1008 | if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) { |
1007 | sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; | 1009 | sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 9c7f4036021b..42c6e4a5e673 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -832,11 +832,13 @@ static inline void ext4_decode_extra_time(struct timespec64 *time, | |||
832 | 832 | ||
833 | #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \ | 833 | #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \ |
834 | do { \ | 834 | do { \ |
835 | (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \ | ||
836 | if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) {\ | 835 | if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) {\ |
836 | (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \ | ||
837 | (raw_inode)->xtime ## _extra = \ | 837 | (raw_inode)->xtime ## _extra = \ |
838 | ext4_encode_extra_time(&(inode)->xtime); \ | 838 | ext4_encode_extra_time(&(inode)->xtime); \ |
839 | } \ | 839 | } \ |
840 | else \ | ||
841 | (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (inode)->xtime.tv_sec, S32_MIN, S32_MAX)); \ | ||
840 | } while (0) | 842 | } while (0) |
841 | 843 | ||
842 | #define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \ | 844 | #define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \ |
@@ -1643,6 +1645,10 @@ static inline bool ext4_verity_in_progress(struct inode *inode) | |||
1643 | 1645 | ||
1644 | #define EXT4_GOOD_OLD_INODE_SIZE 128 | 1646 | #define EXT4_GOOD_OLD_INODE_SIZE 128 |
1645 | 1647 | ||
1648 | #define EXT4_EXTRA_TIMESTAMP_MAX (((s64)1 << 34) - 1 + S32_MIN) | ||
1649 | #define EXT4_NON_EXTRA_TIMESTAMP_MAX S32_MAX | ||
1650 | #define EXT4_TIMESTAMP_MIN S32_MIN | ||
1651 | |||
1646 | /* | 1652 | /* |
1647 | * Feature set definitions | 1653 | * Feature set definitions |
1648 | */ | 1654 | */ |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 27cd622676e7..3db5f17228b7 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -4039,8 +4039,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
4039 | sbi->s_inode_size); | 4039 | sbi->s_inode_size); |
4040 | goto failed_mount; | 4040 | goto failed_mount; |
4041 | } | 4041 | } |
4042 | if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) | 4042 | /* |
4043 | sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2); | 4043 | * i_atime_extra is the last extra field available for [acm]times in |
4044 | * struct ext4_inode. Checking for that field should suffice to ensure | ||
4045 | * we have extra space for all three. | ||
4046 | */ | ||
4047 | if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) + | ||
4048 | sizeof(((struct ext4_inode *)0)->i_atime_extra)) { | ||
4049 | sb->s_time_gran = 1; | ||
4050 | sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX; | ||
4051 | } else { | ||
4052 | sb->s_time_gran = NSEC_PER_SEC; | ||
4053 | sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX; | ||
4054 | } | ||
4055 | |||
4056 | sb->s_time_min = EXT4_TIMESTAMP_MIN; | ||
4044 | } | 4057 | } |
4045 | 4058 | ||
4046 | sbi->s_desc_size = le16_to_cpu(es->s_desc_size); | 4059 | sbi->s_desc_size = le16_to_cpu(es->s_desc_size); |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 39fffc19e00c..56efde9d3659 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -745,15 +745,18 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr) | |||
745 | inode->i_uid = attr->ia_uid; | 745 | inode->i_uid = attr->ia_uid; |
746 | if (ia_valid & ATTR_GID) | 746 | if (ia_valid & ATTR_GID) |
747 | inode->i_gid = attr->ia_gid; | 747 | inode->i_gid = attr->ia_gid; |
748 | if (ia_valid & ATTR_ATIME) | 748 | if (ia_valid & ATTR_ATIME) { |
749 | inode->i_atime = timespec64_trunc(attr->ia_atime, | 749 | inode->i_atime = timestamp_truncate(attr->ia_atime, |
750 | inode->i_sb->s_time_gran); | 750 | inode); |
751 | if (ia_valid & ATTR_MTIME) | 751 | } |
752 | inode->i_mtime = timespec64_trunc(attr->ia_mtime, | 752 | if (ia_valid & ATTR_MTIME) { |
753 | inode->i_sb->s_time_gran); | 753 | inode->i_mtime = timestamp_truncate(attr->ia_mtime, |
754 | if (ia_valid & ATTR_CTIME) | 754 | inode); |
755 | inode->i_ctime = timespec64_trunc(attr->ia_ctime, | 755 | } |
756 | inode->i_sb->s_time_gran); | 756 | if (ia_valid & ATTR_CTIME) { |
757 | inode->i_ctime = timestamp_truncate(attr->ia_ctime, | ||
758 | inode); | ||
759 | } | ||
757 | if (ia_valid & ATTR_MODE) { | 760 | if (ia_valid & ATTR_MODE) { |
758 | umode_t mode = attr->ia_mode; | 761 | umode_t mode = attr->ia_mode; |
759 | 762 | ||
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 05689198f5af..5f04c5c810fb 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -31,6 +31,11 @@ | |||
31 | 31 | ||
32 | #define KB_IN_SECTORS 2 | 32 | #define KB_IN_SECTORS 2 |
33 | 33 | ||
34 | /* DOS dates from 1980/1/1 through 2107/12/31 */ | ||
35 | #define FAT_DATE_MIN (0<<9 | 1<<5 | 1) | ||
36 | #define FAT_DATE_MAX (127<<9 | 12<<5 | 31) | ||
37 | #define FAT_TIME_MAX (23<<11 | 59<<5 | 29) | ||
38 | |||
34 | /* | 39 | /* |
35 | * A deserialized copy of the on-disk structure laid out in struct | 40 | * A deserialized copy of the on-disk structure laid out in struct |
36 | * fat_boot_sector. | 41 | * fat_boot_sector. |
@@ -1605,6 +1610,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1605 | int debug; | 1610 | int debug; |
1606 | long error; | 1611 | long error; |
1607 | char buf[50]; | 1612 | char buf[50]; |
1613 | struct timespec64 ts; | ||
1608 | 1614 | ||
1609 | /* | 1615 | /* |
1610 | * GFP_KERNEL is ok here, because while we do hold the | 1616 | * GFP_KERNEL is ok here, because while we do hold the |
@@ -1698,6 +1704,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1698 | sbi->free_clus_valid = 0; | 1704 | sbi->free_clus_valid = 0; |
1699 | sbi->prev_free = FAT_START_ENT; | 1705 | sbi->prev_free = FAT_START_ENT; |
1700 | sb->s_maxbytes = 0xffffffff; | 1706 | sb->s_maxbytes = 0xffffffff; |
1707 | fat_time_fat2unix(sbi, &ts, 0, cpu_to_le16(FAT_DATE_MIN), 0); | ||
1708 | sb->s_time_min = ts.tv_sec; | ||
1709 | |||
1710 | fat_time_fat2unix(sbi, &ts, cpu_to_le16(FAT_TIME_MAX), | ||
1711 | cpu_to_le16(FAT_DATE_MAX), 0); | ||
1712 | sb->s_time_max = ts.tv_sec; | ||
1701 | 1713 | ||
1702 | if (!sbi->fat_length && bpb.fat32_length) { | 1714 | if (!sbi->fat_length && bpb.fat32_length) { |
1703 | struct fat_boot_fsinfo *fsinfo; | 1715 | struct fat_boot_fsinfo *fsinfo; |
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index a89f68c3cbed..578a5062706e 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -229,6 +229,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) | |||
229 | 229 | ||
230 | sbp->s_op = &vxfs_super_ops; | 230 | sbp->s_op = &vxfs_super_ops; |
231 | sbp->s_fs_info = infp; | 231 | sbp->s_fs_info = infp; |
232 | sbp->s_time_min = 0; | ||
233 | sbp->s_time_max = U32_MAX; | ||
232 | 234 | ||
233 | if (!vxfs_try_sb_magic(sbp, silent, 1, | 235 | if (!vxfs_try_sb_magic(sbp, silent, 1, |
234 | (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) { | 236 | (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) { |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index ab2e7cc2ff33..1cca83218fb5 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -334,7 +334,7 @@ long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg); | |||
334 | * local time (HPFS) to GMT (Unix) | 334 | * local time (HPFS) to GMT (Unix) |
335 | */ | 335 | */ |
336 | 336 | ||
337 | static inline time64_t local_to_gmt(struct super_block *s, time32_t t) | 337 | static inline time64_t local_to_gmt(struct super_block *s, time64_t t) |
338 | { | 338 | { |
339 | extern struct timezone sys_tz; | 339 | extern struct timezone sys_tz; |
340 | return t + sys_tz.tz_minuteswest * 60 + hpfs_sb(s)->sb_timeshift; | 340 | return t + sys_tz.tz_minuteswest * 60 + hpfs_sb(s)->sb_timeshift; |
@@ -343,9 +343,7 @@ static inline time64_t local_to_gmt(struct super_block *s, time32_t t) | |||
343 | static inline time32_t gmt_to_local(struct super_block *s, time64_t t) | 343 | static inline time32_t gmt_to_local(struct super_block *s, time64_t t) |
344 | { | 344 | { |
345 | extern struct timezone sys_tz; | 345 | extern struct timezone sys_tz; |
346 | t = t - sys_tz.tz_minuteswest * 60 - hpfs_sb(s)->sb_timeshift; | 346 | return t - sys_tz.tz_minuteswest * 60 - hpfs_sb(s)->sb_timeshift; |
347 | |||
348 | return clamp_t(time64_t, t, 0, U32_MAX); | ||
349 | } | 347 | } |
350 | 348 | ||
351 | static inline time32_t local_get_seconds(struct super_block *s) | 349 | static inline time32_t local_get_seconds(struct super_block *s) |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 9db6d84f0d62..0a677a9aaf34 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -614,6 +614,8 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
614 | s->s_magic = HPFS_SUPER_MAGIC; | 614 | s->s_magic = HPFS_SUPER_MAGIC; |
615 | s->s_op = &hpfs_sops; | 615 | s->s_op = &hpfs_sops; |
616 | s->s_d_op = &hpfs_dentry_operations; | 616 | s->s_d_op = &hpfs_dentry_operations; |
617 | s->s_time_min = local_to_gmt(s, 0); | ||
618 | s->s_time_max = local_to_gmt(s, U32_MAX); | ||
617 | 619 | ||
618 | sbi->sb_root = le32_to_cpu(superblock->root); | 620 | sbi->sb_root = le32_to_cpu(superblock->root); |
619 | sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors); | 621 | sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors); |
diff --git a/fs/inode.c b/fs/inode.c index 0f1e3b563c47..64bf28cf05cd 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -2167,6 +2167,37 @@ struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran) | |||
2167 | EXPORT_SYMBOL(timespec64_trunc); | 2167 | EXPORT_SYMBOL(timespec64_trunc); |
2168 | 2168 | ||
2169 | /** | 2169 | /** |
2170 | * timestamp_truncate - Truncate timespec to a granularity | ||
2171 | * @t: Timespec | ||
2172 | * @inode: inode being updated | ||
2173 | * | ||
2174 | * Truncate a timespec to the granularity supported by the fs | ||
2175 | * containing the inode. Always rounds down. gran must | ||
2176 | * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). | ||
2177 | */ | ||
2178 | struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode) | ||
2179 | { | ||
2180 | struct super_block *sb = inode->i_sb; | ||
2181 | unsigned int gran = sb->s_time_gran; | ||
2182 | |||
2183 | t.tv_sec = clamp(t.tv_sec, sb->s_time_min, sb->s_time_max); | ||
2184 | if (unlikely(t.tv_sec == sb->s_time_max || t.tv_sec == sb->s_time_min)) | ||
2185 | t.tv_nsec = 0; | ||
2186 | |||
2187 | /* Avoid division in the common cases 1 ns and 1 s. */ | ||
2188 | if (gran == 1) | ||
2189 | ; /* nothing */ | ||
2190 | else if (gran == NSEC_PER_SEC) | ||
2191 | t.tv_nsec = 0; | ||
2192 | else if (gran > 1 && gran < NSEC_PER_SEC) | ||
2193 | t.tv_nsec -= t.tv_nsec % gran; | ||
2194 | else | ||
2195 | WARN(1, "invalid file time granularity: %u", gran); | ||
2196 | return t; | ||
2197 | } | ||
2198 | EXPORT_SYMBOL(timestamp_truncate); | ||
2199 | |||
2200 | /** | ||
2170 | * current_time - Return FS time | 2201 | * current_time - Return FS time |
2171 | * @inode: inode. | 2202 | * @inode: inode. |
2172 | * | 2203 | * |
@@ -2187,7 +2218,7 @@ struct timespec64 current_time(struct inode *inode) | |||
2187 | return now; | 2218 | return now; |
2188 | } | 2219 | } |
2189 | 2220 | ||
2190 | return timespec64_trunc(now, inode->i_sb->s_time_gran); | 2221 | return timestamp_truncate(now, inode); |
2191 | } | 2222 | } |
2192 | EXPORT_SYMBOL(current_time); | 2223 | EXPORT_SYMBOL(current_time); |
2193 | 2224 | ||
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 9e30d8703735..62c0462dc89f 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include "isofs.h" | 30 | #include "isofs.h" |
31 | #include "zisofs.h" | 31 | #include "zisofs.h" |
32 | 32 | ||
33 | /* max tz offset is 13 hours */ | ||
34 | #define MAX_TZ_OFFSET (52*15*60) | ||
35 | |||
33 | #define BEQUIET | 36 | #define BEQUIET |
34 | 37 | ||
35 | static int isofs_hashi(const struct dentry *parent, struct qstr *qstr); | 38 | static int isofs_hashi(const struct dentry *parent, struct qstr *qstr); |
@@ -801,6 +804,10 @@ root_found: | |||
801 | */ | 804 | */ |
802 | s->s_maxbytes = 0x80000000000LL; | 805 | s->s_maxbytes = 0x80000000000LL; |
803 | 806 | ||
807 | /* ECMA-119 timestamp from 1900/1/1 with tz offset */ | ||
808 | s->s_time_min = mktime64(1900, 1, 1, 0, 0, 0) - MAX_TZ_OFFSET; | ||
809 | s->s_time_max = mktime64(U8_MAX+1900, 12, 31, 23, 59, 59) + MAX_TZ_OFFSET; | ||
810 | |||
804 | /* Set this for reference. Its not currently used except on write | 811 | /* Set this for reference. Its not currently used except on write |
805 | which we don't have .. */ | 812 | which we don't have .. */ |
806 | 813 | ||
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 8a20ddd25f2d..d0b59d03a7a9 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -590,6 +590,9 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
590 | sb->s_blocksize = PAGE_SIZE; | 590 | sb->s_blocksize = PAGE_SIZE; |
591 | sb->s_blocksize_bits = PAGE_SHIFT; | 591 | sb->s_blocksize_bits = PAGE_SHIFT; |
592 | sb->s_magic = JFFS2_SUPER_MAGIC; | 592 | sb->s_magic = JFFS2_SUPER_MAGIC; |
593 | sb->s_time_min = 0; | ||
594 | sb->s_time_max = U32_MAX; | ||
595 | |||
593 | if (!sb_rdonly(sb)) | 596 | if (!sb_rdonly(sb)) |
594 | jffs2_start_garbage_collect_thread(c); | 597 | jffs2_start_garbage_collect_thread(c); |
595 | return 0; | 598 | return 0; |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index f4e10cb9f734..b2dc4d1f9dcc 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -503,6 +503,8 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) | |||
503 | 503 | ||
504 | sb->s_fs_info = sbi; | 504 | sb->s_fs_info = sbi; |
505 | sb->s_max_links = JFS_LINK_MAX; | 505 | sb->s_max_links = JFS_LINK_MAX; |
506 | sb->s_time_min = 0; | ||
507 | sb->s_time_max = U32_MAX; | ||
506 | sbi->sb = sb; | 508 | sbi->sb = sb; |
507 | sbi->uid = INVALID_UID; | 509 | sbi->uid = INVALID_UID; |
508 | sbi->gid = INVALID_GID; | 510 | sbi->gid = INVALID_GID; |
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index f3f3984cce80..f3eaa8869f42 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c | |||
@@ -158,12 +158,11 @@ static inline void set_default_inode_attr(struct inode *inode, umode_t mode) | |||
158 | static inline void set_inode_attr(struct inode *inode, | 158 | static inline void set_inode_attr(struct inode *inode, |
159 | struct kernfs_iattrs *attrs) | 159 | struct kernfs_iattrs *attrs) |
160 | { | 160 | { |
161 | struct super_block *sb = inode->i_sb; | ||
162 | inode->i_uid = attrs->ia_uid; | 161 | inode->i_uid = attrs->ia_uid; |
163 | inode->i_gid = attrs->ia_gid; | 162 | inode->i_gid = attrs->ia_gid; |
164 | inode->i_atime = timespec64_trunc(attrs->ia_atime, sb->s_time_gran); | 163 | inode->i_atime = timestamp_truncate(attrs->ia_atime, inode); |
165 | inode->i_mtime = timespec64_trunc(attrs->ia_mtime, sb->s_time_gran); | 164 | inode->i_mtime = timestamp_truncate(attrs->ia_mtime, inode); |
166 | inode->i_ctime = timespec64_trunc(attrs->ia_ctime, sb->s_time_gran); | 165 | inode->i_ctime = timestamp_truncate(attrs->ia_ctime, inode); |
167 | } | 166 | } |
168 | 167 | ||
169 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) | 168 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index f96073f25432..7cb5fd38eb14 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -277,6 +277,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
277 | 277 | ||
278 | /* set up enough so that it can read an inode */ | 278 | /* set up enough so that it can read an inode */ |
279 | s->s_op = &minix_sops; | 279 | s->s_op = &minix_sops; |
280 | s->s_time_min = 0; | ||
281 | s->s_time_max = U32_MAX; | ||
280 | root_inode = minix_iget(s, MINIX_ROOT_INO); | 282 | root_inode = minix_iget(s, MINIX_ROOT_INO); |
281 | if (IS_ERR(root_inode)) { | 283 | if (IS_ERR(root_inode)) { |
282 | ret = PTR_ERR(root_inode); | 284 | ret = PTR_ERR(root_inode); |
diff --git a/fs/namespace.c b/fs/namespace.c index 227f7b343034..93c043245c46 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2466,6 +2466,26 @@ static void set_mount_attributes(struct mount *mnt, unsigned int mnt_flags) | |||
2466 | unlock_mount_hash(); | 2466 | unlock_mount_hash(); |
2467 | } | 2467 | } |
2468 | 2468 | ||
2469 | static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *mnt) | ||
2470 | { | ||
2471 | struct super_block *sb = mnt->mnt_sb; | ||
2472 | |||
2473 | if (!__mnt_is_readonly(mnt) && | ||
2474 | (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) { | ||
2475 | char *buf = (char *)__get_free_page(GFP_KERNEL); | ||
2476 | char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM); | ||
2477 | struct tm tm; | ||
2478 | |||
2479 | time64_to_tm(sb->s_time_max, 0, &tm); | ||
2480 | |||
2481 | pr_warn("Mounted %s file system at %s supports timestamps until %04ld (0x%llx)\n", | ||
2482 | sb->s_type->name, mntpath, | ||
2483 | tm.tm_year+1900, (unsigned long long)sb->s_time_max); | ||
2484 | |||
2485 | free_page((unsigned long)buf); | ||
2486 | } | ||
2487 | } | ||
2488 | |||
2469 | /* | 2489 | /* |
2470 | * Handle reconfiguration of the mountpoint only without alteration of the | 2490 | * Handle reconfiguration of the mountpoint only without alteration of the |
2471 | * superblock it refers to. This is triggered by specifying MS_REMOUNT|MS_BIND | 2491 | * superblock it refers to. This is triggered by specifying MS_REMOUNT|MS_BIND |
@@ -2491,6 +2511,9 @@ static int do_reconfigure_mnt(struct path *path, unsigned int mnt_flags) | |||
2491 | if (ret == 0) | 2511 | if (ret == 0) |
2492 | set_mount_attributes(mnt, mnt_flags); | 2512 | set_mount_attributes(mnt, mnt_flags); |
2493 | up_write(&sb->s_umount); | 2513 | up_write(&sb->s_umount); |
2514 | |||
2515 | mnt_warn_timestamp_expiry(path, &mnt->mnt); | ||
2516 | |||
2494 | return ret; | 2517 | return ret; |
2495 | } | 2518 | } |
2496 | 2519 | ||
@@ -2531,6 +2554,9 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, | |||
2531 | } | 2554 | } |
2532 | up_write(&sb->s_umount); | 2555 | up_write(&sb->s_umount); |
2533 | } | 2556 | } |
2557 | |||
2558 | mnt_warn_timestamp_expiry(path, &mnt->mnt); | ||
2559 | |||
2534 | put_fs_context(fc); | 2560 | put_fs_context(fc); |
2535 | return err; | 2561 | return err; |
2536 | } | 2562 | } |
@@ -2739,8 +2765,13 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint, | |||
2739 | return PTR_ERR(mnt); | 2765 | return PTR_ERR(mnt); |
2740 | 2766 | ||
2741 | error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags); | 2767 | error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags); |
2742 | if (error < 0) | 2768 | if (error < 0) { |
2743 | mntput(mnt); | 2769 | mntput(mnt); |
2770 | return error; | ||
2771 | } | ||
2772 | |||
2773 | mnt_warn_timestamp_expiry(mountpoint, mnt); | ||
2774 | |||
2744 | return error; | 2775 | return error; |
2745 | } | 2776 | } |
2746 | 2777 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 703f595dce90..19a76cfa8b1f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -2382,6 +2382,15 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) | |||
2382 | sb->s_flags |= SB_POSIXACL; | 2382 | sb->s_flags |= SB_POSIXACL; |
2383 | sb->s_time_gran = 1; | 2383 | sb->s_time_gran = 1; |
2384 | sb->s_export_op = &nfs_export_ops; | 2384 | sb->s_export_op = &nfs_export_ops; |
2385 | } else | ||
2386 | sb->s_time_gran = 1000; | ||
2387 | |||
2388 | if (server->nfs_client->rpc_ops->version != 4) { | ||
2389 | sb->s_time_min = 0; | ||
2390 | sb->s_time_max = U32_MAX; | ||
2391 | } else { | ||
2392 | sb->s_time_min = S64_MIN; | ||
2393 | sb->s_time_max = S64_MAX; | ||
2385 | } | 2394 | } |
2386 | 2395 | ||
2387 | nfs_initialise_sb(sb); | 2396 | nfs_initialise_sb(sb); |
@@ -2402,7 +2411,6 @@ static void nfs_clone_super(struct super_block *sb, | |||
2402 | sb->s_maxbytes = old_sb->s_maxbytes; | 2411 | sb->s_maxbytes = old_sb->s_maxbytes; |
2403 | sb->s_xattr = old_sb->s_xattr; | 2412 | sb->s_xattr = old_sb->s_xattr; |
2404 | sb->s_op = old_sb->s_op; | 2413 | sb->s_op = old_sb->s_op; |
2405 | sb->s_time_gran = 1; | ||
2406 | sb->s_export_op = old_sb->s_export_op; | 2414 | sb->s_export_op = old_sb->s_export_op; |
2407 | 2415 | ||
2408 | if (server->nfs_client->rpc_ops->version != 2) { | 2416 | if (server->nfs_client->rpc_ops->version != 2) { |
@@ -2410,6 +2418,16 @@ static void nfs_clone_super(struct super_block *sb, | |||
2410 | * so ourselves when necessary. | 2418 | * so ourselves when necessary. |
2411 | */ | 2419 | */ |
2412 | sb->s_flags |= SB_POSIXACL; | 2420 | sb->s_flags |= SB_POSIXACL; |
2421 | sb->s_time_gran = 1; | ||
2422 | } else | ||
2423 | sb->s_time_gran = 1000; | ||
2424 | |||
2425 | if (server->nfs_client->rpc_ops->version != 4) { | ||
2426 | sb->s_time_min = 0; | ||
2427 | sb->s_time_max = U32_MAX; | ||
2428 | } else { | ||
2429 | sb->s_time_min = S64_MIN; | ||
2430 | sb->s_time_max = S64_MAX; | ||
2413 | } | 2431 | } |
2414 | 2432 | ||
2415 | nfs_initialise_sb(sb); | 2433 | nfs_initialise_sb(sb); |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 8baa34baf548..6c7388430ad3 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -2899,15 +2899,18 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
2899 | ia_valid |= ATTR_MTIME | ATTR_CTIME; | 2899 | ia_valid |= ATTR_MTIME | ATTR_CTIME; |
2900 | } | 2900 | } |
2901 | } | 2901 | } |
2902 | if (ia_valid & ATTR_ATIME) | 2902 | if (ia_valid & ATTR_ATIME) { |
2903 | vi->i_atime = timespec64_trunc(attr->ia_atime, | 2903 | vi->i_atime = timestamp_truncate(attr->ia_atime, |
2904 | vi->i_sb->s_time_gran); | 2904 | vi); |
2905 | if (ia_valid & ATTR_MTIME) | 2905 | } |
2906 | vi->i_mtime = timespec64_trunc(attr->ia_mtime, | 2906 | if (ia_valid & ATTR_MTIME) { |
2907 | vi->i_sb->s_time_gran); | 2907 | vi->i_mtime = timestamp_truncate(attr->ia_mtime, |
2908 | if (ia_valid & ATTR_CTIME) | 2908 | vi); |
2909 | vi->i_ctime = timespec64_trunc(attr->ia_ctime, | 2909 | } |
2910 | vi->i_sb->s_time_gran); | 2910 | if (ia_valid & ATTR_CTIME) { |
2911 | vi->i_ctime = timestamp_truncate(attr->ia_ctime, | ||
2912 | vi); | ||
2913 | } | ||
2911 | mark_inode_dirty(vi); | 2914 | mark_inode_dirty(vi); |
2912 | out: | 2915 | out: |
2913 | return err; | 2916 | return err; |
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index 08226a835ec3..b76ec6b88ded 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c | |||
@@ -478,6 +478,10 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) | |||
478 | 478 | ||
479 | sb->s_maxbytes = 0xffffffff; | 479 | sb->s_maxbytes = 0xffffffff; |
480 | 480 | ||
481 | sb->s_time_gran = NSEC_PER_MSEC; | ||
482 | sb->s_time_min = 0; | ||
483 | sb->s_time_max = U64_MAX / MSEC_PER_SEC; | ||
484 | |||
481 | sb_set_blocksize(sb, 0x200); | 485 | sb_set_blocksize(sb, 0x200); |
482 | 486 | ||
483 | bh = sb_bread(sb, 0); | 487 | bh = sb_bread(sb, 0); |
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 2bb3468fc93a..8caff834f002 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
@@ -144,6 +144,7 @@ static int ramoops_read_kmsg_hdr(char *buffer, struct timespec64 *time, | |||
144 | if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu-%c\n%n", | 144 | if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu-%c\n%n", |
145 | (time64_t *)&time->tv_sec, &time->tv_nsec, &data_type, | 145 | (time64_t *)&time->tv_sec, &time->tv_nsec, &data_type, |
146 | &header_length) == 3) { | 146 | &header_length) == 3) { |
147 | time->tv_nsec *= 1000; | ||
147 | if (data_type == 'C') | 148 | if (data_type == 'C') |
148 | *compressed = true; | 149 | *compressed = true; |
149 | else | 150 | else |
@@ -151,6 +152,7 @@ static int ramoops_read_kmsg_hdr(char *buffer, struct timespec64 *time, | |||
151 | } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu\n%n", | 152 | } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu\n%n", |
152 | (time64_t *)&time->tv_sec, &time->tv_nsec, | 153 | (time64_t *)&time->tv_sec, &time->tv_nsec, |
153 | &header_length) == 2) { | 154 | &header_length) == 2) { |
155 | time->tv_nsec *= 1000; | ||
154 | *compressed = false; | 156 | *compressed = false; |
155 | } else { | 157 | } else { |
156 | time->tv_sec = 0; | 158 | time->tv_sec = 0; |
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 922d083bbc7c..e8da1cde87b9 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c | |||
@@ -201,6 +201,8 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent) | |||
201 | s->s_op = &qnx4_sops; | 201 | s->s_op = &qnx4_sops; |
202 | s->s_magic = QNX4_SUPER_MAGIC; | 202 | s->s_magic = QNX4_SUPER_MAGIC; |
203 | s->s_flags |= SB_RDONLY; /* Yup, read-only yet */ | 203 | s->s_flags |= SB_RDONLY; /* Yup, read-only yet */ |
204 | s->s_time_min = 0; | ||
205 | s->s_time_max = U32_MAX; | ||
204 | 206 | ||
205 | /* Check the superblock signature. Since the qnx4 code is | 207 | /* Check the superblock signature. Since the qnx4 code is |
206 | dangerous, we should leave as quickly as possible | 208 | dangerous, we should leave as quickly as possible |
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c index 0f8b0ff1ba43..345db56c98fd 100644 --- a/fs/qnx6/inode.c +++ b/fs/qnx6/inode.c | |||
@@ -429,6 +429,8 @@ mmi_success: | |||
429 | s->s_op = &qnx6_sops; | 429 | s->s_op = &qnx6_sops; |
430 | s->s_magic = QNX6_SUPER_MAGIC; | 430 | s->s_magic = QNX6_SUPER_MAGIC; |
431 | s->s_flags |= SB_RDONLY; /* Yup, read-only yet */ | 431 | s->s_flags |= SB_RDONLY; /* Yup, read-only yet */ |
432 | s->s_time_min = 0; | ||
433 | s->s_time_max = U32_MAX; | ||
432 | 434 | ||
433 | /* ease the later tree level calculations */ | 435 | /* ease the later tree level calculations */ |
434 | sbi = QNX6_SB(s); | 436 | sbi = QNX6_SB(s); |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index ab028ea0e561..d69b4ac0ae2f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1976,6 +1976,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1976 | goto error_unlocked; | 1976 | goto error_unlocked; |
1977 | } | 1977 | } |
1978 | 1978 | ||
1979 | s->s_time_min = 0; | ||
1980 | s->s_time_max = U32_MAX; | ||
1981 | |||
1979 | rs = SB_DISK_SUPER_BLOCK(s); | 1982 | rs = SB_DISK_SUPER_BLOCK(s); |
1980 | /* | 1983 | /* |
1981 | * Let's do basic sanity check to verify that underlying device is not | 1984 | * Let's do basic sanity check to verify that underlying device is not |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index 7d580f7c3f1d..a42c0e3079dc 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
@@ -478,6 +478,8 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) | |||
478 | sb->s_maxbytes = 0xFFFFFFFF; | 478 | sb->s_maxbytes = 0xFFFFFFFF; |
479 | sb->s_magic = ROMFS_MAGIC; | 479 | sb->s_magic = ROMFS_MAGIC; |
480 | sb->s_flags |= SB_RDONLY | SB_NOATIME; | 480 | sb->s_flags |= SB_RDONLY | SB_NOATIME; |
481 | sb->s_time_min = 0; | ||
482 | sb->s_time_max = 0; | ||
481 | sb->s_op = &romfs_super_ops; | 483 | sb->s_op = &romfs_super_ops; |
482 | 484 | ||
483 | #ifdef CONFIG_ROMFS_ON_MTD | 485 | #ifdef CONFIG_ROMFS_ON_MTD |
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index effa638d6d85..a9e9837617a9 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
@@ -183,6 +183,8 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
183 | (u64) le64_to_cpu(sblk->id_table_start)); | 183 | (u64) le64_to_cpu(sblk->id_table_start)); |
184 | 184 | ||
185 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 185 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
186 | sb->s_time_min = 0; | ||
187 | sb->s_time_max = U32_MAX; | ||
186 | sb->s_flags |= SB_RDONLY; | 188 | sb->s_flags |= SB_RDONLY; |
187 | sb->s_op = &squashfs_super_ops; | 189 | sb->s_op = &squashfs_super_ops; |
188 | 190 | ||
diff --git a/fs/super.c b/fs/super.c index 9459ba75a32e..2d679db9e8c7 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -258,6 +258,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, | |||
258 | s->s_maxbytes = MAX_NON_LFS; | 258 | s->s_maxbytes = MAX_NON_LFS; |
259 | s->s_op = &default_op; | 259 | s->s_op = &default_op; |
260 | s->s_time_gran = 1000000000; | 260 | s->s_time_gran = 1000000000; |
261 | s->s_time_min = TIME64_MIN; | ||
262 | s->s_time_max = TIME64_MAX; | ||
261 | s->cleancache_poolid = CLEANCACHE_NO_POOL; | 263 | s->cleancache_poolid = CLEANCACHE_NO_POOL; |
262 | 264 | ||
263 | s->s_shrink.seeks = DEFAULT_SEEKS; | 265 | s->s_shrink.seeks = DEFAULT_SEEKS; |
diff --git a/fs/sysv/super.c b/fs/sysv/super.c index d788b1daa7eb..cc8e2ed155c8 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c | |||
@@ -368,7 +368,8 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) | |||
368 | sbi->s_block_base = 0; | 368 | sbi->s_block_base = 0; |
369 | mutex_init(&sbi->s_lock); | 369 | mutex_init(&sbi->s_lock); |
370 | sb->s_fs_info = sbi; | 370 | sb->s_fs_info = sbi; |
371 | 371 | sb->s_time_min = 0; | |
372 | sb->s_time_max = U32_MAX; | ||
372 | sb_set_blocksize(sb, BLOCK_SIZE); | 373 | sb_set_blocksize(sb, BLOCK_SIZE); |
373 | 374 | ||
374 | for (i = 0; i < ARRAY_SIZE(flavours) && !size; i++) { | 375 | for (i = 0; i < ARRAY_SIZE(flavours) && !size; i++) { |
@@ -487,6 +488,8 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) | |||
487 | sbi->s_type = FSTYPE_V7; | 488 | sbi->s_type = FSTYPE_V7; |
488 | mutex_init(&sbi->s_lock); | 489 | mutex_init(&sbi->s_lock); |
489 | sb->s_fs_info = sbi; | 490 | sb->s_fs_info = sbi; |
491 | sb->s_time_min = 0; | ||
492 | sb->s_time_max = U32_MAX; | ||
490 | 493 | ||
491 | sb_set_blocksize(sb, 512); | 494 | sb_set_blocksize(sb, 512); |
492 | 495 | ||
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 400970d740bb..cd52585c8f4f 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -1078,15 +1078,18 @@ static void do_attr_changes(struct inode *inode, const struct iattr *attr) | |||
1078 | inode->i_uid = attr->ia_uid; | 1078 | inode->i_uid = attr->ia_uid; |
1079 | if (attr->ia_valid & ATTR_GID) | 1079 | if (attr->ia_valid & ATTR_GID) |
1080 | inode->i_gid = attr->ia_gid; | 1080 | inode->i_gid = attr->ia_gid; |
1081 | if (attr->ia_valid & ATTR_ATIME) | 1081 | if (attr->ia_valid & ATTR_ATIME) { |
1082 | inode->i_atime = timespec64_trunc(attr->ia_atime, | 1082 | inode->i_atime = timestamp_truncate(attr->ia_atime, |
1083 | inode->i_sb->s_time_gran); | 1083 | inode); |
1084 | if (attr->ia_valid & ATTR_MTIME) | 1084 | } |
1085 | inode->i_mtime = timespec64_trunc(attr->ia_mtime, | 1085 | if (attr->ia_valid & ATTR_MTIME) { |
1086 | inode->i_sb->s_time_gran); | 1086 | inode->i_mtime = timestamp_truncate(attr->ia_mtime, |
1087 | if (attr->ia_valid & ATTR_CTIME) | 1087 | inode); |
1088 | inode->i_ctime = timespec64_trunc(attr->ia_ctime, | 1088 | } |
1089 | inode->i_sb->s_time_gran); | 1089 | if (attr->ia_valid & ATTR_CTIME) { |
1090 | inode->i_ctime = timestamp_truncate(attr->ia_ctime, | ||
1091 | inode); | ||
1092 | } | ||
1090 | if (attr->ia_valid & ATTR_MODE) { | 1093 | if (attr->ia_valid & ATTR_MODE) { |
1091 | umode_t mode = attr->ia_mode; | 1094 | umode_t mode = attr->ia_mode; |
1092 | 1095 | ||
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 4ed0dca52ec8..1da0be667409 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -843,6 +843,10 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
843 | 843 | ||
844 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 844 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
845 | 845 | ||
846 | sb->s_time_gran = NSEC_PER_SEC; | ||
847 | sb->s_time_min = S32_MIN; | ||
848 | sb->s_time_max = S32_MAX; | ||
849 | |||
846 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { | 850 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { |
847 | case UFS_MOUNT_UFSTYPE_44BSD: | 851 | case UFS_MOUNT_UFSTYPE_44BSD: |
848 | UFSD("ufstype=44bsd\n"); | 852 | UFSD("ufstype=44bsd\n"); |
@@ -861,6 +865,9 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
861 | uspi->s_fshift = 9; | 865 | uspi->s_fshift = 9; |
862 | uspi->s_sbsize = super_block_size = 1536; | 866 | uspi->s_sbsize = super_block_size = 1536; |
863 | uspi->s_sbbase = 0; | 867 | uspi->s_sbbase = 0; |
868 | sb->s_time_gran = 1; | ||
869 | sb->s_time_min = S64_MIN; | ||
870 | sb->s_time_max = S64_MAX; | ||
864 | flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 871 | flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
865 | break; | 872 | break; |
866 | 873 | ||
diff --git a/fs/utimes.c b/fs/utimes.c index 350c9c16ace1..1ba3f7883870 100644 --- a/fs/utimes.c +++ b/fs/utimes.c | |||
@@ -36,16 +36,14 @@ static int utimes_common(const struct path *path, struct timespec64 *times) | |||
36 | if (times[0].tv_nsec == UTIME_OMIT) | 36 | if (times[0].tv_nsec == UTIME_OMIT) |
37 | newattrs.ia_valid &= ~ATTR_ATIME; | 37 | newattrs.ia_valid &= ~ATTR_ATIME; |
38 | else if (times[0].tv_nsec != UTIME_NOW) { | 38 | else if (times[0].tv_nsec != UTIME_NOW) { |
39 | newattrs.ia_atime.tv_sec = times[0].tv_sec; | 39 | newattrs.ia_atime = timestamp_truncate(times[0], inode); |
40 | newattrs.ia_atime.tv_nsec = times[0].tv_nsec; | ||
41 | newattrs.ia_valid |= ATTR_ATIME_SET; | 40 | newattrs.ia_valid |= ATTR_ATIME_SET; |
42 | } | 41 | } |
43 | 42 | ||
44 | if (times[1].tv_nsec == UTIME_OMIT) | 43 | if (times[1].tv_nsec == UTIME_OMIT) |
45 | newattrs.ia_valid &= ~ATTR_MTIME; | 44 | newattrs.ia_valid &= ~ATTR_MTIME; |
46 | else if (times[1].tv_nsec != UTIME_NOW) { | 45 | else if (times[1].tv_nsec != UTIME_NOW) { |
47 | newattrs.ia_mtime.tv_sec = times[1].tv_sec; | 46 | newattrs.ia_mtime = timestamp_truncate(times[1], inode); |
48 | newattrs.ia_mtime.tv_nsec = times[1].tv_nsec; | ||
49 | newattrs.ia_valid |= ATTR_MTIME_SET; | 47 | newattrs.ia_valid |= ATTR_MTIME_SET; |
50 | } | 48 | } |
51 | /* | 49 | /* |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 391b4748cae3..8d1df9f8be07 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -1664,6 +1664,8 @@ xfs_fs_fill_super( | |||
1664 | sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits); | 1664 | sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits); |
1665 | sb->s_max_links = XFS_MAXLINK; | 1665 | sb->s_max_links = XFS_MAXLINK; |
1666 | sb->s_time_gran = 1; | 1666 | sb->s_time_gran = 1; |
1667 | sb->s_time_min = S32_MIN; | ||
1668 | sb->s_time_max = S32_MAX; | ||
1667 | sb->s_iflags |= SB_I_CGROUPWB; | 1669 | sb->s_iflags |= SB_I_CGROUPWB; |
1668 | 1670 | ||
1669 | set_posix_acl_flag(sb); | 1671 | set_posix_acl_flag(sb); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index ffe35d97afcb..866268c2c6e3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -732,6 +732,8 @@ struct inode { | |||
732 | void *i_private; /* fs or device private pointer */ | 732 | void *i_private; /* fs or device private pointer */ |
733 | } __randomize_layout; | 733 | } __randomize_layout; |
734 | 734 | ||
735 | struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode); | ||
736 | |||
735 | static inline unsigned int i_blocksize(const struct inode *node) | 737 | static inline unsigned int i_blocksize(const struct inode *node) |
736 | { | 738 | { |
737 | return (1 << node->i_blkbits); | 739 | return (1 << node->i_blkbits); |
@@ -1458,6 +1460,9 @@ struct super_block { | |||
1458 | 1460 | ||
1459 | /* Granularity of c/m/atime in ns (cannot be worse than a second) */ | 1461 | /* Granularity of c/m/atime in ns (cannot be worse than a second) */ |
1460 | u32 s_time_gran; | 1462 | u32 s_time_gran; |
1463 | /* Time limits for c/m/atime in seconds */ | ||
1464 | time64_t s_time_min; | ||
1465 | time64_t s_time_max; | ||
1461 | #ifdef CONFIG_FSNOTIFY | 1466 | #ifdef CONFIG_FSNOTIFY |
1462 | __u32 s_fsnotify_mask; | 1467 | __u32 s_fsnotify_mask; |
1463 | struct fsnotify_mark_connector __rcu *s_fsnotify_marks; | 1468 | struct fsnotify_mark_connector __rcu *s_fsnotify_marks; |
diff --git a/include/linux/time64.h b/include/linux/time64.h index a620ee610b9f..19125489ae94 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h | |||
@@ -30,6 +30,8 @@ struct itimerspec64 { | |||
30 | 30 | ||
31 | /* Located here for timespec[64]_valid_strict */ | 31 | /* Located here for timespec[64]_valid_strict */ |
32 | #define TIME64_MAX ((s64)~((u64)1 << 63)) | 32 | #define TIME64_MAX ((s64)~((u64)1 << 63)) |
33 | #define TIME64_MIN (-TIME64_MAX - 1) | ||
34 | |||
33 | #define KTIME_MAX ((s64)~((u64)1 << 63)) | 35 | #define KTIME_MAX ((s64)~((u64)1 << 63)) |
34 | #define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) | 36 | #define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) |
35 | 37 | ||