From: John Stultz <john.stultz@linaro.org>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: John Stultz <john.stultz@linaro.org>,
John Whitmore <arigead@gmail.com>,
Alessandro Zummo <a.zummo@towertech.it>,
Alexander Holler <holler@ahsoftware.de>
Subject: [PATCH 1/2][RFC] time: Introduce do_first_settimeofday()
Date: Fri, 27 Jun 2014 10:27:10 -0700 [thread overview]
Message-ID: <1403890031-26419-2-git-send-email-john.stultz@linaro.org> (raw)
In-Reply-To: <1403890031-26419-1-git-send-email-john.stultz@linaro.org>
There's some cases in the kernel, particuarly with RTC drivers,
where we want to set the time, but only if no one else has
already set it.
This is useful for systems where the RTC driver is a module, and
is loaded late in initialization. However, we want to be sure we
don't override the time that may have been set by userspace.
Cc: John Whitmore <arigead@gmail.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexander Holler <holler@ahsoftware.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
include/linux/time.h | 2 ++
kernel/time/timekeeping.c | 54 ++++++++++++++++++++++++++++++++++++++---------
2 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/include/linux/time.h b/include/linux/time.h
index d5d229b..7379291 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -157,6 +157,8 @@ extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday(const struct timespec *tv);
extern int do_sys_settimeofday(const struct timespec *tv,
const struct timezone *tz);
+extern int do_first_settimeofday(const struct timespec *ts);
+
#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
struct itimerval;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 32d8d6a..45c2642 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -487,6 +487,25 @@ void do_gettimeofday(struct timeval *tv)
}
EXPORT_SYMBOL(do_gettimeofday);
+
+static void __do_settimeofday(struct timekeeper *tk, const struct timespec *tv)
+{
+ struct timespec ts_delta, xt;
+
+ timekeeping_forward_now(tk);
+
+ xt = tk_xtime(tk);
+ ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
+ ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
+
+ tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, ts_delta));
+
+ tk_set_xtime(tk, tv);
+
+ timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
+}
+
+
/**
* do_settimeofday - Sets the time of day
* @tv: pointer to the timespec variable containing the new time
@@ -496,7 +515,6 @@ EXPORT_SYMBOL(do_gettimeofday);
int do_settimeofday(const struct timespec *tv)
{
struct timekeeper *tk = &timekeeper;
- struct timespec ts_delta, xt;
unsigned long flags;
if (!timespec_valid_strict(tv))
@@ -505,27 +523,43 @@ int do_settimeofday(const struct timespec *tv)
raw_spin_lock_irqsave(&timekeeper_lock, flags);
write_seqcount_begin(&timekeeper_seq);
- timekeeping_forward_now(tk);
+ __do_settimeofday(tk, tv);
- xt = tk_xtime(tk);
- ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
- ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
+ write_seqcount_end(&timekeeper_seq);
+ raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
- tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, ts_delta));
+ /* signal hrtimers about time change */
+ clock_was_set();
- tk_set_xtime(tk, tv);
+ return 0;
+}
+EXPORT_SYMBOL(do_settimeofday);
- timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
+int do_first_settimeofday(const struct timespec *tv)
+{
+ struct timekeeper *tk = &timekeeper;
+ unsigned long flags;
+ int ret = 0;
+
+ if (!timespec_valid_strict(tv))
+ return -EINVAL;
+
+ raw_spin_lock_irqsave(&timekeeper_lock, flags);
+ write_seqcount_begin(&timekeeper_seq);
+
+ if (!tk->wall_to_monotonic.tv_sec && !tk->wall_to_monotonic.tv_nsec)
+ __do_settimeofday(tk, tv);
+ else
+ ret = -EACCES;
write_seqcount_end(&timekeeper_seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
/* signal hrtimers about time change */
clock_was_set();
- return 0;
+ return ret;
}
-EXPORT_SYMBOL(do_settimeofday);
/**
* timekeeping_inject_offset - Adds or subtracts from the current time.
--
1.9.1
next prev parent reply other threads:[~2014-06-27 17:27 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-27 17:27 [PATCH 0/2][RFC] Try to handle hctosys w/ rtc modules John Stultz
2014-06-27 17:27 ` John Stultz [this message]
2014-06-27 17:27 ` [PATCH 2/2][RFC] rtc: Rework hctosys so that it is called on RTC registration John Stultz
2014-06-28 7:18 ` [PATCH 0/2][RFC] Try to handle hctosys w/ rtc modules Alexander Holler
2014-06-28 7:32 ` Alexander Holler
2014-06-28 18:54 ` Marc Dietrich
2014-06-28 20:50 ` Alexander Holler
2014-06-30 19:37 ` Alessandro Zummo
2014-07-01 18:42 ` Alexander Holler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1403890031-26419-2-git-send-email-john.stultz@linaro.org \
--to=john.stultz@linaro.org \
--cc=a.zummo@towertech.it \
--cc=arigead@gmail.com \
--cc=holler@ahsoftware.de \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome