Re: [PATCH 16/31] nds32: VDSO support
> Do applications call into the vdso directly and expect to get a timespec > out? If they always go through the C library as an intermediate, then > the glibc clock_gettime() could do the conversion. It is recommended that applications do not call vdso symbols directly. According to manpage: "If you're trying to call the vDSO in your own application rather than using the C library, you're most likely doing it wrong." -Deepa
Re: [PATCH 16/31] nds32: VDSO support
On Wed, Nov 8, 2017 at 1:37 AM, Arnd Bergmannwrote: > On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu wrote: > >> --- /dev/null >> +++ b/arch/nds32/include/asm/vdso_datapage.h >> @@ -0,0 +1,51 @@ > >> +#ifndef __ASM_VDSO_DATAPAGE_H >> +#define __ASM_VDSO_DATAPAGE_H >> + >> +#ifdef __KERNEL__ >> + >> +#ifndef __ASSEMBLY__ >> + >> +struct vdso_data { >> + bool cycle_count_down; /* timer cyclye counter is decrease with >> time */ >> + u32 cycle_count_offset; /* offset of timer cycle counter register */ >> + u32 seq_count; /* sequence count - odd during updates */ >> + u32 xtime_coarse_sec; /* coarse time */ >> + u32 xtime_coarse_nsec; >> + >> + u32 wtm_clock_sec; /* wall to monotonic offset */ >> + u32 wtm_clock_nsec; >> + u32 xtime_clock_sec;/* CLOCK_REALTIME - seconds */ >> + u32 cs_mult;/* clocksource multiplier */ >> + u32 cs_shift; /* Cycle to nanosecond divisor (power of >> two) */ >> + >> + u64 cs_cycle_last; /* last cycle value */ >> + u64 cs_mask;/* clocksource mask */ >> + >> + u64 xtime_clock_nsec; /* CLOCK_REALTIME sub-ns base */ >> + u32 tz_minuteswest; /* timezone info for gettimeofday(2) */ >> + u32 tz_dsttime; >> +}; > > I need some insight from Deepa and Palmer here: to prepare for 64-bit > time_t in the > future, would it make sense to define the vdso to use 64-bit seconds numbers > consistently, and provide vdso symbols that return 64-bit times, having the > glibc convert that to normal timespec values, or should we leave it for now? Other architectures also have a similar way of defining these as u32 (eg: x86) I think for performance reasons on 32 bit systems. u32 still works until 2106 as the timekeeping structures are s64. I was planning to leave it that way for x86. If this architecture can live with u64, then it will be better to use it here. > For the normal syscalls I think we are better off keeping things consistent > between architectures, but the vdso is architecture specific by definition, so > we may as well use 64-bit times there now (same for risc-v, which still > has time to modify this before the 4.15 release and glibc merge). But, I don't think this vdso can return 64 bit times without syscalls for the architecture also supporting that. The problem is that all fallback paths depend on syscalls directly. Also I couldn't find any arch specific handling of vdso interfaces in glibc. I think they expect the vdso wrappers in the kernel to handle this part. -Deepa
Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
On Thu, Jun 1, 2017 at 5:36 PM, John Stultz <john.stu...@linaro.org> wrote: > On Thu, Jun 1, 2017 at 5:26 PM, Yan, Zheng <uker...@gmail.com> wrote: >> On Thu, Jun 1, 2017 at 6:22 PM, Arnd Bergmann <a...@arndb.de> wrote: >>> On Thu, Jun 1, 2017 at 11:56 AM, Yan, Zheng <uker...@gmail.com> wrote: >>>> On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.ker...@gmail.com> >>>> wrote: >>> >>>>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c >>>>> index 517838b..77204da 100644 >>>>> --- a/drivers/block/rbd.c >>>>> +++ b/drivers/block/rbd.c >>>>> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct >>>>> rbd_obj_request *obj_request) >>>>> { >>>>> struct ceph_osd_request *osd_req = obj_request->osd_req; >>>>> >>>>> - osd_req->r_mtime = CURRENT_TIME; >>>>> + ktime_get_real_ts(_req->r_mtime); >>>>> osd_req->r_data_offset = obj_request->offset; >>>>> } >>>>> >>>>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c >>>>> index c681762..1d3fa90 100644 >>>>> --- a/fs/ceph/mds_client.c >>>>> +++ b/fs/ceph/mds_client.c >>>>> @@ -1666,6 +1666,7 @@ struct ceph_mds_request * >>>>> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode) >>>>> { >>>>> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS); >>>>> + struct timespec ts; >>>>> >>>>> if (!req) >>>>> return ERR_PTR(-ENOMEM); >>>>> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client >>>>> *mdsc, int op, int mode) >>>>> init_completion(>r_safe_completion); >>>>> INIT_LIST_HEAD(>r_unsafe_item); >>>>> >>>>> - req->r_stamp = current_fs_time(mdsc->fsc->sb); >>>>> + ktime_get_real_ts(); >>>>> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran); >>>> >>>> This change causes our kernel_untar_tar test case to fail (inode's >>>> ctime goes back). The reason is that there is time drift between the >>>> time stamps got by ktime_get_real_ts() and current_time(). We need to >>>> revert this change until current_time() uses ktime_get_real_ts() >>>> internally. >>> >>> Hmm, the change was not supposed to have a user-visible effect, so >>> something has gone wrong, but I don't immediately see how it >>> relates to what you observe. >>> >>> ktime_get_real_ts() and current_time() use the same time base, there >>> is no drift, but there is a difference in resolution, as the latter uses >>> the time stamp of the last jiffies update, which may be up to one jiffy >>> (10ms) behind the exact time we put in the request stamps here. >>> >>> Do you still see problems if you use current_kernel_time() instead of >>> ktime_get_real_ts()? >> >> The problem disappears after using current_kernel_time(). >> >> https://github.com/ceph/ceph-client/commit/2e0f648da23167034a3cf1500bc90ec60aef2417 > > From the commit above: > "It seems there is time drift between ktime_get_real_ts() and > current_kernel_time()" > > Its more of a granularity difference. current_kernel_time() returns > the cached time at the last tick, where as ktime_get_real_ts() reads > the clocksource hardware and returns the immediate time. > > Filesystems usually use the cached time (similar to > CLOCK_REALTIME_COARSE), for performance reasons, as touching the > clocksource takes time. Alternatively, it would be best for this code also to use current_time(). I had suggested this in one of the previous versions of the patch. The implementation of current_time() will change when we switch vfs to use 64 bit time. This will prevent such errors from happening again. But, this also means there is more code reordering for these modules to get a reference to inode. -Deepa
Re: [PATCH 06/12] audit: Use timespec64 to represent audit timestamps
> I have no problem merging this patch into audit/next for v4.12, would > you prefer me to do that so at least this patch is merged? This would be fine. But, I think whoever takes the last 2 deletion patches should also take them. I'm not sure how that part works out. > It would probably make life a small bit easier for us in the audit > world too as it would reduce the potential merge conflict. However, > that's a relatively small thing to worry about. -Deepa
Re: [PATCH 02/12] trace: Make trace_hwlat timestamp y2038 safe
>> - trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%ld.%09ld", >> + trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu >> ts:%lld.%09ld", >>field->seqnum, >>field->duration, >>field->outer_duration, >> - field->timestamp.tv_sec, >> + (long long)field->timestamp.tv_sec, > > Refresh my memory. We need the cast because on 64 bit boxes > timestamp.tv_sec is just a long? This is only required until we change the definition of timespec64. Right now it is defined as #if __BITS_PER_LONG == 64 # define timespec64 timespec #else struct timespec64 { time64_t tv_sec; long tv_nsec; }; #endif And timespec.tv_sec is just long int on 64 bit machines. This is why we need the cast now. We will probably change this and only define __kernel_timespec instead of timespec, leaving only one definition of timespec64. At that time, we will not need this. -Deepa
[PATCH 05/12] fs: ufs: Use ktime_get_real_ts64() for birthtime
CURRENT_TIME is not y2038 safe. Replace it with ktime_get_real_ts64(). Inode time formats are already 64 bit long and accommodates time64_t. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> --- fs/ufs/ialloc.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 9774555..d1dd8cc 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -176,6 +176,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode) struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; struct inode * inode; + struct timespec64 ts; unsigned cg, bit, i, j, start; struct ufs_inode_info *ufsi; int err = -ENOSPC; @@ -323,8 +324,9 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode) lock_buffer(bh); ufs2_inode = (struct ufs2_inode *)bh->b_data; ufs2_inode += ufs_inotofsbo(inode->i_ino); - ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec); - ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec); + ktime_get_real_ts64(); + ufs2_inode->ui_birthtime = cpu_to_fs64(sb, ts.tv_sec); + ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, ts.tv_nsec); mark_buffer_dirty(bh); unlock_buffer(bh); if (sb->s_flags & MS_SYNCHRONOUS) -- 2.7.4
[PATCH 02/12] trace: Make trace_hwlat timestamp y2038 safe
struct timespec is not y2038 safe on 32 bit machines and needs to be replaced by struct timespec64 in order to represent times beyond year 2038 on such machines. Fix all the timestamp representation in struct trace_hwlat and all the corresponding implementations. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> --- kernel/trace/trace_entries.h | 6 +++--- kernel/trace/trace_hwlat.c | 14 +++--- kernel/trace/trace_output.c | 9 - 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index c203ac4..adcdbbe 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -348,14 +348,14 @@ FTRACE_ENTRY(hwlat, hwlat_entry, __field(u64,duration) __field(u64,outer_duration ) __field(u64,nmi_total_ts) - __field_struct( struct timespec,timestamp ) - __field_desc( long, timestamp, tv_sec ) + __field_struct( struct timespec64, timestamp ) + __field_desc( s64,timestamp, tv_sec ) __field_desc( long, timestamp, tv_nsec ) __field(unsigned int, nmi_count ) __field(unsigned int, seqnum ) ), - F_printk("cnt:%u\tts:%010lu.%010lu\tinner:%llu\touter:%llunmi-ts:%llu\tnmi-count:%u\n", + F_printk("cnt:%u\tts:%010llu.%010lu\tinner:%llu\touter:%llunmi-ts:%llu\tnmi-count:%u\n", __entry->seqnum, __entry->tv_sec, __entry->tv_nsec, diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index 21ea6ae..d7c8e4e 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -79,12 +79,12 @@ static u64 last_tracing_thresh = DEFAULT_LAT_THRESHOLD * NSEC_PER_USEC; /* Individual latency samples are stored here when detected. */ struct hwlat_sample { - u64 seqnum; /* unique sequence */ - u64 duration; /* delta */ - u64 outer_duration; /* delta (outer loop) */ - u64 nmi_total_ts; /* Total time spent in NMIs */ - struct timespec timestamp; /* wall time */ - int nmi_count; /* # NMIs during this sample */ + u64 seqnum; /* unique sequence */ + u64 duration; /* delta */ + u64 outer_duration; /* delta (outer loop) */ + u64 nmi_total_ts; /* Total time spent in NMIs */ + struct timespec64 timestamp; /* wall time */ + int nmi_count; /* # NMIs during this sample */ }; /* keep the global state somewhere. */ @@ -250,7 +250,7 @@ static int get_sample(void) s.seqnum = hwlat_data.count; s.duration = sample; s.outer_duration = outer_sample; - s.timestamp = CURRENT_TIME; + ktime_get_real_ts64(); s.nmi_total_ts = nmi_total_ts; s.nmi_count = nmi_count; trace_hwlat_sample(); diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 02a4aeb..08f9bab 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -4,7 +4,6 @@ * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srost...@redhat.com> * */ - #include #include #include @@ -1161,11 +1160,11 @@ trace_hwlat_print(struct trace_iterator *iter, int flags, trace_assign_type(field, entry); - trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%ld.%09ld", + trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld", field->seqnum, field->duration, field->outer_duration, -field->timestamp.tv_sec, +(long long)field->timestamp.tv_sec, field->timestamp.tv_nsec); if (field->nmi_count) { @@ -1195,10 +1194,10 @@ trace_hwlat_raw(struct trace_iterator *iter, int flags, trace_assign_type(field, iter->ent); - trace_seq_printf(s, "%llu %lld %ld %09ld %u\n", + trace_seq_printf(s, "%llu %lld %lld %09ld %u\n", field->duration, field->outer_duration, -field->timestamp.tv_sec, +(long long)field->timestamp.tv_sec, field->timestamp.tv_nsec, field->seqnum); -- 2.7.4
[PATCH 10/12] apparmorfs: Replace CURRENT_TIME with current_time()
CURRENT_TIME macro is not y2038 safe on 32 bit systems. The patch replaces all the uses of CURRENT_TIME by current_time(). This is also in preparation for the patch that transitions vfs timestamps to use 64 bit time and hence make them y2038 safe. current_time() is also planned to be transitioned to y2038 safe behavior along with this change. CURRENT_TIME macro will be deleted before merging the aforementioned change. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> --- security/apparmor/apparmorfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index be0b498..4f6ac9d 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -1357,7 +1357,7 @@ static int aa_mk_null_file(struct dentry *parent) inode->i_ino = get_next_ino(); inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); d_instantiate(dentry, inode); -- 2.7.4
[PATCH 11/12] time: Delete CURRENT_TIME_SEC and CURRENT_TIME
All uses of CURRENT_TIME_SEC and CURRENT_TIME macros have been replaced by other time functions. These macros are also not y2038 safe. And, all their use cases can be fulfilled by y2038 safe ktime_get_* variants. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Acked-by: John Stultz <john.stu...@linaro.org> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- include/linux/time.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/time.h b/include/linux/time.h index 23f0f5c..c0543f5 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -151,9 +151,6 @@ static inline bool timespec_inject_offset_valid(const struct timespec *ts) return true; } -#define CURRENT_TIME (current_kernel_time()) -#define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 }) - /* Some architectures do not supply their own clocksource. * This is mainly the case in architectures that get their * inter-tick times by reading the counter on their interval -- 2.7.4
[PATCH 09/12] lustre: Replace CURRENT_TIME macro
CURRENT_TIME macro is not y2038 safe on 32 bit systems. The patch replaces all the uses of CURRENT_TIME by current_time() for filesystem times, and ktime_get_* functions for others. struct timespec is also not y2038 safe. Retain timespec for timestamp representation here as lustre uses it internally everywhere. These references will be changed to use struct timespec64 in a separate patch. This is also in preparation for the patch that transitions vfs timestamps to use 64 bit time and hence make them y2038 safe. current_time() is also planned to be transitioned to y2038 safe behavior along with this change. CURRENT_TIME macro will be deleted before merging the aforementioned change. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> --- drivers/staging/lustre/lustre/llite/llite_lib.c | 6 +++--- drivers/staging/lustre/lustre/osc/osc_io.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 7b80040..2b4b6b9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1472,17 +1472,17 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) /* We mark all of the fields "set" so MDS/OST does not re-set them */ if (attr->ia_valid & ATTR_CTIME) { - attr->ia_ctime = CURRENT_TIME; + attr->ia_ctime = current_time(inode); attr->ia_valid |= ATTR_CTIME_SET; } if (!(attr->ia_valid & ATTR_ATIME_SET) && (attr->ia_valid & ATTR_ATIME)) { - attr->ia_atime = CURRENT_TIME; + attr->ia_atime = current_time(inode); attr->ia_valid |= ATTR_ATIME_SET; } if (!(attr->ia_valid & ATTR_MTIME_SET) && (attr->ia_valid & ATTR_MTIME)) { - attr->ia_mtime = CURRENT_TIME; + attr->ia_mtime = current_time(inode); attr->ia_valid |= ATTR_MTIME_SET; } diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index f991bee..cbab800 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -216,7 +216,7 @@ static int osc_io_submit(const struct lu_env *env, struct cl_object *obj = ios->cis_obj; cl_object_attr_lock(obj); - attr->cat_mtime = LTIME_S(CURRENT_TIME); + attr->cat_mtime = ktime_get_real_seconds(); attr->cat_ctime = attr->cat_mtime; cl_object_attr_update(env, obj, attr, CAT_MTIME | CAT_CTIME); cl_object_attr_unlock(obj); @@ -256,7 +256,7 @@ static void osc_page_touch_at(const struct lu_env *env, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms, loi->loi_lvb.lvb_size); - attr->cat_ctime = LTIME_S(CURRENT_TIME); + attr->cat_ctime = ktime_get_real_seconds(); attr->cat_mtime = attr->cat_ctime; valid = CAT_MTIME | CAT_CTIME; if (kms > loi->loi_kms) { -- 2.7.4
[PATCH 07/12] fs: btrfs: Use ktime_get_real_ts for root ctime
btrfs_root_item maintains the ctime for root updates. This is not part of vfs_inode. Since current_time() uses struct inode* as an argument as Linus suggested, this cannot be used to update root times unless, we modify the signature to use inode. Since btrfs uses nanosecond time granularity, it can also use ktime_get_real_ts directly to obtain timestamp for the root. It is necessary to use the timespec time api here because the same btrfs_set_stack_timespec_*() apis are used for vfs inode times as well. These can be transitioned to using timespec64 when btrfs internally changes to use timespec64 as well. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Acked-by: David Sterba <dste...@suse.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- fs/btrfs/root-tree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index a08224e..7d6bc30 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -501,8 +501,9 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans, struct btrfs_root *root) { struct btrfs_root_item *item = >root_item; - struct timespec ct = current_fs_time(root->fs_info->sb); + struct timespec ct; + ktime_get_real_ts(); spin_lock(>root_item_lock); btrfs_set_root_ctransid(item, trans->transid); btrfs_set_stack_timespec_sec(>ctime, ct.tv_sec); -- 2.7.4
[PATCH 08/12] fs: ubifs: Replace CURRENT_TIME_SEC with current_time
CURRENT_TIME_SEC is not y2038 safe. current_time() will be transitioned to use 64 bit time along with vfs in a separate patch. There is no plan to transition CURRENT_TIME_SEC to use y2038 safe time interfaces. current_time() returns timestamps according to the granularities set in the inode's super_block. The granularity check to call current_fs_time() or CURRENT_TIME_SEC is not required. Use current_time() directly to update inode timestamp. Use timespec_trunc during file system creation, before the first inode is created. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- fs/ubifs/dir.c | 12 ++-- fs/ubifs/file.c | 12 ++-- fs/ubifs/ioctl.c | 2 +- fs/ubifs/misc.h | 10 -- fs/ubifs/sb.c| 14 ++ fs/ubifs/xattr.c | 6 +++--- 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 30825d88..8510d79 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -121,7 +121,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, inode_init_owner(inode, dir, mode); inode->i_mtime = inode->i_atime = inode->i_ctime = -ubifs_current_time(inode); +current_time(inode); inode->i_mapping->nrpages = 0; switch (mode & S_IFMT) { @@ -750,7 +750,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, lock_2_inodes(dir, inode); inc_nlink(inode); ihold(inode); - inode->i_ctime = ubifs_current_time(inode); + inode->i_ctime = current_time(inode); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; @@ -823,7 +823,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) } lock_2_inodes(dir, inode); - inode->i_ctime = ubifs_current_time(dir); + inode->i_ctime = current_time(dir); drop_nlink(inode); dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; @@ -927,7 +927,7 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) } lock_2_inodes(dir, inode); - inode->i_ctime = ubifs_current_time(dir); + inode->i_ctime = current_time(dir); clear_nlink(inode); drop_nlink(dir); dir->i_size -= sz_change; @@ -1405,7 +1405,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, * Like most other Unix systems, set the @i_ctime for inodes on a * rename. */ - time = ubifs_current_time(old_dir); + time = current_time(old_dir); old_inode->i_ctime = time; /* We must adjust parent link count when renaming directories */ @@ -1578,7 +1578,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry, lock_4_inodes(old_dir, new_dir, NULL, NULL); - time = ubifs_current_time(old_dir); + time = current_time(old_dir); fst_inode->i_ctime = time; snd_inode->i_ctime = time; old_dir->i_mtime = old_dir->i_ctime = time; diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index d9ae86f..2cda3d6 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1196,7 +1196,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, mutex_lock(>ui_mutex); ui->ui_size = inode->i_size; /* Truncation changes inode [mc]time */ - inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); /* Other attributes may be changed at the same time as well */ do_attr_changes(inode, attr); err = ubifs_jnl_truncate(c, inode, old_size, new_size); @@ -1243,7 +1243,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode, mutex_lock(>ui_mutex); if (attr->ia_valid & ATTR_SIZE) { /* Truncation changes inode [mc]time */ - inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); /* 'truncate_setsize()' changed @i_size, update @ui_size */ ui->ui_size = inode->i_size; } @@ -1420,7 +1420,7 @@ int ubifs_update_time(struct inode *inode, struct timespec *time, */ static int update_mctime(struct inode *inode) { - struct timespec now = ubifs_current_time(inode); + struct timespec now = current_time(inode); struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_info *c = inode->i_sb->s_fs_info; @@ -1434,7 +1434,7 @@ static int update_mctime(struct inode *inode) return err; mutex_lock(>ui_mutex); - inode->i_mti
[PATCH 12/12] time: Delete current_fs_time() function
All uses of the current_fs_time() function have been replaced by other time interfaces. And, its use cases can be fulfilled by current_time() or ktime_get_* variants. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- include/linux/fs.h | 1 - kernel/time/time.c | 14 -- 2 files changed, 15 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index f1d7347..cce6c57 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1430,7 +1430,6 @@ static inline void i_gid_write(struct inode *inode, gid_t gid) inode->i_gid = make_kgid(inode->i_sb->s_user_ns, gid); } -extern struct timespec current_fs_time(struct super_block *sb); extern struct timespec current_time(struct inode *inode); /* diff --git a/kernel/time/time.c b/kernel/time/time.c index 25bdd25..cf69cca 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -230,20 +230,6 @@ SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p) return copy_to_user(txc_p, , sizeof(struct timex)) ? -EFAULT : ret; } -/** - * current_fs_time - Return FS time - * @sb: Superblock. - * - * Return the current time truncated to the time granularity supported by - * the fs. - */ -struct timespec current_fs_time(struct super_block *sb) -{ - struct timespec now = current_kernel_time(); - return timespec_trunc(now, sb->s_time_gran); -} -EXPORT_SYMBOL(current_fs_time); - /* * Convert jiffies to milliseconds and back. * -- 2.7.4
[PATCH 03/12] fs: cifs: Replace CURRENT_TIME by other appropriate apis
CURRENT_TIME macro is not y2038 safe on 32 bit systems. The patch replaces all the uses of CURRENT_TIME by current_time() for filesystem times, and ktime_get_* functions for authentication timestamps and timezone calculations. This is also in preparation for the patch that transitions vfs timestamps to use 64 bit time and hence make them y2038 safe. CURRENT_TIME macro will be deleted before merging the aforementioned change. The inode timestamps read from the server are assumed to have correct granularity and range. The patch also assumes that the difference between server and client times lie in the range INT_MIN..INT_MAX. This is valid because this is the difference between current times between server and client, and the largest timezone difference is in the range of one day. All cifs timestamps currently use timespec representation internally. Authentication and timezone timestamps can also be transitioned into using timespec64 when all other timestamps for cifs is transitioned to use timespec64. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- fs/cifs/cifsencrypt.c | 4 +++- fs/cifs/cifssmb.c | 10 +- fs/cifs/inode.c | 28 +++- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 058ac9b..68abbb0 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -478,6 +478,7 @@ find_timestamp(struct cifs_ses *ses) unsigned char *blobptr; unsigned char *blobend; struct ntlmssp2_name *attrptr; + struct timespec ts; if (!ses->auth_key.len || !ses->auth_key.response) return 0; @@ -502,7 +503,8 @@ find_timestamp(struct cifs_ses *ses) blobptr += attrsize; /* advance attr value */ } - return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + ktime_get_real_ts(); + return cpu_to_le64(cifs_UnixTimeToNT(ts)); } static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0669506..2f279b7 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -478,14 +478,14 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) * this requirement. */ int val, seconds, remain, result; - struct timespec ts, utc; - utc = CURRENT_TIME; + struct timespec ts; + unsigned long utc = ktime_get_real_seconds(); ts = cnvrtDosUnixTm(rsp->SrvTime.Date, rsp->SrvTime.Time, 0); cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n", -(int)ts.tv_sec, (int)utc.tv_sec, -(int)(utc.tv_sec - ts.tv_sec)); - val = (int)(utc.tv_sec - ts.tv_sec); +(int)ts.tv_sec, (int)utc, +(int)(utc - ts.tv_sec)); + val = (int)(utc - ts.tv_sec); seconds = abs(val); result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; remain = seconds % MIN_TZ_ADJ; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b261db3..c3b2fa0 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -322,9 +322,9 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; fattr->cf_uid = cifs_sb->mnt_uid; fattr->cf_gid = cifs_sb->mnt_gid; - fattr->cf_atime = CURRENT_TIME; - fattr->cf_ctime = CURRENT_TIME; - fattr->cf_mtime = CURRENT_TIME; + ktime_get_real_ts(>cf_mtime); + fattr->cf_mtime = timespec_trunc(fattr->cf_mtime, sb->s_time_gran); + fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime; fattr->cf_nlink = 2; fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; } @@ -586,9 +586,10 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ static void cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, - struct cifs_sb_info *cifs_sb, bool adjust_tz, + struct super_block *sb, bool adjust_tz, bool symlink) { + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); memset(fattr, 0, sizeof(*fattr)); @@ -598,8 +599,10 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, if (info->LastAccessTime) fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); - else - fattr->cf_atime = CURRENT_TIME; + else { + ktime_get_real_ts(>cf_atime); + fatt
[PATCH 06/12] audit: Use timespec64 to represent audit timestamps
struct timespec is not y2038 safe. Audit timestamps are recorded in string format into an audit buffer for a given context. These mark the entry timestamps for the syscalls. Use y2038 safe struct timespec64 to represent the times. The log strings can handle this transition as strings can hold upto 1024 characters. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> Acked-by: Paul Moore <p...@paul-moore.com> Acked-by: Richard Guy Briggs <r...@redhat.com> --- include/linux/audit.h | 4 ++-- kernel/audit.c| 10 +- kernel/audit.h| 2 +- kernel/auditsc.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 6fdfefc..f830508 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -332,7 +332,7 @@ static inline void audit_ptrace(struct task_struct *t) /* Private API (for audit.c only) */ extern unsigned int audit_serial(void); extern int auditsc_get_stamp(struct audit_context *ctx, - struct timespec *t, unsigned int *serial); + struct timespec64 *t, unsigned int *serial); extern int audit_set_loginuid(kuid_t loginuid); static inline kuid_t audit_get_loginuid(struct task_struct *tsk) @@ -511,7 +511,7 @@ static inline void __audit_seccomp(unsigned long syscall, long signr, int code) static inline void audit_seccomp(unsigned long syscall, long signr, int code) { } static inline int auditsc_get_stamp(struct audit_context *ctx, - struct timespec *t, unsigned int *serial) + struct timespec64 *t, unsigned int *serial) { return 0; } diff --git a/kernel/audit.c b/kernel/audit.c index 2f4964c..fcbf377 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1625,10 +1625,10 @@ unsigned int audit_serial(void) } static inline void audit_get_stamp(struct audit_context *ctx, - struct timespec *t, unsigned int *serial) + struct timespec64 *t, unsigned int *serial) { if (!ctx || !auditsc_get_stamp(ctx, t, serial)) { - *t = CURRENT_TIME; + ktime_get_real_ts64(t); *serial = audit_serial(); } } @@ -1652,7 +1652,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) { struct audit_buffer *ab; - struct timespec t; + struct timespec64 t; unsigned int uninitialized_var(serial); if (audit_initialized != AUDIT_INITIALIZED) @@ -1705,8 +1705,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, } audit_get_stamp(ab->ctx, , ); - audit_log_format(ab, "audit(%lu.%03lu:%u): ", -t.tv_sec, t.tv_nsec/100, serial); + audit_log_format(ab, "audit(%llu.%03lu:%u): ", +(unsigned long long)t.tv_sec, t.tv_nsec/100, serial); return ab; } diff --git a/kernel/audit.h b/kernel/audit.h index 0f1cf6d..cdf96f4 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -112,7 +112,7 @@ struct audit_context { enum audit_statestate, current_state; unsigned intserial; /* serial number for record */ int major; /* syscall number */ - struct timespec ctime; /* time of syscall entry */ + struct timespec64 ctime; /* time of syscall entry */ unsigned long argv[4];/* syscall arguments */ longreturn_code;/* syscall return code */ u64 prio; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e59ffc7..a2d9217 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1532,7 +1532,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, return; context->serial = 0; - context->ctime = CURRENT_TIME; + ktime_get_real_ts64(>ctime); context->in_syscall = 1; context->current_state = state; context->ppid = 0; @@ -1941,13 +1941,13 @@ EXPORT_SYMBOL_GPL(__audit_inode_child); /** * auditsc_get_stamp - get local copies of audit_context values * @ctx: audit_context for the task - * @t: timespec to store time recorded in the audit_context + * @t: timespec64 to store time recorded in the audit_context * @serial: serial value that is recorded in the audit_context * * Also sets the context as auditable. */ int auditsc_get_stamp(struct audit_context *ctx, - struct timespec *t, unsigned int *serial) + struct timespec64 *t, unsigned int *serial) { if (!ctx->in_syscall) return 0; -- 2.7.4
[PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
CURRENT_TIME is not y2038 safe. The macro will be deleted and all the references to it will be replaced by ktime_get_* apis. struct timespec is also not y2038 safe. Retain timespec for timestamp representation here as ceph uses it internally everywhere. These references will be changed to use struct timespec64 in a separate patch. The current_fs_time() api is being changed to use vfs struct inode* as an argument instead of struct super_block*. Set the new mds client request r_stamp field using ktime_get_real_ts() instead of using current_fs_time(). Also, since r_stamp is used as mtime on the server, use timespec_trunc() to truncate the timestamp, using the right granularity from the superblock. This api will be transitioned to be y2038 safe along with vfs. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- drivers/block/rbd.c | 2 +- fs/ceph/mds_client.c | 4 +++- net/ceph/messenger.c | 6 -- net/ceph/osd_client.c | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 517838b..77204da 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request) { struct ceph_osd_request *osd_req = obj_request->osd_req; - osd_req->r_mtime = CURRENT_TIME; + ktime_get_real_ts(_req->r_mtime); osd_req->r_data_offset = obj_request->offset; } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index c681762..1d3fa90 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1666,6 +1666,7 @@ struct ceph_mds_request * ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode) { struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS); + struct timespec ts; if (!req) return ERR_PTR(-ENOMEM); @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode) init_completion(>r_safe_completion); INIT_LIST_HEAD(>r_unsafe_item); - req->r_stamp = current_fs_time(mdsc->fsc->sb); + ktime_get_real_ts(); + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran); req->r_op = op; req->r_direct_mode = mode; diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f76bb33..5766a6c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1386,8 +1386,9 @@ static void prepare_write_keepalive(struct ceph_connection *con) dout("prepare_write_keepalive %p\n", con); con_out_kvec_reset(con); if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) { - struct timespec now = CURRENT_TIME; + struct timespec now; + ktime_get_real_ts(); con_out_kvec_add(con, sizeof(tag_keepalive2), _keepalive2); ceph_encode_timespec(>out_temp_keepalive2, ); con_out_kvec_add(con, sizeof(con->out_temp_keepalive2), @@ -3176,8 +3177,9 @@ bool ceph_con_keepalive_expired(struct ceph_connection *con, { if (interval > 0 && (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) { - struct timespec now = CURRENT_TIME; + struct timespec now; struct timespec ts; + ktime_get_real_ts(); jiffies_to_timespec(interval, ); ts = timespec_add(con->last_keepalive_ack, ts); return timespec_compare(, ) >= 0; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index e15ea9e..242d7c0 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -3574,7 +3574,7 @@ ceph_osdc_watch(struct ceph_osd_client *osdc, ceph_oid_copy(>t.base_oid, oid); ceph_oloc_copy(>t.base_oloc, oloc); lreq->t.flags = CEPH_OSD_FLAG_WRITE; - lreq->mtime = CURRENT_TIME; + ktime_get_real_ts(>mtime); lreq->reg_req = alloc_linger_request(lreq); if (!lreq->reg_req) { @@ -3632,7 +3632,7 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc, ceph_oid_copy(>r_base_oid, >t.base_oid); ceph_oloc_copy(>r_base_oloc, >t.base_oloc); req->r_flags = CEPH_OSD_FLAG_WRITE; - req->r_mtime = CURRENT_TIME; + ktime_get_real_ts(>r_mtime); osd_req_op_watch_init(req, 0, lreq->linger_id, CEPH_OSD_WATCH_OP_UNWATCH); -- 2.7.4
[PATCH 01/12] fs: f2fs: Use ktime_get_real_seconds for sit_info times
CURRENT_TIME_SEC is not y2038 safe. Replace use of CURRENT_TIME_SEC with ktime_get_real_seconds in segment timestamps used by GC algorithm including the segment mtime timestamps. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> --- fs/f2fs/segment.c | 2 +- fs/f2fs/segment.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 010324c..0531500 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2678,7 +2678,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi) sit_i->dirty_sentries = 0; sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time); - sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec; + sit_i->mounted_time = ktime_get_real_seconds(); mutex_init(_i->sentry_lock); return 0; } diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 57e36c1..156afc3 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -692,8 +692,9 @@ static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start) static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi) { struct sit_info *sit_i = SIT_I(sbi); - return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec - - sit_i->mounted_time; + time64_t now = ktime_get_real_seconds(); + + return sit_i->elapsed_time + now - sit_i->mounted_time; } static inline void set_summary(struct f2fs_summary *sum, nid_t nid, -- 2.7.4
[PATCH 00/12] Delete CURRENT_TIME, CURRENT_TIME_SEC and current_fs_time
The series contains the last unmerged uses of CURRENT_TIME, CURRENT_TIME_SEC, and current_fs_time(). The series also deletes these apis. All the patches except [PATCH 9/12] and [PATCH 10/12] are resend patches. These patches fix new instances of CURRENT_TIME. cifs and ceph patches have been squashed so that we have one patch per filesystem. We want to get these merged onto 4.12 release so that I can post the series that changes vfs timestamps to use 64 bits for 4.13 release. I'm proposing these to be merged through Andrew's tree. Filesystem maintainers, please let Andrew know if you will be picking up the patch in your trees. Let me know if anybody has other preferences for merging. Deepa Dinamani (12): fs: f2fs: Use ktime_get_real_seconds for sit_info times trace: Make trace_hwlat timestamp y2038 safe fs: cifs: Replace CURRENT_TIME by other appropriate apis fs: ceph: CURRENT_TIME with ktime_get_real_ts() fs: ufs: Use ktime_get_real_ts64() for birthtime audit: Use timespec64 to represent audit timestamps fs: btrfs: Use ktime_get_real_ts for root ctime fs: ubifs: Replace CURRENT_TIME_SEC with current_time lustre: Replace CURRENT_TIME macro apparmorfs: Replace CURRENT_TIME with current_time() time: Delete CURRENT_TIME_SEC and CURRENT_TIME time: Delete current_fs_time() function drivers/block/rbd.c | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 6 +++--- drivers/staging/lustre/lustre/osc/osc_io.c | 4 ++-- fs/btrfs/root-tree.c| 3 ++- fs/ceph/mds_client.c| 4 +++- fs/cifs/cifsencrypt.c | 4 +++- fs/cifs/cifssmb.c | 10 - fs/cifs/inode.c | 28 + fs/f2fs/segment.c | 2 +- fs/f2fs/segment.h | 5 +++-- fs/ubifs/dir.c | 12 +-- fs/ubifs/file.c | 12 +-- fs/ubifs/ioctl.c| 2 +- fs/ubifs/misc.h | 10 - fs/ubifs/sb.c | 14 + fs/ubifs/xattr.c| 6 +++--- fs/ufs/ialloc.c | 6 -- include/linux/audit.h | 4 ++-- include/linux/fs.h | 1 - include/linux/time.h| 3 --- kernel/audit.c | 10 - kernel/audit.h | 2 +- kernel/auditsc.c| 6 +++--- kernel/time/time.c | 14 - kernel/trace/trace_entries.h| 6 +++--- kernel/trace/trace_hwlat.c | 14 ++--- kernel/trace/trace_output.c | 9 net/ceph/messenger.c| 6 -- net/ceph/osd_client.c | 4 ++-- security/apparmor/apparmorfs.c | 2 +- 30 files changed, 100 insertions(+), 111 deletions(-) -- 2.7.4
[PATCH v2 0/7] Change k_clock interfaces to use timespec64
The series is aimed at replacing struct timespec which is not y2038 safe with y2038 safe struct timespec64 for k_clock interfaces. The series also replaces struct itimerspec which uses struct timespec internally with struct itimerspec64 for the k_clock interfaces. The series does not change the syscall interface. This will be done in a follow up series. A few existing checkpatch-noted style issues, such as the 80 line character limit, have been left as-is to facilitate easier review. Changes since v1: * Address review comments for change logs and coding style. * Fix kbuild test error for alpha. Deepa Dinamani (7): time: Delete do_sys_setimeofday() time: Change posix clocks ops interfaces to use timespec64 Change k_clock clock_get() to use timespec64 Change k_clock clock_getres() to use timespec64 Change k_clock clock_set() to use timespec64 Change k_clock timer_set() and timer_get() to use timespec64 Change k_clock nsleep() to use timespec64 arch/alpha/kernel/osf_sys.c| 4 +- drivers/char/mmtimer.c | 28 ++--- drivers/ptp/ptp_clock.c| 18 include/linux/hrtimer.h| 2 +- include/linux/posix-clock.h| 10 ++--- include/linux/posix-timers.h | 20 - include/linux/timekeeping.h| 20 +++-- kernel/compat.c| 10 +++-- kernel/time/alarmtimer.c | 24 +-- kernel/time/hrtimer.c | 10 +++-- kernel/time/posix-clock.c | 10 ++--- kernel/time/posix-cpu-timers.c | 66 +++-- kernel/time/posix-stubs.c | 20 ++--- kernel/time/posix-timers.c | 95 -- kernel/time/time.c | 4 +- 15 files changed, 179 insertions(+), 162 deletions(-) -- 2.7.4 Cc: Richard Cochran <richardcoch...@gmail.com> Cc: linux-al...@vger.kernel.org Cc: netdev@vger.kernel.org
[PATCH v2 2/7] time: Change posix clocks ops interfaces to use timespec64
struct timespec is not y2038 safe on 32 bit machines. The posix clocks apis use struct timespec directly and through struct itimerspec. Replace the posix clock interfaces to use struct timespec64 and struct itimerspec64 instead. Also fix up their implementations accordingly. Note that the clock_getres() interface has also been changed to use timespec64 even though this particular interface is not affected by the y2038 problem. This helps verification for internal kernel code for y2038 readiness by getting rid of time_t/ timeval/ timespec. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: Richard Cochran <richardcoch...@gmail.com> Cc: netdev@vger.kernel.org --- drivers/ptp/ptp_clock.c | 18 +++--- include/linux/posix-clock.h | 10 +- kernel/time/posix-clock.c | 34 -- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index e814280..b774357 100644 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@ -97,30 +97,26 @@ static s32 scaled_ppm_to_ppb(long ppm) /* posix clock implementation */ -static int ptp_clock_getres(struct posix_clock *pc, struct timespec *tp) +static int ptp_clock_getres(struct posix_clock *pc, struct timespec64 *tp) { tp->tv_sec = 0; tp->tv_nsec = 1; return 0; } -static int ptp_clock_settime(struct posix_clock *pc, const struct timespec *tp) +static int ptp_clock_settime(struct posix_clock *pc, const struct timespec64 *tp) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); - struct timespec64 ts = timespec_to_timespec64(*tp); - return ptp->info->settime64(ptp->info, ); + return ptp->info->settime64(ptp->info, tp); } -static int ptp_clock_gettime(struct posix_clock *pc, struct timespec *tp) +static int ptp_clock_gettime(struct posix_clock *pc, struct timespec64 *tp) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); - struct timespec64 ts; int err; - err = ptp->info->gettime64(ptp->info, ); - if (!err) - *tp = timespec64_to_timespec(ts); + err = ptp->info->gettime64(ptp->info, tp); return err; } @@ -133,7 +129,7 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx) ops = ptp->info; if (tx->modes & ADJ_SETOFFSET) { - struct timespec ts; + struct timespec64 ts; ktime_t kt; s64 delta; @@ -146,7 +142,7 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx) if ((unsigned long) ts.tv_nsec >= NSEC_PER_SEC) return -EINVAL; - kt = timespec_to_ktime(ts); + kt = timespec64_to_ktime(ts); delta = ktime_to_ns(kt); err = ops->adjtime(ops, delta); } else if (tx->modes & ADJ_FREQUENCY) { diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h index 34c4498..83b22ae 100644 --- a/include/linux/posix-clock.h +++ b/include/linux/posix-clock.h @@ -59,23 +59,23 @@ struct posix_clock_operations { int (*clock_adjtime)(struct posix_clock *pc, struct timex *tx); - int (*clock_gettime)(struct posix_clock *pc, struct timespec *ts); + int (*clock_gettime)(struct posix_clock *pc, struct timespec64 *ts); - int (*clock_getres) (struct posix_clock *pc, struct timespec *ts); + int (*clock_getres) (struct posix_clock *pc, struct timespec64 *ts); int (*clock_settime)(struct posix_clock *pc, - const struct timespec *ts); + const struct timespec64 *ts); int (*timer_create) (struct posix_clock *pc, struct k_itimer *kit); int (*timer_delete) (struct posix_clock *pc, struct k_itimer *kit); void (*timer_gettime)(struct posix_clock *pc, - struct k_itimer *kit, struct itimerspec *tsp); + struct k_itimer *kit, struct itimerspec64 *tsp); int (*timer_settime)(struct posix_clock *pc, struct k_itimer *kit, int flags, - struct itimerspec *tsp, struct itimerspec *old); + struct itimerspec64 *tsp, struct itimerspec64 *old); /* * Optional character device methods: */ diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index 9cff0ab..e24008c 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -300,14 +300,17 @@ static int pc_clock_adjtime(clockid_t id, struct timex *tx) static int pc_clock_gettime(clockid_t id, struct timespec *ts) { struct posix_clock_desc cd; + struct timespec64 ts64; int err; err = get_clock_
[PATCH 00/21] Delete CURRENT_TIME and CURRENT_TIME_SEC macros
The series is aimed at getting rid of CURRENT_TIME and CURRENT_TIME_SEC macros. The macros are not y2038 safe. There is no plan to transition them into being y2038 safe. ktime_get_* api's can be used in their place. And, these are y2038 safe. All filesystem timestamps use current_fs_time() for the right granularity as mentioned in the respective commit texts of patches. This series also serves as a preparatory series to transition vfs to 64 bit timestamps as outlined here: https://lkml.org/lkml/2016/2/12/104 . As per Linus's suggestion in https://lkml.org/lkml/2016/5/24/663 , all the inode timestamp changes have been squashed into a single patch. Also, current_fs_time() now is used as a single generic filesystem timestamp api. Posting all patches together in a bigger series so that the big picture is clear. As per the suggestion in https://lwn.net/Articles/672598/ , CURRENT_TIME macro bug fixes are being handled in a series separate from transitioning vfs to use 64 bit timestamps. Some reviewers have requested not to change line wrapping only for the longer function call names, so checkpatch warnings for such cases are ignored in the patch series. Deepa Dinamani (21): fs: Replace CURRENT_TIME_SEC with current_fs_time() fs: ext4: Use current_fs_time() for inode timestamps fs: ubifs: Use current_fs_time() for inode timestamps fs: Replace CURRENT_TIME with current_fs_time() for inode timestamps fs: jfs: Replace CURRENT_TIME_SEC by current_fs_time() fs: udf: Replace CURRENT_TIME with current_fs_time() fs: cifs: Replace CURRENT_TIME by current_fs_time() fs: cifs: Replace CURRENT_TIME with ktime_get_real_ts() fs: cifs: Replace CURRENT_TIME by get_seconds fs: f2fs: Use ktime_get_real_seconds for sit_info times drivers: staging: lustre: Replace CURRENT_TIME with current_fs_time() block: rbd: Replace non inode CURRENT_TIME with current_fs_time() fs: ocfs2: Use time64_t to represent orphan scan times fs: ocfs2: Replace CURRENT_TIME with ktime_get_real_seconds() time: Add time64_to_tm() fnic: Use time64_t to represent trace timestamps audit: Use timespec64 to represent audit timestamps fs: nfs: Make nfs boot time y2038 safe libceph: Remove CURRENT_TIME references libceph: Replace CURRENT_TIME with ktime_get_real_ts time: Delete CURRENT_TIME_SEC and CURRENT_TIME macro arch/powerpc/platforms/cell/spufs/inode.c | 2 +- arch/s390/hypfs/inode.c| 4 +-- drivers/block/rbd.c| 2 +- drivers/infiniband/hw/qib/qib_fs.c | 2 +- drivers/misc/ibmasm/ibmasmfs.c | 2 +- drivers/oprofile/oprofilefs.c | 2 +- drivers/scsi/fnic/fnic_trace.c | 4 +-- drivers/scsi/fnic/fnic_trace.h | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c| 17 ++- drivers/staging/lustre/lustre/llite/namei.c| 4 +-- drivers/staging/lustre/lustre/mdc/mdc_reint.c | 6 ++-- .../lustre/lustre/obdclass/linux/linux-obdo.c | 6 ++-- drivers/staging/lustre/lustre/obdclass/obdo.c | 6 ++-- drivers/staging/lustre/lustre/osc/osc_io.c | 2 +- drivers/usb/core/devio.c | 19 ++-- drivers/usb/gadget/function/f_fs.c | 2 +- drivers/usb/gadget/legacy/inode.c | 2 +- fs/9p/vfs_inode.c | 2 +- fs/adfs/inode.c| 2 +- fs/affs/amigaffs.c | 6 ++-- fs/affs/inode.c| 2 +- fs/afs/inode.c | 3 +- fs/autofs4/inode.c | 2 +- fs/autofs4/root.c | 19 +++- fs/bfs/dir.c | 18 ++- fs/btrfs/inode.c | 2 +- fs/cifs/cifsencrypt.c | 4 ++- fs/cifs/cifssmb.c | 10 +++ fs/cifs/inode.c| 15 +- fs/coda/dir.c | 2 +- fs/coda/file.c | 2 +- fs/coda/inode.c| 2 +- fs/devpts/inode.c | 6 ++-- fs/efivarfs/inode.c| 2 +- fs/exofs/dir.c | 9 +++--- fs/exofs/inode.c | 7 +++-- fs/exofs/namei.c | 6 ++-- fs/ext2/acl.c | 2 +- fs/ext2/dir.c | 6 ++-- fs/ext2/ialloc.c | 2 +- fs/ext2/inode.c| 4 +-- fs/ext2/ioctl.c| 5 ++-- fs/ext2/namei.c
[RESEND PATCH 2/3] fs: poll/select/recvmmsg: use timespec64 for timeout events
struct timespec is not y2038 safe. Even though timespec might be sufficient to represent timeouts, use struct timespec64 here as the plan is to get rid of all timespec reference in the kernel. The patch transitions the common functions: poll_select_set_timeout() and select_estimate_accuracy() to use timespec64. And, all the syscalls that use these functions are transitioned in the same patch. The restart block parameters for poll uses monotonic time. Use timespec64 here as well to assign timeout value. This parameter in the restart block need not change because this only holds the monotonic timestamp at which timeout should occur. And, unsigned long data type should be big enough for this timestamp. The system call interfaces will be handled in a separate series. Compat interfaces need not change as timespec64 is an alias to struct timespec on a 64 bit system. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: Alexander Viro <v...@zeniv.linux.org.uk> Cc: "David S. Miller" <da...@davemloft.net> Cc: netdev@vger.kernel.org --- Resending to include John and Thomas on this patch as well. This is to include this patch also in John's tree. This will let all 3 patches in the series to merged through the same tree. fs/eventpoll.c | 12 +- fs/select.c | 67 +--- include/linux/poll.h | 11 + net/socket.c | 8 --- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 8a74a2a..10db912 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1583,15 +1583,15 @@ static int ep_send_events(struct eventpoll *ep, return ep_scan_ready_list(ep, ep_send_events_proc, , 0, false); } -static inline struct timespec ep_set_mstimeout(long ms) +static inline struct timespec64 ep_set_mstimeout(long ms) { - struct timespec now, ts = { + struct timespec64 now, ts = { .tv_sec = ms / MSEC_PER_SEC, .tv_nsec = NSEC_PER_MSEC * (ms % MSEC_PER_SEC), }; - ktime_get_ts(); - return timespec_add_safe(now, ts); + ktime_get_ts64(); + return timespec64_add_safe(now, ts); } /** @@ -1621,11 +1621,11 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, ktime_t expires, *to = NULL; if (timeout > 0) { - struct timespec end_time = ep_set_mstimeout(timeout); + struct timespec64 end_time = ep_set_mstimeout(timeout); slack = select_estimate_accuracy(_time); to = - *to = timespec_to_ktime(end_time); + *to = timespec64_to_ktime(end_time); } else if (timeout == 0) { /* * Avoid the unnecessary trip to the wait queue loop, if the diff --git a/fs/select.c b/fs/select.c index 8692939..8ed9da5 100644 --- a/fs/select.c +++ b/fs/select.c @@ -47,7 +47,7 @@ #define MAX_SLACK (100 * NSEC_PER_MSEC) -static long __estimate_accuracy(struct timespec *tv) +static long __estimate_accuracy(struct timespec64 *tv) { long slack; int divfactor = 1000; @@ -70,10 +70,10 @@ static long __estimate_accuracy(struct timespec *tv) return slack; } -u64 select_estimate_accuracy(struct timespec *tv) +u64 select_estimate_accuracy(struct timespec64 *tv) { u64 ret; - struct timespec now; + struct timespec64 now; /* * Realtime tasks get a slack of 0 for obvious reasons. @@ -82,8 +82,8 @@ u64 select_estimate_accuracy(struct timespec *tv) if (rt_task(current)) return 0; - ktime_get_ts(); - now = timespec_sub(*tv, now); + ktime_get_ts64(); + now = timespec64_sub(*tv, now); ret = __estimate_accuracy(); if (ret < current->timer_slack_ns) return current->timer_slack_ns; @@ -260,7 +260,7 @@ EXPORT_SYMBOL(poll_schedule_timeout); /** * poll_select_set_timeout - helper function to setup the timeout value - * @to:pointer to timespec variable for the final timeout + * @to:pointer to timespec64 variable for the final timeout * @sec: seconds (from user space) * @nsec: nanoseconds (from user space) * @@ -269,26 +269,28 @@ EXPORT_SYMBOL(poll_schedule_timeout); * * Returns -EINVAL if sec/nsec are not normalized. Otherwise 0. */ -int poll_select_set_timeout(struct timespec *to, long sec, long nsec) +int poll_select_set_timeout(struct timespec64 *to, time64_t sec, long nsec) { - struct timespec ts = {.tv_sec = sec, .tv_nsec = nsec}; + struct timespec64 ts = {.tv_sec = sec, .tv_nsec = nsec}; - if (!timespec_valid()) + if (!timespec64_valid()) return -EINVAL; /* Optimize for the zero timeout value here */ if (!sec && !nsec) { to->tv_sec = to->tv_n
[PATCH 2/3] fs: poll/select/recvmmsg: use timespec64 for timeout events
struct timespec is not y2038 safe. Even though timespec might be sufficient to represent timeouts, use struct timespec64 here as the plan is to get rid of all timespec reference in the kernel. The patch transitions the common functions: poll_select_set_timeout() and select_estimate_accuracy() to use timespec64. And, all the syscalls that use these functions are transitioned in the same patch. The restart block parameters for poll uses monotonic time. Use timespec64 here as well to assign timeout value. This parameter in the restart block need not change because this only holds the monotonic timestamp at which timeout should occur. And, unsigned long data type should be big enough for this timestamp. The system call interfaces will be handled in a separate series. Compat interfaces need not change as timespec64 is an alias to struct timespec on a 64 bit system. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: Alexander Viro <v...@zeniv.linux.org.uk> Cc: "David S. Miller" <da...@davemloft.net> Cc: netdev@vger.kernel.org --- fs/eventpoll.c | 12 +- fs/select.c | 67 +--- include/linux/poll.h | 11 + net/socket.c | 8 --- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 8a74a2a..10db912 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1583,15 +1583,15 @@ static int ep_send_events(struct eventpoll *ep, return ep_scan_ready_list(ep, ep_send_events_proc, , 0, false); } -static inline struct timespec ep_set_mstimeout(long ms) +static inline struct timespec64 ep_set_mstimeout(long ms) { - struct timespec now, ts = { + struct timespec64 now, ts = { .tv_sec = ms / MSEC_PER_SEC, .tv_nsec = NSEC_PER_MSEC * (ms % MSEC_PER_SEC), }; - ktime_get_ts(); - return timespec_add_safe(now, ts); + ktime_get_ts64(); + return timespec64_add_safe(now, ts); } /** @@ -1621,11 +1621,11 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, ktime_t expires, *to = NULL; if (timeout > 0) { - struct timespec end_time = ep_set_mstimeout(timeout); + struct timespec64 end_time = ep_set_mstimeout(timeout); slack = select_estimate_accuracy(_time); to = - *to = timespec_to_ktime(end_time); + *to = timespec64_to_ktime(end_time); } else if (timeout == 0) { /* * Avoid the unnecessary trip to the wait queue loop, if the diff --git a/fs/select.c b/fs/select.c index 8692939..8ed9da5 100644 --- a/fs/select.c +++ b/fs/select.c @@ -47,7 +47,7 @@ #define MAX_SLACK (100 * NSEC_PER_MSEC) -static long __estimate_accuracy(struct timespec *tv) +static long __estimate_accuracy(struct timespec64 *tv) { long slack; int divfactor = 1000; @@ -70,10 +70,10 @@ static long __estimate_accuracy(struct timespec *tv) return slack; } -u64 select_estimate_accuracy(struct timespec *tv) +u64 select_estimate_accuracy(struct timespec64 *tv) { u64 ret; - struct timespec now; + struct timespec64 now; /* * Realtime tasks get a slack of 0 for obvious reasons. @@ -82,8 +82,8 @@ u64 select_estimate_accuracy(struct timespec *tv) if (rt_task(current)) return 0; - ktime_get_ts(); - now = timespec_sub(*tv, now); + ktime_get_ts64(); + now = timespec64_sub(*tv, now); ret = __estimate_accuracy(); if (ret < current->timer_slack_ns) return current->timer_slack_ns; @@ -260,7 +260,7 @@ EXPORT_SYMBOL(poll_schedule_timeout); /** * poll_select_set_timeout - helper function to setup the timeout value - * @to:pointer to timespec variable for the final timeout + * @to:pointer to timespec64 variable for the final timeout * @sec: seconds (from user space) * @nsec: nanoseconds (from user space) * @@ -269,26 +269,28 @@ EXPORT_SYMBOL(poll_schedule_timeout); * * Returns -EINVAL if sec/nsec are not normalized. Otherwise 0. */ -int poll_select_set_timeout(struct timespec *to, long sec, long nsec) +int poll_select_set_timeout(struct timespec64 *to, time64_t sec, long nsec) { - struct timespec ts = {.tv_sec = sec, .tv_nsec = nsec}; + struct timespec64 ts = {.tv_sec = sec, .tv_nsec = nsec}; - if (!timespec_valid()) + if (!timespec64_valid()) return -EINVAL; /* Optimize for the zero timeout value here */ if (!sec && !nsec) { to->tv_sec = to->tv_nsec = 0; } else { - ktime_get_ts(to); - *to = timespec_add_safe(*to, ts); + ktime_get_ts64(to); + *to = timespec64_add_safe(
[PATCH 0/3] Use timespec64 for select like timeouts
The series is part of y2038 changes. This changes a few syscalls that have common functions to use struct timespec64 instead of struct timespec. This does not include changes to system call uapi interfaces. Those will be in a different series. Thanks to Arnd Bergmann for comments on the patches. Deepa Dinamani (3): time: Add missing implementation for timespec64_add_safe() fs: poll/select/recvmmsg: use timespec64 for timeout events time: Remove timespec_add_safe() fs/eventpoll.c | 12 - fs/select.c| 67 -- include/linux/poll.h | 11 + include/linux/time64.h | 17 ++--- kernel/time/time.c | 21 net/socket.c | 8 +++--- 6 files changed, 82 insertions(+), 54 deletions(-) -- 1.9.1 Cc: John Stultz <john.stu...@linaro.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: Alexander Viro <v...@zeniv.linux.org.uk> Cc: "David S. Miller" <da...@davemloft.net> Cc: netdev@vger.kernel.org
[PATCH RESEND] net: ipv4: Fix truncated timestamp returned by inet_current_timestamp()
The millisecond timestamps returned by the function is converted to network byte order by making a call to htons(). htons() only returns __be16 while __be32 is required here. This was identified by the sparse warning from the buildbot: net/ipv4/af_inet.c:1405:16: sparse: incorrect type in return expression (different base types) net/ipv4/af_inet.c:1405:16: expected restricted __be32 net/ipv4/af_inet.c:1405:16: got restricted __be16 [usertype] Change the function to use htonl() to return the correct __be32 type instead so that the millisecond value doesn't get truncated. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: James Morris <jmor...@namei.org> Cc: Patrick McHardy <ka...@trash.net> Cc: Arnd Bergmann <a...@arndb.de> Fixes: 822c868532ca ("net: ipv4: Convert IP network timestamps to be y2038 safe") Reported-by: Fengguang Wu <fengguang...@intel.com> [0-day test robot] --- Fixed the y2038 list email address. net/ipv4/af_inet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0cc923f..5fab7e3 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1402,7 +1402,7 @@ __be32 inet_current_timestamp(void) msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC; /* Convert to network byte order. */ - return htons(msecs); + return htonl(msecs); } EXPORT_SYMBOL(inet_current_timestamp); -- 1.9.1
[PATCH 1/1] net: ipv4: Fix truncated timestamp returned by inet_current_timestamp()
The millisecond timestamps returned by the function is converted to network byte order by making a call to htons(). htons() only returns __be16 while __be32 is required here. This was identified by the sparse warning from the buildbot: net/ipv4/af_inet.c:1405:16: sparse: incorrect type in return expression (different base types) net/ipv4/af_inet.c:1405:16: expected restricted __be32 net/ipv4/af_inet.c:1405:16: got restricted __be16 [usertype] Change the function to use htonl() to return the correct __be32 type instead so that the millisecond value doesn't get truncated. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: James Morris <jmor...@namei.org> Cc: Patrick McHardy <ka...@trash.net> Cc: Arnd Bergmann <a...@arndb.de> Fixes: 822c868532ca ("net: ipv4: Convert IP network timestamps to be y2038 safe") Reported-by: Fengguang Wu <fengguang...@intel.com> [0-day test robot] --- net/ipv4/af_inet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0cc923f..5fab7e3 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1402,7 +1402,7 @@ __be32 inet_current_timestamp(void) msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC; /* Convert to network byte order. */ - return htons(msecs); + return htonl(msecs); } EXPORT_SYMBOL(inet_current_timestamp); -- 1.9.1
[PATCH v2 2/3] net: ipv4: tcp_probe: Replace timespec with timespec64
TCP probe log timestamps use struct timespec which is not y2038 safe. Even though timespec might be good enough here as it is used to represent delta time, the plan is to get rid of all uses of timespec in the kernel. Replace with struct timespec64 which is y2038 safe. Prints still use unsigned long format and type. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: James Morris <jmor...@namei.org> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: Patrick McHardy <ka...@trash.net> --- net/ipv4/tcp_probe.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index ebf5ff5..f6c50af 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -187,13 +187,13 @@ static int tcpprobe_sprint(char *tbuf, int n) { const struct tcp_log *p = tcp_probe.log + tcp_probe.tail; - struct timespec tv - = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); + struct timespec64 ts + = ktime_to_timespec64(ktime_sub(p->tstamp, tcp_probe.start)); return scnprintf(tbuf, n, "%lu.%09lu %pISpc %pISpc %d %#x %#x %u %u %u %u %u\n", - (unsigned long)tv.tv_sec, - (unsigned long)tv.tv_nsec, + (unsigned long)ts.tv_sec, + (unsigned long)ts.tv_nsec, >src, >dst, p->length, p->snd_nxt, p->snd_una, p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt, p->rcv_wnd); } -- 1.9.1
[PATCH v2 3/3] net: sctp: Convert log timestamps to be y2038 safe
SCTP probe log timestamps use struct timespec which is not y2038 safe. Use struct timespec64 which is 2038 safe instead. Use monotonic time instead of real time as only time differences are logged. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Reviewed-by: Arnd Bergmann <a...@arndb.de> Acked-by: Neil Horman <nhor...@tuxdriver.com> Cc: Vlad Yasevich <vyasev...@gmail.com> Cc: Neil Horman <nhor...@tuxdriver.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: linux-s...@vger.kernel.org --- net/sctp/probe.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/sctp/probe.c b/net/sctp/probe.c index 5e68b94..6cc2152 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c @@ -65,7 +65,7 @@ static struct { struct kfifo fifo; spinlock_tlock; wait_queue_head_t wait; - struct timespec tstart; + struct timespec64 tstart; } sctpw; static __printf(1, 2) void printl(const char *fmt, ...) @@ -85,7 +85,7 @@ static __printf(1, 2) void printl(const char *fmt, ...) static int sctpprobe_open(struct inode *inode, struct file *file) { kfifo_reset(); - getnstimeofday(); + ktime_get_ts64(); return 0; } @@ -138,7 +138,7 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net, struct sk_buff *skb = chunk->skb; struct sctp_transport *sp; static __u32 lcwnd = 0; - struct timespec now; + struct timespec64 now; sp = asoc->peer.primary_path; @@ -149,8 +149,8 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net, (full || sp->cwnd != lcwnd)) { lcwnd = sp->cwnd; - getnstimeofday(); - now = timespec_sub(now, sctpw.tstart); + ktime_get_ts64(); + now = timespec64_sub(now, sctpw.tstart); printl("%lu.%06lu ", (unsigned long) now.tv_sec, (unsigned long) now.tv_nsec / NSEC_PER_USEC); -- 1.9.1
[PATCH v2 1/3] net: ipv4: Convert IP network timestamps to be y2038 safe
ICMP timestamp messages and IP source route options require timestamps to be in milliseconds modulo 24 hours from midnight UT format. Add inet_current_timestamp() function to support this. The function returns the required timestamp in network byte order. Timestamp calculation is also changed to call ktime_get_real_ts64() which uses struct timespec64. struct timespec64 is y2038 safe. Previously it called getnstimeofday() which uses struct timespec. struct timespec is not y2038 safe. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: James Morris <jmor...@namei.org> Cc: Patrick McHardy <ka...@trash.net> --- include/net/ip.h | 2 ++ net/ipv4/af_inet.c| 26 ++ net/ipv4/icmp.c | 5 + net/ipv4/ip_options.c | 14 ++ 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 1a98f1c..5d3a9eb 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -240,6 +240,8 @@ static inline int inet_is_local_reserved_port(struct net *net, int port) } #endif +__be32 inet_current_timestamp(void); + /* From inetpeer.c */ extern int inet_peer_threshold; extern int inet_peer_minttl; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index eade66d..408e2b3 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1386,6 +1386,32 @@ out: return pp; } +#define SECONDS_PER_DAY86400 + +/* inet_current_timestamp - Return IP network timestamp + * + * Return milliseconds since midnight in network byte order. + */ +__be32 inet_current_timestamp(void) +{ + u32 secs; + u32 msecs; + struct timespec64 ts; + + ktime_get_real_ts64(); + + /* Get secs since midnight. */ + (void)div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, ); + /* Convert to msecs. */ + msecs = secs * MSEC_PER_SEC; + /* Convert nsec to msec. */ + msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC; + + /* Convert to network byte order. */ + return htons(msecs); +} +EXPORT_SYMBOL(inet_current_timestamp); + int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) { if (sk->sk_family == AF_INET) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 36e2697..6333489 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -931,7 +931,6 @@ static bool icmp_echo(struct sk_buff *skb) */ static bool icmp_timestamp(struct sk_buff *skb) { - struct timespec tv; struct icmp_bxm icmp_param; /* * Too short. @@ -942,9 +941,7 @@ static bool icmp_timestamp(struct sk_buff *skb) /* * Fill in the current time as ms since midnight UT: */ - getnstimeofday(); - icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + -tv.tv_nsec / NSEC_PER_MSEC); + icmp_param.data.times[1] = inet_current_timestamp(); icmp_param.data.times[2] = icmp_param.data.times[1]; if (skb_copy_bits(skb, 0, _param.data.times[0], 4)) BUG(); diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index bd24679..4d158ff 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -58,10 +58,9 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt, if (opt->ts_needaddr) ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); if (opt->ts_needtime) { - struct timespec tv; __be32 midtime; - getnstimeofday(); - midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); + + midtime = inet_current_timestamp(); memcpy(iph+opt->ts+iph[opt->ts+2]-5, , 4); } return; @@ -415,11 +414,10 @@ int ip_options_compile(struct net *net, break; } if (timeptr) { - struct timespec tv; - u32 midtime; - getnstimeofday(); - midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC; - put_unaligned_be32(midtime, timeptr); + __be32 midtime; + + midtime = inet_current_timestamp(); + memcpy(timeptr, , 4); opt->is_changed = 1; } } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) { -- 1.9.1
[PATCH v2 0/3] Convert network timestamps to be y2038 safe
Introduction: The series is aimed at transitioning network timestamps to being y2038 safe. All patches can be reviewed and merged independently. Socket timestamps and ioctl calls will be handled separately. Thanks to Arnd Bergmann for discussing solution options with me. Solution: Data type struct timespec is not y2038 safe. Replace timespec with struct timespec64 which is y2038 safe. Changes v1 -> v2: Move and rename inet_current_time() as discussed Squash patches 1 and 2 Reword commit text for patch 2/3 Carry over review tags Deepa Dinamani (3): net: ipv4: Convert IP network timestamps to be y2038 safe net: ipv4: tcp_probe: Replace timespec with timespec64 net: sctp: Convert log timestamps to be y2038 safe include/net/ip.h | 2 ++ net/ipv4/af_inet.c| 26 ++ net/ipv4/icmp.c | 5 + net/ipv4/ip_options.c | 14 ++ net/ipv4/tcp_probe.c | 8 net/sctp/probe.c | 10 +- 6 files changed, 44 insertions(+), 21 deletions(-) -- 1.9.1 Cc: Vlad Yasevich <vyasev...@gmail.com> Cc: Neil Horman <nhor...@tuxdriver.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: James Morris <jmor...@namei.org> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: Patrick McHardy <ka...@trash.net> Cc: linux-s...@vger.kernel.org
Re: [PATCH 3/4] net: ipv4: tcp_probe: Replace timespec with timespec64
On Thu, Feb 25, 2016 at 8:31 PM, Arnd Bergmann <a...@arndb.de> wrote: > On Wednesday 24 February 2016 23:07:10 Deepa Dinamani wrote: >> TCP probe log timestamps use struct timespec which is >> not y2038 safe. Even though timespec might be good enough here >> as it is used to represent delta time, the plan is to get rid >> of all uses of timespec in the kernel. >> Replace with struct timespec64 which is y2038 safe. >> >> Prints still use unsigned long format and type. >> This is because long is 64 bit on 64 bit systems and 32 bit on >> 32 bit systems. Hence, time64_t(64 bit signed number) does not >> have a specifier that matches on both architectures. > > Actually time64_t is always 'long long', but tv_sec is time_t > (long) instead of time64_t on 64-bit architectures. > > Using a %ll format string and a cast to s64 would work as well, > but as you say above, it's not important here. You are right. A cast to u64 would work as well. I missed that the size of long long on 64 bit architectures according to all current data models is equivalent to long. I will leave the prints to be in long format. But, will reword the commit text in v2. Thanks, -Deepa
Re: [PATCH 1/4] kernel: time: Add current_nw_timestamp() for network timestamps
>> include/linux/ip.h | 2 ++ >> include/linux/time64.h | 3 +++ >> kernel/time/time.c | 26 ++ >> 3 files changed, 31 insertions(+) >> >> diff --git a/include/linux/ip.h b/include/linux/ip.h >> index 492bc65..edf923e 100644 >> --- a/include/linux/ip.h >> +++ b/include/linux/ip.h >> @@ -34,4 +34,6 @@ static inline struct iphdr *ipip_hdr(const struct sk_buff >> *skb) >> { >> return (struct iphdr *)skb_transport_header(skb); >> } >> + >> +extern __be32 current_nw_timestamp(void); >> #endif /* _LINUX_IP_H */ >> diff --git a/include/linux/time64.h b/include/linux/time64.h >> index 367d5af..5b5db3b 100644 >> --- a/include/linux/time64.h >> +++ b/include/linux/time64.h >> @@ -35,6 +35,9 @@ struct itimerspec64 { >> #define NSEC_PER_SEC 10L >> #define FSEC_PER_SEC 1000LL >> >> +#define SECONDS_PER_DAY 86400 >> +#define MSEC_PER_DAY (SECONDS_PER_DAY * MSEC_PER_SEC) >> + >> /* Located here for timespec[64]_valid_strict */ >> #define TIME64_MAX ((s64)~((u64)1 << 63)) >> #define KTIME_MAX((s64)~((u64)1 << 63)) >> diff --git a/kernel/time/time.c b/kernel/time/time.c >> index 86751c6..6df15df 100644 >> --- a/kernel/time/time.c >> +++ b/kernel/time/time.c >> @@ -245,6 +245,32 @@ struct timespec current_fs_time(struct super_block *sb) >> EXPORT_SYMBOL(current_fs_time); >> >> /* >> + * current_nw_timestamp - Return network time >> + * >> + * Return milliseconds since midnight in network byte order. >> + */ >> +__be32 current_nw_timestamp(void) >> +{ >> + u64 now; >> + u32 secs; >> + u32 msecs; >> + struct timespec64 ts; >> + >> + ktime_get_ts64(); >> + >> + /* Get secs since midnight. */ >> + now = div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, ); >> + /* Convert to msecs. */ >> + msecs = secs * MSEC_PER_SEC; >> + /* Convert nsec to msec. */ >> + msecs += (u32)ts.tv_nsec/NSEC_PER_MSEC; >> + >> + /* Convert to network byte order. */ >> + return htons(msecs); >> +} >> +EXPORT_SYMBOL(current_nw_timestamp); >> + >> +/* >> * Convert jiffies to milliseconds and back. >> * >> * Avoid unnecessary multiplications/divisions in the >> > > Since net/ipv4/* are the only users, it is enough to put > it in under net/ipv4/. time.c hosts functions that are used by individual subsystems like current_fs_time() used by filesystems (sometimes used by other subsystems also). The network timestamp function is used for both source route ip option and timestamp icmp messages. So it makes it difficult for it to be owned by a single layer. This is the reason it was chosen to include here. Another option is to include it in the lowest layer its used: af_inet.c. Is this what you were suggesting? -Deepa
[PATCH 4/4] net: sctp: Convert log timestamps to be y2038 safe
SCTP probe log timestamps use struct timespec which is not y2038 safe. Use struct timespec64 which is 2038 safe instead. Use monotonic time instead of real time as only time differences are logged. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: Vlad Yasevich <vyasev...@gmail.com> Cc: Neil Horman <nhor...@tuxdriver.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: linux-s...@vger.kernel.org --- net/sctp/probe.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/sctp/probe.c b/net/sctp/probe.c index 5e68b94..6cc2152 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c @@ -65,7 +65,7 @@ static struct { struct kfifo fifo; spinlock_tlock; wait_queue_head_t wait; - struct timespec tstart; + struct timespec64 tstart; } sctpw; static __printf(1, 2) void printl(const char *fmt, ...) @@ -85,7 +85,7 @@ static __printf(1, 2) void printl(const char *fmt, ...) static int sctpprobe_open(struct inode *inode, struct file *file) { kfifo_reset(); - getnstimeofday(); + ktime_get_ts64(); return 0; } @@ -138,7 +138,7 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net, struct sk_buff *skb = chunk->skb; struct sctp_transport *sp; static __u32 lcwnd = 0; - struct timespec now; + struct timespec64 now; sp = asoc->peer.primary_path; @@ -149,8 +149,8 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net, (full || sp->cwnd != lcwnd)) { lcwnd = sp->cwnd; - getnstimeofday(); - now = timespec_sub(now, sctpw.tstart); + ktime_get_ts64(); + now = timespec64_sub(now, sctpw.tstart); printl("%lu.%06lu ", (unsigned long) now.tv_sec, (unsigned long) now.tv_nsec / NSEC_PER_USEC); -- 1.9.1
[PATCH 2/4] net: ipv4: Use y2038 safe functions and data structures
ICMP timestamp messages and IP source route options require timestamps to be in milliseconds modulo 24 hours from midnight UT format. Timestamps are calculated from realtime by making a call to getnstimeofday() which uses struct timespec. timespec is not y2038 safe. Replace the above calls with y2038 safe current_nw_time() to obtain network timestamps which uses y2038 safe struct timespec64. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: James Morris <jmor...@namei.org> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: Patrick McHardy <ka...@trash.net> --- net/ipv4/icmp.c | 5 + net/ipv4/ip_options.c | 13 + 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 36e2697..e43dfa3 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -931,7 +931,6 @@ static bool icmp_echo(struct sk_buff *skb) */ static bool icmp_timestamp(struct sk_buff *skb) { - struct timespec tv; struct icmp_bxm icmp_param; /* * Too short. @@ -942,9 +941,7 @@ static bool icmp_timestamp(struct sk_buff *skb) /* * Fill in the current time as ms since midnight UT: */ - getnstimeofday(); - icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + -tv.tv_nsec / NSEC_PER_MSEC); + icmp_param.data.times[1] = current_nw_timestamp(); icmp_param.data.times[2] = icmp_param.data.times[1]; if (skb_copy_bits(skb, 0, _param.data.times[0], 4)) BUG(); diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index bd24679..6958e7c 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -58,10 +58,8 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt, if (opt->ts_needaddr) ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); if (opt->ts_needtime) { - struct timespec tv; __be32 midtime; - getnstimeofday(); - midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); + midtime = current_nw_timestamp(); memcpy(iph+opt->ts+iph[opt->ts+2]-5, , 4); } return; @@ -415,11 +413,10 @@ int ip_options_compile(struct net *net, break; } if (timeptr) { - struct timespec tv; - u32 midtime; - getnstimeofday(); - midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC; - put_unaligned_be32(midtime, timeptr); + __be32 midtime; + + midtime = current_nw_timestamp(); + memcpy(timeptr, , 4); opt->is_changed = 1; } } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) { -- 1.9.1
[PATCH 3/4] net: ipv4: tcp_probe: Replace timespec with timespec64
TCP probe log timestamps use struct timespec which is not y2038 safe. Even though timespec might be good enough here as it is used to represent delta time, the plan is to get rid of all uses of timespec in the kernel. Replace with struct timespec64 which is y2038 safe. Prints still use unsigned long format and type. This is because long is 64 bit on 64 bit systems and 32 bit on 32 bit systems. Hence, time64_t(64 bit signed number) does not have a specifier that matches on both architectures. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: James Morris <jmor...@namei.org> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: Patrick McHardy <ka...@trash.net> --- net/ipv4/tcp_probe.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index ebf5ff5..f6c50af 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -187,13 +187,13 @@ static int tcpprobe_sprint(char *tbuf, int n) { const struct tcp_log *p = tcp_probe.log + tcp_probe.tail; - struct timespec tv - = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); + struct timespec64 ts + = ktime_to_timespec64(ktime_sub(p->tstamp, tcp_probe.start)); return scnprintf(tbuf, n, "%lu.%09lu %pISpc %pISpc %d %#x %#x %u %u %u %u %u\n", - (unsigned long)tv.tv_sec, - (unsigned long)tv.tv_nsec, + (unsigned long)ts.tv_sec, + (unsigned long)ts.tv_nsec, >src, >dst, p->length, p->snd_nxt, p->snd_una, p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt, p->rcv_wnd); } -- 1.9.1
[PATCH 1/4] kernel: time: Add current_nw_timestamp() for network timestamps
ICMP timestamp messages and IP source route options require timestamps to be in milliseconds modulo 24 hours from midnight UTC format. Add a time function to support this. The function returns the required timestamp in network byte order. The function also uses y2038 safe time functions and data structures. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: John Stultz <john.stu...@linaro.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: James Morris <jmor...@namei.org> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: Patrick McHardy <ka...@trash.net> --- include/linux/ip.h | 2 ++ include/linux/time64.h | 3 +++ kernel/time/time.c | 26 ++ 3 files changed, 31 insertions(+) diff --git a/include/linux/ip.h b/include/linux/ip.h index 492bc65..edf923e 100644 --- a/include/linux/ip.h +++ b/include/linux/ip.h @@ -34,4 +34,6 @@ static inline struct iphdr *ipip_hdr(const struct sk_buff *skb) { return (struct iphdr *)skb_transport_header(skb); } + +extern __be32 current_nw_timestamp(void); #endif /* _LINUX_IP_H */ diff --git a/include/linux/time64.h b/include/linux/time64.h index 367d5af..5b5db3b 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h @@ -35,6 +35,9 @@ struct itimerspec64 { #define NSEC_PER_SEC 10L #define FSEC_PER_SEC 1000LL +#define SECONDS_PER_DAY86400 +#define MSEC_PER_DAY (SECONDS_PER_DAY * MSEC_PER_SEC) + /* Located here for timespec[64]_valid_strict */ #define TIME64_MAX ((s64)~((u64)1 << 63)) #define KTIME_MAX ((s64)~((u64)1 << 63)) diff --git a/kernel/time/time.c b/kernel/time/time.c index 86751c6..6df15df 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -245,6 +245,32 @@ struct timespec current_fs_time(struct super_block *sb) EXPORT_SYMBOL(current_fs_time); /* + * current_nw_timestamp - Return network time + * + * Return milliseconds since midnight in network byte order. + */ +__be32 current_nw_timestamp(void) +{ + u64 now; + u32 secs; + u32 msecs; + struct timespec64 ts; + + ktime_get_ts64(); + + /* Get secs since midnight. */ + now = div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, ); + /* Convert to msecs. */ + msecs = secs * MSEC_PER_SEC; + /* Convert nsec to msec. */ + msecs += (u32)ts.tv_nsec/NSEC_PER_MSEC; + + /* Convert to network byte order. */ + return htons(msecs); +} +EXPORT_SYMBOL(current_nw_timestamp); + +/* * Convert jiffies to milliseconds and back. * * Avoid unnecessary multiplications/divisions in the -- 1.9.1
[PATCH 0/4] Convert network timestamps to be y2038 safe
Introduction: The series is aimed at transitioning network timestamps to being y2038 safe. All patches can be reviewed and merged independently, except for the [PATCH 2/4], which is dependent on the [PATCH 1/4]. Socket timestamps and ioctl calls will be handled separately. Thanks to Arnd Bergmann for discussing solution options with me. Solution: Data type struct timespec is not y2038 safe. Replace timespec with struct timespec64 which is y2038 safe. Deepa Dinamani (4): kernel: time: Add current_nw_timestamp() for network timestamps net: ipv4: Use y2038 safe functions and data structures net: ipv4: tcp_probe: Replace timespec with timespec64 net: sctp: Convert log timestamps to be y2038 safe include/linux/ip.h | 2 ++ include/linux/time64.h | 3 +++ kernel/time/time.c | 26 ++ net/ipv4/icmp.c| 5 + net/ipv4/ip_options.c | 13 + net/ipv4/tcp_probe.c | 8 net/sctp/probe.c | 10 +- 7 files changed, 46 insertions(+), 21 deletions(-) -- 1.9.1 Cc: Vlad Yasevich <vyasev...@gmail.com> Cc: Neil Horman <nhor...@tuxdriver.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: James Morris <jmor...@namei.org> Cc: Hideaki YOSHIFUJI <yoshf...@linux-ipv6.org> Cc: Patrick McHardy <ka...@trash.net> Cc: John Stultz <john.stu...@linaro.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: linux-s...@vger.kernel.org
Re: [PATCH 8/8] net: sunrpc: Replace CURRENT_TIME by current_fs_time()
On Mon, Feb 22, 2016 at 9:04 PM, Trond Myklebust <trond.mykleb...@primarydata.com> wrote: > On Mon, Feb 22, 2016 at 10:17 AM, Deepa Dinamani <deepa.ker...@gmail.com> > wrote: >> >> CURRENT_TIME macro is not appropriate for filesystems as it >> doesn't use the right granularity for filesystem timestamps. >> Use current_fs_time() instead. >> >> Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> >> Cc: "J. Bruce Fields" <bfie...@fieldses.org> >> Cc: Jeff Layton <jlay...@poochiereds.net> >> Cc: Trond Myklebust <trond.mykleb...@primarydata.com> >> Cc: Anna Schumaker <anna.schuma...@netapp.com> >> Cc: "David S. Miller" <da...@davemloft.net> >> Cc: linux-...@vger.kernel.org >> Cc: netdev@vger.kernel.org >> --- >> net/sunrpc/rpc_pipe.c | 4 +++- >> 1 file changed, 3 insertions(+), 1 deletion(-) >> >> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c >> index 31789ef..bab3187 100644 >> --- a/net/sunrpc/rpc_pipe.c >> +++ b/net/sunrpc/rpc_pipe.c >> @@ -477,7 +477,9 @@ rpc_get_inode(struct super_block *sb, umode_t mode) >> return NULL; >> inode->i_ino = get_next_ino(); >> inode->i_mode = mode; >> - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; >> + inode->i_atime = current_fs_time(sb); >> + inode->i_mtime = inode->i_atime; >> + inode->i_ctime = inode->i_atime; >> switch (mode & S_IFMT) { >> case S_IFDIR: >> inode->i_fop = _dir_operations; > > Why would we care? This is a pseudo-fs. There is no expectation w.r.t. > timestamp accuracy or resolution. CURRENT_TIME is not y2038 safe. We are switching all vfs timestamps to use 64 bit time. And, deleting all references to CURRENT_TIME. So CURRENT_TIME users will be replaced by either ktime_get_* apis or current_fs_time_* apis. There is going to be another series (based on https://lkml.org/lkml/2016/2/12/76) which switches vfs time to 64 bit. This means [a,c,m] times in struct inode, struct attr and struct kstat will be changed to use timespec64. Even though this is a psuedo-fs, we choose to use filesystem apis rather than ktime_get_* apis as current_fs_time_* apis will switch time data types together with vfs. -Deepa
[PATCH 8/8] net: sunrpc: Replace CURRENT_TIME by current_fs_time()
CURRENT_TIME macro is not appropriate for filesystems as it doesn't use the right granularity for filesystem timestamps. Use current_fs_time() instead. Signed-off-by: Deepa Dinamani <deepa.ker...@gmail.com> Cc: "J. Bruce Fields" <bfie...@fieldses.org> Cc: Jeff Layton <jlay...@poochiereds.net> Cc: Trond Myklebust <trond.mykleb...@primarydata.com> Cc: Anna Schumaker <anna.schuma...@netapp.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: linux-...@vger.kernel.org Cc: netdev@vger.kernel.org --- net/sunrpc/rpc_pipe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 31789ef..bab3187 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -477,7 +477,9 @@ rpc_get_inode(struct super_block *sb, umode_t mode) return NULL; inode->i_ino = get_next_ino(); inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_atime = current_fs_time(sb); + inode->i_mtime = inode->i_atime; + inode->i_ctime = inode->i_atime; switch (mode & S_IFMT) { case S_IFDIR: inode->i_fop = _dir_operations; -- 1.9.1